From c4a5874dcaaa14083dfe624d57b07c816599e208 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 23 Apr 2023 20:24:31 +0100 Subject: [PATCH 01/22] start work --- src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 4 ++++ .../java/lol/pyr/znpcsplus/npc/NPCType.java | 4 ++++ .../pyr/znpcsplus/packets/PacketFactory.java | 21 ++++++++++++++++ .../pyr/znpcsplus/packets/V1_8Factory.java | 4 ++++ .../lol/pyr/znpcsplus/util/LazyLoader.java | 24 +++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPC.java create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCType.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java new file mode 100644 index 0000000..d619ef8 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.npc; + +public class NPC { +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java new file mode 100644 index 0000000..4f90fe4 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.npc; + +public class NPCType { +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java new file mode 100644 index 0000000..ce5f394 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -0,0 +1,21 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.manager.server.ServerVersion; +import lol.pyr.znpcsplus.util.LazyLoader; + +import java.util.Map; + +public interface PacketFactory { + + Map> factories = buildFactoryMap(); + + + static PacketFactory get() { + return factories.get(PacketEvents.getAPI().getServerManager().getVersion()).get(); + } + + private static Map> buildFactoryMap() { + + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java new file mode 100644 index 0000000..6db778c --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.packets; + +public class V1_8Factory implements PacketFactory { +} diff --git a/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java b/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java new file mode 100644 index 0000000..e39d16a --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.util; + +public class LazyLoader { + private final ObjectProvider provider; + private T value; + + private LazyLoader(ObjectProvider provider) { + this.provider = provider; + } + + public T get() { + if (value == null) value = provider.provide(); + return value; + } + + public static LazyLoader of(ObjectProvider provider) { + return new LazyLoader<>(provider); + } + + @FunctionalInterface + public interface ObjectProvider { + T provide(); + } +} From 944dc14fd2879ced1a5a8061ae34541e41a70411 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 23 Apr 2023 20:24:31 +0100 Subject: [PATCH 02/22] start work --- src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 4 ++++ .../java/lol/pyr/znpcsplus/npc/NPCType.java | 4 ++++ .../pyr/znpcsplus/packets/PacketFactory.java | 21 ++++++++++++++++ .../pyr/znpcsplus/packets/V1_8Factory.java | 4 ++++ .../lol/pyr/znpcsplus/util/LazyLoader.java | 24 +++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPC.java create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCType.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java new file mode 100644 index 0000000..d619ef8 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.npc; + +public class NPC { +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java new file mode 100644 index 0000000..4f90fe4 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.npc; + +public class NPCType { +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java new file mode 100644 index 0000000..ce5f394 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -0,0 +1,21 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.manager.server.ServerVersion; +import lol.pyr.znpcsplus.util.LazyLoader; + +import java.util.Map; + +public interface PacketFactory { + + Map> factories = buildFactoryMap(); + + + static PacketFactory get() { + return factories.get(PacketEvents.getAPI().getServerManager().getVersion()).get(); + } + + private static Map> buildFactoryMap() { + + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java new file mode 100644 index 0000000..6db778c --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.packets; + +public class V1_8Factory implements PacketFactory { +} diff --git a/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java b/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java new file mode 100644 index 0000000..e39d16a --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.util; + +public class LazyLoader { + private final ObjectProvider provider; + private T value; + + private LazyLoader(ObjectProvider provider) { + this.provider = provider; + } + + public T get() { + if (value == null) value = provider.provide(); + return value; + } + + public static LazyLoader of(ObjectProvider provider) { + return new LazyLoader<>(provider); + } + + @FunctionalInterface + public interface ObjectProvider { + T provide(); + } +} From b24a6ef93ddaf40a962c45fae65f82ba1d70ddbd Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 17:12:50 +0100 Subject: [PATCH 03/22] so much progress --- .gitignore | 2 + .../commands/list/DefaultCommand.java | 4 +- .../configuration/ConfigurationValue.java | 2 +- .../npc/task/NPCVisibilityTask.java | 34 -------- .../znpcservers/reflection/Reflections.java | 11 +++ .../reflection/types/FieldReflection.java | 51 +++++++++-- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 46 +++++----- .../znpcsplus/entity/EntityIDProvider.java | 15 ++++ .../pyr/znpcsplus/entity/PacketEntity.java | 46 ++++++++++ .../pyr/znpcsplus/entity/PacketLocation.java | 85 +++++++++++++++++++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 82 ++++++++++++++++++ .../lol/pyr/znpcsplus/npc/NPCRegistry.java | 25 ++++++ .../java/lol/pyr/znpcsplus/npc/NPCType.java | 32 +++++++ .../pyr/znpcsplus/packets/PacketFactory.java | 27 +++++- .../pyr/znpcsplus/packets/V1_8Factory.java | 54 ++++++++++++ .../pyr/znpcsplus/properties/NPCProperty.java | 4 + .../znpcsplus/tasks/NPCVisibilityTask.java | 24 ++++++ 17 files changed, 469 insertions(+), 75 deletions(-) delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java create mode 100644 src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java create mode 100644 src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java diff --git a/.gitignore b/.gitignore index ca905d1..ca98d55 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ bin/ /.idea/ gradle.properties + +gradle.properties diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java index 207b26a..f22cf33 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java @@ -91,7 +91,7 @@ public class DefaultCommand extends Command { Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NOT_SUPPORTED_NPC_TYPE); return; } - ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name); + // ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name); Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); } @@ -111,7 +111,7 @@ public class DefaultCommand extends Command { Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); return; } - ZNPCsPlus.deleteNPC(id); + // ZNPCsPlus.deleteNPC(id); Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java index f9b67bf..1ed63e9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java +++ b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java @@ -18,7 +18,7 @@ public enum ConfigurationValue { SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class), MAX_PATH_LOCATIONS("config", 500, Integer.class), NAMING_METHOD("config", NamingType.DEFAULT, NamingType.class), - DEBUG_ENABLED("config", true, Boolean.class), + DEBUG_ENABLED("config", false, Boolean.class), LINE_SPACING("config", 0.3D, Double.class), ANIMATION_RGB("config", false, Boolean.class), CHECK_FOR_UPDATES("config", true, Boolean.class), diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java b/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java deleted file mode 100644 index 764f07e..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.task; - -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel; -import io.github.znetworkw.znpcservers.user.ZUser; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; - -public class NPCVisibilityTask extends BukkitRunnable { - public NPCVisibilityTask(Plugin serversNPC) { - runTaskTimerAsynchronously(serversNPC, 60L, 10L); - } - - public void run() { - int distSq = ConfigurationConstants.VIEW_DISTANCE * ConfigurationConstants.VIEW_DISTANCE; - for (NPC npc : NPC.all()) for (Player player : Bukkit.getOnlinePlayers()) { - ZUser zUser = ZUser.find(player); - boolean canSeeNPC = (player.getWorld() == npc.getLocation().getWorld() && player.getLocation().distanceSquared(npc.getLocation()) <= distSq); - if (npc.getViewers().contains(zUser) && !canSeeNPC) { - npc.delete(zUser); - continue; - } - if (canSeeNPC) { - if (!npc.getViewers().contains(zUser)) npc.spawn(zUser); - npc.getHologram().updateNames(zUser); - ConversationModel conversationStorage = npc.getNpcPojo().getConversation(); - if (conversationStorage != null && conversationStorage.getConversationType() == ConversationModel.ConversationType.RADIUS) npc.tryStartConversation(player); - } - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index 4accb86..1615ab1 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -15,6 +15,7 @@ import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; /** * Class containing all of the lazy-loaded reflections that the plugin uses to access @@ -657,4 +658,14 @@ public final class Reflections { public static final ReflectionLazyLoader COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) .withClassName("CraftServer") .withFieldName("commandMap")).valueLoader(Bukkit.getServer(), CommandMap.class); + + public static final FieldReflection.ValueModifier ENTITY_ID_MODIFIER = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) + .withClassName(ENTITY_CLASS) + .withFieldName("entityCount") + .setStrict(!Utils.versionNewer(14))).staticValueModifier(int.class); + + public static final ReflectionLazyLoader ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) + .withClassName(ENTITY_CLASS) + .withFieldName("entityCount") + .setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java index 3262a93..0dbd720 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java @@ -44,25 +44,35 @@ public class FieldReflection extends ReflectionLazyLoader { logger.accept("Field Type: " + expectType); } - public FieldValueReflection staticValueLoader() { + public ValueReflection staticValueLoader() { return staticValueLoader(Object.class); } @SuppressWarnings("unused") - public FieldValueReflection staticValueLoader(Class valueType) { - return new FieldValueReflection<>(this, possibleClassNames, null, strict); + public ValueReflection staticValueLoader(Class valueType) { + return new ValueReflection<>(this, possibleClassNames, null, strict); } @SuppressWarnings("unused") - public FieldValueReflection valueLoader(Object obj, Class valueType) { - return new FieldValueReflection<>(this, possibleClassNames, obj, strict); + public ValueReflection valueLoader(Object obj, Class valueType) { + return new ValueReflection<>(this, possibleClassNames, obj, strict); } - private static class FieldValueReflection extends ReflectionLazyLoader { - private final Object obj; - private final FieldReflection fieldReflection; + @SuppressWarnings("unused") + public ValueModifier staticValueModifier(Class valueType) { + return new ValueModifier<>(this, possibleClassNames, null, strict); + } - public FieldValueReflection(FieldReflection fieldReflection, List className, Object obj, boolean strict) { + @SuppressWarnings("unused") + public ValueModifier valueModifier(Object obj, Class valueType) { + return new ValueModifier<>(this, possibleClassNames, obj, strict); + } + + public static class ValueReflection extends ReflectionLazyLoader { + protected final Object obj; + protected final FieldReflection fieldReflection; + + private ValueReflection(FieldReflection fieldReflection, List className, Object obj, boolean strict) { super(className, strict); this.obj = obj; this.fieldReflection = fieldReflection; @@ -78,4 +88,27 @@ public class FieldReflection extends ReflectionLazyLoader { fieldReflection.printDebugInfo(logger); } } + + public static class ValueModifier extends ValueReflection { + private ValueModifier(FieldReflection fieldReflection, List className, Object obj, boolean strict) { + super(fieldReflection, className, obj, strict); + } + + @Override + public T get() { + try { + return load(); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public void set(T value) { + try { + fieldReflection.get().set(obj, value); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } } \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 8434106..2c39893 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -10,19 +10,20 @@ import io.github.znetworkw.znpcservers.configuration.Configuration; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.listeners.PlayerListener; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.NPCModel; import io.github.znetworkw.znpcservers.npc.NPCPath; -import io.github.znetworkw.znpcservers.npc.NPCType; import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener; import io.github.znetworkw.znpcservers.npc.task.NPCPositionTask; import io.github.znetworkw.znpcservers.npc.task.NPCSaveTask; -import io.github.znetworkw.znpcservers.npc.task.NPCVisibilityTask; import io.github.znetworkw.znpcservers.user.ZUser; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; import io.github.znetworkw.znpcservers.utility.location.ZLocation; +import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCRegistry; +import lol.pyr.znpcsplus.npc.NPCType; +import lol.pyr.znpcsplus.tasks.NPCVisibilityTask; import lol.pyr.znpcsplus.updater.UpdateChecker; import lol.pyr.znpcsplus.updater.UpdateNotificationListener; import net.kyori.adventure.platform.bukkit.BukkitAudiences; @@ -30,13 +31,12 @@ import org.apache.commons.io.FileUtils; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; import java.io.IOException; -import java.util.Collections; import java.util.logging.Logger; public class ZNPCsPlus extends JavaPlugin { @@ -56,25 +56,6 @@ public class ZNPCsPlus extends JavaPlugin { private boolean enabled = false; - public static NPC createNPC(int id, NPCType npcType, Location location, String name) { - NPC find = NPC.find(id); - if (find != null) - return find; - NPCModel pojo = new NPCModel(id).withHologramLines(Collections.singletonList(name)) - .withHologramHeight(npcType.getHoloHeight()) - .withLocation(new ZLocation(location)) - .withNpcType(npcType); - ConfigurationConstants.NPC_LIST.add(pojo); - return new NPC(pojo, true); - } - - public static void deleteNPC(int npcID) { - NPC npc = NPC.find(npcID); - if (npc == null) throw new IllegalStateException("can't find npc: " + npcID); - NPC.unregister(npcID); - ConfigurationConstants.NPC_LIST.remove(npc.getNpcPojo()); - } - @Override public void onLoad() { PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); @@ -146,6 +127,21 @@ public class ZNPCsPlus extends JavaPlugin { enabled = true; log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)"); log(""); + + if (ConfigurationConstants.DEBUG_ENABLED) { + int wrap = 20; + int x = 0; + int z = 0; + World world = Bukkit.getWorld("world"); + if (world == null) world = Bukkit.getWorlds().get(0); + for (NPCType type : NPCType.values()) { + NPCRegistry.register("debug_npc" + (z * wrap + x), new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0))); + if (x++ > wrap) { + x = 0; + z++; + } + } + } } @Override diff --git a/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java b/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java new file mode 100644 index 0000000..dcf8b78 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java @@ -0,0 +1,15 @@ +package lol.pyr.znpcsplus.entity; + +import io.github.znetworkw.znpcservers.reflection.Reflections; +import io.github.znetworkw.znpcservers.utility.Utils; + +public class EntityIDProvider { + public static int reserve() { + if (Utils.versionNewer(14)) return Reflections.ATOMIC_ENTITY_ID_FIELD.get().incrementAndGet(); + else { + int id = Reflections.ENTITY_ID_MODIFIER.get(); + Reflections.ENTITY_ID_MODIFIER.set(id + 1); + return id; + } + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java new file mode 100644 index 0000000..09354c4 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -0,0 +1,46 @@ +package lol.pyr.znpcsplus.entity; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import lol.pyr.znpcsplus.packets.PacketFactory; +import org.bukkit.entity.Player; + +import java.util.Set; + +public class PacketEntity { + private final int entityId; + private final EntityType type; + private PacketLocation location; + + public PacketEntity(EntityType type, PacketLocation location) { + this.entityId = EntityIDProvider.reserve(); + this.type = type; + this.location = location; + } + + public int getEntityId() { + return entityId; + } + + public PacketLocation getLocation() { + return location; + } + + public EntityType getType() { + return type; + } + + public void setLocation(PacketLocation location, Set viewers) { + this.location = location; + for (Player viewer : viewers) PacketFactory.get().teleportEntity(viewer, this); + } + + public void spawn(Player player) { + if (type == EntityTypes.PLAYER) PacketFactory.get().spawnPlayer(player, this); + else PacketFactory.get().spawnEntity(player, this); + } + + public void despawn(Player player) { + PacketFactory.get().destroyEntity(player, this); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java new file mode 100644 index 0000000..631442b --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java @@ -0,0 +1,85 @@ +package lol.pyr.znpcsplus.entity; + +import com.github.retrooper.packetevents.util.Vector3d; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.util.NumberConversions; +import org.bukkit.util.Vector; + +public class PacketLocation { + private final double x; + private final double y; + private final double z; + private final float yaw; + private final float pitch; + + public PacketLocation(double x, double y, double z, float yaw, float pitch) { + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } + + public PacketLocation(Location location) { + this(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + } + + public double getX() { + return this.x; + } + + public double getY() { + return this.y; + } + + public double getZ() { + return this.z; + } + + public float getYaw() { + return this.yaw; + } + + public float getPitch() { + return this.pitch; + } + + public Location toBukkitLocation(World world) { + return new Location(world, this.x, this.y, this.z, this.yaw, this.pitch); + } + + public Vector toVector() { + return new Vector(x, y, z); + } + + public Vector3d toVector3d() { + return new Vector3d(x, y, z); + } + + private static final double _2PI = 2 * Math.PI; + + public Location lookingAt(Location loc) { + return lookingAt(new PacketLocation(loc)).toBukkitLocation(loc.getWorld()); + } + + public PacketLocation lookingAt(PacketLocation loc) { + final double x = loc.getX() - this.x; + final double z = loc.getZ() - this.z; + final double y = loc.getY() - this.y; + + if (x == 0 && z == 0) { + return new PacketLocation(this.x, this.y, this.z, this.yaw, y > 0 ? -90 : 90); + } + + double x2 = NumberConversions.square(x); + double z2 = NumberConversions.square(z); + double xz = Math.sqrt(x2 + z2); + + double theta = Math.atan2(-x, z); + float yaw = (float) Math.toDegrees((theta + _2PI) % _2PI); + float pitch = (float) Math.toDegrees(Math.atan(-y / xz)); + + return new PacketLocation(this.x, this.y, this.z, yaw, pitch); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index d619ef8..100279b 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -1,4 +1,86 @@ package lol.pyr.znpcsplus.npc; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.Set; + public class NPC { + private final Set viewers = new HashSet<>(); + private final String worldName; + private PacketEntity entity; + private PacketLocation location; + private NPCType type; + + public NPC(World world, NPCType type, PacketLocation location) { + this.worldName = world.getName(); + this.type = type; + this.location = location; + entity = new PacketEntity(type.getType(), location); // TODO: Entity ID Provider + } + + public void setType(NPCType type) { + _hideAll(); + this.type = type; + entity = new PacketEntity(type.getType(), entity.getLocation()); + _showAll(); + } + + public NPCType getType() { + return type; + } + + public PacketLocation getLocation() { + return location; + } + + public void setLocation(PacketLocation location) { + this.location = location; + entity.setLocation(location, viewers); + } + + public World getWorld() { + return Bukkit.getWorld(worldName); + } + + public void delete() { + _hideAll(); + viewers.clear(); + } + + public void show(Player player) { + if (viewers.contains(player)) return; + _show(player); + viewers.add(player); + } + + private void _show(Player player) { + entity.spawn(player); + } + + public void hide(Player player) { + if (!viewers.contains(player)) return; + _hide(player); + viewers.remove(player); + } + + private void _hide(Player player) { + entity.despawn(player); + } + + private void _hideAll() { + for (Player viewer : viewers) _hide(viewer); + } + + private void _showAll() { + for (Player viewer : viewers) _show(viewer); + } + + public boolean isShown(Player player) { + return viewers.contains(player); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java new file mode 100644 index 0000000..de74b7d --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java @@ -0,0 +1,25 @@ +package lol.pyr.znpcsplus.npc; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class NPCRegistry { + private static final Map npcMap = new HashMap<>(); + + public static NPC get(String id) { + return npcMap.get(id); + } + + public static Collection all() { + return npcMap.values(); + } + + public static void register(String id, NPC npc) { + npcMap.put(id, npc); + } + + public static void unregister(String id) { + npcMap.remove(id); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 4f90fe4..6773df1 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -1,4 +1,36 @@ package lol.pyr.znpcsplus.npc; +import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.google.common.collect.ImmutableList; + +import java.util.List; + public class NPCType { + private final static ImmutableList npcTypes; + + public static List values() { + return npcTypes; + } + + private final EntityType type; + + public NPCType(EntityType type) { + this.type = type; + } + + public EntityType getType() { + return type; + } + + static { + ImmutableList.Builder builder = new ImmutableList.Builder<>(); + + builder.add(new NPCType(EntityTypes.PLAYER)); + builder.add(new NPCType(EntityTypes.CREEPER)); + builder.add(new NPCType(EntityTypes.ZOMBIE)); + builder.add(new NPCType(EntityTypes.SKELETON)); + + npcTypes = builder.build(); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index ce5f394..d57b4fb 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -2,20 +2,39 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.util.LazyLoader; +import org.bukkit.entity.Player; +import java.util.HashMap; import java.util.Map; public interface PacketFactory { + void spawnPlayer(Player player, PacketEntity entity); + void spawnEntity(Player player, PacketEntity entity); + void destroyEntity(Player player, PacketEntity entity); + void teleportEntity(Player player, PacketEntity entity); + void addTabPlayer(Player player, PacketEntity entity); + void removeTabPlayer(Player player, PacketEntity entity); - Map> factories = buildFactoryMap(); - + PacketFactory factory = get(); static PacketFactory get() { - return factories.get(PacketEvents.getAPI().getServerManager().getVersion()).get(); + if (factory != null) return factory; + ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); + Map> factories = buildFactoryMap(); + if (factories.containsKey(version)) return factories.get(version).get(); + for (ServerVersion v : ServerVersion.reversedValues()) { + if (v.isNewerThan(version)) continue; + if (!factories.containsKey(v)) continue; + return factories.get(v).get(); + } + throw new RuntimeException("Unsupported version!"); } private static Map> buildFactoryMap() { - + HashMap> map = new HashMap<>(); + map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); + return map; } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 6db778c..3a31083 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -1,4 +1,58 @@ package lol.pyr.znpcsplus.packets; +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.play.server.*; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + public class V1_8Factory implements PacketFactory { + @Override + public void spawnPlayer(Player player, PacketEntity entity) { + addTabPlayer(player, entity); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer()); + // TODO + } + + @Override + public void spawnEntity(Player player, PacketEntity entity) { + PacketLocation location = entity.getLocation(); + EntityType type = entity.getType(); + ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, type.getLegacyId(clientVersion) == -1 ? + new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), new UUID(0, 0), type, location.toVector3d(), + location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : + new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.empty(), entity.getType(), location.toVector3d(), + location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); + } + + @Override + public void destroyEntity(Player player, PacketEntity entity) { + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + } + + @Override + public void teleportEntity(Player player, PacketEntity entity) { + PacketLocation location = entity.getLocation(); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), + location.toVector3d(), location.getYaw(), location.getPitch(), true)); + } + + @Override + public void addTabPlayer(Player player, PacketEntity entity) { + + } + + @Override + public void removeTabPlayer(Player player, PacketEntity entity) { + new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, new UserProfile(gameProfile.getId(), gameProfile.getName()), null, 1)) + } } diff --git a/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java new file mode 100644 index 0000000..bbf2a10 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.properties; + +public class NPCProperty { +} diff --git a/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java new file mode 100644 index 0000000..59a5d97 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.tasks; + +import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; +import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCRegistry; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +public class NPCVisibilityTask extends BukkitRunnable { + public NPCVisibilityTask(Plugin plugin) { + runTaskTimerAsynchronously(plugin, 60L, 10L); + } + + public void run() { + int distSq = ConfigurationConstants.VIEW_DISTANCE * ConfigurationConstants.VIEW_DISTANCE; + for (NPC npc : NPCRegistry.all()) for (Player player : Bukkit.getOnlinePlayers()) { + boolean inRange = (player.getWorld() == npc.getWorld() && player.getLocation().distanceSquared(npc.getLocation().toBukkitLocation(npc.getWorld())) <= distSq); + if (!inRange && npc.isShown(player)) npc.hide(player); + if (inRange && !npc.isShown(player)) npc.show(player); + } + } +} From 8cf4f25c5a6e489eb548c80599c0f80b206ae8f5 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 19:10:55 +0100 Subject: [PATCH 04/22] stuff --- .../commands/list/DefaultCommand.java | 4 +- .../znetworkw/znpcservers/npc/NPCSkin.java | 9 ++- .../znpcservers/reflection/Reflections.java | 3 + .../reflection/types/FieldReflection.java | 23 +++++--- .../znpcservers/skin/SkinFetcher.java | 4 +- .../znpcservers/skin/SkinFetcherResult.java | 2 +- .../pyr/znpcsplus/entity/PacketEntity.java | 8 +++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 14 +++++ .../pyr/znpcsplus/packets/PacketFactory.java | 4 ++ .../pyr/znpcsplus/packets/V1_14Factory.java | 17 ++++++ .../pyr/znpcsplus/packets/V1_19Factory.java | 30 ++++++++++ .../pyr/znpcsplus/packets/V1_8Factory.java | 58 +++++++++++++++---- .../znpcsplus/properties/NPCPropertyKey.java | 7 +++ 13 files changed, 156 insertions(+), 27 deletions(-) create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java index f22cf33..4f5bd69 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java @@ -39,14 +39,14 @@ public class DefaultCommand extends Command { private static final Joiner SPACE_JOINER = Joiner.on(" "); - private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (values, ex) -> { + private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (value, signature, ex) -> { if (ex != null) { Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.CANT_GET_SKIN, skin); ZNPCsPlus.LOGGER.warning("Failed to fetch skin:"); ex.printStackTrace(); return; } - npc.changeSkin(NPCSkin.forValues(values)); + npc.changeSkin(NPCSkin.forValues(value, signature)); Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.GET_SKIN); }); diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java index c1807a4..94baaa9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java @@ -9,14 +9,13 @@ public class NPCSkin { private final String texture; private final String signature; - protected NPCSkin(String... values) { - if (values.length < 1) throw new IllegalArgumentException("Invalid arguments for NPC skin constructor"); - this.texture = values[0]; - this.signature = values[1]; + protected NPCSkin(String texture, String signature) { + this.texture = texture; + this.signature = signature; } public static NPCSkin forValues(String... values) { - return new NPCSkin((values.length > 0) ? values : new String[0]); + return new NPCSkin(values[0], (values.length > 1) ? values[1] : null); } public static void forName(String skin, SkinFetcherResult skinFetcherResult) { diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index 1615ab1..1ea090f 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -667,5 +667,8 @@ public final class Reflections { public static final ReflectionLazyLoader ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withClassName(ENTITY_CLASS) .withFieldName("entityCount") + .withFieldName("d") + .withFieldName("c") + .withExpectResult(AtomicInteger.class) .setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java index 0dbd720..b222326 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java @@ -18,26 +18,35 @@ public class FieldReflection extends ReflectionLazyLoader { } protected Field load() throws NoSuchFieldException { - for (Class clazz : this.reflectionClasses) { - Field field = load(clazz); + if (fieldName != null && fieldName.length() > 0) for (Class clazz : this.reflectionClasses) { + Field field = loadByName(clazz); + if (field != null) return field; + } + if (expectType != null) for (Class clazz : this.reflectionClasses) { + Field field = loadByType(clazz); if (field != null) return field; } return null; } - private Field load(Class clazz) { - if (expectType != null) for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) { - field.setAccessible(true); - return field; - } + private Field loadByName(Class clazz) { try { Field field = clazz.getDeclaredField(fieldName); + if (expectType != null && !field.getType().equals(expectType)) return null; field.setAccessible(true); return field; } catch (NoSuchFieldException ignored) {} return null; } + private Field loadByType(Class clazz) { + for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) { + field.setAccessible(true); + return field; + } + return null; + } + @Override protected void printDebugInfo(Consumer logger) { logger.accept("Field Name: " + fieldName); diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java index 096ede8..0421af9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java @@ -46,11 +46,11 @@ public class SkinFetcher { }); completableFuture.whenComplete((response, throwable) -> { if (completableFuture.isCompletedExceptionally()) { - skinFetcherResult.onDone(null, throwable); + skinFetcherResult.onDone(null, null, throwable); } else { JsonObject jsonObject = response.getAsJsonObject(this.builder.getAPIServer().getValueKey()); JsonObject properties = jsonObject.getAsJsonObject(this.builder.getAPIServer().getSignatureKey()); - skinFetcherResult.onDone(new String[]{properties.get("value").getAsString(), properties.get("signature").getAsString()}, null); + skinFetcherResult.onDone(properties.get("value").getAsString(), properties.get("signature").getAsString(), null); } }); return completableFuture; diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java index 59db73e..ec55efa 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java @@ -1,5 +1,5 @@ package io.github.znetworkw.znpcservers.skin; public interface SkinFetcherResult { - void onDone(String[] paramArrayOfString, Throwable paramThrowable); + void onDone(String value, String signature, Throwable paramThrowable); } diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 09354c4..93d9dcb 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -6,14 +6,18 @@ import lol.pyr.znpcsplus.packets.PacketFactory; import org.bukkit.entity.Player; import java.util.Set; +import java.util.UUID; public class PacketEntity { private final int entityId; + private final UUID uuid; + private final EntityType type; private PacketLocation location; public PacketEntity(EntityType type, PacketLocation location) { this.entityId = EntityIDProvider.reserve(); + this.uuid = UUID.randomUUID(); this.type = type; this.location = location; } @@ -26,6 +30,10 @@ public class PacketEntity { return location; } + public UUID getUuid() { + return uuid; + } + public EntityType getType() { return type; } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 100279b..9283a5e 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -2,11 +2,15 @@ package lol.pyr.znpcsplus.npc; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.properties.NPCProperty; +import lol.pyr.znpcsplus.properties.NPCPropertyKey; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; public class NPC { @@ -16,6 +20,8 @@ public class NPC { private PacketLocation location; private NPCType type; + private final Map propertyMap = new HashMap<>(); + public NPC(World world, NPCType type, PacketLocation location) { this.worldName = world.getName(); this.type = type; @@ -83,4 +89,12 @@ public class NPC { public boolean isShown(Player player) { return viewers.contains(player); } + + public NPCProperty getProperty(NPCPropertyKey key) { + return propertyMap.get(key); + } + + public boolean hasProperty(NPCPropertyKey key) { + return propertyMap.containsKey(key); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index d57b4fb..3baf573 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -16,6 +16,8 @@ public interface PacketFactory { void teleportEntity(Player player, PacketEntity entity); void addTabPlayer(Player player, PacketEntity entity); void removeTabPlayer(Player player, PacketEntity entity); + void createTeam(Player player, PacketEntity entity); + void removeTeam(Player player, PacketEntity entity); PacketFactory factory = get(); @@ -35,6 +37,8 @@ public interface PacketFactory { private static Map> buildFactoryMap() { HashMap> map = new HashMap<>(); map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); + map.put(ServerVersion.V_1_14, LazyLoader.of(V1_14Factory::new)); + map.put(ServerVersion.V_1_19, LazyLoader.of(V1_19Factory::new)); return map; } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java new file mode 100644 index 0000000..07c8a7e --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java @@ -0,0 +1,17 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import org.bukkit.entity.Player; + +import java.util.Optional; + +public class V1_14Factory extends V1_8Factory { + @Override + public void spawnEntity(Player player, PacketEntity entity) { + PacketLocation location = entity.getLocation(); + sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), + location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java new file mode 100644 index 0000000..98aaee1 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java @@ -0,0 +1,30 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate; +import lol.pyr.znpcsplus.entity.PacketEntity; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; + +import java.util.EnumSet; + +public class V1_19Factory extends V1_14Factory { + @Override + public void addTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return; + WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( + new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), false, 1, GameMode.CREATIVE, + Component.empty(), null); + sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, + WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); + } + + @Override + public void removeTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfoRemove(entity.getUuid())); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 3a31083..26e7d4b 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -2,24 +2,32 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.GameMode; import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.*; +import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; import java.util.List; import java.util.Optional; -import java.util.UUID; public class V1_8Factory implements PacketFactory { @Override public void spawnPlayer(Player player, PacketEntity entity) { addTabPlayer(player, entity); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer()); - // TODO + createTeam(player, entity); + PacketLocation location = entity.getLocation(); + sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), + entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); + ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> removeTabPlayer(player, entity), 60); } @Override @@ -27,32 +35,62 @@ public class V1_8Factory implements PacketFactory { PacketLocation location = entity.getLocation(); EntityType type = entity.getType(); ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, type.getLegacyId(clientVersion) == -1 ? - new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), new UUID(0, 0), type, location.toVector3d(), + sendPacket(player, type.getLegacyId(clientVersion) == -1 ? + new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), entity.getUuid(), type, location.toVector3d(), location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : - new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.empty(), entity.getType(), location.toVector3d(), + new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); } @Override public void destroyEntity(Player player, PacketEntity entity) { - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, entity); } @Override public void teleportEntity(Player player, PacketEntity entity) { PacketLocation location = entity.getLocation(); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), + sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), location.toVector3d(), location.getYaw(), location.getPitch(), true)); } @Override public void addTabPlayer(Player player, PacketEntity entity) { - + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfo( + WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), + new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), GameMode.CREATIVE, 1))); } @Override public void removeTabPlayer(Player player, PacketEntity entity) { - new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, new UserProfile(gameProfile.getId(), gameProfile.getName()), null, 1)) + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfo( + WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, + new UserProfile(entity.getUuid(), null), null, -1))); + } + + @Override + public void createTeam(Player player, PacketEntity entity) { + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo( + Component.empty(), + Component.empty(), + Component.empty(), + WrapperPlayServerTeams.NameTagVisibility.NEVER, + WrapperPlayServerTeams.CollisionRule.NEVER, + NamedTextColor.WHITE, + WrapperPlayServerTeams.OptionData.NONE + ))); + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, Integer.toString(entity.getEntityId()))); + } + + @Override + public void removeTeam(Player player, PacketEntity entity) { + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null)); + } + + protected void sendPacket(Player player, PacketWrapper packet) { + PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet); } } diff --git a/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java b/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java new file mode 100644 index 0000000..9f87d74 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java @@ -0,0 +1,7 @@ +package lol.pyr.znpcsplus.properties; + +public class NPCPropertyKey { + public NPCPropertyKey() {} + + public static NPCPropertyKey<> +} From 30b8d906654e56cc55b2da85f94a0fe41b0ffc07 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Sun, 23 Apr 2023 20:24:31 +0100 Subject: [PATCH 05/22] start work --- src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 4 ++++ .../java/lol/pyr/znpcsplus/npc/NPCType.java | 4 ++++ .../pyr/znpcsplus/packets/PacketFactory.java | 21 ++++++++++++++++ .../pyr/znpcsplus/packets/V1_8Factory.java | 4 ++++ .../lol/pyr/znpcsplus/util/LazyLoader.java | 24 +++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPC.java create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCType.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java new file mode 100644 index 0000000..d619ef8 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.npc; + +public class NPC { +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java new file mode 100644 index 0000000..4f90fe4 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.npc; + +public class NPCType { +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java new file mode 100644 index 0000000..ce5f394 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -0,0 +1,21 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.manager.server.ServerVersion; +import lol.pyr.znpcsplus.util.LazyLoader; + +import java.util.Map; + +public interface PacketFactory { + + Map> factories = buildFactoryMap(); + + + static PacketFactory get() { + return factories.get(PacketEvents.getAPI().getServerManager().getVersion()).get(); + } + + private static Map> buildFactoryMap() { + + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java new file mode 100644 index 0000000..6db778c --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.packets; + +public class V1_8Factory implements PacketFactory { +} diff --git a/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java b/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java new file mode 100644 index 0000000..e39d16a --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.util; + +public class LazyLoader { + private final ObjectProvider provider; + private T value; + + private LazyLoader(ObjectProvider provider) { + this.provider = provider; + } + + public T get() { + if (value == null) value = provider.provide(); + return value; + } + + public static LazyLoader of(ObjectProvider provider) { + return new LazyLoader<>(provider); + } + + @FunctionalInterface + public interface ObjectProvider { + T provide(); + } +} From d32870628bd9115021920a27bae414ed8bd080f3 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 17:12:50 +0100 Subject: [PATCH 06/22] so much progress --- .gitignore | 2 + .../commands/list/DefaultCommand.java | 4 +- .../configuration/ConfigurationValue.java | 2 +- .../npc/task/NPCVisibilityTask.java | 34 -------- .../znpcservers/reflection/Reflections.java | 11 +++ .../reflection/types/FieldReflection.java | 51 +++++++++-- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 46 +++++----- .../znpcsplus/entity/EntityIDProvider.java | 15 ++++ .../pyr/znpcsplus/entity/PacketEntity.java | 46 ++++++++++ .../pyr/znpcsplus/entity/PacketLocation.java | 85 +++++++++++++++++++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 82 ++++++++++++++++++ .../lol/pyr/znpcsplus/npc/NPCRegistry.java | 25 ++++++ .../java/lol/pyr/znpcsplus/npc/NPCType.java | 32 +++++++ .../pyr/znpcsplus/packets/PacketFactory.java | 27 +++++- .../pyr/znpcsplus/packets/V1_8Factory.java | 54 ++++++++++++ .../pyr/znpcsplus/properties/NPCProperty.java | 4 + .../znpcsplus/tasks/NPCVisibilityTask.java | 24 ++++++ 17 files changed, 469 insertions(+), 75 deletions(-) delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java create mode 100644 src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java create mode 100644 src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java diff --git a/.gitignore b/.gitignore index ca905d1..ca98d55 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ bin/ /.idea/ gradle.properties + +gradle.properties diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java index 207b26a..f22cf33 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java @@ -91,7 +91,7 @@ public class DefaultCommand extends Command { Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NOT_SUPPORTED_NPC_TYPE); return; } - ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name); + // ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name); Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); } @@ -111,7 +111,7 @@ public class DefaultCommand extends Command { Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); return; } - ZNPCsPlus.deleteNPC(id); + // ZNPCsPlus.deleteNPC(id); Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java index f9b67bf..1ed63e9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java +++ b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java @@ -18,7 +18,7 @@ public enum ConfigurationValue { SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class), MAX_PATH_LOCATIONS("config", 500, Integer.class), NAMING_METHOD("config", NamingType.DEFAULT, NamingType.class), - DEBUG_ENABLED("config", true, Boolean.class), + DEBUG_ENABLED("config", false, Boolean.class), LINE_SPACING("config", 0.3D, Double.class), ANIMATION_RGB("config", false, Boolean.class), CHECK_FOR_UPDATES("config", true, Boolean.class), diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java b/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java deleted file mode 100644 index 764f07e..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCVisibilityTask.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.task; - -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel; -import io.github.znetworkw.znpcservers.user.ZUser; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; - -public class NPCVisibilityTask extends BukkitRunnable { - public NPCVisibilityTask(Plugin serversNPC) { - runTaskTimerAsynchronously(serversNPC, 60L, 10L); - } - - public void run() { - int distSq = ConfigurationConstants.VIEW_DISTANCE * ConfigurationConstants.VIEW_DISTANCE; - for (NPC npc : NPC.all()) for (Player player : Bukkit.getOnlinePlayers()) { - ZUser zUser = ZUser.find(player); - boolean canSeeNPC = (player.getWorld() == npc.getLocation().getWorld() && player.getLocation().distanceSquared(npc.getLocation()) <= distSq); - if (npc.getViewers().contains(zUser) && !canSeeNPC) { - npc.delete(zUser); - continue; - } - if (canSeeNPC) { - if (!npc.getViewers().contains(zUser)) npc.spawn(zUser); - npc.getHologram().updateNames(zUser); - ConversationModel conversationStorage = npc.getNpcPojo().getConversation(); - if (conversationStorage != null && conversationStorage.getConversationType() == ConversationModel.ConversationType.RADIUS) npc.tryStartConversation(player); - } - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index 4accb86..1615ab1 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -15,6 +15,7 @@ import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; /** * Class containing all of the lazy-loaded reflections that the plugin uses to access @@ -657,4 +658,14 @@ public final class Reflections { public static final ReflectionLazyLoader COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) .withClassName("CraftServer") .withFieldName("commandMap")).valueLoader(Bukkit.getServer(), CommandMap.class); + + public static final FieldReflection.ValueModifier ENTITY_ID_MODIFIER = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) + .withClassName(ENTITY_CLASS) + .withFieldName("entityCount") + .setStrict(!Utils.versionNewer(14))).staticValueModifier(int.class); + + public static final ReflectionLazyLoader ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) + .withClassName(ENTITY_CLASS) + .withFieldName("entityCount") + .setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java index 3262a93..0dbd720 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java @@ -44,25 +44,35 @@ public class FieldReflection extends ReflectionLazyLoader { logger.accept("Field Type: " + expectType); } - public FieldValueReflection staticValueLoader() { + public ValueReflection staticValueLoader() { return staticValueLoader(Object.class); } @SuppressWarnings("unused") - public FieldValueReflection staticValueLoader(Class valueType) { - return new FieldValueReflection<>(this, possibleClassNames, null, strict); + public ValueReflection staticValueLoader(Class valueType) { + return new ValueReflection<>(this, possibleClassNames, null, strict); } @SuppressWarnings("unused") - public FieldValueReflection valueLoader(Object obj, Class valueType) { - return new FieldValueReflection<>(this, possibleClassNames, obj, strict); + public ValueReflection valueLoader(Object obj, Class valueType) { + return new ValueReflection<>(this, possibleClassNames, obj, strict); } - private static class FieldValueReflection extends ReflectionLazyLoader { - private final Object obj; - private final FieldReflection fieldReflection; + @SuppressWarnings("unused") + public ValueModifier staticValueModifier(Class valueType) { + return new ValueModifier<>(this, possibleClassNames, null, strict); + } - public FieldValueReflection(FieldReflection fieldReflection, List className, Object obj, boolean strict) { + @SuppressWarnings("unused") + public ValueModifier valueModifier(Object obj, Class valueType) { + return new ValueModifier<>(this, possibleClassNames, obj, strict); + } + + public static class ValueReflection extends ReflectionLazyLoader { + protected final Object obj; + protected final FieldReflection fieldReflection; + + private ValueReflection(FieldReflection fieldReflection, List className, Object obj, boolean strict) { super(className, strict); this.obj = obj; this.fieldReflection = fieldReflection; @@ -78,4 +88,27 @@ public class FieldReflection extends ReflectionLazyLoader { fieldReflection.printDebugInfo(logger); } } + + public static class ValueModifier extends ValueReflection { + private ValueModifier(FieldReflection fieldReflection, List className, Object obj, boolean strict) { + super(fieldReflection, className, obj, strict); + } + + @Override + public T get() { + try { + return load(); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public void set(T value) { + try { + fieldReflection.get().set(obj, value); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } } \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 8434106..2c39893 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -10,19 +10,20 @@ import io.github.znetworkw.znpcservers.configuration.Configuration; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.listeners.PlayerListener; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.NPCModel; import io.github.znetworkw.znpcservers.npc.NPCPath; -import io.github.znetworkw.znpcservers.npc.NPCType; import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener; import io.github.znetworkw.znpcservers.npc.task.NPCPositionTask; import io.github.znetworkw.znpcservers.npc.task.NPCSaveTask; -import io.github.znetworkw.znpcservers.npc.task.NPCVisibilityTask; import io.github.znetworkw.znpcservers.user.ZUser; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; import io.github.znetworkw.znpcservers.utility.location.ZLocation; +import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCRegistry; +import lol.pyr.znpcsplus.npc.NPCType; +import lol.pyr.znpcsplus.tasks.NPCVisibilityTask; import lol.pyr.znpcsplus.updater.UpdateChecker; import lol.pyr.znpcsplus.updater.UpdateNotificationListener; import net.kyori.adventure.platform.bukkit.BukkitAudiences; @@ -30,13 +31,12 @@ import org.apache.commons.io.FileUtils; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; import java.io.IOException; -import java.util.Collections; import java.util.logging.Logger; public class ZNPCsPlus extends JavaPlugin { @@ -56,25 +56,6 @@ public class ZNPCsPlus extends JavaPlugin { private boolean enabled = false; - public static NPC createNPC(int id, NPCType npcType, Location location, String name) { - NPC find = NPC.find(id); - if (find != null) - return find; - NPCModel pojo = new NPCModel(id).withHologramLines(Collections.singletonList(name)) - .withHologramHeight(npcType.getHoloHeight()) - .withLocation(new ZLocation(location)) - .withNpcType(npcType); - ConfigurationConstants.NPC_LIST.add(pojo); - return new NPC(pojo, true); - } - - public static void deleteNPC(int npcID) { - NPC npc = NPC.find(npcID); - if (npc == null) throw new IllegalStateException("can't find npc: " + npcID); - NPC.unregister(npcID); - ConfigurationConstants.NPC_LIST.remove(npc.getNpcPojo()); - } - @Override public void onLoad() { PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); @@ -146,6 +127,21 @@ public class ZNPCsPlus extends JavaPlugin { enabled = true; log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)"); log(""); + + if (ConfigurationConstants.DEBUG_ENABLED) { + int wrap = 20; + int x = 0; + int z = 0; + World world = Bukkit.getWorld("world"); + if (world == null) world = Bukkit.getWorlds().get(0); + for (NPCType type : NPCType.values()) { + NPCRegistry.register("debug_npc" + (z * wrap + x), new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0))); + if (x++ > wrap) { + x = 0; + z++; + } + } + } } @Override diff --git a/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java b/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java new file mode 100644 index 0000000..dcf8b78 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java @@ -0,0 +1,15 @@ +package lol.pyr.znpcsplus.entity; + +import io.github.znetworkw.znpcservers.reflection.Reflections; +import io.github.znetworkw.znpcservers.utility.Utils; + +public class EntityIDProvider { + public static int reserve() { + if (Utils.versionNewer(14)) return Reflections.ATOMIC_ENTITY_ID_FIELD.get().incrementAndGet(); + else { + int id = Reflections.ENTITY_ID_MODIFIER.get(); + Reflections.ENTITY_ID_MODIFIER.set(id + 1); + return id; + } + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java new file mode 100644 index 0000000..09354c4 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -0,0 +1,46 @@ +package lol.pyr.znpcsplus.entity; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import lol.pyr.znpcsplus.packets.PacketFactory; +import org.bukkit.entity.Player; + +import java.util.Set; + +public class PacketEntity { + private final int entityId; + private final EntityType type; + private PacketLocation location; + + public PacketEntity(EntityType type, PacketLocation location) { + this.entityId = EntityIDProvider.reserve(); + this.type = type; + this.location = location; + } + + public int getEntityId() { + return entityId; + } + + public PacketLocation getLocation() { + return location; + } + + public EntityType getType() { + return type; + } + + public void setLocation(PacketLocation location, Set viewers) { + this.location = location; + for (Player viewer : viewers) PacketFactory.get().teleportEntity(viewer, this); + } + + public void spawn(Player player) { + if (type == EntityTypes.PLAYER) PacketFactory.get().spawnPlayer(player, this); + else PacketFactory.get().spawnEntity(player, this); + } + + public void despawn(Player player) { + PacketFactory.get().destroyEntity(player, this); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java new file mode 100644 index 0000000..631442b --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java @@ -0,0 +1,85 @@ +package lol.pyr.znpcsplus.entity; + +import com.github.retrooper.packetevents.util.Vector3d; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.util.NumberConversions; +import org.bukkit.util.Vector; + +public class PacketLocation { + private final double x; + private final double y; + private final double z; + private final float yaw; + private final float pitch; + + public PacketLocation(double x, double y, double z, float yaw, float pitch) { + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } + + public PacketLocation(Location location) { + this(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + } + + public double getX() { + return this.x; + } + + public double getY() { + return this.y; + } + + public double getZ() { + return this.z; + } + + public float getYaw() { + return this.yaw; + } + + public float getPitch() { + return this.pitch; + } + + public Location toBukkitLocation(World world) { + return new Location(world, this.x, this.y, this.z, this.yaw, this.pitch); + } + + public Vector toVector() { + return new Vector(x, y, z); + } + + public Vector3d toVector3d() { + return new Vector3d(x, y, z); + } + + private static final double _2PI = 2 * Math.PI; + + public Location lookingAt(Location loc) { + return lookingAt(new PacketLocation(loc)).toBukkitLocation(loc.getWorld()); + } + + public PacketLocation lookingAt(PacketLocation loc) { + final double x = loc.getX() - this.x; + final double z = loc.getZ() - this.z; + final double y = loc.getY() - this.y; + + if (x == 0 && z == 0) { + return new PacketLocation(this.x, this.y, this.z, this.yaw, y > 0 ? -90 : 90); + } + + double x2 = NumberConversions.square(x); + double z2 = NumberConversions.square(z); + double xz = Math.sqrt(x2 + z2); + + double theta = Math.atan2(-x, z); + float yaw = (float) Math.toDegrees((theta + _2PI) % _2PI); + float pitch = (float) Math.toDegrees(Math.atan(-y / xz)); + + return new PacketLocation(this.x, this.y, this.z, yaw, pitch); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index d619ef8..100279b 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -1,4 +1,86 @@ package lol.pyr.znpcsplus.npc; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.Set; + public class NPC { + private final Set viewers = new HashSet<>(); + private final String worldName; + private PacketEntity entity; + private PacketLocation location; + private NPCType type; + + public NPC(World world, NPCType type, PacketLocation location) { + this.worldName = world.getName(); + this.type = type; + this.location = location; + entity = new PacketEntity(type.getType(), location); // TODO: Entity ID Provider + } + + public void setType(NPCType type) { + _hideAll(); + this.type = type; + entity = new PacketEntity(type.getType(), entity.getLocation()); + _showAll(); + } + + public NPCType getType() { + return type; + } + + public PacketLocation getLocation() { + return location; + } + + public void setLocation(PacketLocation location) { + this.location = location; + entity.setLocation(location, viewers); + } + + public World getWorld() { + return Bukkit.getWorld(worldName); + } + + public void delete() { + _hideAll(); + viewers.clear(); + } + + public void show(Player player) { + if (viewers.contains(player)) return; + _show(player); + viewers.add(player); + } + + private void _show(Player player) { + entity.spawn(player); + } + + public void hide(Player player) { + if (!viewers.contains(player)) return; + _hide(player); + viewers.remove(player); + } + + private void _hide(Player player) { + entity.despawn(player); + } + + private void _hideAll() { + for (Player viewer : viewers) _hide(viewer); + } + + private void _showAll() { + for (Player viewer : viewers) _show(viewer); + } + + public boolean isShown(Player player) { + return viewers.contains(player); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java new file mode 100644 index 0000000..de74b7d --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java @@ -0,0 +1,25 @@ +package lol.pyr.znpcsplus.npc; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class NPCRegistry { + private static final Map npcMap = new HashMap<>(); + + public static NPC get(String id) { + return npcMap.get(id); + } + + public static Collection all() { + return npcMap.values(); + } + + public static void register(String id, NPC npc) { + npcMap.put(id, npc); + } + + public static void unregister(String id) { + npcMap.remove(id); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 4f90fe4..6773df1 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -1,4 +1,36 @@ package lol.pyr.znpcsplus.npc; +import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.google.common.collect.ImmutableList; + +import java.util.List; + public class NPCType { + private final static ImmutableList npcTypes; + + public static List values() { + return npcTypes; + } + + private final EntityType type; + + public NPCType(EntityType type) { + this.type = type; + } + + public EntityType getType() { + return type; + } + + static { + ImmutableList.Builder builder = new ImmutableList.Builder<>(); + + builder.add(new NPCType(EntityTypes.PLAYER)); + builder.add(new NPCType(EntityTypes.CREEPER)); + builder.add(new NPCType(EntityTypes.ZOMBIE)); + builder.add(new NPCType(EntityTypes.SKELETON)); + + npcTypes = builder.build(); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index ce5f394..d57b4fb 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -2,20 +2,39 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.util.LazyLoader; +import org.bukkit.entity.Player; +import java.util.HashMap; import java.util.Map; public interface PacketFactory { + void spawnPlayer(Player player, PacketEntity entity); + void spawnEntity(Player player, PacketEntity entity); + void destroyEntity(Player player, PacketEntity entity); + void teleportEntity(Player player, PacketEntity entity); + void addTabPlayer(Player player, PacketEntity entity); + void removeTabPlayer(Player player, PacketEntity entity); - Map> factories = buildFactoryMap(); - + PacketFactory factory = get(); static PacketFactory get() { - return factories.get(PacketEvents.getAPI().getServerManager().getVersion()).get(); + if (factory != null) return factory; + ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); + Map> factories = buildFactoryMap(); + if (factories.containsKey(version)) return factories.get(version).get(); + for (ServerVersion v : ServerVersion.reversedValues()) { + if (v.isNewerThan(version)) continue; + if (!factories.containsKey(v)) continue; + return factories.get(v).get(); + } + throw new RuntimeException("Unsupported version!"); } private static Map> buildFactoryMap() { - + HashMap> map = new HashMap<>(); + map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); + return map; } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 6db778c..3a31083 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -1,4 +1,58 @@ package lol.pyr.znpcsplus.packets; +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.play.server.*; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + public class V1_8Factory implements PacketFactory { + @Override + public void spawnPlayer(Player player, PacketEntity entity) { + addTabPlayer(player, entity); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer()); + // TODO + } + + @Override + public void spawnEntity(Player player, PacketEntity entity) { + PacketLocation location = entity.getLocation(); + EntityType type = entity.getType(); + ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, type.getLegacyId(clientVersion) == -1 ? + new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), new UUID(0, 0), type, location.toVector3d(), + location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : + new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.empty(), entity.getType(), location.toVector3d(), + location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); + } + + @Override + public void destroyEntity(Player player, PacketEntity entity) { + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + } + + @Override + public void teleportEntity(Player player, PacketEntity entity) { + PacketLocation location = entity.getLocation(); + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), + location.toVector3d(), location.getYaw(), location.getPitch(), true)); + } + + @Override + public void addTabPlayer(Player player, PacketEntity entity) { + + } + + @Override + public void removeTabPlayer(Player player, PacketEntity entity) { + new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, new UserProfile(gameProfile.getId(), gameProfile.getName()), null, 1)) + } } diff --git a/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java new file mode 100644 index 0000000..bbf2a10 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java @@ -0,0 +1,4 @@ +package lol.pyr.znpcsplus.properties; + +public class NPCProperty { +} diff --git a/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java new file mode 100644 index 0000000..59a5d97 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.tasks; + +import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; +import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCRegistry; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +public class NPCVisibilityTask extends BukkitRunnable { + public NPCVisibilityTask(Plugin plugin) { + runTaskTimerAsynchronously(plugin, 60L, 10L); + } + + public void run() { + int distSq = ConfigurationConstants.VIEW_DISTANCE * ConfigurationConstants.VIEW_DISTANCE; + for (NPC npc : NPCRegistry.all()) for (Player player : Bukkit.getOnlinePlayers()) { + boolean inRange = (player.getWorld() == npc.getWorld() && player.getLocation().distanceSquared(npc.getLocation().toBukkitLocation(npc.getWorld())) <= distSq); + if (!inRange && npc.isShown(player)) npc.hide(player); + if (inRange && !npc.isShown(player)) npc.show(player); + } + } +} From e039071a380465664fda756d6c7d5af74aec5e32 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 19:10:55 +0100 Subject: [PATCH 07/22] stuff --- .../commands/list/DefaultCommand.java | 4 +- .../znetworkw/znpcservers/npc/NPCSkin.java | 9 ++- .../znpcservers/reflection/Reflections.java | 3 + .../reflection/types/FieldReflection.java | 23 +++++--- .../znpcservers/skin/SkinFetcher.java | 4 +- .../znpcservers/skin/SkinFetcherResult.java | 2 +- .../pyr/znpcsplus/entity/PacketEntity.java | 8 +++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 14 +++++ .../pyr/znpcsplus/packets/PacketFactory.java | 4 ++ .../pyr/znpcsplus/packets/V1_14Factory.java | 17 ++++++ .../pyr/znpcsplus/packets/V1_19Factory.java | 30 ++++++++++ .../pyr/znpcsplus/packets/V1_8Factory.java | 58 +++++++++++++++---- .../znpcsplus/properties/NPCPropertyKey.java | 7 +++ 13 files changed, 156 insertions(+), 27 deletions(-) create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java index f22cf33..4f5bd69 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java @@ -39,14 +39,14 @@ public class DefaultCommand extends Command { private static final Joiner SPACE_JOINER = Joiner.on(" "); - private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (values, ex) -> { + private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (value, signature, ex) -> { if (ex != null) { Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.CANT_GET_SKIN, skin); ZNPCsPlus.LOGGER.warning("Failed to fetch skin:"); ex.printStackTrace(); return; } - npc.changeSkin(NPCSkin.forValues(values)); + npc.changeSkin(NPCSkin.forValues(value, signature)); Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.GET_SKIN); }); diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java index c1807a4..94baaa9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java @@ -9,14 +9,13 @@ public class NPCSkin { private final String texture; private final String signature; - protected NPCSkin(String... values) { - if (values.length < 1) throw new IllegalArgumentException("Invalid arguments for NPC skin constructor"); - this.texture = values[0]; - this.signature = values[1]; + protected NPCSkin(String texture, String signature) { + this.texture = texture; + this.signature = signature; } public static NPCSkin forValues(String... values) { - return new NPCSkin((values.length > 0) ? values : new String[0]); + return new NPCSkin(values[0], (values.length > 1) ? values[1] : null); } public static void forName(String skin, SkinFetcherResult skinFetcherResult) { diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index 1615ab1..1ea090f 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -667,5 +667,8 @@ public final class Reflections { public static final ReflectionLazyLoader ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withClassName(ENTITY_CLASS) .withFieldName("entityCount") + .withFieldName("d") + .withFieldName("c") + .withExpectResult(AtomicInteger.class) .setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java index 0dbd720..b222326 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java @@ -18,26 +18,35 @@ public class FieldReflection extends ReflectionLazyLoader { } protected Field load() throws NoSuchFieldException { - for (Class clazz : this.reflectionClasses) { - Field field = load(clazz); + if (fieldName != null && fieldName.length() > 0) for (Class clazz : this.reflectionClasses) { + Field field = loadByName(clazz); + if (field != null) return field; + } + if (expectType != null) for (Class clazz : this.reflectionClasses) { + Field field = loadByType(clazz); if (field != null) return field; } return null; } - private Field load(Class clazz) { - if (expectType != null) for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) { - field.setAccessible(true); - return field; - } + private Field loadByName(Class clazz) { try { Field field = clazz.getDeclaredField(fieldName); + if (expectType != null && !field.getType().equals(expectType)) return null; field.setAccessible(true); return field; } catch (NoSuchFieldException ignored) {} return null; } + private Field loadByType(Class clazz) { + for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) { + field.setAccessible(true); + return field; + } + return null; + } + @Override protected void printDebugInfo(Consumer logger) { logger.accept("Field Name: " + fieldName); diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java index 096ede8..0421af9 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java @@ -46,11 +46,11 @@ public class SkinFetcher { }); completableFuture.whenComplete((response, throwable) -> { if (completableFuture.isCompletedExceptionally()) { - skinFetcherResult.onDone(null, throwable); + skinFetcherResult.onDone(null, null, throwable); } else { JsonObject jsonObject = response.getAsJsonObject(this.builder.getAPIServer().getValueKey()); JsonObject properties = jsonObject.getAsJsonObject(this.builder.getAPIServer().getSignatureKey()); - skinFetcherResult.onDone(new String[]{properties.get("value").getAsString(), properties.get("signature").getAsString()}, null); + skinFetcherResult.onDone(properties.get("value").getAsString(), properties.get("signature").getAsString(), null); } }); return completableFuture; diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java index 59db73e..ec55efa 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java @@ -1,5 +1,5 @@ package io.github.znetworkw.znpcservers.skin; public interface SkinFetcherResult { - void onDone(String[] paramArrayOfString, Throwable paramThrowable); + void onDone(String value, String signature, Throwable paramThrowable); } diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 09354c4..93d9dcb 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -6,14 +6,18 @@ import lol.pyr.znpcsplus.packets.PacketFactory; import org.bukkit.entity.Player; import java.util.Set; +import java.util.UUID; public class PacketEntity { private final int entityId; + private final UUID uuid; + private final EntityType type; private PacketLocation location; public PacketEntity(EntityType type, PacketLocation location) { this.entityId = EntityIDProvider.reserve(); + this.uuid = UUID.randomUUID(); this.type = type; this.location = location; } @@ -26,6 +30,10 @@ public class PacketEntity { return location; } + public UUID getUuid() { + return uuid; + } + public EntityType getType() { return type; } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 100279b..9283a5e 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -2,11 +2,15 @@ package lol.pyr.znpcsplus.npc; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.properties.NPCProperty; +import lol.pyr.znpcsplus.properties.NPCPropertyKey; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; public class NPC { @@ -16,6 +20,8 @@ public class NPC { private PacketLocation location; private NPCType type; + private final Map propertyMap = new HashMap<>(); + public NPC(World world, NPCType type, PacketLocation location) { this.worldName = world.getName(); this.type = type; @@ -83,4 +89,12 @@ public class NPC { public boolean isShown(Player player) { return viewers.contains(player); } + + public NPCProperty getProperty(NPCPropertyKey key) { + return propertyMap.get(key); + } + + public boolean hasProperty(NPCPropertyKey key) { + return propertyMap.containsKey(key); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index d57b4fb..3baf573 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -16,6 +16,8 @@ public interface PacketFactory { void teleportEntity(Player player, PacketEntity entity); void addTabPlayer(Player player, PacketEntity entity); void removeTabPlayer(Player player, PacketEntity entity); + void createTeam(Player player, PacketEntity entity); + void removeTeam(Player player, PacketEntity entity); PacketFactory factory = get(); @@ -35,6 +37,8 @@ public interface PacketFactory { private static Map> buildFactoryMap() { HashMap> map = new HashMap<>(); map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new)); + map.put(ServerVersion.V_1_14, LazyLoader.of(V1_14Factory::new)); + map.put(ServerVersion.V_1_19, LazyLoader.of(V1_19Factory::new)); return map; } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java new file mode 100644 index 0000000..07c8a7e --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java @@ -0,0 +1,17 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import org.bukkit.entity.Player; + +import java.util.Optional; + +public class V1_14Factory extends V1_8Factory { + @Override + public void spawnEntity(Player player, PacketEntity entity) { + PacketLocation location = entity.getLocation(); + sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), + location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java new file mode 100644 index 0000000..98aaee1 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java @@ -0,0 +1,30 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate; +import lol.pyr.znpcsplus.entity.PacketEntity; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; + +import java.util.EnumSet; + +public class V1_19Factory extends V1_14Factory { + @Override + public void addTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return; + WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( + new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), false, 1, GameMode.CREATIVE, + Component.empty(), null); + sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, + WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); + } + + @Override + public void removeTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfoRemove(entity.getUuid())); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 3a31083..26e7d4b 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -2,24 +2,32 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.GameMode; import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.*; +import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; import java.util.List; import java.util.Optional; -import java.util.UUID; public class V1_8Factory implements PacketFactory { @Override public void spawnPlayer(Player player, PacketEntity entity) { addTabPlayer(player, entity); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer()); - // TODO + createTeam(player, entity); + PacketLocation location = entity.getLocation(); + sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), + entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); + ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> removeTabPlayer(player, entity), 60); } @Override @@ -27,32 +35,62 @@ public class V1_8Factory implements PacketFactory { PacketLocation location = entity.getLocation(); EntityType type = entity.getType(); ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, type.getLegacyId(clientVersion) == -1 ? - new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), new UUID(0, 0), type, location.toVector3d(), + sendPacket(player, type.getLegacyId(clientVersion) == -1 ? + new WrapperPlayServerSpawnLivingEntity(entity.getEntityId(), entity.getUuid(), type, location.toVector3d(), location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : - new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.empty(), entity.getType(), location.toVector3d(), + new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); } @Override public void destroyEntity(Player player, PacketEntity entity) { - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); + if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, entity); } @Override public void teleportEntity(Player player, PacketEntity entity) { PacketLocation location = entity.getLocation(); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), + sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), location.toVector3d(), location.getYaw(), location.getPitch(), true)); } @Override public void addTabPlayer(Player player, PacketEntity entity) { - + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfo( + WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), + new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), GameMode.CREATIVE, 1))); } @Override public void removeTabPlayer(Player player, PacketEntity entity) { - new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, new UserProfile(gameProfile.getId(), gameProfile.getName()), null, 1)) + if (entity.getType() != EntityTypes.PLAYER) return; + sendPacket(player, new WrapperPlayServerPlayerInfo( + WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, + new UserProfile(entity.getUuid(), null), null, -1))); + } + + @Override + public void createTeam(Player player, PacketEntity entity) { + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo( + Component.empty(), + Component.empty(), + Component.empty(), + WrapperPlayServerTeams.NameTagVisibility.NEVER, + WrapperPlayServerTeams.CollisionRule.NEVER, + NamedTextColor.WHITE, + WrapperPlayServerTeams.OptionData.NONE + ))); + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, Integer.toString(entity.getEntityId()))); + } + + @Override + public void removeTeam(Player player, PacketEntity entity) { + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null)); + } + + protected void sendPacket(Player player, PacketWrapper packet) { + PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet); } } diff --git a/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java b/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java new file mode 100644 index 0000000..9f87d74 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java @@ -0,0 +1,7 @@ +package lol.pyr.znpcsplus.properties; + +public class NPCPropertyKey { + public NPCPropertyKey() {} + + public static NPCPropertyKey<> +} From ab3acf1076d14b222083959ab6dcb5962769b06a Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 20:58:14 +0100 Subject: [PATCH 08/22] properties woo --- .../znpcsplus/entity/EntityIDProvider.java | 15 ------ .../pyr/znpcsplus/entity/PacketEntity.java | 17 +++++-- .../pyr/znpcsplus/entity/PacketPlayer.java | 24 +++++++++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 51 +++++++++++++------ .../lol/pyr/znpcsplus/npc/NPCPropertyKey.java | 35 +++++++++++++ .../pyr/znpcsplus/packets/PacketFactory.java | 11 ++-- .../pyr/znpcsplus/packets/V1_19Factory.java | 9 ++-- .../pyr/znpcsplus/packets/V1_8Factory.java | 23 ++++----- .../pyr/znpcsplus/properties/NPCProperty.java | 4 -- .../znpcsplus/properties/NPCPropertyKey.java | 7 --- 10 files changed, 128 insertions(+), 68 deletions(-) delete mode 100644 src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java delete mode 100644 src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java delete mode 100644 src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java diff --git a/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java b/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java deleted file mode 100644 index dcf8b78..0000000 --- a/src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java +++ /dev/null @@ -1,15 +0,0 @@ -package lol.pyr.znpcsplus.entity; - -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.utility.Utils; - -public class EntityIDProvider { - public static int reserve() { - if (Utils.versionNewer(14)) return Reflections.ATOMIC_ENTITY_ID_FIELD.get().incrementAndGet(); - else { - int id = Reflections.ENTITY_ID_MODIFIER.get(); - Reflections.ENTITY_ID_MODIFIER.set(id + 1); - return id; - } - } -} diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 93d9dcb..a77aab9 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -2,6 +2,8 @@ package lol.pyr.znpcsplus.entity; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import io.github.znetworkw.znpcservers.reflection.Reflections; +import io.github.znetworkw.znpcservers.utility.Utils; import lol.pyr.znpcsplus.packets.PacketFactory; import org.bukkit.entity.Player; @@ -16,7 +18,8 @@ public class PacketEntity { private PacketLocation location; public PacketEntity(EntityType type, PacketLocation location) { - this.entityId = EntityIDProvider.reserve(); + if (type == EntityTypes.PLAYER) throw new RuntimeException("Wrong class used for player"); + this.entityId = reserveEntityID(); this.uuid = UUID.randomUUID(); this.type = type; this.location = location; @@ -44,11 +47,19 @@ public class PacketEntity { } public void spawn(Player player) { - if (type == EntityTypes.PLAYER) PacketFactory.get().spawnPlayer(player, this); - else PacketFactory.get().spawnEntity(player, this); + PacketFactory.get().spawnEntity(player, this); } public void despawn(Player player) { PacketFactory.get().destroyEntity(player, this); } + + private static int reserveEntityID() { + if (Utils.versionNewer(14)) return Reflections.ATOMIC_ENTITY_ID_FIELD.get().incrementAndGet(); + else { + int id = Reflections.ENTITY_ID_MODIFIER.get(); + Reflections.ENTITY_ID_MODIFIER.set(id + 1); + return id; + } + } } diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java new file mode 100644 index 0000000..373944f --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.entity; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import lol.pyr.znpcsplus.packets.PacketFactory; +import org.bukkit.entity.Player; + +public class PacketPlayer extends PacketEntity { + private final UserProfile gameProfile; + + public PacketPlayer(PacketLocation location) { + super(EntityTypes.PLAYER, location); + this.gameProfile = new UserProfile(getUuid(), Integer.toString(getEntityId())); + } + + @Override + public void spawn(Player player) { + PacketFactory.get().spawnPlayer(player, this); + } + + public UserProfile getGameProfile() { + return gameProfile; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 9283a5e..9dee875 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -1,9 +1,9 @@ package lol.pyr.znpcsplus.npc; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; -import lol.pyr.znpcsplus.properties.NPCProperty; -import lol.pyr.znpcsplus.properties.NPCPropertyKey; +import lol.pyr.znpcsplus.entity.PacketPlayer; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; @@ -20,19 +20,19 @@ public class NPC { private PacketLocation location; private NPCType type; - private final Map propertyMap = new HashMap<>(); + private final Map, Object> propertyMap = new HashMap<>(); public NPC(World world, NPCType type, PacketLocation location) { this.worldName = world.getName(); this.type = type; this.location = location; - entity = new PacketEntity(type.getType(), location); // TODO: Entity ID Provider + entity = new PacketEntity(type.getType(), location); } public void setType(NPCType type) { _hideAll(); this.type = type; - entity = new PacketEntity(type.getType(), entity.getLocation()); + entity = type.getType() == EntityTypes.PLAYER ? new PacketPlayer(entity.getLocation()) : new PacketEntity(type.getType(), entity.getLocation()); _showAll(); } @@ -40,6 +40,10 @@ public class NPC { return type; } + public PacketEntity getEntity() { + return entity; + } + public PacketLocation getLocation() { return location; } @@ -58,22 +62,31 @@ public class NPC { viewers.clear(); } + public void respawn() { + _hideAll(); + _showAll(); + } + public void show(Player player) { if (viewers.contains(player)) return; _show(player); viewers.add(player); } - private void _show(Player player) { - entity.spawn(player); - } - public void hide(Player player) { if (!viewers.contains(player)) return; _hide(player); viewers.remove(player); } + public boolean isShown(Player player) { + return viewers.contains(player); + } + + private void _show(Player player) { + entity.spawn(player); + } + private void _hide(Player player) { entity.despawn(player); } @@ -86,15 +99,21 @@ public class NPC { for (Player viewer : viewers) _show(viewer); } - public boolean isShown(Player player) { - return viewers.contains(player); + @SuppressWarnings("unchecked") + public T getProperty(NPCPropertyKey key) { + return (T) propertyMap.get(key); } - public NPCProperty getProperty(NPCPropertyKey key) { - return propertyMap.get(key); - } - - public boolean hasProperty(NPCPropertyKey key) { + public boolean hasProperty(NPCPropertyKey key) { return propertyMap.containsKey(key); } + + public void setProperty(NPCPropertyKey key, T value) { + propertyMap.put(key, value); + key.update(this, value); + } + + public void removeProperty(NPCPropertyKey key) { + propertyMap.remove(key); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java new file mode 100644 index 0000000..4cc09ca --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java @@ -0,0 +1,35 @@ +package lol.pyr.znpcsplus.npc; + +import com.github.retrooper.packetevents.protocol.player.TextureProperty; +import io.github.znetworkw.znpcservers.npc.NPCSkin; +import lol.pyr.znpcsplus.entity.PacketPlayer; + +import java.util.List; + +public class NPCPropertyKey { + private final UpdateCallback updateCallback; + + public NPCPropertyKey() { + this(null); + } + + public NPCPropertyKey(UpdateCallback updateCallback) { + this.updateCallback = updateCallback; + } + + public void update(NPC npc, T value) { + if (updateCallback != null) updateCallback.onUpdate(npc, value); + } + + @FunctionalInterface + public interface UpdateCallback { + void onUpdate(NPC npc, T value); + } + + public static NPCPropertyKey NPC_SKIN = new NPCPropertyKey<>((npc, skin) -> { + if (!(npc.getEntity() instanceof PacketPlayer entity)) + throw new RuntimeException("Tried to set a skin on an entity that isn't a player"); + entity.getGameProfile().setTextureProperties(List.of(new TextureProperty("textures", skin.getTexture(), skin.getSignature()))); + npc.respawn(); + }); +} diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 3baf573..e79702b 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketPlayer; import lol.pyr.znpcsplus.util.LazyLoader; import org.bukkit.entity.Player; @@ -10,14 +11,14 @@ import java.util.HashMap; import java.util.Map; public interface PacketFactory { - void spawnPlayer(Player player, PacketEntity entity); + void spawnPlayer(Player player, PacketPlayer entity); void spawnEntity(Player player, PacketEntity entity); void destroyEntity(Player player, PacketEntity entity); void teleportEntity(Player player, PacketEntity entity); - void addTabPlayer(Player player, PacketEntity entity); - void removeTabPlayer(Player player, PacketEntity entity); - void createTeam(Player player, PacketEntity entity); - void removeTeam(Player player, PacketEntity entity); + void addTabPlayer(Player player, PacketPlayer entity); + void removeTabPlayer(Player player, PacketPlayer entity); + void createTeam(Player player, PacketPlayer entity); + void removeTeam(Player player, PacketPlayer entity); PacketFactory factory = get(); diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java index 98aaee1..230b3bc 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java @@ -2,10 +2,9 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.GameMode; -import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate; -import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketPlayer; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @@ -13,17 +12,17 @@ import java.util.EnumSet; public class V1_19Factory extends V1_14Factory { @Override - public void addTabPlayer(Player player, PacketEntity entity) { + public void addTabPlayer(Player player, PacketPlayer entity) { if (entity.getType() != EntityTypes.PLAYER) return; WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( - new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), false, 1, GameMode.CREATIVE, + entity.getGameProfile(), false, 1, GameMode.CREATIVE, Component.empty(), null); sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); } @Override - public void removeTabPlayer(Player player, PacketEntity entity) { + public void removeTabPlayer(Player player, PacketPlayer entity) { if (entity.getType() != EntityTypes.PLAYER) return; sendPacket(player, new WrapperPlayServerPlayerInfoRemove(entity.getUuid())); } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 26e7d4b..2951d1d 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -5,13 +5,13 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.GameMode; -import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.*; import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.entity.PacketPlayer; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; @@ -21,7 +21,7 @@ import java.util.Optional; public class V1_8Factory implements PacketFactory { @Override - public void spawnPlayer(Player player, PacketEntity entity) { + public void spawnPlayer(Player player, PacketPlayer entity) { addTabPlayer(player, entity); createTeam(player, entity); PacketLocation location = entity.getLocation(); @@ -45,7 +45,7 @@ public class V1_8Factory implements PacketFactory { @Override public void destroyEntity(Player player, PacketEntity entity) { sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); - if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, entity); + if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, (PacketPlayer) entity); } @Override @@ -56,27 +56,24 @@ public class V1_8Factory implements PacketFactory { } @Override - public void addTabPlayer(Player player, PacketEntity entity) { + public void addTabPlayer(Player player, PacketPlayer entity) { if (entity.getType() != EntityTypes.PLAYER) return; sendPacket(player, new WrapperPlayServerPlayerInfo( - WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), - new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId())), GameMode.CREATIVE, 1))); + WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), entity.getGameProfile(), GameMode.CREATIVE, 1))); } @Override - public void removeTabPlayer(Player player, PacketEntity entity) { + public void removeTabPlayer(Player player, PacketPlayer entity) { if (entity.getType() != EntityTypes.PLAYER) return; sendPacket(player, new WrapperPlayServerPlayerInfo( WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, - new UserProfile(entity.getUuid(), null), null, -1))); + entity.getGameProfile(), null, -1))); } @Override - public void createTeam(Player player, PacketEntity entity) { + public void createTeam(Player player, PacketPlayer entity) { sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo( - Component.empty(), - Component.empty(), - Component.empty(), + Component.empty(), Component.empty(), Component.empty(), WrapperPlayServerTeams.NameTagVisibility.NEVER, WrapperPlayServerTeams.CollisionRule.NEVER, NamedTextColor.WHITE, @@ -86,7 +83,7 @@ public class V1_8Factory implements PacketFactory { } @Override - public void removeTeam(Player player, PacketEntity entity) { + public void removeTeam(Player player, PacketPlayer entity) { sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null)); } diff --git a/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java deleted file mode 100644 index bbf2a10..0000000 --- a/src/main/java/lol/pyr/znpcsplus/properties/NPCProperty.java +++ /dev/null @@ -1,4 +0,0 @@ -package lol.pyr.znpcsplus.properties; - -public class NPCProperty { -} diff --git a/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java b/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java deleted file mode 100644 index 9f87d74..0000000 --- a/src/main/java/lol/pyr/znpcsplus/properties/NPCPropertyKey.java +++ /dev/null @@ -1,7 +0,0 @@ -package lol.pyr.znpcsplus.properties; - -public class NPCPropertyKey { - public NPCPropertyKey() {} - - public static NPCPropertyKey<> -} From aff69dbb71fdb079d858dfcac3a4963668e09fb3 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 22:31:48 +0100 Subject: [PATCH 09/22] skin layers & metadata --- .../commands/list/DefaultCommand.java | 4 +- .../znetworkw/znpcservers/npc/NPCSkin.java | 2 +- .../znpcservers/skin/SkinFetcher.java | 5 ++- .../znpcservers/skin/SkinFetcherResult.java | 4 +- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 7 +++- .../pyr/znpcsplus/entity/PacketEntity.java | 13 ++++-- .../pyr/znpcsplus/entity/PacketPlayer.java | 24 ----------- .../znpcsplus/metadata/MetadataFactory.java | 38 ++++++++++++++++++ .../pyr/znpcsplus/metadata/V1_14Factory.java | 10 +++++ .../pyr/znpcsplus/metadata/V1_16Factory.java | 10 +++++ .../pyr/znpcsplus/metadata/V1_17Factory.java | 10 +++++ .../pyr/znpcsplus/metadata/V1_8Factory.java | 15 +++++++ .../pyr/znpcsplus/metadata/V1_9Factory.java | 10 +++++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 22 +++++----- .../lol/pyr/znpcsplus/npc/NPCProperty.java | 38 ++++++++++++++++++ .../lol/pyr/znpcsplus/npc/NPCPropertyKey.java | 35 ---------------- .../java/lol/pyr/znpcsplus/npc/NPCType.java | 11 ++++- .../pyr/znpcsplus/packets/PacketFactory.java | 13 +++--- .../pyr/znpcsplus/packets/V1_19Factory.java | 11 ++--- .../pyr/znpcsplus/packets/V1_8Factory.java | 40 ++++++++++++++----- 20 files changed, 219 insertions(+), 103 deletions(-) delete mode 100644 src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java create mode 100644 src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/metadata/V1_16Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/metadata/V1_17Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java create mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java delete mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java index 4f5bd69..6cf4600 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java @@ -39,14 +39,14 @@ public class DefaultCommand extends Command { private static final Joiner SPACE_JOINER = Joiner.on(" "); - private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (value, signature, ex) -> { + private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (npcSkin, ex) -> { if (ex != null) { Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.CANT_GET_SKIN, skin); ZNPCsPlus.LOGGER.warning("Failed to fetch skin:"); ex.printStackTrace(); return; } - npc.changeSkin(NPCSkin.forValues(value, signature)); + npc.changeSkin(npcSkin); Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.GET_SKIN); }); diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java index 94baaa9..9a51541 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java @@ -9,7 +9,7 @@ public class NPCSkin { private final String texture; private final String signature; - protected NPCSkin(String texture, String signature) { + public NPCSkin(String texture, String signature) { this.texture = texture; this.signature = signature; } diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java index 0421af9..9984a0b 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java @@ -2,6 +2,7 @@ package io.github.znetworkw.znpcservers.skin; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import io.github.znetworkw.znpcservers.npc.NPCSkin; import java.io.DataOutputStream; import java.io.InputStreamReader; @@ -46,11 +47,11 @@ public class SkinFetcher { }); completableFuture.whenComplete((response, throwable) -> { if (completableFuture.isCompletedExceptionally()) { - skinFetcherResult.onDone(null, null, throwable); + skinFetcherResult.onDone(null, throwable); } else { JsonObject jsonObject = response.getAsJsonObject(this.builder.getAPIServer().getValueKey()); JsonObject properties = jsonObject.getAsJsonObject(this.builder.getAPIServer().getSignatureKey()); - skinFetcherResult.onDone(properties.get("value").getAsString(), properties.get("signature").getAsString(), null); + skinFetcherResult.onDone(new NPCSkin(properties.get("value").getAsString(), properties.get("signature").getAsString()), null); } }); return completableFuture; diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java index ec55efa..f1c54d6 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java +++ b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java @@ -1,5 +1,7 @@ package io.github.znetworkw.znpcservers.skin; +import io.github.znetworkw.znpcservers.npc.NPCSkin; + public interface SkinFetcherResult { - void onDone(String value, String signature, Throwable paramThrowable); + void onDone(NPCSkin npcSkin, Throwable paramThrowable); } diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 2c39893..43764f4 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -2,6 +2,7 @@ package lol.pyr.znpcsplus; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; @@ -11,6 +12,7 @@ import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.listeners.PlayerListener; import io.github.znetworkw.znpcservers.npc.NPCPath; +import io.github.znetworkw.znpcservers.npc.NPCSkin; import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener; import io.github.znetworkw.znpcservers.npc.task.NPCPositionTask; import io.github.znetworkw.znpcservers.npc.task.NPCSaveTask; @@ -21,6 +23,7 @@ import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; import io.github.znetworkw.znpcservers.utility.location.ZLocation; import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCProperty; import lol.pyr.znpcsplus.npc.NPCRegistry; import lol.pyr.znpcsplus.npc.NPCType; import lol.pyr.znpcsplus.tasks.NPCVisibilityTask; @@ -135,7 +138,9 @@ public class ZNPCsPlus extends JavaPlugin { World world = Bukkit.getWorld("world"); if (world == null) world = Bukkit.getWorlds().get(0); for (NPCType type : NPCType.values()) { - NPCRegistry.register("debug_npc" + (z * wrap + x), new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0))); + NPC npc = new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0)); + if (type.getType() == EntityTypes.PLAYER) NPCSkin.forName("Pyrbu", (skin, ex) -> npc.setProperty(NPCProperty.SKIN, skin)); + NPCRegistry.register("debug_npc" + (z * wrap + x), npc); if (x++ > wrap) { x = 0; z++; diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index a77aab9..bfe8075 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -4,6 +4,7 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import io.github.znetworkw.znpcservers.reflection.Reflections; import io.github.znetworkw.znpcservers.utility.Utils; +import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.packets.PacketFactory; import org.bukkit.entity.Player; @@ -11,14 +12,15 @@ import java.util.Set; import java.util.UUID; public class PacketEntity { + private final NPC owner; private final int entityId; private final UUID uuid; private final EntityType type; private PacketLocation location; - public PacketEntity(EntityType type, PacketLocation location) { - if (type == EntityTypes.PLAYER) throw new RuntimeException("Wrong class used for player"); + public PacketEntity(NPC owner, EntityType type, PacketLocation location) { + this.owner = owner; this.entityId = reserveEntityID(); this.uuid = UUID.randomUUID(); this.type = type; @@ -41,13 +43,18 @@ public class PacketEntity { return type; } + public NPC getOwner() { + return owner; + } + public void setLocation(PacketLocation location, Set viewers) { this.location = location; for (Player viewer : viewers) PacketFactory.get().teleportEntity(viewer, this); } public void spawn(Player player) { - PacketFactory.get().spawnEntity(player, this); + if (type == EntityTypes.PLAYER) PacketFactory.get().spawnPlayer(player, this); + else PacketFactory.get().spawnEntity(player, this); } public void despawn(Player player) { diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java deleted file mode 100644 index 373944f..0000000 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketPlayer.java +++ /dev/null @@ -1,24 +0,0 @@ -package lol.pyr.znpcsplus.entity; - -import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import com.github.retrooper.packetevents.protocol.player.UserProfile; -import lol.pyr.znpcsplus.packets.PacketFactory; -import org.bukkit.entity.Player; - -public class PacketPlayer extends PacketEntity { - private final UserProfile gameProfile; - - public PacketPlayer(PacketLocation location) { - super(EntityTypes.PLAYER, location); - this.gameProfile = new UserProfile(getUuid(), Integer.toString(getEntityId())); - } - - @Override - public void spawn(Player player) { - PacketFactory.get().spawnPlayer(player, this); - } - - public UserProfile getGameProfile() { - return gameProfile; - } -} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java new file mode 100644 index 0000000..7800961 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java @@ -0,0 +1,38 @@ +package lol.pyr.znpcsplus.metadata; + +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import lol.pyr.znpcsplus.util.LazyLoader; + +import java.util.HashMap; +import java.util.Map; + +public interface MetadataFactory { + EntityData skinLayers(); + + MetadataFactory factory = get(); + + static MetadataFactory get() { + if (factory != null) return factory; + ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); + Map> factories = buildFactoryMap(); + if (factories.containsKey(version)) return factories.get(version).get(); + for (ServerVersion v : ServerVersion.reversedValues()) { + if (v.isNewerThan(version)) continue; + if (!factories.containsKey(v)) continue; + return factories.get(v).get(); + } + throw new RuntimeException("Unsupported version!"); + } + + private static Map> buildFactoryMap() { + HashMap> map = new HashMap<>(); + 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_14, LazyLoader.of(V1_14Factory::new)); + map.put(ServerVersion.V_1_16, LazyLoader.of(V1_16Factory::new)); + map.put(ServerVersion.V_1_17, LazyLoader.of(V1_17Factory::new)); + return map; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java new file mode 100644 index 0000000..af0efe8 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java @@ -0,0 +1,10 @@ +package lol.pyr.znpcsplus.metadata; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; + +public class V1_14Factory extends V1_9Factory { + @Override + public EntityData skinLayers() { + return createSkinLayers(15); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_16Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_16Factory.java new file mode 100644 index 0000000..da7c8d7 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_16Factory.java @@ -0,0 +1,10 @@ +package lol.pyr.znpcsplus.metadata; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; + +public class V1_16Factory extends V1_14Factory { + @Override + public EntityData skinLayers() { + return createSkinLayers(16); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_17Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_17Factory.java new file mode 100644 index 0000000..b83b796 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_17Factory.java @@ -0,0 +1,10 @@ +package lol.pyr.znpcsplus.metadata; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; + +public class V1_17Factory extends V1_16Factory { + @Override + public EntityData skinLayers() { + return createSkinLayers(17); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java new file mode 100644 index 0000000..c368fc5 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java @@ -0,0 +1,15 @@ +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_8Factory implements MetadataFactory { + @Override + public EntityData skinLayers() { + return createSkinLayers(12); + } + + protected EntityData createSkinLayers(int index) { + return new EntityData(index, EntityDataTypes.BYTE, Byte.MAX_VALUE); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java new file mode 100644 index 0000000..0d5bd78 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java @@ -0,0 +1,10 @@ +package lol.pyr.znpcsplus.metadata; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; + +public class V1_9Factory extends V1_8Factory { + @Override + public EntityData skinLayers() { + return createSkinLayers(13); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 9dee875..0be9acc 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -1,9 +1,7 @@ package lol.pyr.znpcsplus.npc; -import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; -import lol.pyr.znpcsplus.entity.PacketPlayer; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; @@ -20,19 +18,19 @@ public class NPC { private PacketLocation location; private NPCType type; - private final Map, Object> propertyMap = new HashMap<>(); + private final Map, Object> propertyMap = new HashMap<>(); public NPC(World world, NPCType type, PacketLocation location) { this.worldName = world.getName(); this.type = type; this.location = location; - entity = new PacketEntity(type.getType(), location); + entity = new PacketEntity(this, type.getType(), location); } public void setType(NPCType type) { _hideAll(); this.type = type; - entity = type.getType() == EntityTypes.PLAYER ? new PacketPlayer(entity.getLocation()) : new PacketEntity(type.getType(), entity.getLocation()); + entity = new PacketEntity(this, type.getType(), entity.getLocation()); _showAll(); } @@ -100,20 +98,20 @@ public class NPC { } @SuppressWarnings("unchecked") - public T getProperty(NPCPropertyKey key) { - return (T) propertyMap.get(key); + public T getProperty(NPCProperty key) { + return hasProperty(key) ? (T) propertyMap.get(key) : key.getDefaultValue(); } - public boolean hasProperty(NPCPropertyKey key) { + public boolean hasProperty(NPCProperty key) { return propertyMap.containsKey(key); } - public void setProperty(NPCPropertyKey key, T value) { - propertyMap.put(key, value); - key.update(this, value); + public void setProperty(NPCProperty key, T value) { + if (value.equals(key.getDefaultValue())) removeProperty(key); + else propertyMap.put(key, value); } - public void removeProperty(NPCPropertyKey key) { + public void removeProperty(NPCProperty key) { propertyMap.remove(key); } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java new file mode 100644 index 0000000..2752ed2 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java @@ -0,0 +1,38 @@ +package lol.pyr.znpcsplus.npc; + +import io.github.znetworkw.znpcservers.npc.NPCSkin; + +import java.util.HashMap; +import java.util.Map; + +public class NPCProperty { + private final String name; + private final T defaultValue; + + public NPCProperty(String name) { + this(name, null); + } + + public NPCProperty(String name, T defaultValue) { + this.name = name.toUpperCase(); + this.defaultValue = defaultValue; + BY_NAME.put(this.name, this); + } + + public String getName() { + return name; + } + + protected T getDefaultValue() { + return defaultValue; + } + + private final static Map> BY_NAME = new HashMap<>(); + + public static NPCProperty getByName(String name) { + return BY_NAME.get(name.toUpperCase()); + } + + public static NPCProperty SKIN_LAYERS = new NPCProperty<>("skin_layers", true); + public static NPCProperty SKIN = new NPCProperty<>("skin"); +} \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java deleted file mode 100644 index 4cc09ca..0000000 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCPropertyKey.java +++ /dev/null @@ -1,35 +0,0 @@ -package lol.pyr.znpcsplus.npc; - -import com.github.retrooper.packetevents.protocol.player.TextureProperty; -import io.github.znetworkw.znpcservers.npc.NPCSkin; -import lol.pyr.znpcsplus.entity.PacketPlayer; - -import java.util.List; - -public class NPCPropertyKey { - private final UpdateCallback updateCallback; - - public NPCPropertyKey() { - this(null); - } - - public NPCPropertyKey(UpdateCallback updateCallback) { - this.updateCallback = updateCallback; - } - - public void update(NPC npc, T value) { - if (updateCallback != null) updateCallback.onUpdate(npc, value); - } - - @FunctionalInterface - public interface UpdateCallback { - void onUpdate(NPC npc, T value); - } - - public static NPCPropertyKey NPC_SKIN = new NPCPropertyKey<>((npc, skin) -> { - if (!(npc.getEntity() instanceof PacketPlayer entity)) - throw new RuntimeException("Tried to set a skin on an entity that isn't a player"); - entity.getGameProfile().setTextureProperties(List.of(new TextureProperty("textures", skin.getTexture(), skin.getSignature()))); - npc.respawn(); - }); -} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 6773df1..3d81460 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -5,6 +5,7 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.google.common.collect.ImmutableList; import java.util.List; +import java.util.Set; public class NPCType { private final static ImmutableList npcTypes; @@ -14,19 +15,25 @@ public class NPCType { } private final EntityType type; + private final Set> allowedProperties; - public NPCType(EntityType type) { + public NPCType(EntityType type, NPCProperty... allowedProperties) { this.type = type; + this.allowedProperties = Set.of(allowedProperties); } public EntityType getType() { return type; } + public Set> getAllowedProperties() { + return allowedProperties; + } + static { ImmutableList.Builder builder = new ImmutableList.Builder<>(); - builder.add(new NPCType(EntityTypes.PLAYER)); + builder.add(new NPCType(EntityTypes.PLAYER, NPCProperty.SKIN)); builder.add(new NPCType(EntityTypes.CREEPER)); builder.add(new NPCType(EntityTypes.ZOMBIE)); builder.add(new NPCType(EntityTypes.SKELETON)); diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index e79702b..2005987 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -2,8 +2,8 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import lol.pyr.znpcsplus.entity.PacketEntity; -import lol.pyr.znpcsplus.entity.PacketPlayer; import lol.pyr.znpcsplus.util.LazyLoader; import org.bukkit.entity.Player; @@ -11,14 +11,15 @@ import java.util.HashMap; import java.util.Map; public interface PacketFactory { - void spawnPlayer(Player player, PacketPlayer entity); + void spawnPlayer(Player player, PacketEntity entity); void spawnEntity(Player player, PacketEntity entity); void destroyEntity(Player player, PacketEntity entity); void teleportEntity(Player player, PacketEntity entity); - void addTabPlayer(Player player, PacketPlayer entity); - void removeTabPlayer(Player player, PacketPlayer entity); - void createTeam(Player player, PacketPlayer entity); - void removeTeam(Player player, PacketPlayer entity); + void addTabPlayer(Player player, PacketEntity entity); + void removeTabPlayer(Player player, PacketEntity entity); + void createTeam(Player player, PacketEntity entity); + void removeTeam(Player player, PacketEntity entity); + void sendMetadata(Player player, PacketEntity entity, EntityData... data); PacketFactory factory = get(); diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java index 230b3bc..3cd2a13 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java @@ -2,9 +2,10 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate; -import lol.pyr.znpcsplus.entity.PacketPlayer; +import lol.pyr.znpcsplus.entity.PacketEntity; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @@ -12,17 +13,17 @@ import java.util.EnumSet; public class V1_19Factory extends V1_14Factory { @Override - public void addTabPlayer(Player player, PacketPlayer entity) { + public void addTabPlayer(Player player, PacketEntity entity) { if (entity.getType() != EntityTypes.PLAYER) return; WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( - entity.getGameProfile(), false, 1, GameMode.CREATIVE, - Component.empty(), null); + skinned(entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))), false, + 1, GameMode.CREATIVE, Component.empty(), null); sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); } @Override - public void removeTabPlayer(Player player, PacketPlayer entity) { + public void removeTabPlayer(Player player, PacketEntity entity) { if (entity.getType() != EntityTypes.PLAYER) return; sendPacket(player, new WrapperPlayServerPlayerInfoRemove(entity.getUuid())); } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 2951d1d..2a55199 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -1,17 +1,23 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.protocol.player.TextureProperty; +import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.*; +import io.github.znetworkw.znpcservers.npc.NPCSkin; import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; -import lol.pyr.znpcsplus.entity.PacketPlayer; +import lol.pyr.znpcsplus.metadata.MetadataFactory; +import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCProperty; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; @@ -21,12 +27,14 @@ import java.util.Optional; public class V1_8Factory implements PacketFactory { @Override - public void spawnPlayer(Player player, PacketPlayer entity) { + public void spawnPlayer(Player player, PacketEntity entity) { + NPC owner = entity.getOwner(); addTabPlayer(player, entity); createTeam(player, entity); PacketLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); + if (owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> removeTabPlayer(player, entity), 60); } @@ -45,7 +53,7 @@ public class V1_8Factory implements PacketFactory { @Override public void destroyEntity(Player player, PacketEntity entity) { sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); - if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, (PacketPlayer) entity); + if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, entity); } @Override @@ -56,22 +64,23 @@ public class V1_8Factory implements PacketFactory { } @Override - public void addTabPlayer(Player player, PacketPlayer entity) { + public void addTabPlayer(Player player, PacketEntity entity) { if (entity.getType() != EntityTypes.PLAYER) return; sendPacket(player, new WrapperPlayServerPlayerInfo( - WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), entity.getGameProfile(), GameMode.CREATIVE, 1))); + WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), + skinned(entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))), GameMode.CREATIVE, 1))); } @Override - public void removeTabPlayer(Player player, PacketPlayer entity) { + public void removeTabPlayer(Player player, PacketEntity entity) { if (entity.getType() != EntityTypes.PLAYER) return; sendPacket(player, new WrapperPlayServerPlayerInfo( WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, - entity.getGameProfile(), null, -1))); + new UserProfile(entity.getUuid(), null), null, -1))); } @Override - public void createTeam(Player player, PacketPlayer entity) { + public void createTeam(Player player, PacketEntity entity) { sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo( Component.empty(), Component.empty(), Component.empty(), WrapperPlayServerTeams.NameTagVisibility.NEVER, @@ -83,11 +92,24 @@ public class V1_8Factory implements PacketFactory { } @Override - public void removeTeam(Player player, PacketPlayer entity) { + public void removeTeam(Player player, PacketEntity entity) { sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null)); } + @Override + public void sendMetadata(Player player, PacketEntity entity, EntityData... data) { + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), List.of(data))); + } + protected void sendPacket(Player player, PacketWrapper packet) { PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet); } + + protected UserProfile skinned(PacketEntity entity, UserProfile profile) { + NPC owner = entity.getOwner(); + if (!owner.hasProperty(NPCProperty.SKIN)) return profile; + NPCSkin skin = owner.getProperty(NPCProperty.SKIN); + profile.setTextureProperties(List.of(new TextureProperty("textures", skin.getTexture(), skin.getSignature()))); + return profile; + } } From 7ee4be80091869d97aca3928781663f572155209 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 23:09:54 +0100 Subject: [PATCH 10/22] add fire & glow property and links for wikis --- src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java | 7 ++++++- .../pyr/znpcsplus/metadata/MetadataFactory.java | 15 +++++++++++++++ .../lol/pyr/znpcsplus/metadata/V1_8Factory.java | 5 +++++ .../java/lol/pyr/znpcsplus/npc/NPCProperty.java | 3 +++ .../lol/pyr/znpcsplus/packets/V1_8Factory.java | 6 +++++- 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 43764f4..82abea0 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -30,6 +30,7 @@ import lol.pyr.znpcsplus.tasks.NPCVisibilityTask; import lol.pyr.znpcsplus.updater.UpdateChecker; import lol.pyr.znpcsplus.updater.UpdateNotificationListener; import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.format.NamedTextColor; import org.apache.commons.io.FileUtils; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; @@ -139,7 +140,11 @@ public class ZNPCsPlus extends JavaPlugin { if (world == null) world = Bukkit.getWorlds().get(0); for (NPCType type : NPCType.values()) { NPC npc = new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0)); - if (type.getType() == EntityTypes.PLAYER) NPCSkin.forName("Pyrbu", (skin, ex) -> npc.setProperty(NPCProperty.SKIN, skin)); + if (type.getType() == EntityTypes.PLAYER) { + npc.setProperty(NPCProperty.GLOW, NamedTextColor.RED); + npc.setProperty(NPCProperty.FIRE, true); + NPCSkin.forName("Notch", (skin, ex) -> npc.setProperty(NPCProperty.SKIN, skin)); + } NPCRegistry.register("debug_npc" + (z * wrap + x), npc); if (x++ > wrap) { x = 0; diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java index 7800961..621fcd2 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java @@ -8,8 +8,23 @@ import lol.pyr.znpcsplus.util.LazyLoader; import java.util.HashMap; import java.util.Map; +/** + * 1.8 https://wiki.vg/index.php?title=Entity_metadata&oldid=7415 + * 1.9 https://wiki.vg/index.php?title=Entity_metadata&oldid=7968 + * 1.10 https://wiki.vg/index.php?title=Entity_metadata&oldid=8241 + * 1.11 https://wiki.vg/index.php?title=Entity_metadata&oldid=8534 + * 1.12 https://wiki.vg/index.php?title=Entity_metadata&oldid=14048 + * 1.13 https://wiki.vg/index.php?title=Entity_metadata&oldid=14800 + * 1.14 https://wiki.vg/index.php?title=Entity_metadata&oldid=15240 + * 1.15 https://wiki.vg/index.php?title=Entity_metadata&oldid=15991 + * 1.16 https://wiki.vg/index.php?title=Entity_metadata&oldid=16539 + * 1.17 https://wiki.vg/index.php?title=Entity_metadata&oldid=17521 + * 1.18 NOTHING CHANGED + * 1.19 https://wiki.vg/index.php?title=Entity_metadata + */ public interface MetadataFactory { EntityData skinLayers(); + EntityData effects(boolean onFire, boolean glowing); MetadataFactory factory = get(); diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java index c368fc5..b422bf5 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java @@ -9,6 +9,11 @@ public class V1_8Factory implements MetadataFactory { return createSkinLayers(12); } + @Override + public EntityData effects(boolean onFire, boolean glowing) { + return new EntityData(0, EntityDataTypes.BYTE, (byte) ((onFire ? 0x01 : 0) | (glowing ? 0x40 : 0))); + } + protected EntityData createSkinLayers(int index) { return new EntityData(index, EntityDataTypes.BYTE, Byte.MAX_VALUE); } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java index 2752ed2..ef98ffd 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java @@ -1,6 +1,7 @@ package lol.pyr.znpcsplus.npc; import io.github.znetworkw.znpcservers.npc.NPCSkin; +import net.kyori.adventure.text.format.NamedTextColor; import java.util.HashMap; import java.util.Map; @@ -35,4 +36,6 @@ public class NPCProperty { public static NPCProperty SKIN_LAYERS = new NPCProperty<>("skin_layers", true); public static NPCProperty SKIN = new NPCProperty<>("skin"); + public static NPCProperty GLOW = new NPCProperty<>("glow"); + public static NPCProperty FIRE = new NPCProperty<>("fire", false); } \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 2a55199..b00c0a4 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -35,6 +35,9 @@ public class V1_8Factory implements PacketFactory { sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); if (owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); + boolean glow = owner.hasProperty(NPCProperty.GLOW); + boolean fire = owner.getProperty(NPCProperty.FIRE); + if (glow || fire) sendMetadata(player, entity, MetadataFactory.get().effects(fire, glow)); ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> removeTabPlayer(player, entity), 60); } @@ -81,11 +84,12 @@ public class V1_8Factory implements PacketFactory { @Override public void createTeam(Player player, PacketEntity entity) { + NPC owner = entity.getOwner(); sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo( Component.empty(), Component.empty(), Component.empty(), WrapperPlayServerTeams.NameTagVisibility.NEVER, WrapperPlayServerTeams.CollisionRule.NEVER, - NamedTextColor.WHITE, + owner.hasProperty(NPCProperty.GLOW) ? owner.getProperty(NPCProperty.GLOW) : NamedTextColor.WHITE, WrapperPlayServerTeams.OptionData.NONE ))); sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, Integer.toString(entity.getEntityId()))); From 7fade89b8d9733dac5d16746063de3658c1d7da6 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 23:58:12 +0100 Subject: [PATCH 11/22] make glow work for all entities + better 1.8 support --- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 4 +-- .../pyr/znpcsplus/metadata/V1_8Factory.java | 2 +- .../pyr/znpcsplus/metadata/V1_9Factory.java | 6 ++++ .../lol/pyr/znpcsplus/npc/NPCProperty.java | 2 +- .../java/lol/pyr/znpcsplus/npc/NPCType.java | 8 ++--- .../pyr/znpcsplus/packets/PacketFactory.java | 2 ++ .../pyr/znpcsplus/packets/V1_14Factory.java | 5 ++- .../pyr/znpcsplus/packets/V1_8Factory.java | 17 ++++++---- .../pyr/znpcsplus/packets/V1_9Factory.java | 31 +++++++++++++++++++ 9 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 82abea0..8ef9a4d 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -141,10 +141,10 @@ public class ZNPCsPlus extends JavaPlugin { for (NPCType type : NPCType.values()) { NPC npc = new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0)); if (type.getType() == EntityTypes.PLAYER) { - npc.setProperty(NPCProperty.GLOW, NamedTextColor.RED); - npc.setProperty(NPCProperty.FIRE, true); NPCSkin.forName("Notch", (skin, ex) -> npc.setProperty(NPCProperty.SKIN, skin)); } + npc.setProperty(NPCProperty.GLOW, NamedTextColor.RED); + npc.setProperty(NPCProperty.FIRE, true); NPCRegistry.register("debug_npc" + (z * wrap + x), npc); if (x++ > wrap) { x = 0; diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java index b422bf5..b36b7fa 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java @@ -11,7 +11,7 @@ public class V1_8Factory implements MetadataFactory { @Override public EntityData effects(boolean onFire, boolean glowing) { - return new EntityData(0, EntityDataTypes.BYTE, (byte) ((onFire ? 0x01 : 0) | (glowing ? 0x40 : 0))); + return new EntityData(0, EntityDataTypes.BYTE, onFire ? 0x01 : 0); } protected EntityData createSkinLayers(int index) { diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java index 0d5bd78..1a8a9c5 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java @@ -1,10 +1,16 @@ 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_9Factory extends V1_8Factory { @Override public EntityData skinLayers() { return createSkinLayers(13); } + + @Override + public EntityData effects(boolean onFire, boolean glowing) { + return new EntityData(0, EntityDataTypes.BYTE, (byte) ((onFire ? 0x01 : 0) | (glowing ? 0x40 : 0))); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java index ef98ffd..9496537 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java @@ -20,7 +20,7 @@ public class NPCProperty { BY_NAME.put(this.name, this); } - public String getName() { + public String name() { return name; } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 3d81460..db8a12a 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -33,10 +33,10 @@ public class NPCType { static { ImmutableList.Builder builder = new ImmutableList.Builder<>(); - builder.add(new NPCType(EntityTypes.PLAYER, NPCProperty.SKIN)); - builder.add(new NPCType(EntityTypes.CREEPER)); - builder.add(new NPCType(EntityTypes.ZOMBIE)); - builder.add(new NPCType(EntityTypes.SKELETON)); + builder.add(new NPCType(EntityTypes.PLAYER, NPCProperty.GLOW, NPCProperty.FIRE, NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); + builder.add(new NPCType(EntityTypes.CREEPER, NPCProperty.GLOW, NPCProperty.FIRE)); + builder.add(new NPCType(EntityTypes.ZOMBIE, NPCProperty.GLOW, NPCProperty.FIRE)); + builder.add(new NPCType(EntityTypes.SKELETON, NPCProperty.GLOW, NPCProperty.FIRE)); npcTypes = builder.build(); } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 2005987..6c5f9f9 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -19,6 +19,7 @@ public interface PacketFactory { void removeTabPlayer(Player player, PacketEntity entity); void createTeam(Player player, PacketEntity entity); void removeTeam(Player player, PacketEntity entity); + void sendAllMetadata(Player player, PacketEntity entity); void sendMetadata(Player player, PacketEntity entity, EntityData... data); PacketFactory factory = get(); @@ -39,6 +40,7 @@ public interface PacketFactory { private static Map> buildFactoryMap() { HashMap> map = new HashMap<>(); 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_14, LazyLoader.of(V1_14Factory::new)); map.put(ServerVersion.V_1_19, LazyLoader.of(V1_19Factory::new)); return map; diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java index 07c8a7e..560f948 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java @@ -3,15 +3,18 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.npc.NPCProperty; import org.bukkit.entity.Player; import java.util.Optional; -public class V1_14Factory extends V1_8Factory { +public class V1_14Factory extends V1_9Factory { @Override public void spawnEntity(Player player, PacketEntity entity) { PacketLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); + if (entity.getOwner().hasProperty(NPCProperty.GLOW)) createTeam(player, entity); + sendAllMetadata(player, entity); } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index b00c0a4..5c8be45 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -28,16 +28,12 @@ import java.util.Optional; public class V1_8Factory implements PacketFactory { @Override public void spawnPlayer(Player player, PacketEntity entity) { - NPC owner = entity.getOwner(); addTabPlayer(player, entity); createTeam(player, entity); PacketLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); - if (owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); - boolean glow = owner.hasProperty(NPCProperty.GLOW); - boolean fire = owner.getProperty(NPCProperty.FIRE); - if (glow || fire) sendMetadata(player, entity, MetadataFactory.get().effects(fire, glow)); + sendAllMetadata(player, entity); ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> removeTabPlayer(player, entity), 60); } @@ -51,6 +47,7 @@ public class V1_8Factory implements PacketFactory { location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); + sendAllMetadata(player, entity); } @Override @@ -92,7 +89,8 @@ public class V1_8Factory implements PacketFactory { owner.hasProperty(NPCProperty.GLOW) ? owner.getProperty(NPCProperty.GLOW) : NamedTextColor.WHITE, WrapperPlayServerTeams.OptionData.NONE ))); - sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, Integer.toString(entity.getEntityId()))); + sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, + entity.getType() == EntityTypes.PLAYER ? Integer.toString(entity.getEntityId()) : entity.getUuid().toString())); } @Override @@ -100,6 +98,13 @@ public class V1_8Factory implements PacketFactory { sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null)); } + @Override + public void sendAllMetadata(Player player, PacketEntity entity) { + NPC owner = entity.getOwner(); + if (entity.getType() == EntityTypes.PLAYER && owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); + if (owner.getProperty(NPCProperty.FIRE)) sendMetadata(player, entity, MetadataFactory.get().effects(true, false)); + } + @Override public void sendMetadata(Player player, PacketEntity entity, EntityData... data) { PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), List.of(data))); diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java new file mode 100644 index 0000000..dac06ed --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java @@ -0,0 +1,31 @@ +package lol.pyr.znpcsplus.packets; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.metadata.MetadataFactory; +import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCProperty; +import org.bukkit.entity.Player; + +public class V1_9Factory extends V1_8Factory { + @Override + public void sendAllMetadata(Player player, PacketEntity entity) { + NPC owner = entity.getOwner(); + if (entity.getType() == EntityTypes.PLAYER && owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); + boolean glow = owner.hasProperty(NPCProperty.GLOW); + boolean fire = owner.getProperty(NPCProperty.FIRE); + if (glow || fire) sendMetadata(player, entity, MetadataFactory.get().effects(fire, glow)); + } + + @Override + public void spawnEntity(Player player, PacketEntity entity) { + super.spawnEntity(player, entity); + if (entity.getOwner().hasProperty(NPCProperty.GLOW)) createTeam(player, entity); + } + + @Override + public void destroyEntity(Player player, PacketEntity entity) { + super.destroyEntity(player, entity); + if (entity.getType() != EntityTypes.PLAYER && entity.getOwner().hasProperty(NPCProperty.GLOW)) removeTeam(player, entity); + } +} From 85d2b852f9a759577aae85ca3c6795d988508f52 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 25 Apr 2023 00:08:13 +0100 Subject: [PATCH 12/22] better property definitions --- .../java/lol/pyr/znpcsplus/npc/NPCType.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index db8a12a..f29463c 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -1,16 +1,19 @@ package lol.pyr.znpcsplus.npc; +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; public class NPCType { - private final static ImmutableList npcTypes; + private final static Set npcTypes; - public static List values() { + public static Set values() { return npcTypes; } @@ -19,7 +22,10 @@ public class NPCType { public NPCType(EntityType type, NPCProperty... allowedProperties) { this.type = type; - this.allowedProperties = Set.of(allowedProperties); + ArrayList> list = new ArrayList<>(List.of(allowedProperties)); + list.add(NPCProperty.FIRE); + if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) list.add(NPCProperty.GLOW); + this.allowedProperties = Set.copyOf(list); } public EntityType getType() { @@ -31,13 +37,11 @@ public class NPCType { } static { - ImmutableList.Builder builder = new ImmutableList.Builder<>(); - - builder.add(new NPCType(EntityTypes.PLAYER, NPCProperty.GLOW, NPCProperty.FIRE, NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); - builder.add(new NPCType(EntityTypes.CREEPER, NPCProperty.GLOW, NPCProperty.FIRE)); - builder.add(new NPCType(EntityTypes.ZOMBIE, NPCProperty.GLOW, NPCProperty.FIRE)); - builder.add(new NPCType(EntityTypes.SKELETON, NPCProperty.GLOW, NPCProperty.FIRE)); - - npcTypes = builder.build(); + Set set = new HashSet<>(); + set.add(new NPCType(EntityTypes.PLAYER, NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); + set.add(new NPCType(EntityTypes.CREEPER)); + set.add(new NPCType(EntityTypes.ZOMBIE)); + set.add(new NPCType(EntityTypes.SKELETON)); + npcTypes = Set.copyOf(set); } } From 8c0d6f07fa44958e4b43309a4fe4bcb877b5d30e Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 25 Apr 2023 16:52:23 +0100 Subject: [PATCH 13/22] rewrite skins & add support for placeholders skins --- .../github/znetworkw/znpcservers/npc/NPC.java | 4 +- .../InteractionPacketListener.java | 2 +- .../znpcservers/user/EventService.java | 2 +- .../znpcservers/utility/SchedulerUtils.java | 8 +- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 24 +++- src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 5 + .../lol/pyr/znpcsplus/npc/NPCProperty.java | 4 +- .../java/lol/pyr/znpcsplus/npc/NPCType.java | 38 +++-- .../pyr/znpcsplus/packets/PacketFactory.java | 3 +- .../pyr/znpcsplus/packets/V1_19Factory.java | 19 ++- .../pyr/znpcsplus/packets/V1_8Factory.java | 52 ++++--- .../java/lol/pyr/znpcsplus/skin/Skin.java | 45 ++++++ .../pyr/znpcsplus/skin/SkinDescriptor.java | 11 ++ .../pyr/znpcsplus/skin/cache/CachedId.java | 18 +++ .../pyr/znpcsplus/skin/cache/SkinCache.java | 131 ++++++++++++++++++ .../skin/cache/SkinCacheCleanTask.java | 15 ++ .../skin/descriptor/FetchingDescriptor.java | 38 +++++ .../skin/descriptor/MirrorDescriptor.java | 28 ++++ .../skin/descriptor/PrefetchedDescriptor.java | 30 ++++ 19 files changed, 422 insertions(+), 55 deletions(-) create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/Skin.java create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptor.java create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/cache/CachedId.java create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCache.java create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCacheCleanTask.java create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/descriptor/FetchingDescriptor.java create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/descriptor/MirrorDescriptor.java create mode 100644 src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java index 0587a1c..1148672 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java @@ -234,7 +234,7 @@ public class NPC { if (npcIsPlayer) { if (FunctionFactory.isTrue(this, "mirror")) updateProfile(user.getGameProfile().getProperties()); Utils.sendPackets(user, this.tabConstructor, this.updateTabConstructor); - ZNPCsPlus.SCHEDULER.runTask(() -> { + ZNPCsPlus.SCHEDULER.runNextTick(() -> { PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer(entityID, this.gameProfile.getId(), SpigotConversionUtil.fromBukkitLocation(location.toBukkitLocation()))); PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entityID, @@ -257,7 +257,7 @@ public class NPC { updateMetadata(Collections.singleton(user)); sendEquipPackets(user); lookAt(user, getLocation(), true); - if (npcIsPlayer) ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> { + if (npcIsPlayer) ZNPCsPlus.SCHEDULER.runTaskLaterSync(() -> { removeFromTab(player); Utils.sendPackets(user, this.updateTabConstructor); }, 60); diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/InteractionPacketListener.java b/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/InteractionPacketListener.java index 97c232b..dd97b22 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/InteractionPacketListener.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/InteractionPacketListener.java @@ -30,7 +30,7 @@ public class InteractionPacketListener implements PacketListener { ClickType clickType = ClickType.forName(packet.getAction().name()); user.updateLastInteract(); - ZNPCsPlus.SCHEDULER.runTask(() -> { + ZNPCsPlus.SCHEDULER.runNextTick(() -> { Bukkit.getServer().getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); List actions = npc.getNpcPojo().getClickActions(); if (actions == null) return; diff --git a/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java b/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java index 7c8d898..5674204 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java +++ b/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java @@ -31,7 +31,7 @@ public class EventService { } public void runAll(T event) { - ZNPCsPlus.SCHEDULER.runTask(() -> this.eventConsumers.forEach(consumer -> consumer.accept(event))); + ZNPCsPlus.SCHEDULER.runNextTick(() -> this.eventConsumers.forEach(consumer -> consumer.accept(event))); } public static EventService addService(ZUser user, Class eventClass) { diff --git a/src/main/java/io/github/znetworkw/znpcservers/utility/SchedulerUtils.java b/src/main/java/io/github/znetworkw/znpcservers/utility/SchedulerUtils.java index b43c832..394b89e 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/utility/SchedulerUtils.java +++ b/src/main/java/io/github/znetworkw/znpcservers/utility/SchedulerUtils.java @@ -24,11 +24,15 @@ public class SchedulerUtils { return Bukkit.getScheduler().runTaskTimerAsynchronously(this.plugin, runnable, delay, continuousDelay); } - public void scheduleSyncDelayedTask(Runnable runnable, int delay) { + public void runTaskLaterSync(Runnable runnable, int delay) { Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, runnable, delay); } - public BukkitTask runTask(Runnable runnable) { + public BukkitTask runNextTick(Runnable runnable) { return Bukkit.getScheduler().runTask(this.plugin, runnable); } + + public void runAsync(Runnable runnable) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 8ef9a4d..63e5ee5 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -12,10 +12,7 @@ import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.listeners.PlayerListener; import io.github.znetworkw.znpcservers.npc.NPCPath; -import io.github.znetworkw.znpcservers.npc.NPCSkin; import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener; -import io.github.znetworkw.znpcservers.npc.task.NPCPositionTask; -import io.github.znetworkw.znpcservers.npc.task.NPCSaveTask; import io.github.znetworkw.znpcservers.user.ZUser; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; @@ -26,6 +23,11 @@ import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.npc.NPCProperty; import lol.pyr.znpcsplus.npc.NPCRegistry; import lol.pyr.znpcsplus.npc.NPCType; +import lol.pyr.znpcsplus.skin.cache.SkinCache; +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.updater.UpdateChecker; import lol.pyr.znpcsplus.updater.UpdateNotificationListener; @@ -57,6 +59,7 @@ public class ZNPCsPlus extends JavaPlugin { public static SchedulerUtils SCHEDULER; public static BungeeUtils BUNGEE_UTILS; public static BukkitAudiences ADVENTURE; + public static boolean PLACEHOLDERS_SUPPORTED; private boolean enabled = false; @@ -106,6 +109,9 @@ public class ZNPCsPlus extends JavaPlugin { PacketEvents.getAPI().getEventManager().registerListener(new InteractionPacketListener(), PacketListenerPriority.MONITOR); PacketEvents.getAPI().init(); + PLACEHOLDERS_SUPPORTED = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); + if (PLACEHOLDERS_SUPPORTED) log(ChatColor.WHITE + " * Enabling PlaceholderAPI Support..."); + PLUGIN_FOLDER.mkdirs(); PATH_FOLDER.mkdirs(); @@ -121,11 +127,10 @@ public class ZNPCsPlus extends JavaPlugin { Bukkit.getOnlinePlayers().forEach(ZUser::find); log(ChatColor.WHITE + " * Starting tasks..."); - new NPCPositionTask(this); new NPCVisibilityTask(this); - new NPCSaveTask(this, ConfigurationConstants.SAVE_DELAY); new PlayerListener(this); new InventoryListener(this); + new SkinCacheCleanTask(this); if (ConfigurationConstants.CHECK_FOR_UPDATES) new UpdateNotificationListener(this, new UpdateChecker(this)); enabled = true; @@ -141,7 +146,7 @@ public class ZNPCsPlus extends JavaPlugin { for (NPCType type : NPCType.values()) { NPC npc = new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0)); if (type.getType() == EntityTypes.PLAYER) { - NPCSkin.forName("Notch", (skin, ex) -> npc.setProperty(NPCProperty.SKIN, skin)); + SkinCache.fetchByName("Notch").thenAccept(skin -> npc.setProperty(NPCProperty.SKIN, new PrefetchedDescriptor(skin))); } npc.setProperty(NPCProperty.GLOW, NamedTextColor.RED); npc.setProperty(NPCProperty.FIRE, true); @@ -151,6 +156,13 @@ public class ZNPCsPlus extends JavaPlugin { z++; } } + NPC npc = new NPC(world, NPCType.byName("player"), new PacketLocation(x * 3, 200, z * 3, 0, 0)); + npc.setProperty(NPCProperty.SKIN, new FetchingDescriptor("jeb_")); + NPCRegistry.register("debug_npc" + (z * wrap + x), npc); + x++; + npc = new NPC(world, NPCType.byName("player"), new PacketLocation(x * 3, 200, z * 3, 0, 0)); + npc.setProperty(NPCProperty.SKIN, new MirrorDescriptor()); + NPCRegistry.register("debug_npc" + (z * wrap + x), npc); } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 0be9acc..bd14db7 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -65,6 +65,11 @@ public class NPC { _showAll(); } + public void respawn(Player player) { + _hide(player); + _show(player); + } + public void show(Player player) { if (viewers.contains(player)) return; _show(player); diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java index 9496537..588aca8 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java @@ -1,6 +1,6 @@ package lol.pyr.znpcsplus.npc; -import io.github.znetworkw.znpcservers.npc.NPCSkin; +import lol.pyr.znpcsplus.skin.SkinDescriptor; import net.kyori.adventure.text.format.NamedTextColor; import java.util.HashMap; @@ -35,7 +35,7 @@ public class NPCProperty { } public static NPCProperty SKIN_LAYERS = new NPCProperty<>("skin_layers", true); - public static NPCProperty SKIN = new NPCProperty<>("skin"); + public static NPCProperty SKIN = new NPCProperty<>("skin"); public static NPCProperty GLOW = new NPCProperty<>("glow"); public static NPCProperty FIRE = new NPCProperty<>("fire", false); } \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index f29463c..5ea159a 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -5,22 +5,25 @@ import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; public class NPCType { - private final static Set npcTypes; + private final static Map BY_NAME = new HashMap<>(); - public static Set values() { - return npcTypes; + public static Collection values() { + return BY_NAME.values(); + } + + public static NPCType byName(String name) { + return BY_NAME.get(name.toUpperCase()); } private final EntityType type; private final Set> allowedProperties; + private final String name; - public NPCType(EntityType type, NPCProperty... allowedProperties) { + private NPCType(String name, EntityType type, NPCProperty... allowedProperties) { + this.name = name.toUpperCase(); this.type = type; ArrayList> list = new ArrayList<>(List.of(allowedProperties)); list.add(NPCProperty.FIRE); @@ -28,6 +31,10 @@ public class NPCType { this.allowedProperties = Set.copyOf(list); } + public String getName() { + return name; + } + public EntityType getType() { return type; } @@ -36,12 +43,15 @@ public class NPCType { return allowedProperties; } + private static void register(NPCType type) { + BY_NAME.put(type.getName(), type); + + } + static { - Set set = new HashSet<>(); - set.add(new NPCType(EntityTypes.PLAYER, NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); - set.add(new NPCType(EntityTypes.CREEPER)); - set.add(new NPCType(EntityTypes.ZOMBIE)); - set.add(new NPCType(EntityTypes.SKELETON)); - npcTypes = Set.copyOf(set); + register(new NPCType("player", EntityTypes.PLAYER, NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); + register(new NPCType("creeper", EntityTypes.CREEPER)); + register(new NPCType("zombie", EntityTypes.ZOMBIE)); + register(new NPCType("skeleton", EntityTypes.SKELETON)); } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 6c5f9f9..9cdaf43 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -9,13 +9,14 @@ import org.bukkit.entity.Player; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CompletableFuture; public interface PacketFactory { void spawnPlayer(Player player, PacketEntity entity); void spawnEntity(Player player, PacketEntity entity); void destroyEntity(Player player, PacketEntity entity); void teleportEntity(Player player, PacketEntity entity); - void addTabPlayer(Player player, PacketEntity entity); + CompletableFuture addTabPlayer(Player player, PacketEntity entity); void removeTabPlayer(Player player, PacketEntity entity); void createTeam(Player player, PacketEntity entity); void removeTeam(Player player, PacketEntity entity); diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java index 3cd2a13..ad0b12c 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java @@ -10,16 +10,21 @@ import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; import java.util.EnumSet; +import java.util.concurrent.CompletableFuture; public class V1_19Factory extends V1_14Factory { @Override - public void addTabPlayer(Player player, PacketEntity entity) { - if (entity.getType() != EntityTypes.PLAYER) return; - WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( - skinned(entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))), false, - 1, GameMode.CREATIVE, Component.empty(), null); - sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, - WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); + public CompletableFuture addTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return CompletableFuture.completedFuture(null); + CompletableFuture future = new CompletableFuture<>(); + skinned(player, entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> { + WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( + profile, false, 1, GameMode.CREATIVE, Component.empty(), null); + sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, + WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info)); + future.complete(null); + }); + return future; } @Override diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 5c8be45..8b32f96 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -6,35 +6,36 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.GameMode; -import com.github.retrooper.packetevents.protocol.player.TextureProperty; import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.*; -import io.github.znetworkw.znpcservers.npc.NPCSkin; import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.metadata.MetadataFactory; import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.npc.NPCProperty; +import lol.pyr.znpcsplus.skin.SkinDescriptor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; public class V1_8Factory implements PacketFactory { @Override public void spawnPlayer(Player player, PacketEntity entity) { - addTabPlayer(player, entity); - createTeam(player, entity); - PacketLocation location = entity.getLocation(); - sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), - entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); - sendAllMetadata(player, entity); - ZNPCsPlus.SCHEDULER.scheduleSyncDelayedTask(() -> removeTabPlayer(player, entity), 60); + addTabPlayer(player, entity).thenAccept(ignored -> { + createTeam(player, entity); + PacketLocation location = entity.getLocation(); + sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), + entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); + sendAllMetadata(player, entity); + ZNPCsPlus.SCHEDULER.runTaskLaterSync(() -> removeTabPlayer(player, entity), 60); + }); } @Override @@ -64,11 +65,16 @@ public class V1_8Factory implements PacketFactory { } @Override - public void addTabPlayer(Player player, PacketEntity entity) { - if (entity.getType() != EntityTypes.PLAYER) return; - sendPacket(player, new WrapperPlayServerPlayerInfo( - WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), - skinned(entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))), GameMode.CREATIVE, 1))); + public CompletableFuture addTabPlayer(Player player, PacketEntity entity) { + if (entity.getType() != EntityTypes.PLAYER) return CompletableFuture.completedFuture(null); + CompletableFuture future = new CompletableFuture<>(); + skinned(player, entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> { + sendPacket(player, new WrapperPlayServerPlayerInfo( + WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), + profile, GameMode.CREATIVE, 1))); + future.complete(null); + }); + return future; } @Override @@ -114,11 +120,19 @@ public class V1_8Factory implements PacketFactory { PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet); } - protected UserProfile skinned(PacketEntity entity, UserProfile profile) { + protected CompletableFuture skinned(Player player, PacketEntity entity, UserProfile profile) { NPC owner = entity.getOwner(); - if (!owner.hasProperty(NPCProperty.SKIN)) return profile; - NPCSkin skin = owner.getProperty(NPCProperty.SKIN); - profile.setTextureProperties(List.of(new TextureProperty("textures", skin.getTexture(), skin.getSignature()))); - return profile; + if (!owner.hasProperty(NPCProperty.SKIN)) return CompletableFuture.completedFuture(profile); + SkinDescriptor descriptor = owner.getProperty(NPCProperty.SKIN); + if (descriptor.supportsInstant(player)) { + descriptor.fetchInstant(player).apply(profile); + return CompletableFuture.completedFuture(profile); + } + CompletableFuture future = new CompletableFuture<>(); + descriptor.fetch(player).thenAccept(skin -> { + skin.apply(profile); + future.complete(profile); + }); + return future; } } diff --git a/src/main/java/lol/pyr/znpcsplus/skin/Skin.java b/src/main/java/lol/pyr/znpcsplus/skin/Skin.java new file mode 100644 index 0000000..7954304 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/Skin.java @@ -0,0 +1,45 @@ +package lol.pyr.znpcsplus.skin; + +import com.github.retrooper.packetevents.protocol.player.TextureProperty; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.authlib.properties.PropertyMap; + +import java.util.ArrayList; +import java.util.List; + +public class Skin { + private final long timestamp = System.currentTimeMillis(); + private final List properties = new ArrayList<>(); + + public Skin(String texture, String signature) { + properties.add(new TextureProperty("textures", texture, signature)); + } + + public Skin(TextureProperty... properties) { + this.properties.addAll(List.of(properties)); + } + + public Skin(PropertyMap properties) { + this.properties.addAll(properties.values().stream() + .map(property -> new TextureProperty(property.getName(), property.getValue(), property.getSignature())) + .toList()); + } + + public Skin(JsonObject obj) { + for (JsonElement e : obj.get("properties").getAsJsonArray()) { + JsonObject o = e.getAsJsonObject(); + properties.add(new TextureProperty(o.get("name").getAsString(), o.get("value").getAsString(), o.has("signature") ? o.get("signature").getAsString() : null)); + } + } + + public UserProfile apply(UserProfile profile) { + profile.setTextureProperties(properties); + return profile; + } + + public boolean isExpired() { + return System.currentTimeMillis() - timestamp > 60000L; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptor.java b/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptor.java new file mode 100644 index 0000000..0c5ad23 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/SkinDescriptor.java @@ -0,0 +1,11 @@ +package lol.pyr.znpcsplus.skin; + +import org.bukkit.entity.Player; + +import java.util.concurrent.CompletableFuture; + +public interface SkinDescriptor { + CompletableFuture fetch(Player player); + Skin fetchInstant(Player player); + boolean supportsInstant(Player player); +} diff --git a/src/main/java/lol/pyr/znpcsplus/skin/cache/CachedId.java b/src/main/java/lol/pyr/znpcsplus/skin/cache/CachedId.java new file mode 100644 index 0000000..cf60441 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/cache/CachedId.java @@ -0,0 +1,18 @@ +package lol.pyr.znpcsplus.skin.cache; + +public class CachedId { + private final long timestamp = System.currentTimeMillis(); + private final String id; + + public CachedId(String id) { + this.id = id; + } + + public boolean isExpired() { + return System.currentTimeMillis() - timestamp > 60000L; + } + + public String getId() { + return id; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCache.java b/src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCache.java new file mode 100644 index 0000000..ff2afec --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCache.java @@ -0,0 +1,131 @@ +package lol.pyr.znpcsplus.skin.cache; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.mojang.authlib.GameProfile; +import io.github.znetworkw.znpcservers.reflection.Reflections; +import lol.pyr.znpcsplus.skin.Skin; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.InvocationTargetException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +public class SkinCache { + private final static Map cache = new ConcurrentHashMap<>(); + private final static Map idCache = new ConcurrentHashMap<>(); + + public static void cleanCache() { + for (Map.Entry entry : cache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey()); + for (Map.Entry entry : idCache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey()); + } + + public static CompletableFuture fetchByName(String name) { + Player player = Bukkit.getPlayerExact(name); + if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player)); + + if (cache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId()); + + CompletableFuture future = new CompletableFuture<>(); + CompletableFuture.runAsync(() -> { + URL url = parseUrl("https://api.mojang.com/users/profiles/minecraft/" + name); + HttpURLConnection connection = null; + try { + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) { + JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject(); + if (obj.has("errorMessage")) future.complete(null); + String id = obj.get("id").getAsString(); + idCache.put(name.toLowerCase(), new CachedId(id)); + fetchByUUID(id).thenAccept(future::complete); + } + } catch (IOException exception) { + exception.printStackTrace(); + } finally { + if (connection != null) connection.disconnect(); + } + }); + return future; + } + + public static CompletableFuture fetchByUUID(UUID uuid) { + return fetchByUUID(uuid.toString().replace("-", "")); + } + + public static boolean isNameFullyCached(String s) { + String name = s.toLowerCase(); + if (!idCache.containsKey(name)) return false; + CachedId id = idCache.get(name); + if (id.isExpired() || !cache.containsKey(id.getId())) return false; + Skin skin = cache.get(id.getId()); + return !skin.isExpired(); + } + + public static Skin getFullyCachedByName(String s) { + String name = s.toLowerCase(); + if (!idCache.containsKey(name)) return null; + CachedId id = idCache.get(name); + if (id.isExpired() || !cache.containsKey(id.getId())) return null; + Skin skin = cache.get(id.getId()); + if (skin.isExpired()) return null; + return skin; + } + + public static CompletableFuture fetchByUUID(String uuid) { + Player player = Bukkit.getPlayer(uuid); + if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player)); + + if (cache.containsKey(uuid)) { + Skin skin = cache.get(uuid); + if (!skin.isExpired()) return CompletableFuture.completedFuture(skin); + } + + return CompletableFuture.supplyAsync(() -> { + URL url = parseUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false"); + HttpURLConnection connection = null; + try { + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) { + Skin skin = new Skin(JsonParser.parseReader(reader).getAsJsonObject()); + cache.put(uuid, skin); + return skin; + } + } catch (IOException exception) { + exception.printStackTrace(); + } finally { + if (connection != null) connection.disconnect(); + } + return null; + }); + } + + public static Skin getFromPlayer(Player player) { + try { + Object playerHandle = Reflections.GET_HANDLE_PLAYER_METHOD.get().invoke(player); + GameProfile gameProfile = (GameProfile) Reflections.GET_PROFILE_METHOD.get().invoke(playerHandle, new Object[0]); + return new Skin(gameProfile.getProperties()); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static URL parseUrl(String url) { + try { + return new URL(url); + } catch (MalformedURLException exception) { + throw new RuntimeException(exception); + } + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCacheCleanTask.java b/src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCacheCleanTask.java new file mode 100644 index 0000000..443d0ca --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCacheCleanTask.java @@ -0,0 +1,15 @@ +package lol.pyr.znpcsplus.skin.cache; + +import lol.pyr.znpcsplus.ZNPCsPlus; +import org.bukkit.scheduler.BukkitRunnable; + +public class SkinCacheCleanTask extends BukkitRunnable { + public SkinCacheCleanTask(ZNPCsPlus plugin) { + runTaskTimerAsynchronously(plugin, 1200, 1200); + } + + @Override + public void run() { + SkinCache.cleanCache(); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/skin/descriptor/FetchingDescriptor.java b/src/main/java/lol/pyr/znpcsplus/skin/descriptor/FetchingDescriptor.java new file mode 100644 index 0000000..7c024cc --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/descriptor/FetchingDescriptor.java @@ -0,0 +1,38 @@ +package lol.pyr.znpcsplus.skin.descriptor; + +import lol.pyr.znpcsplus.ZNPCsPlus; +import lol.pyr.znpcsplus.skin.Skin; +import lol.pyr.znpcsplus.skin.SkinDescriptor; +import lol.pyr.znpcsplus.skin.cache.SkinCache; +import me.clip.placeholderapi.PlaceholderAPI; +import org.bukkit.entity.Player; + +import java.util.concurrent.CompletableFuture; + +public class FetchingDescriptor implements SkinDescriptor { + private final String name; + + public FetchingDescriptor(String name) { + this.name = name; + } + + @Override + public CompletableFuture fetch(Player player) { + return SkinCache.fetchByName(papi(player)); + } + + @Override + public Skin fetchInstant(Player player) { + return SkinCache.getFullyCachedByName(papi(player)); + } + + @Override + public boolean supportsInstant(Player player) { + return SkinCache.isNameFullyCached(papi(player)); + } + + private String papi(Player player) { + if (ZNPCsPlus.PLACEHOLDERS_SUPPORTED) return PlaceholderAPI.setPlaceholders(player, name); + return name; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/skin/descriptor/MirrorDescriptor.java b/src/main/java/lol/pyr/znpcsplus/skin/descriptor/MirrorDescriptor.java new file mode 100644 index 0000000..d2d124d --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/descriptor/MirrorDescriptor.java @@ -0,0 +1,28 @@ +package lol.pyr.znpcsplus.skin.descriptor; + +import lol.pyr.znpcsplus.skin.Skin; +import lol.pyr.znpcsplus.skin.SkinDescriptor; +import lol.pyr.znpcsplus.skin.cache.SkinCache; +import org.bukkit.entity.Player; + +import java.util.concurrent.CompletableFuture; + +public class MirrorDescriptor implements SkinDescriptor { + + public MirrorDescriptor() {} + + @Override + public CompletableFuture fetch(Player player) { + return CompletableFuture.completedFuture(SkinCache.getFromPlayer(player)); + } + + @Override + public Skin fetchInstant(Player player) { + return SkinCache.getFromPlayer(player); + } + + @Override + public boolean supportsInstant(Player player) { + return true; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java b/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java new file mode 100644 index 0000000..c08d2e6 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/skin/descriptor/PrefetchedDescriptor.java @@ -0,0 +1,30 @@ +package lol.pyr.znpcsplus.skin.descriptor; + +import lol.pyr.znpcsplus.skin.Skin; +import lol.pyr.znpcsplus.skin.SkinDescriptor; +import org.bukkit.entity.Player; + +import java.util.concurrent.CompletableFuture; + +public class PrefetchedDescriptor implements SkinDescriptor { + private final Skin skin; + + public PrefetchedDescriptor(Skin skin) { + this.skin = skin; + } + + @Override + public CompletableFuture fetch(Player player) { + return CompletableFuture.completedFuture(skin); + } + + @Override + public Skin fetchInstant(Player player) { + return skin; + } + + @Override + public boolean supportsInstant(Player player) { + return true; + } +} From 32b96384e1e66a0438503074f5316e8795eb32ea Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 25 Apr 2023 17:05:28 +0100 Subject: [PATCH 14/22] add invisible property --- src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java | 1 + .../java/lol/pyr/znpcsplus/metadata/MetadataFactory.java | 2 +- src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java | 4 ++-- src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java | 4 ++-- src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java | 1 + src/main/java/lol/pyr/znpcsplus/npc/NPCType.java | 1 + src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java | 6 ++++-- src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java | 3 ++- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 63e5ee5..e096ed3 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -147,6 +147,7 @@ public class ZNPCsPlus extends JavaPlugin { NPC npc = new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0)); if (type.getType() == EntityTypes.PLAYER) { SkinCache.fetchByName("Notch").thenAccept(skin -> npc.setProperty(NPCProperty.SKIN, new PrefetchedDescriptor(skin))); + npc.setProperty(NPCProperty.INVISIBLE, true); } npc.setProperty(NPCProperty.GLOW, NamedTextColor.RED); npc.setProperty(NPCProperty.FIRE, true); diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java index 621fcd2..22c674d 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java @@ -24,7 +24,7 @@ import java.util.Map; */ public interface MetadataFactory { EntityData skinLayers(); - EntityData effects(boolean onFire, boolean glowing); + EntityData effects(boolean onFire, boolean glowing, boolean invisible); MetadataFactory factory = get(); diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java index b36b7fa..201aa2d 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java @@ -10,8 +10,8 @@ public class V1_8Factory implements MetadataFactory { } @Override - public EntityData effects(boolean onFire, boolean glowing) { - return new EntityData(0, EntityDataTypes.BYTE, onFire ? 0x01 : 0); + public EntityData effects(boolean onFire, boolean glowing, boolean invisible) { + return new EntityData(0, EntityDataTypes.BYTE, (onFire ? 0x01 : 0) | (invisible ? 0x20 : 0)); } protected EntityData createSkinLayers(int index) { diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java index 1a8a9c5..5e9ebc3 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java @@ -10,7 +10,7 @@ public class V1_9Factory extends V1_8Factory { } @Override - public EntityData effects(boolean onFire, boolean glowing) { - return new EntityData(0, EntityDataTypes.BYTE, (byte) ((onFire ? 0x01 : 0) | (glowing ? 0x40 : 0))); + public EntityData effects(boolean onFire, boolean glowing, boolean invisible) { + return new EntityData(0, EntityDataTypes.BYTE, (byte) ((onFire ? 0x01 : 0) | (invisible ? 0x20 : 0) | (glowing ? 0x40 : 0))); } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java index 588aca8..6236194 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java @@ -38,4 +38,5 @@ public class NPCProperty { public static NPCProperty SKIN = new NPCProperty<>("skin"); public static NPCProperty GLOW = new NPCProperty<>("glow"); public static NPCProperty FIRE = new NPCProperty<>("fire", false); + public static NPCProperty INVISIBLE = new NPCProperty<>("invisible", false); } \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 5ea159a..2e3c61c 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -27,6 +27,7 @@ public class NPCType { this.type = type; ArrayList> list = new ArrayList<>(List.of(allowedProperties)); list.add(NPCProperty.FIRE); + list.add(NPCProperty.INVISIBLE); if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) list.add(NPCProperty.GLOW); this.allowedProperties = Set.copyOf(list); } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index 8b32f96..ebeda9f 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -108,7 +108,9 @@ public class V1_8Factory implements PacketFactory { public void sendAllMetadata(Player player, PacketEntity entity) { NPC owner = entity.getOwner(); if (entity.getType() == EntityTypes.PLAYER && owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); - if (owner.getProperty(NPCProperty.FIRE)) sendMetadata(player, entity, MetadataFactory.get().effects(true, false)); + boolean fire = owner.getProperty(NPCProperty.FIRE); + boolean invisible = owner.getProperty(NPCProperty.INVISIBLE); + if (fire || invisible) sendMetadata(player, entity, MetadataFactory.get().effects(fire, false, invisible)); } @Override @@ -130,7 +132,7 @@ public class V1_8Factory implements PacketFactory { } CompletableFuture future = new CompletableFuture<>(); descriptor.fetch(player).thenAccept(skin -> { - skin.apply(profile); + if (skin != null) skin.apply(profile); future.complete(profile); }); return future; diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java index dac06ed..0a1eaeb 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java @@ -14,7 +14,8 @@ public class V1_9Factory extends V1_8Factory { if (entity.getType() == EntityTypes.PLAYER && owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); boolean glow = owner.hasProperty(NPCProperty.GLOW); boolean fire = owner.getProperty(NPCProperty.FIRE); - if (glow || fire) sendMetadata(player, entity, MetadataFactory.get().effects(fire, glow)); + boolean invisible = owner.getProperty(NPCProperty.INVISIBLE); + if (glow || fire) sendMetadata(player, entity, MetadataFactory.get().effects(fire, glow, invisible)); } @Override From 5d5c2407be09a91e0f189b8c9352986e3ef651ba Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 25 Apr 2023 17:24:38 +0100 Subject: [PATCH 15/22] add NPCType builder --- .../java/lol/pyr/znpcsplus/npc/NPCType.java | 53 +++++++++++++++---- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 2e3c61c..463b8d5 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -22,14 +22,10 @@ public class NPCType { private final Set> allowedProperties; private final String name; - private NPCType(String name, EntityType type, NPCProperty... allowedProperties) { + private NPCType(String name, EntityType type, Set> allowedProperties) { this.name = name.toUpperCase(); this.type = type; - ArrayList> list = new ArrayList<>(List.of(allowedProperties)); - list.add(NPCProperty.FIRE); - list.add(NPCProperty.INVISIBLE); - if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) list.add(NPCProperty.GLOW); - this.allowedProperties = Set.copyOf(list); + this.allowedProperties = allowedProperties; } public String getName() { @@ -44,15 +40,52 @@ public class NPCType { return allowedProperties; } + private static void register(Builder builder) { + register(builder.build()); + } + private static void register(NPCType type) { BY_NAME.put(type.getName(), type); } static { - register(new NPCType("player", EntityTypes.PLAYER, NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); - register(new NPCType("creeper", EntityTypes.CREEPER)); - register(new NPCType("zombie", EntityTypes.ZOMBIE)); - register(new NPCType("skeleton", EntityTypes.SKELETON)); + register(new Builder("player", EntityTypes.PLAYER) + .addProperties(NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); + register(new Builder("creeper", EntityTypes.CREEPER)); + register(new Builder("zombie", EntityTypes.ZOMBIE)); + register(new Builder("skeleton", EntityTypes.SKELETON)); + } + + private static final class Builder { + private final String name; + private final EntityType type; + private final List> allowedProperties = new ArrayList<>(); + private boolean globalProperties = true; + + private Builder(String name, EntityType type) { + this.name = name; + this.type = type; + } + + public Builder addProperties(NPCProperty... properties) { + allowedProperties.addAll(List.of(properties)); + return this; + } + + public Builder setEnableGlobalProperties(boolean enabled) { + globalProperties = enabled; + return this; + } + + public NPCType build() { + if (globalProperties) { + allowedProperties.add(NPCProperty.FIRE); + allowedProperties.add(NPCProperty.INVISIBLE); + if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) + allowedProperties.add(NPCProperty.GLOW); + } + return new NPCType(name, type, Set.copyOf(allowedProperties)); + } } } From 3f9c027005580c60ce97441d90fdca70709d90b2 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 25 Apr 2023 17:57:18 +0100 Subject: [PATCH 16/22] add User, delete a bunch of stuff we're not using anymore --- .../znpcservers/commands/Command.java | 77 --- .../commands/CommandInformation.java | 18 - .../znpcservers/commands/CommandInvoker.java | 37 -- .../znpcservers/commands/CommandSender.java | 61 -- .../commands/list/DefaultCommand.java | 563 ------------------ .../list/inventory/ConversationGUI.java | 48 +- .../configuration/ConfigurationConstants.java | 15 - .../configuration/ConfigurationValue.java | 9 +- .../ChannelRegistrationException.java | 23 - .../znpcservers/hologram/Hologram.java | 133 ----- .../hologram/replacer/LineReplacer.java | 21 - .../hologram/replacer/RGBLine.java | 37 -- .../znpcservers/listeners/PlayerListener.java | 47 -- .../github/znetworkw/znpcservers/nms/NMS.java | 72 --- .../znetworkw/znpcservers/nms/NMSFactory.java | 19 - .../znetworkw/znpcservers/nms/NMSV17.java | 21 - .../znetworkw/znpcservers/nms/NMSV18.java | 15 - .../znetworkw/znpcservers/nms/NMSV19.java | 19 - .../znetworkw/znpcservers/nms/NMSV8.java | 42 -- .../znetworkw/znpcservers/nms/NMSV9.java | 26 - .../znpcservers/nms/PacketCache.java | 89 --- .../znpcservers/nms/PacketValue.java | 14 - .../znetworkw/znpcservers/nms/ValueType.java | 20 - .../znpcservers/npc/CustomizationLoader.java | 48 -- .../znpcservers/npc/FunctionContext.java | 34 -- .../znpcservers/npc/FunctionFactory.java | 31 - .../github/znetworkw/znpcservers/npc/NPC.java | 363 ----------- .../znetworkw/znpcservers/npc/NPCAction.java | 94 --- .../znpcservers/npc/NPCFunction.java | 66 -- .../znetworkw/znpcservers/npc/NPCModel.java | 247 -------- .../znetworkw/znpcservers/npc/NPCPath.java | 263 -------- .../znetworkw/znpcservers/npc/NPCSkin.java | 63 -- .../znetworkw/znpcservers/npc/NPCType.java | 82 +-- .../znetworkw/znpcservers/npc/NamingType.java | 13 - .../npc/PrimitivePropertyType.java | 34 -- .../npc/conversation/Conversation.java | 58 -- .../npc/conversation/ConversationKey.java | 57 -- .../npc/conversation/ConversationModel.java | 73 --- .../conversation/ConversationProcessor.java | 70 --- .../npc/function/GlowFunction.java | 44 -- .../npc/interaction/ClickType.java | 11 - .../npc/interaction/NPCInteractEvent.java | 48 -- .../znpcservers/npc/task/NPCLoadTask.java | 29 - .../znpcservers/npc/task/NPCPositionTask.java | 28 - .../znpcservers/npc/task/NPCSaveTask.java | 15 - .../znpcservers/skin/SkinFetcher.java | 63 -- .../znpcservers/skin/SkinFetcherBuilder.java | 76 --- .../znpcservers/skin/SkinFetcherResult.java | 7 - .../znpcservers/user/EventService.java | 11 +- .../znetworkw/znpcservers/user/ZUser.java | 99 --- .../utility/location/ZLocation.java | 137 ----- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 29 +- .../InteractionPacketListener.java | 19 +- src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 5 + .../lol/pyr/znpcsplus/npc/NPCRegistry.java | 10 +- .../java/lol/pyr/znpcsplus/user/User.java | 55 ++ .../lol/pyr/znpcsplus/user/UserListener.java | 38 ++ 57 files changed, 150 insertions(+), 3596 deletions(-) delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/commands/Command.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/commands/CommandInformation.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/commands/CommandInvoker.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/commands/CommandSender.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/exception/ChannelRegistrationException.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/hologram/Hologram.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/LineReplacer.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/RGBLine.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/listeners/PlayerListener.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/NMS.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/NMSFactory.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/NMSV17.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/NMSV18.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/NMSV19.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/NMSV8.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/NMSV9.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/PacketCache.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/PacketValue.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/nms/ValueType.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/CustomizationLoader.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/FunctionContext.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/FunctionFactory.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NPCAction.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NPCFunction.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NPCModel.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NPCPath.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NamingType.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/PrimitivePropertyType.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/conversation/Conversation.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationKey.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationModel.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationProcessor.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/function/GlowFunction.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/interaction/ClickType.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/interaction/NPCInteractEvent.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCLoadTask.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCPositionTask.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCSaveTask.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherBuilder.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/user/ZUser.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/utility/location/ZLocation.java rename src/main/java/{io/github/znetworkw/znpcservers/npc => lol/pyr/znpcsplus}/interaction/InteractionPacketListener.java (73%) create mode 100644 src/main/java/lol/pyr/znpcsplus/user/User.java create mode 100644 src/main/java/lol/pyr/znpcsplus/user/UserListener.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/Command.java b/src/main/java/io/github/znetworkw/znpcservers/commands/Command.java deleted file mode 100644 index e6b68c9..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/Command.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.github.znetworkw.znpcservers.commands; - -import com.google.common.collect.Iterables; -import io.github.znetworkw.znpcservers.exception.CommandException; -import io.github.znetworkw.znpcservers.exception.CommandExecuteException; -import io.github.znetworkw.znpcservers.exception.CommandPermissionException; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.defaults.BukkitCommand; - -import java.lang.reflect.Method; -import java.util.*; - -public class Command extends BukkitCommand { - private final Map subCommands; - - public Command(String name) { - super(name); - this.subCommands = new HashMap<>(); - load(); - } - - private void load() { - Reflections.COMMAND_MAP_FIELD.get().register(getName(), this); - for (Method method : getClass().getMethods()) { - if (method.isAnnotationPresent(CommandInformation.class)) { - CommandInformation cmdInfo = method.getAnnotation(CommandInformation.class); - this.subCommands.put(cmdInfo, new CommandInvoker(this, method, cmdInfo.permission())); - } - } - } - - private Map loadArgs(CommandInformation subCommand, Iterable args) { - int size = Iterables.size(args); - int subCommandsSize = (subCommand.arguments()).length; - Map argsMap = new HashMap<>(); - if (size > 1) if (subCommand.isMultiple()) { - argsMap.put(Iterables.get(args, 1), String.join(" ", Iterables.skip(args, 2))); - } else { - for (int i = 0; i < Math.min(subCommandsSize, size); i++) { - int fixedLength = i + 1; - if (size > fixedLength) { - String input = Iterables.get(args, fixedLength); - if (fixedLength == subCommandsSize) - input = String.join(" ", Iterables.skip(args, subCommandsSize)); - argsMap.put(subCommand.arguments()[i], input); - } - } - } - return argsMap; - } - - public Set getCommands() { - return this.subCommands.keySet(); - } - - public boolean execute(CommandSender sender, String commandLabel, String[] args) { - Optional> subCommandOptional = this.subCommands.entrySet().stream().filter(command -> command.getKey().name().contentEquals((args.length > 0) ? args[0] : "")).findFirst(); - if (subCommandOptional.isEmpty()) { - sender.sendMessage(ChatColor.RED + "Unable to locate the following command: " + commandLabel + "."); - return false; - } - try { - Map.Entry subCommand = subCommandOptional.get(); - subCommand.getValue().execute(new io.github.znetworkw.znpcservers.commands.CommandSender(sender), loadArgs(subCommand.getKey(), Arrays.asList(args))); - } catch (CommandExecuteException e) { - sender.sendMessage(ChatColor.RED + "Cannot execute this command or this command execution has failed."); - e.printStackTrace(); - } catch (CommandPermissionException e) { - sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command."); - } catch (CommandException e) { - sender.sendMessage(ChatColor.RED + e.getMessage()); - } - return true; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/CommandInformation.java b/src/main/java/io/github/znetworkw/znpcservers/commands/CommandInformation.java deleted file mode 100644 index c185f09..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/CommandInformation.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.znetworkw.znpcservers.commands; - -import java.lang.annotation.*; - -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface CommandInformation { - String[] arguments(); - - String[] help() default {}; - - String name(); - - String permission(); - - boolean isMultiple() default false; -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/CommandInvoker.java b/src/main/java/io/github/znetworkw/znpcservers/commands/CommandInvoker.java deleted file mode 100644 index b3f583c..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/CommandInvoker.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.github.znetworkw.znpcservers.commands; - -import io.github.znetworkw.znpcservers.exception.CommandException; -import io.github.znetworkw.znpcservers.exception.CommandExecuteException; -import io.github.znetworkw.znpcservers.exception.CommandPermissionException; -import org.bukkit.entity.Player; - -import java.lang.reflect.Method; - -public class CommandInvoker { - private final Command command; - private final Method commandMethod; - private final String permission; - - public CommandInvoker(Command command, Method commandMethod, String permission) { - this.command = command; - this.commandMethod = commandMethod; - this.permission = permission; - } - - public void execute(CommandSender sender, Object command) throws CommandException { - // Check if the sender is not a player - if (!(sender.getCommandSender() instanceof Player player)) - throw new CommandException("Only players may execute this command."); - - // Check if the permission is not empty and the player does not have the permission - if (this.permission.length() > 0 && !player.hasPermission(this.permission)) - throw new CommandPermissionException("You cannot execute this command."); - - try { - // Command execution - this.commandMethod.invoke(this.command, sender, command); - } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException e) { - throw new CommandExecuteException(e.getMessage(), e.getCause()); - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/CommandSender.java b/src/main/java/io/github/znetworkw/znpcservers/commands/CommandSender.java deleted file mode 100644 index cbbb1e1..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/CommandSender.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.github.znetworkw.znpcservers.commands; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import lol.pyr.znpcsplus.ZNPCsPlus; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.entity.Player; - -import java.util.Arrays; -import java.util.stream.Collectors; - -public class CommandSender { - static final Joiner LINE_SEPARATOR_JOINER = Joiner.on("\n"); - - private static final ImmutableList HELP_PREFIX = ImmutableList.of("&6&lEXAMPLES&r:"); - - private final org.bukkit.command.CommandSender commandSender; - - private final SenderType type; - - public CommandSender(org.bukkit.command.CommandSender commandSender) { - this.commandSender = commandSender; - this.type = (commandSender instanceof Player) ? SenderType.PLAYER : SenderType.CONSOLE; - } - - public void sendMessage(String message) { - sendMessage(message, null); - } - - public void sendMessage(CommandInformation subCommand) { - sendMessage(" &7\u00BB &6/&eznpcs " + subCommand.name() + " " + - Arrays.stream(subCommand.arguments()) - .map(s -> "<" + s + ">") - .collect(Collectors.joining(" ")), - Arrays.asList(subCommand.help())); - } - - public void sendMessage(String message, Iterable hover) { - message = message.replace(LegacyComponentSerializer.SECTION_CHAR, LegacyComponentSerializer.AMPERSAND_CHAR); - LegacyComponentSerializer serializer = LegacyComponentSerializer.legacyAmpersand(); - TextComponent textComponent = serializer.deserialize(message); - if (hover != null) textComponent = textComponent.hoverEvent(serializer.deserialize(LINE_SEPARATOR_JOINER.join(Iterables.concat(HELP_PREFIX, hover)))); - ZNPCsPlus.ADVENTURE.player(getPlayer()).sendMessage(textComponent); - } - - public Player getPlayer() { - if (this.type != SenderType.PLAYER) - throw new IllegalStateException("The following sender is not a player."); - return (Player) getCommandSender(); - } - - public org.bukkit.command.CommandSender getCommandSender() { - return this.commandSender; - } - - enum SenderType { - PLAYER, CONSOLE - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java deleted file mode 100644 index 6cf4600..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/DefaultCommand.java +++ /dev/null @@ -1,563 +0,0 @@ -package io.github.znetworkw.znpcservers.commands.list; - -import com.github.retrooper.packetevents.protocol.player.EquipmentSlot; -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.primitives.Doubles; -import com.google.common.primitives.Ints; -import io.github.znetworkw.znpcservers.commands.Command; -import io.github.znetworkw.znpcservers.commands.CommandInformation; -import io.github.znetworkw.znpcservers.commands.CommandSender; -import io.github.znetworkw.znpcservers.commands.list.inventory.ConversationGUI; -import io.github.znetworkw.znpcservers.configuration.Configuration; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.configuration.ConfigurationValue; -import io.github.znetworkw.znpcservers.npc.*; -import io.github.znetworkw.znpcservers.npc.conversation.Conversation; -import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel; -import io.github.znetworkw.znpcservers.user.ZUser; -import io.github.znetworkw.znpcservers.utility.location.ZLocation; -import lol.pyr.znpcsplus.ZNPCsPlus; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.event.HoverEvent; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.md_5.bungee.api.ChatColor; -import org.bukkit.entity.Player; - -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -@SuppressWarnings({"UnstableApiUsage", "deprecation"}) -public class DefaultCommand extends Command { - private static final Splitter SPACE_SPLITTER = Splitter.on(" "); - - private static final Joiner SPACE_JOINER = Joiner.on(" "); - - private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (npcSkin, ex) -> { - if (ex != null) { - Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.CANT_GET_SKIN, skin); - ZNPCsPlus.LOGGER.warning("Failed to fetch skin:"); - ex.printStackTrace(); - return; - } - npc.changeSkin(npcSkin); - Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.GET_SKIN); - }); - - public DefaultCommand() { - super("znpcs"); - } - - @CommandInformation(arguments = {}, name = "", permission = "") - public void defaultCommand(CommandSender sender, Map args) { - sender.sendMessage("&6&m------------------------------------------"); - sender.sendMessage("&b&lZNPCsPlus &8\u00BB &7ZNetwork & Pyr"); - sender.sendMessage("&6https://www.spigotmc.org/resources/znpcsplus.109380/"); - Objects.requireNonNull(sender); - getCommands().forEach(sender::sendMessage); - sender.sendMessage(ChatColor.DARK_GRAY + "Hover over the commands to view command arguments."); - sender.sendMessage("&6&m------------------------------------------"); - } - - @CommandInformation(arguments = {"id", "type", "name"}, name = "create", permission = "znpcs.cmd.create", help = {" &f&l* &e/znpcs create PLAYER Steve"}) - public void createNPC(CommandSender sender, Map args) { - if (args.size() < 3) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - boolean foundNPC = ConfigurationConstants.NPC_LIST.stream().anyMatch(npc -> (npc.getId() == id)); - if (foundNPC) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_FOUND); - return; - } - String name = args.get("name").trim(); - if (name.length() < 3 || name.length() > 16) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NAME_LENGTH); - return; - } - NPCType npcType = NPCType.valueOf(args.get("type").toUpperCase()); - if (npcType.getConstructor() == null && !npcType.equals(NPCType.PLAYER)) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NOT_SUPPORTED_NPC_TYPE); - return; - } - // ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {"id"}, name = "delete", permission = "znpcs.cmd.delete", help = {" &f&l* &e/znpcs delete "}) - public void deleteNPC(CommandSender sender, Map args) { - if (args.size() < 1) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - // ZNPCsPlus.deleteNPC(id); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {}, name = "list", permission = "znpcs.cmd.list") - public void list(CommandSender sender, Map args) { - if (ConfigurationConstants.NPC_LIST.isEmpty()) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_NPC_FOUND); - } else { - sender.sendMessage(ChatColor.DARK_GREEN + "NPC list:"); - for (NPCModel npcModel : ConfigurationConstants.NPC_LIST) - ZNPCsPlus.ADVENTURE.player(sender.getPlayer()).sendMessage(Component.text("-", NamedTextColor.GREEN) - .append(Component.text(" " + npcModel.getId(), npcModel.getShouldSpawn() ? NamedTextColor.GREEN : NamedTextColor.RED)) - .append(Component.text(" " + npcModel.getHologramLines().toString() + - " (" + npcModel.getLocation().getWorldName() + " " + (int) npcModel.getLocation().getX() + " " + - (int) npcModel.getLocation().getY() + " " + (int) npcModel.getLocation().getZ() + ") ", NamedTextColor.GREEN)) - .append(Component.text("[TELEPORT]", NamedTextColor.DARK_GREEN, TextDecoration.BOLD) - .clickEvent(ClickEvent.runCommand("/znpcs teleport " + npcModel.getId())) - .hoverEvent(HoverEvent.showText(Component.text("Click to teleport to this NPC.")))) - .append(Component.text(" [DELETE]", NamedTextColor.RED, TextDecoration.BOLD) - .clickEvent(ClickEvent.runCommand("/znpcs delete " + npcModel.getId())) - .hoverEvent(HoverEvent.showText(Component.text("Click to delete this NPC."))))); - } - } - - @CommandInformation(arguments = {"id", "skin"}, name = "skin", permission = "znpcs.cmd.skin", help = {" &f&l* &e/znpcs skin Notch"}) - public void setSkin(CommandSender sender, Map args) { - if (args.size() < 1) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - String skin = args.get("skin"); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.FETCHING_SKIN, skin); - DO_APPLY_SKIN.apply(sender.getPlayer(), foundNPC, args.get("skin")); - } - - @CommandInformation(arguments = {"id", "slot"}, name = "equip", permission = "znpcs.cmd.equip", help = {" &f&l* &e/znpcs equip [HAND/OFFHAND/HELMET/CHESTPLATE/LEGGINGS/BOOTS]", "&8(You need to have the item in your hand)."}) - public void equip(CommandSender sender, Map args) { - if (args.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - foundNPC.getNpcPojo().getNpcEquip().put(EquipmentSlot.valueOf(args.get("slot").toUpperCase()), sender.getPlayer().getInventory().getItemInHand()); - foundNPC.getPackets().flushCache("equipPackets"); - Objects.requireNonNull(foundNPC); - foundNPC.getViewers().forEach(foundNPC::sendEquipPackets); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {"id", "lines"}, name = "lines", permission = "znpcs.cmd.lines", help = {" &f&l* &e/znpcs lines First Second Third-Space"}) - public void changeLines(CommandSender sender, Map args) { - if (args.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - foundNPC.getNpcPojo().setHologramLines(Lists.reverse(SPACE_SPLITTER.splitToList(args.get("lines")))); - foundNPC.getHologram().createHologram(); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {"id"}, name = "move", permission = "znpcs.cmd.move", help = {" &f&l* &e/znpcs move "}) - public void move(CommandSender sender, Map args) { - if (args.size() < 1) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - foundNPC.getNpcPojo().setLocation(new ZLocation(sender.getPlayer().getLocation())); - foundNPC.changeType(foundNPC.getNpcPojo().getNpcType()); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {"id", "type"}, name = "type", permission = "znpcs.cmd.type", help = {" &f&l* &e/znpcs type ZOMBIE"}) - public void changeType(CommandSender sender, Map args) { - if (args.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - NPCType npcType = NPCType.valueOf(args.get("type").toUpperCase()); - if (npcType != NPCType.PLAYER && npcType.getConstructor() == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.UNSUPPORTED_ENTITY); - return; - } - foundNPC.changeType(npcType); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {"add", "remove", "cooldown", "list"}, name = "action", isMultiple = true, permission = "znpcs.cmd.action", help = {" &f&l* &e/znpcs action add SERVER survival", " &f&l* &e/znpcs action add CMD spawn", " &f&l* &e/znpcs action remove ", " &f&l* &e/znpcs action cooldown ", " &f&l* &e/znpcs action list "}) - public void action(CommandSender sender, Map args) { - if (args.size() < 1) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - if (args.containsKey("add")) { - List split = SPACE_SPLITTER.splitToList(args.get("add")); - if (split.size() < 3) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.ACTION_ADD_INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(split.get(0)); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - foundNPC.getNpcPojo().getClickActions().add(new NPCAction(split.get(1).toUpperCase(), SPACE_JOINER.join(Iterables.skip(split, 2)))); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } else if (args.containsKey("remove")) { - List split = SPACE_SPLITTER.splitToList(args.get("remove")); - Integer id = Ints.tryParse(split.get(0)); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - Integer actionId = Ints.tryParse(split.get(1)); - if (actionId == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - } else { - if (actionId >= foundNPC.getNpcPojo().getClickActions().size()) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_ACTION_FOUND); - return; - } - foundNPC.getNpcPojo().getClickActions().remove(actionId.intValue()); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - } else if (args.containsKey("cooldown")) { - List split = SPACE_SPLITTER.splitToList(args.get("cooldown")); - if (split.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.ACTION_DELAY_INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(split.get(0)); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - Integer actionId = Ints.tryParse(split.get(1)); - Integer actionDelay = Ints.tryParse(split.get(2)); - if (actionId == null || actionDelay == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - } else { - if (actionId >= foundNPC.getNpcPojo().getClickActions().size()) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_ACTION_FOUND); - return; - } - foundNPC.getNpcPojo().getClickActions().get(actionId).setDelay(actionDelay); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - } else if (args.containsKey("list")) { - Integer id = Ints.tryParse(args.get("list")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - if (foundNPC.getNpcPojo().getClickActions().isEmpty()) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_ACTION_FOUND); - } else { - foundNPC.getNpcPojo().getClickActions().forEach(s -> sender.sendMessage("&8(&a" + foundNPC.getNpcPojo().getClickActions().indexOf(s) + "&8) &6" + s.toString())); - } - } - } - - @CommandInformation(arguments = {"id", "type", "value"}, name = "toggle", permission = "znpcs.cmd.toggle", help = {" &f&l* &e/znpcs toggle look"}) - public void toggle(CommandSender sender, Map args) { - if (args.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - NPCFunction npcFunction = FunctionFactory.findFunctionForName(args.get("type")); - if (npcFunction.getName().equalsIgnoreCase("glow")) { - npcFunction.doRunFunction(foundNPC, new FunctionContext.ContextWithValue(foundNPC, args.get("value"))); - } else { - npcFunction.doRunFunction(foundNPC, new FunctionContext.DefaultContext(foundNPC)); - } - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {"id", "customizeValues"}, name = "customize", permission = "znpcs.cmd.customize", help = {" &f&l* &e/znpcs customize "}) - public void customize(CommandSender sender, Map args) { - if (args.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - NPCType npcType = foundNPC.getNpcPojo().getNpcType(); - List customizeOptions = SPACE_SPLITTER.splitToList(args.get("customizeValues")); - String methodName = customizeOptions.get(0); - if (npcType.getCustomizationLoader().contains(methodName)) { - Method method = npcType.getCustomizationLoader().getMethods().get(methodName); - Iterable split = Iterables.skip(customizeOptions, 1); - if (Iterables.size(split) < (method.getParameterTypes()).length) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.TOO_FEW_ARGUMENTS); - return; - } - String[] values = Iterables.toArray(split, String.class); - npcType.updateCustomization(foundNPC, methodName, values); - foundNPC.getNpcPojo().getCustomizationMap().put(methodName, values); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } else { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.METHOD_NOT_FOUND); - for (Map.Entry method : npcType.getCustomizationLoader().getMethods().entrySet()) - sender.sendMessage(ChatColor.YELLOW + method.getKey() + " " + SPACE_JOINER.join(method.getValue().getParameterTypes())); - } - } - - @CommandInformation(arguments = {"set", "create", "exit", "path", "list"}, name = "path", isMultiple = true, permission = "znpcs.cmd.path", help = {" &f&l* &e/znpcs path create name", " &f&l* &e/znpcs path set name"}) - public void path(CommandSender sender, Map args) { - if (args.size() < 1) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - ZUser znpcUser = ZUser.find(sender.getPlayer()); - if (znpcUser == null) - return; - if (args.containsKey("set")) { - List split = SPACE_SPLITTER.splitToList(args.get("set")); - if (split.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.PATH_SET_INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(split.get(0)); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - foundNPC.setPath(NPCPath.AbstractTypeWriter.find(split.get(1))); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } else if (args.containsKey("create")) { - String pathName = args.get("create"); - if (pathName.length() < 3 || pathName.length() > 16) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NAME_LENGTH); - return; - } - if (NPCPath.AbstractTypeWriter.find(pathName) != null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.PATH_FOUND); - return; - } - if (znpcUser.isHasPath()) { - sender.getPlayer().sendMessage(ChatColor.RED + "You already have a path creator active! To remove it, type " + ChatColor.WHITE + "/znpcs path exit" + ChatColor.RED + "."); - return; - } - NPCPath.AbstractTypeWriter.forCreation(pathName, znpcUser, NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.PATH_START); - } else if (args.containsKey("exit")) { - znpcUser.setHasPath(false); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.EXIT_PATH); - } else if (args.containsKey("list")) { - if (NPCPath.AbstractTypeWriter.getPaths().isEmpty()) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_PATH_FOUND); - } else { - NPCPath.AbstractTypeWriter.getPaths().forEach(path -> sender.getPlayer().sendMessage(ChatColor.GREEN + path.getName())); - } - } - } - - @CommandInformation(arguments = {"id"}, name = "teleport", permission = "znpcs.cmd.teleport", help = {" &f&l* &e/znpcs teleport "}) - public void teleport(CommandSender sender, Map args) { - if (args.size() < 1) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - sender.getPlayer().teleport(foundNPC.getLocation()); - } - - @CommandInformation(arguments = {"id", "height"}, name = "height", permission = "znpcs.cmd.height", help = {" &f&l* &e/znpcs height 2", "&8Set a greater or lesser distance of a hologram from the NPC."}) - public void changeHologramHeight(CommandSender sender, Map args) { - if (args.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(args.get("id")); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - Double givenHeight = Doubles.tryParse(args.get("height")); - if (givenHeight == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - foundNPC.getNpcPojo().setHologramHeight(givenHeight); - foundNPC.getHologram().createHologram(); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - - @CommandInformation(arguments = {"create", "remove", "gui", "set"}, name = "conversation", isMultiple = true, permission = "znpcs.cmd.conversation", help = {" &f&l* &e/znpcs conversation create first", " &f&l* &e/znpcs conversation remove first", " &f&l* &e/znpcs conversation set first [CLICK/RADIUS]", " &f&l* &e/znpcs conversation gui &8(&7Opens a GUI to manage conversations&8)", "&8RADIUS: &7Activates when the player is near the NPC", "&8CLICK: &7Activates when the player interacts with the NPC"}) - public void conversations(CommandSender sender, Map args) { - if (args.size() < 1) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE); - return; - } - if (args.containsKey("create")) { - String conversationName = args.get("create"); - if (Conversation.exists(conversationName)) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.CONVERSATION_FOUND); - return; - } - if (conversationName.length() < 3 || conversationName.length() > 16) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NAME_LENGTH); - return; - } - ConfigurationConstants.NPC_CONVERSATIONS.add(new Conversation(conversationName)); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } else if (args.containsKey("remove")) { - String conversationName = args.get("remove"); - if (!Conversation.exists(conversationName)) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_CONVERSATION_FOUND); - return; - } - ConfigurationConstants.NPC_CONVERSATIONS.remove(Conversation.forName(conversationName)); - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } else if (args.containsKey("gui")) { - sender.getPlayer().openInventory((new ConversationGUI(sender.getPlayer())).build()); - } else if (args.containsKey("set")) { - List split = SPACE_SPLITTER.splitToList(args.get("set")); - if (split.size() < 2) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.CONVERSATION_SET_INCORRECT_USAGE); - return; - } - Integer id = Ints.tryParse(split.get(0)); - if (id == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER); - return; - } - NPC foundNPC = NPC.find(id); - if (foundNPC == null) { - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND); - return; - } - String conversationName = split.get(1); - if (Conversation.exists(conversationName)) { - foundNPC.getNpcPojo().setConversation(new ConversationModel(conversationName, (split.size() > 1) ? split.get(2) : "CLICK")); - } else { - foundNPC.getNpcPojo().setConversation(null); - } - Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS); - } - } - - interface SkinFunction { - void apply(Player param1Player, NPC param1NPC, String param1String); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/inventory/ConversationGUI.java b/src/main/java/io/github/znetworkw/znpcservers/commands/list/inventory/ConversationGUI.java index 5323284..d1ead88 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/inventory/ConversationGUI.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/list/inventory/ConversationGUI.java @@ -2,28 +2,9 @@ package io.github.znetworkw.znpcservers.commands.list.inventory; import com.google.common.base.Joiner; import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; -import com.google.common.primitives.Ints; -import io.github.znetworkw.znpcservers.configuration.Configuration; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.configuration.ConfigurationValue; -import io.github.znetworkw.znpcservers.npc.NPCAction; -import io.github.znetworkw.znpcservers.npc.conversation.Conversation; -import io.github.znetworkw.znpcservers.npc.conversation.ConversationKey; -import io.github.znetworkw.znpcservers.user.EventService; -import io.github.znetworkw.znpcservers.user.ZUser; -import io.github.znetworkw.znpcservers.utility.Utils; import io.github.znetworkw.znpcservers.utility.inventory.ZInventory; import io.github.znetworkw.znpcservers.utility.inventory.ZInventoryPage; -import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackBuilder; -import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.player.AsyncPlayerChatEvent; - -import java.util.Collections; -import java.util.List; public class ConversationGUI extends ZInventory { private static final Splitter SPACE_SPLITTER = Splitter.on(" "); @@ -34,8 +15,16 @@ public class ConversationGUI extends ZInventory { this.setCurrentPage(new MainPage(this)); } - @SuppressWarnings({"UnstableApiUsage", "deprecation"}) static class MainPage extends ZInventoryPage { + public MainPage(ZInventory inventory) { + super(inventory, "Conversations", 6); + } + + @Override + public void update() { + + } + /* int pageID = 1; @@ -79,7 +68,7 @@ public class ConversationGUI extends ZInventory { this.addItem(ItemStackBuilder.forMaterial(Material.PAPER).setName(ChatColor.GREEN + conversation.getName()).setLore("&7this conversation has &b" + conversation.getTexts().size() + " &7texts,", "&7it will activate when a player is on a &b" + conversation.getRadius() + "x" + conversation.getRadius() + " &7radius,", "&7or when a player interacts with an npc.", "&7when the conversation is finish, there is a &b" + conversation.getDelay() + "s &7delay to start again.", "&f&lUSES", " &bLeft-click &7to manage texts.", " &bRight-click &7to add a new text.", " &bQ &7to change the radius.", " &bMiddle-click &7to change the cooldown.").build(), i - ((getRows() - 9) * (pageID - 1)), clickEvent -> { if (clickEvent.getClick() == ClickType.DROP) { Utils.sendTitle(this.getPlayer(), "&b&lCHANGE RADIUS", "&7Type the new radius..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) { Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND); } else { @@ -96,7 +85,7 @@ public class ConversationGUI extends ZInventory { }).addConsumer(event -> this.openInventory()); } else if (clickEvent.isRightClick()) { Utils.sendTitle(this.getPlayer(), "&e&lADD LINE", "&7Type the new line..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) { Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND); } else { @@ -108,7 +97,7 @@ public class ConversationGUI extends ZInventory { new EditConversationPage(this.getInventory(), conversation).openInventory(); } else if (clickEvent.getClick() == ClickType.MIDDLE) { Utils.sendTitle(this.getPlayer(), "&6&lCHANGE COOLDOWN", "&7Type the new cooldown..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) { Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND); } else { @@ -182,7 +171,7 @@ public class ConversationGUI extends ZInventory { } this.addItem(ItemStackBuilder.forMaterial(Material.EMERALD).setName(ChatColor.AQUA + "ADD A NEW ACTION").setLore("&7click here...").build(), this.getRows() - 5, clickEvent -> { Utils.sendTitle(this.getPlayer(), "&d&lADD ACTION", "&7Type the new action..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(this.conversationKey)) { List stringList = SPACE_SPLITTER.splitToList(event.getMessage()); if (stringList.size() < 2) { @@ -199,7 +188,7 @@ public class ConversationGUI extends ZInventory { } } - @SuppressWarnings({"deprecation", "UnstableApiUsage"}) + @SuppressWarnings({"UnstableApiUsage"}) static class EditConversationPage extends ZInventoryPage { private final Conversation conversation; @@ -240,7 +229,7 @@ public class ConversationGUI extends ZInventory { this.addItem(ItemStackBuilder.forMaterial(Material.NAME_TAG).setName(ChatColor.AQUA + conversationKey.getTextFormatted() + "....").setLore("&7this conversation text has a delay of &b" + conversationKey.getDelay() + "s &7to be executed,", "&7the sound for the text is &b" + (conversationKey.getSoundName() == null ? "NONE" : conversationKey.getSoundName()) + "&7,", "&7before sending the text there is a delay of &b" + conversationKey.getDelay() + "s", "&7the index for the text is &b" + i + "&7,", "&7and the conversation has currently &b" + conversationKey.getActions().size() + " actions&7.", "&f&lUSES", " &bLeft-click &7to change the position.", " &bRight-click &7to remove text.", " &bLeft-Shift-click &7to change the sound.", " &bMiddle-click &7to change the delay.", " &bRight-Shift-click &7to edit the text.", " &bQ &7to manage actions.").build(), i, clickEvent -> { if (clickEvent.getClick() == ClickType.SHIFT_LEFT) { Utils.sendTitle(this.getPlayer(), "&c&lCHANGE SOUND", "&7Type the new sound..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { String sound = event.getMessage().trim(); conversationKey.setSoundName(sound); @@ -251,7 +240,7 @@ public class ConversationGUI extends ZInventory { }).addConsumer(event -> this.openInventory()); } else if (clickEvent.getClick() == ClickType.SHIFT_RIGHT) { Utils.sendTitle(this.getPlayer(), "&a&lEDIT TEXT", "&7Type the new text..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { conversationKey.getLines().clear(); conversationKey.getLines().addAll(SPACE_SPLITTER.splitToList(event.getMessage())); @@ -262,7 +251,7 @@ public class ConversationGUI extends ZInventory { }).addConsumer(event -> this.openInventory()); } else if (clickEvent.isLeftClick()) { Utils.sendTitle(this.getPlayer(), "&e&lCHANGE POSITION &a>=0&c<=" + this.conversation.getTexts().size(), "&7Type the new position..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { Integer position = Ints.tryParse(event.getMessage()); if (position == null) { @@ -283,7 +272,7 @@ public class ConversationGUI extends ZInventory { this.openInventory(); } else if (clickEvent.getClick() == ClickType.MIDDLE) { Utils.sendTitle(this.getPlayer(), "&d&lCHANGE DELAY", "&7Type the new delay..."); - EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { + EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { Integer delay = Ints.tryParse(event.getMessage()); if (delay == null) { @@ -310,5 +299,6 @@ public class ConversationGUI extends ZInventory { return super.getPageName() + " - " + pageID + "/" + (int) (Math.ceil((double) conversation.getTexts().size() / (double) 45)); } } + */ } } diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java index c0d7811..6b7500b 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java +++ b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java @@ -1,23 +1,8 @@ package io.github.znetworkw.znpcservers.configuration; -import io.github.znetworkw.znpcservers.npc.NPCModel; -import io.github.znetworkw.znpcservers.npc.conversation.Conversation; - -import java.util.List; - public final class ConfigurationConstants { public static final String SPACE_SYMBOL = Configuration.CONFIGURATION.getValue(ConfigurationValue.REPLACE_SYMBOL); public static final boolean DEBUG_ENABLED = Configuration.CONFIGURATION.getValue(ConfigurationValue.DEBUG_ENABLED); public static final int VIEW_DISTANCE = Configuration.CONFIGURATION.getValue(ConfigurationValue.VIEW_DISTANCE); - public static final int SAVE_DELAY = Configuration.CONFIGURATION.getValue(ConfigurationValue.SAVE_NPCS_DELAY_SECONDS); - public static final boolean RGB_ANIMATION = Configuration.CONFIGURATION.getValue(ConfigurationValue.ANIMATION_RGB); - public static final List NPC_LIST = Configuration.DATA.getValue(ConfigurationValue.NPC_LIST); - public static final List NPC_CONVERSATIONS = Configuration.CONVERSATIONS.getValue(ConfigurationValue.CONVERSATION_LIST); public static final boolean CHECK_FOR_UPDATES = Configuration.CONFIGURATION.getValue(ConfigurationValue.CHECK_FOR_UPDATES); - - static { - NPC_LIST.stream() - .map(io.github.znetworkw.znpcservers.npc.NPC::new) - .forEach(io.github.znetworkw.znpcservers.npc.task.NPCLoadTask::new); - } } diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java index 1ed63e9..b14cfef 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java +++ b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java @@ -1,23 +1,17 @@ package io.github.znetworkw.znpcservers.configuration; import com.google.common.collect.ImmutableSet; -import io.github.znetworkw.znpcservers.npc.NPCModel; -import io.github.znetworkw.znpcservers.npc.NamingType; -import io.github.znetworkw.znpcservers.npc.conversation.Conversation; import io.github.znetworkw.znpcservers.utility.GuavaCollectors; -import java.util.ArrayList; import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; public enum ConfigurationValue { - NPC_LIST("data", new ArrayList<>(), NPCModel.class), VIEW_DISTANCE("config", 32, Integer.class), REPLACE_SYMBOL("config", "-", String.class), SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class), MAX_PATH_LOCATIONS("config", 500, Integer.class), - NAMING_METHOD("config", NamingType.DEFAULT, NamingType.class), DEBUG_ENABLED("config", false, Boolean.class), LINE_SPACING("config", 0.3D, Double.class), ANIMATION_RGB("config", false, Boolean.class), @@ -51,8 +45,7 @@ public enum ConfigurationValue { FETCHING_SKIN("messages", "&aFetching skin for name: &f%s&a. Please wait...", String.class), CANT_GET_SKIN("messages", "&cCould not fetch skin for name: %s.", String.class), GET_SKIN("messages", "&aSkin successfully fetched!", String.class), - NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class), - CONVERSATION_LIST("conversations" /* Leave this lowercase or it will break */, new ArrayList<>(), Conversation.class); + NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class); public static final Map> VALUES_BY_NAME; diff --git a/src/main/java/io/github/znetworkw/znpcservers/exception/ChannelRegistrationException.java b/src/main/java/io/github/znetworkw/znpcservers/exception/ChannelRegistrationException.java deleted file mode 100644 index c6b62eb..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/exception/ChannelRegistrationException.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.znetworkw.znpcservers.exception; - -import com.google.common.collect.ImmutableList; - -import java.util.List; - -public class ChannelRegistrationException extends Throwable { - private final Throwable throwable; - private final List channelNames; - - public ChannelRegistrationException(Throwable t, List channelNames) { - this.throwable = t; - this.channelNames = new ImmutableList.Builder().addAll(channelNames).build(); - } - - public Throwable getThrowable() { - return throwable; - } - - public List getChannelNames() { - return channelNames; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/hologram/Hologram.java b/src/main/java/io/github/znetworkw/znpcservers/hologram/Hologram.java deleted file mode 100644 index 1b9d3a7..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/hologram/Hologram.java +++ /dev/null @@ -1,133 +0,0 @@ -package io.github.znetworkw.znpcservers.hologram; - -import com.github.retrooper.packetevents.PacketEvents; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities; -import io.github.znetworkw.znpcservers.UnexpectedCallException; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.configuration.Configuration; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.configuration.ConfigurationValue; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.hologram.replacer.LineReplacer; -import io.github.znetworkw.znpcservers.user.ZUser; -import io.github.znetworkw.znpcservers.utility.Utils; -import org.bukkit.Location; - -import javax.annotation.Nullable; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; - -public class Hologram { - private static final boolean NEW_METHOD = (Utils.BUKKIT_VERSION > 12); - private static final double LINE_SPACING = Configuration.CONFIGURATION.getValue(ConfigurationValue.LINE_SPACING); - private final List hologramLines = new ArrayList<>(); - private final NPC npc; - - public Hologram(NPC npc) { - this.npc = npc; - } - - public void createHologram() { - this.npc.getViewers().forEach(this::delete); - try { - this.hologramLines.clear(); - double y = 0.0D; - Location location = this.npc.getLocation(); - for (String line : this.npc.getNpcPojo().getHologramLines()) { - boolean visible = !line.equalsIgnoreCase("%space%"); - Object armorStand = Reflections.ENTITY_CONSTRUCTOR.get().newInstance(Reflections.GET_HANDLE_WORLD_METHOD.get().invoke(location.getWorld()), - location.getX(), location.getY() - 0.15D + y, location.getZ()); - if (visible) { - Reflections.SET_CUSTOM_NAME_VISIBLE_METHOD.get().invoke(armorStand, true); - updateLine(line, armorStand, null); - } - Reflections.SET_INVISIBLE_METHOD.get().invoke(armorStand, true); - this.hologramLines.add(new HologramLine(line.replace(ConfigurationConstants.SPACE_SYMBOL, " "), armorStand, (Integer) Reflections.GET_ENTITY_ID - .get().invoke(armorStand))); - y += LINE_SPACING; - } - setLocation(location, 0.0D); - this.npc.getPackets().flushCache("createArmorStandSpawnPacket"); - this.npc.getViewers().forEach(this::spawn); - } catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - - public void spawn(ZUser user) { - this.hologramLines.forEach(hologramLine -> { - try { - Object entityPlayerPacketSpawn = this.npc.getPackets().getNms().createArmorStandSpawnPacket(hologramLine.armorStand); - Utils.sendPackets(user, entityPlayerPacketSpawn); - } catch (ReflectiveOperationException operationException) { - delete(user); - } - }); - } - - public void delete(ZUser user) { - this.hologramLines.forEach(hologramLine -> PacketEvents.getAPI().getPlayerManager().sendPacket(user.toPlayer(), new WrapperPlayServerDestroyEntities(hologramLine.id))); - } - - public void updateNames(ZUser user) { - for (HologramLine hologramLine : this.hologramLines) { - try { - updateLine(hologramLine.line, hologramLine.armorStand, user); - Object metaData = this.npc.getPackets().getNms().createMetadataPacket(hologramLine.id, hologramLine.armorStand); - Utils.sendPackets(user, metaData); - } catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - } - - public void updateLocation() { - this.hologramLines.forEach(hologramLine -> { - try { - Object packet = Reflections.PACKET_PLAY_OUT_ENTITY_TELEPORT_CONSTRUCTOR.get().newInstance(hologramLine.armorStand); - this.npc.getViewers().forEach(player -> Utils.sendPackets(player, packet)); - } - catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - }); - } - - public void setLocation(Location location, double height) { - location = location.clone().add(0.0, height, 0.0); - try { - double y = this.npc.getNpcPojo().getHologramHeight(); - for (HologramLine hologramLine : this.hologramLines) { - Reflections.SET_LOCATION_METHOD.get().invoke(hologramLine.armorStand, location.getX(), location.getY() - 0.15 + y, location.getZ(), location.getYaw(), location.getPitch()); - y += LINE_SPACING; - } - this.updateLocation(); - } - catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - - private void updateLine(String line, Object armorStand, @Nullable ZUser user) throws InvocationTargetException, IllegalAccessException { - if (NEW_METHOD) { - Reflections.SET_CUSTOM_NAME_NEW_METHOD.get().invoke(armorStand, Reflections.CRAFT_CHAT_MESSAGE_METHOD.get().invoke(null, LineReplacer.makeAll(user, line))); - } else { - Reflections.SET_CUSTOM_NAME_OLD_METHOD.get().invoke(armorStand, LineReplacer.makeAll(user, line)); - } - } - - private static class HologramLine { - private final String line; - - private final Object armorStand; - - private final int id; - - protected HologramLine(String line, Object armorStand, int id) { - this.line = line; - this.armorStand = armorStand; - this.id = id; - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/LineReplacer.java b/src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/LineReplacer.java deleted file mode 100644 index e2944ba..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/LineReplacer.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.znetworkw.znpcservers.hologram.replacer; - -import com.google.common.collect.ImmutableList; -import io.github.znetworkw.znpcservers.user.ZUser; -import io.github.znetworkw.znpcservers.utility.Utils; - -public interface LineReplacer { - ImmutableList LINE_REPLACERS = ImmutableList.of(new RGBLine()); - - static String makeAll(ZUser user, String string) { - for (LineReplacer lineReplacer : LINE_REPLACERS) { - if (!lineReplacer.isSupported()) continue; - string = lineReplacer.make(string); - } - return Utils.toColor((Utils.PLACEHOLDER_SUPPORT && user != null) ? Utils.getWithPlaceholders(string, user.toPlayer()) : string); - } - - String make(String paramString); - - boolean isSupported(); -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/RGBLine.java b/src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/RGBLine.java deleted file mode 100644 index 13efc89..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/hologram/replacer/RGBLine.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.github.znetworkw.znpcservers.hologram.replacer; - -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.utility.Utils; -import net.md_5.bungee.api.ChatColor; - -import java.util.concurrent.ThreadLocalRandom; - -public class RGBLine implements LineReplacer { - public String make(String string) { - String rgbString = string; - for (int i = 0; i < rgbString.length(); i++) { - char charAt = rgbString.charAt(i); - if (charAt == '#') { - int endIndex = i + 6 + 1; - boolean success = true; - StringBuilder hexCodeStringBuilder = new StringBuilder(); - for (int i2 = i; i2 < endIndex; i2++) { - if (rgbString.length() - 1 < i2) { - success = false; - break; - } - char hexCode = rgbString.charAt(i2); - hexCodeStringBuilder.append((ConfigurationConstants.RGB_ANIMATION && hexCode != '#') ? Integer.toHexString(ThreadLocalRandom.current().nextInt(16)) : Character.valueOf(hexCode)); - } - if (success) try { - rgbString = rgbString.substring(0, i) + ChatColor.of(hexCodeStringBuilder.toString()) + rgbString.substring(endIndex); - } catch (Exception ignored) {} - } - } - return rgbString; - } - - public boolean isSupported() { - return (Utils.BUKKIT_VERSION > 15); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/listeners/PlayerListener.java b/src/main/java/io/github/znetworkw/znpcservers/listeners/PlayerListener.java deleted file mode 100644 index 6e2a168..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/listeners/PlayerListener.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.znetworkw.znpcservers.listeners; - -import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel; -import io.github.znetworkw.znpcservers.npc.interaction.NPCInteractEvent; -import io.github.znetworkw.znpcservers.user.EventService; -import io.github.znetworkw.znpcservers.user.ZUser; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.plugin.Plugin; - -public class PlayerListener implements Listener { - public PlayerListener(Plugin serversNPC) { - serversNPC.getServer().getPluginManager().registerEvents(this, serversNPC); - } - - @EventHandler - public void onJoin(PlayerJoinEvent event) { - ZUser.find(event.getPlayer()); - } - - @EventHandler - public void onQuit(PlayerQuitEvent event) { - ZUser.unregister(event.getPlayer()); - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void onTalk(AsyncPlayerChatEvent event) { - ZUser zUser = ZUser.find(event.getPlayer()); - if (EventService.hasService(zUser, AsyncPlayerChatEvent.class)) { - event.setCancelled(true); - EventService eventService = EventService.findService(zUser, AsyncPlayerChatEvent.class); - eventService.runAll(event); - zUser.getEventServices().remove(eventService); - } - } - - @EventHandler - public void onConversation(NPCInteractEvent event) { - ConversationModel conversationStorage = event.getNpc().getNpcPojo().getConversation(); - if (conversationStorage == null || conversationStorage.getConversationType() != ConversationModel.ConversationType.CLICK) return; - event.getNpc().tryStartConversation(event.getPlayer()); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/NMS.java b/src/main/java/io/github/znetworkw/znpcservers/nms/NMS.java deleted file mode 100644 index e748853..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/NMS.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import com.google.common.collect.ImmutableList; -import com.mojang.authlib.GameProfile; -import io.github.znetworkw.znpcservers.npc.FunctionFactory; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.NPCType; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.utility.ReflectionUtils; -import io.github.znetworkw.znpcservers.utility.Utils; - -import java.util.Collection; - -public interface NMS { - int version(); - - @PacketValue(keyName = "playerPacket") - Object createPlayer(Object paramObject, GameProfile paramGameProfile) throws ReflectiveOperationException; - - Object createMetadataPacket(int paramInt, Object paramObject) throws ReflectiveOperationException; - - @PacketValue(keyName = "hologramSpawnPacket", valueType = ValueType.ARGUMENTS) - Object createArmorStandSpawnPacket(Object paramObject) throws ReflectiveOperationException; - - @SuppressWarnings("unchecked") - @PacketValue(keyName = "scoreboardPackets") - default ImmutableList updateScoreboard(NPC npc) throws ReflectiveOperationException { - ImmutableList.Builder builder = ImmutableList.builder(); - boolean isVersion17 = (Utils.BUKKIT_VERSION > 16); - boolean isVersion9 = (Utils.BUKKIT_VERSION > 8); - Object scoreboardTeamPacket = isVersion17 ? Reflections.SCOREBOARD_TEAM_CONSTRUCTOR.get().newInstance(null, npc.getGameProfile().getName()) : Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CONSTRUCTOR_OLD.get().newInstance(); - if (!isVersion17) { - Utils.setValue(scoreboardTeamPacket, "a", npc.getGameProfile().getName()); - Utils.setValue(scoreboardTeamPacket, isVersion9 ? "i" : "h", 1); - } - builder.add(isVersion17 ? Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CREATE_V1.get().invoke(null, scoreboardTeamPacket) : scoreboardTeamPacket); - if (isVersion17) { - scoreboardTeamPacket = Reflections.SCOREBOARD_TEAM_CONSTRUCTOR.get().newInstance(null, npc.getGameProfile().getName()); - if (Utils.BUKKIT_VERSION > 17) { - Utils.setValue(scoreboardTeamPacket, "d", npc.getGameProfile().getName()); - ReflectionUtils.findFieldForClassAndSet(scoreboardTeamPacket, Reflections.ENUM_TAG_VISIBILITY, Reflections.ENUM_TAG_VISIBILITY_NEVER_FIELD.get()); - Utils.setValue(scoreboardTeamPacket, "m", Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, "DARK_GRAY")); - } else { - Utils.setValue(scoreboardTeamPacket, "e", npc.getGameProfile().getName()); - Utils.setValue(scoreboardTeamPacket, "l", Reflections.ENUM_TAG_VISIBILITY_NEVER_FIELD.get()); - } - } else { - scoreboardTeamPacket = Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CONSTRUCTOR_OLD.get().newInstance(); - Utils.setValue(scoreboardTeamPacket, "a", npc.getGameProfile().getName()); - Utils.setValue(scoreboardTeamPacket, "e", "never"); - Utils.setValue(scoreboardTeamPacket, isVersion9 ? "i" : "h", 0); - } - Collection collection = isVersion17 ? (Collection) Reflections.SCOREBOARD_PLAYER_LIST.get().invoke(scoreboardTeamPacket) : (Collection) Utils.getValue(scoreboardTeamPacket, isVersion9 ? "h" : "g"); - if (npc.getNpcPojo().getNpcType() == NPCType.PLAYER) { - collection.add(npc.getGameProfile().getName()); - } else { - collection.add(npc.getUUID().toString()); - } - if (allowsGlowColor() && FunctionFactory.isTrue(npc, "glow")) - updateGlow(npc, scoreboardTeamPacket); - builder.add(isVersion17 ? Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CREATE.get().invoke(null, scoreboardTeamPacket, Boolean.TRUE) : scoreboardTeamPacket); - return builder.build(); - } - - void updateGlow(NPC paramNPC, Object paramObject) throws ReflectiveOperationException; - - boolean allowsGlowColor(); - - default void update(PacketCache packetCache) throws ReflectiveOperationException { - packetCache.flushCache("scoreboardPackets"); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSFactory.java b/src/main/java/io/github/znetworkw/znpcservers/nms/NMSFactory.java deleted file mode 100644 index 2435785..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import com.google.common.collect.ImmutableSet; -import io.github.znetworkw.znpcservers.utility.Utils; - -import java.util.Comparator; - -public final class NMSFactory { - public static final ImmutableSet ALL = ImmutableSet.of(new NMSV8(), new NMSV9(), new NMSV17(), new NMSV18(), new NMSV19()); - - public static final NMS NMS_FOR_CURRENT_VERSION = findPacketForVersion(Utils.BUKKIT_VERSION); - - public static NMS findPacketForVersion(int version) { - return ALL.stream() - .filter(NMS -> (version >= NMS.version())) - .max(Comparator.comparing(NMS::version)) - .orElseThrow(() -> new IllegalArgumentException("No NMS instance found for version: " + version)); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV17.java b/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV17.java deleted file mode 100644 index b89a167..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV17.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import com.mojang.authlib.GameProfile; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.utility.Utils; -import org.bukkit.Bukkit; - -public class NMSV17 extends NMSV9 { - public int version() { - return 17; - } - - public Object createPlayer(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException { - return Reflections.PLAYER_CONSTRUCTOR_NEW.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile); - } - - public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException { - Utils.setValue(packet, "n", Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, npc.getNpcPojo().getGlowName())); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV18.java b/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV18.java deleted file mode 100644 index be611db..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV18.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.utility.Utils; - -public class NMSV18 extends NMSV17 { - public int version() { - return 18; - } - - public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException { - Utils.setValue(packet, "m", Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, npc.getNpcPojo().getGlowName())); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV19.java b/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV19.java deleted file mode 100644 index 730e7fd..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV19.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import com.mojang.authlib.GameProfile; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import org.bukkit.Bukkit; - -public class NMSV19 extends NMSV18 { - public int version() { - return 19; - } - - public Object createPlayer(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException { - try { - return Reflections.PLAYER_CONSTRUCTOR_NEW_1.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile, null); - } catch (Throwable e) { - return Reflections.PLAYER_CONSTRUCTOR_NEW_2.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile); - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV8.java b/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV8.java deleted file mode 100644 index bef6d66..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV8.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import com.mojang.authlib.GameProfile; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.utility.Utils; -import org.bukkit.Bukkit; - -import java.lang.reflect.Constructor; - -public class NMSV8 implements NMS { - public int version() { - return 8; - } - - public Object createPlayer(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException { - Constructor constructor = (Utils.BUKKIT_VERSION > 13) ? Reflections.PLAYER_INTERACT_MANAGER_NEW_CONSTRUCTOR.get() : Reflections.PLAYER_INTERACT_MANAGER_OLD_CONSTRUCTOR.get(); - return Reflections.PLAYER_CONSTRUCTOR_OLD.get().newInstance(Reflections.GET_SERVER_METHOD - .get().invoke(Bukkit.getServer()), nmsWorld, gameProfile, constructor.newInstance(nmsWorld)); - } - - public Object createMetadataPacket(int entityId, Object nmsEntity) throws ReflectiveOperationException { - Object dataWatcher = Reflections.GET_DATA_WATCHER_METHOD.get().invoke(nmsEntity); - try { - return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR.get().newInstance(entityId, dataWatcher, true); - } catch (Exception e2) { - return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1.get().newInstance(entityId, Reflections.GET_DATAWATCHER_B_LIST.get().invoke(dataWatcher)); - } - } - - public Object createArmorStandSpawnPacket(Object armorStand) throws ReflectiveOperationException { - return Reflections.PACKET_PLAY_OUT_SPAWN_ENTITY_CONSTRUCTOR.get().newInstance(armorStand); - } - - public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException { - throw new IllegalStateException("Glow color is not supported for 1.8 version."); - } - - public boolean allowsGlowColor() { - return false; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV9.java b/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV9.java deleted file mode 100644 index 4878c91..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/NMSV9.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.utility.Utils; - -public class NMSV9 extends NMSV8 { - public int version() { - return 9; - } - - public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException { - Object enumChatString = Reflections.ENUM_CHAT_TO_STRING_METHOD.get().invoke(npc.getGlowColor()); - if (Utils.BUKKIT_VERSION > 12) { - Utils.setValue(packet, npc.getGlowColor(), Reflections.ENUM_CHAT_CLASS); - Utils.setValue(packet, "c", Reflections.I_CHAT_BASE_COMPONENT_A_CONSTRUCTOR.get().newInstance(enumChatString)); - } else { - Utils.setValue(packet, "g", Reflections.GET_ENUM_CHAT_ID_METHOD.get().invoke(npc.getGlowColor())); - Utils.setValue(packet, "c", enumChatString); - } - } - - public boolean allowsGlowColor() { - return true; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/PacketCache.java b/src/main/java/io/github/znetworkw/znpcservers/nms/PacketCache.java deleted file mode 100644 index 52fd94f..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/PacketCache.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import com.google.common.collect.ImmutableMap; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -@SuppressWarnings("unused") -public class PacketCache { - protected static final ImmutableMap VALUE_LOOKUP_BY_NAME; - - static { - ImmutableMap.Builder methodPacketValueBuilder = ImmutableMap.builder(); - for (Method method : NMS.class.getMethods()) { - if (method.isAnnotationPresent(PacketValue.class)) - methodPacketValueBuilder.put(method, method.getAnnotation(PacketValue.class)); - } - VALUE_LOOKUP_BY_NAME = methodPacketValueBuilder.build(); - } - - private final Map packetResultCache = new ConcurrentHashMap<>(); - - private final NMS nms; - - public PacketCache(NMS NMS) { - this.nms = newNMSInstance(NMS); - } - - public PacketCache() { - this(NMSFactory.NMS_FOR_CURRENT_VERSION); - } - - public NMS getNms() { - return this.nms; - } - - protected NMS newNMSInstance(NMS NMS) { - return (NMS) Proxy.newProxyInstance(NMS - .getClass().getClassLoader(), new Class[]{NMS.class}, new PacketHandler(this, NMS)); - } - - private Object getOrCache(NMS instance, Method method, Object[] args) { - if (!VALUE_LOOKUP_BY_NAME.containsKey(method)) - throw new IllegalStateException("value not found for method: " + method.getName()); - PacketValue packetValue = VALUE_LOOKUP_BY_NAME.get(method); - assert packetValue != null; - String keyString = packetValue.valueType().resolve(packetValue.keyName(), args); - return this.packetResultCache.computeIfAbsent(keyString, o -> { - try { - return method.invoke(instance, args); - } catch (InvocationTargetException | IllegalAccessException operationException) { - throw new AssertionError("can't invoke method: " + method.getName(), operationException); - } - }); - } - - public void flushCache(String... strings) { - Set> set = this.packetResultCache.entrySet(); - for (String string : strings) - set.removeIf(entry -> entry.getKey().startsWith(string)); - } - - public void flushCache() { - flushCache(VALUE_LOOKUP_BY_NAME.values().stream() - .map(PacketValue::keyName).toArray(String[]::new)); - } - - private static class PacketHandler implements InvocationHandler { - private final PacketCache packetCache; - - private final NMS packets; - - public PacketHandler(PacketCache packetCache, NMS packets) { - this.packetCache = packetCache; - this.packets = packets; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (PacketCache.VALUE_LOOKUP_BY_NAME.containsKey(method)) - return this.packetCache.getOrCache(this.packets, method, args); - return method.invoke(this.packets, args); - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/PacketValue.java b/src/main/java/io/github/znetworkw/znpcservers/nms/PacketValue.java deleted file mode 100644 index 25994ab..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/PacketValue.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface PacketValue { - String keyName(); - - ValueType valueType() default ValueType.DEFAULT; -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/nms/ValueType.java b/src/main/java/io/github/znetworkw/znpcservers/nms/ValueType.java deleted file mode 100644 index c9437c4..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/nms/ValueType.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.znetworkw.znpcservers.nms; - -import java.util.Arrays; - -public enum ValueType { - ARGUMENTS { - String resolve(String keyName, Object[] args) { - if (args.length == 0) - throw new IllegalArgumentException("invalid size, must be > 0"); - return keyName + Arrays.hashCode(args); - } - }, - DEFAULT { - String resolve(String keyName, Object[] args) { - return keyName; - } - }; - - abstract String resolve(String paramString, Object[] paramArrayOfObject); -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/CustomizationLoader.java b/src/main/java/io/github/znetworkw/znpcservers/npc/CustomizationLoader.java deleted file mode 100644 index d18a625..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/CustomizationLoader.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import com.google.common.collect.Iterables; -import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; -import io.github.znetworkw.znpcservers.reflection.ReflectionPackage; -import io.github.znetworkw.znpcservers.reflection.types.EnumReflection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -public class CustomizationLoader { - private final Class entityClass; - private final Map methods; - - public CustomizationLoader(EntityType entityType, Iterable methodsName) { - this(entityType.getEntityClass(), methodsName); - } - - protected CustomizationLoader(Class entityClass, Iterable methodsName) { - this.entityClass = entityClass; - this.methods = loadMethods(methodsName); - } - - protected Map loadMethods(Iterable iterable) { - Map builder = new HashMap<>(); - for (Method method : this.entityClass.getMethods()) { - if (builder.containsKey(method.getName()) || !Iterables.contains(iterable, method.getName())) continue; - for (Class parameter : method.getParameterTypes()) { - PrimitivePropertyType primitivePropertyType = PrimitivePropertyType.forType(parameter); - if (primitivePropertyType != null || !parameter.isEnum()) continue; - new EnumReflection(new ReflectionBuilder(ReflectionPackage.MINECRAFT).withClassName(parameter)).get(); - } - builder.put(method.getName(), method); - } - return builder; - } - - public boolean contains(String name) { - return this.methods.containsKey(name); - } - - public Map getMethods() { - return this.methods; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/FunctionContext.java b/src/main/java/io/github/znetworkw/znpcservers/npc/FunctionContext.java deleted file mode 100644 index dec0bdd..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/FunctionContext.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -public interface FunctionContext { - NPC getNPC(); - - interface WithValue extends FunctionContext { - String getValue(); - } - - class DefaultContext implements FunctionContext { - private final NPC npc; - - public DefaultContext(NPC npc) { - this.npc = npc; - } - - public NPC getNPC() { - return this.npc; - } - } - - class ContextWithValue extends DefaultContext implements WithValue { - private final String value; - - public ContextWithValue(NPC npc, String value) { - super(npc); - this.value = value; - } - - public String getValue() { - return this.value; - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/FunctionFactory.java b/src/main/java/io/github/znetworkw/znpcservers/npc/FunctionFactory.java deleted file mode 100644 index 4713c88..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/FunctionFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.github.znetworkw.znpcservers.npc.function.GlowFunction; -import io.github.znetworkw.znpcservers.utility.GuavaCollectors; - -public final class FunctionFactory { - public static ImmutableList WITHOUT_FUNCTION = ImmutableList.of(new NPCFunction.WithoutFunction("look"), new NPCFunction.WithoutFunctionSelfUpdate("holo"), new NPCFunction.WithoutFunctionSelfUpdate("mirror")); - public static ImmutableList WITH_FUNCTION = ImmutableList.of(new GlowFunction()); - public static ImmutableList ALL = new ImmutableList.Builder().addAll(WITHOUT_FUNCTION).addAll(WITH_FUNCTION).build(); - public static ImmutableMap BY_NAME = ALL.stream().collect(GuavaCollectors.toImmutableMap(NPCFunction::getName, function -> function)); - - public static NPCFunction findFunctionForName(String name) { - return BY_NAME.get(name); - } - - public static ImmutableList findFunctionsForNpc(NPC npc) { - return ALL.stream() - .filter(function -> isTrue(npc, function)) - .collect(GuavaCollectors.toImmutableList()); - } - - public static boolean isTrue(NPC npc, NPCFunction function) { - return npc.getNpcPojo().getFunctions().getOrDefault(function.getName(), false); - } - - public static boolean isTrue(NPC npc, String function) { - return isTrue(npc, findFunctionForName(function)); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java deleted file mode 100644 index 1148672..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPC.java +++ /dev/null @@ -1,363 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import com.github.retrooper.packetevents.PacketEvents; -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.EntityDataTypes; -import com.github.retrooper.packetevents.protocol.entity.type.EntityType; -import com.github.retrooper.packetevents.protocol.player.Equipment; -import com.github.retrooper.packetevents.protocol.player.UserProfile; -import com.github.retrooper.packetevents.util.Vector3d; -import com.github.retrooper.packetevents.wrapper.PacketWrapper; -import com.github.retrooper.packetevents.wrapper.play.server.*; -import com.google.common.collect.ImmutableList; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; -import com.mojang.authlib.properties.PropertyMap; -import io.github.retrooper.packetevents.util.SpigotConversionUtil; -import io.github.znetworkw.znpcservers.UnexpectedCallException; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.hologram.Hologram; -import io.github.znetworkw.znpcservers.nms.PacketCache; -import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.user.ZUser; -import io.github.znetworkw.znpcservers.utility.Utils; -import io.github.znetworkw.znpcservers.utility.location.ZLocation; -import lol.pyr.znpcsplus.ZNPCsPlus; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public class NPC { - private static final ConcurrentMap NPC_MAP = new ConcurrentHashMap<>(); - private final Set viewers = new HashSet<>(); - private final PacketCache packets = new PacketCache(); - private final NPCModel npcPojo; - private final Hologram hologram; - private final String npcName; - private final NPCSkin npcSkin; - private long lastMove = -1L; - private int entityID; - private Object glowColor; - private Object tabConstructor; - private Object updateTabConstructor; - private Object nmsEntity; - private Object bukkitEntity; - private UUID uuid; - private GameProfile gameProfile; - private NPCPath.PathInitializer npcPath; - - public NPC(NPCModel npcModel, boolean load) { - this.npcPojo = npcModel; - this.hologram = new Hologram(this); - this.npcName = NamingType.DEFAULT.resolve(this); - this.npcSkin = NPCSkin.forValues(npcModel.getSkin(), npcModel.getSignature()); - this.uuid = npcModel.getUuid(); - if (load) onLoad(); - } - - public NPC(NPCModel npcModel) { - this(npcModel, false); - } - - public static NPC find(int id) { - return NPC_MAP.get(id); - } - - public static void unregister(int id) { - NPC npc = find(id); - if (npc == null) throw new IllegalStateException("can't find npc with id " + id); - NPC_MAP.remove(id); - npc.deleteViewers(); - } - - public static Collection all() { - return NPC_MAP.values(); - } - - public void onLoad() { - if (NPC_MAP.containsKey(getNpcPojo().getId())) throw new IllegalStateException("npc with id " + getNpcPojo().getId() + " already exists."); - this.gameProfile = new GameProfile(this.uuid, "[ZNPC] " + this.npcName); - this.gameProfile.getProperties().put("textures", new Property("textures", this.npcPojo.getSkin(), this.npcPojo.getSignature())); - if (this.npcPojo.getNpcType().getConstructor() == null && !this.npcPojo.getNpcType().equals(NPCType.PLAYER)) { - this.npcPojo.setShouldSpawn(false); - if (ConfigurationConstants.DEBUG_ENABLED) { - ZNPCsPlus.LOGGER.warning("The NPC Type " + npcPojo.getNpcType().name() + " does not exist or is not supported in this version."); - } - } else { - this.npcPojo.setShouldSpawn(true); - changeType(this.npcPojo.getNpcType()); - updateProfile(this.gameProfile.getProperties()); - setLocation(getNpcPojo().getLocation().toBukkitLocation(), false); - this.hologram.createHologram(); - if (this.npcPojo.getPathName() != null) setPath(NPCPath.AbstractTypeWriter.find(this.npcPojo.getPathName())); - this.npcPojo.getCustomizationMap().forEach((key, value) -> this.npcPojo.getNpcType().updateCustomization(this, key, value)); - } - NPC_MAP.put(getNpcPojo().getId(), this); - } - - public NPCModel getNpcPojo() { - return this.npcPojo; - } - - public UUID getUUID() { - return this.uuid; - } - - public int getEntityID() { - return this.entityID; - } - - public Object getBukkitEntity() { - return this.bukkitEntity; - } - - public Object getNmsEntity() { - return this.nmsEntity; - } - - public Object getGlowColor() { - return this.glowColor; - } - - public void setGlowColor(Object glowColor) { - this.glowColor = glowColor; - } - - public GameProfile getGameProfile() { - return this.gameProfile; - } - - public NPCPath.PathInitializer getNpcPath() { - return this.npcPath; - } - - public Hologram getHologram() { - return this.hologram; - } - - public Set getViewers() { - return this.viewers; - } - - public PacketCache getPackets() { - return this.packets; - } - - public void setLocation(Location location, boolean updateTime) { - try { - if (this.npcPath == null) { - lookAt(null, location, true); - if (updateTime) this.lastMove = System.nanoTime(); - this.npcPojo.setLocation(new ZLocation(location = new Location(location.getWorld(), location.getBlockX() + 0.5D, location.getY(), location.getBlockZ() + 0.5D, location.getYaw(), location.getPitch()))); - } - Reflections.SET_LOCATION_METHOD.get().invoke(this.nmsEntity, location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - Object npcTeleportPacket = Reflections.PACKET_PLAY_OUT_ENTITY_TELEPORT_CONSTRUCTOR.get().newInstance(this.nmsEntity); - this.viewers.forEach(player -> Utils.sendPackets(player, npcTeleportPacket)); - this.hologram.setLocation(location, this.npcPojo.getNpcType().getHoloHeight()); - } catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - - public void changeSkin(NPCSkin skinFetch) { - this.npcPojo.setSkin(skinFetch.getTexture()); - this.npcPojo.setSignature(skinFetch.getSignature()); - this.gameProfile.getProperties().clear(); - this.gameProfile.getProperties().put("textures", new Property("textures", this.npcPojo.getSkin(), this.npcPojo.getSignature())); - updateProfile(this.gameProfile.getProperties()); - deleteViewers(); - } - - public void setSecondLayerSkin() { - try { - Object dataWatcherObject = Reflections.GET_DATA_WATCHER_METHOD.get().invoke(this.nmsEntity); - if (Utils.versionNewer(9)) Reflections.SET_DATA_WATCHER_METHOD.get().invoke(dataWatcherObject, Reflections.DATA_WATCHER_OBJECT_CONSTRUCTOR.get() - .newInstance(this.npcSkin.getLayerIndex(), Reflections.DATA_WATCHER_REGISTER_FIELD.get()), (byte) 127); - else Reflections.WATCH_DATA_WATCHER_METHOD.get().invoke(dataWatcherObject, 10, (byte) 127); - } catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - - public synchronized void changeType(NPCType npcType) { - deleteViewers(); - try { - Object nmsWorld = Reflections.GET_HANDLE_WORLD_METHOD.get().invoke(getLocation().getWorld()); - boolean isPlayer = (npcType == NPCType.PLAYER); - this.nmsEntity = isPlayer ? this.packets.getNms().createPlayer(nmsWorld, this.gameProfile) : (Utils.versionNewer(14) ? npcType.getConstructor().newInstance(npcType.getNmsEntityType(), nmsWorld) : npcType.getConstructor().newInstance(nmsWorld)); - this.bukkitEntity = Reflections.GET_BUKKIT_ENTITY_METHOD.get().invoke(this.nmsEntity); - this.uuid = (UUID) Reflections.GET_UNIQUE_ID_METHOD.get().invoke(this.nmsEntity, new Object[0]); - if (isPlayer) { - try { - this.tabConstructor = Reflections.PACKET_PLAY_OUT_PLAYER_INFO_CONSTRUCTOR.get().newInstance(Reflections.ADD_PLAYER_FIELD.get(), Collections.singletonList(this.nmsEntity)); - } catch (Throwable e) { - this.tabConstructor = Reflections.PACKET_PLAY_OUT_PLAYER_INFO_CONSTRUCTOR.get().newInstance(Reflections.ADD_PLAYER_FIELD.get(), this.nmsEntity); - this.updateTabConstructor = Reflections.PACKET_PLAY_OUT_PLAYER_INFO_CONSTRUCTOR.get().newInstance(Reflections.UPDATE_LISTED_FIELD.get(), this.nmsEntity); - } - setSecondLayerSkin(); - } - this.npcPojo.setNpcType(npcType); - setLocation(getLocation(), false); - this.packets.flushCache("spawnPacket", "removeTab"); - this.entityID = (Integer) Reflections.GET_ENTITY_ID.get().invoke(this.nmsEntity, new Object[0]); - FunctionFactory.findFunctionsForNpc(this).forEach(function -> function.resolve(this)); - getPackets().getNms().update(this.packets); - this.hologram.createHologram(); - } catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - - public synchronized void spawn(ZUser user) { - if (this.viewers.contains(user)) { - return; - } - if (!getNpcPojo().getShouldSpawn()) { - return; - } - try { - this.viewers.add(user); - boolean npcIsPlayer = (this.npcPojo.getNpcType() == NPCType.PLAYER); - if (FunctionFactory.isTrue(this, "glow") || npcIsPlayer) { - ImmutableList scoreboardPackets = this.packets.getNms().updateScoreboard(this); - scoreboardPackets.forEach(p -> Utils.sendPackets(user, p)); - } - - ZLocation location = npcPojo.getLocation(); - Player player = user.toPlayer(); - if (npcIsPlayer) { - if (FunctionFactory.isTrue(this, "mirror")) updateProfile(user.getGameProfile().getProperties()); - Utils.sendPackets(user, this.tabConstructor, this.updateTabConstructor); - ZNPCsPlus.SCHEDULER.runNextTick(() -> { - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer(entityID, - this.gameProfile.getId(), SpigotConversionUtil.fromBukkitLocation(location.toBukkitLocation()))); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entityID, - List.of(new EntityData(NPCSkin.SkinLayerValues.findLayerByVersion(), EntityDataTypes.BYTE, Byte.MAX_VALUE)))); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityHeadLook(entityID, location.getYaw())); - }); - } - else { - ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); - EntityType type = SpigotConversionUtil.fromBukkitEntityType(((Entity) bukkitEntity).getType()); - if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) PacketEvents.getAPI().getPlayerManager().sendPacket( - player, new WrapperPlayServerSpawnEntity(entityID, Optional.of(uuid), type, location.toVector3d(), - location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); - else PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnLivingEntity( - entityID, uuid, type, location.toVector3d(), location.getYaw(), location.getPitch(), - location.getPitch(), new Vector3d(), List.of())); - } - - if (FunctionFactory.isTrue(this, "holo")) this.hologram.spawn(user); - updateMetadata(Collections.singleton(user)); - sendEquipPackets(user); - lookAt(user, getLocation(), true); - if (npcIsPlayer) ZNPCsPlus.SCHEDULER.runTaskLaterSync(() -> { - removeFromTab(player); - Utils.sendPackets(user, this.updateTabConstructor); - }, 60); - } catch (ReflectiveOperationException operationException) { - delete(user); - throw new UnexpectedCallException(operationException); - } - } - - private void removeFromTab(Player player) { - PacketWrapper packet; - if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19_3)) packet = new WrapperPlayServerPlayerInfoRemove(gameProfile.getId()); - else packet = new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, new UserProfile(gameProfile.getId(), gameProfile.getName()), null, 1)); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet); - } - - public synchronized void delete(ZUser user) { - if (!this.viewers.contains(user)) throw new IllegalStateException(user.getUUID().toString() + " is not a viewer."); - this.viewers.remove(user); - handleDelete(user); - } - - private void handleDelete(ZUser user) { - Player player = user.toPlayer(); - this.hologram.delete(user); - if (this.npcPojo.getNpcType() == NPCType.PLAYER) removeFromTab(player); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerDestroyEntities(this.entityID)); - } - - public void lookAt(ZUser player, Location location, boolean rotation) { - long lastMoveNanos = System.nanoTime() - this.lastMove; - if (this.lastMove > 1L && lastMoveNanos < 1000000000L) return; - Location direction = rotation ? location : this.npcPojo.getLocation().pointingTo(location); - try { - Object lookPacket = Reflections.PACKET_PLAY_OUT_ENTITY_LOOK_CONSTRUCTOR.get().newInstance(this.entityID, (byte) (int) (direction.getYaw() * 256.0F / 360.0F), (byte) (int) (direction.getPitch() * 256.0F / 360.0F), true); - Object headRotationPacket = Reflections.PACKET_PLAY_OUT_ENTITY_HEAD_ROTATION_CONSTRUCTOR.get().newInstance(this.nmsEntity, (byte) (int) (direction.getYaw() * 256.0F / 360.0F)); - if (player != null) Utils.sendPackets(player, lookPacket, headRotationPacket); - else this.viewers.forEach(players -> Utils.sendPackets(players, headRotationPacket)); - } catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - - public void deleteViewers() { - for (ZUser user : this.viewers) handleDelete(user); - this.viewers.clear(); - } - - protected void updateMetadata(Iterable users) { - try { - Object metaData = this.packets.getNms().createMetadataPacket(this.entityID, this.nmsEntity); - for (ZUser user : users) Utils.sendPackets(user, metaData); - } catch (ReflectiveOperationException operationException) { - operationException.getCause().printStackTrace(); - operationException.printStackTrace(); - } - } - - public void updateProfile(PropertyMap propertyMap) { - if (this.npcPojo.getNpcType() != NPCType.PLAYER) return; - try { - Object gameProfile = Reflections.GET_PROFILE_METHOD.get().invoke(this.nmsEntity); - Utils.setValue(gameProfile, "name", this.gameProfile.getName()); - Utils.setValue(gameProfile, "id", this.gameProfile.getId()); - Utils.setValue(gameProfile, "properties", propertyMap); - } catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } - } - - public void sendEquipPackets(ZUser zUser) { - if (this.npcPojo.getNpcEquip().isEmpty()) return; - List equipment = npcPojo.getNpcEquip().entrySet().stream() - .filter(entry -> Objects.nonNull(entry.getKey())) - .filter(entry -> Objects.nonNull(entry.getValue())) - .map(entry -> new Equipment(entry.getKey(), SpigotConversionUtil.fromBukkitItemStack(entry.getValue()))) - .toList(); - - if (Utils.versionNewer(16)) PacketEvents.getAPI().getPlayerManager().sendPacket(zUser.toPlayer(), new WrapperPlayServerEntityEquipment(entityID, equipment)); - else for (Equipment e : equipment) PacketEvents.getAPI().getPlayerManager().sendPacket(zUser.toPlayer(), new WrapperPlayServerEntityEquipment(entityID, List.of(e))); - } - - public void setPath(NPCPath.AbstractTypeWriter typeWriter) { - if (typeWriter == null) { - this.npcPath = null; - this.npcPojo.setPathName("none"); - } else { - this.npcPath = typeWriter.getPath(this); - this.npcPojo.setPathName(typeWriter.getName()); - } - } - - public void tryStartConversation(Player player) { - ConversationModel conversation = this.npcPojo.getConversation(); - if (conversation == null) throw new IllegalStateException("can't find conversation"); - conversation.startConversation(this, player); - } - - public Location getLocation() { - if (this.npcPath != null && this.npcPath.getLocation() != null) return this.npcPath.getLocation().toBukkitLocation(); - return this.npcPojo.getLocation().toBukkitLocation(); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCAction.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCAction.java deleted file mode 100644 index 1470c0b..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCAction.java +++ /dev/null @@ -1,94 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import com.google.common.base.MoreObjects; -import lol.pyr.znpcsplus.ZNPCsPlus; -import io.github.znetworkw.znpcservers.npc.interaction.ClickType; -import io.github.znetworkw.znpcservers.user.ZUser; -import io.github.znetworkw.znpcservers.utility.Utils; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; - -public class NPCAction { - private final ActionType actionType; - private final ClickType clickType; - private final String action; - private int delay; - - public NPCAction(ActionType actionType, ClickType clickType, String action, int delay) { - this.actionType = actionType; - this.clickType = clickType; - this.action = action; - this.delay = delay; - } - - public NPCAction(String actionType, String action) { - this(ActionType.valueOf(actionType), ClickType.DEFAULT, action, 0); - } - - public ActionType getActionType() { - return this.actionType; - } - - public ClickType getClickType() { - return this.clickType; - } - - public String getAction() { - return this.action; - } - - public int getDelay() { - return this.delay; - } - - public void setDelay(int delay) { - this.delay = delay; - } - - public long getFixedDelay() { - return 1000000000L * this.delay; - } - - public void run(ZUser user, String action) { - this.actionType.run(user, Utils.PLACEHOLDER_SUPPORT ? Utils.getWithPlaceholders(action, user.toPlayer()) : action); - } - - public String toString() { - return MoreObjects.toStringHelper(this) - .add("actionType", this.actionType) - .add("clickType", this.clickType) - .add("action", this.action) - .add("delay", this.delay) - .toString(); - } - - enum ActionType { - CMD { - public void run(ZUser user, String actionValue) { - user.toPlayer().performCommand(actionValue); - } - }, - CONSOLE { - public void run(ZUser user, String actionValue) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), actionValue); - } - }, - CHAT { - public void run(ZUser user, String actionValue) { - user.toPlayer().chat(actionValue); - } - }, - MESSAGE { - public void run(ZUser user, String actionValue) { - user.toPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', actionValue)); - } - }, - SERVER { - public void run(ZUser user, String actionValue) { - ZNPCsPlus.BUNGEE_UTILS.sendPlayerToServer(user.toPlayer(), actionValue); - } - }; - - public abstract void run(ZUser param1ZUser, String param1String); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCFunction.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCFunction.java deleted file mode 100644 index 0712ef5..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCFunction.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -public abstract class NPCFunction { - private final String name; - - public NPCFunction(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } - - protected abstract boolean allow(NPC paramNPC); - - protected abstract ResultType runFunction(NPC paramNPC, FunctionContext paramFunctionContext); - - public void doRunFunction(NPC npc, FunctionContext functionContext) { - if (!allow(npc)) - return; - ResultType resultType = runFunction(npc, functionContext); - if (resultType == ResultType.SUCCESS) - npc.getNpcPojo().getFunctions().put(getName(), !isTrue(npc)); - } - - protected ResultType resolve(NPC npc) { - throw new IllegalStateException("resolve is not implemented."); - } - - public boolean isTrue(NPC npc) { - return FunctionFactory.isTrue(npc, this); - } - - public enum ResultType { - SUCCESS, FAIL - } - - public static class WithoutFunction extends NPCFunction { - public WithoutFunction(String name) { - super(name); - } - - protected NPCFunction.ResultType runFunction(NPC npc, FunctionContext functionContext) { - return NPCFunction.ResultType.SUCCESS; - } - - protected boolean allow(NPC npc) { - return true; - } - - protected NPCFunction.ResultType resolve(NPC npc) { - return NPCFunction.ResultType.SUCCESS; - } - } - - public static class WithoutFunctionSelfUpdate extends WithoutFunction { - public WithoutFunctionSelfUpdate(String name) { - super(name); - } - - protected NPCFunction.ResultType runFunction(NPC npc, FunctionContext functionContext) { - npc.deleteViewers(); - return NPCFunction.ResultType.SUCCESS; - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCModel.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCModel.java deleted file mode 100644 index 3131803..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCModel.java +++ /dev/null @@ -1,247 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import com.github.retrooper.packetevents.protocol.player.EquipmentSlot; -import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel; -import io.github.znetworkw.znpcservers.utility.location.ZLocation; -import org.bukkit.inventory.ItemStack; - -import java.util.*; - -@SuppressWarnings("unused") -public class NPCModel { - private int id; - private UUID uuid; - private double hologramHeight; - private String skin; - private String signature; - private String pathName; - private String glowName; - private ConversationModel conversation; - private ZLocation location; - private NPCType npcType; - private boolean shouldSpawn; - private List hologramLines; - private List clickActions; - private Map npcEquip; - private Map npcFunctions; - private Map customizationMap; - - public NPCModel(int id) { - this.id = id; - this.uuid = UUID.randomUUID(); - this.skin = ""; - this.signature = ""; - this.npcType = NPCType.PLAYER; - this.shouldSpawn = true; - this.hologramLines = Collections.singletonList("/znpcs lines"); - this.clickActions = new ArrayList<>(); - this.npcEquip = new HashMap<>(); - this.customizationMap = new HashMap<>(); - this.npcFunctions = new HashMap<>(); - this.npcFunctions.put("holo", Boolean.TRUE); - } - - public int getId() { - return this.id; - } - - public void setId(int id) { - this.id = id; - } - - public NPCModel withId(int id) { - setId(id); - return this; - } - - public UUID getUuid() { - if (this.uuid == null) this.uuid = UUID.randomUUID(); - return this.uuid; - } - - public void setUuid(UUID uuid) { - this.uuid = uuid; - } - - public double getHologramHeight() { - return this.hologramHeight; - } - - public void setHologramHeight(double hologramHeight) { - this.hologramHeight = hologramHeight; - } - - public NPCModel withHologramHeight(double hologramHeight) { - setHologramHeight(hologramHeight); - return this; - } - - public String getSkin() { - return this.skin; - } - - public void setSkin(String skin) { - this.skin = skin; - } - - public NPCModel withSkin(String skin) { - setSkin(skin); - return this; - } - - public String getSignature() { - return this.signature; - } - - public void setSignature(String signature) { - this.signature = signature; - } - - public NPCModel withSignature(String signature) { - setSignature(signature); - return this; - } - - public String getPathName() { - return this.pathName; - } - - public void setPathName(String pathName) { - this.pathName = pathName; - } - - public NPCModel withPathName(String pathName) { - setPathName(pathName); - return this; - } - - public String getGlowName() { - return this.glowName; - } - - public void setGlowName(String glowName) { - this.glowName = glowName; - } - - public NPCModel withGlowName(String glowName) { - setGlowName(this.pathName); - return this; - } - - public ConversationModel getConversation() { - return this.conversation; - } - - public void setConversation(ConversationModel conversation) { - this.conversation = conversation; - } - - public NPCModel withConversation(ConversationModel conversation) { - setConversation(conversation); - return this; - } - - public List getHologramLines() { - return this.hologramLines; - } - - public void setHologramLines(List hologramLines) { - this.hologramLines = hologramLines; - } - - public NPCModel withHologramLines(List hologramLines) { - setHologramLines(hologramLines); - return this; - } - - public ZLocation getLocation() { - return this.location; - } - - public void setLocation(ZLocation location) { - this.location = location; - } - - public NPCModel withLocation(ZLocation location) { - setLocation(location); - return this; - } - - public NPCType getNpcType() { - return this.npcType; - } - - public void setNpcType(NPCType npcType) { - this.npcType = npcType; - } - - public NPCModel withNpcType(NPCType npcType) { - setNpcType(npcType); - return this; - } - - public boolean getShouldSpawn() { - return this.shouldSpawn; - } - - public void setShouldSpawn(boolean shouldSpawn) { - this.shouldSpawn = shouldSpawn; - } - - public NPCModel withShouldSpawn(boolean shouldSpawn) { - setShouldSpawn(shouldSpawn); - return this; - } - - public List getClickActions() { - return this.clickActions; - } - - public void setClickActions(List clickActions) { - this.clickActions = clickActions; - } - - public NPCModel withClickActions(List clickActions) { - setClickActions(clickActions); - return this; - } - - public Map getNpcEquip() { - return this.npcEquip; - } - - public void setNpcEquip(Map npcEquip) { - this.npcEquip = npcEquip; - } - - public NPCModel withNpcEquip(Map npcEquip) { - setNpcEquip(npcEquip); - return this; - } - - public Map getCustomizationMap() { - return this.customizationMap; - } - - public void setCustomizationMap(Map customizationMap) { - this.customizationMap = customizationMap; - } - - public NPCModel withCustomizationMap(Map customizationMap) { - setCustomizationMap(customizationMap); - return this; - } - - public Map getFunctions() { - return this.npcFunctions; - } - - public void setFunctions(Map npcFunctions) { - this.npcFunctions = npcFunctions; - } - - public NPCModel withFunctionValues(Map npcFunctions) { - setFunctions(npcFunctions); - return this; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCPath.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCPath.java deleted file mode 100644 index 952d02f..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCPath.java +++ /dev/null @@ -1,263 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import io.github.znetworkw.znpcservers.configuration.Configuration; -import io.github.znetworkw.znpcservers.configuration.ConfigurationValue; -import io.github.znetworkw.znpcservers.user.ZUser; -import io.github.znetworkw.znpcservers.utility.location.ZLocation; -import lol.pyr.znpcsplus.ZNPCsPlus; -import org.bukkit.Location; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; - -import java.io.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -@SuppressWarnings("ALL") -public interface NPCPath { - void initialize(DataInputStream paramDataInputStream) throws IOException; - void write(DataOutputStream paramDataOutputStream) throws IOException; - void start(); - PathInitializer getPath(NPC paramNPC); - - interface PathInitializer { - void handle(); - - ZLocation getLocation(); - - abstract class AbstractPath implements PathInitializer { - private final NPC npc; - private final NPCPath.AbstractTypeWriter typeWriter; - private ZLocation location; - - public AbstractPath(NPC npc, NPCPath.AbstractTypeWriter typeWriter) { - this.npc = npc; - this.typeWriter = typeWriter; - } - - public NPC getNpc() { - return this.npc; - } - - public NPCPath.AbstractTypeWriter getPath() { - return this.typeWriter; - } - - public ZLocation getLocation() { - return this.location; - } - - public void setLocation(ZLocation location) { - this.location = location; - } - } - } - - class ZNPCPathDelegator { - private final File file; - - protected ZNPCPathDelegator(File file) { - this.file = file; - } - - public static ZNPCPathDelegator forFile(File file) { - return new ZNPCPathDelegator(file); - } - - public static ZNPCPathDelegator forPath(NPCPath.AbstractTypeWriter pathAbstract) { - return new ZNPCPathDelegator(pathAbstract.getFile()); - } - - public DataOutputStream getOutputStream() throws IOException { - return new DataOutputStream(new FileOutputStream(this.file)); - } - - public DataInputStream getInputStream() throws IOException { - return new DataInputStream(new FileInputStream(this.file)); - } - } - - abstract class AbstractTypeWriter implements NPCPath { - private static final ConcurrentMap PATH_TYPES = new ConcurrentHashMap<>(); - private final TypeWriter typeWriter; - private final File file; - private final List locationList; - - public AbstractTypeWriter(TypeWriter typeWriter, File file) { - this.typeWriter = typeWriter; - this.file = file; - this.locationList = new ArrayList<>(); - } - - public AbstractTypeWriter(TypeWriter typeWriter, String pathName) { - this(typeWriter, new File(ZNPCsPlus.PATH_FOLDER, pathName + ".path")); - } - - public static AbstractTypeWriter forCreation(String pathName, ZUser user, TypeWriter typeWriter) { - if (typeWriter == TypeWriter.MOVEMENT) return new TypeMovement(pathName, user); - throw new IllegalStateException("can't find type writer for: " + typeWriter.name()); - } - - public static AbstractTypeWriter forFile(File file, TypeWriter typeWriter) { - if (typeWriter == TypeWriter.MOVEMENT) return new TypeMovement(file); - throw new IllegalStateException("can't find type writer for: " + typeWriter.name()); - } - - public static void register(AbstractTypeWriter abstractZNPCPath) { - PATH_TYPES.put(abstractZNPCPath.getName(), abstractZNPCPath); - } - - public static AbstractTypeWriter find(String name) { - return PATH_TYPES.get(name); - } - - public static Collection getPaths() { - return PATH_TYPES.values(); - } - - public void load() { - try (DataInputStream reader = NPCPath.ZNPCPathDelegator.forFile(this.file).getInputStream()) { - initialize(reader); - register(this); - } catch (IOException e) { - ZNPCsPlus.LOGGER.warning("[AbstractTypeWriter] " + String.format("The path %s could not be loaded", this.file.getName())); - e.printStackTrace(); - } - } - - public void write() { - try (DataOutputStream writer = NPCPath.ZNPCPathDelegator.forFile(getFile()).getOutputStream()) { - write(writer); - if (writer != null) writer.close(); - } catch (IOException e) { - ZNPCsPlus.LOGGER.warning("[AbstractTypeWriter] " + String.format("Path %s could not be created", getName())); - e.printStackTrace(); - } - } - - public File getFile() { - return this.file; - } - - public List getLocationList() { - return this.locationList; - } - - public String getName() { - return this.file.getName().substring(0, this.file.getName().lastIndexOf('.')); - } - - public enum TypeWriter { - MOVEMENT - } - - private static class TypeMovement extends AbstractTypeWriter { - private static final int MAX_LOCATIONS = ((Integer) Configuration.CONFIGURATION.getValue(ConfigurationValue.MAX_PATH_LOCATIONS)).intValue(); - private ZUser npcUser; - private BukkitTask bukkitTask; - - public TypeMovement(File file) { - super(NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT, file); - } - - public TypeMovement(String fileName, ZUser npcUser) { - super(NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT, fileName); - this.npcUser = npcUser; - start(); - } - - public void initialize(DataInputStream dataInputStream) throws IOException { - while (dataInputStream.available() > 0) { - String worldName = dataInputStream.readUTF(); - double x = dataInputStream.readDouble(); - double y = dataInputStream.readDouble(); - double z = dataInputStream.readDouble(); - float yaw = dataInputStream.readFloat(); - float pitch = dataInputStream.readFloat(); - getLocationList().add(new ZLocation(worldName, x, y, z, yaw, pitch)); - } - } - - public void write(DataOutputStream dataOutputStream) throws IOException { - if (getLocationList().isEmpty()) return; - Iterator locationIterator = getLocationList().iterator(); - while (locationIterator.hasNext()) { - ZLocation location = locationIterator.next(); - dataOutputStream.writeUTF(location.getWorldName()); - dataOutputStream.writeDouble(location.getX()); - dataOutputStream.writeDouble(location.getY()); - dataOutputStream.writeDouble(location.getZ()); - dataOutputStream.writeFloat(location.getYaw()); - dataOutputStream.writeFloat(location.getPitch()); - if (!locationIterator.hasNext()) register(this); - } - } - - public void start() { - this.npcUser.setHasPath(true); - this.bukkitTask = ZNPCsPlus.SCHEDULER.runTaskTimerAsynchronously(() -> { - if (this.npcUser.toPlayer() != null && this.npcUser.isHasPath() && MAX_LOCATIONS > getLocationList().size()) { - Location location = this.npcUser.toPlayer().getLocation(); - if (isValid(location)) - getLocationList().add(new ZLocation(location)); - } else { - this.bukkitTask.cancel(); - this.npcUser.setHasPath(false); - write(); - } - }, 1, 1); - } - - public MovementPath getPath(NPC npc) { - return new MovementPath(npc, this); - } - - protected boolean isValid(Location location) { - if (getLocationList().isEmpty()) - return true; - ZLocation last = getLocationList().get(getLocationList().size() - 1); - double xDiff = Math.abs(last.getX() - location.getX()); - double yDiff = Math.abs(last.getY() - location.getY()); - double zDiff = Math.abs(last.getZ() - location.getZ()); - return (xDiff + yDiff + zDiff > 0.01D); - } - - protected static class MovementPath extends NPCPath.PathInitializer.AbstractPath { - private int currentEntryPath = 0; - private boolean pathReverse = false; - - public MovementPath(NPC npc, NPCPath.AbstractTypeWriter.TypeMovement path) { - super(npc, path); - } - - public void handle() { - updatePathLocation(getPath().getLocationList().get(this.currentEntryPath = getNextLocation())); - int nextIndex = getNextLocation(); - if (nextIndex < 1) { - this.pathReverse = false; - } else if (nextIndex >= getPath().getLocationList().size() - 1) { - this.pathReverse = true; - } - } - - private int getNextLocation() { - return this.pathReverse ? (this.currentEntryPath - 1) : (this.currentEntryPath + 1); - } - - protected void updatePathLocation(ZLocation location) { - setLocation(location); - ZLocation next = getPath().getLocationList().get(getNextLocation()); - Vector vector = next.toVector().add(new Vector(0.0D, location.getY() - next.getY(), 0.0D)); - Location direction = next.toBukkitLocation().clone().setDirection(location.toVector().subtract(vector) - .multiply(new Vector(-1, 0, -1))); - getNpc().setLocation(direction, false); - getNpc().lookAt(null, direction, true); - } - } - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java deleted file mode 100644 index 9a51541..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCSkin.java +++ /dev/null @@ -1,63 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import io.github.znetworkw.znpcservers.skin.SkinFetcherBuilder; -import io.github.znetworkw.znpcservers.skin.SkinFetcherResult; -import io.github.znetworkw.znpcservers.utility.Utils; - -public class NPCSkin { - private static final int LAYER_INDEX = SkinLayerValues.findLayerByVersion(); - private final String texture; - private final String signature; - - public NPCSkin(String texture, String signature) { - this.texture = texture; - this.signature = signature; - } - - public static NPCSkin forValues(String... values) { - return new NPCSkin(values[0], (values.length > 1) ? values[1] : null); - } - - public static void forName(String skin, SkinFetcherResult skinFetcherResult) { - SkinFetcherBuilder.withName(skin).toSkinFetcher().doReadSkin(skinFetcherResult); - } - - public String getTexture() { - return this.texture; - } - - public String getSignature() { - return this.signature; - } - - public int getLayerIndex() { - return LAYER_INDEX; - } - - enum SkinLayerValues { - V8(8, 12), - V9(10, 13), - V14(14, 15), - V16(15, 16), - V17(17, 17), - V18(18, 17); - - final int minVersion; - - final int layerValue; - - SkinLayerValues(int minVersion, int layerValue) { - this.minVersion = minVersion; - this.layerValue = layerValue; - } - - static int findLayerByVersion() { - int value = V8.layerValue; - for (SkinLayerValues skinLayerValue : values()) { - if (Utils.BUKKIT_VERSION >= skinLayerValue.minVersion) - value = skinLayerValue.layerValue; - } - return value; - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java index 38e3035..416fa87 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java @@ -1,18 +1,12 @@ package io.github.znetworkw.znpcservers.npc; -import io.github.znetworkw.znpcservers.UnexpectedCallException; -import io.github.znetworkw.znpcservers.reflection.EnumPropertyCache; import io.github.znetworkw.znpcservers.utility.Utils; -import org.bukkit.entity.EntityType; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Optional; import static io.github.znetworkw.znpcservers.reflection.Reflections.*; +/** + * Delete after information transferred + */ @SuppressWarnings("unused") public enum NPCType { ALLAY(ENTITY_ALLAY_CLASS, -1.14), @@ -96,79 +90,9 @@ public enum NPCType { ZOMBIFIED_PIGLIN(Utils.versionNewer(16) ? ENTITY_ZOMBIFIED_PIGLIN_CLASS : null, 0.135, "setBaby"), PIG_ZOMBIE(Utils.versionNewer(16) ? null : ENTITY_ZOMBIFIED_PIGLIN_CLASS, 0.135); - private final double holoHeight; - private final CustomizationLoader customizationLoader; - private final Constructor constructor; - private EntityType bukkitEntityType; - private Object nmsEntityType; - - @SuppressWarnings("OptionalGetWithoutIsPresent") NPCType(Class entityClass, String newName, double holoHeight, String ... methods) { - this.holoHeight = holoHeight; - if (entityClass == null) { - customizationLoader = null; - } else { - this.bukkitEntityType = EntityType.valueOf(newName.length() > 0 ? newName : this.name()); - customizationLoader = new CustomizationLoader(this.bukkitEntityType, Arrays.asList(methods)); - } - if (entityClass == null || entityClass.isAssignableFrom(ENTITY_PLAYER_CLASS)) { - this.constructor = null; - return; - } - try { - if (Utils.versionNewer(14)) { - this.nmsEntityType = ((Optional) ENTITY_TYPES_A_METHOD.get().invoke(null, this.bukkitEntityType.getKey().getKey().toLowerCase())).get(); - this.constructor = entityClass.getConstructor(ENTITY_TYPES_CLASS, WORLD_CLASS); - } else { - this.constructor = entityClass.getConstructor(WORLD_CLASS); - } - } - catch (ReflectiveOperationException operationException) { - throw new UnexpectedCallException(operationException); - } } NPCType(Class entityClass, double holoHeight, String ... customization) { - this(entityClass, "", holoHeight, customization); - } - - public double getHoloHeight() { - return this.holoHeight; - } - - public Constructor getConstructor() { - return this.constructor; - } - - public Object getNmsEntityType() { - return this.nmsEntityType; - } - - public CustomizationLoader getCustomizationLoader() { - return this.customizationLoader; - } - - public static Object[] collectArguments(String[] strings, Method method) { - Class[] methodParameterTypes = method.getParameterTypes(); - Object[] newArray = new Object[methodParameterTypes.length]; - for (int i = 0; i < methodParameterTypes.length; ++i) { - PrimitivePropertyType primitivePropertyType = PrimitivePropertyType.forType(methodParameterTypes[i]); - newArray[i] = primitivePropertyType != null ? primitivePropertyType.getFunction().apply(strings[i]) : EnumPropertyCache.find(strings[i], methodParameterTypes[i]); - } - return newArray; - } - - public void updateCustomization(NPC npc, String name, String[] values) { - if (!this.customizationLoader.contains(name)) { - return; - } - try { - Method method = this.customizationLoader.getMethods().get(name); - method.invoke(npc.getBukkitEntity(), NPCType.collectArguments(values, method)); - npc.updateMetadata(npc.getViewers()); - } - catch (IllegalAccessException | InvocationTargetException e) { - throw new IllegalStateException("can't invoke method: " + name, e); - } } } \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NamingType.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NamingType.java deleted file mode 100644 index dd413a8..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NamingType.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import io.github.znetworkw.znpcservers.utility.Utils; - -public enum NamingType { - DEFAULT { - public String resolve(NPC npc) { - return Utils.randomString(6); - } - }; - - public abstract String resolve(NPC paramNPC); -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/PrimitivePropertyType.java b/src/main/java/io/github/znetworkw/znpcservers/npc/PrimitivePropertyType.java deleted file mode 100644 index 5a68c70..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/PrimitivePropertyType.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import java.util.function.Function; - -public enum PrimitivePropertyType { - STRING(String::toString), - BOOLEAN(Boolean::parseBoolean), - INT(Integer::parseInt), - DOUBLE(Double::parseDouble), - FLOAT(Float::parseFloat), - SHORT(Short::parseShort), - LONG(Long::parseLong); - - private final Function function; - - PrimitivePropertyType(Function function) { - this.function = function; - } - - public static PrimitivePropertyType forType(Class primitiveType) { - if (primitiveType == String.class) return STRING; - if (primitiveType == boolean.class) return BOOLEAN; - if (primitiveType == int.class) return INT; - if (primitiveType == double.class) return DOUBLE; - if (primitiveType == float.class) return FLOAT; - if (primitiveType == short.class) return SHORT; - if (primitiveType == long.class) return LONG; - return null; - } - - public Function getFunction() { - return this.function; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/Conversation.java b/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/Conversation.java deleted file mode 100644 index 1fe0142..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/Conversation.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.conversation; - -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; - -import java.util.ArrayList; -import java.util.List; - -public class Conversation { - private final String name; - private final List texts; - private int radius = 5; - private int delay = 10; - - public Conversation(String name) { - this(name, new ArrayList<>()); - } - - protected Conversation(String name, List text) { - this.name = name; - this.texts = text; - } - - public static Conversation forName(String name) { - return ConfigurationConstants.NPC_CONVERSATIONS.stream() - .filter(conversation -> conversation.getName().equalsIgnoreCase(name)) - .findFirst() - .orElse(null); - } - - public static boolean exists(String name) { - return ConfigurationConstants.NPC_CONVERSATIONS.stream() - .anyMatch(conversation -> conversation.getName().equalsIgnoreCase(name)); - } - - public String getName() { - return this.name; - } - - public List getTexts() { - return this.texts; - } - - public int getDelay() { - return this.delay; - } - - public void setDelay(int delay) { - this.delay = delay; - } - - public int getRadius() { - return this.radius; - } - - public void setRadius(int radius) { - this.radius = radius; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationKey.java b/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationKey.java deleted file mode 100644 index 0b11c29..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationKey.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.conversation; - -import com.google.common.base.Splitter; -import io.github.znetworkw.znpcservers.npc.NPCAction; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -public class ConversationKey { - private static final Splitter SPACE_SPLITTER = Splitter.on(" "); - private final List lines; - private final List actions; - private int delay = 1; - private String soundName; - - public ConversationKey(String line) { - this(SPACE_SPLITTER.split(line)); - } - - public ConversationKey(Iterable line) { - this.lines = StreamSupport.stream(line.spliterator(), false).map(String::toString).collect(Collectors.toList()); - this.actions = new ArrayList<>(); - } - - public List getLines() { - return this.lines; - } - - public int getDelay() { - return this.delay; - } - - public void setDelay(int delay) { - this.delay = delay; - } - - public String getSoundName() { - return this.soundName; - } - - public void setSoundName(String soundName) { - this.soundName = soundName; - } - - public List getActions() { - return this.actions; - } - - public String getTextFormatted() { - if (this.lines.isEmpty()) return ""; - String text = this.lines.iterator().next(); - int fixedLength = Math.min(text.length(), 28); - return text.substring(0, fixedLength); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationModel.java b/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationModel.java deleted file mode 100644 index ddefe9a..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationModel.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.conversation; - -import io.github.znetworkw.znpcservers.npc.NPC; -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Stream; - -public class ConversationModel { - private final transient Map lastStarted = new HashMap<>(); - private String conversationName; - private ConversationType conversationType; - - public ConversationModel(String conversationName, String conversationType) { - this.conversationName = conversationName; - try { - this.conversationType = ConversationType.valueOf(conversationType.toUpperCase()); - } catch (IllegalArgumentException exception) { - throw new IllegalStateException("can't find conversation type " + conversationType); - } - } - - @SuppressWarnings("unused") - private ConversationModel() { - } - - public String getConversationName() { - return this.conversationName; - } - - public ConversationType getConversationType() { - return this.conversationType; - } - - public Conversation getConversation() { - return Conversation.forName(this.conversationName); - } - - public void startConversation(NPC npc, Player player) { - if (!Conversation.exists(this.conversationName)) throw new IllegalStateException("can't find conversation " + this.conversationName); - if (ConversationProcessor.isPlayerConversing(player.getUniqueId())) return; - if (this.lastStarted.containsKey(player.getUniqueId())) { - long lastConversationNanos = System.nanoTime() - this.lastStarted.get(player.getUniqueId()); - if (lastConversationNanos < 1000000000L * getConversation().getDelay()) return; - } - this.lastStarted.remove(player.getUniqueId()); - if (this.conversationType.canStart(npc, getConversation(), player)) { - new ConversationProcessor(npc, this, player); - this.lastStarted.put(player.getUniqueId(), System.nanoTime()); - } - } - - public boolean canRun(NPC npc, Player player) { - return Stream.of(ConversationType.values()).anyMatch(conversationType1 -> !conversationType1.canStart(npc, getConversation(), player)); - } - - public enum ConversationType { - RADIUS { - public boolean canStart(NPC npc, Conversation conversation, Player player) { - return (player.getWorld() == npc.getLocation().getWorld() && player.getLocation().distance(npc.getLocation()) <= conversation.getRadius()); - } - }, - CLICK { - public boolean canStart(NPC npc, Conversation conversation, Player player) { - return true; - } - }; - - abstract boolean canStart(NPC param1NPC, Conversation param1Conversation, Player param1Player); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationProcessor.java b/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationProcessor.java deleted file mode 100644 index fce72a1..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/conversation/ConversationProcessor.java +++ /dev/null @@ -1,70 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.conversation; - -import lol.pyr.znpcsplus.ZNPCsPlus; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.hologram.replacer.LineReplacer; -import io.github.znetworkw.znpcservers.user.ZUser; -import org.bukkit.Bukkit; -import org.bukkit.Sound; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class ConversationProcessor { - private static final Map RUNNING_CONVERSATIONS = new HashMap<>(); - private final NPC npc; - private final ConversationModel conversationModel; - private final Player player; - private int conversationIndex = 0; - private long conversationIndexDelay = System.nanoTime(); - - public ConversationProcessor(NPC npc, ConversationModel conversationModel, Player player) { - if (conversationModel.getConversation().getTexts().isEmpty()) - throw new IllegalStateException("conversation should have a text."); - this.npc = npc; - this.conversationModel = conversationModel; - this.player = player; - RUNNING_CONVERSATIONS.put(player.getUniqueId(), conversationModel.getConversationName()); - start(); - } - - public static boolean isPlayerConversing(UUID uuid) { - return RUNNING_CONVERSATIONS.containsKey(uuid); - } - - private void start() { - ZNPCsPlus.SCHEDULER.runTaskTimer(new BukkitRunnable() { - public void run() { - if (Bukkit.getPlayer(ConversationProcessor.this.player.getUniqueId()) == null || ConversationProcessor.this - .conversationIndex > ConversationProcessor.this.conversationModel.getConversation().getTexts().size() - 1 || ConversationProcessor.this - .conversationModel.canRun(ConversationProcessor.this.npc, ConversationProcessor.this.player)) { - ConversationProcessor.RUNNING_CONVERSATIONS.remove(ConversationProcessor.this.player.getUniqueId()); - cancel(); - return; - } - ConversationKey conversationKey = ConversationProcessor.this.conversationModel.getConversation().getTexts().get(ConversationProcessor.this.conversationIndex); - long conversationDelayNanos = System.nanoTime() - ConversationProcessor.this.conversationIndexDelay; - if (ConversationProcessor.this.conversationIndex != 0 && conversationDelayNanos < 1000000000L * conversationKey - .getDelay()) - return; - ZUser user = ZUser.find(ConversationProcessor.this.player); - conversationKey.getLines().forEach(s -> ConversationProcessor.this.player.sendMessage(LineReplacer.makeAll(user, s).replace(ConfigurationConstants.SPACE_SYMBOL, " "))); - if (conversationKey.getActions().size() > 0) - conversationKey.getActions().forEach(action -> action.run(user, action.getAction())); - if (conversationKey.getSoundName() != null && conversationKey - .getSoundName().length() > 0) - try { - Sound sound = Sound.valueOf(conversationKey.getSoundName().toUpperCase()); - ConversationProcessor.this.player.playSound(ConversationProcessor.this.player.getLocation(), sound, 0.2F, 1.0F); - } catch (IllegalArgumentException ignored) { - } - ConversationProcessor.this.conversationIndexDelay = System.nanoTime(); - ConversationProcessor.this.conversationIndex++; - } - }, 5, 20); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/function/GlowFunction.java b/src/main/java/io/github/znetworkw/znpcservers/npc/function/GlowFunction.java deleted file mode 100644 index 8a12a60..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/function/GlowFunction.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.function; - -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.npc.FunctionContext; -import io.github.znetworkw.znpcservers.npc.FunctionFactory; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.NPCFunction; - -public class GlowFunction extends NPCFunction { - public GlowFunction() { - super("glow"); - } - - protected NPCFunction.ResultType runFunction(NPC npc, FunctionContext functionContext) { - if (!(functionContext instanceof FunctionContext.ContextWithValue)) - throw new IllegalStateException("invalid context type, " + functionContext.getClass().getSimpleName() + ", expected ContextWithValue."); - String glowColorName = ((FunctionContext.ContextWithValue) functionContext).getValue(); - try { - Object glowColor = Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, ( - glowColorName == null || glowColorName.length() == 0) ? "WHITE" : glowColorName); - if (glowColor == null) - return NPCFunction.ResultType.FAIL; - npc.getNpcPojo().setGlowName(glowColorName); - npc.setGlowColor(glowColor); - Reflections.SET_DATA_WATCHER_METHOD.get().invoke(Reflections.GET_DATA_WATCHER_METHOD - .get().invoke(npc.getNmsEntity()), Reflections.DATA_WATCHER_OBJECT_CONSTRUCTOR - .get().newInstance(0, Reflections.DATA_WATCHER_REGISTER_FIELD - .get()), (byte) (!FunctionFactory.isTrue(npc, this) ? 64 : 0)); - npc.getPackets().getNms().update(npc.getPackets()); - npc.deleteViewers(); - return NPCFunction.ResultType.SUCCESS; - } catch (ReflectiveOperationException operationException) { - return NPCFunction.ResultType.FAIL; - } - } - - protected boolean allow(NPC npc) { - return npc.getPackets().getNms().allowsGlowColor(); - } - - public NPCFunction.ResultType resolve(NPC npc) { - return runFunction(npc, new FunctionContext.ContextWithValue(npc, npc.getNpcPojo().getGlowName())); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/ClickType.java b/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/ClickType.java deleted file mode 100644 index 716cc27..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/ClickType.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.interaction; - -public enum ClickType { - RIGHT, LEFT, DEFAULT; - - public static ClickType forName(String clickName) { - if (clickName.startsWith("INTERACT")) return RIGHT; - if (clickName.startsWith("ATTACK")) return LEFT; - return DEFAULT; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/NPCInteractEvent.java b/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/NPCInteractEvent.java deleted file mode 100644 index e1cd4b1..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/NPCInteractEvent.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.interaction; - -import io.github.znetworkw.znpcservers.npc.NPC; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -@SuppressWarnings("unused") -public class NPCInteractEvent extends Event { - private static final HandlerList handlerList = new HandlerList(); - private final Player player; - private final ClickType clickType; - private final NPC npc; - - public NPCInteractEvent(Player player, ClickType clickType, NPC npc) { - this.player = player; - this.clickType = clickType; - this.npc = npc; - } - - public NPCInteractEvent(Player player, String clickType, NPC npc) { - this(player, ClickType.forName(clickType), npc); - } - - public static HandlerList getHandlerList() { - return handlerList; - } - - public Player getPlayer() { - return this.player; - } - - public NPC getNpc() { - return this.npc; - } - - public boolean isRightClick() { - return (this.clickType == ClickType.RIGHT); - } - - public boolean isLeftClick() { - return (this.clickType == ClickType.LEFT); - } - - public HandlerList getHandlers() { - return handlerList; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCLoadTask.java b/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCLoadTask.java deleted file mode 100644 index fdbf60c..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCLoadTask.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.task; - -import lol.pyr.znpcsplus.ZNPCsPlus; -import io.github.znetworkw.znpcservers.npc.NPC; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.scheduler.BukkitRunnable; - -public class NPCLoadTask extends BukkitRunnable { - private final NPC npc; - - private int tries = 0; - - public NPCLoadTask(NPC npc) { - this.npc = npc; - ZNPCsPlus.SCHEDULER.runTaskTimer(this, 40); - } - - public void run() { - if (this.tries++ > 10) { - cancel(); - return; - } - World world = Bukkit.getWorld(this.npc.getNpcPojo().getLocation().getWorldName()); - if (world == null) return; - cancel(); - this.npc.onLoad(); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCPositionTask.java b/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCPositionTask.java deleted file mode 100644 index 0d9a4ea..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCPositionTask.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.task; - -import io.github.znetworkw.znpcservers.npc.FunctionFactory; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.user.ZUser; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; - -public class NPCPositionTask extends BukkitRunnable { - public NPCPositionTask(Plugin serversNPC) { - runTaskTimerAsynchronously(serversNPC, 60L, 1L); - } - - public void run() { - for (NPC npc : NPC.all()) { - if (npc.getNpcPath() != null) { - npc.getNpcPath().handle(); - } - else if (FunctionFactory.isTrue(npc, "look")) for (Player player : Bukkit.getOnlinePlayers()) { - if (!player.getWorld().equals(npc.getLocation().getWorld())) continue; - ZUser user = ZUser.find(player); - if (npc.getViewers().contains(user)) npc.lookAt(user, player.getLocation(), false); - } - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCSaveTask.java b/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCSaveTask.java deleted file mode 100644 index a494ad2..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/task/NPCSaveTask.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.znetworkw.znpcservers.npc.task; - -import io.github.znetworkw.znpcservers.configuration.Configuration; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; - -public class NPCSaveTask extends BukkitRunnable { - public NPCSaveTask(Plugin serversNPC, int seconds) { - runTaskTimerAsynchronously(serversNPC, 200L, seconds); - } - - public void run() { - Configuration.SAVE_CONFIGURATIONS.forEach(Configuration::save); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java deleted file mode 100644 index 9984a0b..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcher.java +++ /dev/null @@ -1,63 +0,0 @@ -package io.github.znetworkw.znpcservers.skin; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import io.github.znetworkw.znpcservers.npc.NPCSkin; - -import java.io.DataOutputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class SkinFetcher { - private static final ExecutorService SKIN_EXECUTOR_SERVICE = Executors.newCachedThreadPool(); - private final SkinFetcherBuilder builder; - - public SkinFetcher(SkinFetcherBuilder builder) { - this.builder = builder; - } - - public CompletableFuture doReadSkin(SkinFetcherResult skinFetcherResult) { - CompletableFuture completableFuture = new CompletableFuture<>(); - SKIN_EXECUTOR_SERVICE.submit(() -> { - try { - HttpURLConnection connection = (HttpURLConnection) (new URL(this.builder.getAPIServer().getURL() + getData())).openConnection(); - connection.setRequestMethod(this.builder.getAPIServer().getMethod()); - if (this.builder.isUrlType()) { - connection.setDoOutput(true); - try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { - outputStream.writeBytes("url=" + URLEncoder.encode(this.builder.getData(), StandardCharsets.UTF_8)); - } - } - try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) { - completableFuture.complete(JsonParser.parseReader(reader).getAsJsonObject()); - } finally { - connection.disconnect(); - } - } catch (Throwable throwable) { - throwable.printStackTrace(); - completableFuture.completeExceptionally(throwable); - } - }); - completableFuture.whenComplete((response, throwable) -> { - if (completableFuture.isCompletedExceptionally()) { - skinFetcherResult.onDone(null, throwable); - } else { - JsonObject jsonObject = response.getAsJsonObject(this.builder.getAPIServer().getValueKey()); - JsonObject properties = jsonObject.getAsJsonObject(this.builder.getAPIServer().getSignatureKey()); - skinFetcherResult.onDone(new NPCSkin(properties.get("value").getAsString(), properties.get("signature").getAsString()), null); - } - }); - return completableFuture; - } - - private String getData() { - return this.builder.isProfileType() ? ("/" + this.builder.getData()) : ""; - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherBuilder.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherBuilder.java deleted file mode 100644 index 60efaa8..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherBuilder.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.github.znetworkw.znpcservers.skin; - -public class SkinFetcherBuilder { - private final SkinServer apiServer; - - private final String name; - - protected SkinFetcherBuilder(SkinServer apiServer, String name) { - this.apiServer = apiServer; - this.name = name; - } - - public static SkinFetcherBuilder create(SkinServer skinAPIURL, String name) { - return new SkinFetcherBuilder(skinAPIURL, name); - } - - public static SkinFetcherBuilder withName(String name) { - return create(name.startsWith("http") ? SkinServer.GENERATE_API : SkinServer.PROFILE_API, name); - } - - public SkinServer getAPIServer() { - return this.apiServer; - } - - public String getData() { - return this.name; - } - - public boolean isUrlType() { - return (this.apiServer == SkinServer.GENERATE_API); - } - - public boolean isProfileType() { - return (this.apiServer == SkinServer.PROFILE_API); - } - - public SkinFetcher toSkinFetcher() { - return new SkinFetcher(this); - } - - public enum SkinServer { - PROFILE_API("GET", "https://api.ashcon.app/mojang/v2/user", "textures", "raw"), - GENERATE_API("POST", "https://api.mineskin.org/generate/url", "data", "texture"); - - private final String method; - - private final String url; - - private final String valueKey; - - private final String signatureKey; - - SkinServer(String method, String url, String valueKey, String signatureKey) { - this.method = method; - this.url = url; - this.valueKey = valueKey; - this.signatureKey = signatureKey; - } - - public String getMethod() { - return this.method; - } - - public String getURL() { - return this.url; - } - - public String getValueKey() { - return this.valueKey; - } - - public String getSignatureKey() { - return this.signatureKey; - } - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java b/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java deleted file mode 100644 index f1c54d6..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/skin/SkinFetcherResult.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.znetworkw.znpcservers.skin; - -import io.github.znetworkw.znpcservers.npc.NPCSkin; - -public interface SkinFetcherResult { - void onDone(NPCSkin npcSkin, Throwable paramThrowable); -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java b/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java index 5674204..0954960 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java +++ b/src/main/java/io/github/znetworkw/znpcservers/user/EventService.java @@ -1,6 +1,7 @@ package io.github.znetworkw.znpcservers.user; import lol.pyr.znpcsplus.ZNPCsPlus; +import lol.pyr.znpcsplus.user.User; import org.bukkit.event.Event; import java.util.ArrayList; @@ -34,21 +35,21 @@ public class EventService { ZNPCsPlus.SCHEDULER.runNextTick(() -> this.eventConsumers.forEach(consumer -> consumer.accept(event))); } - public static EventService addService(ZUser user, Class eventClass) { - if (EventService.hasService(user, eventClass)) throw new IllegalStateException(eventClass.getSimpleName() + " is already register for " + user.getUUID().toString()); + public static EventService addService(User user, Class eventClass) { + if (EventService.hasService(user, eventClass)) throw new IllegalStateException(eventClass.getSimpleName() + " is already register for " + user.getUuid().toString()); EventService service = new EventService<>(eventClass, new ArrayList<>()); user.getEventServices().add(service); - user.toPlayer().closeInventory(); + user.getPlayer().closeInventory(); return service; } @SuppressWarnings("unchecked") - public static EventService findService(ZUser user, Class eventClass) { + public static EventService findService(User user, Class eventClass) { Objects.requireNonNull(EventService.class); return user.getEventServices().stream().filter(eventService -> eventService.getEventClass().isAssignableFrom(eventClass)).map(EventService.class::cast).findFirst().orElse(null); } - public static boolean hasService(ZUser user, Class eventClass) { + public static boolean hasService(User user, Class eventClass) { return user.getEventServices().stream().anyMatch(eventService -> eventService.getEventClass() == eventClass); } } diff --git a/src/main/java/io/github/znetworkw/znpcservers/user/ZUser.java b/src/main/java/io/github/znetworkw/znpcservers/user/ZUser.java deleted file mode 100644 index 04e586f..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/user/ZUser.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.github.znetworkw.znpcservers.user; - -import com.mojang.authlib.GameProfile; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -import java.lang.reflect.InvocationTargetException; -import java.util.*; - -public class ZUser { - private static final Map USER_MAP = new HashMap<>(); - - private final Map lastClicked; - - private final List> eventServices; - - private final UUID uuid; - - private final GameProfile gameProfile; - - private final Object playerConnection; - - private boolean hasPath = false; - - private long lastInteract = 0L; - - public ZUser(UUID uuid) { - this.uuid = uuid; - this.lastClicked = new HashMap<>(); - this.eventServices = new ArrayList<>(); - try { - Object playerHandle = Reflections.GET_HANDLE_PLAYER_METHOD.get().invoke(toPlayer()); - this.gameProfile = (GameProfile) Reflections.GET_PROFILE_METHOD.get().invoke(playerHandle, new Object[0]); - this.playerConnection = Reflections.PLAYER_CONNECTION_FIELD.get().get(playerHandle); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new IllegalStateException("can't create user for player " + uuid.toString(), e.getCause()); - } - } - - public static ZUser find(UUID uuid) { - return USER_MAP.computeIfAbsent(uuid, ZUser::new); - } - - public static ZUser find(Player player) { - return find(player.getUniqueId()); - } - - public static void unregister(Player player) { - ZUser zUser = USER_MAP.get(player.getUniqueId()); - if (zUser == null) - throw new IllegalStateException("can't find user " + player.getUniqueId()); - USER_MAP.remove(player.getUniqueId()); - NPC.all().stream() - .filter(npc -> npc.getViewers().contains(zUser)) - .forEach(npc -> npc.delete(zUser)); - } - - public UUID getUUID() { - return this.uuid; - } - - public GameProfile getGameProfile() { - return this.gameProfile; - } - - public Object getPlayerConnection() { - return this.playerConnection; - } - - public boolean isHasPath() { - return this.hasPath; - } - - public void setHasPath(boolean hasPath) { - this.hasPath = hasPath; - } - - public List> getEventServices() { - return this.eventServices; - } - - public Player toPlayer() { - return Bukkit.getPlayer(this.uuid); - } - - public long getLastInteract() { - return lastInteract; - } - - public Map getLastClicked() { - return lastClicked; - } - - public void updateLastInteract() { - this.lastInteract = System.nanoTime(); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/utility/location/ZLocation.java b/src/main/java/io/github/znetworkw/znpcservers/utility/location/ZLocation.java deleted file mode 100644 index aaf366d..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/utility/location/ZLocation.java +++ /dev/null @@ -1,137 +0,0 @@ -package io.github.znetworkw.znpcservers.utility.location; - -import com.github.retrooper.packetevents.util.Vector3d; -import com.google.common.base.Preconditions; -import com.google.gson.*; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.util.NumberConversions; -import org.bukkit.util.Vector; - -import java.lang.reflect.Type; - -public class ZLocation { - public static final ZLocationSerializer SERIALIZER = new ZLocationSerializer(); - private final String worldName; - private final double x; - private final double y; - private final double z; - private final float yaw; - private final float pitch; - - public ZLocation(String worldName, double x, double y, double z, float yaw, float pitch) { - this.worldName = worldName; - this.x = x; - this.y = y; - this.z = z; - this.yaw = yaw; - this.pitch = pitch; - } - - public ZLocation(Location location) { - this(Preconditions.checkNotNull(location.getWorld()).getName(), location - .getX(), location - .getY(), location - .getZ(), location - .getYaw(), location - .getPitch()); - } - - public String getWorldName() { - return this.worldName; - } - - public World getWorld() { - return Bukkit.getWorld(this.worldName); - } - - public double getX() { - return this.x; - } - - public double getY() { - return this.y; - } - - public double getZ() { - return this.z; - } - - public float getYaw() { - return this.yaw; - } - - public float getPitch() { - return this.pitch; - } - - public Location toBukkitLocation() { - return new Location(getWorld(), this.x, this.y, this.z, this.yaw, this.pitch); - } - - public Vector toVector() { - return new Vector(x, y, z); - } - - public Vector3d toVector3d() { - return new Vector3d(x, y, z); - } - - private static final double _2PI = 2 * Math.PI; - - public Location pointingTo(Location loc) { - return pointingTo(new ZLocation(loc)).toBukkitLocation(); - } - - public ZLocation pointingTo(ZLocation loc) { - /* - * Sin = Opp / Hyp - * Cos = Adj / Hyp - * Tan = Opp / Adj - * - * x = -Opp - * z = Adj - */ - final double x = loc.getX() - this.x; - final double z = loc.getZ() - this.z; - final double y = loc.getY() - this.y; - - if (x == 0 && z == 0) { - return new ZLocation(worldName, this.x, this.y, this.z, this.yaw, y > 0 ? -90 : 90); - } - - double x2 = NumberConversions.square(x); - double z2 = NumberConversions.square(z); - double xz = Math.sqrt(x2 + z2); - - double theta = Math.atan2(-x, z); - float yaw = (float) Math.toDegrees((theta + _2PI) % _2PI); - float pitch = (float) Math.toDegrees(Math.atan(-y / xz)); - - return new ZLocation(worldName, this.x, this.y, this.z, yaw, pitch); - } - - static class ZLocationSerializer implements JsonSerializer, JsonDeserializer { - public JsonElement serialize(ZLocation src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("world", src.getWorldName()); - jsonObject.addProperty("x", src.getX()); - jsonObject.addProperty("y", src.getY()); - jsonObject.addProperty("z", src.getZ()); - jsonObject.addProperty("yaw", src.getYaw()); - jsonObject.addProperty("pitch", src.getPitch()); - return jsonObject; - } - - public ZLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonObject jsonObject = json.getAsJsonObject(); - return new ZLocation(jsonObject.get("world").getAsString(), jsonObject - .get("x").getAsDouble(), jsonObject - .get("y").getAsDouble(), jsonObject - .get("z").getAsDouble(), jsonObject - .get("yaw").getAsFloat(), jsonObject - .get("pitch").getAsFloat()); - } - } -} diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index e096ed3..ec0c7ea 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -6,19 +6,14 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; -import io.github.znetworkw.znpcservers.commands.list.DefaultCommand; import io.github.znetworkw.znpcservers.configuration.Configuration; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; -import io.github.znetworkw.znpcservers.listeners.PlayerListener; -import io.github.znetworkw.znpcservers.npc.NPCPath; -import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener; -import io.github.znetworkw.znpcservers.user.ZUser; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; -import io.github.znetworkw.znpcservers.utility.location.ZLocation; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.interaction.InteractionPacketListener; import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.npc.NPCProperty; import lol.pyr.znpcsplus.npc.NPCRegistry; @@ -31,6 +26,8 @@ import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor; import lol.pyr.znpcsplus.tasks.NPCVisibilityTask; import lol.pyr.znpcsplus.updater.UpdateChecker; import lol.pyr.znpcsplus.updater.UpdateNotificationListener; +import lol.pyr.znpcsplus.user.User; +import lol.pyr.znpcsplus.user.UserListener; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.format.NamedTextColor; import org.apache.commons.io.FileUtils; @@ -50,7 +47,6 @@ public class ZNPCsPlus extends JavaPlugin { public static File PLUGIN_FOLDER; public static File PATH_FOLDER; public static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(ZLocation.class, ZLocation.SERIALIZER) .registerTypeHierarchyAdapter(ItemStack.class, new ItemStackSerializer()) .setPrettyPrinting() .disableHtmlEscaping() @@ -115,22 +111,18 @@ public class ZNPCsPlus extends JavaPlugin { PLUGIN_FOLDER.mkdirs(); PATH_FOLDER.mkdirs(); - log(ChatColor.WHITE + " * Loading paths..."); - loadAllPaths(); - log(ChatColor.WHITE + " * Registering components..."); getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); new Metrics(this, PLUGIN_ID); - new DefaultCommand(); SCHEDULER = new SchedulerUtils(this); BUNGEE_UTILS = new BungeeUtils(this); - Bukkit.getOnlinePlayers().forEach(ZUser::find); + Bukkit.getOnlinePlayers().forEach(User::get); log(ChatColor.WHITE + " * Starting tasks..."); new NPCVisibilityTask(this); - new PlayerListener(this); new InventoryListener(this); new SkinCacheCleanTask(this); + new UserListener(this); if (ConfigurationConstants.CHECK_FOR_UPDATES) new UpdateNotificationListener(this, new UpdateChecker(this)); enabled = true; @@ -171,18 +163,9 @@ public class ZNPCsPlus extends JavaPlugin { public void onDisable() { if (!enabled) return; Configuration.SAVE_CONFIGURATIONS.forEach(Configuration::save); - Bukkit.getOnlinePlayers().forEach(ZUser::unregister); + Bukkit.getOnlinePlayers().forEach(User::remove); ADVENTURE.close(); ADVENTURE = null; } - public void loadAllPaths() { - File[] files = PATH_FOLDER.listFiles(); - if (files == null) return; - for (File file : files) { - if (!file.getName().endsWith(".path")) continue; - NPCPath.AbstractTypeWriter abstractTypeWriter = NPCPath.AbstractTypeWriter.forFile(file, NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT); - abstractTypeWriter.load(); - } - } } diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/InteractionPacketListener.java b/src/main/java/lol/pyr/znpcsplus/interaction/InteractionPacketListener.java similarity index 73% rename from src/main/java/io/github/znetworkw/znpcservers/npc/interaction/InteractionPacketListener.java rename to src/main/java/lol/pyr/znpcsplus/interaction/InteractionPacketListener.java index dd97b22..71e58ab 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/interaction/InteractionPacketListener.java +++ b/src/main/java/lol/pyr/znpcsplus/interaction/InteractionPacketListener.java @@ -1,15 +1,16 @@ -package io.github.znetworkw.znpcservers.npc.interaction; +package lol.pyr.znpcsplus.interaction; import com.github.retrooper.packetevents.event.PacketListener; import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; -import io.github.znetworkw.znpcservers.npc.NPC; -import io.github.znetworkw.znpcservers.npc.NPCAction; -import io.github.znetworkw.znpcservers.user.ZUser; import lol.pyr.znpcsplus.ZNPCsPlus; +import lol.pyr.znpcsplus.npc.NPC; +import lol.pyr.znpcsplus.npc.NPCRegistry; +import lol.pyr.znpcsplus.user.User; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; import java.util.List; @@ -20,16 +21,12 @@ public class InteractionPacketListener implements PacketListener { Player player = (Player) event.getPlayer(); WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); - ZUser user = ZUser.find(player); + User user = User.get(player); + if (!user.canInteract()) return; - long lastInteract = System.nanoTime() - user.getLastInteract(); - if (user.getLastInteract() != 0L && lastInteract < 1000000000L) return; - - NPC npc = NPC.all().stream().filter(n -> n.getEntityID() == packet.getEntityId()).findFirst().orElse(null); + NPC npc = NPCRegistry.getByEntityId(packet.getEntityId()); if (npc == null) return; - ClickType clickType = ClickType.forName(packet.getAction().name()); - user.updateLastInteract(); ZNPCsPlus.SCHEDULER.runNextTick(() -> { Bukkit.getServer().getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); List actions = npc.getNpcPojo().getClickActions(); diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index bd14db7..0cbfeae 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -12,6 +12,8 @@ import java.util.Map; import java.util.Set; public class NPC { + protected static final Set _ALL_NPCS = new HashSet<>(); + private final Set viewers = new HashSet<>(); private final String worldName; private PacketEntity entity; @@ -25,6 +27,8 @@ public class NPC { this.type = type; this.location = location; entity = new PacketEntity(this, type.getType(), location); + + _ALL_NPCS.add(this); } public void setType(NPCType type) { @@ -56,6 +60,7 @@ public class NPC { } public void delete() { + _ALL_NPCS.remove(this); _hideAll(); viewers.clear(); } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java index de74b7d..44c1c29 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java @@ -12,7 +12,15 @@ public class NPCRegistry { } public static Collection all() { - return npcMap.values(); + return NPC._ALL_NPCS; + } + + public static NPC getByEntityId(int id) { + return all().stream().filter(npc -> npc.getEntity().getEntityId() == id).findFirst().orElse(null); + } + + public static Collection ids() { + return npcMap.keySet(); } public static void register(String id, NPC npc) { diff --git a/src/main/java/lol/pyr/znpcsplus/user/User.java b/src/main/java/lol/pyr/znpcsplus/user/User.java new file mode 100644 index 0000000..e6b7c18 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/user/User.java @@ -0,0 +1,55 @@ +package lol.pyr.znpcsplus.user; + +import io.github.znetworkw.znpcservers.user.EventService; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.*; + +public class User { + private final static Map USER_MAP = new HashMap<>(); + + public static User get(Player player) { + return get(player.getUniqueId()); + } + + public static User get(UUID uuid) { + return USER_MAP.computeIfAbsent(uuid, User::new); + } + + public static void remove(Player player) { + remove(player.getUniqueId()); + } + + public static void remove(UUID uuid) { + USER_MAP.remove(uuid); + } + + private final UUID uuid; + private long lastNPCInteraction; + private final List> eventServices = new ArrayList<>(); + + public User(UUID uuid) { + this.uuid = uuid; + } + + public Player getPlayer() { + return Bukkit.getPlayer(uuid); + } + + public boolean canInteract() { + if (System.currentTimeMillis() - lastNPCInteraction > 1000L) { + lastNPCInteraction = System.currentTimeMillis(); + return true; + } + return false; + } + + public List> getEventServices() { + return eventServices; + } + + public UUID getUuid() { + return uuid; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/user/UserListener.java b/src/main/java/lol/pyr/znpcsplus/user/UserListener.java new file mode 100644 index 0000000..3c9a2f3 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/user/UserListener.java @@ -0,0 +1,38 @@ +package lol.pyr.znpcsplus.user; + +import io.github.znetworkw.znpcservers.user.EventService; +import lol.pyr.znpcsplus.ZNPCsPlus; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class UserListener implements Listener { + public UserListener(ZNPCsPlus plugin) { + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + User.get(event.getPlayer()); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + User.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onTalk(AsyncPlayerChatEvent event) { + User zUser = User.get(event.getPlayer()); + if (EventService.hasService(zUser, AsyncPlayerChatEvent.class)) { + event.setCancelled(true); + EventService eventService = EventService.findService(zUser, AsyncPlayerChatEvent.class); + eventService.runAll(event); + zUser.getEventServices().remove(eventService); + } + } +} From eb6d1fc5c968e7041b0caaac649ef7403384f12f Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 25 Apr 2023 18:14:15 +0100 Subject: [PATCH 17/22] actions base --- .../exception/CommandException.java | 22 ---------------- .../exception/CommandExecuteException.java | 7 ------ .../exception/CommandPermissionException.java | 7 ------ .../inventory => gui}/ConversationGUI.java | 6 ++--- .../InteractionPacketListener.java | 18 +++---------- .../pyr/znpcsplus/interaction/NPCAction.java | 25 +++++++++++++++++++ src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 15 ++++++++--- .../java/lol/pyr/znpcsplus/user/User.java | 13 +++++++++- 8 files changed, 54 insertions(+), 59 deletions(-) delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/exception/CommandException.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/exception/CommandExecuteException.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/exception/CommandPermissionException.java rename src/main/java/io/github/znetworkw/znpcservers/{commands/list/inventory => gui}/ConversationGUI.java (94%) create mode 100644 src/main/java/lol/pyr/znpcsplus/interaction/NPCAction.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/exception/CommandException.java b/src/main/java/io/github/znetworkw/znpcservers/exception/CommandException.java deleted file mode 100644 index ffc7fb8..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/exception/CommandException.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.znetworkw.znpcservers.exception; - -import java.io.Serial; - -/** - * @author xCodiq - 20/04/2023 - */ -public class CommandException extends Exception { - @Serial private static final long serialVersionUID = 1L; - - public CommandException(String message) { - super(message); - } - - public CommandException(String message, Throwable cause) { - super(message, cause); - } - - public CommandException(Throwable cause) { - super(cause); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/exception/CommandExecuteException.java b/src/main/java/io/github/znetworkw/znpcservers/exception/CommandExecuteException.java deleted file mode 100644 index 126db39..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/exception/CommandExecuteException.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.znetworkw.znpcservers.exception; - -public class CommandExecuteException extends CommandException { - public CommandExecuteException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/exception/CommandPermissionException.java b/src/main/java/io/github/znetworkw/znpcservers/exception/CommandPermissionException.java deleted file mode 100644 index 6fb767d..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/exception/CommandPermissionException.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.znetworkw.znpcservers.exception; - -public class CommandPermissionException extends CommandException { - public CommandPermissionException(String message) { - super(message); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/list/inventory/ConversationGUI.java b/src/main/java/io/github/znetworkw/znpcservers/gui/ConversationGUI.java similarity index 94% rename from src/main/java/io/github/znetworkw/znpcservers/commands/list/inventory/ConversationGUI.java rename to src/main/java/io/github/znetworkw/znpcservers/gui/ConversationGUI.java index d1ead88..8934342 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/list/inventory/ConversationGUI.java +++ b/src/main/java/io/github/znetworkw/znpcservers/gui/ConversationGUI.java @@ -1,4 +1,4 @@ -package io.github.znetworkw.znpcservers.commands.list.inventory; +package io.github.znetworkw.znpcservers.gui; import com.google.common.base.Joiner; import com.google.common.base.Splitter; @@ -65,7 +65,7 @@ public class ConversationGUI extends ZInventory { for (int i = slots - (getRows() - 9); i < min; ++i) { Conversation conversation = ConfigurationConstants.NPC_CONVERSATIONS.get(i); - this.addItem(ItemStackBuilder.forMaterial(Material.PAPER).setName(ChatColor.GREEN + conversation.getName()).setLore("&7this conversation has &b" + conversation.getTexts().size() + " &7texts,", "&7it will activate when a player is on a &b" + conversation.getRadius() + "x" + conversation.getRadius() + " &7radius,", "&7or when a player interacts with an npc.", "&7when the conversation is finish, there is a &b" + conversation.getDelay() + "s &7delay to start again.", "&f&lUSES", " &bLeft-click &7to manage texts.", " &bRight-click &7to add a new text.", " &bQ &7to change the radius.", " &bMiddle-click &7to change the cooldown.").build(), i - ((getRows() - 9) * (pageID - 1)), clickEvent -> { + this.addItem(ItemStackBuilder.forMaterial(Material.PAPER).setName(ChatColor.GREEN + conversation.getName()).setLore("&7this conversation has &b" + conversation.getTexts().size() + " &7texts,", "&7it will activate when a player is on a &b" + conversation.getRadius() + "x" + conversation.getRadius() + " &7radius,", "&7or when a player interacts with an npc.", "&7when the conversation is finish, there is a &b" + conversation.getCooldown() + "s &7delay to start again.", "&f&lUSES", " &bLeft-click &7to manage texts.", " &bRight-click &7to add a new text.", " &bQ &7to change the radius.", " &bMiddle-click &7to change the cooldown.").build(), i - ((getRows() - 9) * (pageID - 1)), clickEvent -> { if (clickEvent.getClick() == ClickType.DROP) { Utils.sendTitle(this.getPlayer(), "&b&lCHANGE RADIUS", "&7Type the new radius..."); EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { @@ -226,7 +226,7 @@ public class ConversationGUI extends ZInventory { for (int i = slots - (getRows() - 9); i < min; i++) { ConversationKey conversationKey = this.conversation.getTexts().get(i); - this.addItem(ItemStackBuilder.forMaterial(Material.NAME_TAG).setName(ChatColor.AQUA + conversationKey.getTextFormatted() + "....").setLore("&7this conversation text has a delay of &b" + conversationKey.getDelay() + "s &7to be executed,", "&7the sound for the text is &b" + (conversationKey.getSoundName() == null ? "NONE" : conversationKey.getSoundName()) + "&7,", "&7before sending the text there is a delay of &b" + conversationKey.getDelay() + "s", "&7the index for the text is &b" + i + "&7,", "&7and the conversation has currently &b" + conversationKey.getActions().size() + " actions&7.", "&f&lUSES", " &bLeft-click &7to change the position.", " &bRight-click &7to remove text.", " &bLeft-Shift-click &7to change the sound.", " &bMiddle-click &7to change the delay.", " &bRight-Shift-click &7to edit the text.", " &bQ &7to manage actions.").build(), i, clickEvent -> { + this.addItem(ItemStackBuilder.forMaterial(Material.NAME_TAG).setName(ChatColor.AQUA + conversationKey.getTextFormatted() + "....").setLore("&7this conversation text has a delay of &b" + conversationKey.getCooldown() + "s &7to be executed,", "&7the sound for the text is &b" + (conversationKey.getSoundName() == null ? "NONE" : conversationKey.getSoundName()) + "&7,", "&7before sending the text there is a delay of &b" + conversationKey.getCooldown() + "s", "&7the index for the text is &b" + i + "&7,", "&7and the conversation has currently &b" + conversationKey.getActions().size() + " actions&7.", "&f&lUSES", " &bLeft-click &7to change the position.", " &bRight-click &7to remove text.", " &bLeft-Shift-click &7to change the sound.", " &bMiddle-click &7to change the delay.", " &bRight-Shift-click &7to edit the text.", " &bQ &7to manage actions.").build(), i, clickEvent -> { if (clickEvent.getClick() == ClickType.SHIFT_LEFT) { Utils.sendTitle(this.getPlayer(), "&c&lCHANGE SOUND", "&7Type the new sound..."); EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { diff --git a/src/main/java/lol/pyr/znpcsplus/interaction/InteractionPacketListener.java b/src/main/java/lol/pyr/znpcsplus/interaction/InteractionPacketListener.java index 71e58ab..502efe2 100644 --- a/src/main/java/lol/pyr/znpcsplus/interaction/InteractionPacketListener.java +++ b/src/main/java/lol/pyr/znpcsplus/interaction/InteractionPacketListener.java @@ -8,11 +8,7 @@ import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.npc.NPCRegistry; import lol.pyr.znpcsplus.user.User; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; - -import java.util.List; public class InteractionPacketListener implements PacketListener { @Override @@ -28,17 +24,9 @@ public class InteractionPacketListener implements PacketListener { if (npc == null) return; ZNPCsPlus.SCHEDULER.runNextTick(() -> { - Bukkit.getServer().getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); - List actions = npc.getNpcPojo().getClickActions(); - if (actions == null) return; - for (NPCAction action : actions) { - if (action.getClickType() != ClickType.DEFAULT && action.getClickType() != clickType) continue; - if (action.getDelay() > 0) { - int actionId = npc.getNpcPojo().getClickActions().indexOf(action); - if (user.getLastClicked().containsKey(actionId) && System.nanoTime() - user.getLastClicked().get(actionId) < action.getFixedDelay()) continue; - user.getLastClicked().put(actionId, System.nanoTime()); - } - action.run(user, action.getAction()); + for (NPCAction action : npc.getActions()) { + if (action.getCooldown() > 0 && !user.actionCooldownCheck(action)) continue; + action.run(player); } }); } diff --git a/src/main/java/lol/pyr/znpcsplus/interaction/NPCAction.java b/src/main/java/lol/pyr/znpcsplus/interaction/NPCAction.java new file mode 100644 index 0000000..0b25459 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/interaction/NPCAction.java @@ -0,0 +1,25 @@ +package lol.pyr.znpcsplus.interaction; + +import org.bukkit.entity.Player; + +import java.util.UUID; + +public abstract class NPCAction { + private final UUID id; + private final long delay; + + protected NPCAction(long delay) { + this.id = UUID.randomUUID(); + this.delay = delay; + } + + public UUID getUuid() { + return id; + } + + public long getCooldown() { + return delay; + } + + public abstract void run(Player player); +} diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 0cbfeae..1a8c298 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -2,14 +2,12 @@ package lol.pyr.znpcsplus.npc; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.interaction.NPCAction; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; public class NPC { protected static final Set _ALL_NPCS = new HashSet<>(); @@ -21,6 +19,7 @@ public class NPC { private NPCType type; private final Map, Object> propertyMap = new HashMap<>(); + private final Set actions = new HashSet<>(); public NPC(World world, NPCType type, PacketLocation location) { this.worldName = world.getName(); @@ -124,4 +123,12 @@ public class NPC { public void removeProperty(NPCProperty key) { propertyMap.remove(key); } + + public Collection getActions() { + return Collections.unmodifiableSet(actions); + } + + public void addAction(NPCAction action) { + actions.add(action); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/user/User.java b/src/main/java/lol/pyr/znpcsplus/user/User.java index e6b7c18..eff4b04 100644 --- a/src/main/java/lol/pyr/znpcsplus/user/User.java +++ b/src/main/java/lol/pyr/znpcsplus/user/User.java @@ -1,6 +1,7 @@ package lol.pyr.znpcsplus.user; import io.github.znetworkw.znpcservers.user.EventService; +import lol.pyr.znpcsplus.interaction.NPCAction; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -27,6 +28,7 @@ public class User { private final UUID uuid; private long lastNPCInteraction; + private final Map actionCooldownMap = new HashMap<>(); private final List> eventServices = new ArrayList<>(); public User(UUID uuid) { @@ -38,7 +40,7 @@ public class User { } public boolean canInteract() { - if (System.currentTimeMillis() - lastNPCInteraction > 1000L) { + if (System.currentTimeMillis() - lastNPCInteraction > 100L) { lastNPCInteraction = System.currentTimeMillis(); return true; } @@ -52,4 +54,13 @@ public class User { public UUID getUuid() { return uuid; } + + public boolean actionCooldownCheck(NPCAction action) { + UUID id = action.getUuid(); + if (System.currentTimeMillis() - actionCooldownMap.getOrDefault(id, 0L) >= action.getCooldown()) { + actionCooldownMap.put(id, System.currentTimeMillis()); + return true; + } + return false; + } } From 0e9fab6e7a97ef4295eedab88014cb0203507b42 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 25 Apr 2023 18:49:27 +0100 Subject: [PATCH 18/22] respawn when a property changes --- src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 1a8c298..0518fc3 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -117,11 +117,15 @@ public class NPC { public void setProperty(NPCProperty key, T value) { if (value.equals(key.getDefaultValue())) removeProperty(key); - else propertyMap.put(key, value); + else { + propertyMap.put(key, value); + respawn(); + } } public void removeProperty(NPCProperty key) { propertyMap.remove(key); + respawn(); } public Collection getActions() { From 7a4899b2b578c7964c2f54ab4a2d18826e056b62 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 26 Apr 2023 00:31:49 +0100 Subject: [PATCH 19/22] holograms woo --- .../configuration/Configuration.java | 4 - .../znetworkw/znpcservers/npc/NPCType.java | 98 --- .../reflection/EnumPropertyCache.java | 43 -- .../reflection/ReflectionPackage.java | 13 - .../znpcservers/reflection/Reflections.java | 634 +----------------- .../types/ConstructorReflection.java | 44 -- .../reflection/types/EnumReflection.java | 18 - .../reflection/types/FieldReflection.java | 2 +- .../znetworkw/znpcservers/utility/Utils.java | 51 -- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 17 +- .../pyr/znpcsplus/entity/EntityProperty.java | 45 ++ .../pyr/znpcsplus/entity/PacketEntity.java | 25 +- .../pyr/znpcsplus/entity/PropertyHolder.java | 18 + .../lol/pyr/znpcsplus/hologram/Hologram.java | 38 ++ .../pyr/znpcsplus/hologram/HologramLine.java | 54 ++ .../znpcsplus/metadata/MetadataFactory.java | 4 + .../pyr/znpcsplus/metadata/V1_13Factory.java | 19 + .../pyr/znpcsplus/metadata/V1_14Factory.java | 2 +- .../pyr/znpcsplus/metadata/V1_8Factory.java | 18 + .../pyr/znpcsplus/metadata/V1_9Factory.java | 18 + src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 67 +- .../lol/pyr/znpcsplus/npc/NPCProperty.java | 42 -- .../java/lol/pyr/znpcsplus/npc/NPCType.java | 20 +- .../pyr/znpcsplus/packets/PacketFactory.java | 16 +- .../pyr/znpcsplus/packets/V1_14Factory.java | 9 +- .../pyr/znpcsplus/packets/V1_19Factory.java | 5 +- .../pyr/znpcsplus/packets/V1_8Factory.java | 54 +- .../pyr/znpcsplus/packets/V1_9Factory.java | 36 +- .../java/lol/pyr/znpcsplus/util/Viewable.java | 59 ++ 29 files changed, 396 insertions(+), 1077 deletions(-) delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/reflection/EnumPropertyCache.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/EntityProperty.java create mode 100644 src/main/java/lol/pyr/znpcsplus/entity/PropertyHolder.java create mode 100644 src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java create mode 100644 src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java create mode 100644 src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java delete mode 100644 src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java create mode 100644 src/main/java/lol/pyr/znpcsplus/util/Viewable.java diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java index 15d49c8..751c110 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java +++ b/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java @@ -1,6 +1,5 @@ package io.github.znetworkw.znpcservers.configuration; -import com.google.common.collect.ImmutableList; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.gson.internal.$Gson$Types; @@ -25,9 +24,6 @@ public class Configuration { private final Map configurationValues; public static final Configuration CONFIGURATION = new Configuration("config"); public static final Configuration MESSAGES = new Configuration("messages"); - public static final Configuration CONVERSATIONS = new Configuration("conversations"); - public static final Configuration DATA = new Configuration("data"); - public static final ImmutableList SAVE_CONFIGURATIONS = ImmutableList.of(CONVERSATIONS, DATA); protected Configuration(String name) { this(name, ZNPCsPlus.PLUGIN_FOLDER.toPath().resolve(name + ".json")); diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java b/src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java deleted file mode 100644 index 416fa87..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/NPCType.java +++ /dev/null @@ -1,98 +0,0 @@ -package io.github.znetworkw.znpcservers.npc; - -import io.github.znetworkw.znpcservers.utility.Utils; - -import static io.github.znetworkw.znpcservers.reflection.Reflections.*; - -/** - * Delete after information transferred - */ -@SuppressWarnings("unused") -public enum NPCType { - ALLAY(ENTITY_ALLAY_CLASS, -1.14), - ARMOR_STAND(ENTITY_ARMOR_STAND_CLASS, 0.2775, "setSmall", "setArms"), - AXOLOTL(ENTITY_AXOLOTL_CLASS, -1.395, "setVariant", "setAge"), - BAT(ENTITY_BAT_CLASS, -0.915, "setAwake"), - BEE(ENTITY_BEE_CLASS, -1.215, "setAnger", "setHasNectar", "setHasStung"), - BLAZE(ENTITY_BLAZE_CLASS, -0.015), - CAT(ENTITY_CAT_CLASS, -1.115, "setCatType", "setAge", "setCollarColor", "setTamed"), - CAVE_SPIDER(ENTITY_CAVE_SPIDER_CLASS, -1.315), - CHICKEN(ENTITY_CHICKEN_CLASS, -1.115, "setAge"), - COD(ENTITY_COD_CLASS, -1.515), - COW(ENTITY_COW_CLASS, -0.415, "setAge"), - CREEPER(ENTITY_CREEPER_CLASS, -0.115, "setPowered"), - DOLPHIN(ENTITY_DOLPHIN_CLASS, -1.215), - DONKEY(ENTITY_DONKEY_CLASS, -0.315, "setAge", "setCarryingChest"), - DROWNED(ENTITY_DROWNED_CLASS, 0.135), - ELDER_GUARDIAN(ENTITY_ELDER_GUARDIAN_CLASS, 0.182), - ENDER_DRAGON(ENTITY_ENDER_DRAGON_CLASS, 6.185, "setSilent"), - ENDERMAN(ENTITY_ENDERMAN_CLASS, 1.085), - ENDERMITE(ENTITY_ENDERMITE_CLASS, -1.515), - EVOKER(ENTITY_EVOKER_CLASS, 0.135, "setCurrentSpell"), - FOX(ENTITY_FOX_CLASS, -1.115, "setFoxType", "setSitting", "setSleeping", "setAge", "setCrouching"), - FROG(ENTITY_FROG_CLASS, -1.315, "setVariant"), - GHAST(ENTITY_GHAST_CLASS, 2.185), - GIANT(ENTITY_GIANT_ZOMBIE_CLASS, 10.185), - GLOW_SQUID(ENTITY_GLOW_SQUID_CLASS, -1.015), - GOAT(ENTITY_GOAT_CLASS, -0.515, "setScreamingGoat", "setAge", "setLeftHorn", "setRightHorn"), - GUARDIAN(ENTITY_GUARDIAN_CLASS, -0.965), - HORSE(ENTITY_HORSE_CLASS, -0.215, "setStyle", "setAge", "setColor", "setVariant"), - HOGLIN(ENTITY_HOGLIN_CLASS, -0.415, "setAge"), - HUSK(ENTITY_HUSK_CLASS, 0.135), - ILLUSIONER(ENTITY_ILLUSIONER_CLASS, 0.135), - IRON_GOLEM(ENTITY_IRON_GOLEM_CLASS, 0.885), - LLAMA(ENTITY_LLAMA_CLASS, 0.055, "setAge", "setColor"), - MAGMA_CUBE(ENTITY_MAGMA_CUBE_CLASS, 0.225, "setSize"), - MUSHROOM_COW(ENTITY_MUSHROOM_COW_CLASS, -0.415, "setAge", "setVariant"), - MULE(ENTITY_MULE_CLASS, -0.215, "setAge", "setCarryingChest"), - OCELOT(ENTITY_OCELOT_CLASS, -1.115, "setCatType", "setAge"), - PANDA(ENTITY_PANDA_CLASS, -0.565, "setAge", "setMainGene", "setHiddenGene"), - PARROT(ENTITY_PARROT_CLASS, -0.915, "setVariant", "setAge", "setSitting"), - PHANTOM(ENTITY_PHANTOM_CLASS, -1.315, "setSize"), - PIG(ENTITY_PIG_CLASS, -0.915, "setAge", "setSaddle"), - PIGLIN(ENTITY_PIGLIN_CLASS, 0.135, "setBaby"), - PIGLIN_BRUTE(ENTITY_PIGLIN_BRUTE_CLASS, 0.135, "setBaby"), - PILLAGER(ENTITY_PILLAGER_CLASS, 0.135), - PLAYER(ENTITY_PLAYER_CLASS, 0.0), - POLAR_BEAR(ENTITY_POLAR_BEAR_CLASS, -0.415, "setAge"), - PUFFERFISH(ENTITY_PUFFERFISH_CLASS, -1.115, "setPuffState"), - RABBIT(ENTITY_RABBIT_CLASS, -1.315, "setRabbitType"), - RAVAGER(ENTITY_RAVAGER_CLASS, 0.385), - SALMON(ENTITY_SALMON_CLASS, -1.415), - SHEEP(ENTITY_SHEEP_CLASS, -0.515, "setAge", "setSheared", "setColor"), - SHULKER(ENTITY_SHULKER_CLASS, -0.815, "setPeek", "setColor"), - SILVERFISH(ENTITY_SILVERFISH_CLASS, -1.515), - SKELETON(ENTITY_SKELETON_CLASS, 0.175, "setSkeletonType"), - SKELETON_HORSE(ENTITY_SKELETON_HORSE_CLASS, -0.215), - SLIME(ENTITY_SLIME_CLASS, 0.225, "setSize"), - SNOWMAN(ENTITY_SNOWMAN_CLASS, 0.085, "setHasPumpkin", "setDerp"), - SPIDER(ENTITY_SPIDER_CLASS, -0.915), - SQUID(ENTITY_SQUID_CLASS, -1.015), - STRAY(ENTITY_STRAY_CLASS, 0.175), - STRIDER(ENTITY_STRIDER_CLASS, -0.115, "setSaddled", "setShivering", "setBaby"), - TADPOLE(ENTITY_TADPOLE_CLASS, -1.515, "setAge"), - TRADER_LLAMA(ENTITY_TRADER_LLAMA_CLASS, 0.055, "setAge", "setColor"), - TROPICAL_FISH(ENTITY_TROPICAL_FISH_CLASS, -1.415, "setPattern", "setBodyColor", "setPatternColor"), - TURTLE(ENTITY_TURTLE, -1.415, "setAge"), - VEX(ENTITY_VEX_CLASS, -1.015, "setCharging"), - VILLAGER(ENTITY_VILLAGER_CLASS, 0.135, "setProfession", "setVillagerType", "setAge", "setVillagerLevel"), - VINDICATOR(ENTITY_VINDICATOR_CLASS, 0.135), - WANDERING_TRADER(ENTITY_WANDERING_TRADER_CLASS, 0.135), - WARDEN(ENTITY_WARDEN, 1.085, "setSilent"), - WITCH(ENTITY_WITCH_CLASS, 0.135), - WITHER(ENTITY_WITHER_CLASS, 1.685), - WITHER_SKELETON(ENTITY_WITHER_SKELETON_CLASS, 0.585), - WOLF(ENTITY_WOLF_CLASS, -0.965, "setSitting", "setTamed", "setAngry", "setAge", "setCollarColor"), - ZOGLIN(ENTITY_ZOGLIN_CLASS, -0.415, "setBaby"), - ZOMBIE(ENTITY_ZOMBIE_CLASS, 0.135, "setBaby"), - ZOMBIE_HORSE(ENTITY_ZOMBIE_HORSE_CLASS, -0.215, "setBaby"), - ZOMBIE_VILLAGER(ENTITY_ZOMBIE_VILLAGER_CLASS, 0.135, "setVillagerType", "setVillagerProfession", "setBaby"), - ZOMBIFIED_PIGLIN(Utils.versionNewer(16) ? ENTITY_ZOMBIFIED_PIGLIN_CLASS : null, 0.135, "setBaby"), - PIG_ZOMBIE(Utils.versionNewer(16) ? null : ENTITY_ZOMBIFIED_PIGLIN_CLASS, 0.135); - - NPCType(Class entityClass, String newName, double holoHeight, String ... methods) { - } - - NPCType(Class entityClass, double holoHeight, String ... customization) { - } -} \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/EnumPropertyCache.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/EnumPropertyCache.java deleted file mode 100644 index 2907ba3..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/EnumPropertyCache.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.github.znetworkw.znpcservers.reflection; - -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * Gonalez decided to make every single enum we load be stored in this map - * to make NPC property application easier however this is terribly inefficient - * for memory. The entire NPC property system will most likely need a rewrite. - */ -public class EnumPropertyCache { - protected static final ConcurrentMap CACHE = new ConcurrentHashMap<>(); - - public static Object find(String name, Class objectClass) { - return CACHE.get(new CacheKey(name, objectClass)); - } - - public static void register(String name, Object object, Class objectClass) { - CACHE.putIfAbsent(new CacheKey(name, objectClass), object); - } - - private static class CacheKey { - private final Class type; - private final String value; - - public CacheKey(String value, Class type) { - this.type = type; - this.value = value; - } - - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CacheKey classKey = (CacheKey) o; - return (Objects.equals(this.type, classKey.type) && Objects.equals(this.value, classKey.value)); - } - - public int hashCode() { - return Objects.hash(this.type, this.value); - } - } -} \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionPackage.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionPackage.java index b7a3df1..08f88db 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionPackage.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionPackage.java @@ -21,20 +21,7 @@ public class ReflectionPackage { * package string which is another quirk of the old server jars. */ public static final String MINECRAFT = join("net.minecraft", flattened ? "server." + Utils.getBukkitPackage() : ""); - - public static final String NETWORK = flattened ? MINECRAFT : join(MINECRAFT, "network"); - public static final String PROTOCOL = flattened ? MINECRAFT : join(MINECRAFT, "network.protocol"); - public static final String CHAT = flattened ? MINECRAFT : join(MINECRAFT, "network.chat"); - public static final String PACKET = flattened ? MINECRAFT : join(MINECRAFT, "network.protocol.game"); - public static final String SYNCHER = flattened ? MINECRAFT : join(MINECRAFT, "network.syncher"); public static final String ENTITY = flattened ? MINECRAFT : join(MINECRAFT, "world.entity"); - public static final String WORLD_ENTITY_PLAYER = flattened ? MINECRAFT : join(MINECRAFT, "world.entity.player"); - public static final String ITEM = flattened ? MINECRAFT : join(MINECRAFT, "world.item"); - public static final String WORLD_LEVEL = flattened ? MINECRAFT : join(MINECRAFT, "world.level"); - public static final String WORLD_SCORES = flattened ? MINECRAFT : join(MINECRAFT, "world.scores"); - public static final String SERVER_LEVEL = flattened ? MINECRAFT : join(MINECRAFT, "server.level"); - public static final String SERVER_NETWORK = flattened ? MINECRAFT : join(MINECRAFT, "server.network"); - public static final String SERVER = flattened ? MINECRAFT : join(MINECRAFT, "server"); // Simple method that joins all the non-null & non-empty arguments with a dot and returns the result public static String join(String... parts) { diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index 1ea090f..c6cf81a 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -2,663 +2,33 @@ package io.github.znetworkw.znpcservers.reflection; import com.mojang.authlib.GameProfile; import io.github.znetworkw.znpcservers.reflection.types.ClassReflection; -import io.github.znetworkw.znpcservers.reflection.types.ConstructorReflection; import io.github.znetworkw.znpcservers.reflection.types.FieldReflection; import io.github.znetworkw.znpcservers.reflection.types.MethodReflection; import io.github.znetworkw.znpcservers.utility.Utils; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandMap; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.Collection; -import java.util.List; -import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; /** - * Class containing all of the lazy-loaded reflections that the plugin uses to access - * inaccessible things from the server jar like packets, raw entity classes, etc. + * Class containing all of the lazy-loaded reflections that the plugin + * uses to accessinaccessible things from the server jar. */ public final class Reflections { - public static final Class ENUM_PLAYER_INFO_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutPlayerInfo$EnumPlayerInfoAction") - .withClassName("ClientboundPlayerInfoUpdatePacket$a")).get(); - - public static final Class PACKET_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PROTOCOL) - .withClassName("Packet")).get(); - public static final Class ENTITY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withClassName("Entity")).get(); - public static final Class ENTITY_LIVING = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withClassName("EntityLiving")).get(); - - public static final Class ENTITY_ALLAY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.allay") - .withClassName("Allay").setStrict(Utils.versionNewer(19))).get(); - - public static final Class ENTITY_AXOLOTL_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.axolotl") - .withClassName("Axolotl").setStrict(Utils.versionNewer(17))).get(); - - public static final Class ENTITY_ARMOR_STAND_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("decoration") - .withClassName("EntityArmorStand")).get(); - - public static final Class ENTITY_BAT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("ambient") - .withClassName("EntityBat")).get(); - - public static final Class ENTITY_BEE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityBee").setStrict(Utils.versionNewer(15))).get(); - - public static final Class ENTITY_BLAZE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityBlaze")).get(); - - public static final Class ENTITY_CAT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityCat").setStrict(Utils.versionNewer(14))).get(); - - public static final Class ENTITY_CAVE_SPIDER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityCaveSpider")).get(); - - public static final Class ENTITY_CHICKEN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityChicken")).get(); - - public static final Class ENTITY_COD_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityCod").setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_COW_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityCow")).get(); - - public static final Class ENTITY_CREEPER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityCreeper")).get(); - - public static final Class ENTITY_DOLPHIN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityDolphin").setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_DONKEY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.horse") - .withClassName("EntityHorseDonkey") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_DROWNED_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityDrowned") - .setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_ELDER_GUARDIAN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityGuardianElder") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_ENDER_DRAGON_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("boss.enderdragon") - .withClassName("EntityEnderDragon")).get(); - - public static final Class ENTITY_ENDERMAN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityEnderman")).get(); - - public static final Class ENTITY_ENDERMITE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityEndermite")).get(); - - public static final Class ENTITY_EVOKER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityEvoker").setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_FOX_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityFox").setStrict(Utils.versionNewer(14))).get(); - - public static final Class ENTITY_FROG_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.frog") - .withClassName("Frog").setStrict(Utils.versionNewer(19))).get(); - - public static final Class ENTITY_GHAST_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityGhast")).get(); - - public static final Class ENTITY_GIANT_ZOMBIE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityGiantZombie")).get(); - - public static final Class ENTITY_GLOW_SQUID_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withClassName("GlowSquid").setStrict(Utils.versionNewer(17))).get(); - - public static final Class ENTITY_GOAT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.goat") - .withClassName("Goat").setStrict(Utils.versionNewer(17))).get(); - - public static final Class ENTITY_GUARDIAN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityGuardian")).get(); - - public static final Class ENTITY_HORSE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.horse") - .withClassName("EntityHorse")).get(); - - public static final Class ENTITY_HOGLIN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster.hoglin") - .withClassName("EntityHoglin").setStrict(Utils.versionNewer(16))).get(); - - public static final Class ENTITY_HUSK_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityZombieHusk") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_ILLUSIONER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityIllagerIllusioner") - .setStrict(Utils.versionNewer(12))).get(); - - public static final Class ENTITY_IRON_GOLEM_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityIronGolem")).get(); - - public static final Class ENTITY_LLAMA_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.horse") - .withClassName("EntityLlama").setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_MAGMA_CUBE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityMagmaCube")).get(); - - public static final Class ENTITY_MUSHROOM_COW_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityMushroomCow")).get(); - - public static final Class ENTITY_MULE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.horse") - .withClassName("EntityHorseMule") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_OCELOT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityOcelot")).get(); - - public static final Class ENTITY_PANDA_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityPanda").setStrict(Utils.versionNewer(14))).get(); - - public static final Class ENTITY_PARROT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityParrot").setStrict(Utils.versionNewer(12))).get(); - - public static final Class ENTITY_PHANTOM_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityPhantom").setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_PIG_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityPig")).get(); - - public static final Class ENTITY_PIGLIN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster.piglin") - .withClassName("EntityPiglin").setStrict(Utils.versionNewer(16))).get(); - - public static final Class ENTITY_PIGLIN_BRUTE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster.piglin") - .withClassName("EntityPiglinBrute").setStrict(Utils.versionNewer(16))).get(); - - public static final Class ENTITY_PILLAGER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityPillager").setStrict(Utils.versionNewer(14))).get(); - - public static final Class ENTITY_PLAYER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SERVER_LEVEL) - .withClassName("EntityPlayer")).get(); - - public static final Class ENTITY_POLAR_BEAR_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityPolarBear").setStrict(Utils.versionNewer(10))).get(); - - public static final Class ENTITY_PUFFERFISH_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityPufferFish").setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_RABBIT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityRabbit")).get(); - - public static final Class ENTITY_RAVAGER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityRavager").setStrict(Utils.versionNewer(14))).get(); - - public static final Class ENTITY_SALMON_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntitySalmon").setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_SHEEP_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntitySheep")).get(); - - public static final Class ENTITY_SHULKER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityShulker").setStrict(Utils.versionNewer(9))).get(); - - public static final Class ENTITY_SILVERFISH_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntitySilverfish")).get(); - - public static final Class ENTITY_SKELETON_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntitySkeleton")).get(); - - public static final Class ENTITY_SKELETON_HORSE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.horse") - .withClassName("EntityHorseSkeleton") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_SLIME_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntitySlime")).get(); - - public static final Class ENTITY_SNOWMAN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntitySnowman")).get(); - - - public static final Class ENTITY_SPIDER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntitySpider")).get(); - - public static final Class ENTITY_SQUID_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntitySquid")).get(); - - public static final Class ENTITY_STRAY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntitySkeletonStray") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_STRIDER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityStrider") - .setStrict(Utils.versionNewer(16))).get(); - - public static final Class ENTITY_TADPOLE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.frog") - .withClassName("Tadpole") - .setStrict(Utils.versionNewer(19))).get(); - - public static final Class ENTITY_TRADER_LLAMA_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.horse") - .withClassName("EntityLlamaTrader") - .setStrict(Utils.versionNewer(14))).get(); - - public static final Class ENTITY_TROPICAL_FISH_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityTropicalFish").setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_TURTLE = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityTurtle").setStrict(Utils.versionNewer(13))).get(); - - public static final Class ENTITY_VEX_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityVex") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_VILLAGER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("npc") - .withClassName("EntityVillager")).get(); - - public static final Class ENTITY_VINDICATOR_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityVindicator").setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_WANDERING_TRADER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("npc") - .withClassName("EntityVillagerTrader") - .setStrict(Utils.versionNewer(14))).get(); - - public static final Class ENTITY_WARDEN = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster.warden") - .withClassName("EntityWarden") - .withClassName("Warden") - .setStrict(Utils.versionNewer(19))).get(); - - public static final Class ENTITY_WITCH_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityWitch")).get(); - - public static final Class ENTITY_WITHER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("boss.wither") - .withClassName("EntityWither")).get(); - - public static final Class ENTITY_WITHER_SKELETON_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntitySkeletonWither") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_WOLF_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal") - .withClassName("EntityWolf")).get(); - - public static final Class ENTITY_ZOGLIN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityZoglin").setStrict(Utils.versionNewer(16))).get(); - - public static final Class ENTITY_ZOMBIE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityZombie")).get(); - - public static final Class ENTITY_ZOMBIE_HORSE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("animal.horse") - .withClassName("EntityHorseZombie") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_ZOMBIE_VILLAGER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityZombieVillager") - .setStrict(Utils.versionNewer(11))).get(); - - public static final Class ENTITY_ZOMBIFIED_PIGLIN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withSubClass("monster") - .withClassName("EntityPigZombie")).get(); - - public static final Class ENTITY_TYPES_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withClassName("EntityTypes")).get(); - public static final Class ENTITY_HUMAN_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withSubClass("player") .withClassName("EntityHuman")).get(); - public static final Class ENUM_CHAT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.MINECRAFT) - .withClassName("EnumChatFormat")).get(); - - public static final Class I_CHAT_BASE_COMPONENT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.CHAT) - .withClassName("IChatBaseComponent")).get(); - - public static final Class DATA_WATCHER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) - .withClassName("DataWatcher") - .setStrict(Utils.versionNewer(9))).get(); - - public static final Class DATA_WATCHER_OBJECT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) - .withClassName("DataWatcherObject") - .setStrict(Utils.versionNewer(9))).get(); - - public static final Class DATA_WATCHER_REGISTRY = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) - .withClassName("DataWatcherRegistry") - .setStrict(Utils.versionNewer(9))).get(); - - public static final Class DATA_WATCHER_SERIALIZER = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) - .withClassName("DataWatcherSerializer") - .setStrict(Utils.versionNewer(9))).get(); - - public static final Class WORLD_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_LEVEL) - .withClassName("World")).get(); - - public static final Class WORLD_SERVER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SERVER_LEVEL) - .withClassName("WorldServer")).get(); - - public static final Class MINECRAFT_SERVER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SERVER) - .withClassName("MinecraftServer")).get(); - - public static final Class PLAYER_INTERACT_MANAGER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SERVER_LEVEL) - .withClassName("PlayerInteractManager")).get(); - - public static final Class PLAYER_CONNECTION_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SERVER_NETWORK) - .withClassName("PlayerConnection")).get(); - - public static final Class PACKET_PLAY_OUT_PLAYER_INFO_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutPlayerInfo") - .withClassName("ClientboundPlayerInfoUpdatePacket")).get(); - - public static final Class PACKET_PLAY_OUT_SCOREBOARD_TEAM_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutScoreboardTeam")).get(); - - public static final Class SCOREBOARD_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_SCORES) - .withClassName("Scoreboard")).get(); - - public static final Class SCOREBOARD_TEAM_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_SCORES) - .withClassName("ScoreboardTeam")).get(); - - public static final Class ENUM_TAG_VISIBILITY = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_SCORES) - .withClassName("ScoreboardTeamBase$EnumNameTagVisibility")).get(); - - public static final Class CRAFT_CHAT_MESSAGE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) - .withClassName("util.CraftChatMessage")).get(); - - public static final Class PROFILE_PUBLIC_KEY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_ENTITY_PLAYER) - .withClassName("ProfilePublicKey") - .setStrict(Utils.versionNewer(19))).get(); - - public static final ReflectionLazyLoader> SCOREBOARD_TEAM_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(SCOREBOARD_TEAM_CLASS) - .withParameterTypes(SCOREBOARD_CLASS, String.class)); - - public static final ReflectionLazyLoader> PLAYER_CONSTRUCTOR_OLD = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_PLAYER_CLASS) - .withParameterTypes(MINECRAFT_SERVER_CLASS, WORLD_SERVER_CLASS, GameProfile.class, PLAYER_INTERACT_MANAGER_CLASS)); - - public static final ReflectionLazyLoader> PLAYER_CONSTRUCTOR_NEW = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_PLAYER_CLASS) - .withParameterTypes(MINECRAFT_SERVER_CLASS, WORLD_SERVER_CLASS, GameProfile.class)); - - public static final ReflectionLazyLoader> PLAYER_CONSTRUCTOR_NEW_1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_PLAYER_CLASS) - .withParameterTypes(MINECRAFT_SERVER_CLASS, WORLD_SERVER_CLASS, GameProfile.class, PROFILE_PUBLIC_KEY_CLASS) - .setStrict(false)); - - public static final ReflectionLazyLoader> PLAYER_CONSTRUCTOR_NEW_2 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_PLAYER_CLASS) - .withParameterTypes(MINECRAFT_SERVER_CLASS, WORLD_SERVER_CLASS, GameProfile.class)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_PLAYER_INFO_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(PACKET_PLAY_OUT_PLAYER_INFO_CLASS) - .withParameterTypes(ENUM_PLAYER_INFO_CLASS, (Utils.BUKKIT_VERSION > 16) ? Collection.class : Iterable.class).withParameterTypes(ENUM_PLAYER_INFO_CLASS, ENTITY_PLAYER_CLASS)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_ENTITY_LOOK_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutEntity$PacketPlayOutEntityLook") - .withParameterTypes(int.class, byte.class, byte.class, boolean.class)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_ENTITY_HEAD_ROTATION_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutEntityHeadRotation") - .withParameterTypes(ENTITY_CLASS, byte.class)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_ENTITY_TELEPORT_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutEntityTeleport") - .withParameterTypes(ENTITY_CLASS)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutEntityMetadata") - .withParameterTypes(int.class, DATA_WATCHER_CLASS, boolean.class) - .setStrict(false)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutEntityMetadata") - .withParameterTypes(int.class, List.class)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_SPAWN_ENTITY_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutSpawnEntity") - .withClassName("PacketPlayOutSpawnEntityLiving") - .withParameterTypes(ENTITY_LIVING).withParameterTypes(ENTITY_CLASS)); - - public static final ReflectionLazyLoader> PLAYER_INTERACT_MANAGER_OLD_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PlayerInteractManager") - .withParameterTypes(WORLD_CLASS)); - - public static final ReflectionLazyLoader> PLAYER_INTERACT_MANAGER_NEW_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PlayerInteractManager") - .withParameterTypes(WORLD_SERVER_CLASS)); - - public static final ReflectionLazyLoader> PACKET_PLAY_OUT_SCOREBOARD_TEAM_CONSTRUCTOR_OLD = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(PACKET_PLAY_OUT_SCOREBOARD_TEAM_CLASS)); - - public static final ReflectionLazyLoader> I_CHAT_BASE_COMPONENT_A_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.CHAT) - .withClassName("ChatComponentText") - .withParameterTypes(String.class)); - - public static final ReflectionLazyLoader> ENTITY_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_ARMOR_STAND_CLASS) - .withParameterTypes(WORLD_CLASS, double.class, double.class, double.class)); - - public static final ReflectionLazyLoader> DATA_WATCHER_OBJECT_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(DATA_WATCHER_OBJECT) - .withParameterTypes(int.class, DATA_WATCHER_SERIALIZER)); - public static final ReflectionLazyLoader GET_PROFILE_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withClassName(ENTITY_HUMAN_CLASS) .withExpectResult(GameProfile.class)); - public static final ReflectionLazyLoader GET_ENTITY_ID = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_CLASS) - .withMethodName("getId") - .withMethodName("ae") - .withMethodName("ah") - .withMethodName("af") - .withExpectResult(int.class)); - public static final ReflectionLazyLoader GET_HANDLE_PLAYER_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) .withClassName("entity.CraftPlayer").withClassName("entity.CraftHumanEntity") .withMethodName("getHandle")); - public static final ReflectionLazyLoader GET_HANDLE_WORLD_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) - .withClassName("CraftWorld") - .withMethodName("getHandle")); - - public static final ReflectionLazyLoader GET_SERVER_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) - .withClassName("CraftServer") - .withMethodName("getServer")); - - public static final ReflectionLazyLoader SEND_PACKET_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(PLAYER_CONNECTION_CLASS) - .withMethodName("sendPacket").withMethodName("a") - .withParameterTypes(PACKET_CLASS)); - - public static final ReflectionLazyLoader SET_CUSTOM_NAME_OLD_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_CLASS) - .withMethodName("setCustomName") - .withParameterTypes(String.class)); - - public static final ReflectionLazyLoader SET_CUSTOM_NAME_NEW_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_CLASS) - .withMethodName("setCustomName") - .withMethodName("a") - .withMethodName("b") - .withParameterTypes(I_CHAT_BASE_COMPONENT).withExpectResult(void.class)); - - public static final ReflectionLazyLoader SET_CUSTOM_NAME_VISIBLE_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_CLASS) - .withMethodName("setCustomNameVisible") - .withMethodName("n") - .withParameterTypes(boolean.class)); - - public static final ReflectionLazyLoader SET_INVISIBLE_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_ARMOR_STAND_CLASS) - .withMethodName("setInvisible").withMethodName("j") - .withParameterTypes(boolean.class)); - - public static final ReflectionLazyLoader SET_LOCATION_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_CLASS) - .withMethodName("setPositionRotation") - .withMethodName("a") - .withParameterTypes(double.class, double.class, double.class, float.class, float.class)); - - public static final ReflectionLazyLoader SET_DATA_WATCHER_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(DATA_WATCHER_CLASS) - .withMethodName("set").withMethodName("b") - .withParameterTypes(DATA_WATCHER_OBJECT, Object.class)); - - public static final ReflectionLazyLoader WATCH_DATA_WATCHER_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(DATA_WATCHER_CLASS) - .withMethodName("watch") - .withParameterTypes(int.class, Object.class)); - - public static final ReflectionLazyLoader GET_DATA_WATCHER_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_CLASS) - .withMethodName("getDataWatcher") - .withMethodName("ai") - .withMethodName("al") - .withMethodName("aj") - .withExpectResult(DATA_WATCHER_CLASS)); - - public static final ReflectionLazyLoader GET_BUKKIT_ENTITY_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENTITY_CLASS) - .withMethodName("getBukkitEntity")); - - public static final ReflectionLazyLoader GET_ENUM_CHAT_ID_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENUM_CHAT_CLASS) - .withMethodName("b")); - - public static final ReflectionLazyLoader ENUM_CHAT_TO_STRING_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENUM_CHAT_CLASS) - .withExpectResult(String.class) - .withMethodName("toString")); - - public static final ReflectionLazyLoader ENTITY_TYPES_A_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) - .withClassName(ENTITY_TYPES_CLASS) - .withMethodName("a") - .withParameterTypes(String.class)); - - public static final ReflectionLazyLoader PACKET_PLAY_OUT_SCOREBOARD_TEAM_CREATE_V1 = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(PACKET_PLAY_OUT_SCOREBOARD_TEAM_CLASS) - .withMethodName("a") - .withParameterTypes(SCOREBOARD_TEAM_CLASS)); - - public static final ReflectionLazyLoader PACKET_PLAY_OUT_SCOREBOARD_TEAM_CREATE = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(PACKET_PLAY_OUT_SCOREBOARD_TEAM_CLASS) - .withMethodName("a") - .withParameterTypes(SCOREBOARD_TEAM_CLASS, boolean.class)); - - public static final ReflectionLazyLoader SCOREBOARD_PLAYER_LIST = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(SCOREBOARD_TEAM_CLASS) - .withMethodName("getPlayerNameSet").withMethodName("g")); - - public static final ReflectionLazyLoader ENUM_CHAT_FORMAT_FIND = new MethodReflection(new ReflectionBuilder(ReflectionPackage.MINECRAFT) - .withClassName(ENUM_CHAT_CLASS) - .withParameterTypes(String.class).withExpectResult(ENUM_CHAT_CLASS)); - - public static final ReflectionLazyLoader CRAFT_CHAT_MESSAGE_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) - .withClassName(CRAFT_CHAT_MESSAGE_CLASS) - .withMethodName("fromStringOrNull") - .withParameterTypes(String.class)); - - public static final ReflectionLazyLoader GET_UNIQUE_ID_METHOD = new MethodReflection(new ReflectionBuilder(ReflectionPackage.MINECRAFT) - .withClassName(ENTITY_CLASS) - .withExpectResult(UUID.class)); - - public static final ReflectionLazyLoader GET_DATAWATCHER_B_LIST = new MethodReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withMethodName("c") - .withClassName(DATA_WATCHER_CLASS)); - - public static final ReflectionLazyLoader PLAYER_CONNECTION_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.SERVER_LEVEL) - .withClassName(ENTITY_PLAYER_CLASS) - .withFieldName((Utils.BUKKIT_VERSION > 16) ? "b" : "playerConnection")); - - public static final ReflectionLazyLoader ADD_PLAYER_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("PacketPlayOutPlayerInfo$EnumPlayerInfoAction") - .withClassName("ClientboundPlayerInfoUpdatePacket$a") - .withFieldName((Utils.BUKKIT_VERSION > 16) ? "a" : "ADD_PLAYER")).staticValueLoader(); - - public static final ReflectionLazyLoader UPDATE_LISTED_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("ClientboundPlayerInfoUpdatePacket$a") - .withFieldName("d")).staticValueLoader(); - - public static final ReflectionLazyLoader DATA_WATCHER_REGISTER_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(DATA_WATCHER_REGISTRY) - .withFieldName("a")).staticValueLoader(); - - public static final ReflectionLazyLoader ENUM_TAG_VISIBILITY_NEVER_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName(ENUM_TAG_VISIBILITY) - .withFieldName("b")).staticValueLoader(); - - public static final ReflectionLazyLoader COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) - .withClassName("CraftServer") - .withFieldName("commandMap")).valueLoader(Bukkit.getServer(), CommandMap.class); - public static final FieldReflection.ValueModifier ENTITY_ID_MODIFIER = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withClassName(ENTITY_CLASS) .withFieldName("entityCount") diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java deleted file mode 100644 index 87871b0..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.znetworkw.znpcservers.reflection.types; - -import com.google.common.collect.ImmutableList; -import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; -import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader; - -import java.lang.reflect.Constructor; -import java.util.Arrays; -import java.util.function.Consumer; - -public class ConstructorReflection extends ReflectionLazyLoader> { - private final ImmutableList[]> parameterTypes; - - public ConstructorReflection(ReflectionBuilder reflectionBuilder) { - super(reflectionBuilder); - this.parameterTypes = reflectionBuilder.getParameterTypes(); - } - - protected Constructor load() throws NoSuchMethodException { - for (Class clazz : this.reflectionClasses) { - Constructor constructor = load(clazz); - if (constructor != null) return constructor; - } - return null; - } - - private Constructor load(Class clazz) { - if (parameterTypes != null && parameterTypes.size() > 0) for (Class[] possibleConstructor : parameterTypes) try { - Constructor constructor = clazz.getDeclaredConstructor(possibleConstructor); - constructor.setAccessible(true); - return constructor; - } catch (NoSuchMethodException ignored) {} - else try { - return clazz.getDeclaredConstructor(); - } catch (NoSuchMethodException ignored) {} - return null; - } - - @Override - protected void printDebugInfo(Consumer logger) { - logger.accept("Possible Parameter Type Combinations:"); - for (Class[] possible : parameterTypes) logger.accept(Arrays.toString(possible)); - } -} \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java deleted file mode 100644 index 43737ec..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.znetworkw.znpcservers.reflection.types; - -import io.github.znetworkw.znpcservers.reflection.EnumPropertyCache; -import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; -import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader; - -public class EnumReflection extends ReflectionLazyLoader[]> { - public EnumReflection(ReflectionBuilder reflectionBuilder) { - super(reflectionBuilder); - } - - protected Enum[] load() { - if (reflectionClasses.size() == 0) return null; - Enum[] enums = (Enum[]) this.reflectionClasses.get(0).getEnumConstants(); - for (Enum enumConstant : enums) EnumPropertyCache.register(enumConstant.name(), enumConstant, this.reflectionClasses.get(0)); - return enums; - } -} \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java index b222326..029e5b5 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java @@ -17,7 +17,7 @@ public class FieldReflection extends ReflectionLazyLoader { this.expectType = reflectionBuilder.getExpectType(); } - protected Field load() throws NoSuchFieldException { + protected Field load() { if (fieldName != null && fieldName.length() > 0) for (Class clazz : this.reflectionClasses) { Field field = loadByName(clazz); if (field != null) return field; diff --git a/src/main/java/io/github/znetworkw/znpcservers/utility/Utils.java b/src/main/java/io/github/znetworkw/znpcservers/utility/Utils.java index c33f47b..cc0fa04 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/utility/Utils.java +++ b/src/main/java/io/github/znetworkw/znpcservers/utility/Utils.java @@ -1,19 +1,10 @@ package io.github.znetworkw.znpcservers.utility; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; -import io.github.znetworkw.znpcservers.reflection.Reflections; -import io.github.znetworkw.znpcservers.user.ZUser; -import me.clip.placeholderapi.PlaceholderAPI; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.entity.Player; - -import java.lang.reflect.Field; -import java.util.concurrent.ThreadLocalRandom; public final class Utils { public static final int BUKKIT_VERSION; - public static boolean PLACEHOLDER_SUPPORT = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); static { int version = 0; @@ -39,46 +30,4 @@ public final class Utils { public static String toColor(String string) { return ChatColor.translateAlternateColorCodes('&', string); } - - public static String getWithPlaceholders(String string, Player player) { - return PlaceholderAPI.setPlaceholders(player, string).replace(ConfigurationConstants.SPACE_SYMBOL, " "); - } - - public static String randomString(int length) { - StringBuilder stringBuilder = new StringBuilder(); - for (int index = 0; index < length; index++) - stringBuilder.append(ThreadLocalRandom.current().nextInt(0, 9)); - return stringBuilder.toString(); - } - - public static void sendTitle(Player player, String title, String subTitle) { - player.sendTitle(toColor(title), toColor(subTitle), 20, 60, 20); - } - - public static void setValue(Object fieldInstance, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { - Field f = fieldInstance.getClass().getDeclaredField(fieldName); - f.setAccessible(true); - f.set(fieldInstance, value); - } - - public static void setValue(Object fieldInstance, Object value, Class expectedType) throws NoSuchFieldException, IllegalAccessException { - for (Field field : fieldInstance.getClass().getDeclaredFields()) { - if (field.getType() == expectedType) - setValue(fieldInstance, field.getName(), value); - } - } - - public static Object getValue(Object instance, String fieldName) throws NoSuchFieldException, IllegalAccessException { - Field f = instance.getClass().getDeclaredField(fieldName); - f.setAccessible(true); - return f.get(instance); - } - - public static void sendPackets(ZUser user, Object... packets) { - try { - for (Object packet : packets) if (packet != null) Reflections.SEND_PACKET_METHOD.get().invoke(user.getPlayerConnection(), packet); - } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException e) { - e.printStackTrace(); - } - } } diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index ec0c7ea..2b30206 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -6,16 +6,15 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; -import io.github.znetworkw.znpcservers.configuration.Configuration; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; +import lol.pyr.znpcsplus.entity.EntityProperty; import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.interaction.InteractionPacketListener; import lol.pyr.znpcsplus.npc.NPC; -import lol.pyr.znpcsplus.npc.NPCProperty; import lol.pyr.znpcsplus.npc.NPCRegistry; import lol.pyr.znpcsplus.npc.NPCType; import lol.pyr.znpcsplus.skin.cache.SkinCache; @@ -138,11 +137,11 @@ public class ZNPCsPlus extends JavaPlugin { for (NPCType type : NPCType.values()) { NPC npc = new NPC(world, type, new PacketLocation(x * 3, 200, z * 3, 0, 0)); if (type.getType() == EntityTypes.PLAYER) { - SkinCache.fetchByName("Notch").thenAccept(skin -> npc.setProperty(NPCProperty.SKIN, new PrefetchedDescriptor(skin))); - npc.setProperty(NPCProperty.INVISIBLE, true); + SkinCache.fetchByName("Notch").thenAccept(skin -> npc.setProperty(EntityProperty.SKIN, new PrefetchedDescriptor(skin))); + npc.setProperty(EntityProperty.INVISIBLE, true); } - npc.setProperty(NPCProperty.GLOW, NamedTextColor.RED); - npc.setProperty(NPCProperty.FIRE, true); + npc.setProperty(EntityProperty.GLOW, NamedTextColor.RED); + npc.setProperty(EntityProperty.FIRE, true); NPCRegistry.register("debug_npc" + (z * wrap + x), npc); if (x++ > wrap) { x = 0; @@ -150,11 +149,11 @@ public class ZNPCsPlus extends JavaPlugin { } } NPC npc = new NPC(world, NPCType.byName("player"), new PacketLocation(x * 3, 200, z * 3, 0, 0)); - npc.setProperty(NPCProperty.SKIN, new FetchingDescriptor("jeb_")); + npc.setProperty(EntityProperty.SKIN, new FetchingDescriptor("jeb_")); NPCRegistry.register("debug_npc" + (z * wrap + x), npc); x++; npc = new NPC(world, NPCType.byName("player"), new PacketLocation(x * 3, 200, z * 3, 0, 0)); - npc.setProperty(NPCProperty.SKIN, new MirrorDescriptor()); + npc.setProperty(EntityProperty.SKIN, new MirrorDescriptor()); NPCRegistry.register("debug_npc" + (z * wrap + x), npc); } } @@ -162,10 +161,8 @@ public class ZNPCsPlus extends JavaPlugin { @Override public void onDisable() { if (!enabled) return; - Configuration.SAVE_CONFIGURATIONS.forEach(Configuration::save); Bukkit.getOnlinePlayers().forEach(User::remove); ADVENTURE.close(); ADVENTURE = null; } - } diff --git a/src/main/java/lol/pyr/znpcsplus/entity/EntityProperty.java b/src/main/java/lol/pyr/znpcsplus/entity/EntityProperty.java new file mode 100644 index 0000000..31f2776 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/EntityProperty.java @@ -0,0 +1,45 @@ +package lol.pyr.znpcsplus.entity; + +import lol.pyr.znpcsplus.skin.SkinDescriptor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; + +import java.util.HashMap; +import java.util.Map; + +public class EntityProperty { + private final String name; + private final T defaultValue; + + public EntityProperty(String name) { + this(name, null); + } + + public EntityProperty(String name, T defaultValue) { + this.name = name.toUpperCase(); + this.defaultValue = defaultValue; + BY_NAME.put(this.name, this); + } + + public String name() { + return name; + } + + public T getDefaultValue() { + return defaultValue; + } + + private final static Map> BY_NAME = new HashMap<>(); + + public static EntityProperty getByName(String name) { + return BY_NAME.get(name.toUpperCase()); + } + + public static EntityProperty SKIN_LAYERS = new EntityProperty<>("skin_layers", true); + public static EntityProperty SKIN = new EntityProperty<>("skin"); + public static EntityProperty GLOW = new EntityProperty<>("glow"); + public static EntityProperty FIRE = new EntityProperty<>("fire", false); + public static EntityProperty INVISIBLE = new EntityProperty<>("invisible", false); + public static EntityProperty SILENT = new EntityProperty<>("silent", false); + public static EntityProperty NAME = new EntityProperty<>("name"); +} \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index bfe8075..e98ed6b 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -4,23 +4,22 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import io.github.znetworkw.znpcservers.reflection.Reflections; import io.github.znetworkw.znpcservers.utility.Utils; -import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.packets.PacketFactory; import org.bukkit.entity.Player; -import java.util.Set; +import java.util.Collection; import java.util.UUID; public class PacketEntity { - private final NPC owner; + private final PropertyHolder properties; private final int entityId; private final UUID uuid; private final EntityType type; private PacketLocation location; - public PacketEntity(NPC owner, EntityType type, PacketLocation location) { - this.owner = owner; + public PacketEntity(PropertyHolder properties, EntityType type, PacketLocation location) { + this.properties = properties; this.entityId = reserveEntityID(); this.uuid = UUID.randomUUID(); this.type = type; @@ -43,22 +42,22 @@ public class PacketEntity { return type; } - public NPC getOwner() { - return owner; - } - - public void setLocation(PacketLocation location, Set viewers) { + public void setLocation(PacketLocation location, Collection viewers) { this.location = location; for (Player viewer : viewers) PacketFactory.get().teleportEntity(viewer, this); } public void spawn(Player player) { - if (type == EntityTypes.PLAYER) PacketFactory.get().spawnPlayer(player, this); - else PacketFactory.get().spawnEntity(player, this); + if (type == EntityTypes.PLAYER) PacketFactory.get().spawnPlayer(player, this, properties); + else PacketFactory.get().spawnEntity(player, this, properties); } public void despawn(Player player) { - PacketFactory.get().destroyEntity(player, this); + PacketFactory.get().destroyEntity(player, this, properties); + } + + public void refreshMeta(Player player) { + PacketFactory.get().sendAllMetadata(player, this, properties); } private static int reserveEntityID() { diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PropertyHolder.java b/src/main/java/lol/pyr/znpcsplus/entity/PropertyHolder.java new file mode 100644 index 0000000..a776fcb --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/entity/PropertyHolder.java @@ -0,0 +1,18 @@ +package lol.pyr.znpcsplus.entity; + +public interface PropertyHolder { + T getProperty(EntityProperty key); + boolean hasProperty(EntityProperty key); + + PropertyHolder EMPTY = new PropertyHolder() { + @Override + public T getProperty(EntityProperty key) { + return null; + } + + @Override + public boolean hasProperty(EntityProperty key) { + return false; + } + }; +} diff --git a/src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java b/src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java new file mode 100644 index 0000000..79a6e51 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java @@ -0,0 +1,38 @@ +package lol.pyr.znpcsplus.hologram; + +import lol.pyr.znpcsplus.util.Viewable; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public class Hologram extends Viewable { + private final List lines = new ArrayList<>(); + + public Hologram() { + + } + + public void addLine(Component line) { + lines.add(new HologramLine(null, line)); // TODO: Location + } + + public HologramLine getLine(int index) { + return lines.get(index); + } + + public void insertLine(int index, Component line) { + lines.add(index, new HologramLine(null, line)); // TODO: Location + } + + @Override + protected void _show(Player player) { + for (HologramLine line : lines) line.show(player); + } + + @Override + protected void _hide(Player player) { + for (HologramLine line : lines) line.hide(player); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java b/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java new file mode 100644 index 0000000..eeb48e3 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java @@ -0,0 +1,54 @@ +package lol.pyr.znpcsplus.hologram; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import lol.pyr.znpcsplus.entity.EntityProperty; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.entity.PropertyHolder; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public class HologramLine implements PropertyHolder { + private Component text; + private final PacketEntity armorStand; + + public HologramLine(PacketLocation location, Component text) { + this.text = text; + armorStand = new PacketEntity(this, EntityTypes.ARMOR_STAND, location); + } + + public Component getText() { + return text; + } + + public void setText(Component text) { + this.text = text; + } + + protected void show(Player player) { + armorStand.spawn(player); + } + + protected void hide(Player player) { + armorStand.despawn(player); + } + + public void setLocation(PacketLocation location, Collection viewers) { + armorStand.setLocation(location, viewers); + } + + @SuppressWarnings("unchecked") + @Override + public T getProperty(EntityProperty key) { + if (key == EntityProperty.INVISIBLE) return (T) Boolean.TRUE; + if (key == EntityProperty.NAME) return (T) text; + return null; + } + + @Override + public boolean hasProperty(EntityProperty key) { + return key == EntityProperty.NAME || key == EntityProperty.INVISIBLE; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java index 22c674d..c49b978 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java @@ -4,7 +4,9 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import lol.pyr.znpcsplus.util.LazyLoader; +import net.kyori.adventure.text.Component; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -25,6 +27,8 @@ import java.util.Map; public interface MetadataFactory { EntityData skinLayers(); EntityData effects(boolean onFire, boolean glowing, boolean invisible); + Collection name(Component name); + EntityData silent(); MetadataFactory factory = get(); diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java new file mode 100644 index 0000000..3e45cf5 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java @@ -0,0 +1,19 @@ +package lol.pyr.znpcsplus.metadata; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; +import net.kyori.adventure.text.Component; + +import java.util.Collection; +import java.util.List; + +public class V1_13Factory extends V1_8Factory { + @Override + public Collection name(Component name) { + return List.of( + new EntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, AdventureSerializer.getGsonSerializer().serialize(name)), + new EntityData(3, EntityDataTypes.BOOLEAN, true) + ); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java index af0efe8..e312af2 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_14Factory.java @@ -2,7 +2,7 @@ package lol.pyr.znpcsplus.metadata; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; -public class V1_14Factory extends V1_9Factory { +public class V1_14Factory extends V1_13Factory { @Override public EntityData skinLayers() { return createSkinLayers(15); diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java index 201aa2d..a669d85 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java @@ -2,6 +2,11 @@ package lol.pyr.znpcsplus.metadata; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; +import net.kyori.adventure.text.Component; + +import java.util.Collection; +import java.util.List; public class V1_8Factory implements MetadataFactory { @Override @@ -14,6 +19,19 @@ public class V1_8Factory implements MetadataFactory { return new EntityData(0, EntityDataTypes.BYTE, (onFire ? 0x01 : 0) | (invisible ? 0x20 : 0)); } + @Override + public Collection name(Component name) { + return List.of( + new EntityData(2, EntityDataTypes.STRING, AdventureSerializer.getGsonSerializer().serialize(name)), + new EntityData(3, EntityDataTypes.BYTE, 1) + ); + } + + @Override + public EntityData silent() { + return new EntityData(4, EntityDataTypes.BYTE, 1); + } + protected EntityData createSkinLayers(int index) { return new EntityData(index, EntityDataTypes.BYTE, Byte.MAX_VALUE); } diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java index 5e9ebc3..49fb334 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_9Factory.java @@ -2,6 +2,11 @@ package lol.pyr.znpcsplus.metadata; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; +import net.kyori.adventure.text.Component; + +import java.util.Collection; +import java.util.List; public class V1_9Factory extends V1_8Factory { @Override @@ -13,4 +18,17 @@ public class V1_9Factory extends V1_8Factory { public EntityData effects(boolean onFire, boolean glowing, boolean invisible) { return new EntityData(0, EntityDataTypes.BYTE, (byte) ((onFire ? 0x01 : 0) | (invisible ? 0x20 : 0) | (glowing ? 0x40 : 0))); } + + @Override + public Collection name(Component name) { + return List.of( + new EntityData(2, EntityDataTypes.STRING, AdventureSerializer.getGsonSerializer().serialize(name)), + new EntityData(3, EntityDataTypes.BOOLEAN, true) + ); + } + + @Override + public EntityData silent() { + return new EntityData(4, EntityDataTypes.BOOLEAN, true); + } } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 0518fc3..befc4c9 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -1,15 +1,18 @@ package lol.pyr.znpcsplus.npc; +import lol.pyr.znpcsplus.entity.EntityProperty; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; +import lol.pyr.znpcsplus.entity.PropertyHolder; import lol.pyr.znpcsplus.interaction.NPCAction; +import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; import java.util.*; -public class NPC { +public class NPC extends Viewable implements PropertyHolder { protected static final Set _ALL_NPCS = new HashSet<>(); private final Set viewers = new HashSet<>(); @@ -18,7 +21,7 @@ public class NPC { private PacketLocation location; private NPCType type; - private final Map, Object> propertyMap = new HashMap<>(); + private final Map, Object> propertyMap = new HashMap<>(); private final Set actions = new HashSet<>(); public NPC(World world, NPCType type, PacketLocation location) { @@ -31,10 +34,10 @@ public class NPC { } public void setType(NPCType type) { - _hideAll(); + UNSAFE_hideAll(); this.type = type; entity = new PacketEntity(this, type.getType(), entity.getLocation()); - _showAll(); + UNSAFE_showAll(); } public NPCType getType() { @@ -58,74 +61,50 @@ public class NPC { return Bukkit.getWorld(worldName); } + @Override public void delete() { _ALL_NPCS.remove(this); - _hideAll(); - viewers.clear(); + super.delete(); } - public void respawn() { - _hideAll(); - _showAll(); + public void undelete() { + _ALL_NPCS.add(this); } - public void respawn(Player player) { - _hide(player); - _show(player); - } - - public void show(Player player) { - if (viewers.contains(player)) return; - _show(player); - viewers.add(player); - } - - public void hide(Player player) { - if (!viewers.contains(player)) return; - _hide(player); - viewers.remove(player); - } - - public boolean isShown(Player player) { - return viewers.contains(player); - } - - private void _show(Player player) { + @Override + protected void _show(Player player) { entity.spawn(player); } - private void _hide(Player player) { + @Override + protected void _hide(Player player) { entity.despawn(player); } - private void _hideAll() { - for (Player viewer : viewers) _hide(viewer); - } - - private void _showAll() { - for (Player viewer : viewers) _show(viewer); + private void _refreshMeta() { + for (Player viewer : viewers) entity.refreshMeta(viewer); } @SuppressWarnings("unchecked") - public T getProperty(NPCProperty key) { + public T getProperty(EntityProperty key) { return hasProperty(key) ? (T) propertyMap.get(key) : key.getDefaultValue(); } - public boolean hasProperty(NPCProperty key) { + public boolean hasProperty(EntityProperty key) { return propertyMap.containsKey(key); } - public void setProperty(NPCProperty key, T value) { + public void setProperty(EntityProperty key, T value) { if (value.equals(key.getDefaultValue())) removeProperty(key); else { propertyMap.put(key, value); - respawn(); + _refreshMeta(); } } - public void removeProperty(NPCProperty key) { + public void removeProperty(EntityProperty key) { propertyMap.remove(key); - respawn(); + _refreshMeta(); } public Collection getActions() { diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java deleted file mode 100644 index 6236194..0000000 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCProperty.java +++ /dev/null @@ -1,42 +0,0 @@ -package lol.pyr.znpcsplus.npc; - -import lol.pyr.znpcsplus.skin.SkinDescriptor; -import net.kyori.adventure.text.format.NamedTextColor; - -import java.util.HashMap; -import java.util.Map; - -public class NPCProperty { - private final String name; - private final T defaultValue; - - public NPCProperty(String name) { - this(name, null); - } - - public NPCProperty(String name, T defaultValue) { - this.name = name.toUpperCase(); - this.defaultValue = defaultValue; - BY_NAME.put(this.name, this); - } - - public String name() { - return name; - } - - protected T getDefaultValue() { - return defaultValue; - } - - private final static Map> BY_NAME = new HashMap<>(); - - public static NPCProperty getByName(String name) { - return BY_NAME.get(name.toUpperCase()); - } - - public static NPCProperty SKIN_LAYERS = new NPCProperty<>("skin_layers", true); - public static NPCProperty SKIN = new NPCProperty<>("skin"); - public static NPCProperty GLOW = new NPCProperty<>("glow"); - public static NPCProperty FIRE = new NPCProperty<>("fire", false); - public static NPCProperty INVISIBLE = new NPCProperty<>("invisible", false); -} \ No newline at end of file diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 463b8d5..8fcaa86 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -4,6 +4,7 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import lol.pyr.znpcsplus.entity.EntityProperty; import java.util.*; @@ -19,10 +20,10 @@ public class NPCType { } private final EntityType type; - private final Set> allowedProperties; + private final Set> allowedProperties; private final String name; - private NPCType(String name, EntityType type, Set> allowedProperties) { + private NPCType(String name, EntityType type, Set> allowedProperties) { this.name = name.toUpperCase(); this.type = type; this.allowedProperties = allowedProperties; @@ -36,7 +37,7 @@ public class NPCType { return type; } - public Set> getAllowedProperties() { + public Set> getAllowedProperties() { return allowedProperties; } @@ -51,7 +52,7 @@ public class NPCType { static { register(new Builder("player", EntityTypes.PLAYER) - .addProperties(NPCProperty.SKIN, NPCProperty.SKIN_LAYERS)); + .addProperties(EntityProperty.SKIN, EntityProperty.SKIN_LAYERS)); register(new Builder("creeper", EntityTypes.CREEPER)); register(new Builder("zombie", EntityTypes.ZOMBIE)); register(new Builder("skeleton", EntityTypes.SKELETON)); @@ -60,7 +61,7 @@ public class NPCType { private static final class Builder { private final String name; private final EntityType type; - private final List> allowedProperties = new ArrayList<>(); + private final List> allowedProperties = new ArrayList<>(); private boolean globalProperties = true; private Builder(String name, EntityType type) { @@ -68,7 +69,7 @@ public class NPCType { this.type = type; } - public Builder addProperties(NPCProperty... properties) { + public Builder addProperties(EntityProperty... properties) { allowedProperties.addAll(List.of(properties)); return this; } @@ -80,10 +81,11 @@ public class NPCType { public NPCType build() { if (globalProperties) { - allowedProperties.add(NPCProperty.FIRE); - allowedProperties.add(NPCProperty.INVISIBLE); + allowedProperties.add(EntityProperty.FIRE); + allowedProperties.add(EntityProperty.INVISIBLE); + allowedProperties.add(EntityProperty.SILENT); if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) - allowedProperties.add(NPCProperty.GLOW); + allowedProperties.add(EntityProperty.GLOW); } return new NPCType(name, type, Set.copyOf(allowedProperties)); } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 9cdaf43..fc151fa 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -4,24 +4,26 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PropertyHolder; import lol.pyr.znpcsplus.util.LazyLoader; import org.bukkit.entity.Player; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; public interface PacketFactory { - void spawnPlayer(Player player, PacketEntity entity); - void spawnEntity(Player player, PacketEntity entity); - void destroyEntity(Player player, PacketEntity entity); + void spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties); + void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties); + void destroyEntity(Player player, PacketEntity entity, PropertyHolder properties); void teleportEntity(Player player, PacketEntity entity); - CompletableFuture addTabPlayer(Player player, PacketEntity entity); + CompletableFuture addTabPlayer(Player player, PacketEntity entity, PropertyHolder properties); void removeTabPlayer(Player player, PacketEntity entity); - void createTeam(Player player, PacketEntity entity); + void createTeam(Player player, PacketEntity entity, PropertyHolder properties); void removeTeam(Player player, PacketEntity entity); - void sendAllMetadata(Player player, PacketEntity entity); - void sendMetadata(Player player, PacketEntity entity, EntityData... data); + void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties); + void sendMetadata(Player player, PacketEntity entity, List data); PacketFactory factory = get(); diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java index 560f948..fdbad60 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_14Factory.java @@ -3,18 +3,19 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; -import lol.pyr.znpcsplus.npc.NPCProperty; +import lol.pyr.znpcsplus.entity.EntityProperty; +import lol.pyr.znpcsplus.entity.PropertyHolder; import org.bukkit.entity.Player; import java.util.Optional; public class V1_14Factory extends V1_9Factory { @Override - public void spawnEntity(Player player, PacketEntity entity) { + public void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties) { PacketLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); - if (entity.getOwner().hasProperty(NPCProperty.GLOW)) createTeam(player, entity); - sendAllMetadata(player, entity); + if (properties.hasProperty(EntityProperty.GLOW)) createTeam(player, entity, properties); + sendAllMetadata(player, entity, properties); } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java index ad0b12c..9d6522c 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_19Factory.java @@ -6,6 +6,7 @@ import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate; import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.entity.PropertyHolder; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @@ -14,10 +15,10 @@ import java.util.concurrent.CompletableFuture; public class V1_19Factory extends V1_14Factory { @Override - public CompletableFuture addTabPlayer(Player player, PacketEntity entity) { + public CompletableFuture addTabPlayer(Player player, PacketEntity entity, PropertyHolder properties) { if (entity.getType() != EntityTypes.PLAYER) return CompletableFuture.completedFuture(null); CompletableFuture future = new CompletableFuture<>(); - skinned(player, entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> { + skinned(player, properties, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> { WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo( profile, false, 1, GameMode.CREATIVE, Component.empty(), null); sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER, diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java index ebeda9f..122fd88 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_8Factory.java @@ -14,32 +14,33 @@ import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.metadata.MetadataFactory; -import lol.pyr.znpcsplus.npc.NPC; -import lol.pyr.znpcsplus.npc.NPCProperty; +import lol.pyr.znpcsplus.entity.EntityProperty; +import lol.pyr.znpcsplus.entity.PropertyHolder; import lol.pyr.znpcsplus.skin.SkinDescriptor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; public class V1_8Factory implements PacketFactory { @Override - public void spawnPlayer(Player player, PacketEntity entity) { - addTabPlayer(player, entity).thenAccept(ignored -> { - createTeam(player, entity); + public void spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties) { + addTabPlayer(player, entity, properties).thenAccept(ignored -> { + createTeam(player, entity, properties); PacketLocation location = entity.getLocation(); sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(), entity.getUuid(), location.toVector3d(), location.getYaw(), location.getPitch(), List.of())); - sendAllMetadata(player, entity); + sendAllMetadata(player, entity, properties); ZNPCsPlus.SCHEDULER.runTaskLaterSync(() -> removeTabPlayer(player, entity), 60); }); } @Override - public void spawnEntity(Player player, PacketEntity entity) { + public void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties) { PacketLocation location = entity.getLocation(); EntityType type = entity.getType(); ClientVersion clientVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); @@ -48,11 +49,11 @@ public class V1_8Factory implements PacketFactory { location.getYaw(), location.getPitch(), location.getPitch(), new Vector3d(), List.of()) : new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), location.toVector3d(), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty())); - sendAllMetadata(player, entity); + sendAllMetadata(player, entity, properties); } @Override - public void destroyEntity(Player player, PacketEntity entity) { + public void destroyEntity(Player player, PacketEntity entity, PropertyHolder properties) { sendPacket(player, new WrapperPlayServerDestroyEntities(entity.getEntityId())); if (entity.getType() == EntityTypes.PLAYER) removeTeam(player, entity); } @@ -65,10 +66,10 @@ public class V1_8Factory implements PacketFactory { } @Override - public CompletableFuture addTabPlayer(Player player, PacketEntity entity) { + public CompletableFuture addTabPlayer(Player player, PacketEntity entity, PropertyHolder properties) { if (entity.getType() != EntityTypes.PLAYER) return CompletableFuture.completedFuture(null); CompletableFuture future = new CompletableFuture<>(); - skinned(player, entity, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> { + skinned(player, properties, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> { sendPacket(player, new WrapperPlayServerPlayerInfo( WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(""), profile, GameMode.CREATIVE, 1))); @@ -86,13 +87,12 @@ public class V1_8Factory implements PacketFactory { } @Override - public void createTeam(Player player, PacketEntity entity) { - NPC owner = entity.getOwner(); + public void createTeam(Player player, PacketEntity entity, PropertyHolder properties) { sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo( Component.empty(), Component.empty(), Component.empty(), WrapperPlayServerTeams.NameTagVisibility.NEVER, WrapperPlayServerTeams.CollisionRule.NEVER, - owner.hasProperty(NPCProperty.GLOW) ? owner.getProperty(NPCProperty.GLOW) : NamedTextColor.WHITE, + properties.hasProperty(EntityProperty.GLOW) ? properties.getProperty(EntityProperty.GLOW) : NamedTextColor.WHITE, WrapperPlayServerTeams.OptionData.NONE ))); sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null, @@ -105,27 +105,29 @@ public class V1_8Factory implements PacketFactory { } @Override - public void sendAllMetadata(Player player, PacketEntity entity) { - NPC owner = entity.getOwner(); - if (entity.getType() == EntityTypes.PLAYER && owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); - boolean fire = owner.getProperty(NPCProperty.FIRE); - boolean invisible = owner.getProperty(NPCProperty.INVISIBLE); - if (fire || invisible) sendMetadata(player, entity, MetadataFactory.get().effects(fire, false, invisible)); + public void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties) { + ArrayList data = new ArrayList<>(); + if (entity.getType() == EntityTypes.PLAYER && properties.getProperty(EntityProperty.SKIN_LAYERS)) data.add(MetadataFactory.get().skinLayers()); + boolean fire = properties.getProperty(EntityProperty.FIRE); + boolean invisible = properties.getProperty(EntityProperty.INVISIBLE); + if (fire || invisible) data.add(MetadataFactory.get().effects(fire, false, invisible)); + if (properties.getProperty(EntityProperty.SILENT)) data.add(MetadataFactory.get().silent()); + if (properties.hasProperty(EntityProperty.NAME)) data.addAll(MetadataFactory.get().name(properties.getProperty(EntityProperty.NAME))); + sendMetadata(player, entity, data); } @Override - public void sendMetadata(Player player, PacketEntity entity, EntityData... data) { - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), List.of(data))); + public void sendMetadata(Player player, PacketEntity entity, List data) { + PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), data)); } protected void sendPacket(Player player, PacketWrapper packet) { PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet); } - protected CompletableFuture skinned(Player player, PacketEntity entity, UserProfile profile) { - NPC owner = entity.getOwner(); - if (!owner.hasProperty(NPCProperty.SKIN)) return CompletableFuture.completedFuture(profile); - SkinDescriptor descriptor = owner.getProperty(NPCProperty.SKIN); + protected CompletableFuture skinned(Player player, PropertyHolder properties, UserProfile profile) { + if (!properties.hasProperty(EntityProperty.SKIN)) return CompletableFuture.completedFuture(profile); + SkinDescriptor descriptor = properties.getProperty(EntityProperty.SKIN); if (descriptor.supportsInstant(player)) { descriptor.fetchInstant(player).apply(profile); return CompletableFuture.completedFuture(profile); diff --git a/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java b/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java index 0a1eaeb..009d66c 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/V1_9Factory.java @@ -1,32 +1,38 @@ package lol.pyr.znpcsplus.packets; +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.metadata.MetadataFactory; -import lol.pyr.znpcsplus.npc.NPC; -import lol.pyr.znpcsplus.npc.NPCProperty; +import lol.pyr.znpcsplus.entity.EntityProperty; +import lol.pyr.znpcsplus.entity.PropertyHolder; import org.bukkit.entity.Player; +import java.util.ArrayList; + public class V1_9Factory extends V1_8Factory { @Override - public void sendAllMetadata(Player player, PacketEntity entity) { - NPC owner = entity.getOwner(); - if (entity.getType() == EntityTypes.PLAYER && owner.getProperty(NPCProperty.SKIN_LAYERS)) sendMetadata(player, entity, MetadataFactory.get().skinLayers()); - boolean glow = owner.hasProperty(NPCProperty.GLOW); - boolean fire = owner.getProperty(NPCProperty.FIRE); - boolean invisible = owner.getProperty(NPCProperty.INVISIBLE); - if (glow || fire) sendMetadata(player, entity, MetadataFactory.get().effects(fire, glow, invisible)); + public void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties) { + ArrayList data = new ArrayList<>(); + if (entity.getType() == EntityTypes.PLAYER && properties.getProperty(EntityProperty.SKIN_LAYERS)) data.add(MetadataFactory.get().skinLayers()); + boolean glow = properties.hasProperty(EntityProperty.GLOW); + boolean fire = properties.getProperty(EntityProperty.FIRE); + boolean invisible = properties.getProperty(EntityProperty.INVISIBLE); + if (glow || fire || invisible) data.add(MetadataFactory.get().effects(fire, glow, invisible)); + if (properties.getProperty(EntityProperty.SILENT)) data.add(MetadataFactory.get().silent()); + if (properties.hasProperty(EntityProperty.NAME)) data.addAll(MetadataFactory.get().name(properties.getProperty(EntityProperty.NAME))); + sendMetadata(player, entity, data); } @Override - public void spawnEntity(Player player, PacketEntity entity) { - super.spawnEntity(player, entity); - if (entity.getOwner().hasProperty(NPCProperty.GLOW)) createTeam(player, entity); + public void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties) { + super.spawnEntity(player, entity, properties); + if (properties.hasProperty(EntityProperty.GLOW)) createTeam(player, entity, properties); } @Override - public void destroyEntity(Player player, PacketEntity entity) { - super.destroyEntity(player, entity); - if (entity.getType() != EntityTypes.PLAYER && entity.getOwner().hasProperty(NPCProperty.GLOW)) removeTeam(player, entity); + public void destroyEntity(Player player, PacketEntity entity, PropertyHolder properties) { + super.destroyEntity(player, entity, properties); + if (entity.getType() != EntityTypes.PLAYER && properties.hasProperty(EntityProperty.GLOW)) removeTeam(player, entity); } } diff --git a/src/main/java/lol/pyr/znpcsplus/util/Viewable.java b/src/main/java/lol/pyr/znpcsplus/util/Viewable.java new file mode 100644 index 0000000..60b39f3 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/util/Viewable.java @@ -0,0 +1,59 @@ +package lol.pyr.znpcsplus.util; + +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public abstract class Viewable { + private final Set viewers = new HashSet<>(); + + public void delete() { + UNSAFE_hideAll(); + viewers.clear(); + } + + public void respawn() { + UNSAFE_hideAll(); + UNSAFE_showAll(); + } + + public void respawn(Player player) { + if (!viewers.contains(player)) return; + _hide(player); + _show(player); + } + + public void show(Player player) { + if (viewers.contains(player)) return; + _show(player); + viewers.add(player); + } + + public void hide(Player player) { + if (!viewers.contains(player)) return; + _hide(player); + viewers.remove(player); + } + + public boolean isShown(Player player) { + return viewers.contains(player); + } + + protected void UNSAFE_hideAll() { + for (Player viewer : viewers) _hide(viewer); + } + + protected void UNSAFE_showAll() { + for (Player viewer : viewers) _show(viewer); + } + + public Set getViewers() { + return Collections.unmodifiableSet(viewers); + } + + protected abstract void _show(Player player); + + protected abstract void _hide(Player player); +} From 72134f8d740708ab4ad153ad3be432057dfa4a33 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 26 Apr 2023 17:08:14 +0100 Subject: [PATCH 20/22] use this amazing config library i just found --- build.gradle | 5 ++ .../configuration/Configuration.java | 74 ------------------ .../configuration/ConfigurationConstants.java | 8 -- .../configuration/ConfigurationValue.java | 77 ------------------- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 9 ++- .../lol/pyr/znpcsplus/config/Configs.java | 58 ++++++++++++++ .../lol/pyr/znpcsplus/config/MainConfig.java | 24 ++++++ .../pyr/znpcsplus/config/MessageConfig.java | 38 +++++++++ .../znpcsplus/tasks/NPCVisibilityTask.java | 5 +- 9 files changed, 134 insertions(+), 164 deletions(-) delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java delete mode 100644 src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java create mode 100644 src/main/java/lol/pyr/znpcsplus/config/Configs.java create mode 100644 src/main/java/lol/pyr/znpcsplus/config/MainConfig.java create mode 100644 src/main/java/lol/pyr/znpcsplus/config/MessageConfig.java diff --git a/build.gradle b/build.gradle index 34f56a6..76732e6 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation "com.github.robertlit:SpigotResourcesAPI:2.0" implementation "net.kyori:adventure-platform-bukkit:4.3.0" implementation "com.github.retrooper.packetevents:spigot:2.0.0-SNAPSHOT" + implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" } group "lol.pyr" @@ -55,8 +56,12 @@ shadowJar { relocate "org.checkerframework", "lol.pyr.znpcsplus.lib.checkerframework" relocate "javax.annotation", "lol.pyr.znpcsplus.lib.javaxannotation" relocate "com.google", "lol.pyr.znpcsplus.lib.google" + relocate "com.github.retrooper.packetevents", "lol.pyr.znpcsplus.lib.packetevents.api" relocate "io.github.retrooper.packetevents", "lol.pyr.znpcsplus.lib.packetevents.impl" + + relocate "org.yaml.snakeyaml", "lol.pyr.znpcsplus.lib.snakeyaml" + relocate "space.arim.dazzleconf", "lol.pyr.znpcsplus.lib.dazzleconf" minimize() } diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java deleted file mode 100644 index 751c110..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java +++ /dev/null @@ -1,74 +0,0 @@ -package io.github.znetworkw.znpcservers.configuration; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.google.gson.internal.$Gson$Types; -import io.github.znetworkw.znpcservers.utility.Utils; -import lol.pyr.znpcsplus.ZNPCsPlus; - -import java.io.IOException; -import java.io.Reader; -import java.io.Writer; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.Map; -import java.util.stream.Collectors; - -public class Configuration { - private static final Charset CHARSET = StandardCharsets.UTF_8; - private final String name; - private final Path path; - private final Map configurationValues; - public static final Configuration CONFIGURATION = new Configuration("config"); - public static final Configuration MESSAGES = new Configuration("messages"); - - protected Configuration(String name) { - this(name, ZNPCsPlus.PLUGIN_FOLDER.toPath().resolve(name + ".json")); - } - - private Configuration(String name, Path path) { - if (!path.getFileName().toString().endsWith(".json")) throw new IllegalStateException("Invalid configuration format for: " + path.getFileName()); - this.name = name; - this.path = path; - this.configurationValues = ConfigurationValue.VALUES_BY_NAME.get(name).stream().collect(Collectors.toMap((c) -> c, ConfigurationValue::getValue)); - this.onLoad(); - this.save(); - } - - protected void onLoad() { - try (Reader reader = Files.newBufferedReader(this.path, CHARSET)) { - JsonElement data = JsonParser.parseReader(reader); - if (data == null) return; - for(ConfigurationValue configValue : this.configurationValues.keySet()) { - boolean single = this.configurationValues.size() == 1; - JsonElement jsonElement = single ? data : (data.isJsonObject() ? data.getAsJsonObject().get(configValue.name()) : null); - if (jsonElement == null || jsonElement.isJsonNull()) continue; - if (!single && configValue.getPrimitiveType().isEnum()) this.configurationValues.put(configValue, ZNPCsPlus.GSON.fromJson(jsonElement, configValue.getPrimitiveType())); - else this.configurationValues.put(configValue, ZNPCsPlus.GSON.fromJson(jsonElement, $Gson$Types.newParameterizedTypeWithOwner(null, configValue.getValue().getClass(), configValue.getPrimitiveType()))); - } - } catch (NoSuchFileException ignored) { - } catch (IOException ex) { - throw new IllegalStateException("Failed to read configuration: " + this.name); - } - } - - public void save() { - try (Writer writer = Files.newBufferedWriter(this.path, CHARSET)) { - ZNPCsPlus.GSON.toJson(this.configurationValues.size() == 1 ? this.configurationValues.values().iterator().next() : this.configurationValues, writer); - } catch (IOException ex) { - throw new IllegalStateException("Failed to save configuration: " + this.name); - } - } - - @SuppressWarnings("unchecked") - public T getValue(ConfigurationValue configValue) { - return (T)this.configurationValues.get(configValue); - } - - public void sendMessage(org.bukkit.command.CommandSender sender, ConfigurationValue configValue, Object... replaces) { - sender.sendMessage(Utils.toColor(String.format(this.getValue(configValue), replaces))); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java deleted file mode 100644 index 6b7500b..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.github.znetworkw.znpcservers.configuration; - -public final class ConfigurationConstants { - public static final String SPACE_SYMBOL = Configuration.CONFIGURATION.getValue(ConfigurationValue.REPLACE_SYMBOL); - public static final boolean DEBUG_ENABLED = Configuration.CONFIGURATION.getValue(ConfigurationValue.DEBUG_ENABLED); - public static final int VIEW_DISTANCE = Configuration.CONFIGURATION.getValue(ConfigurationValue.VIEW_DISTANCE); - public static final boolean CHECK_FOR_UPDATES = Configuration.CONFIGURATION.getValue(ConfigurationValue.CHECK_FOR_UPDATES); -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java deleted file mode 100644 index b14cfef..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.github.znetworkw.znpcservers.configuration; - -import com.google.common.collect.ImmutableSet; -import io.github.znetworkw.znpcservers.utility.GuavaCollectors; - -import java.util.Arrays; -import java.util.Map; -import java.util.stream.Collectors; - -public enum ConfigurationValue { - VIEW_DISTANCE("config", 32, Integer.class), - REPLACE_SYMBOL("config", "-", String.class), - SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class), - MAX_PATH_LOCATIONS("config", 500, Integer.class), - DEBUG_ENABLED("config", false, Boolean.class), - LINE_SPACING("config", 0.3D, Double.class), - ANIMATION_RGB("config", false, Boolean.class), - CHECK_FOR_UPDATES("config", true, Boolean.class), - NO_PERMISSION("messages", "&cYou do not have permission to execute this command.", String.class), - SUCCESS("messages", "&aSuccess!", String.class), - INCORRECT_USAGE("messages", "&cThe arguments you specified are invalid. Type &f/znpcs&c for examples.", String.class), - COMMAND_NOT_FOUND("messages", "&cThe command you specified does not exist!", String.class), - COMMAND_ERROR("messages", "&cAn error occurred when executing this command. See console for more information.", String.class), - INVALID_NUMBER("messages", "&cThe ID you have specified is invalid. Please use positive integers only!", String.class), - NPC_NOT_FOUND("messages", "&cNo NPCs could be found with this ID!", String.class), - TOO_FEW_ARGUMENTS("messages", "&cThis command does not contain enough arguments. Type &f/znpcs&c or view our documentation for a list/examples of existing arguments.", String.class), - PATH_START("messages", "&aSuccess! Move to create a path for your NPC. When finished, type &f/znpcs path exit&c to exit path creation.", String.class), - EXIT_PATH("messages", "&cYou have exited path creation.", String.class), - PATH_FOUND("messages", "&cThere is already a path with this name.", String.class), - NPC_FOUND("messages", "&cThere is already an NPC with this ID.", String.class), - NO_PATH_FOUND("messages", "&cThe path you have specified does not exist.", String.class), - NO_SKIN_FOUND("messages", "&cThe skin username/URL you have specified does not exist or is invalid.", String.class), - NO_NPC_FOUND("messages", "&cThe NPC you have specified does not exist.", String.class), - NO_ACTION_FOUND("messages", "&cThis action does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing action types.", String.class), - METHOD_NOT_FOUND("messages", "&cThis method does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing methods.", String.class), - INVALID_NAME_LENGTH("messages", "&cThe name you specified either too short or long. Please enter a positive integer of (3 to 16) characters.", String.class), - UNSUPPORTED_ENTITY("messages", "&cThis entity type not available in your current server version.", String.class), - PATH_SET_INCORRECT_USAGE("messages", "&eUsage: &aset ", String.class), - ACTION_ADD_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), - ACTION_DELAY_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), - CONVERSATION_SET_INCORRECT_USAGE("messages", "&cUsage: ", String.class), - NO_CONVERSATION_FOUND("messages", "&cThe conversation you have specified does not exist!", String.class), - CONVERSATION_FOUND("messages", "&cThere is already a conversation with this name.", String.class), - INVALID_SIZE("messages", "&cThe position you have specified cannot exceed the limit.", String.class), - FETCHING_SKIN("messages", "&aFetching skin for name: &f%s&a. Please wait...", String.class), - CANT_GET_SKIN("messages", "&cCould not fetch skin for name: %s.", String.class), - GET_SKIN("messages", "&aSkin successfully fetched!", String.class), - NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class); - - public static final Map> VALUES_BY_NAME; - - static { - VALUES_BY_NAME = Arrays.stream(values()).collect(Collectors.groupingBy(ConfigurationValue::getConfigName, GuavaCollectors.toImmutableSet())); - } - - private final String configName; - private final Object value; - private final Class primitiveType; - - ConfigurationValue(String configName, Object value, Class primitiveType) { - this.configName = configName; - this.value = value; - this.primitiveType = primitiveType; - } - - public String getConfigName() { - return this.configName; - } - - public Object getValue() { - return this.value; - } - - public Class getPrimitiveType() { - return this.primitiveType; - } -} diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 2b30206..58d850c 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -6,11 +6,11 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; +import lol.pyr.znpcsplus.config.Configs; import lol.pyr.znpcsplus.entity.EntityProperty; import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.interaction.InteractionPacketListener; @@ -110,6 +110,9 @@ public class ZNPCsPlus extends JavaPlugin { PLUGIN_FOLDER.mkdirs(); PATH_FOLDER.mkdirs(); + log(ChatColor.WHITE + " * Loading configurations..."); + Configs.init(PLUGIN_FOLDER); + log(ChatColor.WHITE + " * Registering components..."); getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); new Metrics(this, PLUGIN_ID); @@ -122,13 +125,13 @@ public class ZNPCsPlus extends JavaPlugin { new InventoryListener(this); new SkinCacheCleanTask(this); new UserListener(this); - if (ConfigurationConstants.CHECK_FOR_UPDATES) new UpdateNotificationListener(this, new UpdateChecker(this)); + if (Configs.config().checkForUpdates()) new UpdateNotificationListener(this, new UpdateChecker(this)); enabled = true; log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)"); log(""); - if (ConfigurationConstants.DEBUG_ENABLED) { + if (Configs.config().debugEnabled()) { int wrap = 20; int x = 0; int z = 0; diff --git a/src/main/java/lol/pyr/znpcsplus/config/Configs.java b/src/main/java/lol/pyr/znpcsplus/config/Configs.java new file mode 100644 index 0000000..b367878 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/config/Configs.java @@ -0,0 +1,58 @@ +package lol.pyr.znpcsplus.config; + +import lol.pyr.znpcsplus.ZNPCsPlus; +import space.arim.dazzleconf.ConfigurationFactory; +import space.arim.dazzleconf.ConfigurationOptions; +import space.arim.dazzleconf.error.ConfigFormatSyntaxException; +import space.arim.dazzleconf.error.InvalidConfigException; +import space.arim.dazzleconf.ext.snakeyaml.CommentMode; +import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlConfigurationFactory; +import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlOptions; +import space.arim.dazzleconf.helper.ConfigurationHelper; + +import java.io.File; +import java.io.IOException; + +public class Configs { + private volatile static MainConfig config; + private static ConfigurationHelper configHelper; + + private volatile static MessageConfig messages; + private static ConfigurationHelper messagesHelper; + + private static ConfigurationHelper createHelper(Class configClass, File file) { + SnakeYamlOptions yamlOptions = new SnakeYamlOptions.Builder().commentMode(CommentMode.fullComments()).build(); + ConfigurationFactory configFactory = SnakeYamlConfigurationFactory.create(configClass, ConfigurationOptions.defaults(), yamlOptions); + return new ConfigurationHelper<>(file.getParentFile().toPath(), file.getName(), configFactory); + } + + public static void init(File pluginFolder) { + configHelper = createHelper(MainConfig.class, new File(pluginFolder, "config.yaml")); + messagesHelper = createHelper(MessageConfig.class, new File(pluginFolder, "messages.yaml")); + load(); + } + + public static void load() { + try { + config = configHelper.reloadConfigData(); + messages = messagesHelper.reloadConfigData(); + } catch (IOException e) { + ZNPCsPlus.LOGGER.severe("Couldn't open config file!"); + e.printStackTrace(); + } catch (ConfigFormatSyntaxException e) { + ZNPCsPlus.LOGGER.severe("Invalid config syntax!"); + e.printStackTrace(); + } catch (InvalidConfigException e) { + ZNPCsPlus.LOGGER.severe("Invalid config value!"); + e.printStackTrace(); + } + } + + public static MainConfig config() { + return config; + } + + public static MessageConfig messages() { + return messages; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java b/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java new file mode 100644 index 0000000..0bfe954 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.config; + +import space.arim.dazzleconf.annote.ConfKey; + +import static space.arim.dazzleconf.annote.ConfDefault.*; + +// TODO: Add comments to the values using @ConfComments() +public interface MainConfig { + @ConfKey("view-distance") + @DefaultInteger(32) + int viewDistance(); + + @ConfKey("line-spacing") + @DefaultDouble(0.3D) + double lineSpacing(); + + @ConfKey("debug-enabled") + @DefaultBoolean(false) + boolean debugEnabled(); + + @ConfKey("check-for-updates") + @DefaultBoolean(true) + boolean checkForUpdates(); +} diff --git a/src/main/java/lol/pyr/znpcsplus/config/MessageConfig.java b/src/main/java/lol/pyr/znpcsplus/config/MessageConfig.java new file mode 100644 index 0000000..757f6af --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/config/MessageConfig.java @@ -0,0 +1,38 @@ +package lol.pyr.znpcsplus.config; + +/** + * (OLD CONFIGURATION) + * NO_PERMISSION("messages", "&cYou do not have permission to execute this command.", String.class), + * SUCCESS("messages", "&aSuccess!", String.class), + * INCORRECT_USAGE("messages", "&cThe arguments you specified are invalid. Type &f/znpcs&c for examples.", String.class), + * COMMAND_NOT_FOUND("messages", "&cThe command you specified does not exist!", String.class), + * COMMAND_ERROR("messages", "&cAn error occurred when executing this command. See console for more information.", String.class), + * INVALID_NUMBER("messages", "&cThe ID you have specified is invalid. Please use positive integers only!", String.class), + * NPC_NOT_FOUND("messages", "&cNo NPCs could be found with this ID!", String.class), + * TOO_FEW_ARGUMENTS("messages", "&cThis command does not contain enough arguments. Type &f/znpcs&c or view our documentation for a list/examples of existing arguments.", String.class), + * PATH_START("messages", "&aSuccess! Move to create a path for your NPC. When finished, type &f/znpcs path exit&c to exit path creation.", String.class), + * EXIT_PATH("messages", "&cYou have exited path creation.", String.class), + * PATH_FOUND("messages", "&cThere is already a path with this name.", String.class), + * NPC_FOUND("messages", "&cThere is already an NPC with this ID.", String.class), + * NO_PATH_FOUND("messages", "&cThe path you have specified does not exist.", String.class), + * NO_SKIN_FOUND("messages", "&cThe skin username/URL you have specified does not exist or is invalid.", String.class), + * NO_NPC_FOUND("messages", "&cThe NPC you have specified does not exist.", String.class), + * NO_ACTION_FOUND("messages", "&cThis action does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing action types.", String.class), + * METHOD_NOT_FOUND("messages", "&cThis method does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing methods.", String.class), + * INVALID_NAME_LENGTH("messages", "&cThe name you specified either too short or long. Please enter a positive integer of (3 to 16) characters.", String.class), + * UNSUPPORTED_ENTITY("messages", "&cThis entity type not available in your current server version.", String.class), + * PATH_SET_INCORRECT_USAGE("messages", "&eUsage: &aset ", String.class), + * ACTION_ADD_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), + * ACTION_DELAY_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), + * CONVERSATION_SET_INCORRECT_USAGE("messages", "&cUsage: ", String.class), + * NO_CONVERSATION_FOUND("messages", "&cThe conversation you have specified does not exist!", String.class), + * CONVERSATION_FOUND("messages", "&cThere is already a conversation with this name.", String.class), + * INVALID_SIZE("messages", "&cThe position you have specified cannot exceed the limit.", String.class), + * FETCHING_SKIN("messages", "&aFetching skin for name: &f%s&a. Please wait...", String.class), + * CANT_GET_SKIN("messages", "&cCould not fetch skin for name: %s.", String.class), + * GET_SKIN("messages", "&aSkin successfully fetched!", String.class), + * NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class); + */ + +public interface MessageConfig { +} diff --git a/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java index 59a5d97..6a9f105 100644 --- a/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java +++ b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java @@ -1,12 +1,13 @@ package lol.pyr.znpcsplus.tasks; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; +import lol.pyr.znpcsplus.config.Configs; import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.npc.NPCRegistry; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.NumberConversions; public class NPCVisibilityTask extends BukkitRunnable { public NPCVisibilityTask(Plugin plugin) { @@ -14,7 +15,7 @@ public class NPCVisibilityTask extends BukkitRunnable { } public void run() { - int distSq = ConfigurationConstants.VIEW_DISTANCE * ConfigurationConstants.VIEW_DISTANCE; + double distSq = NumberConversions.square(Configs.config().viewDistance()); for (NPC npc : NPCRegistry.all()) for (Player player : Bukkit.getOnlinePlayers()) { boolean inRange = (player.getWorld() == npc.getWorld() && player.getLocation().distanceSquared(npc.getLocation().toBukkitLocation(npc.getWorld())) <= distSq); if (!inRange && npc.isShown(player)) npc.hide(player); From 63c72fe04bc3daba74fda093465fd39211cbc69e Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 26 Apr 2023 17:24:47 +0100 Subject: [PATCH 21/22] add Component serializer --- build.gradle | 1 + .../znpcsplus/config/ComponentSerializer.java | 25 +++++++++++++++++++ .../lol/pyr/znpcsplus/config/Configs.java | 9 ++++--- .../lol/pyr/znpcsplus/config/MainConfig.java | 14 +++++++---- 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 src/main/java/lol/pyr/znpcsplus/config/ComponentSerializer.java diff --git a/build.gradle b/build.gradle index 76732e6..8648269 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,7 @@ dependencies { implementation "org.bstats:bstats-bukkit:3.0.2" implementation "com.github.robertlit:SpigotResourcesAPI:2.0" implementation "net.kyori:adventure-platform-bukkit:4.3.0" + implementation "net.kyori:adventure-text-minimessage:4.13.1" implementation "com.github.retrooper.packetevents:spigot:2.0.0-SNAPSHOT" implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" } diff --git a/src/main/java/lol/pyr/znpcsplus/config/ComponentSerializer.java b/src/main/java/lol/pyr/znpcsplus/config/ComponentSerializer.java new file mode 100644 index 0000000..a63beef --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/config/ComponentSerializer.java @@ -0,0 +1,25 @@ +package lol.pyr.znpcsplus.config; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import space.arim.dazzleconf.error.BadValueException; +import space.arim.dazzleconf.serialiser.Decomposer; +import space.arim.dazzleconf.serialiser.FlexibleType; +import space.arim.dazzleconf.serialiser.ValueSerialiser; + +public class ComponentSerializer implements ValueSerialiser { + @Override + public Class getTargetClass() { + return Component.class; + } + + @Override + public Component deserialise(FlexibleType flexibleType) throws BadValueException { + return MiniMessage.miniMessage().deserialize(flexibleType.getString()); + } + + @Override + public Object serialise(Component value, Decomposer decomposer) { + return MiniMessage.miniMessage().serialize(value); + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/config/Configs.java b/src/main/java/lol/pyr/znpcsplus/config/Configs.java index b367878..832e803 100644 --- a/src/main/java/lol/pyr/znpcsplus/config/Configs.java +++ b/src/main/java/lol/pyr/znpcsplus/config/Configs.java @@ -9,6 +9,7 @@ import space.arim.dazzleconf.ext.snakeyaml.CommentMode; import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlConfigurationFactory; import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlOptions; import space.arim.dazzleconf.helper.ConfigurationHelper; +import space.arim.dazzleconf.serialiser.ValueSerialiser; import java.io.File; import java.io.IOException; @@ -20,15 +21,17 @@ public class Configs { private volatile static MessageConfig messages; private static ConfigurationHelper messagesHelper; - private static ConfigurationHelper createHelper(Class configClass, File file) { + private static ConfigurationHelper createHelper(Class configClass, File file, ValueSerialiser... serialisers) { SnakeYamlOptions yamlOptions = new SnakeYamlOptions.Builder().commentMode(CommentMode.fullComments()).build(); - ConfigurationFactory configFactory = SnakeYamlConfigurationFactory.create(configClass, ConfigurationOptions.defaults(), yamlOptions); + ConfigurationOptions.Builder optionBuilder = new ConfigurationOptions.Builder(); + if (serialisers != null && serialisers.length > 0) optionBuilder.addSerialisers(serialisers); + ConfigurationFactory configFactory = SnakeYamlConfigurationFactory.create(configClass, optionBuilder.build(), yamlOptions); return new ConfigurationHelper<>(file.getParentFile().toPath(), file.getName(), configFactory); } public static void init(File pluginFolder) { configHelper = createHelper(MainConfig.class, new File(pluginFolder, "config.yaml")); - messagesHelper = createHelper(MessageConfig.class, new File(pluginFolder, "messages.yaml")); + messagesHelper = createHelper(MessageConfig.class, new File(pluginFolder, "messages.yaml"), new ComponentSerializer()); load(); } diff --git a/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java b/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java index 0bfe954..f34c2f0 100644 --- a/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java +++ b/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java @@ -1,24 +1,28 @@ package lol.pyr.znpcsplus.config; +import space.arim.dazzleconf.annote.ConfComments; import space.arim.dazzleconf.annote.ConfKey; import static space.arim.dazzleconf.annote.ConfDefault.*; -// TODO: Add comments to the values using @ConfComments() public interface MainConfig { @ConfKey("view-distance") + @ConfComments("How far away do you need to be from any NPC for it to disappear, measured in blocks") @DefaultInteger(32) int viewDistance(); @ConfKey("line-spacing") + @ConfComments("The height between hologram lines, measured in blocks") @DefaultDouble(0.3D) double lineSpacing(); - @ConfKey("debug-enabled") - @DefaultBoolean(false) - boolean debugEnabled(); - @ConfKey("check-for-updates") + @ConfComments("Should the plugin check for available updates and notify admins about them?") @DefaultBoolean(true) boolean checkForUpdates(); + + @ConfKey("debug-enabled") + @ConfComments({"Should debug mode be enabled?", "This is used in development to test various things, you probably don't want to enable this"}) + @DefaultBoolean(false) + boolean debugEnabled(); } From 2372748ddb71432a9e317b32c3fcd967340611dd Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Wed, 26 Apr 2023 18:50:40 +0100 Subject: [PATCH 22/22] fix some bugs, make holograms work --- .../java/lol/pyr/znpcsplus/ZNPCsPlus.java | 18 ++++--- .../pyr/znpcsplus/entity/PacketLocation.java | 4 ++ .../lol/pyr/znpcsplus/hologram/Hologram.java | 47 +++++++++++++++++-- .../pyr/znpcsplus/hologram/HologramLine.java | 2 +- .../znpcsplus/metadata/MetadataFactory.java | 6 ++- .../pyr/znpcsplus/metadata/V1_13Factory.java | 5 +- .../pyr/znpcsplus/metadata/V1_8Factory.java | 2 +- src/main/java/lol/pyr/znpcsplus/npc/NPC.java | 11 ++++- .../java/lol/pyr/znpcsplus/npc/NPCType.java | 28 ++++++++--- .../pyr/znpcsplus/packets/PacketFactory.java | 5 +- 10 files changed, 101 insertions(+), 27 deletions(-) diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 58d850c..e77680a 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -3,13 +3,10 @@ package lol.pyr.znpcsplus; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.event.PacketListenerPriority; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; -import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; import lol.pyr.znpcsplus.config.Configs; import lol.pyr.znpcsplus.entity.EntityProperty; import lol.pyr.znpcsplus.entity.PacketLocation; @@ -28,13 +25,13 @@ import lol.pyr.znpcsplus.updater.UpdateNotificationListener; import lol.pyr.znpcsplus.user.User; import lol.pyr.znpcsplus.user.UserListener; import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.apache.commons.io.FileUtils; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.World; -import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -45,11 +42,6 @@ public class ZNPCsPlus extends JavaPlugin { public static Logger LOGGER; public static File PLUGIN_FOLDER; public static File PATH_FOLDER; - public static final Gson GSON = new GsonBuilder() - .registerTypeHierarchyAdapter(ItemStack.class, new ItemStackSerializer()) - .setPrettyPrinting() - .disableHtmlEscaping() - .create(); private static final int PLUGIN_ID = 18244; public static SchedulerUtils SCHEDULER; public static BungeeUtils BUNGEE_UTILS; @@ -58,6 +50,11 @@ public class ZNPCsPlus extends JavaPlugin { private boolean enabled = false; + public static void debug(String str) { + if (!Configs.config().debugEnabled()) return; + LOGGER.info("[DEBUG] " + str); + } + @Override public void onLoad() { PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); @@ -144,7 +141,8 @@ public class ZNPCsPlus extends JavaPlugin { npc.setProperty(EntityProperty.INVISIBLE, true); } npc.setProperty(EntityProperty.GLOW, NamedTextColor.RED); - npc.setProperty(EntityProperty.FIRE, true); + // npc.setProperty(EntityProperty.FIRE, true); + npc.getHologram().addLine(Component.text("Hello, World!")); NPCRegistry.register("debug_npc" + (z * wrap + x), npc); if (x++ > wrap) { x = 0; diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java index 631442b..bbc6b17 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java @@ -49,6 +49,10 @@ public class PacketLocation { return new Location(world, this.x, this.y, this.z, this.yaw, this.pitch); } + public PacketLocation withY(double y) { + return new PacketLocation(x, y, z, yaw, pitch); + } + public Vector toVector() { return new Vector(x, y, z); } diff --git a/src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java b/src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java index 79a6e51..e1e250b 100644 --- a/src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java +++ b/src/main/java/lol/pyr/znpcsplus/hologram/Hologram.java @@ -1,29 +1,50 @@ package lol.pyr.znpcsplus.hologram; +import lol.pyr.znpcsplus.config.Configs; +import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.util.Viewable; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.List; +import java.util.Set; public class Hologram extends Viewable { + private PacketLocation location; private final List lines = new ArrayList<>(); - public Hologram() { - + public Hologram(PacketLocation location) { + this.location = location; } public void addLine(Component line) { - lines.add(new HologramLine(null, line)); // TODO: Location + HologramLine newLine = new HologramLine(null, line); + lines.add(newLine); + relocateLines(); + for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } public HologramLine getLine(int index) { return lines.get(index); } + public void removeLine(int index) { + HologramLine line = lines.remove(index); + for (Player viewer : getViewers()) line.hide(viewer); + relocateLines(); + } + + public void clearLines() { + UNSAFE_hideAll(); + lines.clear(); + } + public void insertLine(int index, Component line) { - lines.add(index, new HologramLine(null, line)); // TODO: Location + HologramLine newLine = new HologramLine(null, line); + lines.add(index, newLine); + relocateLines(); + for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @Override @@ -35,4 +56,22 @@ public class Hologram extends Viewable { protected void _hide(Player player) { for (HologramLine line : lines) line.hide(player); } + + public void setLocation(PacketLocation location) { + this.location = location; + relocateLines(); + } + + private void relocateLines() { + relocateLines(null); + } + + private void relocateLines(HologramLine newLine) { + final double lineSpacing = Configs.config().lineSpacing(); + double height = location.getY() + lines.size() * lineSpacing; + for (HologramLine line : lines) { + line.setLocation(location.withY(height), line == newLine ? Set.of() : getViewers()); + height -= lineSpacing; + } + } } diff --git a/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java b/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java index eeb48e3..b98d94e 100644 --- a/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java +++ b/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java @@ -44,7 +44,7 @@ public class HologramLine implements PropertyHolder { public T getProperty(EntityProperty key) { if (key == EntityProperty.INVISIBLE) return (T) Boolean.TRUE; if (key == EntityProperty.NAME) return (T) text; - return null; + return key.getDefaultValue(); } @Override diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java index c49b978..95abc45 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/MetadataFactory.java @@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.metadata; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.util.LazyLoader; import net.kyori.adventure.text.Component; @@ -40,7 +41,9 @@ public interface MetadataFactory { for (ServerVersion v : ServerVersion.reversedValues()) { if (v.isNewerThan(version)) continue; if (!factories.containsKey(v)) continue; - return factories.get(v).get(); + MetadataFactory f = factories.get(v).get(); + ZNPCsPlus.debug("Using MetadataFactory Version " + v.name() + " (" + f.getClass().getName() + ")"); + return f; } throw new RuntimeException("Unsupported version!"); } @@ -49,6 +52,7 @@ public interface MetadataFactory { HashMap> map = new HashMap<>(); 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_13, LazyLoader.of(V1_13Factory::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_17, LazyLoader.of(V1_17Factory::new)); diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java index 3e45cf5..0f1d89c 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_13Factory.java @@ -7,12 +7,13 @@ import net.kyori.adventure.text.Component; import java.util.Collection; import java.util.List; +import java.util.Optional; -public class V1_13Factory extends V1_8Factory { +public class V1_13Factory extends V1_9Factory { @Override public Collection name(Component name) { return List.of( - new EntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, AdventureSerializer.getGsonSerializer().serialize(name)), + new EntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.of(AdventureSerializer.getGsonSerializer().serialize(name))), new EntityData(3, EntityDataTypes.BOOLEAN, true) ); } diff --git a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java index a669d85..f170001 100644 --- a/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java +++ b/src/main/java/lol/pyr/znpcsplus/metadata/V1_8Factory.java @@ -16,7 +16,7 @@ public class V1_8Factory implements MetadataFactory { @Override public EntityData effects(boolean onFire, boolean glowing, boolean invisible) { - return new EntityData(0, EntityDataTypes.BYTE, (onFire ? 0x01 : 0) | (invisible ? 0x20 : 0)); + return new EntityData(0, EntityDataTypes.BYTE, (byte) ((onFire ? 0x01 : 0) | (invisible ? 0x20 : 0))); } @Override diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index befc4c9..4f4d038 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java @@ -4,6 +4,7 @@ import lol.pyr.znpcsplus.entity.EntityProperty; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.entity.PropertyHolder; +import lol.pyr.znpcsplus.hologram.Hologram; import lol.pyr.znpcsplus.interaction.NPCAction; import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.Bukkit; @@ -20,6 +21,7 @@ public class NPC extends Viewable implements PropertyHolder { private PacketEntity entity; private PacketLocation location; private NPCType type; + private final Hologram hologram; private final Map, Object> propertyMap = new HashMap<>(); private final Set actions = new HashSet<>(); @@ -29,7 +31,7 @@ public class NPC extends Viewable implements PropertyHolder { this.type = type; this.location = location; entity = new PacketEntity(this, type.getType(), location); - + hologram = new Hologram(location.withY(location.getY() + type.getHologramOffset())); _ALL_NPCS.add(this); } @@ -55,6 +57,11 @@ public class NPC extends Viewable implements PropertyHolder { public void setLocation(PacketLocation location) { this.location = location; entity.setLocation(location, viewers); + hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); + } + + public Hologram getHologram() { + return hologram; } public World getWorld() { @@ -74,11 +81,13 @@ public class NPC extends Viewable implements PropertyHolder { @Override protected void _show(Player player) { entity.spawn(player); + hologram.show(player); } @Override protected void _hide(Player player) { entity.despawn(player); + hologram.hide(player); } private void _refreshMeta() { diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java index 8fcaa86..0ca1b2c 100644 --- a/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java +++ b/src/main/java/lol/pyr/znpcsplus/npc/NPCType.java @@ -22,10 +22,12 @@ public class NPCType { private final EntityType type; private final Set> allowedProperties; private final String name; + private final double hologramOffset; - private NPCType(String name, EntityType type, Set> allowedProperties) { + private NPCType(String name, EntityType type, double hologramOffset, Set> allowedProperties) { this.name = name.toUpperCase(); this.type = type; + this.hologramOffset = hologramOffset; this.allowedProperties = allowedProperties; } @@ -37,6 +39,10 @@ public class NPCType { return type; } + public double getHologramOffset() { + return hologramOffset; + } + public Set> getAllowedProperties() { return allowedProperties; } @@ -52,10 +58,14 @@ public class NPCType { static { register(new Builder("player", EntityTypes.PLAYER) - .addProperties(EntityProperty.SKIN, EntityProperty.SKIN_LAYERS)); - register(new Builder("creeper", EntityTypes.CREEPER)); - register(new Builder("zombie", EntityTypes.ZOMBIE)); - register(new Builder("skeleton", EntityTypes.SKELETON)); + .addProperties(EntityProperty.SKIN, EntityProperty.SKIN_LAYERS) + .setHologramOffset(-0.45D)); + register(new Builder("creeper", EntityTypes.CREEPER) + .setHologramOffset(-0.6D)); + register(new Builder("zombie", EntityTypes.ZOMBIE) + .setHologramOffset(-0.3D)); + register(new Builder("skeleton", EntityTypes.SKELETON) + .setHologramOffset(-0.3D)); } private static final class Builder { @@ -63,6 +73,7 @@ public class NPCType { private final EntityType type; private final List> allowedProperties = new ArrayList<>(); private boolean globalProperties = true; + private double hologramOffset = 0; private Builder(String name, EntityType type) { this.name = name; @@ -79,6 +90,11 @@ public class NPCType { return this; } + public Builder setHologramOffset(double hologramOffset) { + this.hologramOffset = hologramOffset; + return this; + } + public NPCType build() { if (globalProperties) { allowedProperties.add(EntityProperty.FIRE); @@ -87,7 +103,7 @@ public class NPCType { if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) allowedProperties.add(EntityProperty.GLOW); } - return new NPCType(name, type, Set.copyOf(allowedProperties)); + return new NPCType(name, type, hologramOffset, Set.copyOf(allowedProperties)); } } } diff --git a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index fc151fa..58eb9e5 100644 --- a/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.packets; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.entity.PropertyHolder; import lol.pyr.znpcsplus.util.LazyLoader; @@ -35,7 +36,9 @@ public interface PacketFactory { for (ServerVersion v : ServerVersion.reversedValues()) { if (v.isNewerThan(version)) continue; if (!factories.containsKey(v)) continue; - return factories.get(v).get(); + PacketFactory f = factories.get(v).get(); + ZNPCsPlus.debug("Using PacketFactory Version " + v.name() + " (" + f.getClass().getName() + ")"); + return f; } throw new RuntimeException("Unsupported version!"); }