mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Added consumption and heartbound enchantments
This commit is contained in:
parent
0ec8529d39
commit
82bdce6c51
21 changed files with 428 additions and 13 deletions
|
@ -34,6 +34,7 @@ import com.minelittlepony.unicopia.server.world.NocturnalSleepManager;
|
||||||
import com.minelittlepony.unicopia.server.world.UGameRules;
|
import com.minelittlepony.unicopia.server.world.UGameRules;
|
||||||
import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
||||||
import com.minelittlepony.unicopia.server.world.ZapAppleStageStore;
|
import com.minelittlepony.unicopia.server.world.ZapAppleStageStore;
|
||||||
|
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
|
||||||
|
|
||||||
public class Unicopia implements ModInitializer {
|
public class Unicopia implements ModInitializer {
|
||||||
public static final String DEFAULT_NAMESPACE = "unicopia";
|
public static final String DEFAULT_NAMESPACE = "unicopia";
|
||||||
|
@ -62,6 +63,7 @@ public class Unicopia implements ModInitializer {
|
||||||
UCriteria.bootstrap();
|
UCriteria.bootstrap();
|
||||||
UEntities.bootstrap();
|
UEntities.bootstrap();
|
||||||
Commands.bootstrap();
|
Commands.bootstrap();
|
||||||
|
TrinketsDelegate.getInstance().bootstrap();
|
||||||
|
|
||||||
ServerTickEvents.END_WORLD_TICK.register(w -> {
|
ServerTickEvents.END_WORLD_TICK.register(w -> {
|
||||||
((BlockDestructionManager.Source)w).getDestructionManager().tick();
|
((BlockDestructionManager.Source)w).getDestructionManager().tick();
|
||||||
|
|
|
@ -13,7 +13,7 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
import net.minecraft.advancement.criterion.AbstractCriterion;
|
import net.minecraft.advancement.criterion.AbstractCriterion;
|
||||||
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
|
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer;
|
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer;
|
||||||
import net.minecraft.predicate.entity.AdvancementEntityPredicateSerializer;
|
import net.minecraft.predicate.entity.AdvancementEntityPredicateSerializer;
|
||||||
import net.minecraft.predicate.entity.EntityPredicate.Extended;
|
import net.minecraft.predicate.entity.EntityPredicate.Extended;
|
||||||
|
@ -53,7 +53,7 @@ public class CustomEventCriterion extends AbstractCriterion<CustomEventCriterion
|
||||||
public CustomEventCriterion.Trigger createTrigger(String name) {
|
public CustomEventCriterion.Trigger createTrigger(String name) {
|
||||||
return player -> {
|
return player -> {
|
||||||
if (player instanceof ServerPlayerEntity p) {
|
if (player instanceof ServerPlayerEntity p) {
|
||||||
int counter = Pony.of(player).getAdvancementProgress().compute(name, (key, i) -> i == null ? 1 : i + 1);
|
int counter = Pony.of(p).getAdvancementProgress().compute(name, (key, i) -> i == null ? 1 : i + 1);
|
||||||
|
|
||||||
trigger(p, c -> c.test(name, counter, p));
|
trigger(p, c -> c.test(name, counter, p));
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public class CustomEventCriterion extends AbstractCriterion<CustomEventCriterion
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Trigger {
|
public interface Trigger {
|
||||||
void trigger(@Nullable PlayerEntity player);
|
void trigger(@Nullable Entity player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Conditions extends AbstractCriterionConditions {
|
public static class Conditions extends AbstractCriterionConditions {
|
||||||
|
|
|
@ -19,6 +19,8 @@ public interface UCriteria {
|
||||||
CustomEventCriterion.Trigger RECEIVE_OATS = CUSTOM_EVENT.createTrigger("receive_oats");
|
CustomEventCriterion.Trigger RECEIVE_OATS = CUSTOM_EVENT.createTrigger("receive_oats");
|
||||||
CustomEventCriterion.Trigger BREAK_WINDOW = CUSTOM_EVENT.createTrigger("break_window");
|
CustomEventCriterion.Trigger BREAK_WINDOW = CUSTOM_EVENT.createTrigger("break_window");
|
||||||
CustomEventCriterion.Trigger KILL_PHANTOM_WHILE_FLYING = CUSTOM_EVENT.createTrigger("kill_phantom_while_flying");
|
CustomEventCriterion.Trigger KILL_PHANTOM_WHILE_FLYING = CUSTOM_EVENT.createTrigger("kill_phantom_while_flying");
|
||||||
|
CustomEventCriterion.Trigger USE_CONSUMPTION = CUSTOM_EVENT.createTrigger("use_consumption");
|
||||||
|
CustomEventCriterion.Trigger USE_SOULMATE = CUSTOM_EVENT.createTrigger("use_soulmate");
|
||||||
|
|
||||||
static void bootstrap() { }
|
static void bootstrap() { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect;
|
||||||
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
||||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||||
import com.minelittlepony.unicopia.item.UItems;
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.util.*;
|
import com.minelittlepony.unicopia.util.*;
|
||||||
import com.minelittlepony.unicopia.network.*;
|
import com.minelittlepony.unicopia.network.*;
|
||||||
import com.minelittlepony.unicopia.network.datasync.EffectSync.UpdateCallback;
|
import com.minelittlepony.unicopia.network.datasync.EffectSync.UpdateCallback;
|
||||||
|
@ -32,6 +33,7 @@ import com.minelittlepony.common.util.animation.Interpolator;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.entity.*;
|
import net.minecraft.entity.*;
|
||||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
|
@ -42,6 +44,7 @@ import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
import net.minecraft.entity.mob.HostileEntity;
|
import net.minecraft.entity.mob.HostileEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
@ -52,6 +55,7 @@ import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
import net.minecraft.world.GameMode;
|
import net.minecraft.world.GameMode;
|
||||||
|
import net.minecraft.world.GameRules;
|
||||||
|
|
||||||
public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, UpdateCallback {
|
public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, UpdateCallback {
|
||||||
private static final TrackedData<String> RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.STRING);
|
private static final TrackedData<String> RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.STRING);
|
||||||
|
@ -697,6 +701,17 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
} else {
|
} else {
|
||||||
oldPlayer.getSpellSlot().stream(true).filter(SpellPredicate.IS_PLACED).forEach(getSpellSlot()::put);
|
oldPlayer.getSpellSlot().stream(true).filter(SpellPredicate.IS_PLACED).forEach(getSpellSlot()::put);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// putting it here instead of adding another injection point into ServerPlayerEntity.copyFrom()
|
||||||
|
if (!asWorld().getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) {
|
||||||
|
PlayerInventory inventory = oldPlayer.asEntity().getInventory();
|
||||||
|
for (int i = 0; i < inventory.size(); i++) {
|
||||||
|
ItemStack stack = inventory.getStack(i);
|
||||||
|
if (EnchantmentHelper.getLevel(UEnchantments.HEART_BOUND, stack) > 0) {
|
||||||
|
asEntity().getInventory().setStack(i, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldPlayer.getSpellSlot().put(null);
|
oldPlayer.getSpellSlot().put(null);
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import java.util.function.DoubleSupplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||||
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.enchantment.EnchantmentTarget;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.ExperienceOrbEntity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
import net.minecraft.sound.SoundEvents;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class ConsumptionEnchantment extends SimpleEnchantment {
|
||||||
|
protected ConsumptionEnchantment() {
|
||||||
|
super(Rarity.VERY_RARE, EnchantmentTarget.DIGGER, false, 1, UEnchantmentValidSlots.HANDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean applyConsumption(World w, BlockState state, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack tool) {
|
||||||
|
|
||||||
|
if (!(w instanceof ServerWorld world)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tool.isEmpty() && entity instanceof LivingEntity l) {
|
||||||
|
tool = l.getMainHandStack();
|
||||||
|
}
|
||||||
|
if (EnchantmentHelper.getLevel(UEnchantments.CONSUMPTION, tool) <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoubleSupplier vecComponentFactory = () -> world.random.nextTriangular(0, 0.3);
|
||||||
|
|
||||||
|
Block.getDroppedStacks(state, world, pos, blockEntity, entity, tool).forEach(s -> {
|
||||||
|
world.playSound(null, pos, SoundEvents.ENTITY_PLAYER_BURP, SoundCategory.BLOCKS, 0.05F, (float)world.random.nextTriangular(0.6F, 0.2F));
|
||||||
|
ExperienceOrbEntity.spawn(world, Vec3d.ofCenter(pos).add(VecHelper.supply(vecComponentFactory)), s.getCount());
|
||||||
|
UCriteria.USE_CONSUMPTION.trigger(entity);
|
||||||
|
});
|
||||||
|
state.onStacksDropped(world, pos, tool, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.effect.StatusEffect;
|
||||||
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.random.Random;
|
||||||
|
|
||||||
|
public interface EnchantmentUtil {
|
||||||
|
|
||||||
|
static boolean consumeEnchantment(Enchantment enchantment, int levels, ItemStack stack) {
|
||||||
|
return consumeEnchantment(enchantment, levels, stack, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean consumeEnchantment(Enchantment enchantment, int levels, ItemStack stack, @Nullable Random random, int chance) {
|
||||||
|
Map<Enchantment, Integer> enchantments = EnchantmentHelper.get(stack);
|
||||||
|
int level = enchantments.getOrDefault(enchantment, 0);
|
||||||
|
if (level <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (random == null || chance <= 1 || random.nextInt(chance) == 0) {
|
||||||
|
level = Math.max(0, level - levels);
|
||||||
|
if (level == 0) {
|
||||||
|
enchantments.remove(enchantment);
|
||||||
|
} else {
|
||||||
|
enchantments.put(enchantment, level - 1);
|
||||||
|
}
|
||||||
|
EnchantmentHelper.set(enchantments, stack);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getLuck(int baseline, LivingEntity entity) {
|
||||||
|
boolean naturallyLucky = Living.getOrEmpty(entity).filter(c -> c.getSpecies().canUseEarth()).isPresent();
|
||||||
|
if (naturallyLucky) {
|
||||||
|
baseline += 15;
|
||||||
|
}
|
||||||
|
float luckAmplifier = getEffectAmplifier(entity, StatusEffects.LUCK) * (naturallyLucky ? 2 : 1);
|
||||||
|
float dolphinsGraceAmplifier = getEffectAmplifier(entity, StatusEffects.DOLPHINS_GRACE) * 0.5F;
|
||||||
|
float unluckAmplifier = getEffectAmplifier(entity, StatusEffects.UNLUCK) * (naturallyLucky ? 0.5F : 1);
|
||||||
|
float badOmenAmplifier = getEffectAmplifier(entity, StatusEffects.BAD_OMEN) * (naturallyLucky ? 1 : 2);
|
||||||
|
return (int)MathHelper.clamp(baseline + luckAmplifier + dolphinsGraceAmplifier - unluckAmplifier - badOmenAmplifier, -10, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getEffectAmplifier(LivingEntity entity, StatusEffect effect) {
|
||||||
|
if (!entity.hasStatusEffect(effect)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return entity.getStatusEffect(effect).getAmplifier();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,6 @@ import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.util.Resources;
|
import com.minelittlepony.unicopia.util.Resources;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
|
||||||
import net.minecraft.resource.ResourceManager;
|
import net.minecraft.resource.ResourceManager;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvent;
|
import net.minecraft.sound.SoundEvent;
|
||||||
|
@ -31,7 +30,7 @@ public class PoisonedJokeEnchantment extends SimpleEnchantment implements Identi
|
||||||
private List<SoundEvent> sounds = new ArrayList<>();
|
private List<SoundEvent> sounds = new ArrayList<>();
|
||||||
|
|
||||||
protected PoisonedJokeEnchantment() {
|
protected PoisonedJokeEnchantment() {
|
||||||
super(Rarity.VERY_RARE, true, 1, EquipmentSlot.values());
|
super(Rarity.VERY_RARE, true, 1, UEnchantmentValidSlots.ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,12 +4,10 @@ import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
|
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
|
||||||
|
|
||||||
public class StressfulEnchantment extends SimpleEnchantment {
|
public class StressfulEnchantment extends SimpleEnchantment {
|
||||||
|
|
||||||
protected StressfulEnchantment() {
|
protected StressfulEnchantment() {
|
||||||
super(Rarity.RARE, true, 3, EquipmentSlot.values());
|
super(Rarity.RARE, true, 3, UEnchantmentValidSlots.ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
|
||||||
|
public interface UEnchantmentValidSlots {
|
||||||
|
EquipmentSlot[] ANY = EquipmentSlot.values();
|
||||||
|
EquipmentSlot[] ARMOR = { EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET };
|
||||||
|
EquipmentSlot[] HANDS = { EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND };
|
||||||
|
}
|
|
@ -29,12 +29,12 @@ public interface UEnchantments {
|
||||||
/**
|
/**
|
||||||
* Protects against wall collisions and earth pony attacks!
|
* Protects against wall collisions and earth pony attacks!
|
||||||
*/
|
*/
|
||||||
Enchantment PADDED = register("padded", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR, false, 3, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET));
|
Enchantment PADDED = register("padded", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR, false, 3, UEnchantmentValidSlots.ARMOR));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Heavy players move more slowly but are less likely to be flung around wildly.
|
* Heavy players move more slowly but are less likely to be flung around wildly.
|
||||||
*/
|
*/
|
||||||
Enchantment HEAVY = register("heavy", new AttributedEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR, false, 4, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET))
|
Enchantment HEAVY = register("heavy", new AttributedEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR, false, 4, UEnchantmentValidSlots.ARMOR))
|
||||||
.addModifier(EntityAttributes.GENERIC_MOVEMENT_SPEED, (user, level) -> {
|
.addModifier(EntityAttributes.GENERIC_MOVEMENT_SPEED, (user, level) -> {
|
||||||
return new EntityAttributeModifier(UUID.fromString("a3d5a94f-4c40-48f6-a343-558502a13e10"), "Heavyness", (1 - level/(float)10) - 1, Operation.MULTIPLY_TOTAL);
|
return new EntityAttributeModifier(UUID.fromString("a3d5a94f-4c40-48f6-a343-558502a13e10"), "Heavyness", (1 - level/(float)10) - 1, Operation.MULTIPLY_TOTAL);
|
||||||
});
|
});
|
||||||
|
@ -76,7 +76,18 @@ public interface UEnchantments {
|
||||||
/**
|
/**
|
||||||
* This item just wants to be held.
|
* This item just wants to be held.
|
||||||
*/
|
*/
|
||||||
Enchantment CLINGY = register("clingy", new SimpleEnchantment(Rarity.VERY_RARE, true, 6, EquipmentSlot.values()));
|
Enchantment CLINGY = register("clingy", new SimpleEnchantment(Rarity.VERY_RARE, true, 6, UEnchantmentValidSlots.ANY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Items with loyalty are kept after death.
|
||||||
|
* Only works if they don't also have curse of binding.
|
||||||
|
*/
|
||||||
|
Enchantment HEART_BOUND = register("heart_bound", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.VANISHABLE, false, 5, UEnchantmentValidSlots.ANY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes drops whilst mining and produces experience instead
|
||||||
|
*/
|
||||||
|
Enchantment CONSUMPTION = register("consumption", new ConsumptionEnchantment());
|
||||||
|
|
||||||
static void bootstrap() { }
|
static void bootstrap() { }
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,12 @@ import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
|
|
||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
public class WantItNeedItEnchantment extends SimpleEnchantment {
|
public class WantItNeedItEnchantment extends SimpleEnchantment {
|
||||||
|
|
||||||
protected WantItNeedItEnchantment() {
|
protected WantItNeedItEnchantment() {
|
||||||
super(Rarity.VERY_RARE, true, 1, EquipmentSlot.values());
|
super(Rarity.VERY_RARE, true, 1, UEnchantmentValidSlots.ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.minelittlepony.unicopia.mixin;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.ConsumptionEnchantment;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
@Mixin(Block.class)
|
||||||
|
abstract class MixinBlock {
|
||||||
|
@Inject(
|
||||||
|
method = "dropStacks(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/entity/BlockEntity;Lnet/minecraft/entity/Entity;Lnet/minecraft/item/ItemStack;)V",
|
||||||
|
at = @At("HEAD"),
|
||||||
|
cancellable = true
|
||||||
|
)
|
||||||
|
private static void dropStacks(BlockState state, World world, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack stack, CallbackInfo info) {
|
||||||
|
if (ConsumptionEnchantment.applyConsumption(world, state, pos, blockEntity, entity, stack)) {
|
||||||
|
info.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.minelittlepony.unicopia.mixin;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.enchantment.Enchantments;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.inventory.Inventory;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.Nameable;
|
||||||
|
import net.minecraft.util.collection.DefaultedList;
|
||||||
|
|
||||||
|
@Mixin(PlayerInventory.class)
|
||||||
|
abstract class MixinPlayerInventory implements Inventory, Nameable {
|
||||||
|
@Shadow
|
||||||
|
public @Final PlayerEntity player;
|
||||||
|
@Shadow
|
||||||
|
private @Final List<DefaultedList<ItemStack>> combinedInventory;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private List<DefaultedList<ItemStack>> storedCombinedInventory;
|
||||||
|
|
||||||
|
@Inject(method = "dropAll()V", at = @At("HEAD"))
|
||||||
|
public void beforeDropAll(CallbackInfo info) {
|
||||||
|
storedCombinedInventory = combinedInventory.stream().map(l -> DefaultedList.ofSize(l.size(), ItemStack.EMPTY)).toList();
|
||||||
|
for (int group = 0; group < combinedInventory.size(); group++) {
|
||||||
|
var original = combinedInventory.get(group);
|
||||||
|
for (int i = 0; i < original.size(); i++) {
|
||||||
|
ItemStack stack = original.get(i);
|
||||||
|
if (EnchantmentHelper.getLevel(Enchantments.BINDING_CURSE, stack) == 0
|
||||||
|
&& EnchantmentUtil.consumeEnchantment(UEnchantments.HEART_BOUND, 1, stack, player.world.random, EnchantmentUtil.getLuck(3, player))) {
|
||||||
|
original.set(i, ItemStack.EMPTY);
|
||||||
|
UCriteria.USE_CONSUMPTION.trigger(player);
|
||||||
|
storedCombinedInventory.get(group).set(i, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "dropAll()V", at = @At("TAIL"))
|
||||||
|
public void afterDropAll(CallbackInfo info) {
|
||||||
|
if (storedCombinedInventory != null) {
|
||||||
|
for (int group = 0; group < combinedInventory.size(); group++) {
|
||||||
|
var original = combinedInventory.get(group);
|
||||||
|
for (int i = 0; i < original.size(); i++) {
|
||||||
|
ItemStack stored = storedCombinedInventory.get(group).get(i);
|
||||||
|
if (!stored.isEmpty()) {
|
||||||
|
original.set(i, stored);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,10 @@ public interface TrinketsDelegate {
|
||||||
return FabricLoader.getInstance().isModLoaded("trinkets");
|
return FabricLoader.getInstance().isModLoaded("trinkets");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void bootstrap() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
default boolean equipStack(LivingEntity entity, Identifier slot, ItemStack stack) {
|
default boolean equipStack(LivingEntity entity, Identifier slot, ItemStack stack) {
|
||||||
EquipmentSlot eq = MobEntity.getPreferredEquipmentSlot(stack);
|
EquipmentSlot eq = MobEntity.getPreferredEquipmentSlot(stack);
|
||||||
if (!entity.getEquippedStack(eq).isEmpty()) {
|
if (!entity.getEquippedStack(eq).isEmpty()) {
|
||||||
|
|
|
@ -4,10 +4,14 @@ import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.util.InventoryUtil;
|
import com.minelittlepony.unicopia.util.InventoryUtil;
|
||||||
|
|
||||||
import dev.emi.trinkets.TrinketSlot;
|
import dev.emi.trinkets.TrinketSlot;
|
||||||
import dev.emi.trinkets.api.*;
|
import dev.emi.trinkets.api.*;
|
||||||
|
import dev.emi.trinkets.api.TrinketEnums.DropRule;
|
||||||
|
import dev.emi.trinkets.api.event.TrinketDropCallback;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
@ -21,6 +25,16 @@ public class TrinketsDelegateImpl implements TrinketsDelegate {
|
||||||
public static final TrinketsDelegateImpl INSTANCE = new TrinketsDelegateImpl();
|
public static final TrinketsDelegateImpl INSTANCE = new TrinketsDelegateImpl();
|
||||||
// who tf designed this api?
|
// who tf designed this api?
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bootstrap() {
|
||||||
|
TrinketDropCallback.EVENT.register((rule, stack, ref, entity) -> {
|
||||||
|
if (EnchantmentHelper.getLevel(UEnchantments.HEART_BOUND, stack) > 0) {
|
||||||
|
return DropRule.KEEP;
|
||||||
|
}
|
||||||
|
return rule;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equipStack(LivingEntity entity, Identifier slot, ItemStack stack) {
|
public boolean equipStack(LivingEntity entity, Identifier slot, ItemStack stack) {
|
||||||
return getInventory(entity, slot).map(inventory -> {
|
return getInventory(entity, slot).map(inventory -> {
|
||||||
|
|
|
@ -426,6 +426,8 @@
|
||||||
"enchantment.unicopia.want_it_need_it": "Want It Need It",
|
"enchantment.unicopia.want_it_need_it": "Want It Need It",
|
||||||
"enchantment.unicopia.poisoned_joke": "Poisoned Joke",
|
"enchantment.unicopia.poisoned_joke": "Poisoned Joke",
|
||||||
"enchantment.unicopia.stressed": "Stressed",
|
"enchantment.unicopia.stressed": "Stressed",
|
||||||
|
"enchantment.unicopia.heart_bound": "Heart Bound",
|
||||||
|
"enchantment.unicopia.consumption": "Consumption",
|
||||||
|
|
||||||
"commands.race.success.self": "Set own race to %1$s",
|
"commands.race.success.self": "Set own race to %1$s",
|
||||||
"commands.race.success": "%1$s changed race to %2$s",
|
"commands.race.success": "%1$s changed race to %2$s",
|
||||||
|
@ -617,6 +619,14 @@
|
||||||
"advancements.unicopia.eat_pinecone.description": "Eat a pinecone",
|
"advancements.unicopia.eat_pinecone.description": "Eat a pinecone",
|
||||||
"advancements.unicopia.imported_oats.title": "As Delicious As They Are Expensive",
|
"advancements.unicopia.imported_oats.title": "As Delicious As They Are Expensive",
|
||||||
"advancements.unicopia.imported_oats.description": "Send of receive fancy imported oats",
|
"advancements.unicopia.imported_oats.description": "Send of receive fancy imported oats",
|
||||||
|
"advancements.unicopia.experimental.title": "You Can't Take It With You",
|
||||||
|
"advancements.unicopia.experimental.description": "Enchant a tool with Consumption",
|
||||||
|
"advancements.unicopia.xp_mine.title": "XP Miner",
|
||||||
|
"advancements.unicopia.xp_mine.description": "Use consumption to dig up some experience",
|
||||||
|
"advancements.unicopia.hearts_stronger_than_horses.title": "You Can Keep it With You",
|
||||||
|
"advancements.unicopia.hearts_stronger_than_horses.description": "Enchant a tool with Heart Bound",
|
||||||
|
"advancements.unicopia.soulmate.title": "Hearts Stronger Than Horses",
|
||||||
|
"advancements.unicopia.soulmate.description": "Die whilst holding a heart-bound item",
|
||||||
|
|
||||||
"advancements.unicopia.burn_juice.title": "That doesn't seem right",
|
"advancements.unicopia.burn_juice.title": "That doesn't seem right",
|
||||||
"advancements.unicopia.burn_juice.description": "Burn the juice",
|
"advancements.unicopia.burn_juice.description": "Burn the juice",
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:story/enchant_item",
|
||||||
|
"display": {
|
||||||
|
"icon": {
|
||||||
|
"item": "minecraft:netherite_pickaxe"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"translate": "advancements.unicopia.experimental.title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"translate": "advancements.unicopia.experimental.description"
|
||||||
|
},
|
||||||
|
"frame": "task",
|
||||||
|
"show_toast": true,
|
||||||
|
"announce_to_chat": true,
|
||||||
|
"hidden": false
|
||||||
|
},
|
||||||
|
"rewards": {
|
||||||
|
"experience": 120
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"enchant_with_consumption": {
|
||||||
|
"trigger": "minecraft:enchanted_item",
|
||||||
|
"conditions": {
|
||||||
|
"item": {
|
||||||
|
"enchantments": [
|
||||||
|
{ "enchantment": "unicopia:consumption" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[ "enchant_with_consumption" ]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"parent": "minecraft:story/enchant_item",
|
||||||
|
"display": {
|
||||||
|
"icon": {
|
||||||
|
"item": "minecraft:golden_pickaxe"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"translate": "advancements.unicopia.hearts_stronger_than_horses.title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"translate": "advancements.unicopia.hearts_stronger_than_horses.description"
|
||||||
|
},
|
||||||
|
"frame": "task",
|
||||||
|
"show_toast": true,
|
||||||
|
"announce_to_chat": true,
|
||||||
|
"hidden": false
|
||||||
|
},
|
||||||
|
"rewards": {
|
||||||
|
"experience": 120
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"enchant_with_heart_bound": {
|
||||||
|
"trigger": "minecraft:enchanted_item",
|
||||||
|
"conditions": {
|
||||||
|
"item": {
|
||||||
|
"enchantments": [
|
||||||
|
{ "enchantment": "unicopia:heart_bound" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[ "enchant_with_heart_bound" ]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"parent": "unicopia:unicopia/enchanting/hearts_stronger_than_horses",
|
||||||
|
"display": {
|
||||||
|
"icon": {
|
||||||
|
"item": "minecraft:golden_apple"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"translate": "advancements.unicopia.soulmate.title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"translate": "advancements.unicopia.soulmate.description"
|
||||||
|
},
|
||||||
|
"frame": "task",
|
||||||
|
"show_toast": true,
|
||||||
|
"announce_to_chat": true,
|
||||||
|
"hidden": true
|
||||||
|
},
|
||||||
|
"rewards": {
|
||||||
|
"experience": 1200
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"use_soulmate": {
|
||||||
|
"trigger": "unicopia:custom",
|
||||||
|
"conditions": {
|
||||||
|
"event": "use_soulmate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[ "use_soulmate" ]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"parent": "unicopia:unicopia/enchanting/experimental",
|
||||||
|
"display": {
|
||||||
|
"icon": {
|
||||||
|
"item": "minecraft:netherite_pickaxe"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"translate": "advancements.unicopia.xp_mine.title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"translate": "advancements.unicopia.xp_mine.description"
|
||||||
|
},
|
||||||
|
"frame": "task",
|
||||||
|
"show_toast": true,
|
||||||
|
"announce_to_chat": true,
|
||||||
|
"hidden": true
|
||||||
|
},
|
||||||
|
"rewards": {
|
||||||
|
"experience": 1200
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"mine_xp": {
|
||||||
|
"trigger": "unicopia:custom",
|
||||||
|
"conditions": {
|
||||||
|
"event": "use_consumption"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": [
|
||||||
|
[ "mine_xp" ]
|
||||||
|
]
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"MixinAbstractDecorationEntity",
|
"MixinAbstractDecorationEntity",
|
||||||
"MixinBlazeEntity",
|
"MixinBlazeEntity",
|
||||||
|
"MixinBlock",
|
||||||
"MixinBlockEntity",
|
"MixinBlockEntity",
|
||||||
"MixinBlockItem",
|
"MixinBlockItem",
|
||||||
"MixinBoatEntity",
|
"MixinBoatEntity",
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
"MixinMobEntity",
|
"MixinMobEntity",
|
||||||
"MixinPersistentProjectileEntity",
|
"MixinPersistentProjectileEntity",
|
||||||
"MixinPlayerEntity",
|
"MixinPlayerEntity",
|
||||||
|
"MixinPlayerInventory",
|
||||||
"MixinPowderSnowBlock",
|
"MixinPowderSnowBlock",
|
||||||
"MixinProjectileEntity",
|
"MixinProjectileEntity",
|
||||||
"MixinServerPlayerEntity",
|
"MixinServerPlayerEntity",
|
||||||
|
|
Loading…
Reference in a new issue