add all npc types, command improvements

This commit is contained in:
Pyrbu 2023-05-11 10:54:11 +01:00
parent 49f57547c7
commit ba8a0eb6c2
22 changed files with 221 additions and 93 deletions

@ -2,7 +2,6 @@ package lol.pyr.znpcsplus;
import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerPriority; import com.github.retrooper.packetevents.event.PacketListenerPriority;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import lol.pyr.director.adventure.command.CommandManager; import lol.pyr.director.adventure.command.CommandManager;
import lol.pyr.director.adventure.command.MultiCommand; import lol.pyr.director.adventure.command.MultiCommand;
@ -12,13 +11,12 @@ import lol.pyr.znpcsplus.api.ZApiProvider;
import lol.pyr.znpcsplus.commands.*; import lol.pyr.znpcsplus.commands.*;
import lol.pyr.znpcsplus.commands.hologram.*; import lol.pyr.znpcsplus.commands.hologram.*;
import lol.pyr.znpcsplus.commands.parsers.EntityPropertyParser; import lol.pyr.znpcsplus.commands.parsers.EntityPropertyParser;
import lol.pyr.znpcsplus.commands.parsers.NamedTextColorParser;
import lol.pyr.znpcsplus.commands.parsers.NpcEntryParser; import lol.pyr.znpcsplus.commands.parsers.NpcEntryParser;
import lol.pyr.znpcsplus.commands.parsers.NpcTypeParser; import lol.pyr.znpcsplus.commands.parsers.NpcTypeParser;
import lol.pyr.znpcsplus.config.Configs; import lol.pyr.znpcsplus.config.Configs;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl; import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.interaction.InteractionPacketListener; import lol.pyr.znpcsplus.interaction.InteractionPacketListener;
import lol.pyr.znpcsplus.interaction.types.ConsoleCommandAction;
import lol.pyr.znpcsplus.interaction.types.MessageAction;
import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl; import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
@ -27,9 +25,6 @@ import lol.pyr.znpcsplus.scheduling.FoliaScheduler;
import lol.pyr.znpcsplus.scheduling.SpigotScheduler; import lol.pyr.znpcsplus.scheduling.SpigotScheduler;
import lol.pyr.znpcsplus.scheduling.TaskScheduler; import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.skin.cache.SkinCacheCleanTask; import lol.pyr.znpcsplus.skin.cache.SkinCacheCleanTask;
import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import lol.pyr.znpcsplus.tasks.NpcVisibilityTask; import lol.pyr.znpcsplus.tasks.NpcVisibilityTask;
import lol.pyr.znpcsplus.updater.UpdateChecker; import lol.pyr.znpcsplus.updater.UpdateChecker;
import lol.pyr.znpcsplus.updater.UpdateNotificationListener; import lol.pyr.znpcsplus.updater.UpdateNotificationListener;
@ -124,7 +119,7 @@ public class ZNpcsPlus extends JavaPlugin {
PacketEvents.getAPI().init(); PacketEvents.getAPI().init();
PLACEHOLDERS_SUPPORTED = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); PLACEHOLDERS_SUPPORTED = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
if (PLACEHOLDERS_SUPPORTED) log(ChatColor.WHITE + " * Enabling PlaceholderAPI Support..."); if (PLACEHOLDERS_SUPPORTED) log(ChatColor.WHITE + " * Enabling PlaceholderAPI support...");
PLUGIN_FOLDER.mkdirs(); PLUGIN_FOLDER.mkdirs();
PATH_FOLDER.mkdirs(); PATH_FOLDER.mkdirs();
@ -132,6 +127,9 @@ public class ZNpcsPlus extends JavaPlugin {
log(ChatColor.WHITE + " * Loading configurations..."); log(ChatColor.WHITE + " * Loading configurations...");
Configs.init(PLUGIN_FOLDER); Configs.init(PLUGIN_FOLDER);
log(ChatColor.WHITE + " * Defining NPC types...");
NpcTypeImpl.defineTypes();
log(ChatColor.WHITE + " * Registering components..."); log(ChatColor.WHITE + " * Registering components...");
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
new Metrics(this, PLUGIN_ID); new Metrics(this, PLUGIN_ID);
@ -155,37 +153,16 @@ public class ZNpcsPlus extends JavaPlugin {
log(""); log("");
if (Configs.config().debugEnabled()) { if (Configs.config().debugEnabled()) {
int wrap = 20;
int x = 0;
int z = 0;
World world = Bukkit.getWorld("world"); World world = Bukkit.getWorld("world");
if (world == null) world = Bukkit.getWorlds().get(0); if (world == null) world = Bukkit.getWorlds().get(0);
int i = 0;
for (NpcTypeImpl type : NpcTypeImpl.values()) { for (NpcTypeImpl type : NpcTypeImpl.values()) {
NpcEntryImpl entry = NpcRegistryImpl.get().create(ZNpcsPlus.DEBUG_NPC_PREFIX + (z * wrap + x), world, type, new ZLocation(x * 3, 200, z * 3, 0, 0)); NpcEntryImpl entry = NpcRegistryImpl.get().create(ZNpcsPlus.DEBUG_NPC_PREFIX + i, world, type, new ZLocation(i * 3, 200, 0, 0, 0));
entry.setProcessed(true); entry.setProcessed(true);
NpcImpl npc = entry.getNpc(); NpcImpl npc = entry.getNpc();
if (type.getType() == EntityTypes.PLAYER) {
PrefetchedDescriptor.forPlayer("Notch").thenAccept(skin -> npc.setProperty(EntityPropertyImpl.SKIN, skin));
npc.setProperty(EntityPropertyImpl.INVISIBLE, true);
}
npc.setProperty(EntityPropertyImpl.GLOW, NamedTextColor.RED);
npc.getHologram().addLine(Component.text("Hello, World!")); npc.getHologram().addLine(Component.text("Hello, World!"));
if (x++ > wrap) { i++;
x = 0;
z++;
}
} }
NpcEntryImpl entry = NpcRegistryImpl.get().create(ZNpcsPlus.DEBUG_NPC_PREFIX + (z * wrap + x), world, NpcTypeImpl.byName("player"), new ZLocation(x * 3, 200, z * 3, 0, 0));
entry.setProcessed(true);
NpcImpl npc = entry.getNpc();
npc.setProperty(EntityPropertyImpl.SKIN, new FetchingDescriptor("jeb_"));
npc.addAction(new MessageAction(1000L, "<red>Hi, I'm jeb!"));
x++;
entry = NpcRegistryImpl.get().create(ZNpcsPlus.DEBUG_NPC_PREFIX + (z * wrap + x), world, NpcTypeImpl.byName("player"), new ZLocation(x * 3, 200, z * 3, 0, 0));
entry.setProcessed(true);
npc = entry.getNpc();
npc.setProperty(EntityPropertyImpl.SKIN, new MirrorDescriptor());
npc.addAction(new ConsoleCommandAction(1000L, "kick {player}"));
} }
} }
@ -202,11 +179,13 @@ public class ZNpcsPlus extends JavaPlugin {
private void registerCommands() { private void registerCommands() {
// TODO: Messages in here // TODO: Messages in here
CommandManager manager = new CommandManager(this, ADVENTURE, context -> {}); CommandManager manager = new CommandManager(this, ADVENTURE, context -> {});
manager.registerParser(NpcTypeImpl.class, new NpcTypeParser(context -> {})); manager.registerParser(NpcTypeImpl.class, new NpcTypeParser(context -> {}));
manager.registerParser(NpcEntryImpl.class, new NpcEntryParser(context -> {})); manager.registerParser(NpcEntryImpl.class, new NpcEntryParser(context -> {}));
manager.registerParser(EntityPropertyImpl.class, new EntityPropertyParser(context -> {})); manager.registerParser(EntityPropertyImpl.class, new EntityPropertyParser(context -> {}));
manager.registerParser(Integer.class, new IntegerParser(context -> {})); manager.registerParser(Integer.class, new IntegerParser(context -> {}));
manager.registerParser(Boolean.class, new BooleanParser(context -> {})); manager.registerParser(Boolean.class, new BooleanParser(context -> {}));
manager.registerParser(NamedTextColor.class, new NamedTextColorParser(context -> {}));
manager.registerCommand("npc", new MultiCommand() manager.registerCommand("npc", new MultiCommand()
.addSubcommand("action", new ActionCommand()) .addSubcommand("action", new ActionCommand())

@ -3,12 +3,9 @@ package lol.pyr.znpcsplus.commands;
import lol.pyr.director.adventure.command.CommandContext; import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler; import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException; import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeImpl; import lol.pyr.znpcsplus.npc.NpcTypeImpl;
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import lol.pyr.znpcsplus.util.ZLocation; import lol.pyr.znpcsplus.util.ZLocation;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
@ -20,23 +17,17 @@ import java.util.List;
public class CreateCommand implements CommandHandler { public class CreateCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " create <npc_id> <npc_type> <npc_name>"); context.setUsage(context.getLabel() + " create <id> <type>");
Player player = context.ensureSenderIsPlayer(); Player player = context.ensureSenderIsPlayer();
String id = context.popString(); String id = context.popString();
if (NpcRegistryImpl.get().get(id) != null) context.halt(Component.text("NPC with that ID already exists.", NamedTextColor.RED)); if (NpcRegistryImpl.get().get(id) != null) context.halt(Component.text("NPC with that ID already exists.", NamedTextColor.RED));
NpcTypeImpl type = context.parse(NpcTypeImpl.class); NpcTypeImpl type = context.parse(NpcTypeImpl.class);
String name = context.popString();
NpcEntryImpl entry = NpcRegistryImpl.get().create(id, player.getWorld(), type, new ZLocation(player.getLocation())); NpcEntryImpl entry = NpcRegistryImpl.get().create(id, player.getWorld(), type, new ZLocation(player.getLocation()));
entry.enableEverything(); entry.enableEverything();
NpcImpl npc = entry.getNpc(); context.send(Component.text("Created a " + type.getName() + " NPC with ID " + id + ".", NamedTextColor.GREEN));
if (type == NpcTypeImpl.PLAYER) PrefetchedDescriptor.forPlayer(name).thenAccept(skin -> npc.setProperty(EntityPropertyImpl.SKIN, skin));
npc.getHologram().addLine(Component.text(name));
context.send(Component.text("Created NPC with ID " + id + " and name " + name + ".", NamedTextColor.GREEN));
} }
@Override @Override

@ -15,7 +15,7 @@ import java.util.List;
public class DeleteCommand implements CommandHandler { public class DeleteCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " delete <npc_id>"); context.setUsage(context.getLabel() + " delete <id>");
NpcEntryImpl entry = context.parse(NpcEntryImpl.class); NpcEntryImpl entry = context.parse(NpcEntryImpl.class);
NpcRegistryImpl.get().delete(entry.getId()); NpcRegistryImpl.get().delete(entry.getId());
ZNpcsPlus.ADVENTURE.sender(context.getSender()).sendMessage(Component.text("Deleted NPC with ID: " + entry.getId(), NamedTextColor.GREEN)); ZNpcsPlus.ADVENTURE.sender(context.getSender()).sendMessage(Component.text("Deleted NPC with ID: " + entry.getId(), NamedTextColor.GREEN));

@ -17,7 +17,7 @@ import java.util.List;
public class MoveCommand implements CommandHandler { public class MoveCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " move <npc_id>"); context.setUsage(context.getLabel() + " move <id>");
Player player = context.ensureSenderIsPlayer(); Player player = context.ensureSenderIsPlayer();
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
npc.setLocation(new ZLocation(player.getLocation())); npc.setLocation(new ZLocation(player.getLocation()));

@ -17,7 +17,7 @@ import java.util.List;
public class TeleportCommand implements CommandHandler { public class TeleportCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " teleport <npc_id>"); context.setUsage(context.getLabel() + " teleport <id>");
Player player = context.ensureSenderIsPlayer(); Player player = context.ensureSenderIsPlayer();
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
FoliaUtil.teleport(player, npc.getBukkitLocation()); FoliaUtil.teleport(player, npc.getBukkitLocation());

@ -16,7 +16,7 @@ import java.util.List;
public class HoloAddCommand implements CommandHandler { public class HoloAddCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " holo add <npc_id> <text>"); context.setUsage(context.getLabel() + " holo add <id> <text>");
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
hologram.addLine(ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs())); hologram.addLine(ZNpcsPlus.LEGACY_AMPERSAND_SERIALIZER.deserialize(context.dumpAllArgs()));
context.send(Component.text("NPC line added!", NamedTextColor.GREEN)); context.send(Component.text("NPC line added!", NamedTextColor.GREEN));

@ -16,7 +16,7 @@ import java.util.stream.Stream;
public class HoloDeleteCommand implements CommandHandler { public class HoloDeleteCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " holo delete <npc_id> <line>"); context.setUsage(context.getLabel() + " holo delete <id> <line>");
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
int line = context.parse(Integer.class); int line = context.parse(Integer.class);
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED)); if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));

@ -16,7 +16,7 @@ import java.util.List;
public class HoloInfoCommand implements CommandHandler { public class HoloInfoCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " holo info <npc_id>"); context.setUsage(context.getLabel() + " holo info <id>");
NpcEntryImpl entry = context.parse(NpcEntryImpl.class); NpcEntryImpl entry = context.parse(NpcEntryImpl.class);
HologramImpl hologram = entry.getNpc().getHologram(); HologramImpl hologram = entry.getNpc().getHologram();
Component component = Component.text("NPC Hologram Info of ID " + entry.getId() + ":", NamedTextColor.GREEN).appendNewline(); Component component = Component.text("NPC Hologram Info of ID " + entry.getId() + ":", NamedTextColor.GREEN).appendNewline();

@ -17,7 +17,7 @@ import java.util.stream.Stream;
public class HoloInsertCommand implements CommandHandler { public class HoloInsertCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " holo insert <npc_id> <line> <text>"); context.setUsage(context.getLabel() + " holo insert <id> <line> <text>");
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
int line = context.parse(Integer.class); int line = context.parse(Integer.class);
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED)); if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));

@ -17,7 +17,7 @@ import java.util.stream.Stream;
public class HoloSetCommand implements CommandHandler { public class HoloSetCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " holo set <npc_id> <line> <text>"); context.setUsage(context.getLabel() + " holo set <id> <line> <text>");
HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram();
int line = context.parse(Integer.class); int line = context.parse(Integer.class);
if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED)); if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED));

@ -0,0 +1,22 @@
package lol.pyr.znpcsplus.commands.parsers;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.parse.ParserType;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.director.common.message.Message;
import net.kyori.adventure.text.format.NamedTextColor;
import java.util.Deque;
public class NamedTextColorParser extends ParserType<NamedTextColor> {
public NamedTextColorParser(Message<CommandContext> message) {
super(message);
}
@Override
public NamedTextColor parse(Deque<String> deque) throws CommandExecutionException {
NamedTextColor color = NamedTextColor.NAMES.value(deque.pop());
if (color == null) throw new CommandExecutionException();
return color;
}
}

@ -73,7 +73,7 @@ public class HologramImpl extends Viewable implements Hologram {
private void relocateLines(HologramLine newLine) { private void relocateLines(HologramLine newLine) {
final double lineSpacing = Configs.config().lineSpacing(); final double lineSpacing = Configs.config().lineSpacing();
double height = location.getY() + lines.size() * lineSpacing; double height = location.getY() + (lines.size() - 1) * lineSpacing;
for (HologramLine line : lines) { for (HologramLine line : lines) {
line.setLocation(location.withY(height), line == newLine ? Collections.emptySet() : getViewers()); line.setLocation(location.withY(height), line == newLine ? Collections.emptySet() : getViewers());
height -= lineSpacing; height -= lineSpacing;

@ -28,8 +28,9 @@ import java.util.Map;
public interface MetadataFactory { public interface MetadataFactory {
EntityData skinLayers(boolean enabled); EntityData skinLayers(boolean enabled);
EntityData effects(boolean onFire, boolean glowing, boolean invisible); EntityData effects(boolean onFire, boolean glowing, boolean invisible);
Collection<EntityData> name(Component name);
EntityData silent(boolean enabled); EntityData silent(boolean enabled);
Collection<EntityData> name(Component name);
EntityData noGravity();
MetadataFactory factory = get(); MetadataFactory factory = get();
@ -52,6 +53,7 @@ public interface MetadataFactory {
HashMap<ServerVersion, LazyLoader<? extends MetadataFactory>> map = new HashMap<>(); HashMap<ServerVersion, LazyLoader<? extends MetadataFactory>> map = new HashMap<>();
map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new));
map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new)); map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new));
map.put(ServerVersion.V_1_10, LazyLoader.of(V1_10Factory::new));
map.put(ServerVersion.V_1_13, LazyLoader.of(V1_13Factory::new)); map.put(ServerVersion.V_1_13, LazyLoader.of(V1_13Factory::new));
map.put(ServerVersion.V_1_14, LazyLoader.of(V1_14Factory::new)); map.put(ServerVersion.V_1_14, LazyLoader.of(V1_14Factory::new));
map.put(ServerVersion.V_1_16, LazyLoader.of(V1_16Factory::new)); map.put(ServerVersion.V_1_16, LazyLoader.of(V1_16Factory::new));

@ -0,0 +1,11 @@
package lol.pyr.znpcsplus.metadata;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
public class V1_10Factory extends V1_9Factory {
@Override
public EntityData noGravity() {
return new EntityData(5, EntityDataTypes.BOOLEAN, true);
}
}

@ -9,7 +9,7 @@ import net.kyori.adventure.text.Component;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
public class V1_13Factory extends V1_9Factory { public class V1_13Factory extends V1_10Factory {
@Override @Override
public Collection<EntityData> name(Component name) { public Collection<EntityData> name(Component name) {
return ListUtil.immutableList( return ListUtil.immutableList(

@ -27,6 +27,11 @@ public class V1_8Factory implements MetadataFactory {
); );
} }
@Override
public EntityData noGravity() {
throw new UnsupportedOperationException("The gravity entity data isn't supported on this version");
}
@Override @Override
public EntityData silent(boolean enabled) { public EntityData silent(boolean enabled) {
return new EntityData(4, EntityDataTypes.BYTE, enabled ? 1 : 0); return new EntityData(4, EntityDataTypes.BYTE, enabled ? 1 : 0);

@ -56,22 +56,114 @@ public class NpcTypeImpl {
return type; return type;
} }
public static final NpcTypeImpl PLAYER = define( private static boolean defined = false;
new Builder("player", EntityTypes.PLAYER) public static void defineTypes() {
.addProperties(EntityPropertyImpl.SKIN, EntityPropertyImpl.SKIN_LAYERS) if (defined) return;
.setHologramOffset(-0.45D)); defined = true;
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
public static final NpcTypeImpl CREEPER = define( define(new Builder("player", EntityTypes.PLAYER).setHologramOffset(-0.15D)
new Builder("creeper", EntityTypes.CREEPER) .addProperties(EntityPropertyImpl.SKIN, EntityPropertyImpl.SKIN_LAYERS));
.setHologramOffset(-0.6D));
public static final NpcTypeImpl ZOMBIE = define( define(new Builder("armor_stand", EntityTypes.ARMOR_STAND));
new Builder("zombie", EntityTypes.ZOMBIE) define(new Builder("bat", EntityTypes.BAT).setHologramOffset(-1.365));
.setHologramOffset(-0.3D)); define(new Builder("blaze", EntityTypes.BLAZE));
define(new Builder("cat", EntityTypes.CAT));
define(new Builder("cave_spider", EntityTypes.CAVE_SPIDER));
define(new Builder("chicken", EntityTypes.CHICKEN));
define(new Builder("cow", EntityTypes.COW));
define(new Builder("creeper", EntityTypes.CREEPER).setHologramOffset(-0.3D));
define(new Builder("donkey", EntityTypes.DONKEY));
define(new Builder("elder_guardian", EntityTypes.ELDER_GUARDIAN));
define(new Builder("ender_dragon", EntityTypes.ENDER_DRAGON));
define(new Builder("enderman", EntityTypes.ENDERMAN));
define(new Builder("endermite", EntityTypes.ENDERMITE));
define(new Builder("ghast", EntityTypes.GHAST));
define(new Builder("giant", EntityTypes.GIANT));
define(new Builder("guardian", EntityTypes.GUARDIAN));
define(new Builder("horse", EntityTypes.HORSE));
define(new Builder("iron_golem", EntityTypes.IRON_GOLEM));
define(new Builder("magma_cube", EntityTypes.MAGMA_CUBE));
define(new Builder("mooshroom", EntityTypes.MOOSHROOM));
define(new Builder("mule", EntityTypes.MULE));
define(new Builder("ocelot", EntityTypes.OCELOT));
define(new Builder("pig", EntityTypes.PIG));
define(new Builder("rabbit", EntityTypes.RABBIT));
define(new Builder("sheep", EntityTypes.SHEEP));
define(new Builder("silverfish", EntityTypes.SILVERFISH));
define(new Builder("skeleton", EntityTypes.SKELETON));
define(new Builder("skeleton_horse", EntityTypes.SKELETON_HORSE));
define(new Builder("slime", EntityTypes.SLIME));
define(new Builder("snow_golem", EntityTypes.SNOW_GOLEM));
define(new Builder("spider", EntityTypes.SPIDER));
define(new Builder("squid", EntityTypes.SQUID));
define(new Builder("villager", EntityTypes.VILLAGER));
define(new Builder("witch", EntityTypes.WITCH));
define(new Builder("wither", EntityTypes.WITHER));
define(new Builder("wither_skeleton", EntityTypes.WITHER_SKELETON));
define(new Builder("wolf", EntityTypes.WOLF));
define(new Builder("zombie", EntityTypes.ZOMBIE));
define(new Builder("zombie_horse", EntityTypes.ZOMBIE_HORSE));
define(new Builder("zombie_villager", EntityTypes.ZOMBIE_VILLAGER));
public static final NpcTypeImpl SKELETON = define( if (!version.isNewerThanOrEquals(ServerVersion.V_1_9)) return;
new Builder("skeleton", EntityTypes.SKELETON) define(new Builder("shulker", EntityTypes.SHULKER));
.setHologramOffset(-0.3D));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_10)) return;
define(new Builder("husk", EntityTypes.HUSK));
define(new Builder("polar_bear", EntityTypes.POLAR_BEAR));
define(new Builder("stray", EntityTypes.STRAY));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_11)) return;
define(new Builder("evoker", EntityTypes.EVOKER));
define(new Builder("llama", EntityTypes.LLAMA));
define(new Builder("vex", EntityTypes.VEX));
define(new Builder("vindicator", EntityTypes.VINDICATOR));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_12)) return;
define(new Builder("illusioner", EntityTypes.ILLUSIONER));
define(new Builder("parrot", EntityTypes.PARROT));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_13)) return;
define(new Builder("cod", EntityTypes.COD));
define(new Builder("dolphin", EntityTypes.DOLPHIN));
define(new Builder("drowned", EntityTypes.DROWNED));
define(new Builder("phantom", EntityTypes.PHANTOM));
define(new Builder("pufferfish", EntityTypes.PUFFERFISH));
define(new Builder("salmon", EntityTypes.SALMON));
define(new Builder("tropical_fish", EntityTypes.TROPICAL_FISH));
define(new Builder("turtle", EntityTypes.TURTLE));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_14)) return;
define(new Builder("fox", EntityTypes.FOX));
define(new Builder("panda", EntityTypes.PANDA));
define(new Builder("pillager", EntityTypes.PILLAGER));
define(new Builder("ravager", EntityTypes.RAVAGER));
define(new Builder("trader_llama", EntityTypes.TRADER_LLAMA));
define(new Builder("wandering_trader", EntityTypes.WANDERING_TRADER));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_15)) return;
define(new Builder("bee", EntityTypes.BEE));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_16)) return;
define(new Builder("hoglin", EntityTypes.HOGLIN));
define(new Builder("piglin", EntityTypes.PIGLIN));
define(new Builder("piglin_brute", EntityTypes.PIGLIN_BRUTE));
define(new Builder("strider", EntityTypes.STRIDER));
define(new Builder("zoglin", EntityTypes.ZOGLIN));
define(new Builder("zombified_piglin", EntityTypes.ZOMBIFIED_PIGLIN));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_17)) return;
define(new Builder("axolotl", EntityTypes.AXOLOTL));
define(new Builder("glow_squid", EntityTypes.GLOW_SQUID));
define(new Builder("goat", EntityTypes.GOAT));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_19)) return;
define(new Builder("allay", EntityTypes.ALLAY));
define(new Builder("frog", EntityTypes.FROG));
define(new Builder("tadpole", EntityTypes.TADPOLE));
define(new Builder("warden", EntityTypes.WARDEN));
}
private static final class Builder { private static final class Builder {
private final String name; private final String name;

@ -4,14 +4,12 @@ import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import lol.pyr.znpcsplus.ZNpcsPlus; import lol.pyr.znpcsplus.ZNpcsPlus;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.util.LazyLoader; import lol.pyr.znpcsplus.util.LazyLoader;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.HashMap; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public interface PacketFactory { public interface PacketFactory {
@ -23,6 +21,7 @@ public interface PacketFactory {
void removeTabPlayer(Player player, PacketEntity entity); void removeTabPlayer(Player player, PacketEntity entity);
void createTeam(Player player, PacketEntity entity, PropertyHolder properties); void createTeam(Player player, PacketEntity entity, PropertyHolder properties);
void removeTeam(Player player, PacketEntity entity); void removeTeam(Player player, PacketEntity entity);
Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties);
void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties); void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties);
void sendMetadata(Player player, PacketEntity entity, List<EntityData> data); void sendMetadata(Player player, PacketEntity entity, List<EntityData> data);
@ -47,6 +46,7 @@ public interface PacketFactory {
HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> map = new HashMap<>(); HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> map = new HashMap<>();
map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new));
map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new)); map.put(ServerVersion.V_1_9, LazyLoader.of(V1_9Factory::new));
map.put(ServerVersion.V_1_10, LazyLoader.of(V1_10Factory::new));
map.put(ServerVersion.V_1_14, LazyLoader.of(V1_14Factory::new)); map.put(ServerVersion.V_1_14, LazyLoader.of(V1_14Factory::new));
map.put(ServerVersion.V_1_19, LazyLoader.of(V1_19Factory::new)); map.put(ServerVersion.V_1_19, LazyLoader.of(V1_19Factory::new));
return map; return map;

@ -0,0 +1,18 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import org.bukkit.entity.Player;
import java.util.Map;
public class V1_10Factory extends V1_9Factory {
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
Map<Integer, EntityData> data = super.generateMetadata(player, entity, properties);
add(data, MetadataFactory.get().noGravity());
return data;
}
}

@ -1,5 +1,6 @@
package lol.pyr.znpcsplus.packets; package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.util.ZLocation; import lol.pyr.znpcsplus.util.ZLocation;
@ -9,13 +10,14 @@ import org.bukkit.entity.Player;
import java.util.Optional; import java.util.Optional;
public class V1_14Factory extends V1_9Factory { public class V1_14Factory extends V1_10Factory {
@Override @Override
public void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties) { public void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties) {
ZLocation location = entity.getLocation(); ZLocation location = entity.getLocation();
sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(),
location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d())));
if (properties.hasProperty(EntityPropertyImpl.GLOW)) createTeam(player, entity, properties); if (properties.hasProperty(EntityPropertyImpl.GLOW)) createTeam(player, entity, properties);
sendAllMetadata(player, entity, properties); sendAllMetadata(player, entity, properties);
createTeam(player, entity, properties);
} }
} }

@ -21,10 +21,7 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class V1_8Factory implements PacketFactory { public class V1_8Factory implements PacketFactory {
@ -106,14 +103,19 @@ public class V1_8Factory implements PacketFactory {
sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null)); sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null));
} }
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
HashMap<Integer, EntityData> data = new HashMap<>();
if (entity.getType() == EntityTypes.PLAYER) add(data, MetadataFactory.get().skinLayers(properties.getProperty(EntityPropertyImpl.SKIN_LAYERS)));
add(data, MetadataFactory.get().effects(properties.getProperty(EntityPropertyImpl.FIRE), false, properties.getProperty(EntityPropertyImpl.INVISIBLE)));
add(data, MetadataFactory.get().silent(properties.getProperty(EntityPropertyImpl.SILENT)));
if (properties.hasProperty(EntityPropertyImpl.NAME)) addAll(data, MetadataFactory.get().name(properties.getProperty(EntityPropertyImpl.NAME)));
return data;
}
@Override @Override
public void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties) { public void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
ArrayList<EntityData> data = new ArrayList<>(); sendMetadata(player, entity, new ArrayList<>(generateMetadata(player, entity, properties).values()));
if (entity.getType() == EntityTypes.PLAYER) data.add(MetadataFactory.get().skinLayers(properties.getProperty(EntityPropertyImpl.SKIN_LAYERS)));
data.add(MetadataFactory.get().effects(properties.getProperty(EntityPropertyImpl.FIRE), false, properties.getProperty(EntityPropertyImpl.INVISIBLE)));
data.add(MetadataFactory.get().silent(properties.getProperty(EntityPropertyImpl.SILENT)));
if (properties.hasProperty(EntityPropertyImpl.NAME)) data.addAll(MetadataFactory.get().name(properties.getProperty(EntityPropertyImpl.NAME)));
sendMetadata(player, entity, data);
} }
@Override @Override
@ -139,4 +141,12 @@ public class V1_8Factory implements PacketFactory {
}); });
return future; return future;
} }
protected void add(Map<Integer, EntityData> map, EntityData data) {
map.put(data.getIndex(), data);
}
protected void addAll(Map<Integer, EntityData> map, Collection<EntityData> data) {
for (EntityData d : data) add(map, d);
}
} }

@ -1,23 +1,19 @@
package lol.pyr.znpcsplus.packets; package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory; import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.Map;
public class V1_9Factory extends V1_8Factory { public class V1_9Factory extends V1_8Factory {
@Override @Override
public void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties) { public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
ArrayList<EntityData> data = new ArrayList<>(); Map<Integer, EntityData> data = super.generateMetadata(player, entity, properties);
if (entity.getType() == EntityTypes.PLAYER) data.add(MetadataFactory.get().skinLayers(properties.getProperty(EntityPropertyImpl.SKIN_LAYERS))); add(data, MetadataFactory.get().effects(properties.getProperty(EntityPropertyImpl.FIRE), properties.hasProperty(EntityPropertyImpl.GLOW), properties.getProperty(EntityPropertyImpl.INVISIBLE)));
data.add(MetadataFactory.get().effects(properties.getProperty(EntityPropertyImpl.FIRE), properties.hasProperty(EntityPropertyImpl.GLOW), properties.getProperty(EntityPropertyImpl.INVISIBLE))); return data;
data.add(MetadataFactory.get().silent(properties.getProperty(EntityPropertyImpl.SILENT)));
if (properties.hasProperty(EntityPropertyImpl.NAME)) data.addAll(MetadataFactory.get().name(properties.getProperty(EntityPropertyImpl.NAME)));
sendMetadata(player, entity, data);
} }
} }