From 593f3021a7c091be1caafc3310f01f744ffdae2e Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sun, 11 May 2025 00:49:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=BC=B9=E5=B0=84=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../furniture/BukkitFurnitureElement.java | 2 +- .../projectile/BukkitProjectileManager.java | 65 +++++++++++++++++-- .../bukkit/item/ItemEventListener.java | 4 -- .../plugin/network/BukkitNetworkManager.java | 4 +- .../plugin/network/PacketConsumers.java | 29 +++++---- .../handler/ProjectilePacketHandler.java | 52 ++++++--------- .../craftengine/bukkit/util/Reflections.java | 11 ++++ .../craftengine/core/item/ItemSettings.java | 2 +- 8 files changed, 109 insertions(+), 60 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java index ec41936ac..044034209 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java @@ -4,9 +4,9 @@ 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.util.Reflections; -import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement; import net.momirealms.craftengine.core.entity.Billboard; import net.momirealms.craftengine.core.entity.ItemDisplayContext; +import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.Key; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java index 371a024c6..6e1d51452 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java @@ -1,25 +1,31 @@ package net.momirealms.craftengine.bukkit.entity.projectile; +import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.entity.projectile.CustomProjectile; import net.momirealms.craftengine.core.entity.projectile.ProjectileManager; import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.Bukkit; import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; import org.bukkit.entity.Projectile; import org.bukkit.entity.ThrowableProjectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; +import org.bukkit.event.world.EntitiesLoadEvent; import org.bukkit.inventory.ItemStack; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; public class BukkitProjectileManager implements Listener, ProjectileManager { private static BukkitProjectileManager instance; @@ -50,6 +56,24 @@ public class BukkitProjectileManager implements Listener, ProjectileManager { @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onProjectileLaunch(ProjectileLaunchEvent event) { Projectile projectile = event.getEntity(); + handleProjectileLoad(projectile, true); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onEntitiesLoad(EntitiesLoadEvent event) { + for (Entity entity : event.getEntities()) { + if (entity instanceof Projectile projectile) { + handleProjectileLoad(projectile, false); + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) + public void onEntityRemove(EntityRemoveFromWorldEvent event) { + this.projectiles.remove(event.getEntity().getEntityId()); + } + + private void handleProjectileLoad(Projectile projectile, boolean delay) { ItemStack projectileItem; if (projectile instanceof ThrowableProjectile throwableProjectile) { projectileItem = throwableProjectile.getItem(); @@ -58,21 +82,50 @@ public class BukkitProjectileManager implements Listener, ProjectileManager { } else { return; } - System.out.println("发射"); Item wrapped = this.plugin.itemManager().wrap(projectileItem); if (wrapped == null) return; wrapped.getCustomItem().ifPresent(it -> { ProjectileMeta meta = it.settings().projectileMeta(); if (meta != null) { - System.out.println("来啦"); this.projectiles.put(projectile.getEntityId(), new BukkitCustomProjectile(meta, projectile, wrapped)); + ProjectileInjectTask task = new ProjectileInjectTask(projectile); + if (!delay) { + task.run(); + } else if (VersionHelper.isFolia()) { + projectile.getScheduler().run(plugin.bootstrap(), (t) -> task.run(), () -> {}); + } else { + plugin.scheduler().sync().runDelayed(task); + } } }); } - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) - public void onEntityRemove(EntityRemoveEvent event) { - this.projectiles.remove(event.getEntity().getEntityId()); + public class ProjectileInjectTask implements Runnable { + private final Projectile projectile; + + public ProjectileInjectTask(Projectile projectile) { + this.projectile = projectile; + } + + @Override + public void run() { + Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(this.projectile); + Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(nmsEntity); + if (trackedEntity == null) { + plugin.logger().warn("Failed to update server entity tracking interval due to missing tracked entity"); + return; + } + Object serverEntity = FastNMS.INSTANCE.filed$ChunkMap$TrackedEntity$serverEntity(trackedEntity); + if (serverEntity == null) { + plugin.logger().warn("Failed to update server entity tracking interval due to missing server entity"); + return; + } + try { + Reflections.field$ServerEntity$updateInterval.set(serverEntity, 1); + } catch (ReflectiveOperationException e) { + plugin.logger().warn("Failed to update server entity tracking interval", e); + } + } } public static BukkitProjectileManager instance() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java index 461ab6689..bc5e9772f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java @@ -23,16 +23,12 @@ import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; -import org.bukkit.entity.Arrow; import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; -import org.bukkit.entity.ThrowableProjectile; import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; -import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; 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 cf568a561..d5998aed6 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 @@ -139,7 +139,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(PacketConsumers.RESPAWN, Reflections.clazz$ClientboundRespawnPacket); registerNMSPacketConsumer(PacketConsumers.INTERACT_ENTITY, Reflections.clazz$ServerboundInteractPacket); registerNMSPacketConsumer(PacketConsumers.SYNC_ENTITY_POSITION, Reflections.clazz$ClientboundEntityPositionSyncPacket); - registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$Pos); + registerNMSPacketConsumer(PacketConsumers.MOVE_POS_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$Pos); registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, Reflections.clazz$ServerboundPickItemFromEntityPacket); registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, Reflections.clazz$ServerboundRenameItemPacket); registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket); @@ -150,7 +150,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.MOVE_AND_ROTATE_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$PosRot); + registerNMSPacketConsumer(PacketConsumers.MOVE_POS_AND_ROTATE_ENTITY, 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 fa78617ab..dd0c37492 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 @@ -1611,8 +1611,9 @@ public class PacketConsumers { } } else { BukkitProjectileManager.instance().projectileByEntityId(entityId).ifPresent(customProjectile -> { - event.replacePacket(ProjectilePacketHandler.convertAddCustomProjectPacket(packet)); - user.entityPacketHandlers().put(entityId, new ProjectilePacketHandler(customProjectile)); + ProjectilePacketHandler handler = new ProjectilePacketHandler(customProjectile, entityId); + event.replacePacket(handler.convertAddCustomProjectilePacket(packet)); + user.entityPacketHandlers().put(entityId, handler); }); } } catch (Exception e) { @@ -1633,17 +1634,6 @@ public class PacketConsumers { } }; - public static final TriConsumer MOVE_ENTITY = (user, event, packet) -> { - try { - int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); - if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { - event.setCancelled(true); - } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket$Pos", e); - } - }; - public static final BiConsumer REMOVE_ENTITY = (user, event) -> { try { FriendlyByteBuf buf = event.getBuffer(); @@ -2215,7 +2205,18 @@ public class PacketConsumers { } }; - public static final TriConsumer MOVE_AND_ROTATE_ENTITY = (user, event, packet) -> { + public static final TriConsumer MOVE_POS_ENTITY = (user, event, packet) -> { + try { + int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); + if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) { + event.setCancelled(true); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket", e); + } + }; + + public static final TriConsumer MOVE_POS_AND_ROTATE_ENTITY = (user, event, packet) -> { try { int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); EntityPacketHandler handler = user.entityPacketHandlers().get(entityId); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java index 329ea6019..b5f5d1cc4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java @@ -26,22 +26,24 @@ import java.util.UUID; public class ProjectilePacketHandler implements EntityPacketHandler { private final CustomProjectile projectile; + private final Object cachedPacket; + private final List cachedData; - public ProjectilePacketHandler(CustomProjectile projectile) { + public ProjectilePacketHandler(CustomProjectile projectile, int entityId) { this.projectile = projectile; + this.cachedData = createCustomProjectileEntityDataValues(); + this.cachedPacket = FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, this.cachedData); } @Override public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) { FriendlyByteBuf buf = event.getBuffer(); int id = buf.readVarInt(); - List packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); - List newPackedItems = convertCustomProjectileSetEntityDataPacket(packedItems); event.setChanged(true); buf.clear(); buf.writeVarInt(event.packetID()); buf.writeVarInt(id); - FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(newPackedItems, buf); + FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(this.cachedData, buf); } @Override @@ -52,11 +54,15 @@ public class ProjectilePacketHandler implements EntityPacketHandler { @Override public void handleMoveAndRotate(NetWorkUser user, NMSPacketEvent event, Object packet) { - Object converted = convertCustomProjectileMovePacket(packet); - event.replacePacket(converted); + int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); + Object converted = convertCustomProjectileMovePacket(packet, entityId); + event.replacePacket(FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of( + this.cachedPacket, + converted + ))); } - public static Object convertAddCustomProjectPacket(Object packet) { + public Object convertAddCustomProjectilePacket(Object packet) { int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet); UUID uuid = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$uuid(packet); double x = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$x(packet); @@ -70,11 +76,7 @@ public class ProjectilePacketHandler implements EntityPacketHandler { 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 - ); + 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); } private Object convertCustomProjectilePositionSyncPacket(Object packet) { @@ -89,24 +91,11 @@ public class ProjectilePacketHandler implements EntityPacketHandler { return FastNMS.INSTANCE.constructor$ClientboundEntityPositionSyncPacket(entityId, newPositionMoveRotation, onGround); } - // 将原有的投掷物的entity data转化为展示实体的数据包 - public List convertCustomProjectileSetEntityDataPacket(List packedItems) { - List newPackedItems = new ArrayList<>(); - for (Object packedItem : packedItems) { - int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); - if (entityDataId < 8) { - newPackedItems.add(packedItem); - } - } - newPackedItems.addAll(createCustomProjectileEntityDataValues()); - return newPackedItems; - } - - private List createCustomProjectileEntityDataValues() { + public List createCustomProjectileEntityDataValues() { List itemDisplayValues = new ArrayList<>(); Optional> customItem = BukkitItemManager.instance().getCustomItem(this.projectile.metadata().item()); if (customItem.isEmpty()) return itemDisplayValues; - ProjectileMeta meta = projectile.metadata(); + ProjectileMeta meta = this.projectile.metadata(); Item displayedItem = customItem.get().buildItem(ItemBuildContext.EMPTY); // 我们应当使用新的展示物品的组件覆盖原物品的组件,以完成附魔,附魔光效等组件的继承 displayedItem = this.projectile.item().mergeCopy(displayedItem); @@ -114,18 +103,17 @@ public class ProjectilePacketHandler implements EntityPacketHandler { ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(meta.translation(), itemDisplayValues); ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(meta.rotation(), itemDisplayValues); if (VersionHelper.isOrAbove1_20_2()) { - ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues); - ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues); + ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(1, itemDisplayValues); + ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(1, itemDisplayValues); } else { - ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(2, itemDisplayValues); + ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(1, itemDisplayValues); } ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(displayedItem.getLiteralObject(), itemDisplayValues); ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(meta.displayType().id(), itemDisplayValues); return itemDisplayValues; } - private static Object convertCustomProjectileMovePacket(Object packet) { - int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet); + private Object convertCustomProjectileMovePacket(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); 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 1ab0294db..4e5515cd3 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 @@ -6634,4 +6634,15 @@ public class Reflections { ) ); + public static final Class clazz$ServerEntity = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "server.level.EntityTrackerEntry", + "server.level.ServerEntity") + ); + + public static final Field field$ServerEntity$updateInterval = requireNonNull( + ReflectionUtils.getInstanceDeclaredField( + clazz$ServerEntity, int.class, 0 + ) + ); } 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 3b9a5bc07..ff5b725e8 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,7 +1,7 @@ package net.momirealms.craftengine.core.item; -import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta; import net.momirealms.craftengine.core.entity.ItemDisplayContext; +import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta; import net.momirealms.craftengine.core.item.modifier.EquippableModifier; import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.pack.misc.EquipmentGeneration;