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/
|
/.idea/
|
||||||
|
|
||||||
gradle.properties
|
gradle.properties
|
||||||
|
|
||||||
|
gradle.properties
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class DefaultCommand extends Command {
|
||||||
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NOT_SUPPORTED_NPC_TYPE);
|
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NOT_SUPPORTED_NPC_TYPE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name);
|
// ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name);
|
||||||
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
|
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);
|
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ZNPCsPlus.deleteNPC(id);
|
// ZNPCsPlus.deleteNPC(id);
|
||||||
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
|
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ public enum ConfigurationValue {
|
||||||
SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class),
|
SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class),
|
||||||
MAX_PATH_LOCATIONS("config", 500, Integer.class),
|
MAX_PATH_LOCATIONS("config", 500, Integer.class),
|
||||||
NAMING_METHOD("config", NamingType.DEFAULT, NamingType.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),
|
LINE_SPACING("config", 0.3D, Double.class),
|
||||||
ANIMATION_RGB("config", false, Boolean.class),
|
ANIMATION_RGB("config", false, Boolean.class),
|
||||||
CHECK_FOR_UPDATES("config", true, 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.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class containing all of the lazy-loaded reflections that the plugin uses to access
|
* 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)
|
public static final ReflectionLazyLoader<CommandMap> COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT)
|
||||||
.withClassName("CraftServer")
|
.withClassName("CraftServer")
|
||||||
.withFieldName("commandMap")).valueLoader(Bukkit.getServer(), CommandMap.class);
|
.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);
|
logger.accept("Field Type: " + expectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldValueReflection<Object> staticValueLoader() {
|
public ValueReflection<Object> staticValueLoader() {
|
||||||
return staticValueLoader(Object.class);
|
return staticValueLoader(Object.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public <T> FieldValueReflection<T> staticValueLoader(Class<T> valueType) {
|
public <T> ValueReflection<T> staticValueLoader(Class<T> valueType) {
|
||||||
return new FieldValueReflection<>(this, possibleClassNames, null, strict);
|
return new ValueReflection<>(this, possibleClassNames, null, strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public <T> FieldValueReflection<T> valueLoader(Object obj, Class<T> valueType) {
|
public <T> ValueReflection<T> valueLoader(Object obj, Class<T> valueType) {
|
||||||
return new FieldValueReflection<>(this, possibleClassNames, obj, strict);
|
return new ValueReflection<>(this, possibleClassNames, obj, strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FieldValueReflection<T> extends ReflectionLazyLoader<T> {
|
@SuppressWarnings("unused")
|
||||||
private final Object obj;
|
public <T> ValueModifier<T> staticValueModifier(Class<T> valueType) {
|
||||||
private final FieldReflection fieldReflection;
|
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);
|
super(className, strict);
|
||||||
this.obj = obj;
|
this.obj = obj;
|
||||||
this.fieldReflection = fieldReflection;
|
this.fieldReflection = fieldReflection;
|
||||||
|
@ -78,4 +88,27 @@ public class FieldReflection extends ReflectionLazyLoader<Field> {
|
||||||
fieldReflection.printDebugInfo(logger);
|
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.configuration.ConfigurationConstants;
|
||||||
import io.github.znetworkw.znpcservers.listeners.InventoryListener;
|
import io.github.znetworkw.znpcservers.listeners.InventoryListener;
|
||||||
import io.github.znetworkw.znpcservers.listeners.PlayerListener;
|
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.NPCPath;
|
||||||
import io.github.znetworkw.znpcservers.npc.NPCType;
|
|
||||||
import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener;
|
import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener;
|
||||||
import io.github.znetworkw.znpcservers.npc.task.NPCPositionTask;
|
import io.github.znetworkw.znpcservers.npc.task.NPCPositionTask;
|
||||||
import io.github.znetworkw.znpcservers.npc.task.NPCSaveTask;
|
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.user.ZUser;
|
||||||
import io.github.znetworkw.znpcservers.utility.BungeeUtils;
|
import io.github.znetworkw.znpcservers.utility.BungeeUtils;
|
||||||
import io.github.znetworkw.znpcservers.utility.SchedulerUtils;
|
import io.github.znetworkw.znpcservers.utility.SchedulerUtils;
|
||||||
import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer;
|
import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer;
|
||||||
import io.github.znetworkw.znpcservers.utility.location.ZLocation;
|
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.UpdateChecker;
|
||||||
import lol.pyr.znpcsplus.updater.UpdateNotificationListener;
|
import lol.pyr.znpcsplus.updater.UpdateNotificationListener;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
|
@ -30,13 +31,12 @@ import org.apache.commons.io.FileUtils;
|
||||||
import org.bstats.bukkit.Metrics;
|
import org.bstats.bukkit.Metrics;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.World;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class ZNPCsPlus extends JavaPlugin {
|
public class ZNPCsPlus extends JavaPlugin {
|
||||||
|
@ -56,25 +56,6 @@ public class ZNPCsPlus extends JavaPlugin {
|
||||||
|
|
||||||
private boolean enabled = false;
|
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
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||||
|
@ -146,6 +127,21 @@ public class ZNPCsPlus extends JavaPlugin {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)");
|
log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)");
|
||||||
log("");
|
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
|
@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;
|
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 {
|
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;
|
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 {
|
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.PacketEvents;
|
||||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
import lol.pyr.znpcsplus.entity.PacketEntity;
|
||||||
import lol.pyr.znpcsplus.util.LazyLoader;
|
import lol.pyr.znpcsplus.util.LazyLoader;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface PacketFactory {
|
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() {
|
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() {
|
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;
|
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 {
|
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