9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2026-01-04 15:41:38 +00:00

Merge pull request #445 from jhqwqmc/dev

修复tag包
This commit is contained in:
XiaoMoMi
2025-11-07 20:50:04 +08:00
committed by GitHub
4 changed files with 66 additions and 12 deletions

View File

@@ -59,7 +59,7 @@ public final class BukkitBlockManager extends AbstractBlockManager {
private Map<Integer, List<String>> clientBoundTags = Map.of();
private Map<Integer, List<String>> previousClientBoundTags = Map.of();
// 缓存的原版方块tag包
private Object cachedUpdateTagsPacket;
private List<TagUtils.TagEntry> cachedUpdateTags = List.of();
// 被移除声音的原版方块
private Set<Object> missingPlaceSounds = Set.of();
private Set<Object> missingBreakSounds = Set.of();
@@ -157,16 +157,11 @@ public final class BukkitBlockManager extends AbstractBlockManager {
for (Map.Entry<Integer, List<String>> entry : this.clientBoundTags.entrySet()) {
list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue()));
}
this.cachedUpdateTags = 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 List<TagUtils.TagEntry> cachedUpdateTags() {
return this.cachedUpdateTags;
}
public VisualBlockStatePacket cachedVisualBlockStatePacket() {

View File

@@ -1857,11 +1857,20 @@ 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);
List<TagUtils.TagEntry> cachedUpdateTags = BukkitBlockManager.instance().cachedUpdateTags();
if (cachedUpdateTags.isEmpty()) return;
Map<Object, Object> tags;
try {
tags = (Map<Object, Object>) 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(Map.of(MRegistries.BLOCK, cachedUpdateTags), tags));
}
}

View File

@@ -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
)
);
}

View File

@@ -86,4 +86,48 @@ public final class TagUtils {
public record TagEntry(int id, List<String> tags) {
}
public static Object createUpdateTagsPacket(Map<Object, List<TagEntry>> tags, Map<Object, Object> existingTags) {
Map<Object, Object> modified = new HashMap<>();
for (Map.Entry<Object, Object> payload : existingTags.entrySet()) {
List<TagEntry> 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<String, IntList> originalTags = deserializeBuf.readMap(
FriendlyByteBuf::readUtf,
FriendlyByteBuf::readIntIdList
);
Map<Integer, List<String>> reversedTags = new HashMap<>();
for (Map.Entry<String, IntList> 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<String, IntList> processedTags = new HashMap<>();
for (Map.Entry<Integer, List<String>> 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);
}
}