From a030ae3aa67e8a73673f50a09e42438cafa291b0 Mon Sep 17 00:00:00 2001 From: AsukaRyo12 <125512156@qq.com> Date: Fri, 25 Jul 2025 01:27:27 +0800 Subject: [PATCH 1/3] =?UTF-8?q?"Hi=20there!=20I've=20added=20a=20'Custom?= =?UTF-8?q?=20Entity=20Name'=20feature=20to=20replace=20the=20previous=20'?= =?UTF-8?q?Random=20Number=20ID=20or=20Default=20Entity=20Name'.=20I=20tho?= =?UTF-8?q?ught=20this=20might=20be=20useful=20for=20users=20who=20want=20?= =?UTF-8?q?more=20control=20over=20naming=20their=20entities,=20and=20I=20?= =?UTF-8?q?hope=20it=20adds=20value=20to=20the=20project.=20If=20you=20don?= =?UTF-8?q?'t=20mind,=20could=20you=20take=20a=20look=20at=20the=20changes?= =?UTF-8?q?=3F=20I'd=20love=20to=20contribute=20to=20making=20ZNPCsPlus=20?= =?UTF-8?q?even=20better!=20=E2=9D=A4=20Thanks=20for=20your=20hard=20work?= =?UTF-8?q?=20on=20this=20project!"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../znpcsplus/packets/V1_17PacketFactory.java | 29 +++++++++++++++++++ .../packets/V1_19_3PacketFactory.java | 8 +++-- .../packets/V1_20_2PacketFactory.java | 1 + 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java index 5a97fbf7..3e922e60 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java @@ -1,8 +1,11 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEventsAPI; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.config.ConfigManager; @@ -11,12 +14,15 @@ import lol.pyr.znpcsplus.scheduling.TaskScheduler; import lol.pyr.znpcsplus.util.NamedColor; import lol.pyr.znpcsplus.util.NpcLocation; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import java.util.Collections; import java.util.Optional; + public class V1_17PacketFactory extends V1_8PacketFactory { public V1_17PacketFactory(TaskScheduler scheduler, PacketEventsAPI packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, ConfigManager configManager) { super(scheduler, packetEvents, propertyRegistry, textSerializer, configManager); @@ -27,7 +33,30 @@ public void spawnEntity(Player player, PacketEntity entity, PropertyHolder prope NpcLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d()))); + + String displayName = entity.getProperty(propertyRegistry.getByName("display_name", String.class)); + if (displayName != null) { + EntityData> nameData = new EntityData<>( + 2, + EntityDataTypes.OPTIONAL_ADV_COMPONENT, + Optional.of(Component.text(displayName)) + ); + sendPacket(player, new WrapperPlayServerEntityMetadata( + entity.getEntityId(), + Collections.singletonList(nameData) + )); + } + sendAllMetadata(player, entity, properties); + EntityData hideNameDisplay = new EntityData<>( + 3, + EntityDataTypes.BOOLEAN, + false + ); + sendPacket(player, new WrapperPlayServerEntityMetadata( + entity.getEntityId(), + Collections.singletonList(hideNameDisplay) + )); if (EntityTypes.isTypeInstanceOf(entity.getType(), EntityTypes.LIVINGENTITY)) sendAllAttributes(player, entity, properties); createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java index 22fe62db..bb7ff8cb 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java @@ -27,11 +27,15 @@ public V1_19_3PacketFactory(TaskScheduler scheduler, PacketEventsAPI pac @Override public CompletableFuture addTabPlayer(Player player, PacketEntity entity, PropertyHolder properties) { if (entity.getType() != EntityTypes.PLAYER) return CompletableFuture.completedFuture(null); + CompletableFuture future = new CompletableFuture<>(); - skinned(player, properties, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> { + + String displayName = entity.getProperty(propertyRegistry.getByName("display_name", String.class)) == null ? entity.getEntityId()+"" : entity.getProperty(propertyRegistry.getByName("display_name", String.class)); + + skinned(player, properties, new UserProfile(entity.getUuid(), displayName)).thenAccept(profile -> { WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( profile, false, 1, GameMode.CREATIVE, - Component.text(configManager.getConfig().tabDisplayName().replace("{id}", Integer.toString(entity.getEntityId()))), null); + Component.text(configManager.getConfig().tabDisplayName().replace("{id}", displayName)), null); sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); future.complete(null); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java index 4a760e40..75d8903c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java @@ -18,6 +18,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; + public class V1_20_2PacketFactory extends V1_19_3PacketFactory { protected ConfigManager configManager; From b97f2372e49dada7aa6b58f353c7199f2e4bdad1 Mon Sep 17 00:00:00 2001 From: AsukaRyo12 <125512156@qq.com> Date: Mon, 4 Aug 2025 12:55:49 +0800 Subject: [PATCH 2/3] Some model rendering modules or plug-ins may use the entity's creature name to select and replace the NPC model. The previous writing method will cause the player-type NPC to always use a random numeric ID as the entity name. Therefore, in order to solve this problem, I allow NPCs to have custom names. --- .../pyr/znpcsplus/packets/V1_17PacketFactory.java | 12 ++---------- .../pyr/znpcsplus/packets/V1_19_3PacketFactory.java | 3 ++- .../lol/pyr/znpcsplus/packets/V1_8PacketFactory.java | 8 +++++++- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java index 3e922e60..f2699aa0 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_17PacketFactory.java @@ -34,6 +34,8 @@ public void spawnEntity(Player player, PacketEntity entity, PropertyHolder prope sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d()))); + // 设置除玩家以外的实体昵称 若display_name属性为空,则用默认实体名称 + // Sets the nickname of an entity other than the player. If the display_name attribute is empty, the default entity name is used. String displayName = entity.getProperty(propertyRegistry.getByName("display_name", String.class)); if (displayName != null) { EntityData> nameData = new EntityData<>( @@ -46,17 +48,7 @@ public void spawnEntity(Player player, PacketEntity entity, PropertyHolder prope Collections.singletonList(nameData) )); } - sendAllMetadata(player, entity, properties); - EntityData hideNameDisplay = new EntityData<>( - 3, - EntityDataTypes.BOOLEAN, - false - ); - sendPacket(player, new WrapperPlayServerEntityMetadata( - entity.getEntityId(), - Collections.singletonList(hideNameDisplay) - )); if (EntityTypes.isTypeInstanceOf(entity.getType(), EntityTypes.LIVINGENTITY)) sendAllAttributes(player, entity, properties); createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedColor.class))); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java index bb7ff8cb..adca929e 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_19_3PacketFactory.java @@ -30,8 +30,9 @@ public CompletableFuture addTabPlayer(Player player, PacketEntity entity, CompletableFuture future = new CompletableFuture<>(); + // 设置玩家类型NPC的昵称 若display_name属性为空,则用默认虚拟实体ID作为名称 + // Set the nickname of the player type NPC. If the display_name attribute is empty, the default virtual entity ID is used as the name. String displayName = entity.getProperty(propertyRegistry.getByName("display_name", String.class)) == null ? entity.getEntityId()+"" : entity.getProperty(propertyRegistry.getByName("display_name", String.class)); - skinned(player, properties, new UserProfile(entity.getUuid(), displayName)).thenAccept(profile -> { WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( profile, false, 1, GameMode.CREATIVE, diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index 085f338f..65e6722c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -124,8 +124,14 @@ public void createTeam(Player player, PacketEntity entity, NamedColor namedColor namedColor == null ? NamedTextColor.WHITE : NamedTextColor.NAMES.value(namedColor.name().toLowerCase()), WrapperPlayServerTeams.OptionData.NONE ))); + + String displayName = entity.getProperty(propertyRegistry.getByName("display_name", String.class)) == null ? entity.getEntityId()+"" : entity.getProperty(propertyRegistry.getByName("display_name", String.class)); + // 这个displayName替换掉原来的变量,是为了 + // '当NPC实体为玩家类型时,隐藏掉NPC头顶上的名称显示 不然会和hologram一起显示 导致有些混淆与冲突' + // This displayName replaces the original variable in order to + // 'hide the name display above the NPC's head when the NPC entity is a player type, otherwise it will be displayed together with the hologram, causing some confusion and conflict' sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, - entity.getType() == EntityTypes.PLAYER ? Integer.toString(entity.getEntityId()) : entity.getUuid().toString())); + entity.getType() == EntityTypes.PLAYER ? displayName : entity.getUuid().toString())); } @Override From cc91951133e2874b1a40650acf79d20fe38e22e5 Mon Sep 17 00:00:00 2001 From: AsukaRyo12 <125512156@qq.com> Date: Mon, 4 Aug 2025 12:58:20 +0800 Subject: [PATCH 3/3] Some model rendering modules or plug-ins may use the entity's creature name to select and replace the NPC model. The previous writing method will cause the player-type NPC to always use a random numeric ID as the entity name. Therefore, in order to solve this problem, I allow NPCs to have custom names. --- .../java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java index 75d8903c..4a760e40 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_20_2PacketFactory.java @@ -18,7 +18,6 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; - public class V1_20_2PacketFactory extends V1_19_3PacketFactory { protected ConfigManager configManager;