diff --git a/bukkit/compatibility/build.gradle.kts b/bukkit/compatibility/build.gradle.kts index 171607a61..05d1dc29f 100644 --- a/bukkit/compatibility/build.gradle.kts +++ b/bukkit/compatibility/build.gradle.kts @@ -8,6 +8,7 @@ repositories { maven("https://repo.infernalsuite.com/repository/maven-snapshots/") // slime world maven("https://repo.momirealms.net/releases/") maven("https://mvn.lumine.io/repository/maven-public/") // model engine + maven("https://nexus.phoenixdevt.fr/repository/maven-public/") // mmoitems } dependencies { @@ -28,6 +29,9 @@ dependencies { compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.8") // BetterModels compileOnly("io.github.toxicity188:BetterModel:1.4.2") + // MMOItems + compileOnly("net.Indyuce:MMOItems-API:6.10-SNAPSHOT") + compileOnly("io.lumine:MythicLib-dist:1.6.2-SNAPSHOT") } java { diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java new file mode 100644 index 000000000..a22ade2d0 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java @@ -0,0 +1,28 @@ +package net.momirealms.craftengine.bukkit.compatibility.item; + +import net.Indyuce.mmoitems.MMOItems; +import net.Indyuce.mmoitems.api.Type; +import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; +import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ItemBuildContext; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; + +import static java.util.Objects.requireNonNull; + +public class MMOItemsProvider implements ExternalItemProvider { + @Override + public String plugin() { + return "MMOItems"; + } + + @Override + public @Nullable ItemStack build(String id, ItemBuildContext context) { + String[] split = id.split(":", 2); + MMOItem mmoItem = MMOItems.plugin.getMMOItem(Type.get(split[0]), split[1].toUpperCase(Locale.ENGLISH)); + return mmoItem == null ? new ItemStack(Material.AIR) : requireNonNull(mmoItem.newBuilder().build()); + } +} diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index add64ec6f..79c9af030 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -160,9 +160,10 @@ image: title: true bossbar: true container: true - # TODO: toast: true - # TODO: name: true - # TODO: team: true + team: true + scoreboard: true + entity-name: false + text-display: true emoji: {} diff --git a/bukkit/loader/src/main/resources/craft-engine.properties b/bukkit/loader/src/main/resources/craft-engine.properties index 01e0b0244..96d51b50e 100644 --- a/bukkit/loader/src/main/resources/craft-engine.properties +++ b/bukkit/loader/src/main/resources/craft-engine.properties @@ -25,6 +25,7 @@ snake-yaml=${snake_yaml_version} adventure-text-minimessage=${adventure_bundle_version} adventure-text-serializer-gson=${adventure_bundle_version} adventure-text-serializer-json=${adventure_bundle_version} +adventure-text-serializer-json-legacy-impl=${adventure_bundle_version} netty-codec-http=${netty_version} ahocorasick=${ahocorasick_version} lz4=${lz4_version} \ No newline at end of file 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 d0f1c9975..bf9365b43 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 @@ -114,6 +114,7 @@ public class BukkitBlockManager extends AbstractBlockManager { this.stateId2ImmutableBlockStates = new ImmutableBlockState[customBlockCount]; Arrays.fill(this.stateId2ImmutableBlockStates, EmptyBlock.INSTANCE.defaultState()); instance = this; + this.resetPacketConsumers(); } public static BukkitBlockManager instance() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java index 979d8aff0..4dd7721ce 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java @@ -158,7 +158,7 @@ public class CropBlockBehavior extends BushBlockBehavior { } FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); if (sendParticles) { - world.spawnParticle(ParticleUtils.getParticle("HAPPY_VILLAGER"), x + 0.5, y + 0.5, z + 0.5, 12, 0.25, 0.25, 0.25); + world.spawnParticle(ParticleUtils.getParticle("HAPPY_VILLAGER"), x + 0.5, y + 0.5, z + 0.5, 15, 0.25, 0.25, 0.25); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java index e985c3d24..5bfeab461 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java @@ -120,7 +120,7 @@ public class SaplingBlockBehavior extends BushBlockBehavior { int x = FastNMS.INSTANCE.field$Vec3i$x(blockPos); int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos); int z = FastNMS.INSTANCE.field$Vec3i$z(blockPos); - world.spawnParticle(ParticleUtils.getParticle("HAPPY_VILLAGER"), x + 0.5, y + 0.5, z + 0.5, 12, 0.25, 0.25, 0.25); + world.spawnParticle(ParticleUtils.getParticle("HAPPY_VILLAGER"), x + 0.5, y + 0.5, z + 0.5, 15, 0.25, 0.25, 0.25); } return success; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index 9fd2c4f8f..25d4bd735 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -217,6 +217,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { for (Entity entity : entities) { if (entity instanceof ItemDisplay display) { handleBaseEntityLoadEarly(display); + } else if (entity instanceof Shulker shulker) { + handleCollisionEntityLoadOnEntitiesLoad(shulker); } } } @@ -366,10 +368,19 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } public void handleCollisionEntityLoadOnEntitiesLoad(Shulker shulker) { - // remove the shulker if it's on chunk load stage + // faster if (FastNMS.INSTANCE.method$CraftEntity$getHandle(shulker) instanceof CollisionEntity) { shulker.remove(); + return; } + + // not a collision entity + Byte flag = shulker.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE); + if (flag == null || flag != 1) { + return; + } + + shulker.remove(); } private AnchorType getAnchorType(Entity baseEntity, CustomFurniture furniture) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java index 18bfa8e42..fab4d3059 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java @@ -45,6 +45,8 @@ public class FurnitureEventListener implements Listener { for (Entity entity : entities) { if (entity instanceof ItemDisplay itemDisplay) { this.manager.handleBaseEntityLoadEarly(itemDisplay); + } else if (entity instanceof Shulker shulker) { + this.manager.handleCollisionEntityLoadOnEntitiesLoad(shulker); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index 422013f93..ab17f6790 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.item; +import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsProvider; import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider; import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior; import net.momirealms.craftengine.bukkit.item.behavior.BoneMealItemBehavior; @@ -89,6 +90,9 @@ public class BukkitItemManager extends AbstractItemManager { if (this.plugin.isPluginEnabled("NeigeItems")) { registerExternalItemProvider(new NeigeItemsProvider()); } + if (this.plugin.isPluginEnabled("MMOItems")) { + registerExternalItemProvider(new MMOItemsProvider()); + } } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 0b7a822c2..834abb7b1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; -import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; @@ -9,7 +8,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.Shulker; -import org.bukkit.persistence.PersistentDataType; import org.incendo.cloud.Command; import java.util.Collection; 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 4fa682f7d..e43ab1555 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 @@ -8,7 +8,8 @@ import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.plugin.network.impl.*; +import net.momirealms.craftengine.bukkit.plugin.network.impl.PacketIds1_20; +import net.momirealms.craftengine.bukkit.plugin.network.impl.PacketIds1_20_5; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.plugin.CraftEngine; @@ -117,14 +118,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes } private PacketIds setupPacketIds() { - if (VersionHelper.isVersionNewerThan1_21()) { - return new PacketIds1_21(); - } else if (VersionHelper.isVersionNewerThan1_20_5()) { + if (VersionHelper.isVersionNewerThan1_20_5()) { return new PacketIds1_20_5(); - } else if (VersionHelper.isVersionNewerThan1_20_3()) { - return new PacketIds1_20_3(); - } else if (VersionHelper.isVersionNewerThan1_20_2()) { - return new PacketIds1_20_2(); } else { return new PacketIds1_20(); } @@ -141,7 +136,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(PacketConsumers.LOGIN, Reflections.clazz$ClientboundLoginPacket); registerNMSPacketConsumer(PacketConsumers.RESPAWN, Reflections.clazz$ClientboundRespawnPacket); registerNMSPacketConsumer(PacketConsumers.INTERACT_ENTITY, Reflections.clazz$ServerboundInteractPacket); - registerNMSPacketConsumer(PacketConsumers.REMOVE_ENTITY, Reflections.clazz$ClientboundRemoveEntitiesPacket); registerNMSPacketConsumer(PacketConsumers.SYNC_ENTITY_POSITION, Reflections.clazz$ClientboundEntityPositionSyncPacket); registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$Pos); registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, Reflections.clazz$ServerboundPickItemFromEntityPacket); @@ -150,7 +144,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket); registerNMSPacketConsumer(PacketConsumers.EDIT_BOOK, Reflections.clazz$ServerboundEditBookPacket); registerNMSPacketConsumer(PacketConsumers.CUSTOM_PAYLOAD, Reflections.clazz$ServerboundCustomPayloadPacket); -// registerNMSPacketConsumer(PacketConsumers.SET_ENTITY_DATA, Reflections.clazz$ClientboundSetEntityDataPacket); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.LEVEL_PARTICLE, this.packetIds.clientboundLevelParticlesPacket()); @@ -162,10 +155,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.BOSS_EVENT_1_20_3 : PacketConsumers.BOSS_EVENT_1_20, this.packetIds.clientboundBossEventPacket()); registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.SYSTEM_CHAT_1_20_3 : PacketConsumers.SYSTEM_CHAT_1_20, this.packetIds.clientboundSystemChatPacket()); registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.TAB_LIST_1_20_3 : PacketConsumers.TAB_LIST_1_20, this.packetIds.clientboundTabListPacket()); - // registerByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket()); + registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.TEAM_1_20_3 : PacketConsumers.TEAM_1_20, this.packetIds.clientboundSetPlayerTeamPacket()); + registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_20_3() ? PacketConsumers.SET_OBJECTIVE_1_20_3 : PacketConsumers.SET_OBJECTIVE_1_20, this.packetIds.clientboundSetObjectivePacket()); + registerByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket()); registerByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket()); - // registerByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket()); - // registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket()); + registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket()); } public static BukkitNetworkManager instance() { 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 d0c11d59b..a40076531 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 @@ -31,7 +31,6 @@ import net.momirealms.craftengine.core.world.chunk.Palette; import net.momirealms.craftengine.core.world.chunk.PalettedContainer; import net.momirealms.craftengine.core.world.chunk.packet.MCSection; import net.momirealms.sparrow.nbt.Tag; -import net.momirealms.sparrow.nbt.serializer.NBTComponentSerializer; import org.bukkit.*; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; @@ -242,6 +241,184 @@ public class PacketConsumers { } }; + public static final TriConsumer SOUND = (user, event, packet) -> { + try { + Object soundEvent = FastNMS.INSTANCE.field$ClientboundSoundPacket$soundEvent(packet); + Key soundId = Key.of(FastNMS.INSTANCE.field$SoundEvent$location(soundEvent).toString()); + Key mapped = BukkitBlockManager.instance().replaceSoundIfExist(soundId); + if (mapped != null) { + event.setCancelled(true); + Object newId = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath(mapped.namespace(), mapped.value()); + Object newSoundEvent = VersionHelper.isVersionNewerThan1_21_2() ? + Reflections.constructor$SoundEvent.newInstance(newId, Reflections.field$SoundEvent$fixedRange.get(soundEvent)) : + Reflections.constructor$SoundEvent.newInstance(newId, Reflections.field$SoundEvent$range.get(soundEvent), Reflections.field$SoundEvent$newSystem.get(soundEvent)); + Object newSoundPacket = FastNMS.INSTANCE.fastConstructor$ClientboundSoundPacket(newSoundEvent, packet); + user.sendPacket(newSoundPacket, true); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundSoundPacket", e); + } + }; + + public static final BiConsumer TEAM_1_20_3 = (user, event) -> { + if (!Config.interceptTeam()) return; + try { + FriendlyByteBuf buf = event.getBuffer(); + String name = buf.readUtf(); + byte method = buf.readByte(); + if (method != 2 && method != 0) { + return; + } + Tag displayName = buf.readNbt(false); + if (displayName == null) return; + byte friendlyFlags = buf.readByte(); + String nameTagVisibility = buf.readUtf(40); + String collisionRule = buf.readUtf(40); + int color = buf.readVarInt(); + Tag prefix = buf.readNbt(false); + if (prefix == null) return; + Tag suffix = buf.readNbt(false); + if (suffix == null) return; + + Map tokens1 = CraftEngine.instance().imageManager().matchTags(displayName.getAsString()); + Map tokens2 = CraftEngine.instance().imageManager().matchTags(prefix.getAsString()); + Map tokens3 = CraftEngine.instance().imageManager().matchTags(suffix.getAsString()); + if (tokens1.isEmpty() && tokens2.isEmpty() && tokens3.isEmpty()) return; + event.setChanged(true); + + List entities; + if (method == 0) { + entities = buf.readStringList(); + } else { + entities = null; + } + + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeUtf(name); + buf.writeByte(method); + + if (!tokens1.isEmpty()) { + Component component = AdventureHelper.tagToComponent(displayName); + for (Map.Entry token : tokens1.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeNbt(AdventureHelper.componentToTag(component), false); + } else { + buf.writeNbt(displayName, false); + } + + buf.writeByte(friendlyFlags); + buf.writeUtf(nameTagVisibility); + buf.writeUtf(collisionRule); + buf.writeVarInt(color); + + if (!tokens2.isEmpty()) { + Component component = AdventureHelper.tagToComponent(prefix); + for (Map.Entry token : tokens2.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeNbt(AdventureHelper.componentToTag(component), false); + } else { + buf.writeNbt(prefix, false); + } + + if (!tokens3.isEmpty()) { + Component component = AdventureHelper.tagToComponent(suffix); + for (Map.Entry token : tokens3.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeNbt(AdventureHelper.componentToTag(component), false); + } else { + buf.writeNbt(suffix, false); + } + + if (entities != null) { + buf.writeStringList(entities); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundSetPlayerTeamPacket", e); + } + }; + + public static final BiConsumer TEAM_1_20 = (user, event) -> { + if (!Config.interceptTeam()) return; + try { + FriendlyByteBuf buf = event.getBuffer(); + String name = buf.readUtf(); + byte method = buf.readByte(); + if (method != 2 && method != 0) { + return; + } + String displayName = buf.readUtf(); + byte friendlyFlags = buf.readByte(); + String nameTagVisibility = buf.readUtf(40); + String collisionRule = buf.readUtf(40); + int color = buf.readVarInt(); + String prefix = buf.readUtf(); + String suffix = buf.readUtf(); + + Map tokens1 = CraftEngine.instance().imageManager().matchTags(displayName); + Map tokens2 = CraftEngine.instance().imageManager().matchTags(prefix); + Map tokens3 = CraftEngine.instance().imageManager().matchTags(suffix); + if (tokens1.isEmpty() && tokens2.isEmpty() && tokens3.isEmpty()) return; + event.setChanged(true); + + List entities; + if (method == 0) { + entities = buf.readStringList(); + } else { + entities = null; + } + + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeUtf(name); + buf.writeByte(method); + + if (!tokens1.isEmpty()) { + Component component = AdventureHelper.jsonToComponent(displayName); + for (Map.Entry token : tokens1.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeUtf(AdventureHelper.componentToJson(component)); + } else { + buf.writeUtf(displayName); + } + + buf.writeByte(friendlyFlags); + buf.writeUtf(nameTagVisibility); + buf.writeUtf(collisionRule); + buf.writeVarInt(color); + + if (!tokens2.isEmpty()) { + Component component = AdventureHelper.jsonToComponent(prefix); + for (Map.Entry token : tokens2.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeUtf(AdventureHelper.componentToJson(component)); + } else { + buf.writeUtf(prefix); + } + + if (!tokens3.isEmpty()) { + Component component = AdventureHelper.jsonToComponent(suffix); + for (Map.Entry token : tokens3.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeUtf(AdventureHelper.componentToJson(component)); + } else { + buf.writeUtf(suffix); + } + + if (entities != null) { + buf.writeStringList(entities); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundSetPlayerTeamPacket", e); + } + }; + public static final BiConsumer BOSS_EVENT_1_20 = (user, event) -> { if (!Config.interceptBossBar()) return; try { @@ -301,7 +478,7 @@ public class PacketConsumers { if (nbt == null) return; Map tokens = CraftEngine.instance().imageManager().matchTags(nbt.getAsString()); if (tokens.isEmpty()) return; - Component component = NBTComponentSerializer.nbt().deserialize(nbt); + Component component = AdventureHelper.tagToComponent(nbt); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } @@ -314,7 +491,7 @@ public class PacketConsumers { buf.writeVarInt(event.packetID()); buf.writeUUID(uuid); buf.writeVarInt(actionType); - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); buf.writeFloat(health); buf.writeVarInt(color); buf.writeVarInt(division); @@ -325,7 +502,7 @@ public class PacketConsumers { Map tokens = CraftEngine.instance().imageManager().matchTags(nbt.getAsString()); if (tokens.isEmpty()) return; event.setChanged(true); - Component component = NBTComponentSerializer.nbt().deserialize(nbt); + Component component = AdventureHelper.tagToComponent(nbt); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } @@ -333,23 +510,151 @@ public class PacketConsumers { buf.writeVarInt(event.packetID()); buf.writeUUID(uuid); buf.writeVarInt(actionType); - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundBossEventPacket", e); } }; + public static final BiConsumer SET_OBJECTIVE_1_20 = (user, event) -> { + if (!Config.interceptScoreboard()) return; + try { + FriendlyByteBuf buf = event.getBuffer(); + String objective = buf.readUtf(); + byte mode = buf.readByte(); + if (mode != 0 && mode != 2) return; + String displayName = buf.readUtf(); + int renderType = buf.readVarInt(); + Map tokens = CraftEngine.instance().imageManager().matchTags(displayName); + if (tokens.isEmpty()) return; + event.setChanged(true); + Component component = AdventureHelper.jsonToComponent(displayName); + for (Map.Entry token : tokens.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeUtf(objective); + buf.writeByte(mode); + buf.writeUtf(AdventureHelper.componentToJson(component)); + buf.writeVarInt(renderType); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundSetObjectivePacket", e); + } + }; + + public static final BiConsumer SET_OBJECTIVE_1_20_3 = (user, event) -> { + if (!Config.interceptScoreboard()) return; + try { + FriendlyByteBuf buf = event.getBuffer(); + String objective = buf.readUtf(); + byte mode = buf.readByte(); + if (mode != 0 && mode != 2) return; + Tag displayName = buf.readNbt(false); + if (displayName == null) return; + int renderType = buf.readVarInt(); + boolean optionalNumberFormat = buf.readBoolean(); + if (optionalNumberFormat) { + int format = buf.readVarInt(); + if (format == 0) { + Map tokens = CraftEngine.instance().imageManager().matchTags(displayName.getAsString()); + if (tokens.isEmpty()) return; + event.setChanged(true); + Component component = AdventureHelper.tagToComponent(displayName); + for (Map.Entry token : tokens.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeUtf(objective); + buf.writeByte(mode); + buf.writeNbt(AdventureHelper.componentToTag(component), false); + buf.writeVarInt(renderType); + buf.writeBoolean(true); + buf.writeVarInt(0); + } else if (format == 1) { + Map tokens = CraftEngine.instance().imageManager().matchTags(displayName.getAsString()); + if (tokens.isEmpty()) return; + Tag style = buf.readNbt(false); + event.setChanged(true); + Component component = AdventureHelper.tagToComponent(displayName); + for (Map.Entry token : tokens.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeUtf(objective); + buf.writeByte(mode); + buf.writeNbt(AdventureHelper.componentToTag(component), false); + buf.writeVarInt(renderType); + buf.writeBoolean(true); + buf.writeVarInt(1); + buf.writeNbt(style, false); + } else if (format == 2) { + Tag fixed = buf.readNbt(false); + if (fixed == null) return; + Map tokens1 = CraftEngine.instance().imageManager().matchTags(displayName.getAsString()); + Map tokens2 = CraftEngine.instance().imageManager().matchTags(fixed.getAsString()); + if (tokens1.isEmpty() && tokens2.isEmpty()) return; + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeUtf(objective); + buf.writeByte(mode); + if (!tokens1.isEmpty()) { + Component component = AdventureHelper.tagToComponent(displayName); + for (Map.Entry token : tokens1.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeNbt(AdventureHelper.componentToTag(component), false); + } else { + buf.writeNbt(displayName, false); + } + buf.writeVarInt(renderType); + buf.writeBoolean(true); + buf.writeVarInt(2); + if (!tokens2.isEmpty()) { + Component component = AdventureHelper.tagToComponent(fixed); + for (Map.Entry token : tokens2.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.writeNbt(AdventureHelper.componentToTag(component), false); + } else { + buf.writeNbt(fixed, false); + } + } + } else { + Map tokens = CraftEngine.instance().imageManager().matchTags(displayName.getAsString()); + if (tokens.isEmpty()) return; + event.setChanged(true); + Component component = AdventureHelper.tagToComponent(displayName); + for (Map.Entry token : tokens.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeUtf(objective); + buf.writeByte(mode); + buf.writeNbt(AdventureHelper.componentToTag(component), false); + buf.writeVarInt(renderType); + buf.writeBoolean(false); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundSetObjectivePacket", e); + } + }; + public static final BiConsumer SYSTEM_CHAT_1_20 = (user, event) -> { if (!Config.interceptSystemChat()) return; try { FriendlyByteBuf buf = event.getBuffer(); - String json = buf.readUtf(); - Map tokens = CraftEngine.instance().imageManager().matchTags(json); + String jsonOrPlainString = buf.readUtf(); + Map tokens = CraftEngine.instance().imageManager().matchTags(jsonOrPlainString); if (tokens.isEmpty()) return; boolean overlay = buf.readBoolean(); event.setChanged(true); - Component component = AdventureHelper.jsonToComponent(json); + Component component = AdventureHelper.jsonToComponent(jsonOrPlainString); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } @@ -372,13 +677,13 @@ public class PacketConsumers { if (tokens.isEmpty()) return; boolean overlay = buf.readBoolean(); event.setChanged(true); - Component component = NBTComponentSerializer.nbt().deserialize(nbt); + Component component = AdventureHelper.tagToComponent(nbt); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } buf.clear(); buf.writeVarInt(event.packetID()); - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); buf.writeBoolean(overlay); } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSystemChatPacket", e); @@ -414,13 +719,13 @@ public class PacketConsumers { Map tokens = CraftEngine.instance().imageManager().matchTags(nbt.getAsString()); if (tokens.isEmpty()) return; event.setChanged(true); - Component component = NBTComponentSerializer.nbt().deserialize(nbt); + Component component = AdventureHelper.tagToComponent(nbt); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } buf.clear(); buf.writeVarInt(event.packetID()); - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSetSubtitleTextPacket", e); } @@ -455,13 +760,13 @@ public class PacketConsumers { Map tokens = CraftEngine.instance().imageManager().matchTags(nbt.getAsString()); if (tokens.isEmpty()) return; event.setChanged(true); - Component component = NBTComponentSerializer.nbt().deserialize(nbt); + Component component = AdventureHelper.tagToComponent(nbt); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } buf.clear(); buf.writeVarInt(event.packetID()); - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSetTitleTextPacket", e); } @@ -496,13 +801,13 @@ public class PacketConsumers { Map tokens = CraftEngine.instance().imageManager().matchTags(nbt.getAsString()); if (tokens.isEmpty()) return; event.setChanged(true); - Component component = NBTComponentSerializer.nbt().deserialize(nbt); + Component component = AdventureHelper.tagToComponent(nbt); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } buf.clear(); buf.writeVarInt(event.packetID()); - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundSetActionBarTextPacket", e); } @@ -558,20 +863,20 @@ public class PacketConsumers { buf.clear(); buf.writeVarInt(event.packetID()); if (!tokens1.isEmpty()) { - Component component = NBTComponentSerializer.nbt().deserialize(nbt1); + Component component = AdventureHelper.tagToComponent(nbt1); for (Map.Entry token : tokens1.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); } else { buf.writeNbt(nbt1, false); } if (!tokens2.isEmpty()) { - Component component = NBTComponentSerializer.nbt().deserialize(nbt2); + Component component = AdventureHelper.tagToComponent(nbt2); for (Map.Entry token : tokens2.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); } else { buf.writeNbt(nbt2, false); } @@ -614,7 +919,7 @@ public class PacketConsumers { if (nbt == null) return; Map tokens = CraftEngine.instance().imageManager().matchTags(nbt.getAsString()); if (tokens.isEmpty()) return; - Component component = NBTComponentSerializer.nbt().deserialize(nbt); + Component component = AdventureHelper.tagToComponent(nbt); for (Map.Entry token : tokens.entrySet()) { component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); } @@ -622,7 +927,7 @@ public class PacketConsumers { buf.writeVarInt(event.packetID()); buf.writeVarInt(containerId); buf.writeVarInt(type); - buf.writeNbt(NBTComponentSerializer.nbt().serialize(component), false); + buf.writeNbt(AdventureHelper.componentToTag(component), false); } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundOpenScreenPacket", e); } @@ -1039,6 +1344,8 @@ public class PacketConsumers { } } else if (type == Reflections.instance$EntityType$BLOCK_DISPLAY$registryId) { user.entityView().put(id, Reflections.instance$EntityType$BLOCK_DISPLAY); + } else if (type == Reflections.instance$EntityType$TEXT_DISPLAY$registryId) { + user.entityView().put(id, Reflections.instance$EntityType$TEXT_DISPLAY); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundAddEntityPacket", e); @@ -1095,17 +1402,27 @@ public class PacketConsumers { } }; - // TODO USE bytebuffer - public static final TriConsumer REMOVE_ENTITY = (user, event, packet) -> { + public static final BiConsumer REMOVE_ENTITY = (user, event) -> { try { - IntList intList = FastNMS.INSTANCE.field$ClientboundRemoveEntitiesPacket$entityIds(packet); + FriendlyByteBuf buf = event.getBuffer(); + boolean isChange = false; + IntList intList = buf.readIntIdList(); for (int i = 0, size = intList.size(); i < size; i++) { - List entities = user.furnitureView().remove(intList.getInt(i)); + int entityId = intList.getInt(i); + user.entityView().remove(entityId); + List entities = user.furnitureView().remove(entityId); if (entities == null) continue; - for (int entityId : entities) { - intList.add(entityId); + for (int subEntityId : entities) { + isChange = true; + intList.add(subEntityId); } } + if (isChange) { + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeIntIdList(intList); + } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundRemoveEntitiesPacket", e); } @@ -1169,32 +1486,12 @@ public class PacketConsumers { } }); } - }, player.getWorld(), location.getBlockX() >> 4,location.getBlockZ() >> 4); + }, player.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ServerboundInteractPacket", e); } }; - // TODO USE bytebuffer - public static final TriConsumer SOUND = (user, event, packet) -> { - try { - Object soundEvent = FastNMS.INSTANCE.field$ClientboundSoundPacket$soundEvent(packet); - Key soundId = Key.of(FastNMS.INSTANCE.field$SoundEvent$location(soundEvent).toString()); - Key mapped = BukkitBlockManager.instance().replaceSoundIfExist(soundId); - if (mapped != null) { - event.setCancelled(true); - Object newId = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath(mapped.namespace(), mapped.value()); - Object newSoundEvent = VersionHelper.isVersionNewerThan1_21_2() ? - Reflections.constructor$SoundEvent.newInstance(newId, Reflections.field$SoundEvent$fixedRange.get(soundEvent)) : - Reflections.constructor$SoundEvent.newInstance(newId, Reflections.field$SoundEvent$range.get(soundEvent), Reflections.field$SoundEvent$newSystem.get(soundEvent)); - Object newSoundPacket = FastNMS.INSTANCE.fastConstructor$ClientboundSoundPacket(newSoundEvent, packet); - user.sendPacket(newSoundPacket, true); - } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to handle ClientboundSoundPacket", e); - } - }; - // we handle it on packet level to prevent it from being captured by plugins public static final TriConsumer RENAME_ITEM = (user, event, packet) -> { try { @@ -1387,90 +1684,117 @@ public class PacketConsumers { } }; - - // TODO 需要修复 - // @SuppressWarnings("unchecked") - // public static final BiConsumer SET_ENTITY_DATA = (user, event) -> { - // try { - // FriendlyByteBuf buf = event.getBuffer(); - // int id = buf.readVarInt(); - // Object entityType = user.entityView().get(id); - // if (entityType == Reflections.instance$EntityType$BLOCK_DISPLAY) { - // Object registryFriendlyByteBuf = FastNMS.INSTANCE.constructor$RegistryFriendlyByteBuf(buf, Reflections.instance$registryAccess); - // boolean isChanged = false; - // List packedItems = (List) Reflections.method$ClientboundSetEntityDataPacket$unpack.invoke(null, registryFriendlyByteBuf); - // for (int i = 0; i < packedItems.size(); i++) { - // Object packedItem = packedItems.get(i); - // int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); - // if (entityDataId != EntityDataUtils.BLOCK_STATE_DATA_ID) { - // continue; - // } - // Object blockState = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); - // int stateId = BlockStateUtils.blockStateToId(blockState); - // int newStateId; - // if (!user.clientModEnabled()) { - // newStateId = remap(stateId); - // } else { - // newStateId = remapMOD(stateId); - // } - // Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); - // packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue( - // entityDataId, serializer, BlockStateUtils.idToBlockState(newStateId) - // )); - // isChanged = true; - // break; - // } - // if (isChanged) { - // System.out.println("Changed"); - // event.setChanged(true); - // buf.clear(); - // buf.writeVarInt(event.packetID()); - // Reflections.method$ClientboundSetEntityDataPacket$pack.invoke(null, packedItems, registryFriendlyByteBuf); - // } - // } - // } catch (Exception e) { - // CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); - // } - // }; - - // 之前的旧东西经供参考需要改成使用bytebuffer的 - // public static final TriConsumer SET_ENTITY_DATA = (user, event, packet) -> { - // try { - // int id = FastNMS.INSTANCE.field$ClientboundSetEntityDataPacket$id(packet); - // Object entityType = user.entityView().get(id); - // if (entityType == Reflections.instance$EntityType$BLOCK_DISPLAY) { - // List packedItems = FastNMS.INSTANCE.field$ClientboundSetEntityDataPacket$packedItems(packet); - // for (int i = 0; i < packedItems.size(); i++) { - // Object packedItem = packedItems.get(i); - // int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); - // if (entityDataId != EntityDataUtils.BLOCK_STATE_DATA_ID) { - // continue; - // } - // Object blockState = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); - // int stateId = BlockStateUtils.blockStateToId(blockState); - // int newStateId; - // if (!user.clientModEnabled()) { - // newStateId = remap(stateId); - // } else { - // newStateId = remapMOD(stateId); - // } - // Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); - // packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue( - // entityDataId, serializer, BlockStateUtils.idToBlockState(newStateId) - // )); - // break; - // } - // } - // } catch (Exception e) { - // CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); - // } - // }; - -// public static final TriConsumer OPEN_SCREEN = (user, event, packet) -> { -// try { -// -// } catch (Exception e) { -// CraftEngine.instance().logger().warn("Failed to handle ClientboundOpenScreenPacket", e); -// } -// }; + @SuppressWarnings("unchecked") + public static final BiConsumer SET_ENTITY_DATA = (user, event) -> { + try { + FriendlyByteBuf buf = event.getBuffer(); + int id = buf.readVarInt(); + Object entityType = user.entityView().get(id); + if (entityType == Reflections.instance$EntityType$BLOCK_DISPLAY) { + boolean isChanged = false; + List packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); + for (int i = 0; i < packedItems.size(); i++) { + Object packedItem = packedItems.get(i); + int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); + if (entityDataId == EntityDataUtils.BLOCK_STATE_DATA_ID) { + Object blockState = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); + int stateId = BlockStateUtils.blockStateToId(blockState); + int newStateId; + if (!user.clientModEnabled()) { + newStateId = remap(stateId); + } else { + newStateId = remapMOD(stateId); + } + Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); + packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue( + entityDataId, serializer, BlockStateUtils.idToBlockState(newStateId) + )); + isChanged = true; + } else if (Config.interceptEntityName() && entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) { + Optional optionalTextComponent = (Optional) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); + if (optionalTextComponent.isPresent()) { + Object textComponent = optionalTextComponent.get(); + String json = ComponentUtils.minecraftToJson(textComponent); + Map tokens = CraftEngine.instance().imageManager().matchTags(json); + if (!tokens.isEmpty()) { + Component component = AdventureHelper.jsonToComponent(json); + for (Map.Entry token : tokens.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); + packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue( + entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component)) + )); + isChanged = true; + } + } + } + } + if (isChanged) { + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeVarInt(id); + FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf); + } + } else if (Config.interceptEntityName()) { + boolean isChanged = false; + List packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); + if (entityType == Reflections.instance$EntityType$TEXT_DISPLAY) { + for (int i = 0; i < packedItems.size(); i++) { + Object packedItem = packedItems.get(i); + int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); + if (entityDataId == EntityDataUtils.TEXT_DATA_ID) { + Object textComponent = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); + if (textComponent == Reflections.instance$Component$empty) break; + String json = ComponentUtils.minecraftToJson(textComponent); + Map tokens = CraftEngine.instance().imageManager().matchTags(json); + if (!tokens.isEmpty()) { + Component component = AdventureHelper.jsonToComponent(json); + for (Map.Entry token : tokens.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); + packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, ComponentUtils.adventureToMinecraft(component))); + isChanged = true; + break; + } + } + } + } else { + for (int i = 0; i < packedItems.size(); i++) { + Object packedItem = packedItems.get(i); + int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); + if (entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) { + Optional optionalTextComponent = (Optional) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); + if (optionalTextComponent.isPresent()) { + Object textComponent = optionalTextComponent.get(); + String json = ComponentUtils.minecraftToJson(textComponent); + Map tokens = CraftEngine.instance().imageManager().matchTags(json); + if (!tokens.isEmpty()) { + Component component = AdventureHelper.jsonToComponent(json); + for (Map.Entry token : tokens.entrySet()) { + component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(AdventureHelper.miniMessage().deserialize(token.getValue()))); + } + Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); + packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component)))); + isChanged = true; + break; + } + } + } + } + } + if (isChanged) { + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeVarInt(id); + FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf); + } + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e); + } + }; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java index cba589e6e..679af61e3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java @@ -31,4 +31,8 @@ public interface PacketIds { int clientboundSystemChatPacket(); int clientboundTabListPacket(); + + int clientboundSetPlayerTeamPacket(); + + int clientboundSetObjectivePacket(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIdFinder.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIdFinder.java index eea73d2ec..737534fcc 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIdFinder.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIdFinder.java @@ -1,26 +1,35 @@ package net.momirealms.craftengine.bukkit.plugin.network.impl; import com.google.gson.JsonElement; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.VersionHelper; import java.util.HashMap; import java.util.Map; public class PacketIdFinder { - private static final Map> gamePacketIds = new HashMap<>(); + private static final Map> gamePacketIdsByName = new HashMap<>(); + private static final Map, Integer>> gamePacketIdsByClazz = new HashMap<>(); static { try { - Object packetReport = Reflections.constructor$PacketReport.newInstance((Object) null); - JsonElement jsonElement = (JsonElement) Reflections.method$PacketReport$serializePackets.invoke(packetReport); - var play = jsonElement.getAsJsonObject().get("play"); - for (var entry : play.getAsJsonObject().entrySet()) { - Map ids = new HashMap<>(); - gamePacketIds.put(entry.getKey(), ids); - for (var entry2 : entry.getValue().getAsJsonObject().entrySet()) { - ids.put(entry2.getKey(), entry2.getValue().getAsJsonObject().get("protocol_id").getAsInt()); + if (VersionHelper.isVersionNewerThan1_21()) { + Object packetReport = Reflections.constructor$PacketReport.newInstance((Object) null); + JsonElement jsonElement = (JsonElement) Reflections.method$PacketReport$serializePackets.invoke(packetReport); + var play = jsonElement.getAsJsonObject().get("play"); + for (var entry : play.getAsJsonObject().entrySet()) { + Map ids = new HashMap<>(); + gamePacketIdsByName.put(entry.getKey(), ids); + for (var entry2 : entry.getValue().getAsJsonObject().entrySet()) { + ids.put(entry2.getKey(), entry2.getValue().getAsJsonObject().get("protocol_id").getAsInt()); + } } + } else if (VersionHelper.isVersionNewerThan1_20_5()) { + gamePacketIdsByName.putAll(FastNMS.INSTANCE.method$getGamePacketIdsByName()); + } else { + gamePacketIdsByClazz.putAll(FastNMS.INSTANCE.method$getGamePacketIdsByClazz()); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to get packets", e); @@ -28,6 +37,10 @@ public class PacketIdFinder { } public static int clientboundByName(String packetName) { - return gamePacketIds.get("clientbound").getOrDefault(packetName, -1); + return gamePacketIdsByName.get("clientbound").getOrDefault(packetName, -1); + } + + public static int clientboundByClazz(Class clazz) { + return gamePacketIdsByClazz.get("clientbound").getOrDefault(clazz, -1); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20.java index 68b07152f..de1ba2be7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20.java @@ -1,81 +1,92 @@ package net.momirealms.craftengine.bukkit.plugin.network.impl; import net.momirealms.craftengine.bukkit.plugin.network.PacketIds; +import net.momirealms.craftengine.bukkit.util.Reflections; public class PacketIds1_20 implements PacketIds { @Override public int clientboundBlockUpdatePacket() { - return 10; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundBlockUpdatePacket); } @Override public int clientboundSectionBlocksUpdatePacket() { - return 67; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSectionBlocksUpdatePacket); } @Override public int clientboundLevelParticlesPacket() { - return 38; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundLevelParticlesPacket); } @Override public int clientboundLevelEventPacket() { - return 37; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundLevelEventPacket); } @Override public int clientboundAddEntityPacket() { - return 1; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundAddEntityPacket); } @Override public int clientboundOpenScreenPacket() { - return 48; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundOpenScreenPacket); } @Override public int clientboundSoundPacket() { - return 98; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSoundPacket); } @Override public int clientboundRemoveEntitiesPacket() { - return 62; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundRemoveEntitiesPacket); } @Override public int clientboundSetEntityDataPacket() { - return 82; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSetEntityDataPacket); } @Override public int clientboundSetTitleTextPacket() { - return 95; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSetTitleTextPacket); } @Override public int clientboundSetSubtitleTextPacket() { - return 93; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSetSubtitleTextPacket); } @Override public int clientboundSetActionBarTextPacket() { - return 70; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSetActionBarTextPacket); } @Override public int clientboundBossEventPacket() { - return 11; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundBossEventPacket); } @Override public int clientboundSystemChatPacket() { - return 100; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSystemChatPacket); } @Override public int clientboundTabListPacket() { - return 101; + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundTabListPacket); + } + + @Override + public int clientboundSetPlayerTeamPacket() { + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSetPlayerTeamPacket); + } + + @Override + public int clientboundSetObjectivePacket() { + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSetObjectivePacket); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_2.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_2.java deleted file mode 100644 index 9773d7cb5..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_2.java +++ /dev/null @@ -1,81 +0,0 @@ -package net.momirealms.craftengine.bukkit.plugin.network.impl; - -import net.momirealms.craftengine.bukkit.plugin.network.PacketIds; - -public class PacketIds1_20_2 implements PacketIds { - - @Override - public int clientboundBlockUpdatePacket() { - return 9; - } - - @Override - public int clientboundSectionBlocksUpdatePacket() { - return 69; - } - - @Override - public int clientboundLevelParticlesPacket() { - return 39; - } - - @Override - public int clientboundLevelEventPacket() { - return 38; - } - - @Override - public int clientboundAddEntityPacket() { - return 1; - } - - @Override - public int clientboundOpenScreenPacket() { - return 49; - } - - @Override - public int clientboundSoundPacket() { - return 100; - } - - @Override - public int clientboundRemoveEntitiesPacket() { - return 64; - } - - @Override - public int clientboundSetEntityDataPacket() { - return 84; - } - - @Override - public int clientboundSetTitleTextPacket() { - return 97; - } - - @Override - public int clientboundSetSubtitleTextPacket() { - return 95; - } - - @Override - public int clientboundSetActionBarTextPacket() { - return 72; - } - - @Override - public int clientboundBossEventPacket() { - return 10; - } - - @Override - public int clientboundSystemChatPacket() { - return 103; - } - - @Override - public int clientboundTabListPacket() { - return 104; - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_3.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_3.java deleted file mode 100644 index c6d0a66ca..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_3.java +++ /dev/null @@ -1,81 +0,0 @@ -package net.momirealms.craftengine.bukkit.plugin.network.impl; - -import net.momirealms.craftengine.bukkit.plugin.network.PacketIds; - -public class PacketIds1_20_3 implements PacketIds { - - @Override - public int clientboundBlockUpdatePacket() { - return 9; - } - - @Override - public int clientboundSectionBlocksUpdatePacket() { - return 71; - } - - @Override - public int clientboundLevelParticlesPacket() { - return 39; - } - - @Override - public int clientboundLevelEventPacket() { - return 38; - } - - @Override - public int clientboundAddEntityPacket() { - return 1; - } - - @Override - public int clientboundOpenScreenPacket() { - return 49; - } - - @Override - public int clientboundSoundPacket() { - return 102; - } - - @Override - public int clientboundRemoveEntitiesPacket() { - return 64; - } - - @Override - public int clientboundSetEntityDataPacket() { - return 86; - } - - @Override - public int clientboundSetTitleTextPacket() { - return 99; - } - - @Override - public int clientboundSetSubtitleTextPacket() { - return 97; - } - - @Override - public int clientboundSetActionBarTextPacket() { - return 74; - } - - @Override - public int clientboundBossEventPacket() { - return 10; - } - - @Override - public int clientboundSystemChatPacket() { - return 105; - } - - @Override - public int clientboundTabListPacket() { - return 106; - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_5.java index 75b6566e3..1574df2ee 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_20_5.java @@ -6,76 +6,86 @@ public class PacketIds1_20_5 implements PacketIds { @Override public int clientboundBlockUpdatePacket() { - return 9; + return PacketIdFinder.clientboundByName("minecraft:block_update"); } @Override public int clientboundSectionBlocksUpdatePacket() { - return 73; + return PacketIdFinder.clientboundByName("minecraft:section_blocks_update"); } @Override public int clientboundLevelParticlesPacket() { - return 41; + return PacketIdFinder.clientboundByName("minecraft:level_particles"); } @Override public int clientboundLevelEventPacket() { - return 40; + return PacketIdFinder.clientboundByName("minecraft:level_event"); } @Override public int clientboundAddEntityPacket() { - return 1; + return PacketIdFinder.clientboundByName("minecraft:add_entity"); } @Override public int clientboundOpenScreenPacket() { - return 51; + return PacketIdFinder.clientboundByName("minecraft:open_screen"); } @Override public int clientboundSoundPacket() { - return 104; + return PacketIdFinder.clientboundByName("minecraft:sound"); } @Override public int clientboundRemoveEntitiesPacket() { - return 66; + return PacketIdFinder.clientboundByName("minecraft:remove_entities"); } @Override public int clientboundSetEntityDataPacket() { - return 88; + return PacketIdFinder.clientboundByName("minecraft:set_entity_data"); } @Override public int clientboundSetTitleTextPacket() { - return 101; + return PacketIdFinder.clientboundByName("minecraft:set_title_text"); } @Override public int clientboundSetSubtitleTextPacket() { - return 99; + return PacketIdFinder.clientboundByName("minecraft:set_subtitle_text"); } @Override public int clientboundSetActionBarTextPacket() { - return 76; + return PacketIdFinder.clientboundByName("minecraft:set_action_bar_text"); } @Override public int clientboundBossEventPacket() { - return 10; + return PacketIdFinder.clientboundByName("minecraft:boss_event"); } @Override public int clientboundSystemChatPacket() { - return 108; + return PacketIdFinder.clientboundByName("minecraft:system_chat"); } @Override public int clientboundTabListPacket() { - return 109; + return PacketIdFinder.clientboundByName("minecraft:tab_list"); + } + + @Override + public int clientboundSetPlayerTeamPacket() { + return PacketIdFinder.clientboundByName("minecraft:set_player_team"); + } + + @Override + public int clientboundSetObjectivePacket() { + return PacketIdFinder.clientboundByName("minecraft:set_objective"); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_21.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_21.java deleted file mode 100644 index 5dc7fa843..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/impl/PacketIds1_21.java +++ /dev/null @@ -1,81 +0,0 @@ -package net.momirealms.craftengine.bukkit.plugin.network.impl; - -import net.momirealms.craftengine.bukkit.plugin.network.PacketIds; - -public class PacketIds1_21 implements PacketIds { - - @Override - public int clientboundBlockUpdatePacket() { - return PacketIdFinder.clientboundByName("minecraft:block_update"); - } - - @Override - public int clientboundSectionBlocksUpdatePacket() { - return PacketIdFinder.clientboundByName("minecraft:section_blocks_update"); - } - - @Override - public int clientboundLevelParticlesPacket() { - return PacketIdFinder.clientboundByName("minecraft:level_particles"); - } - - @Override - public int clientboundLevelEventPacket() { - return PacketIdFinder.clientboundByName("minecraft:level_event"); - } - - @Override - public int clientboundAddEntityPacket() { - return PacketIdFinder.clientboundByName("minecraft:add_entity"); - } - - @Override - public int clientboundOpenScreenPacket() { - return PacketIdFinder.clientboundByName("minecraft:open_screen"); - } - - @Override - public int clientboundSoundPacket() { - return PacketIdFinder.clientboundByName("minecraft:sound"); - } - - @Override - public int clientboundRemoveEntitiesPacket() { - return PacketIdFinder.clientboundByName("minecraft:remove_entities"); - } - - @Override - public int clientboundSetEntityDataPacket() { - return PacketIdFinder.clientboundByName("minecraft:set_entity_data"); - } - - @Override - public int clientboundSetTitleTextPacket() { - return PacketIdFinder.clientboundByName("minecraft:set_title_text"); - } - - @Override - public int clientboundSetSubtitleTextPacket() { - return PacketIdFinder.clientboundByName("minecraft:set_subtitle_text"); - } - - @Override - public int clientboundSetActionBarTextPacket() { - return PacketIdFinder.clientboundByName("minecraft:set_action_bar_text"); - } - - @Override - public int clientboundBossEventPacket() { - return PacketIdFinder.clientboundByName("minecraft:boss_event"); - } - - @Override - public int clientboundSystemChatPacket() { - return PacketIdFinder.clientboundByName("minecraft:system_chat"); - } - - @Override - public int clientboundTabListPacket() { - return PacketIdFinder.clientboundByName("minecraft:tab_list"); - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java index d9d669755..93b3b88c0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java @@ -12,6 +12,8 @@ public class EntityDataUtils { private static final int LEFT_ALIGNMENT = 0x08; // 8 private static final int RIGHT_ALIGNMENT = 0x10; // 16 public static final int BLOCK_STATE_DATA_ID = VersionHelper.isVersionNewerThan1_20_2() ? 23 : 22; + public static final int TEXT_DATA_ID = VersionHelper.isVersionNewerThan1_20_2() ? 23 : 22; + public static final int CUSTOM_NAME_DATA_ID = 2; public static byte encodeTextDisplayMask(boolean hasShadow, boolean isSeeThrough, boolean useDefaultBackground, int alignment) { int bitMask = 0; 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 282888557..13dea6c76 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 @@ -3335,8 +3335,8 @@ public class Reflections { instance$ItemStack$EMPTY = requireNonNull( ReflectionUtils.getDeclaredField( clazz$ItemStack, clazz$ItemStack, 0 - ).get(null) - ); + ) + ).get(null); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -6270,27 +6270,42 @@ public class Reflections { ); public static final int instance$EntityType$BLOCK_DISPLAY$registryId; + public static final int instance$EntityType$TEXT_DISPLAY$registryId; public static final int instance$EntityType$FALLING_BLOCK$registryId; static { try { instance$EntityType$BLOCK_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$BLOCK_DISPLAY); + instance$EntityType$TEXT_DISPLAY$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$TEXT_DISPLAY); instance$EntityType$FALLING_BLOCK$registryId = (int) Reflections.method$Registry$getId.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, instance$EntityType$FALLING_BLOCK); } catch (Exception e) { throw new RuntimeException(e); } } - // 先注释后面再说 - // public static final Method method$ClientboundSetEntityDataPacket$pack = requireNonNull( - // ReflectionUtils.getDeclaredMethod( - // clazz$ClientboundSetEntityDataPacket, void.class, List.class, clazz$RegistryFriendlyByteBuf - // ) - // ); - // - // public static final Method method$ClientboundSetEntityDataPacket$unpack = requireNonNull( - // ReflectionUtils.getDeclaredMethod( - // clazz$ClientboundSetEntityDataPacket, List.class, clazz$RegistryFriendlyByteBuf - // ) - // ); + public static final Class clazz$ClientboundSetTitleTextPacket = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundSetTitleTextPacket") + ) + ); + + public static final Class clazz$ClientboundSetSubtitleTextPacket = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundSetSubtitleTextPacket") + ) + ); + + public static final Class clazz$ClientboundTabListPacket = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundTabListPacket"), + BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayOutPlayerListHeaderFooter") + ) + ); + + public static final Class clazz$ClientboundSetObjectivePacket = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ClientboundSetObjectivePacket"), + BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayOutScoreboardObjective") + ) + ); } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 2819c5ff8..896447ad4 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -25,6 +25,7 @@ dependencies { compileOnly("net.kyori:adventure-text-serializer-gson:${rootProject.properties["adventure_bundle_version"]}") { exclude("com.google.code.gson", "gson") } + compileOnly("net.kyori:adventure-text-serializer-json-legacy-impl:${rootProject.properties["adventure_bundle_version"]}") // Command compileOnly("org.incendo:cloud-core:${rootProject.properties["cloud_core_version"]}") compileOnly("org.incendo:cloud-minecraft-extras:${rootProject.properties["cloud_minecraft_extras_version"]}") @@ -46,7 +47,6 @@ dependencies { compileOnly("org.lz4:lz4-java:${rootProject.properties["lz4_version"]}") // Commons IO compileOnly("commons-io:commons-io:${rootProject.properties["commons_io_version"]}") - compileOnly("commons-io:commons-io:${rootProject.properties["commons_io_version"]}") // Data Fixer Upper compileOnly("com.mojang:datafixerupper:${rootProject.properties["datafixerupper_version"]}") // Aho-Corasick java implementation diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 94d59d1b7..c99a83be3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -395,14 +395,14 @@ public abstract class AbstractPackManager implements PackManager { for (Pack pack : loadedPacks()) { Pair, List> files = FileUtils.getConfigsDeeply(pack.configurationFolder()); for (Path path : files.left()) { - Yaml yaml = new Yaml(new StringKeyConstructor(new LoaderOptions())); try (InputStreamReader inputStream = new InputStreamReader(new FileInputStream(path.toFile()), StandardCharsets.UTF_8)) { + Yaml yaml = new Yaml(new StringKeyConstructor(new LoaderOptions())); Map data = yaml.load(inputStream); if (data == null) continue; for (Map.Entry entry : data.entrySet()) { processConfigEntry(entry, path, pack); } - } catch (IOException e) { + } catch (Exception e) { this.plugin.logger().warn(path, "Error loading config file", e); } } @@ -413,7 +413,7 @@ public abstract class AbstractPackManager implements PackManager { for (Map.Entry entry : data.entrySet()) { processConfigEntry(entry, path, pack); } - } catch (IOException e) { + } catch (Exception e) { this.plugin.logger().warn(path, "Error loading config file", e); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 868152174..6634f8462 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -142,12 +142,16 @@ public abstract class CraftEngine implements Plugin { if (reloadRecipe) { this.recipeManager.reload(); } - // now we load resources - this.packManager.loadResources(reloadRecipe); - // handle some special client lang for instance block_name - this.translationManager.delayedLoad(); + try { + // now we load resources + this.packManager.loadResources(reloadRecipe); + } catch (Exception e) { + this.logger().warn("Failed to load resources folder", e); + } // init suggestions and packet mapper this.blockManager.delayedLoad(); + // handle some special client lang for instance block_name + this.translationManager.delayedLoad(); // init suggestions this.furnitureManager.delayedLoad(); // sort the categories @@ -278,7 +282,7 @@ public abstract class CraftEngine implements Plugin { Dependencies.SNAKE_YAML, Dependencies.BOOSTED_YAML, Dependencies.MINIMESSAGE, - Dependencies.TEXT_SERIALIZER_GSON, + Dependencies.TEXT_SERIALIZER_GSON, Dependencies.TEXT_SERIALIZER_GSON_LEGACY, Dependencies.TEXT_SERIALIZER_JSON, Dependencies.AHO_CORASICK, Dependencies.LZ4 diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java index 5aaffc694..83f78491d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java @@ -128,6 +128,10 @@ public class Config { protected boolean image$intercept_packets$title; protected boolean image$intercept_packets$bossbar; protected boolean image$intercept_packets$container; + protected boolean image$intercept_packets$team; + protected boolean image$intercept_packets$scoreboard; + protected boolean image$intercept_packets$entity_name; + protected boolean image$intercept_packets$text_display; public Config(CraftEngine plugin) { this.plugin = plugin; @@ -290,6 +294,10 @@ public class Config { image$intercept_packets$title = config.getBoolean("image.intercept-packets.title", true); image$intercept_packets$bossbar = config.getBoolean("image.intercept-packets.bossbar", true); image$intercept_packets$container = config.getBoolean("image.intercept-packets.container", true); + image$intercept_packets$team = config.getBoolean("image.intercept-packets.team", true); + image$intercept_packets$scoreboard = config.getBoolean("image.intercept-packets.scoreboard", true); + image$intercept_packets$entity_name = config.getBoolean("image.intercept-packets.entity-name", true); + image$intercept_packets$text_display = config.getBoolean("image.intercept-packets.text-display", true); Class modClazz = ReflectionUtils.getClazz(CraftEngine.MOD_CLASS); if (modClazz != null) { @@ -614,6 +622,22 @@ public class Config { return instance.image$intercept_packets$container; } + public static boolean interceptTeam() { + return instance.image$intercept_packets$team; + } + + public static boolean interceptEntityName() { + return instance.image$intercept_packets$entity_name; + } + + public static boolean interceptScoreboard() { + return instance.image$intercept_packets$scoreboard; + } + + public static boolean interceptTextDisplay() { + return instance.image$intercept_packets$text_display; + } + public YamlDocument loadOrCreateYamlData(String fileName) { File file = new File(this.plugin.dataFolderFile(), fileName); if (!file.exists()) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java index e8de100b2..6a70db819 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java @@ -200,6 +200,13 @@ public class Dependencies { "adventure-text-serializer-gson", List.of(Relocation.of("adventure", "net{}kyori{}adventure")) ); + public static final Dependency TEXT_SERIALIZER_GSON_LEGACY = new Dependency( + "adventure-text-serializer-json-legacy-impl", + "net{}kyori", + "adventure-text-serializer-json-legacy-impl", + "adventure-text-serializer-json-legacy-impl", + List.of(Relocation.of("adventure", "net{}kyori{}adventure")) + ); public static final Dependency TEXT_SERIALIZER_JSON = new Dependency( "adventure-text-serializer-json", "net{}kyori", diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java index 3442aa6e6..2a365d14d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java @@ -7,6 +7,10 @@ import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.json.JSONOptions; +import net.kyori.adventure.text.serializer.json.legacyimpl.NBTLegacyHoverEventSerializer; +import net.momirealms.sparrow.nbt.Tag; +import net.momirealms.sparrow.nbt.serializer.NBTComponentSerializer; /** * Helper class for handling Adventure components and related functionalities. @@ -16,11 +20,18 @@ public class AdventureHelper { private final MiniMessage miniMessage; private final MiniMessage miniMessageStrict; private final GsonComponentSerializer gsonComponentSerializer; + private final NBTComponentSerializer nbtComponentSerializer; private AdventureHelper() { this.miniMessage = MiniMessage.builder().build(); this.miniMessageStrict = MiniMessage.builder().strict(true).build(); - this.gsonComponentSerializer = GsonComponentSerializer.builder().build(); + GsonComponentSerializer.Builder builder = GsonComponentSerializer.builder(); + if (!VersionHelper.isVersionNewerThan1_20_5()) { + builder.legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.get()); + builder.editOptions((b) -> b.value(JSONOptions.EMIT_HOVER_SHOW_ENTITY_ID_AS_INT_ARRAY, false)); + } + this.gsonComponentSerializer = builder.build(); + this.nbtComponentSerializer = NBTComponentSerializer.builder().build(); } private static class SingletonHolder { @@ -54,6 +65,15 @@ public class AdventureHelper { return getInstance().gsonComponentSerializer; } + /** + * Retrieves the NBTComponentSerializer instance. + * + * @return the NBTComponentSerializer instance + */ + public static NBTComponentSerializer getNBT() { + return getInstance().nbtComponentSerializer; + } + /** * Sends a message to an audience. * @@ -134,6 +154,14 @@ public class AdventureHelper { return getGson().serializeToTree(component); } + public static Tag componentToTag(Component component) { + return getNBT().serialize(component); + } + + public static Component tagToComponent(Tag tag) { + return getNBT().deserialize(tag); + } + /** * Checks if a character is a legacy color code. * diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java b/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java index 304f24c60..81ceb9719 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java @@ -48,6 +48,22 @@ public class FriendlyByteBuf extends ByteBuf { return BlockPos.of(buf.readLong()); } + public List readStringList() { + int i = this.readVarInt(); + List list = new ArrayList<>(i); + for (int j = 0; j < i; ++j) { + list.add(readUtf()); + } + return list; + } + + public void writeStringList(List list) { + writeVarInt(list.size()); + for (String s : list) { + writeUtf(s); + } + } + public FriendlyByteBuf writeBlockPos(BlockPos pos) { this.writeLong(pos.asLong()); return this; diff --git a/gradle.properties b/gradle.properties index 6db3d7e84..acd95d191 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ gson_version=2.11.0 asm_version=9.8 asm_commons_version=9.8 jar_relocator_version=1.7 -adventure_bundle_version=4.19.0 +adventure_bundle_version=4.20.0 adventure_platform_version=4.3.4 cloud_core_version=2.0.0 cloud_services_version=2.0.0 @@ -40,7 +40,7 @@ lz4_version=1.8.0 geantyref_version=1.3.16 zstd_version=1.5.7-2 commons_io_version=2.18.0 -sparrow_nbt_version=0.5 +sparrow_nbt_version=0.6.1 sparrow_util_version=0.37 fastutil_version=8.5.15 netty_version=4.1.119.Final @@ -51,7 +51,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.13 -nms_helper_version=0.45 +nms_helper_version=0.47 # Ignite Dependencies mixinextras_version=0.4.1 mixin_version=0.15.2+mixin.0.8.7