diff --git a/build.gradle.kts b/build.gradle.kts index 8044464..53d94ed 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -79,11 +79,11 @@ tasks { minecraftVersion(mcVersion) downloadPlugins { - hangar("ViaVersion", "5.3.1") - hangar("ViaBackwards", "5.3.1") + hangar("ViaVersion", "5.3.2") + hangar("ViaBackwards", "5.3.2") // For testing groups in config.yml - url("https://download.luckperms.net/1567/bukkit/loader/LuckPerms-Bukkit-5.4.150.jar") + modrinth("luckperms", "v5.4.145-bukkit") } } } diff --git a/src/main/java/com/mattmx/nametags/DependencyVersionChecker.java b/src/main/java/com/mattmx/nametags/DependencyVersionChecker.java new file mode 100644 index 0000000..a6c1fdf --- /dev/null +++ b/src/main/java/com/mattmx/nametags/DependencyVersionChecker.java @@ -0,0 +1,29 @@ +package com.mattmx.nametags; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.PacketEventsAPI; +import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.util.PEVersion; +import net.kyori.adventure.text.Component; + +public class DependencyVersionChecker { + + public static void checkPacketEventsVersion() { + final PacketEventsAPI> api = PacketEvents.getAPI(); + + boolean isOutdated = api.getVersion().isOlderThan(PEVersion.fromString("2.7.0")); + boolean isUnsupported = api.getServerManager().getVersion().isNewerThan(ServerVersion.V_1_21_4); + + if (isOutdated && isUnsupported) { + NameTags.getInstance().getComponentLogger().warn(Component.text(""" + + ⚠ PacketEvents version 2.7.0 does not support versions newer than 1.21.4! + + Please update to a development 2.8.0 build that adds 1.21.5+ support. + https://ci.codemc.io/job/retrooper/job/packetevents/ + + """)); + } + } + +} diff --git a/src/main/java/com/mattmx/nametags/EventsListener.java b/src/main/java/com/mattmx/nametags/EventsListener.java index 517a106..e34ac6f 100644 --- a/src/main/java/com/mattmx/nametags/EventsListener.java +++ b/src/main/java/com/mattmx/nametags/EventsListener.java @@ -12,6 +12,7 @@ import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; import org.jetbrains.annotations.NotNull; +import org.spigotmc.event.player.PlayerSpawnLocationEvent; import java.util.concurrent.TimeUnit; @@ -25,7 +26,7 @@ public EventsListener(@NotNull NameTags plugin) { @EventHandler public void onPlayerJoin(@NotNull PlayerJoinEvent event) { - Bukkit.getAsyncScheduler().runDelayed(plugin, (task) -> { + Bukkit.getAsyncScheduler().runNow(plugin, (task) -> { if (!event.getPlayer().isOnline()) { return; } @@ -33,7 +34,7 @@ public void onPlayerJoin(@NotNull PlayerJoinEvent event) { plugin.getEntityManager() .getOrCreateNameTagEntity(event.getPlayer()) .updateVisibility(); - }, 50L, TimeUnit.MILLISECONDS); + }); } diff --git a/src/main/java/com/mattmx/nametags/NameTags.java b/src/main/java/com/mattmx/nametags/NameTags.java index 20550de..da3a865 100644 --- a/src/main/java/com/mattmx/nametags/NameTags.java +++ b/src/main/java/com/mattmx/nametags/NameTags.java @@ -9,8 +9,6 @@ import com.mattmx.nametags.hook.NeznamyTABHook; import com.mattmx.nametags.hook.SkinRestorerHook; import com.mattmx.nametags.utils.Metrics; -import com.mattmx.nametags.utils.test.TestPassenger; -import com.mattmx.nametags.utils.test.TestPlaceholderExpansion; import me.tofaa.entitylib.APIConfig; import me.tofaa.entitylib.EntityLib; import me.tofaa.entitylib.spigot.SpigotEntityLibPlatform; @@ -40,6 +38,7 @@ public class NameTags extends JavaPlugin { private EventsListener eventsListener; private OutgoingPacketListener packetListener; private Metrics metrics; + private @Nullable ConfigDefaultsListener defaultsListener = null; @Override public void onEnable() { @@ -62,16 +61,8 @@ public void onEnable() { .build() ); - ConfigurationSection defaults = getConfig().getConfigurationSection("defaults"); - if (defaults != null && defaults.getBoolean("enabled")) { - Bukkit.getPluginManager().registerEvents(new ConfigDefaultsListener(this), this); - } - SpigotEntityLibPlatform platform = new SpigotEntityLibPlatform(this); - APIConfig settings = new APIConfig(PacketEvents.getAPI()) -// .tickTickables() -// .trackPlatformEntities() - .usePlatformLogger(); + APIConfig settings = new APIConfig(PacketEvents.getAPI()).usePlatformLogger(); EntityLib.init(platform, settings); @@ -84,15 +75,27 @@ public void onEnable() { SkinRestorerHook.inject(this); Bukkit.getPluginManager().registerEvents(eventsListener, this); + Bukkit.getScheduler().runTaskLater(this, DependencyVersionChecker::checkPacketEventsVersion, 10L); Objects.requireNonNull(Bukkit.getPluginCommand("nametags-reload")).setExecutor(new NameTagsCommand(this)); - } @Override public void reloadConfig() { super.reloadConfig(); + ConfigurationSection defaults = getConfig().getConfigurationSection("defaults"); + if (defaults != null && defaults.getBoolean("enabled")) { + getLogger().info("Using default behaviour from the config file."); + + if (defaultsListener != null) { + HandlerList.unregisterAll(defaultsListener); + } + + defaultsListener = new ConfigDefaultsListener(this); + Bukkit.getPluginManager().registerEvents(defaultsListener, this); + } + String textFormatterIdentifier = getConfig().getString("formatter", "minimessage"); formatter = TextFormatter.getById(textFormatterIdentifier) .orElse(TextFormatter.MINI_MESSAGE); diff --git a/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java b/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java index 2b2128b..b9fd599 100644 --- a/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java +++ b/src/main/java/com/mattmx/nametags/config/ConfigDefaultsListener.java @@ -28,6 +28,8 @@ public ConfigDefaultsListener(@NotNull NameTags plugin) { .getEntityManager() .setDefaultProvider(((entity, meta) -> { meta.setUseDefaultBackground(false); + meta.setTransformationInterpolationDuration(5); + meta.setPositionRotationInterpolationDuration(5); TextDisplayMetaConfiguration.applyMeta(defaultSection(), meta); })); } diff --git a/src/main/java/com/mattmx/nametags/packet/PlayServerEntityMetaDataHandler.java b/src/main/java/com/mattmx/nametags/packet/PlayServerEntityMetaDataHandler.java index 91e9dee..ee80ce1 100644 --- a/src/main/java/com/mattmx/nametags/packet/PlayServerEntityMetaDataHandler.java +++ b/src/main/java/com/mattmx/nametags/packet/PlayServerEntityMetaDataHandler.java @@ -23,15 +23,15 @@ * Responsible for two things: *
* 1. Modifying the passenger entity Y offset, since Mojang changed the - * entity passenger origin by a small amount, which results in the name - * tags rendering inside a player's head in older versions. + * entity passenger origin by a small amount, which results in the name + * tags rendering inside a player's head in older versions. *
- * To fix this, the function will apply an offset of +0.4f in the Y - * axis, which was the closest value found to how it should appear in - * modern versions. + * To fix this, the function will apply an offset of +0.4f in the Y + * axis, which was the closest value found to how it should appear in + * modern versions. *
* 2. Apply relational placeholders (off the netty thread) if there are - * any. + * any. */ public class PlayServerEntityMetaDataHandler { private static final byte TEXT_DISPLAY_TEXT_INDEX = 23; @@ -50,75 +50,80 @@ public class PlayServerEntityMetaDataHandler { public static void handlePacket(@NotNull PacketSendEvent event) { final NameTags plugin = NameTags.getInstance(); - final WrapperPlayServerEntityMetadata packet = new WrapperPlayServerEntityMetadata(event); - final NameTagEntity nameTagEntity = plugin.getEntityManager().getNameTagEntityByTagEntityId(packet.getEntityId()); + final PacketSendEvent eventClone = event.clone(); + final WrapperPlayServerEntityMetadata packet0 = new WrapperPlayServerEntityMetadata(event); - if (nameTagEntity == null) return; + final NameTagEntity nameTagEntity = plugin.getEntityManager().getNameTagEntityByTagEntityId(packet0.getEntityId()); - boolean isOldClient = event.getUser().getClientVersion().isOlderThan(ClientVersion.V_1_20_2); - boolean containsEntityOffset = false; - @Nullable EntityData textEntry = null; + if (nameTagEntity == null) { + eventClone.cleanUp(); + return; + } - for (final EntityData entry : packet.getEntityMetadata()) { - if (containsEntityOffset && textEntry != null) { - break; - } + event.setCancelled(true); + final WrapperPlayServerEntityMetadata packet = new WrapperPlayServerEntityMetadata(eventClone); + + // This could prove a concurrency issue, maybe we should keep track of if there is a newer packet processing? + plugin.getExecutor().execute(() -> { + boolean isOldClient = eventClone.getUser() + .getClientVersion() + .isOlderThan(ClientVersion.V_1_20_2); + + boolean containsEntityOffset = false; + @Nullable EntityData textEntry = null; + + for (final EntityData entry : packet.getEntityMetadata()) { + if (containsEntityOffset && textEntry != null) { + break; + } - if (isOldClient && entry.getIndex() == ENTITY_OFFSET_INDEX) { - Vector3f vec = (Vector3f) entry.getValue(); - entry.setValue(vec.add(PRE_1_20_2_TRANSLATION_OFFSET)); + if (isOldClient && entry.getIndex() == ENTITY_OFFSET_INDEX) { + Vector3f vec = (Vector3f) entry.getValue(); + // If there is already an entity offset, and it's an old client, add to it. + entry.setValue(vec.add(PRE_1_20_2_TRANSLATION_OFFSET)); - containsEntityOffset = true; - event.markForReEncode(true); - } else if (entry.getIndex() == TEXT_DISPLAY_TEXT_INDEX) { - textEntry = entry; - event.markForReEncode(true); + containsEntityOffset = true; + } else if (entry.getIndex() == TEXT_DISPLAY_TEXT_INDEX) { + textEntry = entry; + } } - } - // 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 (isOldClient) { - // If there was no offset found then add one ourselves for the offset. - if (!containsEntityOffset) { + // 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 (isOldClient && !containsEntityOffset) { + // If there was no offset found then add one ourselves for the offset. packet.getEntityMetadata().add(new EntityData( ENTITY_OFFSET_INDEX, EntityDataTypes.VECTOR3F, PRE_1_20_2_TRANSLATION_OFFSET )); - event.markForReEncode(true); } - } - - // Apply relational placeholders to the text of an outgoing display entity - if (plugin.getConfig().getBoolean("options.relative-placeholders-support") && - nameTagEntity.getBukkitEntity() instanceof Player from && - textEntry != null - ) { - final TextComponent originalText = (TextComponent) textEntry.getValue(); - final Player to = event.getPlayer(); - // If this proves to increase ping, since it does require string processing - // I recommend always withholding the packet if it contains the textEntry, - // then we can process all of this off the main thread - boolean containsRelativePlaceholder = ComponentUtils.startsWith(originalText, RELATIVE_ARG_PREFIX); + // Apply relational placeholders to the text of an outgoing display entity + if (plugin.getConfig().getBoolean("options.relative-placeholders-support") && + nameTagEntity.getBukkitEntity() instanceof Player from && + textEntry != null + ) { + final TextComponent originalText = (TextComponent) textEntry.getValue(); + final Player to = eventClone.getPlayer(); - // If it doesn't have any placeholders in then stop - if (!containsRelativePlaceholder) return; + boolean containsRelativePlaceholder = ComponentUtils.startsWith(originalText, RELATIVE_ARG_PREFIX); - // Withhold the packet while we apply placeholders - event.setCancelled(true); + // If it doesn't have any placeholders in then stop + if (!containsRelativePlaceholder) { + eventClone.getUser().sendPacketSilently(packet); + return; + } - final PacketSendEvent clone = event.clone(); - final EntityData finalTextEntry = textEntry; - plugin.getExecutor().execute(() -> { final Component textWithRelativeApplied = PapiHook.setRelationalPlaceholders(from, to, originalText); - finalTextEntry.setValue(textWithRelativeApplied); - clone.getUser().sendPacket(packet); - }); - } + textEntry.setValue(textWithRelativeApplied); + eventClone.getUser().sendPacketSilently(packet); + } else { + eventClone.getUser().sendPacketSilently(packet); + } + }); } } diff --git a/src/main/java/com/mattmx/nametags/packet/PlayServerSpawnEntityHandler.java b/src/main/java/com/mattmx/nametags/packet/PlayServerSpawnEntityHandler.java index fb5670d..1a4ae9e 100644 --- a/src/main/java/com/mattmx/nametags/packet/PlayServerSpawnEntityHandler.java +++ b/src/main/java/com/mattmx/nametags/packet/PlayServerSpawnEntityHandler.java @@ -7,8 +7,9 @@ import org.jetbrains.annotations.NotNull; /** - * Responsible for appending the passenger packet with the - * name tag entity when sending a [WrapperPlayServerSpawnEntity] + * Responsible for appending the name tag spawn packet and + * passenger packet with the name tag entity when sending + * a [WrapperPlayServerSpawnEntity] * packet to the client. */ public class PlayServerSpawnEntityHandler { diff --git a/src/test/java/com/mattmx/nametags/config/TextFormatterTest.java b/src/test/java/com/mattmx/nametags/config/TextFormatterTest.java deleted file mode 100644 index 20fbf17..0000000 --- a/src/test/java/com/mattmx/nametags/config/TextFormatterTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.mattmx.nametags.config; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -public class TextFormatterTest { - - @ParameterizedTest - @CsvSource({ - "&x&c&7&0&0&3&9[Admin],c70039[Admin]", - "&x&9&0&0&c&3&fCoyotea&r,΄c3fCoyotea&r", - "&x&9&0&0&c&3&fCoyotea,΄c3fCoyotea", - "&x&c&7&0&0&3&9[Admin] &x&9&0&0&c&3&fCoyotea&r,c70039[Admin] ΄c3fCoyotea&r" - }) - public void test_convertLegacyHex(String input, String expectedOut) { - final String out = TextFormatter.convertLegacyHex(input); - - Assertions.assertEquals(expectedOut, out); - } - -} \ No newline at end of file