From 1373d6e680d9e2e77edebb975cba3e1f434be7db Mon Sep 17 00:00:00 2001 From: InstantlyMoist Date: Thu, 14 May 2026 13:16:22 +0200 Subject: [PATCH] did whatever to fix older client holos --- .../wrapper/hologram/LegacyHologram.java | 4 +- .../wrapper/hologram/ModernHologram.java | 15 ++--- .../main/java/me/tofaa/entitylib/npc/NPC.java | 59 +++++++++++-------- .../me/tofaa/entitylib/npc/NPCMovement.java | 5 +- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/LegacyHologram.java b/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/LegacyHologram.java index b755cf8..1e8da3f 100644 --- a/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/LegacyHologram.java +++ b/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/LegacyHologram.java @@ -157,9 +157,7 @@ public void teleport(Location location) { Location l = new Location(location.getX(), y, location.getZ(), location.getYaw(), location.getPitch()); line.teleport(l, false); } - if (spawned) { - setParent(getEntity()); - } + } @Override diff --git a/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/ModernHologram.java b/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/ModernHologram.java index a0a34d2..3cb27d7 100644 --- a/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/ModernHologram.java +++ b/api/src/main/java/me/tofaa/entitylib/wrapper/hologram/ModernHologram.java @@ -50,20 +50,21 @@ public void hide() { spawned = false; } + private static final float LINE_SPACING = 0.28f; + @Override public void teleport(Location location) { this.location = location; if (lines.isEmpty()) return; - + if (parent != null) { return; } - - WrapperEntity first = lines.get(0); - first.teleport(location); - for (WrapperEntity e : lines) { - if (e.getUuid().equals(first.getUuid())) continue; - first.addPassenger(e); + + for (int i = 0; i < lines.size(); i++) { + double y = location.getY() + (lines.size() - 1 - i) * LINE_SPACING; + Location lineLoc = new Location(location.getX(), y, location.getZ(), location.getYaw(), location.getPitch()); + lines.get(i).teleport(lineLoc); } } diff --git a/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPC.java b/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPC.java index ee59e47..055c4b6 100644 --- a/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPC.java +++ b/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPC.java @@ -29,6 +29,7 @@ import me.tofaa.entitylib.wrapper.WrapperPlayer; import me.tofaa.entitylib.wrapper.hologram.Hologram; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; @@ -319,9 +320,32 @@ public void remove() { NPCRegistry.unregister(this); } + /** + * Splits a Component into multiple lines on {@code
} tags. + * MiniMessage keeps {@code
} as a tag token through serialize/deserialize round-trips, + * so we serialize back to a MiniMessage string and split on the literal {@code
} token + * before re-deserializing each fragment into its own Component. This allows multi-line NPC + * name tags to be rendered as separate hologram line entities, since armor stands and text + * displays do not visually break a single component on newlines. + */ + private List splitDisplayNameLines(Component component) { + MiniMessage mm = MiniMessage.miniMessage(); + String serialized = mm.serialize(component); + // MiniMessage round-trips
as the literal tag string "
" + String[] parts = serialized.split("(?i)
", -1); + if (parts.length == 1) { + return Collections.singletonList(component); + } + List lines = new ArrayList<>(parts.length); + for (String part : parts) { + lines.add(mm.deserialize(part)); + } + return lines; + } + private void createHologram() { Location loc = getPosition(); - double yOffset = options.isSitting() ? 2.76 : 2.26; + double yOffset = options.isSitting() ? 1.1 : 1.0; Location hologramLoc = new Location( loc.getX(), loc.getY() + yOffset, @@ -330,24 +354,15 @@ private void createHologram() { loc.getPitch() ); - int protocolVersion = EntityLib.getApi() - .getPacketEvents() - .getServerManager() - .getVersion() - .getProtocolVersion(); + Hologram.Legacy hologram = Hologram.legacy(hologramLoc); + hologram.setLineOffset(-0.28f); - Hologram hologram; - if (protocolVersion >= 760) { - hologram = Hologram.modern(hologramLoc); - } else { - hologram = Hologram.legacy(hologramLoc); + Component displayName = options.getDisplayName() != null + ? options.getDisplayName() + : Component.text(name); + for (Component line : splitDisplayNameLines(displayName)) { + hologram.addLine(line); } - - hologram.addLine( - options.getDisplayName() != null - ? options.getDisplayName() - : Component.text(name) - ); hologram.show(); // if (hologram.getEntity().getEntityMeta() instanceof AbstractDisplayMeta displayMeta) { //// displayMeta.setTranslation(new Vector3f(0, 0.5f, 0)); @@ -358,12 +373,10 @@ private void createHologram() { private void updateHologram() { if (hologram != null) { - hologram.setLine( - 0, - options.getDisplayName() != null - ? options.getDisplayName() - : Component.text(name) - ); + Component displayName = options.getDisplayName() != null + ? options.getDisplayName() + : Component.text(name); + hologram.setLines(splitDisplayNameLines(displayName)); } } diff --git a/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPCMovement.java b/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPCMovement.java index 8a77c6e..f020d89 100644 --- a/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPCMovement.java +++ b/spaceNPC/src/main/java/me/tofaa/entitylib/npc/NPCMovement.java @@ -94,7 +94,10 @@ private static void processViewerSync() { Location npcLocation = entity.getLocation(); npc.getHologram().ifPresent(hologram -> { - hologram.setParent(npc.getEntity().get()); + boolean isSittingNow = npc.getOptions().isSitting(); + double yOff = isSittingNow ? 1.1 : 1.0; + Location npcLoc = npc.getEntity().get().getLocation(); + hologram.teleport(new Location(npcLoc.getX(), npcLoc.getY() + yOff, npcLoc.getZ(), npcLoc.getYaw(), npcLoc.getPitch())); }); boolean permanentlyVisible = npc.getOptions().isPermanentlyVisible();