diff --git a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java index 9b6029de1..4ed1f73b8 100644 --- a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java @@ -11,6 +11,7 @@ import java.util.stream.IntStream; import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.command.CommandSender; @@ -25,6 +26,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.util.Transformation; import org.joml.Vector3d; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; @@ -75,7 +77,7 @@ public class HologramTrait extends Trait { * The new line to add */ public void addLine(String text) { - lines.add(new HologramLine(text, true)); + lines.add(new HologramLine(text, true, -1, createDefaultHologramRenderer())); reloadLineHolograms(); } @@ -94,7 +96,7 @@ public class HologramTrait extends Trait { * The number of ticks to last for */ public void addTemporaryLine(String text, int ticks) { - lines.add(new HologramLine(text, false, ticks)); + lines.add(new HologramLine(text, false, ticks, createDefaultHologramRenderer())); reloadLineHolograms(); } @@ -113,6 +115,23 @@ public class HologramTrait extends Trait { lines.clear(); } + private HologramRenderer createDefaultHologramRenderer() { + String hologramSetting = Setting.DEFAULT_HOLOGRAM_RENDERER.asString(); + if (!SUPPORTS_DISPLAY || hologramSetting.equalsIgnoreCase("armorstand")) + return new ArmorstandRenderer(); + return hologramSetting.equalsIgnoreCase("interaction") ? new InteractionVehicleRenderer() + : new TextDisplayVehicleRenderer(); + } + + private HologramRenderer createNameRenderer() { + if (SpigotUtil.getVersion()[1] >= 20) { + return new TextDisplayVehicleRenderer(); + } else if (SpigotUtil.getVersion()[1] == 19) { + return new InteractionVehicleRenderer(); + } + return new ArmorstandVehicleRenderer(); + } + private double getEntityBbHeight() { return NMS.getBoundingBoxHeight(npc.getEntity()); } @@ -129,9 +148,13 @@ public class HologramTrait extends Trait { return base; } + @Deprecated public Collection getHologramEntities() { - return lines.stream().filter(l -> l.renderer.getEntity() != null).map(l -> l.renderer.getEntity()) - .collect(Collectors.toList()); + return lines.stream().flatMap(l -> l.renderer.getEntities().stream()).collect(Collectors.toList()); + } + + public Collection getHologramRenderers() { + return lines.stream().map(l -> l.renderer).collect(Collectors.toList()); } /** @@ -148,8 +171,14 @@ public class HologramTrait extends Trait { return Lists.transform(lines, l -> l.text); } + @Deprecated public Entity getNameEntity() { - return nameLine == null ? null : nameLine.renderer.getEntity(); + return nameLine == null || nameLine.renderer.getEntities().size() == 0 ? null + : nameLine.renderer.getEntities().iterator().next(); + } + + public HologramRenderer getNameRenderer() { + return nameLine == null ? null : nameLine.renderer; } public int getViewRange() { @@ -161,7 +190,7 @@ public class HologramTrait extends Trait { clear(); for (DataKey key : root.getRelative("lines").getIntegerSubKeys()) { HologramLine line = new HologramLine(key.keyExists("text") ? key.getString("text") : key.getString(""), - true); + true, -1, createDefaultHologramRenderer()); line.mt = key.keyExists("margin.top") ? key.getDouble("margin.top") : 0.0; line.mb = key.keyExists("margin.bottom") ? key.getDouble("margin.bottom") : 0.0; lines.add(line); @@ -224,8 +253,7 @@ public class HologramTrait extends Trait { nameLine.removeNPC(); nameLine = null; } else if (nameLine == null && nameplateVisible) { - nameLine = new HologramLine(npc.getRawName(), - SUPPORTS_DISPLAY ? new InteractionVehicleRenderer() : new ArmorstandVehicleRenderer()); + nameLine = new HologramLine(npc.getRawName(), createNameRenderer()); } } Location npcLoc = npc.getStoredLocation(); @@ -247,7 +275,7 @@ public class HologramTrait extends Trait { lastEntityBbHeight = getEntityBbHeight(); } if (nameLine != null) { - if (updatePosition) { + if (updatePosition || nameLine.renderer.getEntities().size() == 0) { nameLine.render(offset); } if (updateName) { @@ -261,7 +289,7 @@ public class HologramTrait extends Trait { lines.remove(i--).removeNPC(); continue; } - if (updatePosition || line.renderer.getEntity() == null) { + if (updatePosition || line.renderer.getEntities().size() == 0) { offset.y = getHeight(i); line.render(offset); } @@ -379,26 +407,6 @@ public class HologramTrait extends Trait { String text; int ticks; - public HologramLine(String text, boolean persist) { - this(text, persist, -1, - SUPPORTS_DISPLAY && Setting.DEFAULT_HOLOGRAM_RENDERER.asString().equalsIgnoreCase("interaction") - ? new InteractionVehicleRenderer() - : SUPPORTS_DISPLAY - && Setting.DEFAULT_HOLOGRAM_RENDERER.asString().equalsIgnoreCase("display") - ? new TextDisplayVehicleRenderer() - : new ArmorstandRenderer()); - } - - public HologramLine(String text, boolean persist, int ticks) { - this(text, persist, ticks, - SUPPORTS_DISPLAY && Setting.DEFAULT_HOLOGRAM_RENDERER.asString().equalsIgnoreCase("interaction") - ? new InteractionVehicleRenderer() - : SUPPORTS_DISPLAY - && Setting.DEFAULT_HOLOGRAM_RENDERER.asString().equalsIgnoreCase("display") - ? new TextDisplayVehicleRenderer() - : new ArmorstandRenderer()); - } - public HologramLine(String text, boolean persist, int ticks, HologramRenderer hr) { if (ITEM_MATCHER.matcher(text).find()) { mb = 0.21; @@ -438,8 +446,7 @@ public class HologramTrait extends Trait { public static interface HologramRenderer { void destroy(); - @Deprecated - Entity getEntity(); + Collection getEntities(); String getPerPlayerText(NPC npc, Player viewer); @@ -468,7 +475,6 @@ public class HologramTrait extends Trait { public void onSeenByPlayer(Player player) { if (lastOffset == null) return; - Messaging.debug("Linking", player, hologram.getEntity()); NMS.linkTextInteraction(player, hologram.getEntity(), npc.getEntity(), lastOffset.y); } @@ -585,8 +591,8 @@ public class HologramTrait extends Trait { } @Override - public Entity getEntity() { - return hologram != null ? hologram.getEntity() : null; + public Collection getEntities() { + return hologram != null ? ImmutableList.of(hologram.getEntity()) : Collections.emptyList(); } @Override @@ -648,9 +654,13 @@ public class HologramTrait extends Trait { } public class TextDisplayVehicleRenderer extends SingleEntityHologramRenderer { + private Color color; + @Override protected NPC createNPC(Entity base, String name, Vector3d offset) { - NPC npc = registry.createNPC(EntityType.TEXT_DISPLAY, name); + NPC npc = registry.createNPC(EntityType.TEXT_DISPLAY, ""); + npc.data().set(NPC.Metadata.NAMEPLATE_VISIBLE, false); + npc.data().set(NPC.Metadata.TEXT_DISPLAY_COMPONENT, Messaging.minecraftComponentFromRawMessage(name)); return npc; } @@ -661,10 +671,25 @@ public class HologramTrait extends Trait { Transformation tf = disp.getTransformation(); tf.getTranslation().y = (float) offset.y + 0.2f; disp.setTransformation(tf); + if (color != null) { + disp.setBackgroundColor(color); + } if (hologram.getEntity().getVehicle() == null) { base.getEntity().addPassenger(hologram.getEntity()); } } + + public void setBackgroundColor(Color color) { + this.color = color; + } + + @Override + public void updateText(NPC npc, String raw) { + this.text = Placeholders.replace(raw, null, npc); + if (hologram == null) + return; + npc.data().set(NPC.Metadata.TEXT_DISPLAY_COMPONENT, Messaging.minecraftComponentFromRawMessage(text)); + } } private static final Pattern ITEM_MATCHER = Pattern.compile(""); diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index d3bc72562..2673a325d 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -906,6 +906,10 @@ public class NMS { BRIDGE.setTeamNameTagVisible(team, visible); } + public static void setTextDisplayComponent(Entity entity, Object component) { + BRIDGE.setTextDisplayComponent(entity, component); + } + public static void setVerticalMovement(Entity bukkitEntity, double d) { BRIDGE.setVerticalMovement(bukkitEntity, d); } diff --git a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java index 608dcbbf0..65083a490 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java +++ b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java @@ -100,6 +100,10 @@ public interface NMSBridge { public GameProfile getProfile(SkullMeta meta); + public default float getRidingHeightOffset(Entity entity, Entity mount) { + return 0; + } + public String getSoundPath(Sound flag) throws CommandException; public Entity getSource(BlockCommandSender sender); @@ -266,6 +270,9 @@ public interface NMSBridge { team.setOption(Team.Option.NAME_TAG_VISIBILITY, visible ? Team.OptionStatus.ALWAYS : Team.OptionStatus.NEVER); } + public default void setTextDisplayComponent(Entity entity, Object component) { + } + public void setVerticalMovement(Entity bukkitEntity, double d); public default void setWardenPose(Entity entity, Object pose) { diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java index 681a70a8f..96a2162d2 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java @@ -16,6 +16,7 @@ import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.util.Util; import net.minecraft.core.PositionImpl; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.Display.TextDisplay; @@ -113,6 +114,11 @@ public class TextDisplayController extends MobEntityController { super.tick(); if (npc != null) { npc.update(); + Component component = npc.data().get(NPC.Metadata.TEXT_DISPLAY_COMPONENT); + if (component != null) { + setText(component); + npc.data().remove(NPC.Metadata.TEXT_DISPLAY_COMPONENT); + } } } diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java index b5a4a3bb0..45975b0d3 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java @@ -734,6 +734,11 @@ public class NMSImpl implements NMSBridge { } } + @Override + public float getRidingHeightOffset(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity mount) { + return (float) (getHandle(mount).getPassengersRidingOffset() - 0.5D); + } + @Override public String getSoundPath(Sound flag) throws CommandException { try { @@ -1500,13 +1505,7 @@ public class NMSImpl implements NMSBridge { @Override public void setCustomName(org.bukkit.entity.Entity entity, Object component, String string) { - if (getHandle(entity) instanceof net.minecraft.world.entity.Display.TextDisplay) { - net.minecraft.world.entity.Display.TextDisplay disp = (net.minecraft.world.entity.Display.TextDisplay) getHandle( - entity); - disp.setText((Component) component); - } else { - getHandle(entity).setCustomName((Component) component); - } + getHandle(entity).setCustomName((Component) component); } @Override @@ -1712,6 +1711,13 @@ public class NMSImpl implements NMSBridge { getHandle(entity).setMaxUpStep(height); } + @Override + public void setTextDisplayComponent(org.bukkit.entity.Entity entity, Object component) { + net.minecraft.world.entity.Display.TextDisplay disp = (net.minecraft.world.entity.Display.TextDisplay) getHandle( + entity); + disp.setText((Component) component); + } + @Override public void setVerticalMovement(org.bukkit.entity.Entity bukkitEntity, double d) { if (!bukkitEntity.getType().isAlive()) diff --git a/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java b/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java index fe4de1313..b8979b926 100644 --- a/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java +++ b/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java @@ -14,6 +14,7 @@ import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.util.Util; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.Display.TextDisplay; @@ -103,6 +104,11 @@ public class TextDisplayController extends MobEntityController { super.tick(); if (npc != null) { npc.update(); + Component component = npc.data().get(NPC.Metadata.TEXT_DISPLAY_COMPONENT); + if (component != null) { + setText(component); + npc.data().remove(NPC.Metadata.TEXT_DISPLAY_COMPONENT); + } } } diff --git a/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/util/NMSImpl.java b/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/util/NMSImpl.java index 6ce378791..a41cb1b5e 100644 --- a/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/util/NMSImpl.java +++ b/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/util/NMSImpl.java @@ -709,6 +709,11 @@ public class NMSImpl implements NMSBridge { } } + @Override + public float getRidingHeightOffset(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity mount) { + return getHandle(entity).getMyRidingOffset(getHandle(mount)); + } + @Override public String getSoundPath(Sound flag) throws CommandException { try { @@ -1470,13 +1475,7 @@ public class NMSImpl implements NMSBridge { @Override public void setCustomName(org.bukkit.entity.Entity entity, Object component, String string) { - if (getHandle(entity) instanceof net.minecraft.world.entity.Display.TextDisplay) { - net.minecraft.world.entity.Display.TextDisplay disp = (net.minecraft.world.entity.Display.TextDisplay) getHandle( - entity); - disp.setText((Component) component); - } else { - getHandle(entity).setCustomName((Component) component); - } + getHandle(entity).setCustomName((Component) component); } @Override @@ -1674,6 +1673,13 @@ public class NMSImpl implements NMSBridge { getHandle(entity).setMaxUpStep(height); } + @Override + public void setTextDisplayComponent(org.bukkit.entity.Entity entity, Object component) { + net.minecraft.world.entity.Display.TextDisplay disp = (net.minecraft.world.entity.Display.TextDisplay) getHandle( + entity); + disp.setText((Component) component); + } + @Override public void setVerticalMovement(org.bukkit.entity.Entity bukkitEntity, double d) { if (!bukkitEntity.getType().isAlive())