diff --git a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/ProtocolLibHookImpl.java b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/ProtocolLibHookImpl.java index 5a374440..cf78705a 100644 --- a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/ProtocolLibHookImpl.java +++ b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/bridge/protocollib/current/ProtocolLibHookImpl.java @@ -14,6 +14,7 @@ */ package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current; +import java.util.Collection; import java.util.List; import java.util.Optional; @@ -38,7 +39,6 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry; import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer; import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; import com.comphenix.protocol.wrappers.WrappedWatchableObject; -import com.gmail.filoghost.holographicdisplays.api.Hologram; import com.gmail.filoghost.holographicdisplays.bridge.protocollib.ProtocolLibHook; import com.gmail.filoghost.holographicdisplays.bridge.protocollib.current.WrapperPlayServerSpawnEntity.ObjectTypes; import com.gmail.filoghost.holographicdisplays.nms.interfaces.NMSManager; @@ -50,6 +50,7 @@ import com.gmail.filoghost.holographicdisplays.object.line.CraftItemLine; import com.gmail.filoghost.holographicdisplays.object.line.CraftTextLine; import com.gmail.filoghost.holographicdisplays.object.line.CraftTouchSlimeLine; import com.gmail.filoghost.holographicdisplays.object.line.CraftTouchableLine; +import com.gmail.filoghost.holographicdisplays.placeholder.RelativePlaceholder; import com.gmail.filoghost.holographicdisplays.util.NMSVersion; import com.gmail.filoghost.holographicdisplays.util.Utils; @@ -125,8 +126,9 @@ public class ProtocolLibHookImpl implements ProtocolLibHook { public void onPacketSending(PacketEvent event) { PacketContainer packet = event.getPacket(); + Player player = event.getPlayer(); - if (event.getPlayer().getClass().getName().equals("com.comphenix.net.sf.cglib.proxy.Factory")) { + if (player.getClass().getName().equals("com.comphenix.net.sf.cglib.proxy.Factory")) { return; // Ignore temporary players (reference: https://github.com/dmulloy2/ProtocolLib/issues/349) } @@ -136,44 +138,37 @@ public class ProtocolLibHookImpl implements ProtocolLibHook { WrapperPlayServerSpawnEntityLiving spawnEntityPacket = new WrapperPlayServerSpawnEntityLiving(packet); Entity entity = spawnEntityPacket.getEntity(event); - if (entity == null || !isHologramType(entity.getType())) { + CraftHologramLine hologramLine = getHologramLine(entity); + if (hologramLine == null) { return; } - Hologram hologram = getHologram(entity); - if (hologram == null) { - return; - } - - Player player = event.getPlayer(); - if (!hologram.getVisibilityManager().isVisibleTo(player)) { + if (!hologramLine.getParent().getVisibilityManager().isVisibleTo(player)) { event.setCancelled(true); return; } + Collection relativePlaceholders = hologramLine.getRelativePlaceholders(); + if (relativePlaceholders == null || relativePlaceholders.isEmpty()) { + return; + } + + spawnEntityPacket = new WrapperPlayServerSpawnEntityLiving(packet.deepClone()); WrappedWatchableObject customNameWatchableObject = spawnEntityPacket.getMetadata().getWatchableObject(customNameWatcherIndex); - replacePlayerRelativePlaceholders(customNameWatchableObject, event.getPlayer()); + replaceRelativePlaceholders(customNameWatchableObject, player, relativePlaceholders); + event.setPacket(spawnEntityPacket.getHandle()); } else if (packet.getType() == PacketType.Play.Server.SPAWN_ENTITY) { WrapperPlayServerSpawnEntity spawnEntityPacket = new WrapperPlayServerSpawnEntity(packet); Entity entity = spawnEntityPacket.getEntity(event); - if (entity == null) { + CraftHologramLine hologramLine = getHologramLine(entity); + if (hologramLine == null) { return; } - if (!isHologramType(entity.getType())) { - return; - } - - Hologram hologram = getHologram(entity); - if (hologram == null) { - return; - } - - Player player = event.getPlayer(); - if (!hologram.getVisibilityManager().isVisibleTo(player)) { + if (!hologramLine.getParent().getVisibilityManager().isVisibleTo(player)) { event.setCancelled(true); return; } @@ -183,35 +178,34 @@ public class ProtocolLibHookImpl implements ProtocolLibHook { WrapperPlayServerEntityMetadata entityMetadataPacket = new WrapperPlayServerEntityMetadata(packet); Entity entity = entityMetadataPacket.getEntity(event); - if (entity == null) { - return; - } - - if (!isHologramType(entity.getType())) { + CraftHologramLine hologramLine = getHologramLine(entity); + if (hologramLine == null) { return; } - Hologram hologram = getHologram(entity); - if (hologram == null) { - return; - } - - Player player = event.getPlayer(); - if (!hologram.getVisibilityManager().isVisibleTo(player)) { + if (!hologramLine.getParent().getVisibilityManager().isVisibleTo(player)) { event.setCancelled(true); return; } + Collection relativePlaceholders = hologramLine.getRelativePlaceholders(); + if (relativePlaceholders == null || relativePlaceholders.isEmpty()) { + return; + } + + entityMetadataPacket = new WrapperPlayServerEntityMetadata(packet.deepClone()); List dataWatcherValues = entityMetadataPacket.getEntityMetadata(); + for (int i = 0; i < dataWatcherValues.size(); i++) { - WrappedWatchableObject watchableObject = dataWatcherValues.get(i); + if (watchableObject.getIndex() == customNameWatcherIndex) { - - if (replacePlayerRelativePlaceholders(watchableObject, event.getPlayer())) { - entityMetadataPacket.setEntityMetadata(dataWatcherValues); + if (replaceRelativePlaceholders(watchableObject, player, relativePlaceholders)) { event.setPacket(entityMetadataPacket.getHandle()); } + + // No reason to check further. + return; } } } @@ -222,7 +216,7 @@ public class ProtocolLibHookImpl implements ProtocolLibHook { } - private boolean replacePlayerRelativePlaceholders(WrappedWatchableObject customNameWatchableObject, Player player) { + private boolean replaceRelativePlaceholders(WrappedWatchableObject customNameWatchableObject, Player player, Collection relativePlaceholders) { if (customNameWatchableObject == null) { return true; } @@ -251,11 +245,9 @@ public class ProtocolLibHookImpl implements ProtocolLibHook { customName = (String) customNameWatchableObjectValue; } - if (!customName.contains("{player}") && !customName.contains("{displayname}")) { - return false; + for (RelativePlaceholder relativePlaceholder : relativePlaceholders) { + customName = customName.replace(relativePlaceholder.getTextPlaceholder(), relativePlaceholder.getReplacement(player)); } - - customName = customName.replace("{player}", player.getName()).replace("{displayname}", player.getDisplayName()); if (NMSVersion.isGreaterEqualThan(NMSVersion.v1_13_R1)) { customNameWatchableObject.setValue(Optional.of(WrappedChatComponent.fromJson(customName).getHandle())); @@ -397,19 +389,21 @@ public class ProtocolLibHookImpl implements ProtocolLibHook { attachPacket.sendPacket(receiver); } } - - - private boolean isHologramType(EntityType type) { - return type == EntityType.ARMOR_STAND || type == EntityType.DROPPED_ITEM || type == EntityType.SLIME; - } - private Hologram getHologram(Entity bukkitEntity) { - NMSEntityBase entity = nmsManager.getNMSEntityBase(bukkitEntity); - if (entity != null) { - return entity.getHologramLine().getParent(); + private CraftHologramLine getHologramLine(Entity bukkitEntity) { + if (bukkitEntity != null && isHologramType(bukkitEntity.getType())) { + NMSEntityBase entity = nmsManager.getNMSEntityBase(bukkitEntity); + if (entity != null) { + return (CraftHologramLine) entity.getHologramLine(); + } } return null; } + + + private boolean isHologramType(EntityType type) { + return type == EntityType.ARMOR_STAND || type == EntityType.DROPPED_ITEM || type == EntityType.SLIME; + } } diff --git a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftHologramLine.java b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftHologramLine.java index dc62b115..d17de244 100644 --- a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftHologramLine.java +++ b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftHologramLine.java @@ -14,10 +14,13 @@ */ package com.gmail.filoghost.holographicdisplays.object.line; +import java.util.Collection; + import org.bukkit.World; import com.gmail.filoghost.holographicdisplays.api.line.HologramLine; import com.gmail.filoghost.holographicdisplays.object.CraftHologram; +import com.gmail.filoghost.holographicdisplays.placeholder.RelativePlaceholder; import com.gmail.filoghost.holographicdisplays.util.Validator; public abstract class CraftHologramLine implements HologramLine { @@ -64,6 +67,10 @@ public abstract class CraftHologramLine implements HologramLine { public final boolean isSpawned() { return isSpawned; } + + public Collection getRelativePlaceholders() { + return null; + } public abstract int[] getEntitiesIDs(); diff --git a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java index 79dfe8f7..31c606a6 100644 --- a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java +++ b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/object/line/CraftTextLine.java @@ -14,6 +14,9 @@ */ package com.gmail.filoghost.holographicdisplays.object.line; +import java.util.Collection; +import java.util.List; + import org.apache.commons.lang.ArrayUtils; import org.bukkit.Location; import org.bukkit.World; @@ -24,11 +27,14 @@ import com.gmail.filoghost.holographicdisplays.api.line.TextLine; import com.gmail.filoghost.holographicdisplays.nms.interfaces.entity.NMSNameable; import com.gmail.filoghost.holographicdisplays.object.CraftHologram; import com.gmail.filoghost.holographicdisplays.placeholder.PlaceholdersManager; +import com.gmail.filoghost.holographicdisplays.placeholder.RelativePlaceholder; import com.gmail.filoghost.holographicdisplays.util.Offsets; +import com.gmail.filoghost.holographicdisplays.util.Utils; public class CraftTextLine extends CraftTouchableLine implements TextLine { private String text; + private List relativePlaceholders; private NMSNameable nmsNameble; @@ -60,6 +66,22 @@ public class CraftTextLine extends CraftTouchableLine implements TextLine { } } } + + if (text != null) { + for (RelativePlaceholder relativePlaceholder : RelativePlaceholder.getRegistry()) { + if (text.contains(relativePlaceholder.getTextPlaceholder())) { + if (relativePlaceholders == null) { + relativePlaceholders = Utils.newList(); + } + relativePlaceholders.add(relativePlaceholder); + } + } + } + + // Deallocate the list if unused + if (relativePlaceholders != null && relativePlaceholders.isEmpty()) { + relativePlaceholders = null; + } } @Override @@ -98,6 +120,12 @@ public class CraftTextLine extends CraftTouchableLine implements TextLine { nmsNameble = null; } } + + + @Override + public Collection getRelativePlaceholders() { + return relativePlaceholders; + } @Override diff --git a/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/placeholder/RelativePlaceholder.java b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/placeholder/RelativePlaceholder.java new file mode 100644 index 00000000..a6fd6ace --- /dev/null +++ b/Plugin/src/main/java/com/gmail/filoghost/holographicdisplays/placeholder/RelativePlaceholder.java @@ -0,0 +1,71 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.gmail.filoghost.holographicdisplays.placeholder; + +import java.util.Collection; +import org.bukkit.entity.Player; + +import com.gmail.filoghost.holographicdisplays.util.Utils; + +public abstract class RelativePlaceholder { + + private static final Collection registry = Utils.newSet(); + + // The placeholder itself, something like {player}. + private final String textPlaceholder; + + public RelativePlaceholder(String textPlaceholder) { + this.textPlaceholder = textPlaceholder; + } + + public String getTextPlaceholder() { + return textPlaceholder; + } + + public abstract String getReplacement(Player player); + + public static void register(RelativePlaceholder relativePlaceholder) { + for (RelativePlaceholder existingPlaceholder : registry) { + if (existingPlaceholder.getTextPlaceholder().equals(relativePlaceholder.getTextPlaceholder())) { + throw new IllegalArgumentException("Relative placeholder already registered."); + } + } + + registry.add(relativePlaceholder); + } + + public static Collection getRegistry() { + return registry; + } + + static { + register(new RelativePlaceholder("{player}") { + + @Override + public String getReplacement(Player player) { + return player.getName(); + } + }); + + register(new RelativePlaceholder("{displayname}") { + + @Override + public String getReplacement(Player player) { + return player.getDisplayName(); + } + }); + } + +}