diff --git a/gradle.properties b/gradle.properties index 378d3a75..c1e19842 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ fabric_version=0.97.6+1.20.6 maven_group = eu.pb4 -mod_version = 0.8.0-pre.1 +mod_version = 0.8.0 minecraft_version_supported = ">=1.20.5-" diff --git a/polymer-autohost/src/main/resources/polymer-autohost.mixins.json b/polymer-autohost/src/main/resources/polymer-autohost.mixins.json index 8f4c72d5..d89914db 100644 --- a/polymer-autohost/src/main/resources/polymer-autohost.mixins.json +++ b/polymer-autohost/src/main/resources/polymer-autohost.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "eu.pb4.polymer.autohost.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "ClientConnectionMixin", "MinecraftServerMixin", diff --git a/polymer-blocks/src/main/resources/polymer-blocks.mixins.json b/polymer-blocks/src/main/resources/polymer-blocks.mixins.json index 3254f19b..ad91128b 100644 --- a/polymer-blocks/src/main/resources/polymer-blocks.mixins.json +++ b/polymer-blocks/src/main/resources/polymer-blocks.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "eu.pb4.polymer.blocks.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "plugin": "eu.pb4.polymer.blocks.mixin.PolymerBlocksMixinConfigPlugin", "mixins": [ "polymc.PolyRegistryMixin" diff --git a/polymer-common/src/main/resources/polymer-common.mixins.json b/polymer-common/src/main/resources/polymer-common.mixins.json index fb2b3b38..10c05034 100644 --- a/polymer-common/src/main/resources/polymer-common.mixins.json +++ b/polymer-common/src/main/resources/polymer-common.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "eu.pb4.polymer.common.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "ClientConnectionMixin", "CommandManagerMixin", diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItem.java b/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItem.java index 8d56ca43..3cb48633 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItem.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItem.java @@ -103,4 +103,8 @@ default boolean handleMiningOnServer(ItemStack tool, BlockState targetBlock, Blo default ItemStack getPolymerItemStack(ItemStack itemStack, TooltipType tooltipType, @Nullable ServerPlayerEntity player) { return PolymerItemUtils.createItemStack(itemStack, tooltipType, player); } + + default boolean shouldStorePolymerItemStackCount() { + return false; + } } \ No newline at end of file diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItemUtils.java b/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItemUtils.java index b71953fb..0eefae65 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItemUtils.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/api/item/PolymerItemUtils.java @@ -1,5 +1,8 @@ package eu.pb4.polymer.core.api.item; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.Dynamic; import com.mojang.serialization.MapCodec; import eu.pb4.polymer.common.api.PolymerCommonUtils; import eu.pb4.polymer.common.api.events.BooleanEvent; @@ -24,6 +27,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.trim.ArmorTrim; import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtOps; import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.Registries; @@ -40,20 +44,29 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Predicate; public final class PolymerItemUtils { public static final String POLYMER_STACK = "$polymer:stack"; public static final MapCodec POLYMER_STACK_CODEC = ItemStack.CODEC.fieldOf(POLYMER_STACK); + public static final MapCodec POLYMER_STACK_UNCOUNTED_CODEC = ItemStack.UNCOUNTED_CODEC.fieldOf(POLYMER_STACK); + public static final MapCodec POLYMER_STACK_HAS_COUNT_CODEC = Codec.BOOL.optionalFieldOf("$polymer:counted", false); public static final MapCodec POLYMER_STACK_ID_CODEC = Identifier.CODEC.fieldOf("id").fieldOf(POLYMER_STACK); + public static final MapCodec> POLYMER_STACK_COMPONENTS_CODEC = Codec.unboundedMap(Identifier.CODEC, + Codec.PASSTHROUGH.comapFlatMap((dynamic) -> { + var nbt = dynamic.convert(NbtOps.INSTANCE).getValue(); + return DataResult.success(nbt == dynamic.getValue() ? nbt.copy() : nbt); + }, (nbt) -> new Dynamic<>(NbtOps.INSTANCE, nbt.copy()))) + .optionalFieldOf("components", Map.of()).fieldOf(POLYMER_STACK); public static final Style CLEAN_STYLE = Style.EMPTY.withItalic(false).withColor(Formatting.WHITE); /** * Allows to force rendering of some items as polymer one (for example vanilla ones) */ public static final BooleanEvent> ITEM_CHECK = new BooleanEvent<>(); /** - * Allows to modify how virtual items looks before being send to client (only if using build in methods!) + * Allows to modify how virtual items looks before being sent to client (only if using build in methods!) * It can modify virtual version directly, as long as it's returned at the end. * You can also return new ItemStack, however please keep previous nbt so other modifications aren't removed if not needed! */ @@ -117,7 +130,6 @@ public static ItemStack getPolymerItemStack(ItemStack itemStack, RegistryWrapper * @param tooltipContext Tooltip Context * @param player Player being sent to * @return Client side ItemStack - * */ public static ItemStack getPolymerItemStack(ItemStack itemStack, TooltipType tooltipContext, RegistryWrapper.WrapperLookup lookup, @Nullable ServerPlayerEntity player) { if (getPolymerIdentifier(itemStack) != null) { @@ -146,8 +158,16 @@ public static ItemStack getRealItemStack(ItemStack itemStack, RegistryWrapper.Wr if (custom != null && custom.contains(POLYMER_STACK)) { try { + var counted = custom.get(POLYMER_STACK_HAS_COUNT_CODEC).result().orElse(Boolean.FALSE); + //noinspection deprecation - return POLYMER_STACK_CODEC.decode(RegistryOps.of(NbtOps.INSTANCE, lookup), NbtOps.INSTANCE.getMap(custom.getNbt()).getOrThrow()).getOrThrow(); + var x = (counted ? POLYMER_STACK_CODEC : POLYMER_STACK_UNCOUNTED_CODEC).decode(RegistryOps.of(NbtOps.INSTANCE, lookup), NbtOps.INSTANCE.getMap(custom.getNbt()).getOrThrow()).getOrThrow(); + + if (!counted) { + x.setCount(itemStack.getCount()); + } + + return x; } catch (Throwable ignored) { } @@ -163,6 +183,7 @@ public static ItemStack getRealItemStack(ItemStack itemStack, RegistryWrapper.Wr public static Identifier getPolymerIdentifier(ItemStack itemStack) { return getPolymerIdentifier(itemStack.get(DataComponentTypes.CUSTOM_DATA)); } + public static Identifier getPolymerIdentifier(@Nullable NbtComponent custom) { if (custom != null && custom.contains(POLYMER_STACK)) { @@ -189,6 +210,31 @@ public static Identifier getServerIdentifier(@Nullable NbtComponent nbtData) { return getPolymerIdentifier(nbtData); } + @Nullable + public static Map getServerComponents(ItemStack stack) { + return getPolymerComponents(stack.get(DataComponentTypes.CUSTOM_DATA)); + } + + @Nullable + public static Map getPolymerComponents(ItemStack stack) { + return getPolymerComponents(stack.get(DataComponentTypes.CUSTOM_DATA)); + + } + + @Nullable + public static Map getServerComponents(@Nullable NbtComponent nbtData) { + return getPolymerComponents(nbtData); + } + + @Nullable + public static Map getPolymerComponents(@Nullable NbtComponent nbtData) { + if (nbtData == null || getPolymerIdentifier(nbtData) == null) { + return null; + } + + return nbtData.get(POLYMER_STACK_COMPONENTS_CODEC).result().orElse(Map.of()); + } + public static boolean isPolymerServerItem(ItemStack itemStack) { return isPolymerServerItem(itemStack, PolymerUtils.getPlayerContext()); } @@ -318,6 +364,7 @@ public static int getSafeColor(int inputColor) { * @param player Player seeing it * @return Client side ItemStack */ + public static ItemStack createItemStack(ItemStack itemStack, @Nullable ServerPlayerEntity player) { return createItemStack(itemStack, PolymerUtils.getTooltipType(player), player); } @@ -339,11 +386,15 @@ public static ItemStack createItemStack(ItemStack itemStack, TooltipType tooltip Item item = itemStack.getItem(); int cmd = -1; int color = -1; + boolean storeCount; if (itemStack.getItem() instanceof PolymerItem virtualItem) { var data = PolymerItemUtils.getItemSafely(virtualItem, itemStack, player); item = data.item(); cmd = data.customModelData(); color = data.color(); + storeCount = virtualItem.shouldStorePolymerItemStackCount(); + } else { + storeCount = false; } ItemStack out = new ItemStack(item, itemStack.getCount()); @@ -367,9 +418,15 @@ public static ItemStack createItemStack(ItemStack itemStack, TooltipType tooltip } try { PolymerCommonUtils.executeWithPlayerContext(null, () -> { - out.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of( - (NbtCompound) POLYMER_STACK_CODEC.encoder().encodeStart(RegistryOps.of(NbtOps.INSTANCE, lookup), itemStack).getOrThrow() - )); + var comp = NbtComponent.of( + (NbtCompound) (storeCount ? POLYMER_STACK_CODEC : POLYMER_STACK_UNCOUNTED_CODEC).encoder() + .encodeStart(RegistryOps.of(NbtOps.INSTANCE, lookup), itemStack).getOrThrow() + ); + if (storeCount) { + out.set(DataComponentTypes.CUSTOM_DATA, comp.with(POLYMER_STACK_HAS_COUNT_CODEC, true).getOrThrow()); + } else { + out.set(DataComponentTypes.CUSTOM_DATA, comp); + } }); } catch (Throwable e) { out.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT.with(POLYMER_STACK_ID_CODEC, Registries.ITEM.getId(itemStack.getItem())).getOrThrow()); diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/PolymerImplUtils.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/PolymerImplUtils.java index c654ef7a..f88ed724 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/PolymerImplUtils.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/PolymerImplUtils.java @@ -22,6 +22,8 @@ import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.item.TooltipType; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; @@ -252,16 +254,17 @@ public static void pickBlock(ServerPlayerEntity player, BlockPos pos, boolean wi return; } - BlockEntity blockEntity = null; if (isCreative && withNbt && blockState.hasBlockEntity()) { - blockEntity = player.getWorld().getBlockEntity(pos); + var blockEntity = player.getWorld().getBlockEntity(pos); + if (blockEntity != null && (!blockEntity.copyItemDataRequiresOperator() || player.isCreativeLevelTwoOp())) { + itemStack.applyComponentsFrom(blockEntity.createComponentMap()); + itemStack.set(DataComponentTypes.BLOCK_ENTITY_DATA, NbtComponent.of(blockEntity.createComponentlessNbt(player.getRegistryManager()))); + } } PlayerInventory playerInventory = player.getInventory(); - if (blockEntity != null) { - addBlockEntityNbt(itemStack, blockEntity); - } + int i = playerInventory.getSlotWithStack(itemStack); if (isCreative) { @@ -279,25 +282,6 @@ public static void pickBlock(ServerPlayerEntity player, BlockPos pos, boolean wi } } - - private static void addBlockEntityNbt(ItemStack stack, BlockEntity blockEntity) { - // todo - - /*NbtCompound nbtCompound = blockEntity.createNbtWithId(blockEntity.getWorld().getRegistryManager()); - NbtCompound nbtCompound3; - if (stack.getItem() instanceof PlayerHeadItem && nbtCompound.contains("SkullOwner")) { - nbtCompound3 = nbtCompound.getCompound("SkullOwner"); - stack.getOrCreateNbt().put("SkullOwner", nbtCompound3); - } else { - stack.setSubNbt("BlockEntityTag", nbtCompound); - nbtCompound3 = new NbtCompound(); - NbtList nbtList = new NbtList(); - nbtList.add(NbtString.of("\"(+NBT)\"")); - nbtCompound3.put("Lore", nbtList); - stack.setSubNbt("display", nbtCompound3); - }*/ - } - public static void pickEntity(ServerPlayerEntity player, Entity entity) { var isCreative = player.isCreative(); diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/client/compat/CompatUtils.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/client/compat/CompatUtils.java index bd697b1c..741fa083 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/client/compat/CompatUtils.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/client/compat/CompatUtils.java @@ -1,12 +1,8 @@ package eu.pb4.polymer.core.impl.client.compat; -import eu.pb4.polymer.core.api.client.PolymerClientUtils; import eu.pb4.polymer.core.api.item.PolymerItemUtils; -import eu.pb4.polymer.core.impl.PolymerImpl; import eu.pb4.polymer.core.impl.client.InternalClientRegistry; import eu.pb4.polymer.core.impl.client.interfaces.ClientItemGroupExtension; -import eu.pb4.polymer.networking.impl.client.ClientPacketRegistry; -import net.minecraft.client.MinecraftClient; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.NbtComponent; import net.minecraft.item.*; @@ -17,6 +13,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +import java.util.Map; import java.util.Objects; import java.util.function.Consumer; @@ -34,29 +31,14 @@ public static boolean areEqualItems(ItemStack a, ItemStack b) { if (!areSamePolymerType(a, b)) { return false; } - var nbtA = getBackingNbt(a); - var nbtB = getBackingNbt(b); + var nbtA = getBackingComponents(a); + var nbtB = getBackingComponents(b); return Objects.equals(nbtA, nbtB); } @Nullable - public static NbtCompound getBackingNbt(ItemStack stack) { - if (!stack.contains(DataComponentTypes.CUSTOM_DATA)) { - return null; - } - var nbt = stack.get(DataComponentTypes.CUSTOM_DATA).getNbt(); - if (PolymerItemUtils.getServerIdentifier(stack) == null) { - return nbt; - } - - var maybeNbt = nbt.getCompound(PolymerItemUtils.POLYMER_STACK).getCompound("components"); - - if (maybeNbt != null) { - return maybeNbt; - } - maybeNbt = nbt.getCompound("PolyMcOriginal"); - - return maybeNbt != null && maybeNbt.contains("tag", NbtElement.COMPOUND_TYPE) ? maybeNbt.getCompound("tag") : null; + public static Map getBackingComponents(ItemStack stack) { + return PolymerItemUtils.getServerComponents(stack); } public static boolean isServerSide(ItemStack stack) { diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/interfaces/TypeAwareNbtCompound.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/interfaces/TypeAwareNbtCompound.java deleted file mode 100644 index afb4b2e2..00000000 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/interfaces/TypeAwareNbtCompound.java +++ /dev/null @@ -1,16 +0,0 @@ -package eu.pb4.polymer.core.impl.interfaces; - -import net.minecraft.nbt.NbtByte; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtString; - -public interface TypeAwareNbtCompound { - String MARKER_KEY = "$$polymer:type"; - - NbtString STACK_TYPE = NbtString.of( "item_stack"); - NbtString STATE_TYPE = NbtString.of("block_state"); - default void polymerCore$setType(NbtString type) {}; - default NbtString polymerCore$getType() { - return null; - }; -} diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java index a54cf715..afbfc277 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/PacketPatcher.java @@ -1,6 +1,7 @@ package eu.pb4.polymer.core.impl.networking; import eu.pb4.polymer.common.impl.CompatStatus; +import eu.pb4.polymer.common.impl.entity.InternalEntityHelpers; import eu.pb4.polymer.core.api.block.PolymerBlockUtils; import eu.pb4.polymer.core.api.entity.PolymerEntity; import eu.pb4.polymer.core.api.other.PolymerStatusEffect; @@ -93,6 +94,10 @@ public static boolean prevent(ServerCommonNetworkHandler handler, Packet pack return true; } else if ((packet instanceof EntityEquipmentUpdateS2CPacket original && original.getEquipmentList().isEmpty()) || !EntityAttachedPacket.shouldSend(packet, player)) { return true; + } else if ((packet instanceof EntityAttributesS2CPacket original + && EntityAttachedPacket.get(packet, original.getEntityId()) instanceof PolymerEntity entity + && InternalEntityHelpers.isLivingEntity(entity.getPolymerEntityType(player)))) { + return true; } else if (packet instanceof BlockEntityUpdateS2CPacket be && PolymerBlockUtils.isPolymerBlockEntityType(be.getBlockEntityType())) { return true; } diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/entry/PolymerItemEntry.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/entry/PolymerItemEntry.java index 824c05a9..c7066522 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/entry/PolymerItemEntry.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/networking/entry/PolymerItemEntry.java @@ -9,7 +9,6 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; -// todo @ApiStatus.Internal public record PolymerItemEntry(int numId, Identifier identifier, ItemStack representation) { public static final PacketCodec CODEC = PacketCodec.of(PolymerItemEntry::write, PolymerItemEntry::read); diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/ui/MicroUi.java b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/ui/MicroUi.java index e8a213fe..32f57f0e 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/impl/ui/MicroUi.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/impl/ui/MicroUi.java @@ -86,8 +86,7 @@ public static void playSound(ServerPlayerEntity player, RegistryEntry 256) { + command = new StringBuilder("give @s " + id); + } + if (amount != 1) { + command.append(" ").append(amount); } - command += " " + amount; - client.player.networkHandler.sendChatCommand(command); + client.player.networkHandler.sendChatCommand(command.toString()); cir.setReturnValue(true); } } catch (Throwable e) { diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/entity/EntityAttributesS2CPacketAccessor.java b/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/entity/EntityAttributesS2CPacketAccessor.java new file mode 100644 index 00000000..85ce91b0 --- /dev/null +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/entity/EntityAttributesS2CPacketAccessor.java @@ -0,0 +1,13 @@ +package eu.pb4.polymer.core.mixin.entity; + +import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(EntityAttributesS2CPacket.class) +public interface EntityAttributesS2CPacketAccessor { + @Accessor + List getEntries(); +} diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/entity/EntityAttributesS2CPacketMixin.java b/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/entity/EntityAttributesS2CPacketMixin.java index 5691a26e..ab31d5b1 100644 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/entity/EntityAttributesS2CPacketMixin.java +++ b/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/entity/EntityAttributesS2CPacketMixin.java @@ -1,9 +1,11 @@ package eu.pb4.polymer.core.mixin.entity; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import eu.pb4.polymer.core.api.entity.PolymerEntity; import eu.pb4.polymer.core.api.utils.PolymerUtils; import eu.pb4.polymer.common.impl.entity.InternalEntityHelpers; import eu.pb4.polymer.core.impl.interfaces.EntityAttachedPacket; +import eu.pb4.polymer.core.impl.networking.TransformingPacketCodec; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.entity.Entity; @@ -11,6 +13,9 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.attribute.DefaultAttributeRegistry; +import net.minecraft.entity.attribute.EntityAttributeInstance; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -26,42 +31,23 @@ @Mixin(EntityAttributesS2CPacket.class) public abstract class EntityAttributesS2CPacketMixin { - - // Todo - /*@Shadow @Final private int entityId; - - /** - * If the entity is not living, use an invalid entity ID so the client ignores it. - * No error is printed, packet is just silently ignored. - *//* - @ModifyArg(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketByteBuf;writeVarInt(I)Lnet/minecraft/network/PacketByteBuf;", ordinal = 0)) - private int polymer$replaceWithPolymer(int input) { - if (EntityAttachedPacket.get(this, this.entityId) instanceof PolymerEntity entity && !InternalEntityHelpers.isLivingEntity(entity.getPolymerEntityType(PolymerUtils.getPlayerContext()))) { - return -1; - } - return input; - } - - @SuppressWarnings("unchecked") - @ModifyArg(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketByteBuf;writeCollection(Ljava/util/Collection;Lnet/minecraft/network/PacketByteBuf$PacketWriter;)V", ordinal = 0)) - private Collection polymer$replaceWithPolymer(Collection value) { - if (EntityAttachedPacket.get(this, this.entityId) instanceof PolymerEntity entity) { - var type = entity.getPolymerEntityType(PolymerUtils.getPlayerContext()); - if (!InternalEntityHelpers.isLivingEntity(type)) { - return List.of(); + @SuppressWarnings("UnreachableCode") + @ModifyExpressionValue(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/codec/PacketCodec;tuple(Lnet/minecraft/network/codec/PacketCodec;Ljava/util/function/Function;Lnet/minecraft/network/codec/PacketCodec;Ljava/util/function/Function;Ljava/util/function/BiFunction;)Lnet/minecraft/network/codec/PacketCodec;")) + private static PacketCodec patchCodec(PacketCodec original) { + return TransformingPacketCodec.encodeOnly(original, (buf, packet) -> { + if (EntityAttachedPacket.get(packet, packet.getEntityId()) instanceof PolymerEntity entity) { + var type = entity.getPolymerEntityType(PolymerUtils.getPlayerContext()); + var p = new EntityAttributesS2CPacket(packet.getEntityId(), List.of()); + var list = ((EntityAttributesS2CPacketAccessor) p).getEntries(); + var vanillaContainer = DefaultAttributeRegistry.get((EntityType) type); + for (var entry : packet.getEntries()) { + if (vanillaContainer.has(entry.attribute())) { + list.add(entry); + } + } + return p; } - - DefaultAttributeContainer vanillaContainer = DefaultAttributeRegistry.get((EntityType) type); - List list = new ArrayList<>(); - for (EntityAttributesS2CPacket.Entry entry : value) { - // todo - //if (vanillaContainer.has(entry.getAttribute())) { - list.add(entry); - //} - } - return list; - } - - return value; - }*/ + return packet; + }); + } } diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/item/NbtCompoundFallbackMixin.java b/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/item/NbtCompoundFallbackMixin.java deleted file mode 100644 index 30be8738..00000000 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/item/NbtCompoundFallbackMixin.java +++ /dev/null @@ -1,10 +0,0 @@ -package eu.pb4.polymer.core.mixin.item; - -import eu.pb4.polymer.core.impl.interfaces.TypeAwareNbtCompound; -import net.minecraft.nbt.NbtCompound; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(NbtCompound.class) -public class NbtCompoundFallbackMixin implements TypeAwareNbtCompound { - -} diff --git a/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/item/NbtCompoundMixin.java b/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/item/NbtCompoundMixin.java deleted file mode 100644 index 0f65a04a..00000000 --- a/polymer-core/src/main/java/eu/pb4/polymer/core/mixin/item/NbtCompoundMixin.java +++ /dev/null @@ -1,126 +0,0 @@ -package eu.pb4.polymer.core.mixin.item; - -import com.llamalad7.mixinextras.injector.WrapWithCondition; -import com.llamalad7.mixinextras.sugar.Share; -import com.llamalad7.mixinextras.sugar.ref.LocalRef; -import eu.pb4.polymer.common.api.PolymerCommonUtils; -import eu.pb4.polymer.core.api.block.PolymerBlockUtils; -import eu.pb4.polymer.core.api.item.PolymerItemUtils; -import eu.pb4.polymer.core.impl.interfaces.TypeAwareNbtCompound; -import net.minecraft.block.BlockState; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtHelper; -import net.minecraft.nbt.NbtString; -import net.minecraft.registry.Registries; -import net.minecraft.state.property.Property; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.io.DataOutput; -import java.io.IOException; -import java.util.Collection; - -@Mixin(NbtCompound.class) -public abstract class NbtCompoundMixin implements TypeAwareNbtCompound { - @Shadow - private static void write(String key, NbtElement element, DataOutput output) throws IOException { - } - - @Unique - private NbtString polymerCore$type; - - @Override - public void polymerCore$setType(NbtString value) { - this.polymerCore$type = value; - } - - @Override - public NbtString polymerCore$getType() { - return this.polymerCore$type; - } -// todo - @Inject(method = "write(Ljava/io/DataOutput;)V", at = @At("HEAD")) - private void polymerCore$storePlayerContextedItemStack(DataOutput output, CallbackInfo ci, @Share("polymerCore:stack") LocalRef polymerStack) { - /*if (this.polymerCore$type != null && PolymerCommonUtils.isServerNetworkingThread()) { - var player = PolymerCommonUtils.getPlayerContextNoClient(); - if (this.polymerCore$type == TypeAwareNbtCompound.STACK_TYPE) { - var stack = ItemStack.fromNbt((NbtCompound) (Object) this); - if (player != null && stack != null && !stack.isEmpty()) { - polymerStack.set(PolymerItemUtils.getPolymerItemStack(stack, player)); - } - } else if (this.polymerCore$type == TypeAwareNbtCompound.STATE_TYPE) { - var stack = NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), (NbtCompound) (Object) this); - if (player != null && stack != null && !stack.isAir()) { - polymerStack.set(PolymerBlockUtils.getPolymerBlockState(stack, player)); - } - } - }*/ - } - - @WrapWithCondition( - method = "write(Ljava/io/DataOutput;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NbtCompound;write(Ljava/lang/String;Lnet/minecraft/nbt/NbtElement;Ljava/io/DataOutput;)V") - ) - private boolean polymerCore$ignoreIdAndTag(String key, NbtElement element, DataOutput output, @Share("polymerCore:stack") LocalRef polymerStack) { - if (this.polymerCore$type != null && PolymerCommonUtils.isServerNetworkingThread()) { - var stack = polymerStack.get(); - if (stack != null) { - if (this.polymerCore$type == TypeAwareNbtCompound.STACK_TYPE) { - return !key.equals("id") && !key.equals("tag"); - - } else if (this.polymerCore$type == TypeAwareNbtCompound.STATE_TYPE) { - return !key.equals("Name") && !key.equals("Properties"); - } - } - } - - return true; - } - @Inject(method = "write(Ljava/io/DataOutput;)V", at = @At(value = "INVOKE", target = "Ljava/io/DataOutput;writeByte(I)V", ordinal = 0)) - private void polymerCore$writeNbtIfMissing(DataOutput output, CallbackInfo ci, @Share("polymerCore:stack") LocalRef polymerStack) throws IOException { - /* - if (this.polymerCore$type != null && PolymerCommonUtils.isServerNetworkingThread()) { - write(MARKER_KEY, this.polymerCore$type, output); - if (this.polymerCore$type == TypeAwareNbtCompound.STACK_TYPE) { - var stack = (ItemStack) polymerStack.get(); - if (stack != null) { - write("id", NbtString.of(Registries.ITEM.getId(stack.getItem()).toString()), output); - if (stack.hasNbt()) { - write("tag", stack.getNbt(), output); - } - } - } else if (this.polymerCore$type == TypeAwareNbtCompound.STATE_TYPE) { - var stack = (BlockState) polymerStack.get(); - if (stack != null) { - write("Name", NbtString.of(Registries.BLOCK.getId(stack.getBlock()).toString()), output); - //noinspection unchecked - var props = (Collection) (Object) stack.getBlock().getStateManager().getProperties(); - if (!props.isEmpty()) { - output.writeByte(NbtElement.COMPOUND_TYPE); - output.writeUTF("Properties"); - - for(var prop : props) { - output.writeByte(NbtElement.STRING_TYPE); - output.writeUTF(prop.getName()); - //noinspection unchecked - output.writeUTF(prop.name(stack.get(prop))); - } - output.writeByte(0); - } - } - } - }*/ - } - - @Inject(method = "copy()Lnet/minecraft/nbt/NbtCompound;", at = @At("RETURN")) - private void polymerCore$copyStack(CallbackInfoReturnable cir) { - ((TypeAwareNbtCompound) cir.getReturnValue()).polymerCore$setType(this.polymerCore$type); - } -} diff --git a/polymer-core/src/main/resources/polymer-core.mixins.json b/polymer-core/src/main/resources/polymer-core.mixins.json index 546a288f..c1085e57 100644 --- a/polymer-core/src/main/resources/polymer-core.mixins.json +++ b/polymer-core/src/main/resources/polymer-core.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "eu.pb4.polymer.core.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "plugin": "eu.pb4.polymer.core.mixin.PolymerMixinConfigPlugin", "mixins": [ "block.AbstractBlockMixin", @@ -37,6 +37,7 @@ "entity.DataTrackerAccessor", "entity.EntityAccessor", "entity.EntityAttachedPacketsMixin", + "entity.EntityAttributesS2CPacketAccessor", "entity.EntityAttributesS2CPacketMixin", "entity.EntityPositionS2CPacketMixin", "entity.EntitySetHeadYawS2CPacketMixin", @@ -54,8 +55,6 @@ "item.ItemGroupsMixin", "item.ItemStackMixin", "item.MinecraftServerMixin", - "item.NbtCompoundFallbackMixin", - "item.NbtCompoundMixin", "item.NbtHelperMixin", "item.PlayerManagerMixin", "item.ServerPlayNetworkHandlerMixin", diff --git a/polymer-core/src/testmod/java/eu/pb4/polymertest/ManaCauldron.java b/polymer-core/src/testmod/java/eu/pb4/polymertest/ManaCauldron.java new file mode 100644 index 00000000..a9165cdb --- /dev/null +++ b/polymer-core/src/testmod/java/eu/pb4/polymertest/ManaCauldron.java @@ -0,0 +1,181 @@ +package eu.pb4.polymertest; + +import com.mojang.serialization.MapCodec; +import eu.pb4.polymer.core.api.block.PolymerBlock; +import eu.pb4.polymer.virtualentity.api.BlockWithMovingElementHolder; +import eu.pb4.polymer.virtualentity.api.ElementHolder; +import eu.pb4.polymer.virtualentity.api.attachment.BlockBoundAttachment; +import eu.pb4.polymer.virtualentity.api.elements.BlockDisplayElement; +import net.minecraft.block.*; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.IntProperty; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.Collection; + + +// Bug reported with +// https://github.com/Dev0Louis/Zauber/blob/54fd6f06a9f1c83fdf37641f587da2b27860b98b/src/main/java/dev/louis/zauber/block/ManaCauldron.java +public class ManaCauldron extends Block implements PolymerBlock, BlockWithMovingElementHolder { + public static final MapCodec CODEC = createCodec(ManaCauldron::new); + public static final IntProperty MANA_LEVEL = IntProperty.of("mana_level", 0, 2); + + protected ManaCauldron(Settings settings) { + super(settings); + setDefaultState(getDefaultState().with(MANA_LEVEL, 0)); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(MANA_LEVEL); + } + + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + world.setBlockState(pos, state.cycle(MANA_LEVEL)); + return ActionResult.PASS; + } + + @Override + protected MapCodec getCodec() { + return CODEC; + } + + @Override + public BlockState getPolymerBlockState(BlockState state) { + return Blocks.CAULDRON.getDefaultState(); + } + + @Override + public boolean tickElementHolder(ServerWorld world, BlockPos pos, BlockState initialBlockState) { + return true; + } + + @Override + public @Nullable ElementHolder createElementHolder(ServerWorld world, BlockPos pos, BlockState initialBlockState) { + return new CustomHolder(initialBlockState); + } + + public static class CustomHolder extends ElementHolder { + private static final BlockState EMPTY_STATE = Blocks.AIR.getDefaultState(); + private static final BlockState HALF_FILLED_STATE = Blocks.LIGHT_BLUE_STAINED_GLASS.getDefaultState(); + private static final BlockState FULL_STATE = Blocks.LIGHT_BLUE_STAINED_GLASS.getDefaultState(); + private static final BlockState MANA_BUBBLE_STATE = Blocks.LIGHT_BLUE_STAINED_GLASS.getDefaultState(); + private final BlockDisplayElement manaFill; + private final Collection manaBubbles = new ArrayList<>(); + private final Random random = Random.create(); + private int age; + + public CustomHolder(BlockState initialBlockState) { + this.manaFill = this.addElement(new BlockDisplayElement(this.getState(initialBlockState))); + this.manaFill.setOffset(new Vec3d(-0.375, 0, -0.375)); + this.manaFill.setScale(new Vector3f(0.75f, 0.2f * initialBlockState.get(MANA_LEVEL) + (float)Math.sin(age / 50f) * 0.05f, 0.75f)); + this.manaFill.setGlowing(false); + } + + @Override + public void onTick() { + this.age++; + this.manaFill.setOffset(new Vec3d(-0.375, 0, -0.375)); + var attachment = this.getAttachment(); + if (attachment == null) throw new IllegalStateException("Attachment is null"); + var blockBoundAttachment = ((BlockBoundAttachment)attachment); + var blockPos = blockBoundAttachment.getBlockPos(); + var manaLevel = blockBoundAttachment.getBlockState().get(MANA_LEVEL); + var offset = (float)Math.sin(age / 50f) * 0.05f; + this.manaFill.setScale(new Vector3f(0.75f, 0.2f * manaLevel + offset, 0.75f)); + this.manaFill.setBlockState(this.getState(this.getAttachment().getWorld(), blockPos)); + + var world = attachment.getWorld(); + if (manaLevel > 0) { + if (age % (4 - manaLevel) == 0) { + world.spawnParticles(ParticleTypes.UNDERWATER, blockPos.getX() + 0.5, blockPos.getY() + 0.75 + offset, blockPos.getZ() + 0.5, 10, 0.15, 0.15, 0.15, 1); + } + if (manaBubbles.size() < manaLevel * 10) { + Vec3d velocity = new Vec3d((random.nextFloat() - 0.5) * 0.2, 0.05f * manaLevel, (random.nextFloat() - 0.5) * 0.2); + var blockDisplayEntity = new BlockDisplayElementWithVelocity(MANA_BUBBLE_STATE, velocity); + blockDisplayEntity.setScale(new Vector3f(0.1f)); + this.addElement(blockDisplayEntity); + manaBubbles.add(blockDisplayEntity); + } + } + + manaBubbles.removeIf(element -> { + var remove = element.getOffset().getY() > 3 * manaLevel || random.nextFloat() > 0.93f; + if (remove) { + var pos = this.getAttachment().getPos().add(element.getOffset()); + if (random.nextFloat() > 0.5f) { + + } + world.spawnParticles( + ParticleTypes.BUBBLE_POP, + pos.x, + pos.y, + pos.z, + 1, + 0, + 0, + 0, + 0 + ); + this.removeElement(element); + } + return remove; + }); + + //element.setGlowing(true); + //element.setOffset(element.getOffset().add(element.getVelocity())); + manaBubbles.forEach(BlockDisplayElementWithVelocity::tick); + + } + + public BlockState getState(ServerWorld world, BlockPos pos) { + return this.getState(world.getBlockState(pos)); + } + + public BlockState getState(BlockState state) { + var manaLevel = state.get(MANA_LEVEL); + return switch (manaLevel) { + case 0 -> EMPTY_STATE; + case 1 -> HALF_FILLED_STATE; + case 2 -> FULL_STATE; + default -> throw new IllegalStateException("Unexpected value: " + manaLevel); + }; + } + } + + public static class BlockDisplayElementWithVelocity extends BlockDisplayElement { + private Vec3d velocity; + + public BlockDisplayElementWithVelocity(BlockState state, Vec3d velocity) { + super(state); + this.velocity = velocity; + } + + + @Override + public void tick() { + velocity = velocity.multiply(0.9, 1, 0.9); + this.setOffset(this.getOffset().add(velocity)); + super.tick(); + } + + public Vec3d getVelocity() { + return velocity; + } + } +} \ No newline at end of file diff --git a/polymer-core/src/testmod/java/eu/pb4/polymertest/TestMod.java b/polymer-core/src/testmod/java/eu/pb4/polymertest/TestMod.java index 16c74f17..57bcdbc5 100644 --- a/polymer-core/src/testmod/java/eu/pb4/polymertest/TestMod.java +++ b/polymer-core/src/testmod/java/eu/pb4/polymertest/TestMod.java @@ -13,19 +13,15 @@ import eu.pb4.polymer.core.impl.client.InternalClientRegistry; import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils; import eu.pb4.polymer.virtualentity.api.tracker.EntityTrackedData; -import eu.pb4.polymertest.mixin.EntityAccessor; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; -import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; import net.fabricmc.fabric.api.object.builder.v1.trade.TradeOfferHelper; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.*; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; import net.minecraft.component.type.FoodComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.*; @@ -126,6 +122,10 @@ public void accept(ItemGroup.DisplayContext arg, ItemGroup.Entries entries) { public static Block WEAK_GLASS_BLOCK = new WeakGlassBlock(AbstractBlock.Settings.copy(Blocks.GLASS)); public static Item WEAK_GLASS_BLOCK_ITEM = new PolymerBlockItem(WEAK_GLASS_BLOCK, new Item.Settings(), Items.GLASS); + public static Block MANA_CAULDRON = new ManaCauldron(AbstractBlock.Settings.copy(Blocks.CAULDRON)); + public static Item MANA_CAULDRON_ITEM = new PolymerBlockItem(MANA_CAULDRON, new Item.Settings(), Items.CAULDRON); + + public static TestBowItem BOW_1 = new TestBowItem(new Item.Settings(), "bow"); public static TestBowItem BOW_2 = new TestBowItem(new Item.Settings(), "bow2"); @@ -311,6 +311,9 @@ public void onInitialize() { register(Registries.ITEM, new Identifier("test", "animated"), ANIMATED_BLOCK_ITEM); register(Registries.BLOCK, new Identifier("test", "animated"), ANIMATED_BLOCK); + register(Registries.ITEM, new Identifier("test", "mana_cauldron"), MANA_CAULDRON_ITEM); + register(Registries.BLOCK, new Identifier("test", "mana_cauldron"), MANA_CAULDRON); + for (var i = 0; i < 16; i++) { register(Registries.BLOCK, new Identifier("test", "filler_" + i), new TestBlock(AbstractBlock.Settings.create())); } diff --git a/polymer-networking/src/main/resources/polymer-networking.mixins.json b/polymer-networking/src/main/resources/polymer-networking.mixins.json index 043dbb4e..abfdc735 100644 --- a/polymer-networking/src/main/resources/polymer-networking.mixins.json +++ b/polymer-networking/src/main/resources/polymer-networking.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "eu.pb4.polymer.networking.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "ClientConnectionAccessor", "ClientConnectionMixin", diff --git a/polymer-reg-sync-manipulator/src/main/resources/polymer-rsm.mixins.json b/polymer-reg-sync-manipulator/src/main/resources/polymer-rsm.mixins.json index 0a3684b5..71da5fda 100644 --- a/polymer-reg-sync-manipulator/src/main/resources/polymer-rsm.mixins.json +++ b/polymer-reg-sync-manipulator/src/main/resources/polymer-rsm.mixins.json @@ -3,7 +3,7 @@ "minVersion": "0.8", "package": "eu.pb4.polymer.rsm.mixin", "plugin": "eu.pb4.polymer.rsm.mixin.PolymerMixinConfigPlugin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "SimpleRegistryMixin", "fabric.fabricSync_RegistrySyncManagerMixin", diff --git a/polymer-resource-pack/src/main/resources/polymer-resource-pack.mixins.json b/polymer-resource-pack/src/main/resources/polymer-resource-pack.mixins.json index 730d60b2..40198435 100644 --- a/polymer-resource-pack/src/main/resources/polymer-resource-pack.mixins.json +++ b/polymer-resource-pack/src/main/resources/polymer-resource-pack.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "eu.pb4.polymer.resourcepack.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "plugin": "eu.pb4.polymer.resourcepack.mixin.PolymerResourcePackMixinConfigPlugin", "mixins": [ "compat.polymc.polymc_ArmorColorManagerMixin", diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java index 8a9f173c..4ce83219 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/ElementHolder.java @@ -197,7 +197,7 @@ protected void notifyElementsOfPositionUpdate(Vec3d newPos, Vec3d delta) { } } - public void sendPacket(Packet packet) { + public void sendPacket(Packet packet) { for (var player : players) { player.sendPacket(packet); } diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java index c92855e3..e7b70c47 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/VirtualEntityUtils.java @@ -77,27 +77,27 @@ public static PlaySoundFromEntityS2CPacket createPlaySoundFromEntityPacket(int e @Nullable public static Packet createMovePacket(int id, Vec3d oldPos, Vec3d newPos, boolean rotate, float yaw, float pitch) { - var i = MathHelper.floor(yaw * 256.0F / 360.0F); - var j = MathHelper.floor(pitch * 256.0F / 360.0F); - boolean bl2 = oldPos.subtract(newPos).lengthSquared() >= 7.62939453125E-6D; - long l = Math.round(newPos.x * 4096.0D); - long m = Math.round(newPos.y * 4096.0D); - long n = Math.round(newPos.z * 4096.0D); - boolean bl5 = l < -32768L || l > 32767L || m < -32768L || m > 32767L || n < -32768L || n > 32767L; + var byteYaw = MathHelper.floor(yaw * 256.0F / 360.0F); + var bytePitch = MathHelper.floor(pitch * 256.0F / 360.0F); + boolean areDifferentEnough = oldPos.subtract(newPos).lengthSquared() >= 7.62939453125E-6D; + long newX = Math.round((newPos.x - oldPos.x) * 4096.0D); + long newY = Math.round((newPos.y - oldPos.y) * 4096.0D); + long newZ = Math.round((newPos.z - oldPos.z) * 4096.0D); + boolean bl5 = newX < -32768L || newX > 32767L || newY < -32768L || newY > 32767L || newZ < -32768L || newZ > 32767L; if (!bl5) { - if ((!bl2 || !rotate)) { - if (bl2) { - return new EntityS2CPacket.MoveRelative(id, (short) ((int) l), (short) ((int) m), (short) ((int) n), false); + if ((!areDifferentEnough || !rotate)) { + if (areDifferentEnough) { + return new EntityS2CPacket.MoveRelative(id, (short) ((int) newX), (short) ((int) newY), (short) ((int) newZ), false); } else if (rotate) { - return new EntityS2CPacket.Rotate(id, (byte) i, (byte) j, false); + return new EntityS2CPacket.Rotate(id, (byte) byteYaw, (byte) bytePitch, false); } } else { - return new EntityS2CPacket.RotateAndMoveRelative(id, (short) ((int) l), (short) ((int) m), (short) ((int) n), (byte) i, (byte) j, false); + return new EntityS2CPacket.RotateAndMoveRelative(id, (short) ((int) newX), (short) ((int) newY), (short) ((int) newZ), (byte) byteYaw, (byte) bytePitch, false); } return null; } else { - return createSimpleMovePacket(id, newPos, (byte) i, (byte) j); + return createSimpleMovePacket(id, newPos, (byte) byteYaw, (byte) bytePitch); } } diff --git a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/elements/GenericEntityElement.java b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/elements/GenericEntityElement.java index 2d401b9d..a26b27f6 100644 --- a/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/elements/GenericEntityElement.java +++ b/polymer-virtual-entity/src/main/java/eu/pb4/polymer/virtualentity/api/elements/GenericEntityElement.java @@ -31,6 +31,7 @@ public abstract class GenericEntityElement extends AbstractElement { private final UUID uuid = UUID.randomUUID(); private float pitch; private float yaw; + private Vec3d lastSyncedPos; private boolean isRotationDirty; private boolean sendPositionUpdates = true; @@ -97,10 +98,7 @@ public final int getEntityId() { public void setOffset(Vec3d offset) { super.setOffset(offset); if (this.sendPositionUpdates && this.getHolder() != null) { - var x = VirtualEntityUtils.createMovePacket(this.id, this.getHolder().getPos().add(this.getOffset()), this.getHolder().getPos().add(offset), false, 0f, 0f); - if (x != null) { - this.getHolder().sendPacket(x); - } + this.sendPositionUpdates(); } } @@ -114,8 +112,10 @@ public void startWatching(ServerPlayerEntity player, Consumer createSpawnPacket(ServerPlayerEntity player) { - var pos = this.getHolder().getPos().add(this.getOffset()); - return new EntitySpawnS2CPacket(this.id, this.uuid, pos.x, pos.y, pos.z, this.pitch, this.yaw, this.getEntityType(), 0, Vec3d.ZERO, this.yaw); + if (this.lastSyncedPos == null) { + this.lastSyncedPos = this.getHolder().getPos().add(this.getOffset()); + } + return new EntitySpawnS2CPacket(this.id, this.uuid, this.lastSyncedPos.x, this.lastSyncedPos.y, this.lastSyncedPos.z, this.pitch, this.yaw, this.getEntityType(), 0, Vec3d.ZERO, this.yaw); } protected void sendChangedTrackerEntries(ServerPlayerEntity player, Consumer> packetConsumer) { @@ -129,11 +129,7 @@ protected void sendChangedTrackerEntries(ServerPlayerEntity player, Consumer packet = null; + var pos = this.getHolder().getPos().add(this.getOffset()); + + if (pos.equals(this.lastSyncedPos)) { + return; + } + + if (this.lastSyncedPos == null) { + var i = MathHelper.floor(yaw * 256.0F / 360.0F); + var j = MathHelper.floor(pitch * 256.0F / 360.0F); + packet = VirtualEntityUtils.createSimpleMovePacket(this.id, pos, (byte) i, (byte) j); + } else { + packet = VirtualEntityUtils.createMovePacket(this.id, this.lastSyncedPos, pos, this.isRotationDirty, this.yaw, this.pitch); + } + + if (packet != null) { + this.getHolder().sendPacket(packet); + if (!(packet instanceof EntityS2CPacket.Rotate)) { + this.lastSyncedPos = pos; + } + } + this.isRotationDirty = false; + } + protected void sendTrackerUpdates() { if (this.dataTracker.isDirty()) { var dirty = this.dataTracker.getDirtyEntries(); diff --git a/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json b/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json index b7e23da9..617d1811 100644 --- a/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json +++ b/polymer-virtual-entity/src/main/resources/polymer-virtual-entity.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "eu.pb4.polymer.virtualentity.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "plugin": "eu.pb4.polymer.virtualentity.mixin.PolymerVirtualEntityMixinConfigPlugin", "mixins": [ "ChunkDataSenderMixin",