diff --git a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java index 98e517d24..430f26432 100644 --- a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -13,7 +14,6 @@ import org.bukkit.entity.EntityType; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.inventory.ItemStack; -import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import net.citizensnpcs.Settings.Setting; @@ -26,10 +26,10 @@ import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.TraitName; import net.citizensnpcs.api.util.Colorizer; import net.citizensnpcs.api.util.DataKey; -import net.citizensnpcs.api.util.Messaging; import net.citizensnpcs.api.util.Placeholders; import net.citizensnpcs.api.util.SpigotUtil; import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; /** * Persists a hologram attached to the NPC. @@ -43,7 +43,6 @@ public class HologramTrait extends Trait { private boolean lastNameplateVisible; @Persist private double lineHeight = -1; - private final List lineHolograms = Lists.newArrayList(); private final List lines = Lists.newArrayList(); private NPC nameNPC; private final NPCRegistry registry = CitizensAPI.createCitizensBackedNPCRegistry(new MemoryNPCDataStore()); @@ -74,14 +73,17 @@ public class HologramTrait extends Trait { */ public void addTemporaryLine(String text, int ticks) { lines.add(new HologramLine(text, false, ticks)); + reloadLineHolograms(); } /** * Clears all hologram lines */ public void clear() { + for (HologramLine line : lines) { + line.removeNPC(); + } lines.clear(); - reloadLineHolograms(); } private NPC createHologram(String line, double heightOffset) { @@ -96,6 +98,10 @@ public class HologramTrait extends Trait { Material item = SpigotUtil.isUsing1_13API() ? Material.matchMaterial(itemMatcher.group(1), false) : Material.matchMaterial(itemMatcher.group(1)); NPC itemNPC = registry.createNPCUsingItem(EntityType.DROPPED_ITEM, "", new ItemStack(item, 1)); + if (itemMatcher.groupCount() > 1) { + itemNPC.getOrAddTrait(ScoreboardTrait.class) + .setColor(Util.matchEnum(ChatColor.values(), itemMatcher.group(2))); + } itemNPC.spawn(currentLoc); ((ArmorStand) hologramNPC.getEntity()).addPassenger(itemNPC.getEntity()); itemNPC.addRunnable(new Runnable() { @@ -130,7 +136,8 @@ public class HologramTrait extends Trait { * Note: this is implementation-specific and may be removed at a later date. */ public Collection getHologramEntities() { - return Collections2.transform(lineHolograms, (n) -> (ArmorStand) n.getEntity()); + return lines.stream().filter(l -> l.hologram != null && l.hologram.getEntity() != null) + .map(l -> (ArmorStand) l.hologram.getEntity()).collect(Collectors.toList()); } /** @@ -160,7 +167,7 @@ public class HologramTrait extends Trait { @Override public void load(DataKey root) { - lines.clear(); + clear(); for (DataKey key : root.getRelative("lines").getIntegerSubKeys()) { lines.add(new HologramLine(key.getString(""), true)); } @@ -172,10 +179,10 @@ public class HologramTrait extends Trait { nameNPC.destroy(); nameNPC = null; } - for (NPC npc : lineHolograms) { - npc.destroy(); + + for (HologramLine line : lines) { + line.removeNPC(); } - lineHolograms.clear(); } @Override @@ -187,6 +194,7 @@ public class HologramTrait extends Trait { public void onSpawn() { if (!npc.isSpawned()) return; + lastNameplateVisible = Boolean .parseBoolean(npc.data(). get(NPC.Metadata.NAMEPLATE_VISIBLE, true).toString()); currentLoc = npc.getStoredLocation(); @@ -195,21 +203,20 @@ public class HologramTrait extends Trait { } for (int i = 0; i < lines.size(); i++) { - lineHolograms.add(createHologram(Placeholders.replace(lines.get(i).text, null, npc), getHeight(i))); + lines.get(i).spawnNPC(getHeight(i)); } } private void reloadLineHolograms() { - for (NPC npc : lineHolograms) { - npc.destroy(); + for (HologramLine line : lines) { + line.removeNPC(); } - lineHolograms.clear(); if (!npc.isSpawned()) return; for (int i = 0; i < lines.size(); i++) { - lineHolograms.add(createHologram(Placeholders.replace(lines.get(i).text, null, npc), getHeight(i))); + lines.get(i).spawnNPC(getHeight(i)); } } @@ -222,7 +229,7 @@ public class HologramTrait extends Trait { if (idx < 0 || idx >= lines.size()) return; - lines.remove(idx); + lines.remove(idx).removeNPC(); reloadLineHolograms(); } @@ -249,44 +256,41 @@ public class HologramTrait extends Trait { } } - boolean update = currentLoc.getWorld() != npc.getStoredLocation().getWorld() + boolean updatePosition = currentLoc.getWorld() != npc.getStoredLocation().getWorld() || currentLoc.distance(npc.getStoredLocation()) >= 0.001 || lastNameplateVisible != nameplateVisible || Math.abs(lastEntityHeight - getEntityHeight()) >= 0.05; lastNameplateVisible = nameplateVisible; - if (update) { + if (updatePosition) { currentLoc = npc.getStoredLocation(); lastEntityHeight = getEntityHeight(); } if (nameNPC != null && nameNPC.isSpawned()) { - if (update) { + if (updatePosition) { nameNPC.teleport(currentLoc.clone().add(0, getEntityHeight(), 0), TeleportCause.PLUGIN); } nameNPC.setName(npc.getFullName()); } - for (int i = 0; i < lineHolograms.size(); i++) { - NPC hologramNPC = lineHolograms.get(i); - if (!hologramNPC.isSpawned()) + for (int i = 0; i < lines.size(); i++) { + HologramLine line = lines.get(i); + NPC hologramNPC = line.hologram; + if (hologramNPC == null || !hologramNPC.isSpawned()) continue; - if (update) { + if (updatePosition) { hologramNPC.teleport(currentLoc.clone().add(0, lastEntityHeight + (direction == HologramDirection.BOTTOM_UP ? getHeight(i) : getMaxHeight() - getHeight(i)), 0), TeleportCause.PLUGIN); } - if (i >= lines.size()) { - Messaging.severe("More hologram NPCs than lines for ID", npc.getId(), "lines", lines); - break; - } - - HologramLine line = lines.get(i); if (line.ticks > 0 && --line.ticks == 0) { + line.removeNPC(); lines.remove(i--); continue; } + String text = line.text; if (ITEM_MATCHER.matcher(text).matches()) { text = null; @@ -339,13 +343,11 @@ public class HologramTrait extends Trait { return; } - lines.get(idx).text = text; - if (idx < lineHolograms.size()) { - lineHolograms.get(idx).setName(Placeholders.replace(text, null, npc)); - return; + HologramLine line = lines.get(idx); + line.setText(text); + if (line.hologram == null) { + reloadLineHolograms(); } - - reloadLineHolograms(); } /** @@ -367,9 +369,10 @@ public class HologramTrait extends Trait { } private class HologramLine { + NPC hologram; boolean persist; String text; - public int ticks; + int ticks; public HologramLine(String text, boolean persist) { this(text, persist, -1); @@ -380,7 +383,27 @@ public class HologramTrait extends Trait { this.persist = persist; this.ticks = ticks; } + + public void removeNPC() { + if (hologram == null) + return; + + hologram.destroy(); + hologram = null; + } + + public void setText(String text) { + this.text = text; + + if (hologram != null) { + hologram.setName(Placeholders.replace(text, null, npc)); + } + } + + public void spawnNPC(double height) { + this.hologram = createHologram(Placeholders.replace(text, null, npc), height); + } } - private static final Pattern ITEM_MATCHER = Pattern.compile(""); + private static final Pattern ITEM_MATCHER = Pattern.compile("|"); } diff --git a/main/src/main/java/net/citizensnpcs/trait/text/Text.java b/main/src/main/java/net/citizensnpcs/trait/text/Text.java index 9b673998e..a8e68788a 100644 --- a/main/src/main/java/net/citizensnpcs/trait/text/Text.java +++ b/main/src/main/java/net/citizensnpcs/trait/text/Text.java @@ -233,8 +233,8 @@ public class Text extends Trait implements Runnable, Listener, ConversationAband boolean sendPage(CommandSender player, int page) { Paginator paginator = new Paginator().header("Current Texts").enablePageSwitcher(); for (int i = 0; i < text.size(); i++) { - paginator.addLine("" + text.get(i) + " (edit) ((edit) (-)"); } return paginator.sendPage(player, page); diff --git a/main/src/main/resources/messages_en.properties b/main/src/main/resources/messages_en.properties index 1e1c555f4..e0a9be1dd 100644 --- a/main/src/main/resources/messages_en.properties +++ b/main/src/main/resources/messages_en.properties @@ -340,7 +340,7 @@ citizens.editors.text.range-set=[[Range]] set to [[{0}]]. citizens.editors.text.delay-set=[[Delay]] set to [[{0}]] seconds. citizens.editors.text.realistic-looking-set=[[Realistic looking]] set to [[{0}]]. citizens.editors.text.speech-bubbles-set=[[Speech bubbles]] set to [[{0}]]. -citizens.editors.text.start-prompt=Add text | default to clear)'>item | range | delay
{0}talk close | {1}random | {2}speech bubbles | {3}realistic +citizens.editors.text.start-prompt=Add text | default to clear)">item | range | delay
{0}talk close | {1}random | {2}speech bubbles | {3}realistic citizens.editors.text.talk-item-set=[[Talk item pattern]] set to [[{0}]]. citizens.editors.text.text-list-header=Current text: citizens.editors.waypoints.wander.editing-regions-stop=Exited the region editor.