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();