diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index 1ea090f..1615ab1 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -667,8 +667,5 @@ public final class Reflections { public static final ReflectionLazyLoader ATOMIC_ENTITY_ID_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .withClassName(ENTITY_CLASS) .withFieldName("entityCount") - .withFieldName("d") - .withFieldName("c") - .withExpectResult(AtomicInteger.class) .setStrict(Utils.versionNewer(14))).staticValueLoader(AtomicInteger.class); } diff --git a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 93d9dcb..09354c4 100644 --- a/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -6,18 +6,14 @@ import lol.pyr.znpcsplus.packets.PacketFactory; import org.bukkit.entity.Player; import java.util.Set; -import java.util.UUID; public class PacketEntity { private final int entityId; - private final UUID uuid; - private final EntityType type; private PacketLocation location; public PacketEntity(EntityType type, PacketLocation location) { this.entityId = EntityIDProvider.reserve(); - this.uuid = UUID.randomUUID(); this.type = type; this.location = location; } @@ -30,10 +26,6 @@ public class PacketEntity { return location; } - public UUID getUuid() { - return uuid; - } - public EntityType getType() { return type; } diff --git a/src/main/java/lol/pyr/znpcsplus/npc/NPC.java b/src/main/java/lol/pyr/znpcsplus/npc/NPC.java index 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/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)) + } }