From 58843ecb67421c15ceb4343b20fe0e2e3fd6059a Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Fri, 7 Nov 2025 20:38:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtag=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/block/BukkitBlockManager.java | 13 ++---- .../plugin/network/BukkitNetworkManager.java | 13 ++++-- .../minecraft/NetworkReflections.java | 6 +++ .../craftengine/bukkit/util/TagUtils.java | 44 +++++++++++++++++++ 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index b650e0a57..afde7e0f4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -59,7 +59,7 @@ public final class BukkitBlockManager extends AbstractBlockManager { private Map> clientBoundTags = Map.of(); private Map> previousClientBoundTags = Map.of(); // 缓存的原版方块tag包 - private Object cachedUpdateTagsPacket; + private Map> cachedUpdateTags; // 被移除声音的原版方块 private Set missingPlaceSounds = Set.of(); private Set missingBreakSounds = Set.of(); @@ -157,16 +157,11 @@ public final class BukkitBlockManager extends AbstractBlockManager { for (Map.Entry> entry : this.clientBoundTags.entrySet()) { list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue())); } + this.cachedUpdateTags = Map.of(MRegistries.BLOCK, list); Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.BLOCK, list)); for (BukkitServerPlayer player : this.plugin.networkManager().onlineUsers()) { player.sendPacket(packet, false); } - // 如果空,那么新来的玩家就没必要收到更新包了 - if (list.isEmpty()) { - this.cachedUpdateTagsPacket = null; - } else { - this.cachedUpdateTagsPacket = packet; - } } @Nullable @@ -364,8 +359,8 @@ public final class BukkitBlockManager extends AbstractBlockManager { } } - public Object cachedUpdateTagsPacket() { - return this.cachedUpdateTagsPacket; + public Map> cachedUpdateTags() { + return this.cachedUpdateTags; } public VisualBlockStatePacket cachedVisualBlockStatePacket() { 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 f7a0ec525..4b6e39545 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 @@ -1857,11 +1857,18 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes public static class UpdateTagsListener implements NMSPacketListener { + @SuppressWarnings("unchecked") @Override public void onPacketSend(NetWorkUser user, NMSPacketEvent event, Object packet) { - Object modifiedPacket = BukkitBlockManager.instance().cachedUpdateTagsPacket(); - if (packet.equals(modifiedPacket) || modifiedPacket == null) return; - event.replacePacket(modifiedPacket); + Map tags; + try { + tags = (Map) NetworkReflections.field$ClientboundUpdateTagsPacket$tags.get(packet); + } catch (Throwable e) { + CraftEngine.instance().logger().warn("Failed to get tags from ClientboundUpdateTagsPacket", e); + return; + } + if (tags.get(MRegistries.BLOCK) == null) return; + event.replacePacket(TagUtils.createUpdateTagsPacket(BukkitBlockManager.instance().cachedUpdateTags(), tags)); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java index 567234cb1..f5b1e4ee9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java @@ -1720,4 +1720,10 @@ public final class NetworkReflections { "network.protocol.game.ClientboundBlockEntityDataPacket" ) ); + + public static final Field field$ClientboundUpdateTagsPacket$tags = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ClientboundUpdateTagsPacket, Map.class, 0 + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java index 530ccc248..51e2887d6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/TagUtils.java @@ -86,4 +86,48 @@ public final class TagUtils { public record TagEntry(int id, List tags) { } + + + public static Object createUpdateTagsPacket(Map> tags, Map existingTags) { + Map modified = new HashMap<>(); + for (Map.Entry payload : existingTags.entrySet()) { + List overrides = tags.get(payload.getKey()); + if (overrides == null || overrides.isEmpty()) { + modified.put(payload.getKey(), payload.getValue()); + continue; + } + FriendlyByteBuf deserializeBuf = new FriendlyByteBuf(Unpooled.buffer()); + FastNMS.INSTANCE.method$TagNetworkSerialization$NetworkPayload$write(payload.getValue(), deserializeBuf); + Map originalTags = deserializeBuf.readMap( + FriendlyByteBuf::readUtf, + FriendlyByteBuf::readIntIdList + ); + Map> reversedTags = new HashMap<>(); + for (Map.Entry tagEntry : originalTags.entrySet()) { + for (int id : tagEntry.getValue()) { + reversedTags.computeIfAbsent(id, k -> new ArrayList<>()).add(tagEntry.getKey()); + } + } + for (TagEntry tagEntry : overrides) { + reversedTags.remove(tagEntry.id); + for (String tag : tagEntry.tags) { + reversedTags.computeIfAbsent(tagEntry.id, k -> new ArrayList<>()).add(tag); + } + } + Map processedTags = new HashMap<>(); + for (Map.Entry> tagEntry : reversedTags.entrySet()) { + for (String tag : tagEntry.getValue()) { + processedTags.computeIfAbsent(tag, k -> new IntArrayList()).addLast(tagEntry.getKey()); + } + } + FriendlyByteBuf serializeBuf = new FriendlyByteBuf(Unpooled.buffer()); + serializeBuf.writeMap(processedTags, + FriendlyByteBuf::writeUtf, + FriendlyByteBuf::writeIntIdList + ); + Object mergedPayload = FastNMS.INSTANCE.method$TagNetworkSerialization$NetworkPayload$read(serializeBuf); + modified.put(payload.getKey(), mergedPayload); + } + return FastNMS.INSTANCE.constructor$ClientboundUpdateTagsPacket(modified); + } }