Implement player placeholders in hologram names

This commit is contained in:
fullwall 2023-04-23 23:46:20 +08:00
parent 798ec1c3aa
commit ed4f43a5aa
4 changed files with 78 additions and 8 deletions

View File

@ -77,7 +77,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.7.0</version>
<version>5.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@ -241,7 +241,7 @@
</configuration>
</execution>
</executions>
</plugin>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>

View File

@ -2,9 +2,12 @@ package net.citizensnpcs;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.PacketType.Play.Server;
@ -20,8 +23,10 @@ import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedDataValue;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import com.google.common.collect.Iterables;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
@ -46,6 +51,53 @@ public class ProtocolLibListener {
flagsClass = MinecraftReflection.getMinecraftClass("RelativeMovement", "world.entity.RelativeMovement",
"EnumPlayerTeleportFlags", "PacketPlayOutPosition$EnumPlayerTeleportFlags",
"network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags");
manager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.HIGHEST, Server.ENTITY_METADATA) {
@Override
public void onPacketSending(PacketEvent event) {
NPC npc = getNPCFromPacket(event);
if (npc == null || !npc.data().has(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER))
return;
Function<Player, String> hvs = npc.data().get(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER);
int version = manager.getProtocolVersion(event.getPlayer());
PacketContainer packet = event.getPacket();
if (version < 761) {
List<WrappedWatchableObject> wwo = packet.getWatchableCollectionModifier().readSafely(0);
if (wwo == null)
return;
boolean delta = false;
String text = hvs.apply(event.getPlayer());
for (WrappedWatchableObject wo : wwo) {
if (wo.getIndex() != 2)
continue;
if (version <= 340) {
wo.setValue(text);
} else {
wo.setValue(Optional.of(Messaging.minecraftComponentFromRawMessage(text)));
}
delta = true;
break;
}
if (delta) {
packet.getWatchableCollectionModifier().write(0, wwo);
}
} else {
List<WrappedDataValue> wdvs = packet.getDataValueCollectionModifier().readSafely(0);
if (wdvs == null)
return;
boolean delta = false;
String text = hvs.apply(event.getPlayer());
for (WrappedDataValue wdv : wdvs) {
if (wdv.getIndex() != 2)
continue;
wdv.setValue(Optional.of(Messaging.minecraftComponentFromRawMessage(text)));
break;
}
if (delta) {
packet.getDataValueCollectionModifier().write(0, wdvs);
}
}
}
});
manager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.HIGHEST, Server.PLAYER_INFO) {
@Override
public void onPacketSending(PacketEvent event) {
@ -66,8 +118,9 @@ public class ProtocolLibListener {
if (npc == null || !npc.isSpawned())
continue;
MirrorTrait trait = npc.getTraitNullable(MirrorTrait.class);
if (trait == null || !trait.isMirroring(event.getPlayer()))
if (trait == null || !trait.isMirroring(event.getPlayer())) {
continue;
}
GameProfile profile = NMS.getProfile(event.getPlayer());
if (trait.mirrorName()) {
list.set(i,

View File

@ -319,8 +319,8 @@ public class SkinUpdateTracker {
List<SkinnableEntity> visible = getNearbyNPCs(player, reset, false);
for (SkinnableEntity skinnable : visible) {
if (Messaging.isDebugging()) {
Messaging.debug("Sending skin from", skinnable.getBukkitEntity(), "to", player, "(" + delay,
reset + ")");
Messaging.debug("Sending skin from", skinnable.getBukkitEntity(), "to", player,
"(" + delay + "t delay, reset", reset + ")");
}
skinnable.getSkinTracker().updateViewer(player);
}

View File

@ -2,6 +2,7 @@ package net.citizensnpcs.trait;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -12,6 +13,7 @@ import org.bukkit.Material;
import org.bukkit.entity.Display.Billboard;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.TextDisplay;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
@ -404,7 +406,8 @@ public class HologramTrait extends Trait {
TOP_DOWN;
}
private class HologramLine {
private class HologramLine implements Function<Player, String> {
boolean hasPlayerPlaceholder;
NPC hologram;
double mb, mt;
boolean persist;
@ -416,7 +419,7 @@ public class HologramTrait extends Trait {
}
public HologramLine(String text, boolean persist, int ticks) {
this.text = text == null ? "" : text;
setText(text);
this.persist = persist;
this.ticks = ticks;
if (ITEM_MATCHER.matcher(text).matches()) {
@ -425,6 +428,11 @@ public class HologramTrait extends Trait {
}
}
@Override
public String apply(Player viewer) {
return Placeholders.replace(text, viewer, npc);
}
public void removeNPC() {
if (hologram == null)
return;
@ -434,18 +442,27 @@ public class HologramTrait extends Trait {
}
public void setText(String text) {
this.text = text;
this.text = text == null ? "" : text;
this.hasPlayerPlaceholder = Placeholders.containsPlayerPlaceholder(text);
if (hologram != null) {
String name = Placeholders.replace(text, null, npc);
hologram.setName(name);
hologram.data().set(NPC.Metadata.NAMEPLATE_VISIBLE, ChatColor.stripColor(name).length() > 0);
if (Placeholders.containsPlayerPlaceholder(text)) {
hologram.data().set(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER, this);
} else {
hologram.data().remove(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER);
}
}
}
public void spawnNPC(double height) {
String name = Placeholders.replace(text, null, npc);
this.hologram = createHologram(name, height);
if (Placeholders.containsPlayerPlaceholder(text)) {
hologram.data().set(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER, this);
}
}
}