From b107bd98fa24236a9826c020708737bb5233d079 Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Mon, 24 Apr 2023 17:12:50 +0100 Subject: [PATCH] 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 ef45a7f..442d078 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 e865d5f..1331c77 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); + } + } +}