mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-04 15:41:38 +00:00
@@ -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() {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user