diff --git a/build.gradle.kts b/build.gradle.kts index 0479b3d..05d1757 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -77,7 +77,7 @@ tasks { hangar("ViaBackwards", "5.0.1") // For testing groups in config.yml - url("https://download.luckperms.net/1556/bukkit/loader/LuckPerms-Bukkit-5.4.141.jar") +// url("https://download.luckperms.net/1556/bukkit/loader/LuckPerms-Bukkit-5.4.141.jar") } } } diff --git a/src/main/java/com/mattmx/nametags/OutgoingPacketListener.java b/src/main/java/com/mattmx/nametags/OutgoingPacketListener.java index 76c70ec..d4ef392 100644 --- a/src/main/java/com/mattmx/nametags/OutgoingPacketListener.java +++ b/src/main/java/com/mattmx/nametags/OutgoingPacketListener.java @@ -13,13 +13,19 @@ import com.github.retrooper.packetevents.util.Vector3f; import com.github.retrooper.packetevents.wrapper.play.server.*; import com.mattmx.nametags.entity.NameTagEntity; -import me.tofaa.entitylib.meta.display.TextDisplayMeta; +import me.clip.placeholderapi.PlaceholderAPI; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.Arrays; public class OutgoingPacketListener extends PacketListenerAbstract { - private static final Vector3f PRE_1_20_2_TRANSLATION = new Vector3f(0f, 0.4f, 0f); + private static final byte TEXT_DISPLAY_TEXT_INDEX = 23; + private static final byte PRE_1_20_2_TRANSLATION_INDEX = 10; + private static final byte POST_1_20_2_TRANSLATION_INDEX = 10; + private static final Vector3f PRE_1_20_2_TRANSLATION_OFFSET = new Vector3f(0f, 0.4f, 0f); private final @NotNull NameTags plugin; public OutgoingPacketListener(@NotNull NameTags plugin) { @@ -50,38 +56,66 @@ public void onPacketSend(@NotNull PacketSendEvent event) { }); } case PacketType.Play.Server.ENTITY_METADATA -> { - if (event.getUser().getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_2)) { - return; - } - WrapperPlayServerEntityMetadata packet = new WrapperPlayServerEntityMetadata(event); NameTagEntity nameTagEntity = plugin.getEntityManager().getNameTagEntityByTagEntityId(packet.getEntityId()); if (nameTagEntity == null) return; - byte index = PacketEvents.getAPI() - .getServerManager() - .getVersion() - .is(VersionComparison.OLDER_THAN, ServerVersion.V_1_20_2) - ? (byte) 10 - : (byte) 11; - - packet.getEntityMetadata() - .stream() - .filter((meta) -> meta.getIndex() == index) - .findFirst() - .ifPresentOrElse((data) -> { - Vector3f vec = (Vector3f) data.getValue(); - data.setValue(vec.add(PRE_1_20_2_TRANSLATION)); - }, () -> packet.getEntityMetadata().add(new EntityData( - index, - EntityDataTypes.VECTOR3F, - PRE_1_20_2_TRANSLATION - )) - ); - - event.markForReEncode(true); + // Backwards compatibility for clients older than 1.20.2 + // Mojank changed the passenger origin point when riding an entity so the tag appears inside their head. + if (event.getUser().getClientVersion().isOlderThan(ClientVersion.V_1_20_2)) { + + byte index = PacketEvents.getAPI() + .getServerManager() + .getVersion() + .is(VersionComparison.OLDER_THAN, ServerVersion.V_1_20_2) + ? PRE_1_20_2_TRANSLATION_INDEX + : POST_1_20_2_TRANSLATION_INDEX; + + packet.getEntityMetadata() + .stream() + .filter((meta) -> meta.getIndex() == index) + .findFirst() + .ifPresentOrElse((data) -> { + Vector3f vec = (Vector3f) data.getValue(); + data.setValue(vec.add(PRE_1_20_2_TRANSLATION_OFFSET)); + }, () -> packet.getEntityMetadata().add(new EntityData( + index, + EntityDataTypes.VECTOR3F, + PRE_1_20_2_TRANSLATION_OFFSET + )) + ); + event.markForReEncode(true); + } + + // Apply relational placeholders to the text of an outgoing display entity + if (nameTagEntity.getBukkitEntity() instanceof Player from) { + packet.getEntityMetadata() + .stream() + .filter((meta) -> meta.getIndex() == TEXT_DISPLAY_TEXT_INDEX && meta.getValue() instanceof Component) + .findFirst() + .ifPresent((data) -> { + final Component originalText = (Component) data.getValue(); + final Player to = event.getPlayer(); + + // TODO(Matt): Replace use of legacy serializer + String legacy = LegacyComponentSerializer + .legacyAmpersand() + .serialize(originalText); + + final Component appliedText = LegacyComponentSerializer + .legacyAmpersand() + .deserialize(PlaceholderAPI.setRelationalPlaceholders(from, to, legacy)); + + if (!originalText.equals(appliedText)) { + + data.setValue(appliedText); + + event.markForReEncode(true); + } + }); + } } case PacketType.Play.Server.DESTROY_ENTITIES -> { WrapperPlayServerDestroyEntities packet = new WrapperPlayServerDestroyEntities(event); diff --git a/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java b/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java index 74c16ae..911cb20 100644 --- a/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java +++ b/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java @@ -63,8 +63,6 @@ public void registerDefaultRefreshListener(@NotNull NameTagEntity tag, long refr refreshMillis, (entity) -> { synchronized (entity) { - - // TODO we need to change the text based off the player the packet is being sent to. TextDisplayMetaConfiguration.applyMeta(defaultSection(), entity.getMeta()); TextDisplayMetaConfiguration.applyTextMeta(defaultSection(), entity.getMeta(), player, player); diff --git a/src/main/java/com/mattmx/nametags/config/TextDisplayMetaConfiguration.java b/src/main/java/com/mattmx/nametags/config/TextDisplayMetaConfiguration.java index ef636d6..0503317 100644 --- a/src/main/java/com/mattmx/nametags/config/TextDisplayMetaConfiguration.java +++ b/src/main/java/com/mattmx/nametags/config/TextDisplayMetaConfiguration.java @@ -26,7 +26,6 @@ public static boolean applyTextMeta(@NotNull ConfigurationSection section, @NotN .stream() .map((line) -> convertToComponent(self, sender, line)); - // TODO(matt): Test if (NameTags.getInstance().getConfig().getBoolean("defaults.remove-empty-lines", false)) { stream = stream.filter(TextComponent.IS_NOT_EMPTY); }