Compare commits

...

3 Commits

Author SHA1 Message Date
fullwall d3c0205d9e Bugfix TextDisplayVehicleRenderer 2024-04-15 20:21:26 +08:00
fullwall ccce76d9f0 Add some interaction debug for holograms 2024-04-15 15:47:59 +08:00
fullwall b0ba7b2062 Further bugfixes for item holograms 2024-04-15 13:08:02 +08:00
7 changed files with 174 additions and 54 deletions

View File

@ -11,12 +11,14 @@ 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;
import org.bukkit.entity.Display.Billboard;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.entity.Player;
import org.bukkit.entity.TextDisplay;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
@ -24,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;
@ -74,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();
}
@ -93,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();
}
@ -112,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());
}
@ -128,9 +148,13 @@ public class HologramTrait extends Trait {
return base;
}
@Deprecated
public Collection<Entity> 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<HologramRenderer> getHologramRenderers() {
return lines.stream().map(l -> l.renderer).collect(Collectors.toList());
}
/**
@ -147,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() {
@ -160,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);
@ -194,7 +224,6 @@ public class HologramTrait extends Trait {
nameLine.removeNPC();
nameLine = null;
}
currentLoc = null;
}
/**
@ -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) {
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;
@ -425,7 +433,7 @@ public class HologramTrait extends Trait {
public void setText(String text) {
this.text = text == null ? "" : text;
if (ITEM_MATCHER.matcher(text).find()) {
if (ITEM_MATCHER.matcher(text).find() && !(renderer instanceof ItemRenderer)) {
renderer.destroy();
mb = 0.21;
mt = 0.07;
@ -438,8 +446,7 @@ public class HologramTrait extends Trait {
public static interface HologramRenderer {
void destroy();
@Deprecated
Entity getEntity();
Collection<Entity> getEntities();
String getPerPlayerText(NPC npc, Player viewer);
@ -480,7 +487,7 @@ public class HologramTrait extends Trait {
}
}
public class ItemRenderer extends SingleEntityHologramRenderer {
public class ItemDisplayRenderer extends SingleEntityHologramRenderer {
@Override
protected NPC createNPC(Entity base, String name, Vector3d offset) {
Matcher itemMatcher = ITEM_MATCHER.matcher(name);
@ -488,7 +495,7 @@ public class HologramTrait extends Trait {
Material item = SpigotUtil.isUsing1_13API() ? Material.matchMaterial(itemMatcher.group(1), false)
: Material.matchMaterial(itemMatcher.group(1));
ItemStack itemStack = new ItemStack(item, 1);
NPC npc = registry.createNPCUsingItem(EntityType.DROPPED_ITEM, "", itemStack);
NPC npc = registry.createNPCUsingItem(EntityType.ITEM_DISPLAY, "", itemStack);
npc.data().setPersistent(NPC.Metadata.NAMEPLATE_VISIBLE, false);
if (itemMatcher.group(2) != null) {
if (itemMatcher.group(2).charAt(1) == '{') {
@ -502,12 +509,71 @@ public class HologramTrait extends Trait {
return npc;
}
@Override
public void render0(NPC base, Vector3d offset) {
ItemDisplay disp = (ItemDisplay) hologram.getEntity();
Transformation tf = disp.getTransformation();
tf.getTranslation().y = (float) offset.y + 0.1f;
disp.setTransformation(tf);
if (hologram.getEntity().getVehicle() == null) {
base.getEntity().addPassenger(hologram.getEntity());
}
}
@Override
public void updateText(NPC npc, String text) {
this.text = Placeholders.replace(text, null, npc);
}
}
public class ItemRenderer extends SingleEntityHologramRenderer {
private NPC itemNPC;
@Override
protected NPC createNPC(Entity base, String name, Vector3d offset) {
NPC mount = registry.createNPC(EntityType.ARMOR_STAND, "");
mount.getOrAddTrait(ArmorStandTrait.class).setAsPointEntity();
Matcher itemMatcher = ITEM_MATCHER.matcher(name);
itemMatcher.find();
Material item = SpigotUtil.isUsing1_13API() ? Material.matchMaterial(itemMatcher.group(1), false)
: Material.matchMaterial(itemMatcher.group(1));
ItemStack itemStack = new ItemStack(item, 1);
itemNPC = registry.createNPCUsingItem(EntityType.DROPPED_ITEM, "", itemStack);
itemNPC.data().setPersistent(NPC.Metadata.NAMEPLATE_VISIBLE, false);
if (itemMatcher.group(2) != null) {
if (itemMatcher.group(2).charAt(1) == '{') {
Bukkit.getUnsafe().modifyItemStack(itemStack, itemMatcher.group(2).substring(1));
itemNPC.setItemProvider(() -> itemStack);
} else {
itemNPC.getOrAddTrait(ScoreboardTrait.class)
.setColor(Util.matchEnum(ChatColor.values(), itemMatcher.group(2).substring(1)));
}
}
itemNPC.spawn(base.getLocation());
itemNPC.getOrAddTrait(MountTrait.class).setMountedOn(mount.getUniqueId());
return mount;
}
@Override
public void destroy() {
super.destroy();
if (itemNPC == null)
return;
itemNPC.destroy();
itemNPC = null;
}
@Override
protected void render0(NPC npc, Vector3d offset) {
hologram.getEntity().teleport(
npc.getStoredLocation().clone().add(offset.x, offset.y + getEntityBbHeight(), offset.z),
TeleportCause.PLUGIN);
}
@Override
public void updateText(NPC npc, String text) {
this.text = Placeholders.replace(text, null, npc);
}
}
public abstract class SingleEntityHologramRenderer implements HologramRenderer {
@ -525,8 +591,8 @@ public class HologramTrait extends Trait {
}
@Override
public Entity getEntity() {
return hologram != null ? hologram.getEntity() : null;
public Collection<Entity> getEntities() {
return hologram != null ? ImmutableList.of(hologram.getEntity()) : Collections.emptyList();
}
@Override
@ -588,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;
}
@ -599,12 +669,27 @@ public class HologramTrait extends Trait {
TextDisplay disp = (TextDisplay) hologram.getEntity();
disp.setBillboard(Billboard.CENTER);
Transformation tf = disp.getTransformation();
tf.getTranslation().y = (float) offset.y + 0.1f;
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("<item:([a-zA-Z0-9_ ]*?)([:].*?)?>");

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);
}
}
}

View File

@ -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())

View File

@ -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);
}
}
}

View File

@ -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())