Merge branch 'modular-property-system' into upstream-modular-property-system
# Conflicts: # plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java
This commit is contained in:
commit
4e584b8d46
17 changed files with 431 additions and 75 deletions
|
@ -202,9 +202,9 @@ public class ZNpcsPlus extends JavaPlugin {
|
|||
NpcEntryImpl entry = npcRegistry.create("debug_npc_" + i, world, type, new NpcLocation(i * 3, 200, 0, 0, 0));
|
||||
entry.setProcessed(true);
|
||||
NpcImpl npc = entry.getNpc();
|
||||
npc.getHologram().addLineComponent(Component.text("Hello, World!", TextColor.color(255, 0, 0)));
|
||||
npc.getHologram().addLineComponent(Component.text("Hello, World!", TextColor.color(0, 255, 0)));
|
||||
npc.getHologram().addLineComponent(Component.text("Hello, World!", TextColor.color(0, 0, 255)));
|
||||
npc.getHologram().addTextLineComponent(Component.text("Hello, World!", TextColor.color(255, 0, 0)));
|
||||
npc.getHologram().addTextLineComponent(Component.text("Hello, World!", TextColor.color(0, 255, 0)));
|
||||
npc.getHologram().addTextLineComponent(Component.text("Hello, World!", TextColor.color(0, 0, 255)));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -214,6 +214,7 @@ public class ZNpcsPlus extends JavaPlugin {
|
|||
public void onDisable() {
|
||||
NpcApiProvider.unregister();
|
||||
for (Runnable runnable : shutdownTasks) runnable.run();
|
||||
shutdownTasks.clear();
|
||||
PacketEvents.getAPI().terminate();
|
||||
}
|
||||
|
||||
|
@ -283,11 +284,14 @@ public class ZNpcsPlus extends JavaPlugin {
|
|||
.addSubcommand("reload", new LoadAllCommand(npcRegistry))
|
||||
.addSubcommand("import", new ImportCommand(npcRegistry, importerRegistry)))
|
||||
.addSubcommand("holo", new MultiCommand(loadHelpMessage("holo"))
|
||||
.addSubcommand("add", new HoloAddCommand(npcRegistry, textSerializer))
|
||||
.addSubcommand("add", new HoloAddCommand(npcRegistry))
|
||||
.addSubcommand("additem", new HoloAddItemCommand(npcRegistry))
|
||||
.addSubcommand("delete", new HoloDeleteCommand(npcRegistry))
|
||||
.addSubcommand("info", new HoloInfoCommand(npcRegistry))
|
||||
.addSubcommand("insert", new HoloInsertCommand(npcRegistry, textSerializer))
|
||||
.addSubcommand("set", new HoloSetCommand(npcRegistry, textSerializer))
|
||||
.addSubcommand("insert", new HoloInsertCommand(npcRegistry))
|
||||
.addSubcommand("insertitem", new HoloInsertItemCommand(npcRegistry))
|
||||
.addSubcommand("set", new HoloSetCommand(npcRegistry))
|
||||
.addSubcommand("setitem", new HoloSetItemCommand(npcRegistry))
|
||||
.addSubcommand("offset", new HoloOffsetCommand(npcRegistry))
|
||||
.addSubcommand("refreshdelay", new HoloRefreshDelayCommand(npcRegistry)))
|
||||
.addSubcommand("action", new MultiCommand(loadHelpMessage("action"))
|
||||
|
|
|
@ -4,22 +4,20 @@ import lol.pyr.director.adventure.command.CommandContext;
|
|||
import lol.pyr.director.adventure.command.CommandHandler;
|
||||
import lol.pyr.director.common.command.CommandExecutionException;
|
||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||
import lol.pyr.znpcsplus.hologram.HologramItem;
|
||||
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class HoloAddCommand implements CommandHandler {
|
||||
private final NpcRegistryImpl registry;
|
||||
private final LegacyComponentSerializer textSerializer;
|
||||
|
||||
public HoloAddCommand(NpcRegistryImpl registry, LegacyComponentSerializer textSerializer) {
|
||||
public HoloAddCommand(NpcRegistryImpl registry) {
|
||||
this.registry = registry;
|
||||
this.textSerializer = textSerializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,7 +25,13 @@ public class HoloAddCommand implements CommandHandler {
|
|||
context.setUsage(context.getLabel() + " holo add <id> <text>");
|
||||
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
|
||||
context.ensureArgsNotEmpty();
|
||||
hologram.addLineComponent(textSerializer.deserialize(context.dumpAllArgs()));
|
||||
String in = context.dumpAllArgs();
|
||||
if (in.toLowerCase().startsWith("item:")) {
|
||||
if (!HologramItem.ensureValidItemInput(in.substring(5))) {
|
||||
context.halt(Component.text("The item input is invalid!", NamedTextColor.RED));
|
||||
}
|
||||
}
|
||||
hologram.addLine(in);
|
||||
context.send(Component.text("NPC line added!", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package lol.pyr.znpcsplus.commands.hologram;
|
||||
|
||||
import lol.pyr.director.adventure.command.CommandContext;
|
||||
import lol.pyr.director.adventure.command.CommandHandler;
|
||||
import lol.pyr.director.common.command.CommandExecutionException;
|
||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class HoloAddItemCommand implements CommandHandler {
|
||||
private final NpcRegistryImpl registry;
|
||||
|
||||
public HoloAddItemCommand(NpcRegistryImpl registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(CommandContext context) throws CommandExecutionException {
|
||||
context.setUsage(context.getLabel() + " holo additem <id>");
|
||||
Player player = context.ensureSenderIsPlayer();
|
||||
org.bukkit.inventory.ItemStack itemStack = player.getInventory().getItemInHand();
|
||||
if (itemStack == null) context.halt(Component.text("You must be holding an item!", NamedTextColor.RED));
|
||||
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
|
||||
hologram.addItemLineStack(itemStack);
|
||||
context.send(Component.text("NPC item line added!", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
||||
if (context.argSize() == 1) return context.suggestCollection(registry.getModifiableIds());
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import lol.pyr.director.adventure.command.CommandContext;
|
|||
import lol.pyr.director.adventure.command.CommandHandler;
|
||||
import lol.pyr.director.common.command.CommandExecutionException;
|
||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||
import lol.pyr.znpcsplus.hologram.HologramLine;
|
||||
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
@ -26,7 +25,11 @@ public class HoloInfoCommand implements CommandHandler {
|
|||
NpcEntryImpl entry = context.parse(NpcEntryImpl.class);
|
||||
HologramImpl hologram = entry.getNpc().getHologram();
|
||||
Component component = Component.text("NPC Hologram Info of ID " + entry.getId() + ":", NamedTextColor.GREEN).appendNewline();
|
||||
for (HologramLine line : hologram.getLines()) component = component.append(line.getText()).appendNewline();
|
||||
for (int i = 0; i < hologram.getLines().size(); i++) {
|
||||
component = component.append(Component.text(i + ") ", NamedTextColor.GREEN))
|
||||
.append(Component.text(hologram.getLine(i), NamedTextColor.WHITE))
|
||||
.appendNewline();
|
||||
}
|
||||
context.send(component);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ import lol.pyr.director.adventure.command.CommandContext;
|
|||
import lol.pyr.director.adventure.command.CommandHandler;
|
||||
import lol.pyr.director.common.command.CommandExecutionException;
|
||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||
import lol.pyr.znpcsplus.hologram.HologramItem;
|
||||
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -16,11 +16,9 @@ import java.util.stream.Stream;
|
|||
|
||||
public class HoloInsertCommand implements CommandHandler {
|
||||
private final NpcRegistryImpl npcRegistry;
|
||||
private final LegacyComponentSerializer componentSerializer;
|
||||
|
||||
public HoloInsertCommand(NpcRegistryImpl npcRegistry, LegacyComponentSerializer componentSerializer) {
|
||||
public HoloInsertCommand(NpcRegistryImpl npcRegistry) {
|
||||
this.npcRegistry = npcRegistry;
|
||||
this.componentSerializer = componentSerializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,7 +28,13 @@ public class HoloInsertCommand implements CommandHandler {
|
|||
int line = context.parse(Integer.class);
|
||||
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));
|
||||
context.ensureArgsNotEmpty();
|
||||
hologram.insertLineComponent(line, componentSerializer.deserialize(context.dumpAllArgs()));
|
||||
String in = context.dumpAllArgs();
|
||||
if (in.toLowerCase().startsWith("item:")) {
|
||||
if (!HologramItem.ensureValidItemInput(in.substring(5))) {
|
||||
context.halt(Component.text("The item input is invalid!", NamedTextColor.RED));
|
||||
}
|
||||
}
|
||||
hologram.insertLine(line, in);
|
||||
context.send(Component.text("NPC line inserted!", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package lol.pyr.znpcsplus.commands.hologram;
|
||||
|
||||
import lol.pyr.director.adventure.command.CommandContext;
|
||||
import lol.pyr.director.adventure.command.CommandHandler;
|
||||
import lol.pyr.director.common.command.CommandExecutionException;
|
||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class HoloInsertItemCommand implements CommandHandler {
|
||||
private final NpcRegistryImpl npcRegistry;
|
||||
|
||||
public HoloInsertItemCommand(NpcRegistryImpl npcRegistry) {
|
||||
this.npcRegistry = npcRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(CommandContext context) throws CommandExecutionException {
|
||||
context.setUsage(context.getLabel() + " holo insertitem <id> <line>");
|
||||
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
|
||||
int line = context.parse(Integer.class);
|
||||
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));
|
||||
Player player = context.ensureSenderIsPlayer();
|
||||
org.bukkit.inventory.ItemStack itemStack = player.getInventory().getItemInHand();
|
||||
if (itemStack == null) context.halt(Component.text("You must be holding an item!", NamedTextColor.RED));
|
||||
hologram.insertItemLineStack(line, itemStack);
|
||||
context.send(Component.text("NPC item line inserted!", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
||||
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
|
||||
if (context.argSize() == 2) return context.suggestStream(Stream.iterate(0, n -> n + 1)
|
||||
.limit(context.suggestionParse(0, NpcEntryImpl.class).getNpc().getHologram().getLines().size())
|
||||
.map(String::valueOf));
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
|||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -16,11 +15,9 @@ import java.util.stream.Stream;
|
|||
|
||||
public class HoloSetCommand implements CommandHandler {
|
||||
private final NpcRegistryImpl npcRegistry;
|
||||
private final LegacyComponentSerializer componentSerializer;
|
||||
|
||||
public HoloSetCommand(NpcRegistryImpl npcRegistry, LegacyComponentSerializer componentSerializer) {
|
||||
public HoloSetCommand(NpcRegistryImpl npcRegistry) {
|
||||
this.npcRegistry = npcRegistry;
|
||||
this.componentSerializer = componentSerializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,7 +28,7 @@ public class HoloSetCommand implements CommandHandler {
|
|||
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));
|
||||
context.ensureArgsNotEmpty();
|
||||
hologram.removeLine(line);
|
||||
hologram.insertLineComponent(line, componentSerializer.deserialize(context.dumpAllArgs()));
|
||||
hologram.insertLine(line, context.dumpAllArgs());
|
||||
context.send(Component.text("NPC line set!", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
|
@ -42,8 +39,7 @@ public class HoloSetCommand implements CommandHandler {
|
|||
HologramImpl hologram = context.suggestionParse(0, NpcEntryImpl.class).getNpc().getHologram();
|
||||
if (context.argSize() == 2) return context.suggestStream(Stream.iterate(0, n -> n + 1)
|
||||
.limit(hologram.getLines().size()).map(String::valueOf));
|
||||
if (context.argSize() == 3) return context.suggestLiteral(componentSerializer.serialize(
|
||||
hologram.getLineComponent(context.suggestionParse(1, Integer.class))));
|
||||
if (context.argSize() == 3) return context.suggestLiteral(hologram.getLine(context.suggestionParse(1, Integer.class)));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package lol.pyr.znpcsplus.commands.hologram;
|
||||
|
||||
import lol.pyr.director.adventure.command.CommandContext;
|
||||
import lol.pyr.director.adventure.command.CommandHandler;
|
||||
import lol.pyr.director.common.command.CommandExecutionException;
|
||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class HoloSetItemCommand implements CommandHandler {
|
||||
private final NpcRegistryImpl npcRegistry;
|
||||
|
||||
public HoloSetItemCommand(NpcRegistryImpl npcRegistry) {
|
||||
this.npcRegistry = npcRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(CommandContext context) throws CommandExecutionException {
|
||||
context.setUsage(context.getLabel() + " holo setitem <id> <line>");
|
||||
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
|
||||
int line = context.parse(Integer.class);
|
||||
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));
|
||||
Player player = context.ensureSenderIsPlayer();
|
||||
org.bukkit.inventory.ItemStack itemStack = player.getInventory().getItemInHand();
|
||||
if (itemStack == null) context.halt(Component.text("You must be holding an item!", NamedTextColor.RED));
|
||||
hologram.removeLine(line);
|
||||
hologram.insertItemLineStack(line, itemStack);
|
||||
context.send(Component.text("NPC item line set!", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
||||
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
|
||||
if (context.argSize() >= 2) {
|
||||
HologramImpl hologram = context.suggestionParse(0, NpcEntryImpl.class).getNpc().getHologram();
|
||||
if (context.argSize() == 2) return context.suggestStream(Stream.iterate(0, n -> n + 1)
|
||||
.limit(hologram.getLines().size()).map(String::valueOf));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -82,7 +82,7 @@ public class CitizensImporter implements DataImporter {
|
|||
world = Bukkit.getWorlds().get(0).getName();
|
||||
}
|
||||
NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, world, typeRegistry.getByName("armor_stand"), new NpcLocation(0, 0, 0, 0, 0));
|
||||
npc.getHologram().addLineComponent(textSerializer.deserialize(name));
|
||||
npc.getHologram().addTextLineComponent(textSerializer.deserialize(name));
|
||||
ConfigurationSection traits = npcSection.getConfigurationSection("traits");
|
||||
if (traits != null) {
|
||||
for (String traitName : traits.getKeys(false)) {
|
||||
|
|
|
@ -106,7 +106,7 @@ public class ZNpcImporter implements DataImporter {
|
|||
hologram.setOffset(model.getHologramHeight());
|
||||
for (String raw : model.getHologramLines()) {
|
||||
Component line = textSerializer.deserialize(raw);
|
||||
hologram.addLineComponent(line);
|
||||
hologram.addTextLineComponent(line);
|
||||
}
|
||||
|
||||
for (ZNpcsAction action : model.getClickActions()) {
|
||||
|
|
|
@ -224,6 +224,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
|||
register(new GlowProperty(packetFactory));
|
||||
register(new SimpleBitsetProperty("fire", 0, 0x01));
|
||||
register(new SimpleBitsetProperty("invisible", 0, 0x20));
|
||||
register(new HoloItemProperty());
|
||||
linkProperties("glow", "fire", "invisible");
|
||||
|
||||
register(new SimpleBooleanProperty("silent", 4, false, legacyBooleans));
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package lol.pyr.znpcsplus.entity.properties;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
|
||||
import lol.pyr.znpcsplus.entity.PacketEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class HoloItemProperty extends EntityPropertyImpl<ItemStack> {
|
||||
|
||||
public HoloItemProperty() {
|
||||
super("holo_item", null, ItemStack.class);
|
||||
setPlayerModifiable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
|
||||
properties.put(8, newEntityData(8, EntityDataTypes.ITEMSTACK, entity.getProperty(this)));
|
||||
properties.put(5, newEntityData(5, EntityDataTypes.BOOLEAN, true));
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
package lol.pyr.znpcsplus.hologram;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import lol.pyr.znpcsplus.api.hologram.Hologram;
|
||||
import lol.pyr.znpcsplus.config.ConfigManager;
|
||||
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||
import lol.pyr.znpcsplus.util.Viewable;
|
||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import lol.pyr.znpcsplus.util.Viewable;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -24,7 +26,7 @@ public class HologramImpl extends Viewable implements Hologram {
|
|||
private long refreshDelay = -1;
|
||||
private long lastRefresh = System.currentTimeMillis();
|
||||
private NpcLocation location;
|
||||
private final List<HologramLine> lines = new ArrayList<>();
|
||||
private final List<HologramLine<?>> lines = new ArrayList<>();
|
||||
|
||||
public HologramImpl(EntityPropertyRegistryImpl propertyRegistry, ConfigManager configManager, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, NpcLocation location) {
|
||||
this.propertyRegistry = propertyRegistry;
|
||||
|
@ -34,32 +36,59 @@ public class HologramImpl extends Viewable implements Hologram {
|
|||
this.location = location;
|
||||
}
|
||||
|
||||
public void addLineComponent(Component line) {
|
||||
HologramLine newLine = new HologramLine(propertyRegistry, packetFactory, null, line);
|
||||
public void addTextLineComponent(Component line) {
|
||||
HologramText newLine = new HologramText(propertyRegistry, packetFactory, null, line);
|
||||
lines.add(newLine);
|
||||
relocateLines(newLine);
|
||||
for (Player viewer : getViewers()) newLine.show(viewer.getPlayer());
|
||||
}
|
||||
|
||||
public void addTextLine(String line) {
|
||||
addTextLineComponent(textSerializer.deserialize(line));
|
||||
}
|
||||
|
||||
public void addItemLineStack(org.bukkit.inventory.ItemStack item) {
|
||||
addItemLinePEStack(SpigotConversionUtil.fromBukkitItemStack(item));
|
||||
}
|
||||
|
||||
public void addItemLine(String serializedItem) {
|
||||
addItemLinePEStack(HologramItem.deserialize(serializedItem));
|
||||
}
|
||||
|
||||
public void addItemLinePEStack(ItemStack item) {
|
||||
HologramItem newLine = new HologramItem(propertyRegistry, packetFactory, null, item);
|
||||
lines.add(newLine);
|
||||
relocateLines(newLine);
|
||||
for (Player viewer : getViewers()) newLine.show(viewer.getPlayer());
|
||||
}
|
||||
|
||||
public void addLine(String line) {
|
||||
addLineComponent(textSerializer.deserialize(line));
|
||||
if (line.toLowerCase().startsWith("item:")) {
|
||||
addItemLine(line.substring(5));
|
||||
} else {
|
||||
addTextLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
public Component getLineComponent(int index) {
|
||||
return lines.get(index).getText();
|
||||
public Component getLineTextComponent(int index) {
|
||||
return ((HologramText) lines.get(index)).getValue();
|
||||
}
|
||||
|
||||
public String getLine(int index) {
|
||||
return textSerializer.serialize(getLineComponent(index));
|
||||
if (lines.get(index) instanceof HologramItem) {
|
||||
return ((HologramItem) lines.get(index)).serialize();
|
||||
} else {
|
||||
return textSerializer.serialize(getLineTextComponent(index));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeLine(int index) {
|
||||
HologramLine line = lines.remove(index);
|
||||
HologramLine<?> line = lines.remove(index);
|
||||
for (Player viewer : getViewers()) line.hide(viewer);
|
||||
relocateLines();
|
||||
}
|
||||
|
||||
public List<HologramLine> getLines() {
|
||||
public List<HologramLine<?>> getLines() {
|
||||
return Collections.unmodifiableList(lines);
|
||||
}
|
||||
|
||||
|
@ -68,25 +97,48 @@ public class HologramImpl extends Viewable implements Hologram {
|
|||
lines.clear();
|
||||
}
|
||||
|
||||
public void insertLineComponent(int index, Component line) {
|
||||
HologramLine newLine = new HologramLine(propertyRegistry, packetFactory, null, line);
|
||||
public void insertTextLineComponent(int index, Component line) {
|
||||
HologramText newLine = new HologramText(propertyRegistry, packetFactory, null, line);
|
||||
lines.add(index, newLine);
|
||||
relocateLines(newLine);
|
||||
for (Player viewer : getViewers()) newLine.show(viewer.getPlayer());
|
||||
}
|
||||
|
||||
public void insertTextLine(int index, String line) {
|
||||
insertTextLineComponent(index, textSerializer.deserialize(line));
|
||||
}
|
||||
|
||||
public void insertItemLineStack(int index, org.bukkit.inventory.ItemStack item) {
|
||||
insertItemLinePEStack(index, SpigotConversionUtil.fromBukkitItemStack(item));
|
||||
}
|
||||
|
||||
public void insertItemLinePEStack(int index, ItemStack item) {
|
||||
HologramItem newLine = new HologramItem(propertyRegistry, packetFactory, null, item);
|
||||
lines.add(index, newLine);
|
||||
relocateLines(newLine);
|
||||
for (Player viewer : getViewers()) newLine.show(viewer.getPlayer());
|
||||
}
|
||||
|
||||
public void insertItemLine(int index, String item) {
|
||||
insertItemLinePEStack(index, HologramItem.deserialize(item));
|
||||
}
|
||||
|
||||
public void insertLine(int index, String line) {
|
||||
insertLineComponent(index, textSerializer.deserialize(line));
|
||||
if (line.toLowerCase().startsWith("item:")) {
|
||||
insertItemLine(index, line.substring(5));
|
||||
} else {
|
||||
insertTextLine(index, line);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void UNSAFE_show(Player player) {
|
||||
for (HologramLine line : lines) line.show(player);
|
||||
for (HologramLine<?> line : lines) line.show(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void UNSAFE_hide(Player player) {
|
||||
for (HologramLine line : lines) line.hide(player);
|
||||
for (HologramLine<?> line : lines) line.hide(player);
|
||||
}
|
||||
|
||||
public long getRefreshDelay() {
|
||||
|
@ -103,7 +155,7 @@ public class HologramImpl extends Viewable implements Hologram {
|
|||
|
||||
public void refresh() {
|
||||
lastRefresh = System.currentTimeMillis();
|
||||
for (HologramLine line : lines) for (Player viewer : getViewers()) line.refreshMeta(viewer);
|
||||
for (HologramLine<?> line : lines) for (Player viewer : getViewers()) line.refreshMeta(viewer);
|
||||
}
|
||||
|
||||
public void setLocation(NpcLocation location) {
|
||||
|
@ -115,10 +167,10 @@ public class HologramImpl extends Viewable implements Hologram {
|
|||
relocateLines(null);
|
||||
}
|
||||
|
||||
private void relocateLines(HologramLine newLine) {
|
||||
private void relocateLines(HologramLine<?> newLine) {
|
||||
final double lineSpacing = configManager.getConfig().lineSpacing();
|
||||
double height = location.getY() + (lines.size() - 1) * lineSpacing + getOffset();
|
||||
for (HologramLine line : lines) {
|
||||
for (HologramLine<?> line : lines) {
|
||||
line.setLocation(location.withY(height), line == newLine ? Collections.emptySet() : getViewers());
|
||||
height -= lineSpacing;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package lol.pyr.znpcsplus.hologram;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTNumber;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.codec.NBTCodec;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import lol.pyr.znpcsplus.api.entity.EntityProperty;
|
||||
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class HologramItem extends HologramLine<ItemStack> {
|
||||
public HologramItem(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, ItemStack item) {
|
||||
super(item, packetFactory, EntityTypes.ITEM, location);
|
||||
addProperty(propertyRegistry.getByName("holo_item"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getProperty(EntityProperty<T> key) {
|
||||
if (key.getName().equalsIgnoreCase("holo_item")) return (T) getValue();
|
||||
return super.getProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocation(NpcLocation location, Collection<Player> viewers) {
|
||||
super.setLocation(location.withY(location.getY() + 2.05), viewers);
|
||||
}
|
||||
|
||||
public static boolean ensureValidItemInput(String in) {
|
||||
if (in == null || in.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int indexOfNbt = in.indexOf("{");
|
||||
if (indexOfNbt != -1) {
|
||||
String typeName = in.substring(0, indexOfNbt);
|
||||
ItemType type = ItemTypes.getByName("minecraft:" + typeName.toLowerCase());
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
String nbtString = in.substring(indexOfNbt);
|
||||
return ensureValidNbt(nbtString);
|
||||
} else {
|
||||
ItemType type = ItemTypes.getByName("minecraft:" + in.toLowerCase());
|
||||
return type != null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean ensureValidNbt(String nbtString) {
|
||||
JsonElement nbtJson;
|
||||
try {
|
||||
nbtJson = JsonParser.parseString(nbtString);
|
||||
} catch (JsonSyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
NBTCodec.jsonToNBT(nbtJson);
|
||||
} catch (Exception ignored) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ItemStack deserialize(String serializedItem) {
|
||||
int indexOfNbt = serializedItem.indexOf("{");
|
||||
String typeName = serializedItem;
|
||||
int amount = 1;
|
||||
NBTCompound nbt = new NBTCompound();
|
||||
if (indexOfNbt != -1) {
|
||||
typeName = serializedItem.substring(0, indexOfNbt);
|
||||
String nbtString = serializedItem.substring(indexOfNbt);
|
||||
JsonElement nbtJson = null;
|
||||
try {
|
||||
nbtJson = JsonParser.parseString(nbtString);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
if (nbtJson != null) {
|
||||
nbt = (NBTCompound) NBTCodec.jsonToNBT(nbtJson);
|
||||
NBTNumber nbtAmount = nbt.getNumberTagOrNull("Count");
|
||||
if (nbtAmount != null) {
|
||||
nbt.removeTag("Count");
|
||||
amount = nbtAmount.getAsInt();
|
||||
if (amount <= 0) amount = 1;
|
||||
if (amount > 127) amount = 127;
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemType type = ItemTypes.getByName("minecraft:" + typeName.toLowerCase());
|
||||
if (type == null) type = ItemTypes.STONE;
|
||||
return ItemStack.builder().type(type).amount(amount).nbt(nbt).build();
|
||||
}
|
||||
|
||||
public String serialize() {
|
||||
NBTCompound nbt = getValue().getNBT();
|
||||
if (nbt == null) nbt = new NBTCompound();
|
||||
if (getValue().getAmount() > 1) nbt.setTag("Count", new NBTInt(getValue().getAmount()));
|
||||
if (nbt.isEmpty()) return "item:" + getValue().getType().getName().toString().replace("minecraft:", "");
|
||||
return "item:" + getValue().getType().getName().toString().replace("minecraft:", "") + NBTCodec.nbtToJson(nbt, true);
|
||||
}
|
||||
}
|
|
@ -1,76 +1,73 @@
|
|||
package lol.pyr.znpcsplus.hologram;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||
import lol.pyr.znpcsplus.api.entity.EntityProperty;
|
||||
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
|
||||
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
||||
import lol.pyr.znpcsplus.entity.PacketEntity;
|
||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class HologramLine implements PropertyHolder {
|
||||
private Component text;
|
||||
private final PacketEntity armorStand;
|
||||
public class HologramLine<M> implements PropertyHolder {
|
||||
private M value;
|
||||
private final PacketEntity entity;
|
||||
private final Set<EntityProperty<?>> properties;
|
||||
|
||||
public HologramLine(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) {
|
||||
this.text = text;
|
||||
public HologramLine(M value, PacketFactory packetFactory, EntityType type, NpcLocation location) {
|
||||
this.value = value;
|
||||
this.entity = new PacketEntity(packetFactory, this, type, location);
|
||||
this.properties = new HashSet<>();
|
||||
this.properties.add(propertyRegistry.getByName("name"));
|
||||
this.properties.add(propertyRegistry.getByName("invisible"));
|
||||
armorStand = new PacketEntity(packetFactory, this, EntityTypes.ARMOR_STAND, location);
|
||||
}
|
||||
|
||||
public Component getText() {
|
||||
return text;
|
||||
public M getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setText(Component text) {
|
||||
this.text = text;
|
||||
public void setValue(M value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void refreshMeta(Player player) {
|
||||
armorStand.refreshMeta(player);
|
||||
entity.refreshMeta(player);
|
||||
}
|
||||
|
||||
protected void show(Player player) {
|
||||
armorStand.spawn(player);
|
||||
entity.spawn(player);
|
||||
}
|
||||
|
||||
protected void hide(Player player) {
|
||||
armorStand.despawn(player);
|
||||
entity.despawn(player);
|
||||
}
|
||||
|
||||
public void setLocation(NpcLocation location, Collection<Player> viewers) {
|
||||
armorStand.setLocation(location, viewers);
|
||||
entity.setLocation(location, viewers);
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return armorStand.getEntityId();
|
||||
return entity.getEntityId();
|
||||
}
|
||||
|
||||
public <T> void addProperty(EntityProperty<T> property) {
|
||||
properties.add(property);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getProperty(EntityProperty<T> key) {
|
||||
if (key.getName().equalsIgnoreCase("invisible")) return (T) Boolean.TRUE;
|
||||
if (key.getName().equalsIgnoreCase("name")) return (T) text;
|
||||
return key.getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(EntityProperty<?> key) {
|
||||
return key.getName().equalsIgnoreCase("name") || key.getName().equalsIgnoreCase("invisible");
|
||||
return properties.contains(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setProperty(EntityProperty<T> key, T value) {
|
||||
throw new UnsupportedOperationException("Can't set properties on a hologram");
|
||||
throw new UnsupportedOperationException("Can't set properties on a hologram line");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package lol.pyr.znpcsplus.hologram;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import lol.pyr.znpcsplus.api.entity.EntityProperty;
|
||||
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class HologramText extends HologramLine<Component> {
|
||||
|
||||
public HologramText(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) {
|
||||
super(text, packetFactory, EntityTypes.ARMOR_STAND, location);
|
||||
addProperty(propertyRegistry.getByName("name"));
|
||||
addProperty(propertyRegistry.getByName("invisible"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getProperty(EntityProperty<T> key) {
|
||||
if (key.getName().equalsIgnoreCase("invisible")) return (T) Boolean.TRUE;
|
||||
if (key.getName().equalsIgnoreCase("name")) return (T) getValue();
|
||||
return super.getProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(EntityProperty<?> key) {
|
||||
return key.getName().equalsIgnoreCase("name") || key.getName().equalsIgnoreCase("invisible");
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
|
|||
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
||||
import lol.pyr.znpcsplus.entity.PropertySerializer;
|
||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||
import lol.pyr.znpcsplus.hologram.HologramLine;
|
||||
import lol.pyr.znpcsplus.interaction.ActionRegistry;
|
||||
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcImpl;
|
||||
|
@ -14,7 +13,6 @@ import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
|
|||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||
import lol.pyr.znpcsplus.storage.NpcStorage;
|
||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
@ -73,7 +71,7 @@ public class YamlStorage implements NpcStorage {
|
|||
HologramImpl hologram = npc.getHologram();
|
||||
hologram.setOffset(config.getDouble("hologram.offset", 0.0));
|
||||
hologram.setRefreshDelay(config.getLong("hologram.refresh-delay", -1));
|
||||
for (String line : config.getStringList("hologram.lines")) hologram.addLineComponent(MiniMessage.miniMessage().deserialize(line));
|
||||
for (String line : config.getStringList("hologram.lines")) hologram.addLine(line);
|
||||
for (String s : config.getStringList("actions")) npc.addAction(actionRegistry.deserialize(s));
|
||||
|
||||
NpcEntryImpl entry = new NpcEntryImpl(config.getString("id"), npc);
|
||||
|
@ -112,8 +110,8 @@ public class YamlStorage implements NpcStorage {
|
|||
if (hologram.getOffset() != 0.0) config.set("hologram.offset", hologram.getOffset());
|
||||
if (hologram.getRefreshDelay() != -1) config.set("hologram.refresh-delay", hologram.getRefreshDelay());
|
||||
List<String> lines = new ArrayList<>(npc.getHologram().getLines().size());
|
||||
for (HologramLine line : hologram.getLines()) {
|
||||
lines.add(MiniMessage.miniMessage().serialize(line.getText()));
|
||||
for (int i = 0; i < hologram.getLines().size(); i++) {
|
||||
lines.add(hologram.getLine(i));
|
||||
}
|
||||
config.set("hologram.lines", lines);
|
||||
config.set("actions", npc.getActions().stream()
|
||||
|
|
Loading…
Reference in a new issue