From a70931e051ae7abbf467bca24a4c7c8c2dce5334 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 3 May 2025 16:55:58 +0800 Subject: [PATCH 01/18] =?UTF-8?q?feat(entity):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=B8=89=E5=8F=89=E6=88=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/ThrowableItemProjectileData.java | 12 ++++ .../plugin/command/feature/TestCommand.java | 35 ++++++++++- .../plugin/network/BukkitNetworkManager.java | 3 +- .../plugin/network/PacketConsumers.java | 51 +++++++++++++++- .../plugin/user/BukkitServerPlayer.java | 6 ++ .../craftengine/bukkit/util/Reflections.java | 59 ++++++++++++++++++- .../core/plugin/network/NetWorkUser.java | 2 + 7 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ThrowableItemProjectileData.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ThrowableItemProjectileData.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ThrowableItemProjectileData.java new file mode 100644 index 000000000..6e40923dc --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ThrowableItemProjectileData.java @@ -0,0 +1,12 @@ +package net.momirealms.craftengine.bukkit.entity.data; + +import net.momirealms.craftengine.bukkit.util.Reflections; + +public class ThrowableItemProjectileData extends BaseEntityData { + public static final ThrowableItemProjectileData ItemStack = new ThrowableItemProjectileData<>(8, EntityDataValue.Serializers$ITEM_STACK, Reflections.instance$ItemStack$Air); + + + public ThrowableItemProjectileData(int id, Object serializer, T defaultValue) { + super(id, serializer, defaultValue); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 5e1ae7447..5c8102617 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -1,13 +1,25 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; -import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; -import net.momirealms.craftengine.core.util.Key; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; +import org.checkerframework.checker.nullness.qual.NonNull; import org.incendo.cloud.Command; +import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.context.CommandInput; +import org.incendo.cloud.parser.standard.IntegerParser; +import org.incendo.cloud.suggestion.Suggestion; +import org.incendo.cloud.suggestion.SuggestionProvider; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; public class TestCommand extends BukkitCommandFeature { @@ -19,9 +31,26 @@ public class TestCommand extends BukkitCommandFeature { public Command.Builder assembleCommand(org.incendo.cloud.CommandManager manager, Command.Builder builder) { return builder .senderType(Player.class) + .required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() { + @Override + public @NonNull CompletableFuture> suggestionsFuture(@NonNull CommandContext context, @NonNull CommandInput input) { + return CompletableFuture.completedFuture(plugin().itemManager().cachedSuggestions()); + } + })) + .required("interpolationDelay", IntegerParser.integerParser()) + .required("transformationInterpolationDuration", IntegerParser.integerParser()) + .required("positionRotationInterpolationDuration", IntegerParser.integerParser()) .handler(context -> { Player player = context.sender(); - player.getInventory().addItem(BukkitItemManager.instance().createWrappedItem(Key.from("default:topaz"), null).getItem()); + NamespacedKey namespacedKey = context.get("id"); + var item = ItemStack.of(Material.TRIDENT); + item.editPersistentDataContainer(container -> { + container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")), PersistentDataType.STRING, namespacedKey.asString()); + container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")), PersistentDataType.INTEGER, context.get("interpolationDelay")); + container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")), PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); + container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")), PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); + }); + player.getInventory().addItem(item); }); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index d485c0da4..fdeae8450 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -152,6 +152,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(PacketConsumers.LOGIN_ACKNOWLEDGED, Reflections.clazz$ServerboundLoginAcknowledgedPacket); registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, Reflections.clazz$ServerboundResourcePackPacket); registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, Reflections.clazz$ClientboundEntityEventPacket); + registerNMSPacketConsumer(PacketConsumers.SET_ENTITY_DATA, Reflections.clazz$ClientboundSetEntityDataPacket); registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket()); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); @@ -170,7 +171,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket()); registerByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket()); registerByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket()); - registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket()); + registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA_BYTEBUFFER, this.packetIds.clientboundSetEntityDataPacket()); } public static BukkitNetworkManager instance() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 0b9b202fa..fd9d35cb3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.plugin.network; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.papermc.paper.persistence.PersistentDataContainerView; import it.unimi.dsi.fastutil.ints.IntList; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TranslationArgument; @@ -9,8 +10,10 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent; import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; +import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.pack.BukkitPackManager; @@ -48,8 +51,10 @@ import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; +import org.bukkit.entity.Trident; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; @@ -1590,6 +1595,32 @@ public class PacketConsumers { if (furniture != null) { event.setCancelled(true); } + } else if (entityType == Reflections.instance$EntityType$TRIDENT) { + int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); + Player player = (Player) user.platformPlayer(); + Trident trident = (Trident) FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId); + PersistentDataContainerView container = trident.getItemStack().getPersistentDataContainer(); + if (container == null) return; + String customTrident = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")), PersistentDataType.STRING); + int interpolationDelay = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")), PersistentDataType.INTEGER); + int transformationInterpolationDuration = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")), PersistentDataType.INTEGER); + int positionRotationInterpolationDuration = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")), PersistentDataType.INTEGER); + if (customTrident == null) return; + Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); + List itemDisplayValues = new ArrayList<>(); + Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); + ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(interpolationDelay, itemDisplayValues); + if (VersionHelper.isOrAbove1_20_2()) { + ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); + ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(positionRotationInterpolationDuration, itemDisplayValues); + } else { + ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); + } + ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues); + user.tridentView().put(entityId, itemDisplayValues); + event.addDelayedTask(() -> { + user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); + }); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundAddEntityPacket", e); @@ -1600,6 +1631,12 @@ public class PacketConsumers { public static final TriConsumer SYNC_ENTITY_POSITION = (user, event, packet) -> { try { int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet); + // if (user.tridentView().contains(entityId)) { + // if (!VersionHelper.isOrAbove1_21_3()) return; + // Object values = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); + // user.sendPacket(Reflections.constructor$ClientboundTeleportEntityPacket.newInstance(entityId, values, Set.of(), false), true); + // Bukkit.getOnlinePlayers().forEach(player -> player.sendMessage("Sync entity position: " + values)); + // } if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { event.setCancelled(true); } @@ -1628,6 +1665,7 @@ public class PacketConsumers { int entityId = intList.getInt(i); user.entityView().remove(entityId); List entities = user.furnitureView().remove(entityId); + user.tridentView().remove(entityId); if (entities == null) continue; for (int subEntityId : entities) { isChange = true; @@ -1979,7 +2017,7 @@ public class PacketConsumers { }; @SuppressWarnings("unchecked") - public static final BiConsumer SET_ENTITY_DATA = (user, event) -> { + public static final BiConsumer SET_ENTITY_DATA_BYTEBUFFER = (user, event) -> { try { FriendlyByteBuf buf = event.getBuffer(); int id = buf.readVarInt(); @@ -2301,4 +2339,15 @@ public class PacketConsumers { CraftEngine.instance().logger().warn("Failed to handle ClientboundEntityEventPacket", e); } }; + + public static final TriConsumer SET_ENTITY_DATA = (user, event, packet) -> { + try { + int entityId = Reflections.field$clazz$ClientboundSetEntityDataPacket$id.getInt(packet); + if (user.tridentView().containsKey(entityId)) { + event.replacePacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, user.tridentView().get(entityId))); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); + } + }; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 13341b5b2..4727bc075 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -90,6 +90,7 @@ public class BukkitServerPlayer extends Player { // for better fake furniture visual sync private final Map> furnitureView = new ConcurrentHashMap<>(); private final Map entityTypeView = new ConcurrentHashMap<>(); + private final Map> tridentView = new ConcurrentHashMap<>(); public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) { this.channel = channel; @@ -723,6 +724,11 @@ public class BukkitServerPlayer extends Player { return this.entityTypeView; } + @Override + public Map> tridentView() { + return this.tridentView; + } + public void setResendSound() { resentSoundTick = gameTicks(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 85165e2e5..eba11c579 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -558,7 +558,6 @@ public class Reflections { ) ); - @Deprecated public static final Field field$ClientboundAddEntityPacket$type = requireNonNull( ReflectionUtils.getDeclaredField( clazz$ClientboundAddEntityPacket, clazz$EntityType, 0 @@ -3811,6 +3810,8 @@ public class Reflections { public static final Object instance$EntityType$INTERACTION; public static final Object instance$EntityType$SHULKER; public static final Object instance$EntityType$OAK_BOAT; + public static final Object instance$EntityType$TRIDENT; + public static final Object instance$EntityType$SNOWBALL; static { try { @@ -3830,6 +3831,10 @@ public class Reflections { instance$EntityType$ARMOR_STAND = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, armorStand); Object oakBoat = VersionHelper.isOrAbove1_21_2() ? FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "oak_boat") : FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "boat"); instance$EntityType$OAK_BOAT = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, oakBoat); + Object trident = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "trident"); + instance$EntityType$TRIDENT = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, trident); + Object snowball = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "snowball"); + instance$EntityType$SNOWBALL = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, snowball); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -6615,4 +6620,56 @@ public class Reflections { BukkitReflectionUtils.assembleCBClass("block.CraftBlockStates$BlockEntityStateFactory") ) ); + + public static final Field field$clazz$ClientboundSetEntityDataPacket$id = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundSetEntityDataPacket, int.class, 0 + ) + ); + + // public static final Class clazz$PositionMoveRotation = + // ReflectionUtils.getClazz( + // BukkitReflectionUtils.assembleMCClass("world.entity.PositionMoveRotation") + // ); + // + // public static final Field field$ClientboundEntityPositionSyncPacket$values = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) + // .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$PositionMoveRotation, 0)) + // .orElse(null); + // + // public static final Class clazz$ClientboundTeleportEntityPacket = requireNonNull( + // BukkitReflectionUtils.findReobfOrMojmapClass( + // "network.protocol.game.PacketPlayOutEntityTeleport", + // "network.protocol.game.ClientboundTeleportEntityPacket" + // ) + // ); + // + // /** + // * 实体移动数据包 + // * + // *

1.20 ~ 1.21.1 版本传入参数:

+ // *
    + // *
  • {@code FriendlyByteBuf} 需要按顺序写入: + // *
      + // *
    • {@code id} - VarInt 实体ID
    • + // *
    • {@code x} - Double X坐标
    • + // *
    • {@code y} - Double Y坐标
    • + // *
    • {@code z} - Double Z坐标
    • + // *
    • {@code yRot} - Byte 垂直旋转角度
    • + // *
    • {@code xRot} - Byte 水平旋转角度
    • + // *
    • {@code onGround} - Boolean 着地状态
    • + // *
    + // *
  • + // *
+ // * + // *

1.21.2+ 版本传入参数:

+ // *
    + // *
  • {@code id} - int 实体ID
  • + // *
  • {@code PositionMoveRotation change} - 位置和移动向量和旋转
  • + // *
  • {@code Set relatives} - 相对坐标标记集合
  • + // *
  • {@code onGround} - boolean 着地状态
  • + // *
+ // */ + // public static final Constructor constructor$ClientboundTeleportEntityPacket = requireNonNull( + // ReflectionUtils.getConstructor(clazz$ClientboundTeleportEntityPacket, VersionHelper.isOrAbove1_21_2() ? 0 : 1) + // ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java index a88dd7c6a..b1952a648 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java @@ -46,6 +46,8 @@ public interface NetWorkUser { Map entityView(); + Map> tridentView(); + boolean clientModEnabled(); void setClientModState(boolean enable); From 340c819f4b87340786a8be348e09a7d9a8703d17 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 3 May 2025 17:02:15 +0800 Subject: [PATCH 02/18] =?UTF-8?q?feat(entity):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=B8=89=E5=8F=89=E6=88=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/plugin/network/PacketConsumers.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index fd9d35cb3..054db860c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -1600,12 +1600,18 @@ public class PacketConsumers { Player player = (Player) user.platformPlayer(); Trident trident = (Trident) FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId); PersistentDataContainerView container = trident.getItemStack().getPersistentDataContainer(); - if (container == null) return; - String customTrident = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")), PersistentDataType.STRING); - int interpolationDelay = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")), PersistentDataType.INTEGER); - int transformationInterpolationDuration = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")), PersistentDataType.INTEGER); - int positionRotationInterpolationDuration = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")), PersistentDataType.INTEGER); + NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); + NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); + NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); + NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); + String customTrident = container.get(customTridentKey, PersistentDataType.STRING); + Integer interpolationDelay = container.get(interpolationDelayKey, PersistentDataType.INTEGER); + Integer transformationInterpolationDuration = container.get(transformationInterpolationDurationaKey, PersistentDataType.INTEGER); + Integer positionRotationInterpolationDuration = container.get(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER); if (customTrident == null) return; + if (interpolationDelay == null) return; + if (transformationInterpolationDuration == null) return; + if (positionRotationInterpolationDuration == null) return; Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); List itemDisplayValues = new ArrayList<>(); Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); From 5f1e1173115c7f42ffbd8daf0b0fe53e0fb2332e Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 3 May 2025 17:12:52 +0800 Subject: [PATCH 03/18] =?UTF-8?q?feat(entity):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=B8=89=E5=8F=89=E6=88=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/command/feature/TestCommand.java | 16 ++++++++++++---- .../bukkit/plugin/network/PacketConsumers.java | 6 +++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 5c8102617..181124096 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -14,6 +14,7 @@ import org.incendo.cloud.Command; import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.context.CommandInput; +import org.incendo.cloud.parser.standard.ByteParser; import org.incendo.cloud.parser.standard.IntegerParser; import org.incendo.cloud.suggestion.Suggestion; import org.incendo.cloud.suggestion.SuggestionProvider; @@ -40,15 +41,22 @@ public class TestCommand extends BukkitCommandFeature { .required("interpolationDelay", IntegerParser.integerParser()) .required("transformationInterpolationDuration", IntegerParser.integerParser()) .required("positionRotationInterpolationDuration", IntegerParser.integerParser()) + .required("displayType", ByteParser.byteParser()) .handler(context -> { Player player = context.sender(); NamespacedKey namespacedKey = context.get("id"); var item = ItemStack.of(Material.TRIDENT); + NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); + NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); + NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); + NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); + NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); item.editPersistentDataContainer(container -> { - container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")), PersistentDataType.STRING, namespacedKey.asString()); - container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")), PersistentDataType.INTEGER, context.get("interpolationDelay")); - container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")), PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); - container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")), PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); + container.set(customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); + container.set(interpolationDelayKey, PersistentDataType.INTEGER, context.get("interpolationDelay")); + container.set(transformationInterpolationDurationaKey, PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); + container.set(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); + container.set(displayTypeKey, PersistentDataType.BYTE, context.get("displayType")); }); player.getInventory().addItem(item); }); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 054db860c..5ca00aadd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -1604,14 +1604,13 @@ public class PacketConsumers { NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); + NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); String customTrident = container.get(customTridentKey, PersistentDataType.STRING); Integer interpolationDelay = container.get(interpolationDelayKey, PersistentDataType.INTEGER); Integer transformationInterpolationDuration = container.get(transformationInterpolationDurationaKey, PersistentDataType.INTEGER); Integer positionRotationInterpolationDuration = container.get(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER); + Byte displayType = container.get(displayTypeKey, PersistentDataType.BYTE); if (customTrident == null) return; - if (interpolationDelay == null) return; - if (transformationInterpolationDuration == null) return; - if (positionRotationInterpolationDuration == null) return; Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); List itemDisplayValues = new ArrayList<>(); Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); @@ -1623,6 +1622,7 @@ public class PacketConsumers { ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); } ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues); + ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(displayType, itemDisplayValues); user.tridentView().put(entityId, itemDisplayValues); event.addDelayedTask(() -> { user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); From 7b2b56e836a7758f3ab53113b7d7392fb49390ca Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 4 May 2025 17:09:28 +0800 Subject: [PATCH 04/18] =?UTF-8?q?fix(network):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BD=BF=E7=94=A8via=E8=BF=9B=E6=9C=8D=E6=96=B9=E5=9D=97?= =?UTF-8?q?=E9=80=89=E5=8F=96=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/network/PacketConsumers.java | 15 +++++----- .../craftengine/bukkit/util/Reflections.java | 30 +++++++++---------- gradle.properties | 2 +- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 16d0cfa9f..0b2159d8f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -36,6 +36,7 @@ import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.network.ConnectionState; import net.momirealms.craftengine.core.plugin.network.NetWorkUser; import net.momirealms.craftengine.core.plugin.network.NetworkManager; +import net.momirealms.craftengine.core.plugin.network.ProtocolVersion; import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.BlockHitResult; import net.momirealms.craftengine.core.world.BlockPos; @@ -1344,7 +1345,7 @@ public class PacketConsumers { // When the hotbar is full, the latest creative mode inventory can only be accessed when the player opens the inventory screen. Currently, it is not worth further handling this issue. public static final TriConsumer SET_CREATIVE_SLOT = (user, event, packet) -> { try { - if (VersionHelper.isOrAbove1_21_4()) return; + if (ProtocolVersionUtils.isVersionNewerThan(user.protocolVersion(), ProtocolVersion.V1_21_4)) return; if (!user.isOnline()) return; BukkitServerPlayer player = (BukkitServerPlayer) user; if (VersionHelper.isFolia()) { @@ -1612,6 +1613,7 @@ public class PacketConsumers { Byte displayType = container.get(displayTypeKey, PersistentDataType.BYTE); if (customTrident == null) return; Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); + // System.out.println(packet); List itemDisplayValues = new ArrayList<>(); Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(interpolationDelay, itemDisplayValues); @@ -1637,12 +1639,11 @@ public class PacketConsumers { public static final TriConsumer SYNC_ENTITY_POSITION = (user, event, packet) -> { try { int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet); - // if (user.tridentView().contains(entityId)) { - // if (!VersionHelper.isOrAbove1_21_3()) return; - // Object values = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); - // user.sendPacket(Reflections.constructor$ClientboundTeleportEntityPacket.newInstance(entityId, values, Set.of(), false), true); - // Bukkit.getOnlinePlayers().forEach(player -> player.sendMessage("Sync entity position: " + values)); - // } + if (user.tridentView().containsKey(entityId)) { + if (!VersionHelper.isOrAbove1_21_3()) return; + Object values = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); + // Bukkit.getOnlinePlayers().forEach(player -> player.sendMessage("Sync entity position: " + values)); + } if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { event.setCancelled(true); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index eba11c579..632d6775d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -6627,21 +6627,21 @@ public class Reflections { ) ); - // public static final Class clazz$PositionMoveRotation = - // ReflectionUtils.getClazz( - // BukkitReflectionUtils.assembleMCClass("world.entity.PositionMoveRotation") - // ); - // - // public static final Field field$ClientboundEntityPositionSyncPacket$values = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) - // .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$PositionMoveRotation, 0)) - // .orElse(null); - // - // public static final Class clazz$ClientboundTeleportEntityPacket = requireNonNull( - // BukkitReflectionUtils.findReobfOrMojmapClass( - // "network.protocol.game.PacketPlayOutEntityTeleport", - // "network.protocol.game.ClientboundTeleportEntityPacket" - // ) - // ); + public static final Class clazz$PositionMoveRotation = + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.entity.PositionMoveRotation") + ); + + public static final Field field$ClientboundEntityPositionSyncPacket$values = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) + .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$PositionMoveRotation, 0)) + .orElse(null); + + public static final Class clazz$ClientboundTeleportEntityPacket = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "network.protocol.game.PacketPlayOutEntityTeleport", + "network.protocol.game.ClientboundTeleportEntityPacket" + ) + ); // // /** // * 实体移动数据包 diff --git a/gradle.properties b/gradle.properties index 4783415e2..33dfae1b9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,7 +40,7 @@ geantyref_version=1.3.16 zstd_version=1.5.7-2 commons_io_version=2.18.0 sparrow_nbt_version=0.7.1 -sparrow_util_version=0.39 +sparrow_util_version=0.40 fastutil_version=8.5.15 netty_version=4.1.119.Final joml_version=1.10.8 From 109205b23019952698351f803d4bf40a1d0394c5 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Mon, 5 May 2025 01:14:59 +0800 Subject: [PATCH 05/18] =?UTF-8?q?feat(core):=20=E4=B8=BA=20SelfHostHttpSer?= =?UTF-8?q?ver=20=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89=20URL=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bukkit/loader/src/main/resources/config.yml | 2 ++ .../craftengine/core/pack/host/impl/SelfHost.java | 3 ++- .../craftengine/core/pack/host/impl/SelfHostHttpServer.java | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index da8cf0aa0..c4d0b734f 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -78,6 +78,8 @@ resource-pack: ip: "localhost" port: 8163 protocol: "http" + # The optional URL must be complete and include a trailing slash / at the end. + #url: "http://localhost:8163/" deny-non-minecraft-request: true one-time-token: true rate-limit: diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java index de38d7771..4a8fa9a9b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java @@ -66,6 +66,7 @@ public class SelfHost implements ResourcePackHost { if (port <= 0 || port > 65535) { throw new LocalizedException("warning.config.host.self.invalid_port", String.valueOf(port)); } + String url = arguments.get("url").toString(); boolean oneTimeToken = (boolean) arguments.getOrDefault("one-time-token", true); String protocol = arguments.getOrDefault("protocol", "http").toString(); boolean denyNonMinecraftRequest = (boolean) arguments.getOrDefault("deny-non-minecraft-request", true); @@ -76,7 +77,7 @@ public class SelfHost implements ResourcePackHost { maxRequests = ResourceConfigUtils.getAsInt(rateMap.getOrDefault("max-requests", 5), "max-requests"); resetInterval = ResourceConfigUtils.getAsInt(rateMap.getOrDefault("reset-interval", 20), "reset-interval") * 1000; } - selfHostHttpServer.updateProperties(ip, port, denyNonMinecraftRequest, protocol, maxRequests, resetInterval, oneTimeToken); + selfHostHttpServer.updateProperties(ip, port, url, denyNonMinecraftRequest, protocol, maxRequests, resetInterval, oneTimeToken); return INSTANCE; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHostHttpServer.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHostHttpServer.java index 6ce927583..785a00c6d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHostHttpServer.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHostHttpServer.java @@ -48,6 +48,7 @@ public class SelfHostHttpServer { private String ip = "localhost"; private int port = -1; private String protocol = "http"; + private String url; private boolean denyNonMinecraft = true; private boolean useToken; @@ -57,12 +58,14 @@ public class SelfHostHttpServer { public void updateProperties(String ip, int port, + String url, boolean denyNonMinecraft, String protocol, int maxRequests, int resetInternal, boolean token) { this.ip = ip; + this.url = url; this.denyNonMinecraft = denyNonMinecraft; this.protocol = protocol; this.rateLimit = maxRequests; @@ -112,6 +115,9 @@ public class SelfHostHttpServer { } public String url() { + if (this.url != null && !this.url.isEmpty()) { + return this.url; + } return this.protocol + "://" + this.ip + ":" + this.port + "/"; } From 99e2d5cd36b48efbc1f3a66b7cb84cca1f0d64ef Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Mon, 5 May 2025 09:02:39 +0800 Subject: [PATCH 06/18] =?UTF-8?q?feat(core):=20=E4=B8=80=E4=BA=9B=E5=AF=B9?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=8C=85=E6=89=98=E7=AE=A1=E5=92=8C=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E5=8C=85=E7=94=9F=E6=88=90=E7=9A=84=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bukkit/loader/src/main/resources/translations/en.yml | 4 +++- .../loader/src/main/resources/translations/zh_cn.yml | 4 +++- .../bukkit/plugin/network/PacketConsumers.java | 2 +- .../craftengine/core/pack/AbstractPackManager.java | 6 ++++++ .../craftengine/core/pack/host/impl/SelfHost.java | 8 +++++++- .../core/plugin/network/ProtocolVersion.java | 4 ++++ .../craftengine/core/util/ProtocolVersionUtils.java | 10 ---------- gradle.properties | 2 +- 8 files changed, 25 insertions(+), 15 deletions(-) delete mode 100644 core/src/main/java/net/momirealms/craftengine/core/util/ProtocolVersionUtils.java diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index 6011167dd..eae6aee64 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -272,6 +272,7 @@ warning.config.host.s3.missing_secret: "Issue found in config.yml at 're warning.config.host.s3.missing_upload_path: "Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'upload-path' argument for s3 host." warning.config.host.self.missing_ip: "Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'ip' argument for self host." warning.config.host.self.invalid_port: "Issue found in config.yml at 'resource-pack.delivery.hosting' - Invalid port '' for self host." +warning.config.host.self.invalid_url: "Issue found in config.yml at 'resource-pack.delivery.hosting' - Invalid url '' for self host." warning.config.host.gitlab.missing_url: "Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'gitlab-url' argument for gitlab host." warning.config.host.gitlab.missing_token: "Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'access-token' argument for gitlab host." warning.config.host.gitlab.missing_project: "Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'project-id' argument for gitlab host." @@ -291,4 +292,5 @@ warning.config.conflict_matcher.inverted.missing_term: "Issue found in c warning.config.conflict_matcher.all_of.missing_terms: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'terms' argument for 'all_of' matcher." warning.config.conflict_matcher.any_of.missing_terms: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'terms' argument for 'any_of' matcher." warning.config.conflict_resolution.missing_type: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'type' argument for one of the resolutions." -warning.config.conflict_resolution.invalid_type: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - One of the resolutions is using the invalid type ''." \ No newline at end of file +warning.config.conflict_resolution.invalid_type: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - One of the resolutions is using the invalid type ''." +warning.resource_pack.generation_in_progress: "Resource pack generation is already in progress. Please wait until it finishes." \ No newline at end of file diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index d2dd13dd8..1a1152fc3 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -274,6 +274,7 @@ warning.config.host.s3.missing_secret: "在 config.yml 的 'resource-pac warning.config.host.s3.missing_upload_path: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - S3 托管缺少必需的 'upload-path' 参数" warning.config.host.self.missing_ip: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 自托管托管缺少必需的 'ip' 参数" warning.config.host.self.invalid_port: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 自托管托管的端口 '' 无效" +warning.config.host.self.invalid_url: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 自托管托管的 URL '' 无效" warning.config.host.gitlab.missing_url: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - GitLab 托管缺少必需的 'gitlab-url' 参数" warning.config.host.gitlab.missing_token: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - GitLab 托管缺少必需的 'access-token' 参数" warning.config.host.gitlab.missing_project: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - GitLab 托管缺少必需的 'project-id' 参数" @@ -293,4 +294,5 @@ warning.config.conflict_matcher.inverted.missing_term: "在 config.yml warning.config.conflict_matcher.all_of.missing_terms: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 全匹配器缺少必需的 'terms' 参数" warning.config.conflict_matcher.any_of.missing_terms: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 任一匹配器缺少必需的 'terms' 参数" warning.config.conflict_resolution.missing_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案缺少必需的 'type' 参数" -warning.config.conflict_resolution.invalid_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案使用了无效类型 ''" \ No newline at end of file +warning.config.conflict_resolution.invalid_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案使用了无效类型 ''" +warning.resource_pack.generation_in_progress: "资源包正在生成中, 请等待完成再试" \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 08578f7dc..9858ea30a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -1354,7 +1354,7 @@ public class PacketConsumers { // When the hotbar is full, the latest creative mode inventory can only be accessed when the player opens the inventory screen. Currently, it is not worth further handling this issue. public static final TriConsumer SET_CREATIVE_SLOT = (user, event, packet) -> { try { - if (ProtocolVersionUtils.isVersionNewerThan(user.protocolVersion(), ProtocolVersion.V1_21_4)) return; + if (user.protocolVersion().isVersionNewerThan(ProtocolVersion.V1_21_4)) return; if (!user.isOnline()) return; BukkitServerPlayer player = (BukkitServerPlayer) user; if (VersionHelper.isFolia()) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index ff722cd59..43529efe4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -73,6 +73,7 @@ public abstract class AbstractPackManager implements PackManager { private final TreeMap> cachedConfigs = new TreeMap<>(); protected BiConsumer zipGenerator; protected ResourcePackHost resourcePackHost; + private boolean generateResourcePack = false; public AbstractPackManager(CraftEngine plugin, BiConsumer eventDispatcher) { this.plugin = plugin; @@ -486,6 +487,10 @@ public abstract class AbstractPackManager implements PackManager { @Override public void generateResourcePack() { + if (this.generateResourcePack) { + throw new LocalizedException("warning.resource_pack.generation_in_progress"); + } + this.generateResourcePack = true; this.plugin.logger().info("Generating resource pack..."); long start = System.currentTimeMillis(); // get the target location @@ -547,6 +552,7 @@ public abstract class AbstractPackManager implements PackManager { long end = System.currentTimeMillis(); this.plugin.logger().info("Finished generating resource pack in " + (end - start) + "ms"); this.eventDispatcher.accept(generatedPackPath, zipFile); + this.generateResourcePack = false; } private void generateParticle(Path generatedPackPath) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java index 4a8fa9a9b..acfdd0800 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/SelfHost.java @@ -66,7 +66,13 @@ public class SelfHost implements ResourcePackHost { if (port <= 0 || port > 65535) { throw new LocalizedException("warning.config.host.self.invalid_port", String.valueOf(port)); } - String url = arguments.get("url").toString(); + String url = arguments.getOrDefault("url", "").toString(); + if (!url.isEmpty()) { + if (!url.startsWith("http://") && !url.startsWith("https://")) { + throw new LocalizedException("warning.config.host.self.invalid_url", url); + } + if (!url.endsWith("/")) url += "/"; + } boolean oneTimeToken = (boolean) arguments.getOrDefault("one-time-token", true); String protocol = arguments.getOrDefault("protocol", "http").toString(); boolean denyNonMinecraftRequest = (boolean) arguments.getOrDefault("deny-non-minecraft-request", true); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/ProtocolVersion.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/ProtocolVersion.java index c692c6da6..f9e3c4b05 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/ProtocolVersion.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/ProtocolVersion.java @@ -32,6 +32,10 @@ public enum ProtocolVersion { return name; } + public boolean isVersionNewerThan(ProtocolVersion targetVersion) { + return this.getId() >= targetVersion.getId(); + } + public static ProtocolVersion getByName(String name) { for (ProtocolVersion version : values()) { if (version.getName().equals(name)) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ProtocolVersionUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ProtocolVersionUtils.java deleted file mode 100644 index 8372e1117..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/util/ProtocolVersionUtils.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.momirealms.craftengine.core.util; - -import net.momirealms.craftengine.core.plugin.network.ProtocolVersion; - -public class ProtocolVersionUtils { - - public static boolean isVersionNewerThan(ProtocolVersion version, ProtocolVersion targetVersion) { - return version.getId() >= targetVersion.getId(); - } -} diff --git a/gradle.properties b/gradle.properties index 833e03059..962420ca7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx1G # Rule: [major update].[feature update].[bug fix] project_version=0.0.53-beta.3 config_version=31 -lang_version=10 +lang_version=11 project_group=net.momirealms latest_supported_version=1.21.5 From 82d809ff5abf9e90807a84117efb13d75b495083 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Mon, 5 May 2025 09:25:29 +0800 Subject: [PATCH 07/18] =?UTF-8?q?feat(core):=20=E4=B8=80=E4=BA=9B=E5=AF=B9?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=8C=85=E6=89=98=E7=AE=A1=E5=92=8C=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E5=8C=85=E7=94=9F=E6=88=90=E7=9A=84=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/plugin/command/feature/ReloadCommand.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java index 00056ba91..079dcf240 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ReloadCommand.java @@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; +import net.momirealms.craftengine.core.plugin.locale.LocalizedException; import net.momirealms.craftengine.core.plugin.locale.MessageConstants; import org.bukkit.command.CommandSender; import org.incendo.cloud.Command; @@ -68,7 +69,9 @@ public class ReloadCommand extends BukkitCommandFeature { long time2 = System.currentTimeMillis(); long packTime = time2 - time1; handleFeedback(context, MessageConstants.COMMAND_RELOAD_PACK_SUCCESS, Component.text(packTime)); - + } catch (LocalizedException e) { + handleFeedback(context, MessageConstants.COMMAND_RELOAD_PACK_FAILURE); + plugin().logger().warn(e.getMessage()); } catch (Exception e) { handleFeedback(context, MessageConstants.COMMAND_RELOAD_PACK_FAILURE); plugin().logger().warn("Failed to generate resource pack", e); @@ -89,6 +92,9 @@ public class ReloadCommand extends BukkitCommandFeature { Component.text(reloadResult.syncTime()), Component.text(packTime) ); + } catch (LocalizedException e) { + handleFeedback(context, MessageConstants.COMMAND_RELOAD_ALL_FAILURE); + plugin().logger().warn(e.getMessage()); } finally { RELOAD_PACK_FLAG = false; } From add7fecd34114251b6beb3eac52ba6d6b83b2518 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Mon, 5 May 2025 09:50:40 +0800 Subject: [PATCH 08/18] =?UTF-8?q?fix(core):=20=E4=BF=AE=E5=A4=8D=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E5=8C=85=E7=94=9F=E6=88=90=E9=80=9F=E5=BA=A6=E8=BF=87?= =?UTF-8?q?=E6=85=A2=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/pack/AbstractPackManager.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 43529efe4..448873dca 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -44,6 +44,7 @@ import java.util.*; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.stream.Stream; import static net.momirealms.craftengine.core.util.MiscUtils.castToMap; @@ -142,6 +143,7 @@ public abstract class AbstractPackManager implements PackManager { @Override public void load() { + initFileSystemProvider(); List> list = Config.instance().settings().getMapList("resource-pack.delivery.hosting"); if (list == null || list.isEmpty()) { this.resourcePackHost = NoneHost.INSTANCE; @@ -485,6 +487,36 @@ public abstract class AbstractPackManager implements PackManager { } } + private static void initFileSystemProvider() { + String osName = System.getProperty("os.name").toLowerCase(); + String providerClass = null; + if (osName.contains("win")) { + providerClass = "sun.nio.fs.WindowsFileSystemProvider"; + } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) { + providerClass = "sun.nio.fs.LinuxFileSystemProvider"; + } else if (osName.contains("mac")) { + providerClass = "sun.nio.fs.MacOSXFileSystemProvider"; + } + if (providerClass != null) { + try { + System.setProperty("java.nio.file.spi.DefaultFileSystemProvider", providerClass); + } catch (Exception ignored) {} + } + } + + private static void deleteDirectory(Path folder) throws IOException { + if (!Files.exists(folder)) return; + try (Stream walk = Files.walk(folder)) { + walk.sorted(Comparator.reverseOrder()) + .parallel() + .forEach(path -> { + try { + Files.delete(path); + } catch (IOException ignored) {} + }); + } + } + @Override public void generateResourcePack() { if (this.generateResourcePack) { @@ -499,7 +531,7 @@ public abstract class AbstractPackManager implements PackManager { .resolve("resource_pack"); try { - org.apache.commons.io.FileUtils.deleteDirectory(generatedPackPath.toFile()); + deleteDirectory(generatedPackPath); } catch (IOException e) { this.plugin.logger().severe("Error deleting previous resource pack", e); } From 2ba21c2dce280d4df7f5860b18c2b611618d6a28 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Tue, 6 May 2025 15:47:36 +0800 Subject: [PATCH 09/18] =?UTF-8?q?refactor(core):=20=E6=92=A4=E9=94=80?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bukkit/loader/src/main/resources/translations/en.yml | 3 +-- bukkit/loader/src/main/resources/translations/zh_cn.yml | 3 +-- .../craftengine/core/pack/AbstractPackManager.java | 6 ------ 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index 77375beb6..96cd97723 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -293,5 +293,4 @@ warning.config.conflict_matcher.all_of.missing_terms: "Issue found in co warning.config.conflict_matcher.any_of.missing_terms: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'terms' argument for 'any_of' matcher." warning.config.conflict_resolution.missing_type: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'type' argument for one of the resolutions." warning.config.conflict_resolution.invalid_type: "Issue found in config.yml at 'resource-pack.duplicated-files-handler' - One of the resolutions is using the invalid type ''." -warning.config.function.command.missing_command: "Issue found in file - The config '' is missing the required 'command' argument for 'command' function." -warning.resource_pack.generation_in_progress: "Resource pack generation is already in progress. Please wait until it finishes." \ No newline at end of file +warning.config.function.command.missing_command: "Issue found in file - The config '' is missing the required 'command' argument for 'command' function." \ No newline at end of file diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index 1a1152fc3..f191e0076 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -294,5 +294,4 @@ warning.config.conflict_matcher.inverted.missing_term: "在 config.yml warning.config.conflict_matcher.all_of.missing_terms: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 全匹配器缺少必需的 'terms' 参数" warning.config.conflict_matcher.any_of.missing_terms: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 任一匹配器缺少必需的 'terms' 参数" warning.config.conflict_resolution.missing_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案缺少必需的 'type' 参数" -warning.config.conflict_resolution.invalid_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案使用了无效类型 ''" -warning.resource_pack.generation_in_progress: "资源包正在生成中, 请等待完成再试" \ No newline at end of file +warning.config.conflict_resolution.invalid_type: "在 config.yml 的 'resource-pack.duplicated-files-handler' 处发现问题 - 文件冲突处理器的某个解决方案使用了无效类型 ''" \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 448873dca..b582cb7d9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -74,7 +74,6 @@ public abstract class AbstractPackManager implements PackManager { private final TreeMap> cachedConfigs = new TreeMap<>(); protected BiConsumer zipGenerator; protected ResourcePackHost resourcePackHost; - private boolean generateResourcePack = false; public AbstractPackManager(CraftEngine plugin, BiConsumer eventDispatcher) { this.plugin = plugin; @@ -519,10 +518,6 @@ public abstract class AbstractPackManager implements PackManager { @Override public void generateResourcePack() { - if (this.generateResourcePack) { - throw new LocalizedException("warning.resource_pack.generation_in_progress"); - } - this.generateResourcePack = true; this.plugin.logger().info("Generating resource pack..."); long start = System.currentTimeMillis(); // get the target location @@ -584,7 +579,6 @@ public abstract class AbstractPackManager implements PackManager { long end = System.currentTimeMillis(); this.plugin.logger().info("Finished generating resource pack in " + (end - start) + "ms"); this.eventDispatcher.accept(generatedPackPath, zipFile); - this.generateResourcePack = false; } private void generateParticle(Path generatedPackPath) { From 33f96267b39fc73ac91119a1464b841210bb066b Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Thu, 8 May 2025 06:21:06 +0800 Subject: [PATCH 10/18] =?UTF-8?q?feat(bukkit):=20=E8=BF=9B=E4=B8=80?= =?UTF-8?q?=E6=AD=A5=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 1.20 ~ 1.21.1 可以正常移动 1.21.2+ 需要补包 - 附魔的三叉戟和世界上有的三叉戟玩家离开再回来无法显示 --- .../plugin/command/feature/TestCommand.java | 39 ++++++++--- .../plugin/network/BukkitNetworkManager.java | 1 + .../plugin/network/PacketConsumers.java | 68 +++++++++++++++---- .../craftengine/bukkit/util/Reflections.java | 54 ++++++++++++++- .../craftengine/core/util/MCUtils.java | 13 ++++ 5 files changed, 150 insertions(+), 25 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 181124096..a934709aa 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -1,8 +1,11 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; +import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; +import net.momirealms.craftengine.core.util.Key; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; @@ -14,12 +17,12 @@ import org.incendo.cloud.Command; import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.context.CommandInput; -import org.incendo.cloud.parser.standard.ByteParser; import org.incendo.cloud.parser.standard.IntegerParser; import org.incendo.cloud.suggestion.Suggestion; import org.incendo.cloud.suggestion.SuggestionProvider; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.CompletableFuture; public class TestCommand extends BukkitCommandFeature { @@ -29,6 +32,7 @@ public class TestCommand extends BukkitCommandFeature { } @Override + @SuppressWarnings("deprecation") public Command.Builder assembleCommand(org.incendo.cloud.CommandManager manager, Command.Builder builder) { return builder .senderType(Player.class) @@ -41,22 +45,37 @@ public class TestCommand extends BukkitCommandFeature { .required("interpolationDelay", IntegerParser.integerParser()) .required("transformationInterpolationDuration", IntegerParser.integerParser()) .required("positionRotationInterpolationDuration", IntegerParser.integerParser()) - .required("displayType", ByteParser.byteParser()) + // .required("displayType", ByteParser.byteParser()) + // .required("x", FloatParser.floatParser()) + // .required("y", FloatParser.floatParser()) + // .required("z", FloatParser.floatParser()) + // .required("w", FloatParser.floatParser()) .handler(context -> { Player player = context.sender(); NamespacedKey namespacedKey = context.get("id"); - var item = ItemStack.of(Material.TRIDENT); + ItemStack item = new ItemStack(Material.TRIDENT); NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); - NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); - item.editPersistentDataContainer(container -> { - container.set(customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); - container.set(interpolationDelayKey, PersistentDataType.INTEGER, context.get("interpolationDelay")); - container.set(transformationInterpolationDurationaKey, PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); - container.set(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); - container.set(displayTypeKey, PersistentDataType.BYTE, context.get("displayType")); + // NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); + // NamespacedKey customTridentX = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_x")); + // NamespacedKey customTridentY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_y")); + // NamespacedKey customTridentZ = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_z")); + // NamespacedKey customTridentW = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_w")); + item.editMeta(meta -> { + meta.getPersistentDataContainer().set(customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); + meta.getPersistentDataContainer().set(interpolationDelayKey, PersistentDataType.INTEGER, context.get("interpolationDelay")); + meta.getPersistentDataContainer().set(transformationInterpolationDurationaKey, PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); + meta.getPersistentDataContainer().set(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); + // container.set(displayTypeKey, PersistentDataType.BYTE, context.get("displayType")); + // container.set(customTridentX, PersistentDataType.FLOAT, context.get("x")); + // container.set(customTridentY, PersistentDataType.FLOAT, context.get("y")); + // container.set(customTridentZ, PersistentDataType.FLOAT, context.get("z")); + // container.set(customTridentW, PersistentDataType.FLOAT, context.get("w")); + Item ceItem = BukkitItemManager.instance().createWrappedItem(Key.of(namespacedKey.asString()), null); + Optional customModelData = ceItem.customModelData(); + customModelData.ifPresent(meta::setCustomModelData); }); player.getInventory().addItem(item); }); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index fdeae8450..ffd10dbdb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -153,6 +153,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, Reflections.clazz$ServerboundResourcePackPacket); registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, Reflections.clazz$ClientboundEntityEventPacket); registerNMSPacketConsumer(PacketConsumers.SET_ENTITY_DATA, Reflections.clazz$ClientboundSetEntityDataPacket); + registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY_ALL, Reflections.clazz$ClientboundMoveEntityPacket$PosRot); registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket()); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index a88d663ec..a8e27c484 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -3,7 +3,6 @@ package net.momirealms.craftengine.bukkit.plugin.network; import com.mojang.datafixers.util.Either; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.papermc.paper.persistence.PersistentDataContainerView; import it.unimi.dsi.fastutil.ints.IntList; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TranslationArgument; @@ -56,10 +55,13 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Trident; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; +import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; import org.jetbrains.annotations.Nullable; +import org.joml.Quaternionf; +import org.joml.Vector3f; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; @@ -1616,23 +1618,28 @@ public class PacketConsumers { int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); Player player = (Player) user.platformPlayer(); Trident trident = (Trident) FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId); - PersistentDataContainerView container = trident.getItemStack().getPersistentDataContainer(); + PersistentDataContainer container = trident.getItemStack().getItemMeta().getPersistentDataContainer(); NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); + String customTrident = container.get(customTridentKey, PersistentDataType.STRING); + if (customTrident == null) return; + user.tridentView().put(entityId, List.of()); NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); - NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); - String customTrident = container.get(customTridentKey, PersistentDataType.STRING); Integer interpolationDelay = container.get(interpolationDelayKey, PersistentDataType.INTEGER); Integer transformationInterpolationDuration = container.get(transformationInterpolationDurationaKey, PersistentDataType.INTEGER); Integer positionRotationInterpolationDuration = container.get(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER); - Byte displayType = container.get(displayTypeKey, PersistentDataType.BYTE); - if (customTrident == null) return; + float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$yRot.getByte(packet)); + float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$xRot.getByte(packet)); + player.sendMessage("加载自定义三叉戟实体1: " + packet); Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); - // System.out.println(packet); + Reflections.field$ClientboundAddEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); + Reflections.field$ClientboundAddEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); List itemDisplayValues = new ArrayList<>(); Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(interpolationDelay, itemDisplayValues); + ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(new Vector3f(0, 0, -2), itemDisplayValues); + ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(new Quaternionf(1, 1, 1, 1), itemDisplayValues); if (VersionHelper.isOrAbove1_20_2()) { ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(positionRotationInterpolationDuration, itemDisplayValues); @@ -1640,10 +1647,12 @@ public class PacketConsumers { ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); } ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues); - ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(displayType, itemDisplayValues); + ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue((byte) 0, itemDisplayValues); user.tridentView().put(entityId, itemDisplayValues); + player.sendMessage("加载自定义三叉戟实体2: " + entityId); event.addDelayedTask(() -> { user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); + player.sendMessage("加载自定义三叉戟实体3: " + itemDisplayValues); }); } } catch (Exception e) { @@ -1651,14 +1660,22 @@ public class PacketConsumers { } }; - // 1.21.3+ + // 1.21.2+ public static final TriConsumer SYNC_ENTITY_POSITION = (user, event, packet) -> { try { int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet); if (user.tridentView().containsKey(entityId)) { - if (!VersionHelper.isOrAbove1_21_3()) return; - Object values = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); - // Bukkit.getOnlinePlayers().forEach(player -> player.sendMessage("Sync entity position: " + values)); + Player player = (Player) user.platformPlayer(); + player.sendMessage("同步三叉戟实体位置: " + packet); + Object positionMoveRotation = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); + boolean onGround = Reflections.field$ClientboundEntityPositionSyncPacket$onGround.getBoolean(packet); + Object position = Reflections.field$PositionMoveRotation$position.get(positionMoveRotation); + Object deltaMovement = Reflections.field$PositionMoveRotation$deltaMovement.get(positionMoveRotation); + float yRot = Reflections.field$PositionMoveRotation$yRot.getFloat(positionMoveRotation); + float xRot = Reflections.field$PositionMoveRotation$xRot.getFloat(positionMoveRotation); + Object newPositionMoveRotation = Reflections.constructor$PositionMoveRotation.newInstance(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F)); + event.replacePacket(Reflections.constructor$ClientboundEntityPositionSyncPacket.newInstance(entityId, newPositionMoveRotation, onGround)); + return; } if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { event.setCancelled(true); @@ -1688,7 +1705,11 @@ public class PacketConsumers { int entityId = intList.getInt(i); user.entityView().remove(entityId); List entities = user.furnitureView().remove(entityId); - user.tridentView().remove(entityId); + var removeTrident = user.tridentView().remove(entityId); + if (removeTrident != null && !removeTrident.isEmpty()) { + Player player = (Player) user.platformPlayer(); + player.sendMessage("移除三叉戟实体: " + removeTrident); + } if (entities == null) continue; for (int subEntityId : entities) { isChange = true; @@ -2367,10 +2388,29 @@ public class PacketConsumers { try { int entityId = Reflections.field$clazz$ClientboundSetEntityDataPacket$id.getInt(packet); if (user.tridentView().containsKey(entityId)) { - event.replacePacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, user.tridentView().get(entityId))); + Player player = (Player) user.platformPlayer(); + Object newPacket = FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, user.tridentView().get(entityId)); + player.sendMessage("设置三叉戟实体数据: " + newPacket); + event.replacePacket(newPacket); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); } }; + + public static final TriConsumer MOVE_ENTITY_ALL = (user, event, packet) -> { + try { + int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); + if (user.tridentView().containsKey(entityId)) { + float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$xRot.getByte(packet)); + float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$yRot.getByte(packet)); + Reflections.field$ClientboundMoveEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); + Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); + Player player = (Player) user.platformPlayer(); + player.sendMessage("同步三叉戟实体位置: " + Math.clamp(-xRot, -90.0F, 90.0F) + ", " + -yRot); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket$PosRot", e); + } + }; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 9023eef48..36f6b5a5c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -3984,7 +3984,7 @@ public class Reflections { ) ); - // 1.21.3+ + // 1.21.2+ public static final Class clazz$ClientboundEntityPositionSyncPacket = ReflectionUtils.getClazz( BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundEntityPositionSyncPacket") @@ -6635,16 +6635,68 @@ public class Reflections { BukkitReflectionUtils.assembleMCClass("world.entity.PositionMoveRotation") ); + public static final Constructor constructor$PositionMoveRotation = Optional.ofNullable(clazz$PositionMoveRotation) + .map(it -> ReflectionUtils.getTheOnlyConstructor(it)) + .orElse(null); + public static final Field field$ClientboundEntityPositionSyncPacket$values = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$PositionMoveRotation, 0)) .orElse(null); + public static final Field field$ClientboundEntityPositionSyncPacket$onGround = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) + .map(it -> ReflectionUtils.getInstanceDeclaredField(it, boolean.class, 0)) + .orElse(null); + + public static final Field field$PositionMoveRotation$position = Optional.ofNullable(clazz$PositionMoveRotation) + .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$Vec3, 0)) + .orElse(null); + + public static final Field field$PositionMoveRotation$deltaMovement = Optional.ofNullable(clazz$PositionMoveRotation) + .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$Vec3, 1)) + .orElse(null); + + public static final Field field$PositionMoveRotation$yRot = Optional.ofNullable(clazz$PositionMoveRotation) + .map(it -> ReflectionUtils.getInstanceDeclaredField(it, float.class, 0)) + .orElse(null); + + public static final Field field$PositionMoveRotation$xRot = Optional.ofNullable(clazz$PositionMoveRotation) + .map(it -> ReflectionUtils.getInstanceDeclaredField(it, float.class, 1)) + .orElse(null); + public static final Class clazz$ClientboundTeleportEntityPacket = requireNonNull( BukkitReflectionUtils.findReobfOrMojmapClass( "network.protocol.game.PacketPlayOutEntityTeleport", "network.protocol.game.ClientboundTeleportEntityPacket" ) ); + + public static final Constructor constructor$ClientboundEntityPositionSyncPacket = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) + .map(it -> ReflectionUtils.getTheOnlyConstructor(it)) + .orElse(null); + + public static final Field field$ClientboundAddEntityPacket$xRot = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundAddEntityPacket, byte.class, 0 + ) + ); + + public static final Field field$ClientboundAddEntityPacket$yRot = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundAddEntityPacket, byte.class, 1 + ) + ); + + public static final Field field$ClientboundMoveEntityPacket$xRot = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundMoveEntityPacket, byte.class, 1 + ) + ); + + public static final Field field$ClientboundMoveEntityPacket$yRot = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundMoveEntityPacket, byte.class, 0 + ) + ); // // /** // * 实体移动数据包 diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java index 9669fe006..86f2093ca 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java @@ -184,4 +184,17 @@ public class MCUtils { } return next; } + + public static int floor(float value) { + int i = (int) value; + return value < (float)i ? i - 1 : i; + } + + public static byte packDegrees(float degrees) { + return (byte)floor(degrees * 256.0F / 360.0F); + } + + public static float unpackDegrees(byte degrees) { + return (float)(degrees * 360) / 256.0F; + } } From 5cfb418eb0e0b436272d76f1e9a90506dc7d1b9c Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 02:37:44 +0800 Subject: [PATCH 11/18] =?UTF-8?q?refactor(bukkit):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=B8=89=E5=8F=89=E6=88=9F=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/command/feature/TestCommand.java | 13 +- .../plugin/network/PacketConsumers.java | 76 +---------- .../bukkit/util/CustomTridentUtils.java | 118 ++++++++++++++++++ 3 files changed, 128 insertions(+), 79 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index a934709aa..368aab382 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; +import net.momirealms.craftengine.bukkit.util.CustomTridentUtils; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; @@ -54,20 +55,16 @@ public class TestCommand extends BukkitCommandFeature { Player player = context.sender(); NamespacedKey namespacedKey = context.get("id"); ItemStack item = new ItemStack(Material.TRIDENT); - NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); - NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); - NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); - NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); // NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); // NamespacedKey customTridentX = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_x")); // NamespacedKey customTridentY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_y")); // NamespacedKey customTridentZ = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_z")); // NamespacedKey customTridentW = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_w")); item.editMeta(meta -> { - meta.getPersistentDataContainer().set(customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); - meta.getPersistentDataContainer().set(interpolationDelayKey, PersistentDataType.INTEGER, context.get("interpolationDelay")); - meta.getPersistentDataContainer().set(transformationInterpolationDurationaKey, PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); - meta.getPersistentDataContainer().set(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); + meta.getPersistentDataContainer().set(CustomTridentUtils.customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); + meta.getPersistentDataContainer().set(CustomTridentUtils.interpolationDelayKey, PersistentDataType.INTEGER, context.get("interpolationDelay")); + meta.getPersistentDataContainer().set(CustomTridentUtils.transformationInterpolationDurationaKey, PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); + meta.getPersistentDataContainer().set(CustomTridentUtils.positionRotationInterpolationDurationKey, PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); // container.set(displayTypeKey, PersistentDataType.BYTE, context.get("displayType")); // container.set(customTridentX, PersistentDataType.FLOAT, context.get("x")); // container.set(customTridentY, PersistentDataType.FLOAT, context.get("y")); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index a8e27c484..fc184bf1a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -10,10 +10,8 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent; import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; -import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; -import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.pack.BukkitPackManager; @@ -52,16 +50,11 @@ import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; -import org.bukkit.entity.Trident; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; import org.jetbrains.annotations.Nullable; -import org.joml.Quaternionf; -import org.joml.Vector3f; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; @@ -1615,45 +1608,7 @@ public class PacketConsumers { event.setCancelled(true); } } else if (entityType == Reflections.instance$EntityType$TRIDENT) { - int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); - Player player = (Player) user.platformPlayer(); - Trident trident = (Trident) FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId); - PersistentDataContainer container = trident.getItemStack().getItemMeta().getPersistentDataContainer(); - NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); - String customTrident = container.get(customTridentKey, PersistentDataType.STRING); - if (customTrident == null) return; - user.tridentView().put(entityId, List.of()); - NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); - NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); - NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); - Integer interpolationDelay = container.get(interpolationDelayKey, PersistentDataType.INTEGER); - Integer transformationInterpolationDuration = container.get(transformationInterpolationDurationaKey, PersistentDataType.INTEGER); - Integer positionRotationInterpolationDuration = container.get(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER); - float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$yRot.getByte(packet)); - float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$xRot.getByte(packet)); - player.sendMessage("加载自定义三叉戟实体1: " + packet); - Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); - Reflections.field$ClientboundAddEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); - Reflections.field$ClientboundAddEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); - List itemDisplayValues = new ArrayList<>(); - Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); - ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(interpolationDelay, itemDisplayValues); - ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(new Vector3f(0, 0, -2), itemDisplayValues); - ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(new Quaternionf(1, 1, 1, 1), itemDisplayValues); - if (VersionHelper.isOrAbove1_20_2()) { - ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); - ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(positionRotationInterpolationDuration, itemDisplayValues); - } else { - ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); - } - ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues); - ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue((byte) 0, itemDisplayValues); - user.tridentView().put(entityId, itemDisplayValues); - player.sendMessage("加载自定义三叉戟实体2: " + entityId); - event.addDelayedTask(() -> { - user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); - player.sendMessage("加载自定义三叉戟实体3: " + itemDisplayValues); - }); + CustomTridentUtils.handleCustomTrident(user, event, packet); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundAddEntityPacket", e); @@ -1665,16 +1620,7 @@ public class PacketConsumers { try { int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet); if (user.tridentView().containsKey(entityId)) { - Player player = (Player) user.platformPlayer(); - player.sendMessage("同步三叉戟实体位置: " + packet); - Object positionMoveRotation = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); - boolean onGround = Reflections.field$ClientboundEntityPositionSyncPacket$onGround.getBoolean(packet); - Object position = Reflections.field$PositionMoveRotation$position.get(positionMoveRotation); - Object deltaMovement = Reflections.field$PositionMoveRotation$deltaMovement.get(positionMoveRotation); - float yRot = Reflections.field$PositionMoveRotation$yRot.getFloat(positionMoveRotation); - float xRot = Reflections.field$PositionMoveRotation$xRot.getFloat(positionMoveRotation); - Object newPositionMoveRotation = Reflections.constructor$PositionMoveRotation.newInstance(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F)); - event.replacePacket(Reflections.constructor$ClientboundEntityPositionSyncPacket.newInstance(entityId, newPositionMoveRotation, onGround)); + CustomTridentUtils.modifyCustomTridentPositionSync(event, packet, entityId); return; } if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { @@ -1705,11 +1651,7 @@ public class PacketConsumers { int entityId = intList.getInt(i); user.entityView().remove(entityId); List entities = user.furnitureView().remove(entityId); - var removeTrident = user.tridentView().remove(entityId); - if (removeTrident != null && !removeTrident.isEmpty()) { - Player player = (Player) user.platformPlayer(); - player.sendMessage("移除三叉戟实体: " + removeTrident); - } + user.tridentView().remove(entityId); if (entities == null) continue; for (int subEntityId : entities) { isChange = true; @@ -2388,10 +2330,7 @@ public class PacketConsumers { try { int entityId = Reflections.field$clazz$ClientboundSetEntityDataPacket$id.getInt(packet); if (user.tridentView().containsKey(entityId)) { - Player player = (Player) user.platformPlayer(); - Object newPacket = FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, user.tridentView().get(entityId)); - player.sendMessage("设置三叉戟实体数据: " + newPacket); - event.replacePacket(newPacket); + CustomTridentUtils.modifyCustomTridentSetEntityData(user, event, entityId); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); @@ -2402,12 +2341,7 @@ public class PacketConsumers { try { int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); if (user.tridentView().containsKey(entityId)) { - float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$xRot.getByte(packet)); - float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$yRot.getByte(packet)); - Reflections.field$ClientboundMoveEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); - Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); - Player player = (Player) user.platformPlayer(); - player.sendMessage("同步三叉戟实体位置: " + Math.clamp(-xRot, -90.0F, 90.0F) + ", " + -yRot); + CustomTridentUtils.modifyCustomTridentMove(packet); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket$PosRot", e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java new file mode 100644 index 000000000..761b411e2 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java @@ -0,0 +1,118 @@ +package net.momirealms.craftengine.bukkit.util; + +import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.network.NMSPacketEvent; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.network.NetWorkUser; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MCUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.entity.Trident; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class CustomTridentUtils { + public static final NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); + public static final NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); + public static final NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); + public static final NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); + + public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) throws IllegalAccessException { + int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); + Trident trident = getTridentById(user, entityId); + if (!isCustomTrident(trident)) return; + user.tridentView().put(entityId, List.of()); + modifyCustomTridentPacket(packet); + List itemDisplayValues = buildEntityDataValues(trident); + user.tridentView().put(entityId, itemDisplayValues); + event.addDelayedTask(() -> { + user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); + }); + } + + @Nullable + public static Trident getTridentById(NetWorkUser user, int entityId) { + Player player = (Player) user.platformPlayer(); + return (Trident) FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId); + } + + public static boolean isCustomTrident(Trident trident) { + if (trident == null) return false; + PersistentDataContainer container = trident.getItemStack().getItemMeta().getPersistentDataContainer(); + String customTrident = container.get(customTridentKey, PersistentDataType.STRING); + return customTrident != null; + } + + public static void modifyCustomTridentPacket(Object packet) throws IllegalAccessException { + float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$yRot.getByte(packet)); + float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$xRot.getByte(packet)); + Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); + Reflections.field$ClientboundAddEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); + Reflections.field$ClientboundAddEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); + } + + public static List buildEntityDataValues(Trident trident) { + List itemDisplayValues = new ArrayList<>(); + PersistentDataContainer container = trident.getItemStack().getItemMeta().getPersistentDataContainer(); + String customTrident = container.get(customTridentKey, PersistentDataType.STRING); + Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); + Integer interpolationDelay = container.get(interpolationDelayKey, PersistentDataType.INTEGER); + Integer transformationInterpolationDuration = container.get(transformationInterpolationDurationaKey, PersistentDataType.INTEGER); + Integer positionRotationInterpolationDuration = container.get(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER); + ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(interpolationDelay, itemDisplayValues); + ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(new Vector3f(0, 0, -2), itemDisplayValues); + ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(new Quaternionf(1, 1, 1, 1), itemDisplayValues); + if (VersionHelper.isOrAbove1_20_2()) { + ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); + ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(positionRotationInterpolationDuration, itemDisplayValues); + } else { + ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); + } + ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues); + ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue((byte) 0, itemDisplayValues); + return itemDisplayValues; + } + + // 这里需要补 ClientboundMoveEntityPacket 包 1.21.2+ + public static void modifyCustomTridentPositionSync(NMSPacketEvent event, Object packet, int entityId) throws IllegalAccessException, InvocationTargetException, InstantiationException { + Object positionMoveRotation = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); + boolean onGround = Reflections.field$ClientboundEntityPositionSyncPacket$onGround.getBoolean(packet); + Object position = Reflections.field$PositionMoveRotation$position.get(positionMoveRotation); + Object deltaMovement = Reflections.field$PositionMoveRotation$deltaMovement.get(positionMoveRotation); + float yRot = Reflections.field$PositionMoveRotation$yRot.getFloat(positionMoveRotation); + float xRot = Reflections.field$PositionMoveRotation$xRot.getFloat(positionMoveRotation); + Object newPositionMoveRotation = Reflections.constructor$PositionMoveRotation.newInstance(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F)); + event.replacePacket(Reflections.constructor$ClientboundEntityPositionSyncPacket.newInstance(entityId, newPositionMoveRotation, onGround)); + } + + public static void modifyCustomTridentMove(Object packet) throws IllegalAccessException { + float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$xRot.getByte(packet)); + float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$yRot.getByte(packet)); + Reflections.field$ClientboundMoveEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); + Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); + } + + public static void modifyCustomTridentSetEntityData(NetWorkUser user, NMSPacketEvent event, int entityId) { + List newData = user.tridentView().get(entityId); + if (newData.isEmpty()) { + Trident trident = getTridentById(user, entityId); + if (!isCustomTrident(trident)) return; + newData = buildEntityDataValues(trident); + user.tridentView().put(entityId, newData); + } + event.replacePacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, newData)); + } +} From 855d6ac15117289e10069e3fb4930a93beffb406 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 02:40:04 +0800 Subject: [PATCH 12/18] =?UTF-8?q?refactor(bukkit):=20=E6=B8=85=E7=90=86?= =?UTF-8?q?=E5=8F=8D=E5=B0=84=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../craftengine/bukkit/util/Reflections.java | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 36f6b5a5c..735382427 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -6663,13 +6663,6 @@ public class Reflections { .map(it -> ReflectionUtils.getInstanceDeclaredField(it, float.class, 1)) .orElse(null); - public static final Class clazz$ClientboundTeleportEntityPacket = requireNonNull( - BukkitReflectionUtils.findReobfOrMojmapClass( - "network.protocol.game.PacketPlayOutEntityTeleport", - "network.protocol.game.ClientboundTeleportEntityPacket" - ) - ); - public static final Constructor constructor$ClientboundEntityPositionSyncPacket = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) .map(it -> ReflectionUtils.getTheOnlyConstructor(it)) .orElse(null); @@ -6697,34 +6690,4 @@ public class Reflections { clazz$ClientboundMoveEntityPacket, byte.class, 0 ) ); - // - // /** - // * 实体移动数据包 - // * - // *

1.20 ~ 1.21.1 版本传入参数:

- // *
    - // *
  • {@code FriendlyByteBuf} 需要按顺序写入: - // *
      - // *
    • {@code id} - VarInt 实体ID
    • - // *
    • {@code x} - Double X坐标
    • - // *
    • {@code y} - Double Y坐标
    • - // *
    • {@code z} - Double Z坐标
    • - // *
    • {@code yRot} - Byte 垂直旋转角度
    • - // *
    • {@code xRot} - Byte 水平旋转角度
    • - // *
    • {@code onGround} - Boolean 着地状态
    • - // *
    - // *
  • - // *
- // * - // *

1.21.2+ 版本传入参数:

- // *
    - // *
  • {@code id} - int 实体ID
  • - // *
  • {@code PositionMoveRotation change} - 位置和移动向量和旋转
  • - // *
  • {@code Set relatives} - 相对坐标标记集合
  • - // *
  • {@code onGround} - boolean 着地状态
  • - // *
- // */ - // public static final Constructor constructor$ClientboundTeleportEntityPacket = requireNonNull( - // ReflectionUtils.getConstructor(clazz$ClientboundTeleportEntityPacket, VersionHelper.isOrAbove1_21_2() ? 0 : 1) - // ); } From a7505ea90249b9b93c8075a63f93e828d1b332d3 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 04:33:37 +0800 Subject: [PATCH 13/18] =?UTF-8?q?refactor(bukkit):=20=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/command/feature/TestCommand.java | 20 ++++++++++++++++++- .../bukkit/util/CustomTridentUtils.java | 18 ++++++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 368aab382..c8468833e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.bukkit.util.CustomTridentUtils; import net.momirealms.craftengine.core.item.Item; @@ -11,6 +12,7 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.bukkit.entity.Trident; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; import org.checkerframework.checker.nullness.qual.NonNull; @@ -18,11 +20,14 @@ import org.incendo.cloud.Command; import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.context.CommandInput; +import org.incendo.cloud.parser.standard.BooleanParser; import org.incendo.cloud.parser.standard.IntegerParser; import org.incendo.cloud.suggestion.Suggestion; import org.incendo.cloud.suggestion.SuggestionProvider; -import java.util.Objects; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -37,6 +42,7 @@ public class TestCommand extends BukkitCommandFeature { public Command.Builder assembleCommand(org.incendo.cloud.CommandManager manager, Command.Builder builder) { return builder .senderType(Player.class) + .required("forceUpdate", BooleanParser.booleanParser()) .required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() { @Override public @NonNull CompletableFuture> suggestionsFuture(@NonNull CommandContext context, @NonNull CommandInput input) { @@ -53,6 +59,18 @@ public class TestCommand extends BukkitCommandFeature { // .required("w", FloatParser.floatParser()) .handler(context -> { Player player = context.sender(); + if (context.get("forceUpdate")) { + net.momirealms.craftengine.core.entity.player.Player cePlayer = plugin().adapt(player); + Collection tridents = player.getWorld().getEntitiesByClass(Trident.class); + List packets = new ArrayList<>(); + for (Trident trident : tridents) { + int entityId = FastNMS.INSTANCE.method$Entity$getId(FastNMS.INSTANCE.method$CraftEntity$getHandle(trident)); + player.sendMessage("COMMAND entityId: " + entityId); + packets.add(CustomTridentUtils.buildCustomTridentSetEntityDataPacket(cePlayer, entityId)); + } + cePlayer.sendPackets(packets, true); + return; + } NamespacedKey namespacedKey = context.get("id"); ItemStack item = new ItemStack(Material.TRIDENT); // NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java index 761b411e2..aeb96c865 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java @@ -38,9 +38,7 @@ public class CustomTridentUtils { modifyCustomTridentPacket(packet); List itemDisplayValues = buildEntityDataValues(trident); user.tridentView().put(entityId, itemDisplayValues); - event.addDelayedTask(() -> { - user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); - }); + event.addDelayedTask(() -> user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true)); } @Nullable @@ -105,14 +103,20 @@ public class CustomTridentUtils { Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); } - public static void modifyCustomTridentSetEntityData(NetWorkUser user, NMSPacketEvent event, int entityId) { - List newData = user.tridentView().get(entityId); + public static Object buildCustomTridentSetEntityDataPacket(NetWorkUser user, int entityId) { + List newData = user.tridentView().getOrDefault(entityId, List.of()); if (newData.isEmpty()) { Trident trident = getTridentById(user, entityId); - if (!isCustomTrident(trident)) return; + if (!isCustomTrident(trident)) return null; newData = buildEntityDataValues(trident); user.tridentView().put(entityId, newData); } - event.replacePacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, newData)); + return FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, newData); + } + + public static void modifyCustomTridentSetEntityData(NetWorkUser user, NMSPacketEvent event, int entityId) { + Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); + if (packet == null) return; + event.replacePacket(packet); } } From 0fa9b84a22b3af79ed948ef49664ecc5f338d659 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 07:04:41 +0800 Subject: [PATCH 14/18] =?UTF-8?q?refactor(bukkit):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=A4=A7=E9=83=A8=E5=88=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复addEnchantment - 差一个移动路径补偿 - 求求你们不要喷我频繁提交了,除了这次最多还会有一个实现移动路径补偿的提交,如果你不想收到提交消息可以到我这个pr去取消通知 --- .../factory/ComponentItemFactory1_20_5.java | 4 +- .../item/factory/UniversalItemFactory.java | 8 +-- .../plugin/network/PacketConsumers.java | 8 ++- .../plugin/user/BukkitServerPlayer.java | 6 +++ .../bukkit/util/CustomTridentUtils.java | 51 ++++++++++++++----- .../craftengine/bukkit/util/Reflections.java | 30 ++++++++++- .../core/plugin/network/NetWorkUser.java | 2 + 7 files changed, 83 insertions(+), 26 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java index 08cc98ec3..f7b5e76ff 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java @@ -309,7 +309,7 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory map = EnchantmentUtils.toMap(enchant); - map.put(enchantment.toString(), enchantment.level()); + map.put(enchantment.id().toString(), enchantment.level()); item.setJavaComponent(ComponentTypes.ENCHANTMENTS, map); } catch (ReflectiveOperationException e) { plugin.logger().warn("Failed to add enchantment", e); @@ -321,7 +321,7 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory map = EnchantmentUtils.toMap(enchant); - map.put(enchantment.toString(), enchantment.level()); + map.put(enchantment.id().toString(), enchantment.level()); item.setJavaComponent(ComponentTypes.STORED_ENCHANTMENTS, map); } catch (ReflectiveOperationException e) { plugin.logger().warn("Failed to add stored enchantment", e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java index 787dba986..3dd72fe51 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java @@ -198,9 +198,9 @@ public class UniversalItemFactory extends BukkitItemFactory { return; } } - item.add(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level()), "Enchantments"); + item.add(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level()), "Enchantments"); } else { - item.set(List.of(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level())), "Enchantments"); + item.set(List.of(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level())), "Enchantments"); } } @@ -214,9 +214,9 @@ public class UniversalItemFactory extends BukkitItemFactory { return; } } - item.add(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level()), "StoredEnchantments"); + item.add(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level()), "StoredEnchantments"); } else { - item.set(List.of(Map.of("id", enchantment.toString(), "lvl", (short) enchantment.level())), "StoredEnchantments"); + item.set(List.of(Map.of("id", enchantment.id().toString(), "lvl", (short) enchantment.level())), "StoredEnchantments"); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 1e36bba6a..1d4d4a8b6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -1620,7 +1620,7 @@ public class PacketConsumers { try { int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet); if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentPositionSync(event, packet, entityId); + CustomTridentUtils.modifyCustomTridentPositionSync(user, event, packet, entityId); return; } if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { @@ -2329,9 +2329,7 @@ public class PacketConsumers { public static final TriConsumer SET_ENTITY_DATA = (user, event, packet) -> { try { int entityId = Reflections.field$clazz$ClientboundSetEntityDataPacket$id.getInt(packet); - if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentSetEntityData(user, event, entityId); - } + CustomTridentUtils.modifyCustomTridentSetEntityData(user, event, entityId); } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); } @@ -2341,7 +2339,7 @@ public class PacketConsumers { try { int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentMove(packet); + CustomTridentUtils.modifyCustomTridentMove(packet, user); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket$PosRot", e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 102c2cdaa..38122b1a0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -94,6 +94,7 @@ public class BukkitServerPlayer extends Player { private final Map> furnitureView = new ConcurrentHashMap<>(); private final Map entityTypeView = new ConcurrentHashMap<>(); private final Map> tridentView = new ConcurrentHashMap<>(); + private final Map addTridentPacketView = new ConcurrentHashMap<>(); public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) { this.channel = channel; @@ -743,6 +744,11 @@ public class BukkitServerPlayer extends Player { return this.tridentView; } + @Override + public Map addTridentPacketView() { + return this.addTridentPacketView; + } + public void setResendSound() { resentSoundTick = gameTicks(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java index aeb96c865..2e35b45a4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java @@ -4,12 +4,14 @@ import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.network.NMSPacketEvent; +import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.network.NetWorkUser; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MCUtils; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.NamespacedKey; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.Trident; import org.bukkit.inventory.ItemStack; @@ -33,25 +35,30 @@ public class CustomTridentUtils { public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) throws IllegalAccessException { int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); Trident trident = getTridentById(user, entityId); - if (!isCustomTrident(trident)) return; + if (notCustomTrident(trident)) return; user.tridentView().put(entityId, List.of()); modifyCustomTridentPacket(packet); + user.addTridentPacketView().put(entityId, packet); List itemDisplayValues = buildEntityDataValues(trident); user.tridentView().put(entityId, itemDisplayValues); - event.addDelayedTask(() -> user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true)); + user.sendPacket(packet, true); + user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); + event.setCancelled(true); } @Nullable public static Trident getTridentById(NetWorkUser user, int entityId) { Player player = (Player) user.platformPlayer(); - return (Trident) FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId); + Entity entity = FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId); + if (entity instanceof Trident trident) return trident; + return null; } - public static boolean isCustomTrident(Trident trident) { - if (trident == null) return false; + public static boolean notCustomTrident(Trident trident) { + if (trident == null) return true; PersistentDataContainer container = trident.getItemStack().getItemMeta().getPersistentDataContainer(); String customTrident = container.get(customTridentKey, PersistentDataType.STRING); - return customTrident != null; + return customTrident == null; } public static void modifyCustomTridentPacket(Object packet) throws IllegalAccessException { @@ -64,9 +71,11 @@ public class CustomTridentUtils { public static List buildEntityDataValues(Trident trident) { List itemDisplayValues = new ArrayList<>(); - PersistentDataContainer container = trident.getItemStack().getItemMeta().getPersistentDataContainer(); + ItemStack itemStack = trident.getItemStack(); + PersistentDataContainer container = itemStack.getItemMeta().getPersistentDataContainer(); String customTrident = container.get(customTridentKey, PersistentDataType.STRING); Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); + itemStack.getEnchantments().forEach((enchantment, level) -> item.addEnchantment(new Enchantment(Key.of(enchantment.getKey().toString()), level))); Integer interpolationDelay = container.get(interpolationDelayKey, PersistentDataType.INTEGER); Integer transformationInterpolationDuration = container.get(transformationInterpolationDurationaKey, PersistentDataType.INTEGER); Integer positionRotationInterpolationDuration = container.get(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER); @@ -85,7 +94,7 @@ public class CustomTridentUtils { } // 这里需要补 ClientboundMoveEntityPacket 包 1.21.2+ - public static void modifyCustomTridentPositionSync(NMSPacketEvent event, Object packet, int entityId) throws IllegalAccessException, InvocationTargetException, InstantiationException { + public static void modifyCustomTridentPositionSync(NetWorkUser user, NMSPacketEvent event, Object packet, int entityId) throws IllegalAccessException, InvocationTargetException, InstantiationException { Object positionMoveRotation = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); boolean onGround = Reflections.field$ClientboundEntityPositionSyncPacket$onGround.getBoolean(packet); Object position = Reflections.field$PositionMoveRotation$position.get(positionMoveRotation); @@ -94,11 +103,18 @@ public class CustomTridentUtils { float xRot = Reflections.field$PositionMoveRotation$xRot.getFloat(positionMoveRotation); Object newPositionMoveRotation = Reflections.constructor$PositionMoveRotation.newInstance(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F)); event.replacePacket(Reflections.constructor$ClientboundEntityPositionSyncPacket.newInstance(entityId, newPositionMoveRotation, onGround)); + // List path = SmoothMovementPathUtils.calculatePath(start, move, yRot, xRot); + // ((Player)user.platformPlayer()).sendMessage("entityId: " + entityId + " position: " + position + " deltaMovement: " + deltaMovement + " xRot: " + xRot + " yRot: " + yRot); } - public static void modifyCustomTridentMove(Object packet) throws IllegalAccessException { + public static void modifyCustomTridentMove(Object packet, NetWorkUser user) throws IllegalAccessException { + // int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); + // double xa = Reflections.field$ClientboundMoveEntityPacket$xa.getShort(packet); + // double ya = Reflections.field$ClientboundMoveEntityPacket$ya.getShort(packet); + // double za = Reflections.field$ClientboundMoveEntityPacket$za.getShort(packet); float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$xRot.getByte(packet)); float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$yRot.getByte(packet)); + // ((Player)user.platformPlayer()).sendMessage("entityId: " + entityId + " xa: " + xa + " ya: " + ya + " za: " + za + " xRot: " + xRot + " yRot: " + yRot); Reflections.field$ClientboundMoveEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); } @@ -107,7 +123,7 @@ public class CustomTridentUtils { List newData = user.tridentView().getOrDefault(entityId, List.of()); if (newData.isEmpty()) { Trident trident = getTridentById(user, entityId); - if (!isCustomTrident(trident)) return null; + if (notCustomTrident(trident)) return null; newData = buildEntityDataValues(trident); user.tridentView().put(entityId, newData); } @@ -115,8 +131,17 @@ public class CustomTridentUtils { } public static void modifyCustomTridentSetEntityData(NetWorkUser user, NMSPacketEvent event, int entityId) { - Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); - if (packet == null) return; - event.replacePacket(packet); + if (user.tridentView().containsKey(entityId)) { + Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); + if (packet == null) return; + event.replacePacket(packet); + } else { + Trident trident = getTridentById(user, entityId); + if (trident == null) return; + if (notCustomTrident(trident)) return; + Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); + if (packet == null) return; + event.replacePacket(packet); + } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 735382427..485df7122 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -6103,6 +6103,10 @@ public class Reflections { ) ); + public static final Constructor constructor$ClientboundMoveEntityPacket$PosRot = requireNonNull( + ReflectionUtils.getTheOnlyConstructor(clazz$ClientboundMoveEntityPacket$PosRot) + ); + public static final Class clazz$ClientboundRotateHeadPacket = requireNonNull( BukkitReflectionUtils.findReobfOrMojmapClass( "network.protocol.game.PacketPlayOutEntityHeadRotation", @@ -6400,14 +6404,18 @@ public class Reflections { ); public static final int instance$EntityType$BLOCK_DISPLAY$registryId; + public static final int instance$EntityType$ITEM_DISPLAY$registryId; public static final int instance$EntityType$TEXT_DISPLAY$registryId; public static final int instance$EntityType$FALLING_BLOCK$registryId; + public static final int instance$EntityType$TRIDENT$registryId; static { try { instance$EntityType$BLOCK_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$BLOCK_DISPLAY); + instance$EntityType$ITEM_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$ITEM_DISPLAY); instance$EntityType$TEXT_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$TEXT_DISPLAY); instance$EntityType$FALLING_BLOCK$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$FALLING_BLOCK); + instance$EntityType$TRIDENT$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$TRIDENT); } catch (Exception e) { throw new RuntimeException(e); } @@ -6636,7 +6644,7 @@ public class Reflections { ); public static final Constructor constructor$PositionMoveRotation = Optional.ofNullable(clazz$PositionMoveRotation) - .map(it -> ReflectionUtils.getTheOnlyConstructor(it)) + .map(ReflectionUtils::getTheOnlyConstructor) .orElse(null); public static final Field field$ClientboundEntityPositionSyncPacket$values = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) @@ -6664,7 +6672,7 @@ public class Reflections { .orElse(null); public static final Constructor constructor$ClientboundEntityPositionSyncPacket = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) - .map(it -> ReflectionUtils.getTheOnlyConstructor(it)) + .map(ReflectionUtils::getTheOnlyConstructor) .orElse(null); public static final Field field$ClientboundAddEntityPacket$xRot = requireNonNull( @@ -6690,4 +6698,22 @@ public class Reflections { clazz$ClientboundMoveEntityPacket, byte.class, 0 ) ); + + public static final Field field$ClientboundMoveEntityPacket$xa = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundMoveEntityPacket, short.class, 0 + ) + ); + + public static final Field field$ClientboundMoveEntityPacket$ya = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundMoveEntityPacket, short.class, 1 + ) + ); + + public static final Field field$ClientboundMoveEntityPacket$za = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundMoveEntityPacket, short.class, 2 + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java index b1952a648..b74842ee1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java @@ -48,6 +48,8 @@ public interface NetWorkUser { Map> tridentView(); + Map addTridentPacketView(); + boolean clientModEnabled(); void setClientModState(boolean enable); From dec6cd4063603d7c58385015cfefc502fdd0eb03 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 09:56:42 +0800 Subject: [PATCH 15/18] =?UTF-8?q?refactor(bukkit):=20=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E4=B8=89=E5=8F=89=E6=88=9F=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 接下来是设计配置文件 - 后面和优化一起推上去 --- .../plugin/network/PacketConsumers.java | 9 +++-- .../plugin/user/BukkitServerPlayer.java | 5 +-- .../bukkit/util/CustomTridentUtils.java | 35 +++++++++++++------ .../craftengine/bukkit/util/Reflections.java | 30 +++++++++++----- .../core/plugin/network/NetWorkUser.java | 3 +- 5 files changed, 58 insertions(+), 24 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 1d4d4a8b6..5280c2131 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -35,6 +35,7 @@ import net.momirealms.craftengine.core.plugin.network.ConnectionState; import net.momirealms.craftengine.core.plugin.network.NetWorkUser; import net.momirealms.craftengine.core.plugin.network.NetworkManager; import net.momirealms.craftengine.core.plugin.network.ProtocolVersion; +import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask; import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.BlockHitResult; import net.momirealms.craftengine.core.world.BlockPos; @@ -1620,7 +1621,7 @@ public class PacketConsumers { try { int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet); if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentPositionSync(user, event, packet, entityId); + CustomTridentUtils.modifyCustomTridentPositionSync(event, packet, entityId); return; } if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { @@ -1651,6 +1652,10 @@ public class PacketConsumers { int entityId = intList.getInt(i); user.entityView().remove(entityId); List entities = user.furnitureView().remove(entityId); + SchedulerTask task = user.tridentTaskView().remove(entityId); + if (task != null) { + task.cancel(); + } user.tridentView().remove(entityId); if (entities == null) continue; for (int subEntityId : entities) { @@ -2339,7 +2344,7 @@ public class PacketConsumers { try { int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentMove(packet, user); + CustomTridentUtils.modifyCustomTridentMove(packet); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket$PosRot", e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 38122b1a0..a9e2d0eba 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -20,6 +20,7 @@ import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.network.ConnectionState; import net.momirealms.craftengine.core.plugin.network.ProtocolVersion; +import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; @@ -94,7 +95,7 @@ public class BukkitServerPlayer extends Player { private final Map> furnitureView = new ConcurrentHashMap<>(); private final Map entityTypeView = new ConcurrentHashMap<>(); private final Map> tridentView = new ConcurrentHashMap<>(); - private final Map addTridentPacketView = new ConcurrentHashMap<>(); + private final Map addTridentPacketView = new ConcurrentHashMap<>(); public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) { this.channel = channel; @@ -745,7 +746,7 @@ public class BukkitServerPlayer extends Player { } @Override - public Map addTridentPacketView() { + public Map tridentTaskView() { return this.addTridentPacketView; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java index 2e35b45a4..d4a938669 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java @@ -6,7 +6,9 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.network.NMSPacketEvent; import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.network.NetWorkUser; +import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MCUtils; import net.momirealms.craftengine.core.util.VersionHelper; @@ -25,6 +27,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.concurrent.TimeUnit; public class CustomTridentUtils { public static final NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); @@ -35,15 +38,33 @@ public class CustomTridentUtils { public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) throws IllegalAccessException { int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); Trident trident = getTridentById(user, entityId); + Object serverEntity; + Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(trident); + Object tracker = Reflections.field$Entity$trackedEntity.get(nmsEntity); + if (tracker != null) { + serverEntity = Reflections.field$ChunkMap$TrackedEntity$serverEntity.get(tracker); + } else { + serverEntity = null; + } if (notCustomTrident(trident)) return; user.tridentView().put(entityId, List.of()); modifyCustomTridentPacket(packet); - user.addTridentPacketView().put(entityId, packet); List itemDisplayValues = buildEntityDataValues(trident); user.tridentView().put(entityId, itemDisplayValues); user.sendPacket(packet, true); user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); event.setCancelled(true); + if (serverEntity != null) { + // 这里直接暴力更新 + SchedulerTask task = CraftEngine.instance().scheduler().asyncRepeating(() -> { + try { + Reflections.method$ServerEntity$sendChanges.invoke(serverEntity); + } catch (IllegalAccessException | InvocationTargetException e) { + CraftEngine.instance().logger().warn("Failed to send entity data packet", e); + } + }, 5, 5, TimeUnit.MILLISECONDS); + user.tridentTaskView().put(entityId, task); + } } @Nullable @@ -93,8 +114,7 @@ public class CustomTridentUtils { return itemDisplayValues; } - // 这里需要补 ClientboundMoveEntityPacket 包 1.21.2+ - public static void modifyCustomTridentPositionSync(NetWorkUser user, NMSPacketEvent event, Object packet, int entityId) throws IllegalAccessException, InvocationTargetException, InstantiationException { + public static void modifyCustomTridentPositionSync(NMSPacketEvent event, Object packet, int entityId) throws IllegalAccessException, InvocationTargetException, InstantiationException { Object positionMoveRotation = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); boolean onGround = Reflections.field$ClientboundEntityPositionSyncPacket$onGround.getBoolean(packet); Object position = Reflections.field$PositionMoveRotation$position.get(positionMoveRotation); @@ -103,18 +123,11 @@ public class CustomTridentUtils { float xRot = Reflections.field$PositionMoveRotation$xRot.getFloat(positionMoveRotation); Object newPositionMoveRotation = Reflections.constructor$PositionMoveRotation.newInstance(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F)); event.replacePacket(Reflections.constructor$ClientboundEntityPositionSyncPacket.newInstance(entityId, newPositionMoveRotation, onGround)); - // List path = SmoothMovementPathUtils.calculatePath(start, move, yRot, xRot); - // ((Player)user.platformPlayer()).sendMessage("entityId: " + entityId + " position: " + position + " deltaMovement: " + deltaMovement + " xRot: " + xRot + " yRot: " + yRot); } - public static void modifyCustomTridentMove(Object packet, NetWorkUser user) throws IllegalAccessException { - // int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); - // double xa = Reflections.field$ClientboundMoveEntityPacket$xa.getShort(packet); - // double ya = Reflections.field$ClientboundMoveEntityPacket$ya.getShort(packet); - // double za = Reflections.field$ClientboundMoveEntityPacket$za.getShort(packet); + public static void modifyCustomTridentMove(Object packet) throws IllegalAccessException { float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$xRot.getByte(packet)); float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$yRot.getByte(packet)); - // ((Player)user.platformPlayer()).sendMessage("entityId: " + entityId + " xa: " + xa + " ya: " + ya + " za: " + za + " xRot: " + xRot + " yRot: " + yRot); Reflections.field$ClientboundMoveEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 485df7122..15fe735f3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -6699,21 +6699,35 @@ public class Reflections { ) ); - public static final Field field$ClientboundMoveEntityPacket$xa = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ClientboundMoveEntityPacket, short.class, 0 + public static final Class clazz$ServerEntity = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "server.level.EntityTrackerEntry", + "server.level.ServerEntity" ) ); - public static final Field field$ClientboundMoveEntityPacket$ya = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ClientboundMoveEntityPacket, short.class, 1 + public static final Method method$ServerEntity$sendChanges = requireNonNull( + ReflectionUtils.getMethod( + clazz$ServerEntity, void.class, new String[]{ "sendChanges", "a" } ) ); - public static final Field field$ClientboundMoveEntityPacket$za = requireNonNull( + public static final Class clazz$ChunkMap$TrackedEntity = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "server.level.PlayerChunkMap$EntityTracker", + "server.level.ChunkMap$TrackedEntity" + ) + ); + + public static final Field field$Entity$trackedEntity = requireNonNull( ReflectionUtils.getDeclaredField( - clazz$ClientboundMoveEntityPacket, short.class, 2 + clazz$Entity, clazz$ChunkMap$TrackedEntity, 0 + ) + ); + + public static final Field field$ChunkMap$TrackedEntity$serverEntity = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ChunkMap$TrackedEntity, clazz$ServerEntity, 0 ) ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java index b74842ee1..177e8d12c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.network; import io.netty.channel.Channel; import net.momirealms.craftengine.core.plugin.Plugin; +import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.ApiStatus; @@ -48,7 +49,7 @@ public interface NetWorkUser { Map> tridentView(); - Map addTridentPacketView(); + Map tridentTaskView(); boolean clientModEnabled(); From 0c5d23a260d7acb2bfadf515161dfaafe565b1bf Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 11:29:28 +0800 Subject: [PATCH 16/18] =?UTF-8?q?refactor(bukkit):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E8=B0=83=E8=AF=95=E7=9A=84=E4=B8=9C=E8=A5=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 准备设计配置格式 --- .../plugin/command/feature/TestCommand.java | 38 +++++---------- .../plugin/network/PacketConsumers.java | 4 +- .../bukkit/util/CustomTridentUtils.java | 48 ++++++++----------- 3 files changed, 37 insertions(+), 53 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index c8468833e..8cfc37e8a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -14,14 +14,14 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.entity.Trident; import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import org.checkerframework.checker.nullness.qual.NonNull; import org.incendo.cloud.Command; import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.context.CommandInput; -import org.incendo.cloud.parser.standard.BooleanParser; -import org.incendo.cloud.parser.standard.IntegerParser; +import org.incendo.cloud.parser.standard.*; import org.incendo.cloud.suggestion.Suggestion; import org.incendo.cloud.suggestion.SuggestionProvider; @@ -49,14 +49,10 @@ public class TestCommand extends BukkitCommandFeature { return CompletableFuture.completedFuture(plugin().itemManager().cachedSuggestions()); } })) - .required("interpolationDelay", IntegerParser.integerParser()) - .required("transformationInterpolationDuration", IntegerParser.integerParser()) - .required("positionRotationInterpolationDuration", IntegerParser.integerParser()) - // .required("displayType", ByteParser.byteParser()) - // .required("x", FloatParser.floatParser()) - // .required("y", FloatParser.floatParser()) - // .required("z", FloatParser.floatParser()) - // .required("w", FloatParser.floatParser()) + .required("interpolationDuration", IntegerParser.integerParser()) + .required("displayType", ByteParser.byteParser((byte) 0, (byte) 8)) + .required("translation", StringParser.stringParser()) + .required("rotationLeft", StringParser.stringParser()) .handler(context -> { Player player = context.sender(); if (context.get("forceUpdate")) { @@ -73,21 +69,13 @@ public class TestCommand extends BukkitCommandFeature { } NamespacedKey namespacedKey = context.get("id"); ItemStack item = new ItemStack(Material.TRIDENT); - // NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); - // NamespacedKey customTridentX = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_x")); - // NamespacedKey customTridentY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_y")); - // NamespacedKey customTridentZ = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_z")); - // NamespacedKey customTridentW = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident_w")); - item.editMeta(meta -> { - meta.getPersistentDataContainer().set(CustomTridentUtils.customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); - meta.getPersistentDataContainer().set(CustomTridentUtils.interpolationDelayKey, PersistentDataType.INTEGER, context.get("interpolationDelay")); - meta.getPersistentDataContainer().set(CustomTridentUtils.transformationInterpolationDurationaKey, PersistentDataType.INTEGER, context.get("transformationInterpolationDuration")); - meta.getPersistentDataContainer().set(CustomTridentUtils.positionRotationInterpolationDurationKey, PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration")); - // container.set(displayTypeKey, PersistentDataType.BYTE, context.get("displayType")); - // container.set(customTridentX, PersistentDataType.FLOAT, context.get("x")); - // container.set(customTridentY, PersistentDataType.FLOAT, context.get("y")); - // container.set(customTridentZ, PersistentDataType.FLOAT, context.get("z")); - // container.set(customTridentW, PersistentDataType.FLOAT, context.get("w")); + item.editMeta((meta) -> { + PersistentDataContainer container = meta.getPersistentDataContainer(); + container.set(CustomTridentUtils.customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); + container.set(CustomTridentUtils.interpolationDurationaKey, PersistentDataType.INTEGER, context.get("interpolationDuration")); + container.set(CustomTridentUtils.displayTypeKey, PersistentDataType.BYTE, context.get("displayType")); + container.set(CustomTridentUtils.translationKey, PersistentDataType.STRING, context.get("translation")); + container.set(CustomTridentUtils.rotationLeftKey, PersistentDataType.STRING, context.get("rotationLeft")); Item ceItem = BukkitItemManager.instance().createWrappedItem(Key.of(namespacedKey.asString()), null); Optional customModelData = ceItem.customModelData(); customModelData.ifPresent(meta::setCustomModelData); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 5280c2131..4589fe4ab 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -2334,7 +2334,9 @@ public class PacketConsumers { public static final TriConsumer SET_ENTITY_DATA = (user, event, packet) -> { try { int entityId = Reflections.field$clazz$ClientboundSetEntityDataPacket$id.getInt(packet); - CustomTridentUtils.modifyCustomTridentSetEntityData(user, event, entityId); + if (user.tridentView().containsKey(entityId)) { + CustomTridentUtils.modifyCustomTridentSetEntityData(user, event, entityId); + } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java index d4a938669..09a543a19 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java @@ -31,9 +31,10 @@ import java.util.concurrent.TimeUnit; public class CustomTridentUtils { public static final NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); - public static final NamespacedKey interpolationDelayKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")); - public static final NamespacedKey transformationInterpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")); - public static final NamespacedKey positionRotationInterpolationDurationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")); + public static final NamespacedKey interpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_duration")); + public static final NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); + public static final NamespacedKey translationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:translation")); + public static final NamespacedKey rotationLeftKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:rotation_left")); public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) throws IllegalAccessException { int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); @@ -47,7 +48,6 @@ public class CustomTridentUtils { serverEntity = null; } if (notCustomTrident(trident)) return; - user.tridentView().put(entityId, List.of()); modifyCustomTridentPacket(packet); List itemDisplayValues = buildEntityDataValues(trident); user.tridentView().put(entityId, itemDisplayValues); @@ -94,23 +94,26 @@ public class CustomTridentUtils { List itemDisplayValues = new ArrayList<>(); ItemStack itemStack = trident.getItemStack(); PersistentDataContainer container = itemStack.getItemMeta().getPersistentDataContainer(); - String customTrident = container.get(customTridentKey, PersistentDataType.STRING); + String customTrident = container.getOrDefault(customTridentKey, PersistentDataType.STRING, "craftengine:empty"); Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); itemStack.getEnchantments().forEach((enchantment, level) -> item.addEnchantment(new Enchantment(Key.of(enchantment.getKey().toString()), level))); - Integer interpolationDelay = container.get(interpolationDelayKey, PersistentDataType.INTEGER); - Integer transformationInterpolationDuration = container.get(transformationInterpolationDurationaKey, PersistentDataType.INTEGER); - Integer positionRotationInterpolationDuration = container.get(positionRotationInterpolationDurationKey, PersistentDataType.INTEGER); - ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(interpolationDelay, itemDisplayValues); - ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(new Vector3f(0, 0, -2), itemDisplayValues); - ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(new Quaternionf(1, 1, 1, 1), itemDisplayValues); + Integer interpolationDurationa = container.getOrDefault(interpolationDurationaKey, PersistentDataType.INTEGER, 2); + Byte displayType = container.getOrDefault(displayTypeKey, PersistentDataType.BYTE, (byte) 0); + String translation = container.getOrDefault(translationKey, PersistentDataType.STRING, "0+0+0"); + String[] translations = translation.split("\\+"); + String rotationLeft = container.getOrDefault(rotationLeftKey, PersistentDataType.STRING, "0+0+0+0"); + String[] rotationLefts = rotationLeft.split("\\+"); + ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(-1, itemDisplayValues); + ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(new Vector3f(Float.parseFloat(translations[0]), Float.parseFloat(translations[1]), Float.parseFloat(translations[2])), itemDisplayValues); + ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(new Quaternionf(Float.parseFloat(rotationLefts[0]), Float.parseFloat(rotationLefts[1]), Float.parseFloat(rotationLefts[2]), Float.parseFloat(rotationLefts[3])), itemDisplayValues); if (VersionHelper.isOrAbove1_20_2()) { - ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); - ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(positionRotationInterpolationDuration, itemDisplayValues); + ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(interpolationDurationa, itemDisplayValues); + ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(interpolationDurationa, itemDisplayValues); } else { - ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues); + ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(interpolationDurationa, itemDisplayValues); } ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues); - ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue((byte) 0, itemDisplayValues); + ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(displayType, itemDisplayValues); return itemDisplayValues; } @@ -144,17 +147,8 @@ public class CustomTridentUtils { } public static void modifyCustomTridentSetEntityData(NetWorkUser user, NMSPacketEvent event, int entityId) { - if (user.tridentView().containsKey(entityId)) { - Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); - if (packet == null) return; - event.replacePacket(packet); - } else { - Trident trident = getTridentById(user, entityId); - if (trident == null) return; - if (notCustomTrident(trident)) return; - Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); - if (packet == null) return; - event.replacePacket(packet); - } + Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); + if (packet == null) return; + event.replacePacket(packet); } } From 29b0c9c8c5f6262daebc6fa873371c87b7434e97 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 13:51:03 +0800 Subject: [PATCH 17/18] =?UTF-8?q?refactor(bukkit):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B0=B4=E4=B8=8B=E6=B0=94=E6=B3=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 准备设计配置格式 --- .../plugin/command/feature/TestCommand.java | 13 ------- .../plugin/network/BukkitNetworkManager.java | 3 +- .../plugin/network/PacketConsumers.java | 23 ++++++------ .../bukkit/util/CustomTridentUtils.java | 37 ++++++++++++++----- .../bukkit/util/ParticleUtils.java | 1 + .../craftengine/bukkit/util/Reflections.java | 30 ++++++++++++++- 6 files changed, 69 insertions(+), 38 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 8cfc37e8a..c59ef90bd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -42,7 +42,6 @@ public class TestCommand extends BukkitCommandFeature { public Command.Builder assembleCommand(org.incendo.cloud.CommandManager manager, Command.Builder builder) { return builder .senderType(Player.class) - .required("forceUpdate", BooleanParser.booleanParser()) .required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() { @Override public @NonNull CompletableFuture> suggestionsFuture(@NonNull CommandContext context, @NonNull CommandInput input) { @@ -55,18 +54,6 @@ public class TestCommand extends BukkitCommandFeature { .required("rotationLeft", StringParser.stringParser()) .handler(context -> { Player player = context.sender(); - if (context.get("forceUpdate")) { - net.momirealms.craftengine.core.entity.player.Player cePlayer = plugin().adapt(player); - Collection tridents = player.getWorld().getEntitiesByClass(Trident.class); - List packets = new ArrayList<>(); - for (Trident trident : tridents) { - int entityId = FastNMS.INSTANCE.method$Entity$getId(FastNMS.INSTANCE.method$CraftEntity$getHandle(trident)); - player.sendMessage("COMMAND entityId: " + entityId); - packets.add(CustomTridentUtils.buildCustomTridentSetEntityDataPacket(cePlayer, entityId)); - } - cePlayer.sendPackets(packets, true); - return; - } NamespacedKey namespacedKey = context.get("id"); ItemStack item = new ItemStack(Material.TRIDENT); item.editMeta((meta) -> { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 599364ad9..95bca0475 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -152,7 +152,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(PacketConsumers.LOGIN_ACKNOWLEDGED, Reflections.clazz$ServerboundLoginAcknowledgedPacket); registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, Reflections.clazz$ServerboundResourcePackPacket); registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, Reflections.clazz$ClientboundEntityEventPacket); - registerNMSPacketConsumer(PacketConsumers.SET_ENTITY_DATA, Reflections.clazz$ClientboundSetEntityDataPacket); registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY_ALL, Reflections.clazz$ClientboundMoveEntityPacket$PosRot); registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket()); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); @@ -172,7 +171,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket()); registerByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket()); registerByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket()); - registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA_BYTEBUFFER, this.packetIds.clientboundSetEntityDataPacket()); + registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket()); } public static BukkitNetworkManager instance() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 4589fe4ab..0ab795316 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -2008,10 +2008,20 @@ public class PacketConsumers { }; @SuppressWarnings("unchecked") - public static final BiConsumer SET_ENTITY_DATA_BYTEBUFFER = (user, event) -> { + public static final BiConsumer SET_ENTITY_DATA = (user, event) -> { try { FriendlyByteBuf buf = event.getBuffer(); int id = buf.readVarInt(); + if (user.tridentView().containsKey(id)) { + List packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); + List newPackedItems = CustomTridentUtils.buildCustomTridentSetEntityDataPacket(user, packedItems, id); + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeVarInt(id); + FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(newPackedItems, buf); + return; + } Object entityType = user.entityView().get(id); if (entityType == Reflections.instance$EntityType$BLOCK_DISPLAY) { boolean isChanged = false; @@ -2331,17 +2341,6 @@ public class PacketConsumers { } }; - public static final TriConsumer SET_ENTITY_DATA = (user, event, packet) -> { - try { - int entityId = Reflections.field$clazz$ClientboundSetEntityDataPacket$id.getInt(packet); - if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentSetEntityData(user, event, entityId); - } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); - } - }; - public static final TriConsumer MOVE_ENTITY_ALL = (user, event, packet) -> { try { int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java index 09a543a19..5c4c270e2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java @@ -13,6 +13,7 @@ import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MCUtils; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.NamespacedKey; +import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.Trident; @@ -39,6 +40,8 @@ public class CustomTridentUtils { public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) throws IllegalAccessException { int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); Trident trident = getTridentById(user, entityId); + if (trident == null) return; + World world = trident.getWorld(); Object serverEntity; Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(trident); Object tracker = Reflections.field$Entity$trackedEntity.get(nmsEntity); @@ -59,14 +62,26 @@ public class CustomTridentUtils { SchedulerTask task = CraftEngine.instance().scheduler().asyncRepeating(() -> { try { Reflections.method$ServerEntity$sendChanges.invoke(serverEntity); + if (!isInGround(nmsEntity)) { + world.spawnParticle(ParticleUtils.getParticle("BUBBLE"), trident.getLocation(), 1, 0, 0, 0, 0); + } } catch (IllegalAccessException | InvocationTargetException e) { CraftEngine.instance().logger().warn("Failed to send entity data packet", e); } - }, 5, 5, TimeUnit.MILLISECONDS); + }, 0, 5, TimeUnit.MILLISECONDS); user.tridentTaskView().put(entityId, task); } } + private static boolean isInGround(Object nmsEntity) throws IllegalAccessException, InvocationTargetException { + if (!Reflections.field$Entity$wasTouchingWater.getBoolean(nmsEntity)) return true; + if (VersionHelper.isOrAbove1_21_2()) { + return (boolean) Reflections.method$AbstractArrow$isInGround.invoke(nmsEntity); + } else { + return Reflections.field$AbstractArrow$inGround.getBoolean(nmsEntity); + } + } + @Nullable public static Trident getTridentById(NetWorkUser user, int entityId) { Player player = (Player) user.platformPlayer(); @@ -135,20 +150,22 @@ public class CustomTridentUtils { Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); } - public static Object buildCustomTridentSetEntityDataPacket(NetWorkUser user, int entityId) { + public static List buildCustomTridentSetEntityDataPacket(NetWorkUser user, List packedItems, int entityId) { + List newPackedItems = new ArrayList<>(); + for (Object packedItem : packedItems) { + int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); + if (entityDataId < 8) { + newPackedItems.add(packedItem); + } + } List newData = user.tridentView().getOrDefault(entityId, List.of()); if (newData.isEmpty()) { Trident trident = getTridentById(user, entityId); - if (notCustomTrident(trident)) return null; + if (notCustomTrident(trident)) return newPackedItems; newData = buildEntityDataValues(trident); user.tridentView().put(entityId, newData); } - return FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, newData); - } - - public static void modifyCustomTridentSetEntityData(NetWorkUser user, NMSPacketEvent event, int entityId) { - Object packet = buildCustomTridentSetEntityDataPacket(user, entityId); - if (packet == null) return; - event.replacePacket(packet); + newPackedItems.addAll(newData); + return newPackedItems; } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java index 6e847f6f9..e401be613 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java @@ -12,6 +12,7 @@ public class ParticleUtils { return switch (particle) { case "REDSTONE" -> Particle.valueOf("DUST"); case "VILLAGER_HAPPY", "HAPPY_VILLAGER" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "HAPPY_VILLAGER" : "VILLAGER_HAPPY"); + case "BUBBLE" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "BUBBLE" : "WATER_BUBBLE"); default -> Particle.valueOf(particle); }; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 15fe735f3..d71b22597 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -6632,7 +6632,7 @@ public class Reflections { ) ); - public static final Field field$clazz$ClientboundSetEntityDataPacket$id = requireNonNull( + public static final Field field$ClientboundSetEntityDataPacket$id = requireNonNull( ReflectionUtils.getDeclaredField( clazz$ClientboundSetEntityDataPacket, int.class, 0 ) @@ -6730,4 +6730,32 @@ public class Reflections { clazz$ChunkMap$TrackedEntity, clazz$ServerEntity, 0 ) ); + + public static final Field field$Entity$wasTouchingWater = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$Entity, VersionHelper.isOrAbove1_21_2() + ? new String[]{ "wasTouchingWater", "ag" } : VersionHelper.isOrAbove1_20_5() + ? new String[]{ "wasTouchingWater", "aj" } : VersionHelper.isOrAbove1_20_2() + ? new String[]{ "wasTouchingWater", "ai" } : new String[]{ "wasTouchingWater", "ah" } + ) + ); + + public static final Class clazz$AbstractArrow = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "world.entity.projectile.EntityArrow", + "world.entity.projectile.AbstractArrow" + ) + ); + + // 1.20~1.21.1 + public static final Field field$AbstractArrow$inGround = + ReflectionUtils.getDeclaredField( + clazz$AbstractArrow, boolean.class, 0 + ); + + // 1.21.2+ + public static final Method method$AbstractArrow$isInGround = + ReflectionUtils.getMethod( + clazz$AbstractArrow, boolean.class, VersionHelper.isOrAbove1_21_5() ? new String[]{ "isInGround", "e" } : new String[]{ "isInGround", "l" } + ); } From 79244af7447cd1f7e055860542d4a10f774bc8d7 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sat, 10 May 2025 18:32:07 +0800 Subject: [PATCH 18/18] =?UTF-8?q?refactor(bukkit):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=B9=B6=E4=B8=94=E4=BC=98=E5=8C=96=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/command/feature/TestCommand.java | 7 - .../plugin/network/PacketConsumers.java | 4 +- .../bukkit/util/CustomTridentUtils.java | 140 +++++++++--------- .../craftengine/bukkit/util/Reflections.java | 126 ---------------- .../core/entity/CustomTrident.java | 8 + .../craftengine/core/item/ItemSettings.java | 22 +++ .../craftengine/core/util/MCUtils.java | 12 ++ gradle.properties | 2 +- 8 files changed, 111 insertions(+), 210 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/CustomTrident.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index c59ef90bd..d9a512893 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -48,7 +48,6 @@ public class TestCommand extends BukkitCommandFeature { return CompletableFuture.completedFuture(plugin().itemManager().cachedSuggestions()); } })) - .required("interpolationDuration", IntegerParser.integerParser()) .required("displayType", ByteParser.byteParser((byte) 0, (byte) 8)) .required("translation", StringParser.stringParser()) .required("rotationLeft", StringParser.stringParser()) @@ -57,12 +56,6 @@ public class TestCommand extends BukkitCommandFeature { NamespacedKey namespacedKey = context.get("id"); ItemStack item = new ItemStack(Material.TRIDENT); item.editMeta((meta) -> { - PersistentDataContainer container = meta.getPersistentDataContainer(); - container.set(CustomTridentUtils.customTridentKey, PersistentDataType.STRING, namespacedKey.asString()); - container.set(CustomTridentUtils.interpolationDurationaKey, PersistentDataType.INTEGER, context.get("interpolationDuration")); - container.set(CustomTridentUtils.displayTypeKey, PersistentDataType.BYTE, context.get("displayType")); - container.set(CustomTridentUtils.translationKey, PersistentDataType.STRING, context.get("translation")); - container.set(CustomTridentUtils.rotationLeftKey, PersistentDataType.STRING, context.get("rotationLeft")); Item ceItem = BukkitItemManager.instance().createWrappedItem(Key.of(namespacedKey.asString()), null); Optional customModelData = ceItem.customModelData(); customModelData.ifPresent(meta::setCustomModelData); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 0ab795316..183b20b31 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -1621,7 +1621,7 @@ public class PacketConsumers { try { int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet); if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentPositionSync(event, packet, entityId); + event.replacePacket(CustomTridentUtils.buildCustomTridentPositionSync(packet, entityId)); return; } if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { @@ -2345,7 +2345,7 @@ public class PacketConsumers { try { int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); if (user.tridentView().containsKey(entityId)) { - CustomTridentUtils.modifyCustomTridentMove(packet); + event.replacePacket(CustomTridentUtils.buildCustomTridentMove(packet, entityId)); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket$PosRot", e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java index 5c4c270e2..7f87849de 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/CustomTridentUtils.java @@ -4,6 +4,8 @@ import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.network.NMSPacketEvent; +import net.momirealms.craftengine.core.entity.CustomTrident; +import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; @@ -12,74 +14,51 @@ import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MCUtils; import net.momirealms.craftengine.core.util.VersionHelper; -import org.bukkit.NamespacedKey; import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.Trident; import org.bukkit.inventory.ItemStack; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; -import org.joml.Quaternionf; -import org.joml.Vector3f; import javax.annotation.Nullable; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; +import java.util.UUID; import java.util.concurrent.TimeUnit; public class CustomTridentUtils { - public static final NamespacedKey customTridentKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")); - public static final NamespacedKey interpolationDurationaKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_duration")); - public static final NamespacedKey displayTypeKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:display_type")); - public static final NamespacedKey translationKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:translation")); - public static final NamespacedKey rotationLeftKey = Objects.requireNonNull(NamespacedKey.fromString("craftengine:rotation_left")); - public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) throws IllegalAccessException { + public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) { int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); Trident trident = getTridentById(user, entityId); if (trident == null) return; World world = trident.getWorld(); - Object serverEntity; Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(trident); - Object tracker = Reflections.field$Entity$trackedEntity.get(nmsEntity); - if (tracker != null) { - serverEntity = Reflections.field$ChunkMap$TrackedEntity$serverEntity.get(tracker); - } else { - serverEntity = null; - } + Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(nmsEntity); + Object serverEntity = FastNMS.INSTANCE.filed$ChunkMap$TrackedEntity$serverEntity(trackedEntity); if (notCustomTrident(trident)) return; - modifyCustomTridentPacket(packet); + Object newPacket = modifyCustomTridentPacket(packet, entityId); List itemDisplayValues = buildEntityDataValues(trident); user.tridentView().put(entityId, itemDisplayValues); - user.sendPacket(packet, true); + user.sendPacket(newPacket, true); user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true); event.setCancelled(true); if (serverEntity != null) { // 这里直接暴力更新 SchedulerTask task = CraftEngine.instance().scheduler().asyncRepeating(() -> { - try { - Reflections.method$ServerEntity$sendChanges.invoke(serverEntity); - if (!isInGround(nmsEntity)) { - world.spawnParticle(ParticleUtils.getParticle("BUBBLE"), trident.getLocation(), 1, 0, 0, 0, 0); - } - } catch (IllegalAccessException | InvocationTargetException e) { - CraftEngine.instance().logger().warn("Failed to send entity data packet", e); + FastNMS.INSTANCE.method$ServerEntity$sendChanges(serverEntity); + if (canSpawnParticle(nmsEntity)) { + world.spawnParticle(ParticleUtils.getParticle("BUBBLE"), trident.getLocation(), 1, 0, 0, 0, 0); } }, 0, 5, TimeUnit.MILLISECONDS); user.tridentTaskView().put(entityId, task); } } - private static boolean isInGround(Object nmsEntity) throws IllegalAccessException, InvocationTargetException { - if (!Reflections.field$Entity$wasTouchingWater.getBoolean(nmsEntity)) return true; - if (VersionHelper.isOrAbove1_21_2()) { - return (boolean) Reflections.method$AbstractArrow$isInGround.invoke(nmsEntity); - } else { - return Reflections.field$AbstractArrow$inGround.getBoolean(nmsEntity); - } + private static boolean canSpawnParticle(Object nmsEntity) { + if (!FastNMS.INSTANCE.field$AbstractArrow$wasTouchingWater(nmsEntity)) return false; + return !FastNMS.INSTANCE.method$AbstractArrow$isInGround(nmsEntity); } @Nullable @@ -92,62 +71,75 @@ public class CustomTridentUtils { public static boolean notCustomTrident(Trident trident) { if (trident == null) return true; - PersistentDataContainer container = trident.getItemStack().getItemMeta().getPersistentDataContainer(); - String customTrident = container.get(customTridentKey, PersistentDataType.STRING); - return customTrident == null; + Optional> customItem = BukkitItemManager.instance().wrap(trident.getItemStack()).getCustomItem(); + return customItem.map(itemStackCustomItem -> itemStackCustomItem.settings().customTrident() == null).orElse(true); } - public static void modifyCustomTridentPacket(Object packet) throws IllegalAccessException { - float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$yRot.getByte(packet)); - float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundAddEntityPacket$xRot.getByte(packet)); - Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY); - Reflections.field$ClientboundAddEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); - Reflections.field$ClientboundAddEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); + public static Object modifyCustomTridentPacket(Object packet, int entityId) { + UUID uuid = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$uuid(packet); + double x = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$x(packet); + double y = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$y(packet); + double z = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$z(packet); + float yRot = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$yRot(packet); + float xRot = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$xRot(packet); + Object type = Reflections.instance$EntityType$ITEM_DISPLAY; + int data = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$data(packet); + double xa = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$xa(packet); + double ya = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$ya(packet); + double za = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$za(packet); + double yHeadRot = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$yHeadRot(packet); + return FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId, uuid, x, y, z, + MCUtils.clamp(-xRot, -90.0F, 90.0F), -yRot, + type, data, FastNMS.INSTANCE.constructor$Vec3(xa, ya, za), yHeadRot + ); } public static List buildEntityDataValues(Trident trident) { List itemDisplayValues = new ArrayList<>(); ItemStack itemStack = trident.getItemStack(); - PersistentDataContainer container = itemStack.getItemMeta().getPersistentDataContainer(); - String customTrident = container.getOrDefault(customTridentKey, PersistentDataType.STRING, "craftengine:empty"); - Item item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null); + Optional> customItem = BukkitItemManager.instance().wrap(itemStack).getCustomItem(); + if (customItem.isEmpty()) return itemDisplayValues; + CustomTrident customTrident = customItem.get().settings().customTrident(); + Item item = BukkitItemManager.instance().createWrappedItem(customTrident.customTridentItemId(), null); itemStack.getEnchantments().forEach((enchantment, level) -> item.addEnchantment(new Enchantment(Key.of(enchantment.getKey().toString()), level))); - Integer interpolationDurationa = container.getOrDefault(interpolationDurationaKey, PersistentDataType.INTEGER, 2); - Byte displayType = container.getOrDefault(displayTypeKey, PersistentDataType.BYTE, (byte) 0); - String translation = container.getOrDefault(translationKey, PersistentDataType.STRING, "0+0+0"); - String[] translations = translation.split("\\+"); - String rotationLeft = container.getOrDefault(rotationLeftKey, PersistentDataType.STRING, "0+0+0+0"); - String[] rotationLefts = rotationLeft.split("\\+"); ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(-1, itemDisplayValues); - ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(new Vector3f(Float.parseFloat(translations[0]), Float.parseFloat(translations[1]), Float.parseFloat(translations[2])), itemDisplayValues); - ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(new Quaternionf(Float.parseFloat(rotationLefts[0]), Float.parseFloat(rotationLefts[1]), Float.parseFloat(rotationLefts[2]), Float.parseFloat(rotationLefts[3])), itemDisplayValues); + ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(customTrident.translation(), itemDisplayValues); + ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(customTrident.rotationLefts(), itemDisplayValues); if (VersionHelper.isOrAbove1_20_2()) { - ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(interpolationDurationa, itemDisplayValues); - ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(interpolationDurationa, itemDisplayValues); + ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues); + ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues); } else { - ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(interpolationDurationa, itemDisplayValues); + ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues); } ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues); - ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(displayType, itemDisplayValues); + ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(customTrident.displayType(), itemDisplayValues); return itemDisplayValues; } - public static void modifyCustomTridentPositionSync(NMSPacketEvent event, Object packet, int entityId) throws IllegalAccessException, InvocationTargetException, InstantiationException { - Object positionMoveRotation = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet); - boolean onGround = Reflections.field$ClientboundEntityPositionSyncPacket$onGround.getBoolean(packet); - Object position = Reflections.field$PositionMoveRotation$position.get(positionMoveRotation); - Object deltaMovement = Reflections.field$PositionMoveRotation$deltaMovement.get(positionMoveRotation); - float yRot = Reflections.field$PositionMoveRotation$yRot.getFloat(positionMoveRotation); - float xRot = Reflections.field$PositionMoveRotation$xRot.getFloat(positionMoveRotation); - Object newPositionMoveRotation = Reflections.constructor$PositionMoveRotation.newInstance(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F)); - event.replacePacket(Reflections.constructor$ClientboundEntityPositionSyncPacket.newInstance(entityId, newPositionMoveRotation, onGround)); + public static Object buildCustomTridentPositionSync(Object packet, int entityId) { + Object positionMoveRotation = FastNMS.INSTANCE.field$ClientboundEntityPositionSyncPacket$values(packet); + boolean onGround = FastNMS.INSTANCE.field$ClientboundEntityPositionSyncPacket$onGround(packet); + Object position = FastNMS.INSTANCE.field$PositionMoveRotation$position(positionMoveRotation); + Object deltaMovement = FastNMS.INSTANCE.field$PositionMoveRotation$deltaMovement(positionMoveRotation); + float yRot = FastNMS.INSTANCE.field$PositionMoveRotation$yRot(positionMoveRotation); + float xRot = FastNMS.INSTANCE.field$PositionMoveRotation$xRot(positionMoveRotation); + Object newPositionMoveRotation = FastNMS.INSTANCE.constructor$PositionMoveRotation(position, deltaMovement, -yRot, Math.clamp(-xRot, -90.0F, 90.0F)); + return FastNMS.INSTANCE.constructor$ClientboundEntityPositionSyncPacket(entityId, newPositionMoveRotation, onGround); } - public static void modifyCustomTridentMove(Object packet) throws IllegalAccessException { - float xRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$xRot.getByte(packet)); - float yRot = MCUtils.unpackDegrees(Reflections.field$ClientboundMoveEntityPacket$yRot.getByte(packet)); - Reflections.field$ClientboundMoveEntityPacket$xRot.setByte(packet, MCUtils.packDegrees(Math.clamp(-xRot, -90.0F, 90.0F))); - Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot)); + public static Object buildCustomTridentMove(Object packet, int entityId) { + short xa = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$xa(packet); + short ya = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$ya(packet); + short za = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$za(packet); + float xRot = MCUtils.unpackDegrees(FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$xRot(packet)); + float yRot = MCUtils.unpackDegrees(FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$yRot(packet)); + boolean onGround = FastNMS.INSTANCE.field$ClientboundMoveEntityPacket$onGround(packet); + return FastNMS.INSTANCE.constructor$ClientboundMoveEntityPacket$PosRot( + entityId, xa, ya, za, + MCUtils.packDegrees(-yRot), MCUtils.packDegrees(MCUtils.clamp(-xRot, -90.0F, 90.0F)), + onGround + ); } public static List buildCustomTridentSetEntityDataPacket(NetWorkUser user, List packedItems, int entityId) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index d71b22597..035a3e303 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -6632,130 +6632,4 @@ public class Reflections { ) ); - public static final Field field$ClientboundSetEntityDataPacket$id = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ClientboundSetEntityDataPacket, int.class, 0 - ) - ); - - public static final Class clazz$PositionMoveRotation = - ReflectionUtils.getClazz( - BukkitReflectionUtils.assembleMCClass("world.entity.PositionMoveRotation") - ); - - public static final Constructor constructor$PositionMoveRotation = Optional.ofNullable(clazz$PositionMoveRotation) - .map(ReflectionUtils::getTheOnlyConstructor) - .orElse(null); - - public static final Field field$ClientboundEntityPositionSyncPacket$values = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) - .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$PositionMoveRotation, 0)) - .orElse(null); - - public static final Field field$ClientboundEntityPositionSyncPacket$onGround = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) - .map(it -> ReflectionUtils.getInstanceDeclaredField(it, boolean.class, 0)) - .orElse(null); - - public static final Field field$PositionMoveRotation$position = Optional.ofNullable(clazz$PositionMoveRotation) - .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$Vec3, 0)) - .orElse(null); - - public static final Field field$PositionMoveRotation$deltaMovement = Optional.ofNullable(clazz$PositionMoveRotation) - .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$Vec3, 1)) - .orElse(null); - - public static final Field field$PositionMoveRotation$yRot = Optional.ofNullable(clazz$PositionMoveRotation) - .map(it -> ReflectionUtils.getInstanceDeclaredField(it, float.class, 0)) - .orElse(null); - - public static final Field field$PositionMoveRotation$xRot = Optional.ofNullable(clazz$PositionMoveRotation) - .map(it -> ReflectionUtils.getInstanceDeclaredField(it, float.class, 1)) - .orElse(null); - - public static final Constructor constructor$ClientboundEntityPositionSyncPacket = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket) - .map(ReflectionUtils::getTheOnlyConstructor) - .orElse(null); - - public static final Field field$ClientboundAddEntityPacket$xRot = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ClientboundAddEntityPacket, byte.class, 0 - ) - ); - - public static final Field field$ClientboundAddEntityPacket$yRot = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ClientboundAddEntityPacket, byte.class, 1 - ) - ); - - public static final Field field$ClientboundMoveEntityPacket$xRot = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ClientboundMoveEntityPacket, byte.class, 1 - ) - ); - - public static final Field field$ClientboundMoveEntityPacket$yRot = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ClientboundMoveEntityPacket, byte.class, 0 - ) - ); - - public static final Class clazz$ServerEntity = requireNonNull( - BukkitReflectionUtils.findReobfOrMojmapClass( - "server.level.EntityTrackerEntry", - "server.level.ServerEntity" - ) - ); - - public static final Method method$ServerEntity$sendChanges = requireNonNull( - ReflectionUtils.getMethod( - clazz$ServerEntity, void.class, new String[]{ "sendChanges", "a" } - ) - ); - - public static final Class clazz$ChunkMap$TrackedEntity = requireNonNull( - BukkitReflectionUtils.findReobfOrMojmapClass( - "server.level.PlayerChunkMap$EntityTracker", - "server.level.ChunkMap$TrackedEntity" - ) - ); - - public static final Field field$Entity$trackedEntity = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$Entity, clazz$ChunkMap$TrackedEntity, 0 - ) - ); - - public static final Field field$ChunkMap$TrackedEntity$serverEntity = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ChunkMap$TrackedEntity, clazz$ServerEntity, 0 - ) - ); - - public static final Field field$Entity$wasTouchingWater = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$Entity, VersionHelper.isOrAbove1_21_2() - ? new String[]{ "wasTouchingWater", "ag" } : VersionHelper.isOrAbove1_20_5() - ? new String[]{ "wasTouchingWater", "aj" } : VersionHelper.isOrAbove1_20_2() - ? new String[]{ "wasTouchingWater", "ai" } : new String[]{ "wasTouchingWater", "ah" } - ) - ); - - public static final Class clazz$AbstractArrow = requireNonNull( - BukkitReflectionUtils.findReobfOrMojmapClass( - "world.entity.projectile.EntityArrow", - "world.entity.projectile.AbstractArrow" - ) - ); - - // 1.20~1.21.1 - public static final Field field$AbstractArrow$inGround = - ReflectionUtils.getDeclaredField( - clazz$AbstractArrow, boolean.class, 0 - ); - - // 1.21.2+ - public static final Method method$AbstractArrow$isInGround = - ReflectionUtils.getMethod( - clazz$AbstractArrow, boolean.class, VersionHelper.isOrAbove1_21_5() ? new String[]{ "isInGround", "e" } : new String[]{ "isInGround", "l" } - ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/CustomTrident.java b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomTrident.java new file mode 100644 index 000000000..aed870c82 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomTrident.java @@ -0,0 +1,8 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.util.Key; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +public record CustomTrident(Key customTridentItemId, Byte displayType, Vector3f translation, Quaternionf rotationLefts) { +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java index 59d8a06a4..d9968d902 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.item; +import net.momirealms.craftengine.core.entity.CustomTrident; import net.momirealms.craftengine.core.item.modifier.EquippableModifier; import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.pack.misc.EquipmentGeneration; @@ -9,6 +10,8 @@ import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.VersionHelper; import org.jetbrains.annotations.Nullable; +import org.joml.Quaternionf; +import org.joml.Vector3f; import java.util.*; import java.util.stream.Collectors; @@ -22,6 +25,7 @@ public class ItemSettings { List anvilRepairItems = List.of(); boolean renameable = true; boolean canPlaceRelatedVanillaBlock = false; + CustomTrident customTrident; private ItemSettings() {} @@ -50,6 +54,7 @@ public class ItemSettings { newSettings.anvilRepairItems = settings.anvilRepairItems; newSettings.renameable = settings.renameable; newSettings.canPlaceRelatedVanillaBlock = settings.canPlaceRelatedVanillaBlock; + newSettings.customTrident = settings.customTrident; return newSettings; } @@ -65,6 +70,10 @@ public class ItemSettings { return settings; } + public CustomTrident customTrident() { + return customTrident; + } + public boolean canPlaceRelatedVanillaBlock() { return canPlaceRelatedVanillaBlock; } @@ -109,6 +118,11 @@ public class ItemSettings { return this; } + public ItemSettings customTrident(CustomTrident customTrident) { + this.customTrident = customTrident; + return this; + } + public ItemSettings canPlaceRelatedVanillaBlock(boolean canPlaceRelatedVanillaBlock) { this.canPlaceRelatedVanillaBlock = canPlaceRelatedVanillaBlock; return this; @@ -193,6 +207,14 @@ public class ItemSettings { boolean bool = (boolean) value; return settings -> settings.canPlaceRelatedVanillaBlock(bool); })); + registerFactory("custom-trident", (value -> { + Map args = MiscUtils.castToMap(value, false); + Key customTridentItemId = Key.of(args.get("custom-trident-item").toString()); + Byte displayType = Byte.valueOf(args.get("display-type").toString()); + Vector3f translation = MiscUtils.getAsVector3f(args.get("translation"), "translation"); + Quaternionf rotationLefts = MiscUtils.getAsQuaternionf(args.get("rotation-left"), "rotation-left"); + return settings -> settings.customTrident(new CustomTrident(customTridentItemId, displayType, translation, rotationLefts)); + })); } private static void registerFactory(String id, ItemSettings.Modifier.Factory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java index 86f2093ca..ed472a652 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java @@ -197,4 +197,16 @@ public class MCUtils { public static float unpackDegrees(byte degrees) { return (float)(degrees * 360) / 256.0F; } + + public static int clamp(int value, int min, int max) { + return Math.min(Math.max(value, min), max); + } + + public static float clamp(float value, float min, float max) { + return value < min ? min : Math.min(value, max); + } + + public static double clamp(double value, double min, double max) { + return value < min ? min : Math.min(value, max); + } } diff --git a/gradle.properties b/gradle.properties index ccae7e353..9acb04c0c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -50,7 +50,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.15 -nms_helper_version=0.65.15 +nms_helper_version=0.65.17 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23