From 498ec2bca072bf4a643027e1881b97fd2b3210df Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 23 Jun 2024 14:41:44 +0100 Subject: [PATCH] The pearl necklace now has 4 durability --- .../unicopia/ability/ChangeFormAbility.java | 7 +++ .../unicopia/client/gui/UHud.java | 4 +- .../client/minelittlepony/AmuletGear.java | 4 +- .../client/minelittlepony/BangleGear.java | 6 +-- .../client/minelittlepony/GlassesGear.java | 4 +- .../unicopia/client/minelittlepony/Main.java | 4 +- .../client/render/AmuletFeatureRenderer.java | 2 +- .../render/BraceletFeatureRenderer.java | 14 ++--- .../client/render/GlassesFeatureRenderer.java | 2 +- .../unicopia/client/render/PlayerPoser.java | 2 +- .../compat/trinkets/TrinketsDelegate.java | 51 +++++++++++++------ .../compat/trinkets/TrinketsDelegateImpl.java | 17 ++++++- .../container/SpellbookScreenHandler.java | 4 +- .../unicopia/entity/Living.java | 6 +-- .../effect/SunBlindnessStatusEffect.java | 5 +- .../unicopia/entity/mob/SombraEntity.java | 10 ++-- .../unicopia/entity/player/PlayerPhysics.java | 11 ++-- .../unicopia/entity/player/Pony.java | 5 +- .../unicopia/item/AlicornAmuletItem.java | 2 +- .../unicopia/item/AmuletItem.java | 13 +++-- .../unicopia/item/BellItem.java | 2 +- .../unicopia/item/FriendshipBraceletItem.java | 29 +++++++---- .../unicopia/item/GlassesItem.java | 9 ++-- .../unicopia/item/PegasusAmuletItem.java | 5 -- .../minelittlepony/unicopia/item/UItems.java | 1 + .../unicopia/network/Channel.java | 1 + .../unicopia/network/MsgTrinketBroken.java | 22 ++++++++ .../handler/ClientNetworkHandlerImpl.java | 38 ++++++++++++++ 28 files changed, 194 insertions(+), 86 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/network/MsgTrinketBroken.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ChangeFormAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ChangeFormAbility.java index 67aa667f..6f4cc3e0 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ChangeFormAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ChangeFormAbility.java @@ -10,8 +10,10 @@ import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.advancement.UCriteria; +import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.FriendshipBraceletItem; +import com.minelittlepony.unicopia.item.UItems; import net.minecraft.particle.ParticleTypes; import net.minecraft.sound.SoundCategory; @@ -73,6 +75,11 @@ public class ChangeFormAbility implements Ability { List targets = getTargets(player).toList(); player.subtractEnergyCost(5 * targets.size()); + TrinketsDelegate.EquippedStack amulet = UItems.PEARL_NECKLACE.getForEntity(player.asEntity()); + if (!amulet.stack().isEmpty()) { + amulet.stack().damage(1, player.asEntity(), amulet.breakStatusSender()); + } + boolean isTransforming = player.getSuppressedRace().isUnset(); targets.forEach(target -> { Race supressed = target.getSuppressedRace(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index fb50166e..1dd0ae28 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -214,8 +214,8 @@ public class UHud { boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS); - ItemStack glasses = GlassesItem.getForEntity(client.player); - boolean hasSunglasses = glasses.getItem() == UItems.SUNGLASSES; + ItemStack glasses = GlassesItem.getForEntity(client.player).stack(); + boolean hasSunglasses = glasses.isOf(UItems.SUNGLASSES); if (hasEffect || (!hasSunglasses && pony.getObservedSpecies() == Race.BAT && SunBlindnessStatusEffect.hasSunExposure(client.player))) { float i = hasEffect ? (client.player.getStatusEffect(UEffects.SUN_BLINDNESS).getDuration() - tickDelta) / SunBlindnessStatusEffect.MAX_DURATION : 0; diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/AmuletGear.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/AmuletGear.java index fad07825..68589a6a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/AmuletGear.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/AmuletGear.java @@ -31,7 +31,7 @@ class AmuletGear extends AmuletModel implements IGear { @Override public boolean canRender(IModel model, Entity entity) { - return entity instanceof LivingEntity living && !AmuletItem.getForEntity(living).isEmpty(); + return entity instanceof LivingEntity living && !AmuletItem.get(living).stack().isEmpty(); } @Override @@ -41,7 +41,7 @@ class AmuletGear extends AmuletModel implements IGear { @Override public Identifier getTexture(T entity, Context context) { - return textures.computeIfAbsent(Registries.ITEM.getId(AmuletItem.getForEntity((LivingEntity)entity).getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png")); + return textures.computeIfAbsent(Registries.ITEM.getId(AmuletItem.get((LivingEntity)entity).stack().getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png")); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BangleGear.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BangleGear.java index 5346192a..d223b502 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BangleGear.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BangleGear.java @@ -67,8 +67,8 @@ class BangleGear implements IGear { public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) { alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).getModel().startsWith("slim"); FriendshipBraceletItem.getWornBangles((LivingEntity)entity, slot).findFirst().ifPresent(bracelet -> { - color = ((DyeableItem)bracelet.getItem()).getColor(bracelet); - glowing = ((GlowableItem)bracelet.getItem()).isGlowing(bracelet); + color = ((DyeableItem)bracelet.stack().getItem()).getColor(bracelet.stack()); + glowing = ((GlowableItem)bracelet.stack().getItem()).isGlowing(bracelet.stack()); }); BraceletModel m = alex ? alexModel : steveModel; @@ -76,7 +76,7 @@ class BangleGear implements IGear { m.setAngles(biped); } Arm mainArm = ((LivingEntity)entity).getMainArm(); - m.setVisible(slot == TrinketsDelegate.MAINHAND ? mainArm : mainArm.getOpposite()); + m.setVisible(slot == TrinketsDelegate.MAIN_GLOVE ? mainArm : mainArm.getOpposite()); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/GlassesGear.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/GlassesGear.java index ab06f473..3f582a09 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/GlassesGear.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/GlassesGear.java @@ -28,7 +28,7 @@ class GlassesGear extends GlassesModel implements IGear { @Override public boolean canRender(IModel model, Entity entity) { - return entity instanceof LivingEntity living && !GlassesItem.getForEntity(living).isEmpty(); + return entity instanceof LivingEntity living && !GlassesItem.getForEntity(living).stack().isEmpty(); } @Override @@ -38,7 +38,7 @@ class GlassesGear extends GlassesModel implements IGear { @Override public Identifier getTexture(T entity, Context context) { - return textures.computeIfAbsent(Registries.ITEM.getId(GlassesItem.getForEntity((LivingEntity)entity).getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png")); + return textures.computeIfAbsent(Registries.ITEM.getId(GlassesItem.getForEntity((LivingEntity)entity).stack().getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png")); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java index abb6659e..229fb3ed 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java @@ -44,8 +44,8 @@ public class Main extends MineLPDelegate implements ClientModInitializer { public void onInitializeClient() { INSTANCE = this; PonyModelPrepareCallback.EVENT.register(this::onPonyModelPrepared); - IGear.register(() -> new BangleGear(TrinketsDelegate.MAINHAND)); - IGear.register(() -> new BangleGear(TrinketsDelegate.OFFHAND)); + IGear.register(() -> new BangleGear(TrinketsDelegate.MAIN_GLOVE)); + IGear.register(() -> new BangleGear(TrinketsDelegate.SECONDARY_GLOVE)); IGear.register(HeldEntityGear::new); IGear.register(BodyPartGear::pegasusWings); IGear.register(BodyPartGear::batWings); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java index f2a2c54f..99bce334 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java @@ -42,7 +42,7 @@ public class AmuletFeatureRenderer implements AccessoryF @Override public void render(MatrixStack matrices, VertexConsumerProvider renderContext, int lightUv, E entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch) { - ItemStack stack = AmuletItem.getForEntity(entity); + ItemStack stack = AmuletItem.get(entity).stack(); if (!stack.isEmpty()) { Identifier texture = textures.computeIfAbsent(Registries.ITEM.getId(stack.getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png")); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/BraceletFeatureRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/BraceletFeatureRenderer.java index 017e0f8c..aa5c3b1a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/BraceletFeatureRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/BraceletFeatureRenderer.java @@ -48,11 +48,11 @@ public class BraceletFeatureRenderer implements Accessor @Override public void render(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, E entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch) { - FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.MAINHAND).findFirst().ifPresent(bangle -> { - renderBangleThirdPerson(bangle, stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm()); + FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.MAIN_GLOVE).findFirst().ifPresent(bangle -> { + renderBangleThirdPerson(bangle.stack(), stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm()); }); - FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.OFFHAND).findFirst().ifPresent(bangle -> { - renderBangleThirdPerson(bangle, stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm().getOpposite()); + FriendshipBraceletItem.getWornBangles(entity, TrinketsDelegate.SECONDARY_GLOVE).findFirst().ifPresent(bangle -> { + renderBangleThirdPerson(bangle.stack(), stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch, entity.getMainArm().getOpposite()); }); } @@ -82,14 +82,14 @@ public class BraceletFeatureRenderer implements Accessor @Override public void renderArm(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, E entity, ModelPart armModel, Arm side) { - FriendshipBraceletItem.getWornBangles(entity, side == entity.getMainArm() ? TrinketsDelegate.MAINHAND : TrinketsDelegate.OFFHAND).findFirst().ifPresent(item -> { - int j = ((DyeableItem)item.getItem()).getColor(item); + FriendshipBraceletItem.getWornBangles(entity, side == entity.getMainArm() ? TrinketsDelegate.MAIN_GLOVE : TrinketsDelegate.SECONDARY_GLOVE).findFirst().ifPresent(item -> { + int j = ((DyeableItem)item.stack().getItem()).getColor(item.stack()); boolean alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).getModel().startsWith("slim"); BraceletModel model = alex ? alexModel : steveModel; - boolean glowing = ((GlowableItem)item.getItem()).isGlowing(item); + boolean glowing = ((GlowableItem)item.stack().getItem()).isGlowing(item.stack()); if (MineLPDelegate.getInstance().getPlayerPonyRace((ClientPlayerEntity)entity).isEquine()) { stack.translate(side == Arm.LEFT ? 0.06 : -0.06, 0.3, 0); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/GlassesFeatureRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/GlassesFeatureRenderer.java index 40771191..7a0ca70d 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/GlassesFeatureRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/GlassesFeatureRenderer.java @@ -36,7 +36,7 @@ public class GlassesFeatureRenderer implements Accessory @Override public void render(MatrixStack matrices, VertexConsumerProvider renderContext, int lightUv, E entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch) { - ItemStack stack = GlassesItem.getForEntity(entity); + ItemStack stack = GlassesItem.getForEntity(entity).stack(); if (!stack.isEmpty()) { Identifier texture = textures.computeIfAbsent(Registries.ITEM.getId(stack.getItem()), id -> new Identifier(id.getNamespace(), "textures/models/armor/" + id.getPath() + ".png")); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/PlayerPoser.java b/src/main/java/com/minelittlepony/unicopia/client/render/PlayerPoser.java index 2402dfab..6c21e24c 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/PlayerPoser.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/PlayerPoser.java @@ -42,7 +42,7 @@ public class PlayerPoser { boolean liftLeftArm = mainArm == Arm.LEFT || !ponyRace.isEquine(); boolean liftRightArm = mainArm == Arm.RIGHT || !ponyRace.isEquine(); - ItemStack glasses = GlassesItem.getForEntity(player); + ItemStack glasses = GlassesItem.getForEntity(player).stack(); ModelPart head = model.getHead(); if (context == Context.THIRD_PERSON && !player.isSneaking()) { diff --git a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java index c9e17eb8..f19d592a 100644 --- a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java @@ -1,6 +1,8 @@ package com.minelittlepony.unicopia.compat.trinkets; import java.util.*; +import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -16,16 +18,17 @@ import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.registry.tag.TagKey; import net.minecraft.screen.slot.Slot; import net.minecraft.util.Identifier; public interface TrinketsDelegate { - Identifier MAINHAND = new Identifier("hand:glove"); - Identifier OFFHAND = new Identifier("offhand:glove"); + Identifier MAIN_GLOVE = new Identifier("hand:glove"); + Identifier SECONDARY_GLOVE = new Identifier("offhand:glove"); Identifier NECKLACE = new Identifier("chest:necklace"); Identifier FACE = new Identifier("head:face"); - Set ALL = new TreeSet<>(List.of(MAINHAND, OFFHAND, NECKLACE, FACE)); + Set ALL = new TreeSet<>(List.of(MAIN_GLOVE, SECONDARY_GLOVE, NECKLACE, FACE)); TrinketsDelegate EMPTY = new TrinketsDelegate() {}; @@ -61,8 +64,8 @@ public interface TrinketsDelegate { default void setEquippedStack(LivingEntity entity, Identifier slot, ItemStack stack) { EquipmentSlot eq = slot == FACE ? EquipmentSlot.HEAD : slot == NECKLACE ? EquipmentSlot.CHEST - : slot == MAINHAND ? EquipmentSlot.CHEST - : slot == OFFHAND ? EquipmentSlot.OFFHAND + : slot == MAIN_GLOVE ? EquipmentSlot.CHEST + : slot == SECONDARY_GLOVE ? EquipmentSlot.OFFHAND : null; if (eq != null) { entity.equipStack(eq, stack); @@ -70,19 +73,27 @@ public interface TrinketsDelegate { } default Set getAvailableTrinketSlots(LivingEntity entity, Set probedSlots) { - return probedSlots.stream().filter(slot -> getEquipped(entity, slot).anyMatch(ItemStack::isEmpty)).collect(Collectors.toSet()); + return probedSlots.stream().filter(slot -> getEquipped(entity, slot).map(EquippedStack::stack).anyMatch(ItemStack::isEmpty)).collect(Collectors.toSet()); } - default Stream getEquipped(LivingEntity entity, Identifier slot) { + default Stream getEquipped(LivingEntity entity, Identifier slot, TagKey tag) { + return getEquipped(entity, slot, stack -> stack.isIn(tag)); + } - if (slot == FACE) { - return Stream.of(entity.getEquippedStack(EquipmentSlot.HEAD)); + default Stream getEquipped(LivingEntity entity, Identifier slot) { + return getEquipped(entity, slot, (Predicate)null); + } + + default Stream getEquipped(LivingEntity entity, Identifier slot, @Nullable Predicate predicate) { + + if (slot == FACE && (predicate == null || predicate.test(entity.getEquippedStack(EquipmentSlot.HEAD)))) { + return Stream.of(new EquippedStack(entity, EquipmentSlot.HEAD)); } - if (slot == NECKLACE || slot == MAINHAND) { - return Stream.of(entity.getEquippedStack(EquipmentSlot.CHEST)); + if ((slot == NECKLACE || slot == MAIN_GLOVE) && (predicate == null || predicate.test(entity.getEquippedStack(EquipmentSlot.CHEST)))) { + return Stream.of(new EquippedStack(entity, EquipmentSlot.CHEST)); } - if (slot == OFFHAND) { - return Stream.of(entity.getOffHandStack()); + if (slot == SECONDARY_GLOVE && (predicate == null || predicate.test(entity.getEquippedStack(EquipmentSlot.OFFHAND)))) { + return Stream.of(new EquippedStack(entity, EquipmentSlot.OFFHAND)); } return Stream.empty(); @@ -102,16 +113,24 @@ public interface TrinketsDelegate { interface Inventory extends EntityConvertable { - default Stream getEquippedStacks(Identifier slot) { + default Stream getEquippedStacks(Identifier slot) { return TrinketsDelegate.getInstance(asEntity()).getEquipped(asEntity(), slot); } - default ItemStack getEquippedStack(Identifier slot) { - return getEquippedStacks(slot).findFirst().orElse(ItemStack.EMPTY); + default EquippedStack getEquippedStack(Identifier slot) { + return getEquippedStacks(slot).findFirst().orElse(EquippedStack.EMPTY); } default void equipStack(Identifier slot, ItemStack stack) { TrinketsDelegate.getInstance(asEntity()).setEquippedStack(asEntity(), slot, stack); } } + + record EquippedStack(ItemStack stack, Runnable sendUpdate, Consumer breakStatusSender) { + public static EquippedStack EMPTY = new EquippedStack(ItemStack.EMPTY, () -> {}, l -> {}); + + EquippedStack(LivingEntity entity, EquipmentSlot slot) { + this(entity.getEquippedStack(slot), () -> {}, l -> l.sendEquipmentBreakStatus(slot)); + } + } } diff --git a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegateImpl.java b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegateImpl.java index f8f0ec24..edbe0274 100644 --- a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegateImpl.java +++ b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegateImpl.java @@ -1,11 +1,16 @@ package com.minelittlepony.unicopia.compat.trinkets; import java.util.*; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jetbrains.annotations.Nullable; + import com.minelittlepony.unicopia.container.SpellbookScreenHandler; import com.minelittlepony.unicopia.item.enchantment.UEnchantments; +import com.minelittlepony.unicopia.network.Channel; +import com.minelittlepony.unicopia.network.MsgTrinketBroken; import com.minelittlepony.unicopia.util.InventoryUtil; import dev.emi.trinkets.TrinketSlot; import dev.emi.trinkets.api.*; @@ -80,8 +85,16 @@ public class TrinketsDelegateImpl implements TrinketsDelegate { } @Override - public Stream getEquipped(LivingEntity entity, Identifier slot) { - return getInventory(entity, slot).stream().flatMap(InventoryUtil::stream).filter(s -> !s.isEmpty()); + public Stream getEquipped(LivingEntity entity, Identifier slot, @Nullable Predicate predicate) { + return getInventory(entity, slot).stream().flatMap(inventory -> { + return InventoryUtil.stream(inventory).filter(s -> !s.isEmpty() && (predicate == null || predicate.test(s))).map(stack -> { + ItemStack oldStack = stack.copy(); + return new EquippedStack(stack, inventory::markUpdate, l -> { + inventory.markUpdate(); + Channel.SERVER_TRINKET_BROKEN.sendToSurroundingPlayers(new MsgTrinketBroken(oldStack, l.getId()), l); + }); + }); + }); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/container/SpellbookScreenHandler.java b/src/main/java/com/minelittlepony/unicopia/container/SpellbookScreenHandler.java index de69aacf..8f5f112a 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/SpellbookScreenHandler.java +++ b/src/main/java/com/minelittlepony/unicopia/container/SpellbookScreenHandler.java @@ -147,8 +147,8 @@ public class SpellbookScreenHandler extends ScreenHandler { TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.FACE, 0, rightHandX, inventoryY + slotSpacing * 6).ifPresent(this::addSlot); TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.NECKLACE, 0, leftHandX, equipmentY + slotSpacing).ifPresent(this::addSlot); - TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.MAINHAND, 0, leftHandX, equipmentY).ifPresent(this::addSlot); - TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.OFFHAND, 0, rightHandX, equipmentY).ifPresent(this::addSlot); + TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.MAIN_GLOVE, 0, leftHandX, equipmentY).ifPresent(this::addSlot); + TrinketsDelegate.getInstance(inv.player).createSlot(this, inv.player, TrinketsDelegate.SECONDARY_GLOVE, 0, rightHandX, equipmentY).ifPresent(this::addSlot); addSlot(outputSlot = new OutputSlot(this, inventory.player, input, result, 0, gemPos.get(0))); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index ba453869..756a4491 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -371,8 +371,8 @@ public abstract class Living implements Equine, Caste } if (magical.isIn(UTags.DamageTypes.BREAKS_SUNGLASSES)) { - ItemStack glasses = GlassesItem.getForEntity(entity); - if (glasses.getItem() == UItems.SUNGLASSES) { + ItemStack glasses = GlassesItem.getForEntity(entity).stack(); + if (glasses.isOf(UItems.SUNGLASSES)) { ItemStack broken = UItems.BROKEN_SUNGLASSES.getDefaultStack(); broken.setNbt(glasses.getNbt()); TrinketsDelegate.getInstance(entity).setEquippedStack(entity, TrinketsDelegate.FACE, broken); @@ -417,7 +417,7 @@ public abstract class Living implements Equine, Caste return StreamSupport.stream(entity.getArmorItems().spliterator(), false); } return Stream.concat( - TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE), + TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE).map(TrinketsDelegate.EquippedStack::stack), StreamSupport.stream(entity.getArmorItems().spliterator(), false) ); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java index 10e607a9..57f91ed4 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/SunBlindnessStatusEffect.java @@ -11,7 +11,6 @@ import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.util.MeteorlogicalUtil; import net.minecraft.entity.Entity; -import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; @@ -72,9 +71,7 @@ public class SunBlindnessStatusEffect extends StatusEffect { return true; } - if (entity.getEquippedStack(EquipmentSlot.HEAD).isIn(UTags.Items.SHADES) - || TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(i -> i.isIn(UTags.Items.SHADES)) - || entity.isSubmergedInWater()) { + if (entity.isSubmergedInWater() || TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE, i -> i.isIn(UTags.Items.SHADES)).findAny().isPresent()) { return false; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/SombraEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/SombraEntity.java index 26714449..b673037c 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/SombraEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/SombraEntity.java @@ -11,11 +11,11 @@ import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell; import com.minelittlepony.unicopia.advancement.UCriteria; +import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate; import com.minelittlepony.unicopia.entity.AmuletSelectors; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.ai.ArenaAttackGoal; import com.minelittlepony.unicopia.entity.player.Pony; -import com.minelittlepony.unicopia.item.AmuletItem; import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.ParticleSource; @@ -63,7 +63,6 @@ import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.passive.IronGolemEntity; import net.minecraft.entity.passive.MerchantEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtHelper; @@ -484,9 +483,10 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti player.sendMessage(Text.translatable("entity.unicopia.sombra.taunt")); } } - ItemStack amulet = AmuletItem.getForEntity(player); - if (amulet.isOf(UItems.ALICORN_AMULET)) { - amulet.decrement(1); + TrinketsDelegate.EquippedStack amulet = UItems.ALICORN_AMULET.getForEntity(player); + if (!amulet.stack().isEmpty()) { + amulet.stack().decrement(1); + amulet.sendUpdate(); } } boolean damaged = super.damage(source, amount); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index 1dc7851f..c2789be6 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -13,6 +13,7 @@ import com.minelittlepony.unicopia.advancement.UCriteria; import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.compat.ad_astra.OxygenApi; +import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate; import com.minelittlepony.unicopia.entity.*; import com.minelittlepony.unicopia.entity.damage.UDamageTypes; import com.minelittlepony.unicopia.entity.duck.LivingEntityDuck; @@ -38,12 +39,10 @@ import net.fabricmc.fabric.api.tag.convention.v1.ConventionalBlockTags; import net.minecraft.block.*; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.EntityType; -import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LightningEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.damage.DamageSource; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleTypes; import net.minecraft.predicate.entity.EntityPredicates; @@ -499,8 +498,8 @@ public class PlayerPhysics extends EntityPhysics implements Tickab private void tickArtificialFlight(MutableVector velocity) { if (ticksInAir % 10 == 0 && !entity.getWorld().isClient) { - ItemStack stack = AmuletItem.getForEntity(entity); - if (ChargeableItem.getEnergy(stack) < 9) { + TrinketsDelegate.EquippedStack stack = AmuletItem.get(entity); + if (ChargeableItem.getEnergy(stack.stack()) < 9) { playSound(USounds.ITEM_ICARUS_WINGS_WARN, 0.13F, 0.5F); } @@ -517,10 +516,10 @@ public class PlayerPhysics extends EntityPhysics implements Tickab minDamage *= 3; } - ChargeableItem.consumeEnergy(stack, energyConsumed); + ChargeableItem.consumeEnergy(stack.stack(), energyConsumed); if (entity.getWorld().random.nextInt(damageInterval) == 0) { - stack.damage(minDamage + entity.getWorld().random.nextInt(50), entity, e -> e.sendEquipmentBreakStatus(EquipmentSlot.CHEST)); + stack.stack().damage(minDamage + entity.getWorld().random.nextInt(50), (LivingEntity)entity, stack.breakStatusSender()); } if (!lastFlightType.canFly()) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 6c55a3be..845cb09c 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -484,6 +484,9 @@ public class Pony extends Living implements Copyable, Update AmuletSelectors.PEARL_NECKLACE.test(entity) ? suppressedRace.or(Race.SEAPONY) : null ); UCriteria.PLAYER_CHANGE_RACE.trigger(entity); + + var hasNecklace = AmuletSelectors.PEARL_NECKLACE.test(entity); + System.out.println(hasNecklace); } @Override @@ -526,7 +529,7 @@ public class Pony extends Living implements Copyable, Update } if (getObservedSpecies() == Race.BAT && !entity.hasPortalCooldown()) { - boolean hasShades = TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(s -> s.isIn(UTags.Items.SHADES)); + boolean hasShades = TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE).anyMatch(s -> s.stack().isIn(UTags.Items.SHADES)); if (!this.hasShades && hasShades && getObservedSpecies() == Race.BAT) { UCriteria.WEAR_SHADES.trigger(entity); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java b/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java index f3c16ffa..6cb64651 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java @@ -247,7 +247,7 @@ public class AlicornAmuletItem extends AmuletItem implements ItemTracker.Trackab // bind to the player after 3 days if (daysAttached >= 3 && !pony.asEntity().isCreative()) { - stack = living.getArmour().getEquippedStack(TrinketsDelegate.NECKLACE); + stack = living.getArmour().getEquippedStack(TrinketsDelegate.NECKLACE).stack(); if (stack.getItem() == this && !EnchantmentHelper.hasBindingCurse(stack)) { pony.playSound(USounds.ITEM_ALICORN_AMULET_HALLUCINATION, 3, 1); stack = stack.copy(); diff --git a/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java b/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java index cb3426d5..8e0673f7 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java @@ -86,7 +86,13 @@ public class AmuletItem extends WearableItem implements ChargeableItem { } public final boolean isApplicable(LivingEntity entity) { - return isApplicable(getForEntity(entity)); + return !getForEntity(entity).stack().isEmpty(); + } + + public TrinketsDelegate.EquippedStack getForEntity(LivingEntity entity) { + return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE, this::isApplicable) + .findFirst() + .orElse(TrinketsDelegate.EquippedStack.EMPTY); } @Override @@ -94,11 +100,10 @@ public class AmuletItem extends WearableItem implements ChargeableItem { return maxEnergy; } - public static ItemStack getForEntity(LivingEntity entity) { + public static TrinketsDelegate.EquippedStack get(LivingEntity entity) { return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE) - .filter(stack -> stack.getItem() instanceof AmuletItem) .findFirst() - .orElse(ItemStack.EMPTY); + .orElse(TrinketsDelegate.EquippedStack.EMPTY); } public static class ModifiersBuilder { diff --git a/src/main/java/com/minelittlepony/unicopia/item/BellItem.java b/src/main/java/com/minelittlepony/unicopia/item/BellItem.java index cf9af687..2b5f4d99 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/BellItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/BellItem.java @@ -69,7 +69,7 @@ public class BellItem extends Item implements ChargeableItem { @Override public TypedActionResult use(World world, PlayerEntity player, Hand hand) { ItemStack stack = player.getStackInHand(hand); - ItemStack offhandStack = AmuletItem.getForEntity(player); + ItemStack offhandStack = AmuletItem.get(player).stack(); if (!(offhandStack.getItem() instanceof ChargeableItem)) { offhandStack = player.getStackInHand(hand == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND); diff --git a/src/main/java/com/minelittlepony/unicopia/item/FriendshipBraceletItem.java b/src/main/java/com/minelittlepony/unicopia/item/FriendshipBraceletItem.java index 1828f66d..6fe650ea 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/FriendshipBraceletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/FriendshipBraceletItem.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.item; import java.util.List; import java.util.UUID; +import java.util.function.Predicate; import java.util.stream.Stream; import org.jetbrains.annotations.Nullable; @@ -120,28 +121,36 @@ public class FriendshipBraceletItem extends WearableItem implements DyeableItem, public static boolean isComrade(Owned caster, Entity entity) { return entity instanceof LivingEntity l && caster.getMasterId() - .filter(id -> getWornBangles(l).anyMatch(stack -> isSignedBy(stack, id))) + .filter(id -> getWornBangles(l).anyMatch(stack -> isSignedBy(stack.stack(), id))) .isPresent(); } public static boolean isComrade(UUID signator, Entity entity) { - return entity instanceof LivingEntity l && getWornBangles(l).anyMatch(stack -> isSignedBy(stack, signator)); + return entity instanceof LivingEntity l && getWornBangles(l, stack -> isSignedBy(stack, signator)).findAny().isPresent(); } public static Stream getPartyMembers(Caster caster, double radius) { return Pony.stream(caster.findAllEntitiesInRange(radius, entity -> isComrade(caster, entity))); } - public static Stream getWornBangles(LivingEntity entity) { + private static final Predicate IS_BANGLE = stack -> stack.isOf(UItems.FRIENDSHIP_BRACELET); + + public static Stream getWornBangles(LivingEntity entity) { return Stream.concat( - TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.MAINHAND), - TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.OFFHAND) - ).filter(stack -> stack.getItem() == UItems.FRIENDSHIP_BRACELET); + TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.MAIN_GLOVE, IS_BANGLE), + TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.SECONDARY_GLOVE, IS_BANGLE) + ); } - public static Stream getWornBangles(LivingEntity entity, Identifier slot) { - return TrinketsDelegate.getInstance(entity) - .getEquipped(entity, slot) - .filter(stack -> stack.getItem() == UItems.FRIENDSHIP_BRACELET); + public static Stream getWornBangles(LivingEntity entity, @Nullable Predicate predicate) { + predicate = predicate == null ? IS_BANGLE : IS_BANGLE.and(predicate); + return Stream.concat( + TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.MAIN_GLOVE, predicate), + TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.SECONDARY_GLOVE, predicate) + ); + } + + public static Stream getWornBangles(LivingEntity entity, Identifier slot) { + return TrinketsDelegate.getInstance(entity).getEquipped(entity, slot, IS_BANGLE); } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/GlassesItem.java b/src/main/java/com/minelittlepony/unicopia/item/GlassesItem.java index 3c49931e..0e88bead 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/GlassesItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/GlassesItem.java @@ -25,13 +25,12 @@ public class GlassesItem extends WearableItem { } public boolean isApplicable(LivingEntity entity) { - return getForEntity(entity).getItem() == this; + return getForEntity(entity).stack().isOf(this); } - public static ItemStack getForEntity(LivingEntity entity) { - return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE) - .filter(stack -> stack.getItem() instanceof GlassesItem) + public static TrinketsDelegate.EquippedStack getForEntity(LivingEntity entity) { + return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.FACE, stack -> stack.getItem() instanceof GlassesItem) .findFirst() - .orElse(ItemStack.EMPTY); + .orElse(TrinketsDelegate.EquippedStack.EMPTY); } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/PegasusAmuletItem.java b/src/main/java/com/minelittlepony/unicopia/item/PegasusAmuletItem.java index b80e5f94..65cdb292 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/PegasusAmuletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/PegasusAmuletItem.java @@ -25,11 +25,6 @@ public class PegasusAmuletItem extends AmuletItem implements ItemTracker.Trackab } - @Override - public boolean isApplicable(ItemStack stack) { - return super.isApplicable(stack); - } - @Override public int getDefaultCharge() { return getMaxCharge() / 2; diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index 6b012f20..ce6b0bcf 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -220,6 +220,7 @@ public interface UItems { .rarity(Rarity.UNCOMMON), 0), ItemGroups.TOOLS); AmuletItem PEARL_NECKLACE = register("pearl_necklace", new AmuletItem(new FabricItemSettings() .maxCount(1) + .maxDamage(4) .rarity(Rarity.UNCOMMON), 0), ItemGroups.TOOLS); GlassesItem SUNGLASSES = register("sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1)), ItemGroups.COMBAT); diff --git a/src/main/java/com/minelittlepony/unicopia/network/Channel.java b/src/main/java/com/minelittlepony/unicopia/network/Channel.java index f7464deb..ee3b3025 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/Channel.java +++ b/src/main/java/com/minelittlepony/unicopia/network/Channel.java @@ -37,6 +37,7 @@ public interface Channel { S2CPacketType SERVER_SKY_ANGLE = SimpleNetworking.serverToClient(Unicopia.id("sky_angle"), MsgSkyAngle::new); S2CPacketType CONFIGURATION_CHANGE = SimpleNetworking.serverToClient(Unicopia.id("config"), MsgConfigurationChange::new); S2CPacketType SERVER_ZAP_STAGE = SimpleNetworking.serverToClient(Unicopia.id("zap_stage"), MsgZapAppleStage::new); + S2CPacketType SERVER_TRINKET_BROKEN = SimpleNetworking.serverToClient(Unicopia.id("trinket_broken"), MsgTrinketBroken::new); static void bootstrap() { ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgTrinketBroken.java b/src/main/java/com/minelittlepony/unicopia/network/MsgTrinketBroken.java new file mode 100644 index 00000000..d2d38104 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgTrinketBroken.java @@ -0,0 +1,22 @@ +package com.minelittlepony.unicopia.network; + +import com.sollace.fabwork.api.packets.Packet; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; + +/** + * Sent to the client when an item equipped in a trinket slot breaks + */ +public record MsgTrinketBroken (ItemStack stack, int entityId) implements Packet { + public MsgTrinketBroken(PacketByteBuf buffer) { + this(buffer.readItemStack(), buffer.readInt()); + } + + @Override + public void toBuffer(PacketByteBuf buffer) { + buffer.writeItemStack(stack); + buffer.writeInt(entityId); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java b/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java index e17dc1ff..c014bce5 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java +++ b/src/main/java/com/minelittlepony/unicopia/network/handler/ClientNetworkHandlerImpl.java @@ -20,8 +20,14 @@ import com.minelittlepony.unicopia.network.*; import com.minelittlepony.unicopia.network.MsgCasterLookRequest.Reply; import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.particle.ItemStackParticleEffect; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.sound.SoundEvents; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; public class ClientNetworkHandlerImpl { private final MinecraftClient client = MinecraftClient.getInstance(); @@ -36,6 +42,7 @@ public class ClientNetworkHandlerImpl { Channel.SERVER_ZAP_STAGE.receiver().addPersistentListener(this::handleZapStage); Channel.SERVER_PLAYER_ANIMATION_CHANGE.receiver().addPersistentListener(this::handlePlayerAnimation); Channel.SERVER_REQUEST_PLAYER_LOOK.receiver().addPersistentListener(this::handleCasterLookRequest); + Channel.SERVER_TRINKET_BROKEN.receiver().addPersistentListener(this::handleTrinketBroken); Channel.CONFIGURATION_CHANGE.receiver().addPersistentListener(this::handleConfigurationChange); } @@ -96,6 +103,37 @@ public class ClientNetworkHandlerImpl { Channel.CLIENT_CASTER_LOOK.sendToServer(new Reply(packet.spellId(), Rot.of(player))); } + private void handleTrinketBroken(PlayerEntity player, MsgTrinketBroken packet) { + if (player.getWorld().getEntityById(packet.entityId()) instanceof LivingEntity sender) { + ItemStack stack = packet.stack(); + if (!stack.isEmpty()) { + if (!sender.isSilent()) { + sender.getWorld().playSound( + sender.getX(), sender.getY(), sender.getZ(), + SoundEvents.ENTITY_ITEM_BREAK, sender.getSoundCategory(), + 0.8F, + 0.8F + sender.getWorld().random.nextFloat() * 0.4F, + false + ); + } + + int count = 5; + + for (int i = 0; i < count; ++i) { + Vec3d vec3d = new Vec3d((sender.getWorld().random.nextFloat() - 0.5) * 0.1, Math.random() * 0.1 + 0.1, 0.0); + vec3d = vec3d.rotateX(-sender.getPitch() * (float) (Math.PI / 180.0)); + vec3d = vec3d.rotateY(-sender.getYaw() * (float) (Math.PI / 180.0)); + double d = (-sender.getWorld().random.nextFloat()) * 0.6 - 0.3; + Vec3d vec3d2 = new Vec3d((sender.getWorld().random.nextFloat() - 0.5) * 0.3, d, 0.6); + vec3d2 = vec3d2.rotateX(-sender.getPitch() * (float) (Math.PI / 180.0)); + vec3d2 = vec3d2.rotateY(-sender.getYaw() * (float) (Math.PI / 180.0)); + vec3d2 = vec3d2.add(sender.getX(), sender.getEyeY(), sender.getZ()); + sender.getWorld().addParticle(new ItemStackParticleEffect(ParticleTypes.ITEM, stack), vec3d2.x, vec3d2.y, vec3d2.z, vec3d.x, vec3d.y + 0.05, vec3d.z); + } + } + } + } + private void handleConfigurationChange(PlayerEntity sender, MsgConfigurationChange packet) { InteractionManager.getInstance().setSyncedConfig(packet.config()); }