so much progress
This commit is contained in:
		
							parent
							
								
									30b8d90665
								
							
						
					
					
						commit
						d32870628b
					
				
					 17 changed files with 469 additions and 75 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -46,3 +46,5 @@ bin/
 | 
			
		|||
/.idea/
 | 
			
		||||
 | 
			
		||||
gradle.properties
 | 
			
		||||
 | 
			
		||||
gradle.properties
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<CommandMap> COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT)
 | 
			
		||||
            .withClassName("CraftServer")
 | 
			
		||||
            .withFieldName("commandMap")).valueLoader(Bukkit.getServer(), CommandMap.class);
 | 
			
		||||
 | 
			
		||||
    public static final FieldReflection.ValueModifier<Integer> 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<AtomicInteger> ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
 | 
			
		||||
            .withClassName(ENTITY_CLASS)
 | 
			
		||||
            .withFieldName("entityCount")
 | 
			
		||||
            .setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,25 +44,35 @@ public class FieldReflection extends ReflectionLazyLoader<Field> {
 | 
			
		|||
        logger.accept("Field Type: " + expectType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public FieldValueReflection<Object> staticValueLoader() {
 | 
			
		||||
    public ValueReflection<Object> staticValueLoader() {
 | 
			
		||||
        return staticValueLoader(Object.class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings("unused")
 | 
			
		||||
    public <T> FieldValueReflection<T> staticValueLoader(Class<T> valueType) {
 | 
			
		||||
        return new FieldValueReflection<>(this, possibleClassNames, null, strict);
 | 
			
		||||
    public <T> ValueReflection<T> staticValueLoader(Class<T> valueType) {
 | 
			
		||||
        return new ValueReflection<>(this, possibleClassNames, null, strict);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings("unused")
 | 
			
		||||
    public <T> FieldValueReflection<T> valueLoader(Object obj, Class<T> valueType) {
 | 
			
		||||
        return new FieldValueReflection<>(this, possibleClassNames, obj, strict);
 | 
			
		||||
    public <T> ValueReflection<T> valueLoader(Object obj, Class<T> valueType) {
 | 
			
		||||
        return new ValueReflection<>(this, possibleClassNames, obj, strict);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static class FieldValueReflection<T> extends ReflectionLazyLoader<T> {
 | 
			
		||||
        private final Object obj;
 | 
			
		||||
        private final FieldReflection fieldReflection;
 | 
			
		||||
    @SuppressWarnings("unused")
 | 
			
		||||
    public <T> ValueModifier<T> staticValueModifier(Class<T> valueType) {
 | 
			
		||||
        return new ValueModifier<>(this, possibleClassNames, null, strict);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        public FieldValueReflection(FieldReflection fieldReflection, List<String> className, Object obj, boolean strict) {
 | 
			
		||||
    @SuppressWarnings("unused")
 | 
			
		||||
    public <T> ValueModifier<T> valueModifier(Object obj, Class<T> valueType) {
 | 
			
		||||
        return new ValueModifier<>(this, possibleClassNames, obj, strict);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class ValueReflection<T> extends ReflectionLazyLoader<T> {
 | 
			
		||||
        protected final Object obj;
 | 
			
		||||
        protected final FieldReflection fieldReflection;
 | 
			
		||||
 | 
			
		||||
        private ValueReflection(FieldReflection fieldReflection, List<String> className, Object obj, boolean strict) {
 | 
			
		||||
            super(className, strict);
 | 
			
		||||
            this.obj = obj;
 | 
			
		||||
            this.fieldReflection = fieldReflection;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,4 +88,27 @@ public class FieldReflection extends ReflectionLazyLoader<Field> {
 | 
			
		|||
            fieldReflection.printDebugInfo(logger);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class ValueModifier<T> extends ValueReflection<T> {
 | 
			
		||||
        private ValueModifier(FieldReflection fieldReflection, List<String> 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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/main/java/lol/pyr/znpcsplus/entity/EntityIDProvider.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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<Player> 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/main/java/lol/pyr/znpcsplus/entity/PacketLocation.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<Player> 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/java/lol/pyr/znpcsplus/npc/NPCRegistry.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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<String, NPC> npcMap = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    public static NPC get(String id) {
 | 
			
		||||
        return npcMap.get(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Collection<NPC> 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<NPCType> npcTypes;
 | 
			
		||||
 | 
			
		||||
    public static List<NPCType> values() {
 | 
			
		||||
        return npcTypes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final EntityType type;
 | 
			
		||||
 | 
			
		||||
    public NPCType(EntityType type) {
 | 
			
		||||
        this.type = type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public EntityType getType() {
 | 
			
		||||
        return type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
        ImmutableList.Builder<NPCType> 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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<ServerVersion, LazyLoader<? extends PacketFactory>> 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<ServerVersion, LazyLoader<? extends PacketFactory>> 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<ServerVersion, LazyLoader<? extends PacketFactory>> buildFactoryMap() {
 | 
			
		||||
 | 
			
		||||
        HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> map = new HashMap<>();
 | 
			
		||||
        map.put(ServerVersion.V_1_8, LazyLoader.of(V1_8Factory::new));
 | 
			
		||||
        return map;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
package lol.pyr.znpcsplus.properties;
 | 
			
		||||
 | 
			
		||||
public class NPCProperty {
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in a new issue