diff --git a/src/main/java/com/minelittlepony/unicopia/EquinePredicates.java b/src/main/java/com/minelittlepony/unicopia/EquinePredicates.java index 2e67d2c2..7b5da659 100644 --- a/src/main/java/com/minelittlepony/unicopia/EquinePredicates.java +++ b/src/main/java/com/minelittlepony/unicopia/EquinePredicates.java @@ -6,8 +6,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.Equine; import com.minelittlepony.unicopia.entity.MagicImmune; -import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment; - +import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import net.minecraft.entity.*; import net.minecraft.entity.decoration.AbstractDecorationEntity; import net.minecraft.entity.player.PlayerEntity; @@ -44,7 +43,7 @@ public interface EquinePredicates { Predicate EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate(); Predicate VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE); - Predicate LIVING_HAS_WANT_IT_NEED_IT = e -> WantItNeedItEnchantment.getLevel(e) > 0; + Predicate LIVING_HAS_WANT_IT_NEED_IT = e -> EnchantmentUtil.getWantItNeedItLevel(e) > 0; Predicate VALID_FOR_DISGUISE = EntityPredicates.EXCEPT_SPECTATOR.and(e -> !(e instanceof LightningEntity || e instanceof AbstractDecorationEntity)); static Predicate ofRace(Race race) { diff --git a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java index 6b77ce80..9595321f 100644 --- a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java @@ -29,6 +29,7 @@ public class InteractionManager { public static final int SOUND_MAGIC_BEAM = 5; public static final int SOUND_HEART_BEAT = 6; public static final int SOUND_KIRIN_RAGE = 7; + public static final int SOUND_GEM_FINDING_MAGIC_HUM = 8; public static final int SCREEN_DISPELL_ABILITY = 0; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java index ffd65298..ef1933d1 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java @@ -65,6 +65,7 @@ public enum Trait implements CommandArgumentEnum { private static final Trait[] VALUES = values(); private static final Map IDS = Arrays.stream(values()).collect(Collectors.toMap(Trait::getId, Function.identity())); + @SuppressWarnings("deprecation") private static final EnumCodec NAME_CODEC = StringIdentifiable.createCodec(Trait::values, n -> n.toLowerCase(Locale.ROOT)); public static final Codec CODEC = Identifier.CODEC.xmap(id -> IDS.get(id), Trait::getId); public static final Codec> SET_CODEC = CODEC.listOf().xmap( diff --git a/src/main/java/com/minelittlepony/unicopia/block/HiveBlock.java b/src/main/java/com/minelittlepony/unicopia/block/HiveBlock.java index f55717c9..ce8b6db0 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/HiveBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/HiveBlock.java @@ -101,7 +101,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider { } @Override - public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { + protected BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { if (state.get(CONSUMING)) { return state; } @@ -116,7 +116,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider { } @Override - public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { + protected void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { if (state.get(CONSUMING) || !state.get(AWAKE)) { return; } @@ -142,7 +142,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider { } @Override - public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { if (EquineContext.of(player).getCompositeRace().includes(Race.CHANGELING)) { world.setBlockState(pos, state.with(CONSUMING, true)); if (!world.isClient) { @@ -171,15 +171,13 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider { super.neighborUpdate(state, world, pos, sourceBlock, sourcePos, notify); } - @Deprecated @Override - public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + protected VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { return EquineContext.of(context).getSpecies() == Race.CHANGELING ? VoxelShapes.empty() : super.getCollisionShape(state, world, pos, context); } - @Deprecated @Override - public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) { + protected float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) { float delta = super.calcBlockBreakingDelta(state, player, world, pos); delta *= Pony.of(player).getSpecies() == Race.CHANGELING ? 2 : 1; return delta; @@ -213,6 +211,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider { listener = new Listener(pos); } + @SuppressWarnings("deprecation") @Override public void readNbt(NbtCompound nbt, WrapperLookup lookup) { opening = nbt.getBoolean("opening"); @@ -225,6 +224,7 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider { } } + @SuppressWarnings("deprecation") @Override protected void writeNbt(NbtCompound nbt, WrapperLookup lookup) { nbt.putBoolean("opening", opening); @@ -312,14 +312,15 @@ public class HiveBlock extends ConnectingBlock implements BlockEntityProvider { } record Entry (BlockPos pos, BlockState state, @Nullable BlockEntity data) { + @SuppressWarnings("deprecation") public static final Serializer SERIALIZER = Serializer.of((compound, lookup) -> new Entry( - NbtSerialisable.BLOCK_POS.read(compound.getCompound("pos"), lookup), + NbtSerialisable.decode(BlockPos.CODEC, compound.getCompound("pos")).orElse(BlockPos.ORIGIN), NbtSerialisable.decode(BlockState.CODEC, compound.get("state")).orElse(Blocks.AIR.getDefaultState()), compound.getCompound("data"), lookup ), (entry, lookup) -> { NbtCompound compound = new NbtCompound(); - compound.put("pos", NbtSerialisable.BLOCK_POS.write(entry.pos(), lookup)); + compound.put("pos", NbtSerialisable.encode(BlockPos.CODEC, entry.pos())); compound.put("state", NbtSerialisable.encode(BlockState.CODEC, entry.state())); if (entry.data() != null) { compound.put("data", entry.data().createNbtWithId(lookup)); diff --git a/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java b/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java index ef06917f..80d7fc79 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java +++ b/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java @@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.block.jar; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.IntStream; import com.minelittlepony.unicopia.USounds; @@ -12,6 +11,7 @@ import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.mixin.MixinEntityBucketItem; import com.minelittlepony.unicopia.util.FluidHelper; import com.minelittlepony.unicopia.util.NbtSerialisable; +import com.mojang.serialization.Codec; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; import net.minecraft.block.Block; @@ -20,7 +20,6 @@ import net.minecraft.inventory.SidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; import net.minecraft.registry.RegistryWrapper.WrapperLookup; import net.minecraft.util.Hand; import net.minecraft.util.Pair; @@ -33,15 +32,14 @@ public record ItemsJarContents ( ) implements JarContents, SidedInventory { private static final int MAX_SIZE = 16; private static final int[] SLOTS = IntStream.range(0, MAX_SIZE).toArray(); + private static final Codec> STACKS_CODEC = ItemStack.CODEC.listOf(0, MAX_SIZE); public ItemsJarContents(TileData tile) { this(tile, new ArrayList<>(MAX_SIZE)); } public ItemsJarContents(TileData tile, NbtCompound compound, WrapperLookup lookup) { - this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE), lookup) - .limit(MAX_SIZE) - .collect(Collectors.toList())); + this(tile, new ArrayList<>(NbtSerialisable.decode(STACKS_CODEC, compound.get("items")).orElse(List.of()))); } @Override @@ -199,7 +197,7 @@ public record ItemsJarContents ( @Override public NbtCompound toNBT(NbtCompound compound, WrapperLookup lookup) { - compound.put("items", NbtSerialisable.ITEM_STACK.writeAll(stacks, lookup)); + compound.put("items", NbtSerialisable.encode(STACKS_CODEC, stacks)); return compound; } diff --git a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java index 59690bb1..45ba0074 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java @@ -1,6 +1,8 @@ package com.minelittlepony.unicopia.client; import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.function.Predicate; @@ -18,6 +20,7 @@ import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters; import com.minelittlepony.unicopia.client.particle.ClientBoundParticleSpawner; import com.minelittlepony.unicopia.client.sound.*; import com.minelittlepony.unicopia.container.SpellbookChapter; +import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.player.PlayerPhysics; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.dummy.DummyClientPlayerEntity; @@ -47,10 +50,10 @@ import net.minecraft.util.math.random.Random; import net.minecraft.world.World; public class ClientInteractionManager extends InteractionManager { - private final MinecraftClient client = MinecraftClient.getInstance(); private final Int2ObjectMap> playingSounds = new Int2ObjectOpenHashMap<>(); + private final Map>> entitySounds = new HashMap<>(); @Override public SpellbookChapter readChapter(PacketByteBuf buffer) { @@ -99,11 +102,23 @@ public class ClientInteractionManager extends InteractionManager { return EquinePredicates.RAGING.test(source); } }); + } else if (type == SOUND_GEM_FINDING_MAGIC_HUM) { + play(source.getUuid(), type, () -> { + return new MagicAuraSoundInstance(source.getSoundCategory(), Living.living(source), source.getWorld().getRandom()); + }); } }); } + private void play(UUID sourceId, int type, Supplier soundSupplier) { + play(entitySounds.computeIfAbsent(sourceId, id -> new Int2ObjectOpenHashMap<>()), type, soundSupplier); + } + private void play(int type, Supplier soundSupplier) { + play(playingSounds, type, soundSupplier); + } + + private void play(Int2ObjectMap> playingSounds, int type, Supplier soundSupplier) { WeakReference activeSound = playingSounds.get(type); TickableSoundInstance existing; if (activeSound == null || (existing = activeSound.get()) == null || existing.isDone()) { diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java index 53f2f469..6c0c9ac0 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/SmittenEyesRenderer.java @@ -2,8 +2,7 @@ package com.minelittlepony.unicopia.client.render; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.entity.Creature; -import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment; - +import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import net.minecraft.client.MinecraftClient; import net.minecraft.client.model.Dilation; import net.minecraft.client.model.ModelData; @@ -57,6 +56,6 @@ public class SmittenEyesRenderer { } public boolean isSmitten(Creature pony) { - return pony.isSmitten() || WantItNeedItEnchantment.getLevel(pony.asEntity()) > 0; + return pony.isSmitten() || EnchantmentUtil.getWantItNeedItLevel(pony.asEntity()) > 0; } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java b/src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java index ab81defd..fa9e829c 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java +++ b/src/main/java/com/minelittlepony/unicopia/client/sound/MagicAuraSoundInstance.java @@ -1,10 +1,13 @@ package com.minelittlepony.unicopia.client.sound; import com.minelittlepony.unicopia.USounds; +import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.entity.Living; +import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import net.minecraft.sound.SoundCategory; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; public class MagicAuraSoundInstance extends FadeOutSoundInstance { @@ -12,7 +15,7 @@ public class MagicAuraSoundInstance extends FadeOutSoundInstance { private final Living living; public MagicAuraSoundInstance(SoundCategory category, Living living, Random random) { - super(USounds.ITEM_MAGIC_AURA, category, 1, random); + super(USounds.ITEM_MAGIC_AURA, category, 0.1F, random); this.relative = false; this.living = living; setPosition(living.getOriginVector()); @@ -20,18 +23,32 @@ public class MagicAuraSoundInstance extends FadeOutSoundInstance { @Override protected boolean shouldKeepPlaying() { - var data = living.getEnchants().getOrEmpty(UEnchantments.GEM_FINDER); + int level = EnchantmentUtil.getLevel(UEnchantments.GEM_FINDER, living.asEntity()); setPosition(living.getOriginVector()); - - if (!living.asEntity().isRemoved() && data.isPresent()) { - float level = data.get().level; - if (level != targetVolume) { - setTargetVolume(level); - } - return true; + if (level <= 0 || living.asEntity().isRemoved()) { + return false; } - return false; + float volume = computeTargetVolume(level); + if (volume != targetVolume) { + setTargetVolume(volume); + } + return true; + } + + private float computeTargetVolume(int level) { + int radius = 2 + (level * 2); + + BlockPos origin = living.getOrigin(); + + double volume = BlockPos.findClosest(origin, radius, radius, p -> living.asWorld().getBlockState(p).isIn(UTags.Blocks.INTERESTING)) + .map(p -> living.getOriginVector().squaredDistanceTo(p.getX(), p.getY(), p.getZ())) + .map(find -> (1 - (Math.sqrt(find) / radius))) + .orElse(-1D); + + volume = Math.max(volume, 0.04F); + + return (float)volume * (1.3F + level); } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Enchantments.java b/src/main/java/com/minelittlepony/unicopia/entity/Enchantments.java deleted file mode 100644 index 60a47e27..00000000 --- a/src/main/java/com/minelittlepony/unicopia/entity/Enchantments.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.minelittlepony.unicopia.entity; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Supplier; - -import org.jetbrains.annotations.Nullable; - -import com.minelittlepony.unicopia.item.enchantment.UEnchantments; -import com.minelittlepony.unicopia.util.NbtSerialisable; -import com.minelittlepony.unicopia.util.Tickable; - -import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtList; -import net.minecraft.nbt.NbtString; -import net.minecraft.util.Identifier; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.registry.RegistryWrapper.WrapperLookup; -import net.minecraft.server.world.ServerWorld; - -// TODO: Use a EnchantmentLocationBasedEffect for this instead -@Deprecated -public class Enchantments implements NbtSerialisable, Tickable { - - private final Living entity; - - private final Set> equippedEnchantments = new HashSet<>(); - - private final Map, Data> data = new HashMap<>(); - - Enchantments(Living entity) { - this.entity = entity; - } - - @SuppressWarnings("unchecked") - public Optional getOrEmpty(RegistryKey enchantment) { - return Optional.ofNullable((T)data.get(enchantment)); - } - - @SuppressWarnings("unchecked") - public T computeIfAbsent(RegistryKey enchantment, Supplier factory) { - return (T)data.computeIfAbsent(enchantment, e -> factory.get()); - } - - @Nullable - @SuppressWarnings("unchecked") - public T remove(RegistryKey enchantment) { - return (T)data.remove(enchantment); - } - - @Override - public void tick() { - UEnchantments.REGISTRY.forEach(key -> { - var ench = entity.entryFor(key); - int level = EnchantmentHelper.getEquipmentLevel(ench, entity.asEntity()); - - boolean active = level > 0; - - if (active != equippedEnchantments.contains(key)) { - if (active) { - equippedEnchantments.add(key); - ench.value().applyLocationBasedEffects((ServerWorld)entity.asWorld(), level, null, entity.asEntity()); - } else { - equippedEnchantments.remove(key); - ench.value().removeLocationBasedEffects(level, null, entity.asEntity()); - } - } - - if (active) { - ench.value().onTick((ServerWorld)entity.asWorld(), level, null, entity.asEntity()); - } - }); - } - - @Override - public void toNBT(NbtCompound compound, WrapperLookup lookup) { - NbtList list = new NbtList(); - equippedEnchantments.forEach(key -> { - list.add(NbtString.of(key.getValue().toString())); - }); - compound.put("enchants", list); - } - - @Override - public void fromNBT(NbtCompound compound, WrapperLookup lookup) { - equippedEnchantments.clear(); - if (compound.contains("enchants")) { - compound.getList("enchants", NbtElement.STRING_TYPE).forEach(tag -> { - equippedEnchantments.add(RegistryKey.of(RegistryKeys.ENCHANTMENT, Identifier.of(tag.asString()))); - }); - } - } - - public static class Data { - public float level; - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ItemImpl.java b/src/main/java/com/minelittlepony/unicopia/entity/ItemImpl.java index c2ab6c73..5ef5cf42 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/ItemImpl.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/ItemImpl.java @@ -5,7 +5,6 @@ import java.util.List; import com.minelittlepony.unicopia.*; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.UEnchantments; -import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment; import com.minelittlepony.unicopia.network.track.DataTracker; import com.minelittlepony.unicopia.network.track.DataTrackerManager; import com.minelittlepony.unicopia.network.track.Trackable; @@ -56,7 +55,7 @@ public class ItemImpl implements Equine { public boolean beforeUpdate() { if (!entity.getWorld().isClient) { - if (WantItNeedItEnchantment.getLevel(entity) > 0) { + if (EnchantmentUtil.getWantItNeedItLevel(entity) > 0) { var random = entity.getWorld().random; if (random.nextInt(15) == 0) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index 62cd932c..b882b4b6 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -6,6 +6,7 @@ import java.util.stream.StreamSupport; import org.jetbrains.annotations.Nullable; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.Unicopia; @@ -40,6 +41,8 @@ import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.projectile.ProjectileImpactListener; import com.minelittlepony.unicopia.server.world.DragonBreathStore; import com.minelittlepony.unicopia.util.*; +import com.minelittlepony.unicopia.util.serialization.NbtMap; +import com.mojang.serialization.Codec; import net.fabricmc.fabric.api.util.TriState; import net.minecraft.block.BlockState; @@ -67,6 +70,7 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.SoundCategory; import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; @@ -97,7 +101,7 @@ public abstract class Living implements Equine, Caste private final List tickers = new ArrayList<>(); private final LandingEventHandler landEvent = addTicker(new LandingEventHandler(this)); - private final Enchantments enchants = addTicker(new Enchantments(this)); + private final NbtMap enchants = NbtMap.of(Identifier.CODEC, Codec.FLOAT); private final ItemTracker armour = addTicker(new ItemTracker(this)); private final Transportation transportation = new Transportation<>(this); @@ -152,7 +156,7 @@ public abstract class Living implements Equine, Caste return spells.getSlots(); } - public Enchantments getEnchants() { + public NbtMap getEnchants() { return enchants; } @@ -251,6 +255,10 @@ public abstract class Living implements Equine, Caste updateDragonBreath(); + if (EnchantmentUtil.getLevel(UEnchantments.GEM_FINDER, entity) > 0) { + InteractionManager.getInstance().playLoopingSound(entity, InteractionManager.SOUND_GEM_FINDING_MAGIC_HUM, 0); + } + transportation.tick(); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java index b6194cf1..9bd1b5af 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/ai/WantItTakeItGoal.java @@ -5,7 +5,6 @@ import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import com.minelittlepony.unicopia.item.enchantment.UEnchantments; -import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment; import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; @@ -40,7 +39,7 @@ public class WantItTakeItGoal extends BreakHeartGoal { protected boolean canTarget(Entity e) { return e != null && !e.isRemoved() && ( (e instanceof LivingEntity l && predicate.test(mob, l) - || (e instanceof ItemEntity i && WantItNeedItEnchantment.getLevel(i) > 0) + || (e instanceof ItemEntity i && EnchantmentUtil.getWantItNeedItLevel(i) > 0) ) ); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/AmbientSoundsEnchantmentEffect.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/AmbientSoundsEnchantmentEffect.java new file mode 100644 index 00000000..aadc6d29 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/AmbientSoundsEnchantmentEffect.java @@ -0,0 +1,62 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.entity.Living; +import com.minelittlepony.unicopia.util.RegistryUtils; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.enchantment.EnchantmentEffectContext; +import net.minecraft.enchantment.effect.EnchantmentEntityEffect; +import net.minecraft.entity.Entity; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.random.Random; + +public record AmbientSoundsEnchantmentEffect ( + Identifier id, + TagKey sounds +) implements EnchantmentEntityEffect { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + Identifier.CODEC.fieldOf("id").forGetter(AmbientSoundsEnchantmentEffect::id), + TagKey.codec(RegistryKeys.SOUND_EVENT).fieldOf("sounds").forGetter(AmbientSoundsEnchantmentEffect::sounds) + ).apply(instance, AmbientSoundsEnchantmentEffect::new)); + + @Override + public MapCodec getCodec() { + return CODEC; + } + + @Override + public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity entity, Vec3d pos) { + Living.getOrEmpty(entity).ifPresent(user -> { + user.getEnchants().compute(id, (id, data) -> { + if (data == null) { + data = 0F; + } + Random rng = world.getRandom(); + data -= rng.nextFloat() * 0.8F; + int light = world.getLightLevel(entity.getRootVehicle().getBlockPos()); + if (rng.nextInt(Math.max(1, (light * 9) + data.intValue())) == 0) { + data = (float)rng.nextInt(5000); + + RegistryUtils.pickRandom(world, sounds).ifPresent(event -> { + user.asWorld().playSoundFromEntity( + null, + user.asEntity(), + event, SoundCategory.HOSTILE, + 0.5F + rng.nextFloat() * 0.5F, + 0.5F + rng.nextFloat() * 0.5F + ); + }); + } + return data; + }); + }); + + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/CollaboratorEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/CollaboratorEnchantment.java deleted file mode 100644 index 66e41405..00000000 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/CollaboratorEnchantment.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.minelittlepony.unicopia.item.enchantment; - -import com.minelittlepony.unicopia.Unicopia; -import com.minelittlepony.unicopia.entity.Enchantments; -import com.minelittlepony.unicopia.entity.Living; - -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.attribute.EntityAttributeModifier; -import net.minecraft.util.Identifier; -import net.minecraft.entity.attribute.EntityAttributeModifier.Operation; - -public class CollaboratorEnchantment { - private static final Identifier TEAM_STRENGTH_ID = Unicopia.id("team_strength"); - - protected CollaboratorEnchantment() { - //addModifier(EntityAttributes.GENERIC_ATTACK_DAMAGE, this::getModifier); - } - - protected boolean shouldChangeModifiers(Living user, int level) { - return false;//super.shouldChangeModifiers(user, getTeamCollectiveLevel(user, 2 + (level * 2))); - } - - private EntityAttributeModifier getModifier(Living user, int level) { - return new EntityAttributeModifier(TEAM_STRENGTH_ID, user.getEnchants().computeIfAbsent(UEnchantments.HERDS, Enchantments.Data::new).level / 2, Operation.ADD_VALUE); - } - - private static int getTeamCollectiveLevel(Living user, int radius) { - return user.findAllEntitiesInRange(radius, e -> e instanceof LivingEntity) - .mapToInt(e -> EnchantmentUtil.getLevel(UEnchantments.HERDS, (LivingEntity)e)) - .reduce((a, b) -> a + b) - .orElse(0); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/ConsumptionEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/ConsumptionEnchantmentUtil.java similarity index 97% rename from src/main/java/com/minelittlepony/unicopia/item/enchantment/ConsumptionEnchantment.java rename to src/main/java/com/minelittlepony/unicopia/item/enchantment/ConsumptionEnchantmentUtil.java index 3204a374..b3fd18dc 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/ConsumptionEnchantment.java +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/ConsumptionEnchantmentUtil.java @@ -20,7 +20,7 @@ import net.minecraft.sound.SoundCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class ConsumptionEnchantment { +public class ConsumptionEnchantmentUtil { public static boolean applyConsumption(World w, BlockState state, BlockPos pos, @Nullable BlockEntity blockEntity, Entity entity, ItemStack tool) { if (!(w instanceof ServerWorld world)) { diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/DangerSensingEnchantmentEffect.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/DangerSensingEnchantmentEffect.java new file mode 100644 index 00000000..8a9cc74c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/DangerSensingEnchantmentEffect.java @@ -0,0 +1,47 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; +import com.mojang.serialization.MapCodec; +import com.minelittlepony.unicopia.entity.player.Pony; + +import net.minecraft.enchantment.EnchantmentEffectContext; +import net.minecraft.enchantment.effect.EnchantmentEntityEffect; +import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.HostileEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; + +public class DangerSensingEnchantmentEffect implements EnchantmentEntityEffect { + public static final DangerSensingEnchantmentEffect INSTANCE = new DangerSensingEnchantmentEffect(); + public static final MapCodec CODEC = MapCodec.unit(INSTANCE); + + @Override + public MapCodec getCodec() { + return CODEC; + } + + @Override + public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity entity, Vec3d pos) { + Pony.of(entity).ifPresent(pony -> { + if (pony.asEntity().age % 10 == 0) { + int range = (level + 1) * 3; + if (pony.asWorld().getEntitiesByClass(HostileEntity.class, pony.asEntity().getBoundingBox().expand(range, 0, range), enemy -> { + return enemy != null + && enemy.canTarget(pony.asEntity()) + && enemy.canSee(pony.asEntity()) + && enemy.getTarget() == pony.asEntity(); + }).isEmpty()) { + return; + } + + Bar bar = pony.getMagicalReserves().getEnergy(); + float targetPercent = (level / (float)pony.entryFor(UEnchantments.STRESSED).value().definition().maxLevel()) * 0.05125F; + float increase = 1F + (level * level)/100F; + if (bar.getPercentFill() < targetPercent) { + bar.add(increase); + } + } + }); + + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java index ffdce88c..7585f043 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/EnchantmentUtil.java @@ -8,6 +8,8 @@ import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffects; @@ -40,6 +42,27 @@ public interface EnchantmentUtil { return true; } + + static boolean prefersEquipment(ItemStack newStack, ItemStack oldStack) { + int newLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, newStack); + int oldLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, oldStack); + return newLevel > oldLevel; + } + + static int getWantItNeedItLevel(Entity entity) { + return entity instanceof LivingEntity l ? getWantItNeedItLevel(l) + : entity instanceof ItemEntity i ? getWantItNeedItLevel(i) + : 0; + } + + static int getWantItNeedItLevel(ItemEntity entity) { + return getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getStack()); + } + + static int getWantItNeedItLevel(LivingEntity entity) { + return getLevel(UEnchantments.WANT_IT_NEED_IT, entity); + } + static int getLuck(int baseline, LivingEntity entity) { boolean naturallyLucky = Living.getOrEmpty(entity).filter(c -> c.getCompositeRace().canUseEarth()).isPresent(); if (naturallyLucky) { diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/GemFindingEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/GemFindingEnchantment.java deleted file mode 100644 index db567fdc..00000000 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/GemFindingEnchantment.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.minelittlepony.unicopia.item.enchantment; - -import com.minelittlepony.unicopia.UTags; -import com.minelittlepony.unicopia.client.sound.MagicAuraSoundInstance; -import com.minelittlepony.unicopia.entity.Enchantments; -import com.minelittlepony.unicopia.entity.Living; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.math.BlockPos; - -public class GemFindingEnchantment { - - public void onUserTick(Living user, int level) { - int radius = 2 + (level * 2); - - BlockPos origin = user.getOrigin(); - - double volume = BlockPos.findClosest(origin, radius, radius, pos -> user.asWorld().getBlockState(pos).isIn(UTags.Blocks.INTERESTING)) - .map(p -> user.getOriginVector().squaredDistanceTo(p.getX(), p.getY(), p.getZ())) - .map(find -> (1 - (Math.sqrt(find) / radius))) - .orElse(-1D); - - volume = Math.max(volume, 0.04F); - - user.getEnchants().computeIfAbsent(UEnchantments.GEM_FINDER, Enchantments.Data::new).level = (float)volume * (1.3F + level); - } - - public void onEquipped(Living user) { - if (user.isClient()) { - MinecraftClient.getInstance().getSoundManager().play(new MagicAuraSoundInstance(user.asEntity().getSoundCategory(), user, user.asWorld().getRandom())); - } - } - - public void onUnequipped(Living user) { - user.getEnchants().remove(UEnchantments.GEM_FINDER).level = 0; - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/GroupBasedAttributeEnchantmentEffect.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/GroupBasedAttributeEnchantmentEffect.java new file mode 100644 index 00000000..870b52e0 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/GroupBasedAttributeEnchantmentEffect.java @@ -0,0 +1,53 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.entity.Living; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.enchantment.EnchantmentEffectContext; +import net.minecraft.enchantment.EnchantmentLevelBasedValue; +import net.minecraft.enchantment.effect.AttributeEnchantmentEffect; +import net.minecraft.enchantment.effect.EnchantmentEntityEffect; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.attribute.EntityAttributeModifier; +import net.minecraft.util.math.Vec3d; +import net.minecraft.server.world.ServerWorld; + +public record GroupBasedAttributeEnchantmentEffect ( + AttributeEnchantmentEffect attribute, + EnchantmentLevelBasedValue range + ) implements EnchantmentEntityEffect { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + AttributeEnchantmentEffect.CODEC.fieldOf("attribute").forGetter(GroupBasedAttributeEnchantmentEffect::attribute), + EnchantmentLevelBasedValue.CODEC.fieldOf("range").forGetter(GroupBasedAttributeEnchantmentEffect::range) + ).apply(instance, GroupBasedAttributeEnchantmentEffect::new)); + + @Override + public MapCodec getCodec() { + return CODEC; + } + + @Override + public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity user, Vec3d pos) { + Living.getOrEmpty(user).ifPresent(living -> { + int collectiveLevels = living.findAllEntitiesInRange(range.getValue(level), e -> e instanceof LivingEntity) + .mapToInt(e -> EnchantmentUtil.getLevel(UEnchantments.HERDS, (LivingEntity)e)) + .reduce(Integer::sum) + .orElse(0); + + living.updateAttributeModifier(attribute.id(), attribute.attribute(), attribute.amount().getValue(collectiveLevels), value -> { + return new EntityAttributeModifier(attribute.id(), value, attribute.operation()); + }, false); + }); + } + + @Override + public void remove(EnchantmentEffectContext context, Entity user, Vec3d pos, int level) { + Living.getOrEmpty(user).ifPresent(living -> { + living.updateAttributeModifier(attribute.id(), attribute.attribute(), 0, value -> { + return new EntityAttributeModifier(attribute.id(), value, attribute.operation()); + }, false); + }); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/ParticleTrailEnchantmentEntityEffect.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/ParticleTrailEnchantmentEntityEffect.java new file mode 100644 index 00000000..8ca364f9 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/ParticleTrailEnchantmentEntityEffect.java @@ -0,0 +1,48 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import java.util.Optional; + +import com.minelittlepony.unicopia.particle.FollowingParticleEffect; +import com.minelittlepony.unicopia.particle.ParticleUtils; +import com.minelittlepony.unicopia.particle.UParticles; +import com.minelittlepony.unicopia.particle.WeakTarget; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.enchantment.EnchantmentEffectContext; +import net.minecraft.enchantment.effect.EnchantmentEntityEffect; +import net.minecraft.entity.Entity; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; + +public record ParticleTrailEnchantmentEntityEffect( + Optional particle, + float followSpeed, + int density, + int probability + ) implements EnchantmentEntityEffect { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ParticleTypes.TYPE_CODEC.optionalFieldOf("particle").forGetter(ParticleTrailEnchantmentEntityEffect::particle), + Codec.FLOAT.fieldOf("followSpeed").forGetter(ParticleTrailEnchantmentEntityEffect::followSpeed), + Codec.INT.fieldOf("density").forGetter(ParticleTrailEnchantmentEntityEffect::density), + Codec.INT.fieldOf("probability").forGetter(ParticleTrailEnchantmentEntityEffect::probability) + ).apply(instance, ParticleTrailEnchantmentEntityEffect::new)); + + @Override + public MapCodec getCodec() { + return CODEC; + } + + @Override + public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity entity, Vec3d pos) { + if (probability <= 0 || world.random.nextInt(probability) == 0) { + ParticleUtils.spawnParticles(new FollowingParticleEffect( + UParticles.HEALTH_DRAIN, + new WeakTarget(entity.getCameraPosVec(1), entity), followSpeed, particle + ), entity, density); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/PoisonedJokeEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/PoisonedJokeEnchantment.java deleted file mode 100644 index 52c45f39..00000000 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/PoisonedJokeEnchantment.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.minelittlepony.unicopia.item.enchantment; - -import com.minelittlepony.unicopia.UTags; -import com.minelittlepony.unicopia.entity.Enchantments; -import com.minelittlepony.unicopia.entity.Living; -import com.minelittlepony.unicopia.util.RegistryUtils; -import net.minecraft.sound.SoundCategory; -import net.minecraft.util.math.random.Random; - -public class PoisonedJokeEnchantment { - - public void onUserTick(Living user, int level) { - if (user.asWorld().isClient) { - return; - } - - int light = user.asWorld().getLightLevel(user.asEntity().getRootVehicle().getBlockPos()); - Random rng = user.asWorld().random; - Enchantments.Data data = user.getEnchants().computeIfAbsent(UEnchantments.POISONED_JOKE, Enchantments.Data::new); - - data.level -= rng.nextFloat() * 0.8F; - if (rng.nextInt(Math.max(1, (light * 9) + (int)data.level)) == 0) { - data.level = rng.nextInt(5000); - - RegistryUtils.pickRandom(user.asWorld(), UTags.Sounds.POISON_JOKE_EVENTS).ifPresent(event -> { - user.asWorld().playSoundFromEntity( - null, - user.asEntity(), - event, SoundCategory.HOSTILE, - 0.5F + rng.nextFloat() * 0.5F, - 0.5F + rng.nextFloat() * 0.5F - ); - }); - } - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/StressfulEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/StressfulEnchantment.java deleted file mode 100644 index b184b50b..00000000 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/StressfulEnchantment.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.minelittlepony.unicopia.item.enchantment; - -import com.minelittlepony.unicopia.entity.Living; -import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; - -import com.minelittlepony.unicopia.entity.player.Pony; - -import net.minecraft.entity.mob.HostileEntity; - -public class StressfulEnchantment { - - public void onUserTick(Living user, int level) { - if (user instanceof Pony pony && pony.asEntity().age % 10 == 0) { - int range = (level + 1) * 3; - if (pony.asWorld().getEntitiesByClass(HostileEntity.class, user.asEntity().getBoundingBox().expand(range, 0, range), enemy -> { - return enemy != null - && enemy.canTarget(user.asEntity()) - && enemy.canSee(user.asEntity()) - && enemy.getTarget() == user.asEntity(); - }).isEmpty()) { - return; - } - - Bar bar = pony.getMagicalReserves().getEnergy(); - float targetPercent = (level / (float)user.entryFor(UEnchantments.STRESSED).value().definition().maxLevel()) * 0.05125F; - float increase = 1F + (level * level)/100F; - if (bar.getPercentFill() < targetPercent) { - bar.add(increase); - } - } - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantmentEffects.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantmentEffects.java new file mode 100644 index 00000000..aad02e37 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantmentEffects.java @@ -0,0 +1,21 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import com.minelittlepony.unicopia.Unicopia; +import com.mojang.serialization.MapCodec; + +import net.minecraft.enchantment.effect.EnchantmentEntityEffect; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; + +public interface UEnchantmentEffects { + static void bootstrap() { + register("group_based_attribute", GroupBasedAttributeEnchantmentEffect.CODEC); + register("poisoned_joke_sound", AmbientSoundsEnchantmentEffect.CODEC); + register("danger_sensor", DangerSensingEnchantmentEffect.CODEC); + register("particle_trail", ParticleTrailEnchantmentEntityEffect.CODEC); + } + + private static void register(String name, MapCodec codec) { + Registry.register(Registries.ENCHANTMENT_ENTITY_EFFECT_TYPE, Unicopia.id("name"), codec); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantmentValidSlots.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantmentValidSlots.java deleted file mode 100644 index b4c1c122..00000000 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantmentValidSlots.java +++ /dev/null @@ -1,9 +0,0 @@ -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 }; -} diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java index cb9196b2..ce8629a9 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/UEnchantments.java @@ -2,6 +2,9 @@ package com.minelittlepony.unicopia.item.enchantment; import java.util.ArrayList; import java.util.List; +import java.util.Optional; + +import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.entity.mob.UEntityAttributes; import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback; @@ -12,6 +15,7 @@ import net.minecraft.enchantment.EnchantmentLevelBasedValue; import net.minecraft.enchantment.effect.AttributeEnchantmentEffect; import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.attribute.EntityAttributeModifier.Operation; import net.minecraft.item.Item; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; @@ -137,6 +141,7 @@ public interface UEnchantments { } static void bootstrap() { + UEnchantmentEffects.bootstrap(); // Options.table -> EnchantmentTags.IN_ENCHANTING_TABLE // Optiona.curse -> EnchantmentTags.CURSE // Options.traded -> EnchantmentTags.TRADEABLE @@ -153,7 +158,6 @@ public interface UEnchantments { 4, AttributeModifierSlot.HAND ))); - // TODO: gem finder effect register(registry, PADDED, Enchantment.builder(Enchantment.definition( items.getEntryList(ItemTags.HEAD_ARMOR_ENCHANTABLE).orElseThrow(), @@ -197,8 +201,12 @@ public interface UEnchantments { 1, AttributeModifierSlot.MAINHAND ) - )); - // TODO: Herding effect + ).addEffect(EnchantmentEffectComponentTypes.TICK, new GroupBasedAttributeEnchantmentEffect(new AttributeEnchantmentEffect( + Unicopia.id("team_strength"), + EntityAttributes.GENERIC_ATTACK_DAMAGE, + EnchantmentLevelBasedValue.linear(0, 1), + Operation.ADD_VALUE + ), EnchantmentLevelBasedValue.linear(2, 2)))); register(registry, REPULSION, Enchantment.builder( Enchantment.definition( @@ -225,8 +233,8 @@ public interface UEnchantments { Enchantment.constantCost(2), Enchantment.constantCost(10), 4, AttributeModifierSlot.ANY - ))); - // TODO: Want it need it effect + )).addEffect(EnchantmentEffectComponentTypes.TICK, new ParticleTrailEnchantmentEntityEffect(Optional.empty(), 0.2F, 1, 10))); + register(registry, POISONED_JOKE, Enchantment.builder(Enchantment.definition( items.getEntryList(ItemTags.VANISHING_ENCHANTABLE).orElseThrow(), Rarity.VERY_RARE, @@ -234,8 +242,7 @@ public interface UEnchantments { Enchantment.constantCost(2), Enchantment.constantCost(10), 4, AttributeModifierSlot.ANY - ))); - // TODO: Poisoned joke effect + )).addEffect(EnchantmentEffectComponentTypes.TICK, new AmbientSoundsEnchantmentEffect(Unicopia.id("poisoned_joke_level"), UTags.Sounds.POISON_JOKE_EVENTS))); register(registry, CLINGY, Enchantment.builder(Enchantment.definition( items.getEntryList(ItemTags.VANISHING_ENCHANTABLE).orElseThrow(), @@ -244,8 +251,7 @@ public interface UEnchantments { Enchantment.constantCost(2), Enchantment.constantCost(12), 4, AttributeModifierSlot.ANY - ))); - // TODO: Stressful effect + )).addEffect(EnchantmentEffectComponentTypes.TICK, DangerSensingEnchantmentEffect.INSTANCE)); register(registry, CLINGY, Enchantment.builder(Enchantment.definition( items.getEntryList(ItemTags.EQUIPPABLE_ENCHANTABLE).orElseThrow(), diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/WantItNeedItEnchantment.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/WantItNeedItEnchantment.java deleted file mode 100644 index 3310213b..00000000 --- a/src/main/java/com/minelittlepony/unicopia/item/enchantment/WantItNeedItEnchantment.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.minelittlepony.unicopia.item.enchantment; - -import com.minelittlepony.unicopia.entity.Creature; -import com.minelittlepony.unicopia.entity.Living; -import com.minelittlepony.unicopia.particle.FollowingParticleEffect; -import com.minelittlepony.unicopia.particle.ParticleUtils; -import com.minelittlepony.unicopia.particle.UParticles; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; - -public class WantItNeedItEnchantment { - - public void onUserTick(Living user, int level) { - if (user instanceof Creature && user.asWorld().random.nextInt(10) == 0) { - ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, user.asEntity(), 0.2F), user.asEntity(), 1); - } - } - - public static boolean prefersEquipment(ItemStack newStack, ItemStack oldStack) { - int newLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, newStack); - int oldLevel = EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, oldStack); - return newLevel > oldLevel; - } - - public static int getLevel(Entity entity) { - return entity instanceof LivingEntity l ? getLevel(l) - : entity instanceof ItemEntity i ? getLevel(i) - : 0; - } - - public static int getLevel(ItemEntity entity) { - return EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getStack()); - } - - public static int getLevel(LivingEntity entity) { - return EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity) - + EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getOffHandStack()) - + EnchantmentUtil.getLevel(UEnchantments.WANT_IT_NEED_IT, entity.getMainHandStack()); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBlock.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBlock.java index 3cbfe530..d577b4e7 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinBlock.java @@ -6,7 +6,7 @@ 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 com.minelittlepony.unicopia.item.enchantment.ConsumptionEnchantmentUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -24,7 +24,7 @@ abstract class MixinBlock { 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)) { + if (ConsumptionEnchantmentUtil.applyConsumption(world, state, pos, blockEntity, entity, stack)) { info.cancel(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java index d9200a75..783a413f 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinMobEntity.java @@ -9,8 +9,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.minelittlepony.unicopia.entity.*; -import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment; - +import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.goal.GoalSelector; @@ -35,7 +34,7 @@ abstract class MixinMobEntity extends LivingEntity implements Equine.Container info) { - if (WantItNeedItEnchantment.prefersEquipment(newStack, oldStack)) { + if (EnchantmentUtil.prefersEquipment(newStack, oldStack)) { info.setReturnValue(true); } } diff --git a/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java b/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java index 2191c654..1eb18fdc 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java +++ b/src/main/java/com/minelittlepony/unicopia/util/NbtSerialisable.java @@ -8,7 +8,6 @@ import java.util.stream.Stream; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.*; import net.minecraft.registry.RegistryWrapper.WrapperLookup; import net.minecraft.util.math.BlockPos; @@ -17,8 +16,6 @@ import net.minecraft.util.math.Vec3d; public interface NbtSerialisable { @Deprecated Serializer BLOCK_POS = Serializer.ofCodec(BlockPos.CODEC); - @Deprecated - Serializer ITEM_STACK = Serializer.ofCodec(ItemStack.CODEC); /** * Called to save this to nbt to persist state on file or to transmit over the network diff --git a/src/main/java/com/minelittlepony/unicopia/util/serialization/NbtMap.java b/src/main/java/com/minelittlepony/unicopia/util/serialization/NbtMap.java new file mode 100644 index 00000000..c8cf57ca --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/util/serialization/NbtMap.java @@ -0,0 +1,60 @@ +package com.minelittlepony.unicopia.util.serialization; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.util.NbtSerialisable; +import com.mojang.serialization.Codec; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.registry.RegistryWrapper.WrapperLookup; + +public class NbtMap implements NbtSerialisable { + public static NbtMap of(Codec keyCodec, Codec valueCodec) { + return new NbtMap<>(Codec.unboundedMap(keyCodec, valueCodec)); + } + + private final Codec> codec; + private final Map data = new HashMap<>(); + + public NbtMap(Codec> codec) { + this.codec = codec; + } + + public Optional getOrEmpty(K key) { + return Optional.ofNullable(data.get(key)); + } + + public V computeIfAbsent(K key, Supplier factory) { + return data.computeIfAbsent(key, e -> factory.get()); + } + + public V put(K key, V value) { + return data.put(key, value); + } + + public V compute(K key, BiFunction function) { + return data.compute(key, function); + } + + @Nullable + public V remove(K key) { + return data.remove(key); + } + + @Override + public void toNBT(NbtCompound compound, WrapperLookup lookup) { + compound.put("data", NbtSerialisable.encode(codec, data)); + } + + @Override + public void fromNBT(NbtCompound compound, WrapperLookup lookup) { + data.clear(); + NbtSerialisable.decode(codec, compound.get("data")).ifPresent(data::putAll); + } +}