From 3f3c864a54ff7dfac692437af5018233af09af27 Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Fri, 30 Nov 2018 18:45:19 +0100 Subject: [PATCH 1/9] Started on 1.7.10 (v1_7_R4) support (#10). The older version of Netty is causing a bug with TinyProtocol. --- .travis.yml | 2 + api/pom.xml | 6 + nms/pom.xml | 1 + nms/v1_7_R4/pom.xml | 35 ++++++ .../jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java | 118 ++++++++++++++++++ ...acketPlayOutEntityHeadRotationWrapper.java | 26 ++++ .../PacketPlayOutNamedEntitySpawnWrapper.java | 45 +++++++ .../PacketPlayOutPlayerInfoWrapper.java | 38 ++++++ .../PacketPlayOutScoreboardTeamWrapper.java | 53 ++++++++ 9 files changed, 324 insertions(+) create mode 100755 nms/v1_7_R4/pom.xml create mode 100755 nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java create mode 100755 nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java create mode 100755 nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java create mode 100755 nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java create mode 100755 nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java diff --git a/.travis.yml b/.travis.yml index fb99088..b81ba3c 100755 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ cache: - $HOME/.m2/ install: - wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar +- wget https://github.com/Sarabveer/CraftBukkit-Spigot-Binary/blob/master/spigot-1.7.10-R0.1/spigot-1.7.10-R0.1-1649.jar +- mvn install:install-file -Dfile=spigot-1.7.10-R0.1-1649.jar -DgroupId=org.spigotmc -DartifactId=spigot -Dversion=1.7.10-R0.1-SNAPSHOT -Dpackaging=jar - ls $HOME/.m2/repository/org/spigotmc/spigot/1.8-R0.1-SNAPSHOT >> /dev/null 2>&1 || java -jar BuildTools.jar --rev 1.8 >> /dev/null 2>&1 - ls $HOME/.m2/repository/org/spigotmc/spigot/1.8.3-R0.1-SNAPSHOT >> /dev/null 2>&1 || java -jar BuildTools.jar --rev 1.8.3 >> /dev/null 2>&1 - ls $HOME/.m2/repository/org/spigotmc/spigot/1.8.8-R0.1-SNAPSHOT >> /dev/null 2>&1 || java -jar BuildTools.jar --rev 1.8.8 >> /dev/null 2>&1 diff --git a/api/pom.xml b/api/pom.xml index 27be49f..3f4c2b3 100755 --- a/api/pom.xml +++ b/api/pom.xml @@ -19,6 +19,12 @@ ${project.version} compile + + net.jitse + npclib-nms-v1_7_R4 + ${project.version} + compile + net.jitse npclib-nms-v1_8_R1 diff --git a/nms/pom.xml b/nms/pom.xml index 93bb047..39613f0 100755 --- a/nms/pom.xml +++ b/nms/pom.xml @@ -13,6 +13,7 @@ npclib-nms + v1_7_R4 v1_8_R1 v1_8_R2 v1_8_R3 diff --git a/nms/v1_7_R4/pom.xml b/nms/v1_7_R4/pom.xml new file mode 100755 index 0000000..5324123 --- /dev/null +++ b/nms/v1_7_R4/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + + net.jitse + npclib-nms + 1.3 + + + npclib-nms-v1_7_R4 + + + + org.spigotmc + spigot + 1.7.10-R0.1-SNAPSHOT + provided + + + com.google.code.gson + gson + 2.8.5 + compile + + + io.netty + netty-all + 4.0.23.Final + compile + + + diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java new file mode 100755 index 0000000..3ddfb17 --- /dev/null +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.jitse.npclib.nms.v1_7_R4; + +import net.jitse.npclib.api.NPC; +import net.jitse.npclib.nms.holograms.Hologram; +import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutEntityHeadRotationWrapper; +import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutNamedEntitySpawnWrapper; +import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutPlayerInfoWrapper; +import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutScoreboardTeamWrapper; +import net.jitse.npclib.skin.Skin; +import net.minecraft.server.v1_7_R4.*; +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.com.mojang.authlib.properties.Property; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.List; +import java.util.UUID; + +/** + * @author Jitse Boonstra + */ +public class NPC_v1_7_R4 extends NPC { + + private Hologram hologram; + private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; + private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; + private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + + private GameProfile legacyGameProfile; + + public NPC_v1_7_R4(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { + super(plugin, skin, autoHideDistance, lines); + } + + @Override + public void createPackets() { + this.hologram = new Hologram(location.clone().add(0, 0.5, 0), lines); + hologram.generatePackets(false, false); + + this.legacyGameProfile = generateLegacyGameProfile(uuid, name); + PacketPlayOutPlayerInfoWrapper packetPlayOutPlayerInfoWrapper = new PacketPlayOutPlayerInfoWrapper(); + + // Packets for spawning the NPC: + this.packetPlayOutScoreboardTeamRegister = new PacketPlayOutScoreboardTeamWrapper() + .createRegisterTeam(name); // First packet to send. + + this.packetPlayOutPlayerInfoAdd = packetPlayOutPlayerInfoWrapper + .create(0, legacyGameProfile, name); // Second packet to send. + + this.packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawnWrapper() + .create(uuid, location, entityId); // Third packet to send. + + this.packetPlayOutEntityHeadRotation = new PacketPlayOutEntityHeadRotationWrapper() + .create(location, entityId); // Fourth packet to send. + + this.packetPlayOutPlayerInfoRemove = packetPlayOutPlayerInfoWrapper + .create(4, legacyGameProfile, name); // Fifth packet to send (delayed). + + // Packet for destroying the NPC: + this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + + // Second packet to send is "packetPlayOutPlayerInfoRemove". + + this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() + .createUnregisterTeam(name); // Third packet to send. + } + + @Override + public void sendShowPackets(Player player) { + PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; + + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); + playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); + playerConnection.sendPacket(packetPlayOutEntityHeadRotation); + + hologram.spawn(player); + + Bukkit.getScheduler().runTaskLater(plugin, () -> + playerConnection.sendPacket(packetPlayOutPlayerInfoRemove), 50); + } + + @Override + public void sendHidePackets(Player player, boolean scheduler) { + PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; + + playerConnection.sendPacket(packetPlayOutEntityDestroy); + playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); + + hologram.destroy(player); + + if (scheduler) { + // Sending this a bit later so the player doesn't see the name (for that split second). + Bukkit.getScheduler().runTaskLater(plugin, () -> + playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); + } else { + playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); + } + } + + private GameProfile generateLegacyGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } +} diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java new file mode 100755 index 0000000..a8af781 --- /dev/null +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.jitse.npclib.nms.v1_7_R4.packets; + +import com.comphenix.tinyprotocol.Reflection; +import net.minecraft.server.v1_7_R4.PacketPlayOutEntityHeadRotation; +import org.bukkit.Location; + +/** + * @author Jitse Boonstra + */ +public class PacketPlayOutEntityHeadRotationWrapper { + + public PacketPlayOutEntityHeadRotation create(Location location, int entityId) { + PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation = new PacketPlayOutEntityHeadRotation(); + + Reflection.getField(packetPlayOutEntityHeadRotation.getClass(), "a", int.class). + set(packetPlayOutEntityHeadRotation, entityId); + Reflection.getField(packetPlayOutEntityHeadRotation.getClass(), "b", byte.class) + .set(packetPlayOutEntityHeadRotation, (byte) ((int) location.getYaw() * 256.0F / 360.0F)); + + return packetPlayOutEntityHeadRotation; + } +} diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java new file mode 100755 index 0000000..95823a7 --- /dev/null +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.jitse.npclib.nms.v1_7_R4.packets; + +import com.comphenix.tinyprotocol.Reflection; +import net.minecraft.server.v1_7_R4.DataWatcher; +import net.minecraft.server.v1_7_R4.PacketPlayOutNamedEntitySpawn; +import org.bukkit.Location; + +import java.util.UUID; + +/** + * @author Jitse Boonstra + */ +public class PacketPlayOutNamedEntitySpawnWrapper { + + public PacketPlayOutNamedEntitySpawn create(UUID uuid, Location location, int entityId) { + PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawn(); + + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "a", int.class) + .set(packetPlayOutNamedEntitySpawn, entityId); + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "b", UUID.class) + .set(packetPlayOutNamedEntitySpawn, uuid); + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "c", int.class) + .set(packetPlayOutNamedEntitySpawn, (int) Math.floor(location.getX() * 32.0D)); + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "d", int.class) + .set(packetPlayOutNamedEntitySpawn, (int) Math.floor(location.getY() * 32.0D)); + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "e", int.class) + .set(packetPlayOutNamedEntitySpawn, (int) Math.floor(location.getZ() * 32.0D)); + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "f", byte.class) + .set(packetPlayOutNamedEntitySpawn, (byte) ((int) (location.getYaw() * 256.0F / 360.0F))); + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "g", byte.class) + .set(packetPlayOutNamedEntitySpawn, (byte) ((int) (location.getPitch() * 256.0F / 360.0F))); + + DataWatcher dataWatcher = new DataWatcher(null); + dataWatcher.a(10, (byte) 127); + + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "i", DataWatcher.class) + .set(packetPlayOutNamedEntitySpawn, dataWatcher); + + return packetPlayOutNamedEntitySpawn; + } +} diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java new file mode 100755 index 0000000..3673d16 --- /dev/null +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.jitse.npclib.nms.v1_7_R4.packets; + +import com.comphenix.tinyprotocol.Reflection; +import net.minecraft.server.v1_7_R4.PacketPlayOutPlayerInfo; +import net.minecraft.util.com.mojang.authlib.GameProfile; + +/** + * @author Jitse Boonstra + */ +public class PacketPlayOutPlayerInfoWrapper { + + public PacketPlayOutPlayerInfo create(int action, GameProfile gameProfile, String name) { + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); + + // Action values: + // 0 = Add player + // 1 = Update gamemode + // 2 = Update latency + // 3 = Update display name + // 4 = Remove player + Reflection.getField(packetPlayOutPlayerInfo.getClass(), "action", int.class) + .set(packetPlayOutPlayerInfo, action); + Reflection.getField(packetPlayOutPlayerInfo.getClass(), "player", GameProfile.class) + .set(packetPlayOutPlayerInfo, gameProfile); + Reflection.getField(packetPlayOutPlayerInfo.getClass(), "username", String.class) + .set(packetPlayOutPlayerInfo, name); + Reflection.getField(packetPlayOutPlayerInfo.getClass(), "ping", int.class) + .set(packetPlayOutPlayerInfo, 0); + Reflection.getField(packetPlayOutPlayerInfo.getClass(), "gamemode", int.class) + .set(packetPlayOutPlayerInfo, 1); + + return packetPlayOutPlayerInfo; + } +} diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java new file mode 100755 index 0000000..31002f1 --- /dev/null +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.jitse.npclib.nms.v1_7_R4.packets; + +import com.comphenix.tinyprotocol.Reflection; +import net.minecraft.server.v1_7_R4.PacketPlayOutScoreboardTeam; +import org.bukkit.ChatColor; + +import java.util.Collection; + +/** + * @author Jitse Boonstra + */ +public class PacketPlayOutScoreboardTeamWrapper { + + public PacketPlayOutScoreboardTeam createRegisterTeam(String name) { + PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeam = new PacketPlayOutScoreboardTeam(); + + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "h", int.class) + .set(packetPlayOutScoreboardTeam, 0); + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "b", String.class) + .set(packetPlayOutScoreboardTeam, name); + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "a", String.class) + .set(packetPlayOutScoreboardTeam, name); + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "e", String.class) + .set(packetPlayOutScoreboardTeam, "never"); + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "i", int.class) + .set(packetPlayOutScoreboardTeam, 1); + // Could not get this working in the PacketPlayOutPlayerInfoWrapper class. + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "c", String.class) + .set(packetPlayOutScoreboardTeam, ChatColor.BLUE + "[NPC] "); + Reflection.FieldAccessor collectionFieldAccessor = Reflection.getField( + packetPlayOutScoreboardTeam.getClass(), "g", Collection.class); + Collection collection = collectionFieldAccessor.get(packetPlayOutScoreboardTeam); + collection.add(name); + collectionFieldAccessor.set(packetPlayOutScoreboardTeam, collection); + + return packetPlayOutScoreboardTeam; + } + + public PacketPlayOutScoreboardTeam createUnregisterTeam(String name) { + PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeam = new PacketPlayOutScoreboardTeam(); + + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "h", int.class) + .set(packetPlayOutScoreboardTeam, 1); + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "a", String.class) + .set(packetPlayOutScoreboardTeam, name); + + return packetPlayOutScoreboardTeam; + } +} From ddf90fe005d1c68305d2b8d5cd9b96f6d6ff0a56 Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Tue, 11 Dec 2018 21:51:37 +0100 Subject: [PATCH 2/9] Unpushed work. --- commons/pom.xml | 6 + .../main/java/net/jitse/npclib/api/NPC.java | 14 - .../npclib/listeners/PacketListener.java | 91 +++- .../jitse/npclib/nms/holograms/Hologram.java | 2 +- .../npclib/nms/v1_10_R1/NPC_v1_10_R1.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../npclib/nms/v1_11_R1/NPC_v1_11_R1.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../npclib/nms/v1_12_R1/NPC_v1_12_R1.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../npclib/nms/v1_13_R1/NPC_v1_13_R1.java | 15 +- ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../nms/v1_13_R2/.NPC_v1_13_R2.java.swp | Bin 0 -> 16384 bytes .../npclib/nms/v1_13_R2/NPC_v1_13_R2.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- nms/v1_7_R4/pom.xml | 6 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java | 14 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- tinyprotocol-legacy/pom.xml | 24 + .../comphenix/tinyprotocol/Reflection.java | 397 ++++++++++++++ .../comphenix/tinyprotocol/TinyProtocol.java | 502 ++++++++++++++++++ tinyprotocol/pom.xml | 24 + .../src/main/java/LegacyTinyProtocol.java | 26 +- .../comphenix/tinyprotocol/Reflection.java | 4 + .../comphenix/tinyprotocol/TinyProtocol.java | 499 +++++++++++++++++ 67 files changed, 1719 insertions(+), 105 deletions(-) create mode 100644 nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/.NPC_v1_13_R2.java.swp create mode 100644 tinyprotocol-legacy/pom.xml create mode 100755 tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java create mode 100755 tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java create mode 100644 tinyprotocol/pom.xml rename commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java => tinyprotocol/src/main/java/LegacyTinyProtocol.java (94%) mode change 100755 => 100644 rename {commons => tinyprotocol}/src/main/java/com/comphenix/tinyprotocol/Reflection.java (99%) create mode 100755 tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java diff --git a/commons/pom.xml b/commons/pom.xml index f7e75d9..aa1ea8c 100755 --- a/commons/pom.xml +++ b/commons/pom.xml @@ -19,5 +19,11 @@ 1.13.2-R0.1-SNAPSHOT provided + + org.spigotmc + spigot + 1.7.10-R0.1-SNAPSHOT + provided + diff --git a/commons/src/main/java/net/jitse/npclib/api/NPC.java b/commons/src/main/java/net/jitse/npclib/api/NPC.java index 7856759..7b099e8 100755 --- a/commons/src/main/java/net/jitse/npclib/api/NPC.java +++ b/commons/src/main/java/net/jitse/npclib/api/NPC.java @@ -4,8 +4,6 @@ package net.jitse.npclib.api; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.NPCManager; import net.jitse.npclib.events.NPCDestroyEvent; import net.jitse.npclib.events.NPCSpawnEvent; @@ -39,7 +37,6 @@ public abstract class NPC implements PacketHandler, ActionHandler { protected final List lines; protected JavaPlugin plugin; - protected GameProfile gameProfile; protected Location location; public NPC(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { @@ -51,17 +48,6 @@ public abstract class NPC implements PacketHandler, ActionHandler { NPCManager.add(this); } - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } - - public void destroy() { destroy(true); } diff --git a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java index cb07d28..453a11a 100755 --- a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java +++ b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java @@ -4,9 +4,6 @@ package net.jitse.npclib.listeners; -import com.comphenix.tinyprotocol.Reflection; -import com.comphenix.tinyprotocol.TinyProtocol; -import io.netty.channel.Channel; import net.jitse.npclib.NPCManager; import net.jitse.npclib.api.NPC; import net.jitse.npclib.events.NPCInteractEvent; @@ -14,6 +11,9 @@ import net.jitse.npclib.events.click.ClickType; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; +import tinyprotocol.LegacyTinyProtocol; +import tinyprotocol.Reflection; +import tinyprotocol.TinyProtocol; import java.util.HashSet; import java.util.Set; @@ -35,38 +35,75 @@ public class PacketListener { private final Set delay = new HashSet<>(); public void start(JavaPlugin plugin) { - new TinyProtocol(plugin) { + String versionName = plugin.getServer().getClass().getPackage().getName().split("\\.")[3]; + if (versionName.equals("v1_7_R4")) { + new LegacyTinyProtocol(plugin) { - @Override - public Object onPacketInAsync(Player player, Channel channel, Object packet) { + @Override + public Object onPacketInAsync(Player player, net.minecraft.util.io.netty.channel.Channel channel, Object packet) { - if (packetPlayInUseEntityClazz.isInstance(packet)) { - NPC npc = NPCManager.getAllNPCs().stream().filter( - check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) - .findFirst().orElse(null); + if (packetPlayInUseEntityClazz.isInstance(packet)) { + NPC npc = NPCManager.getAllNPCs().stream().filter( + check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) + .findFirst().orElse(null); - if (npc == null) { - // Default player, not doing magic with the packet. - return super.onPacketInAsync(player, channel, packet); - } + if (npc == null) { + // Default player, not doing magic with the packet. + return super.onPacketInAsync(player, channel, packet); + } - if (delay.contains(player.getUniqueId())) { + if (delay.contains(player.getUniqueId())) { + return null; + } + + ClickType clickType = actionField.get(packet).toString() + .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; + + Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); + + UUID uuid = player.getUniqueId(); + delay.add(uuid); + Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); return null; } - ClickType clickType = actionField.get(packet).toString() - .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; - - Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); - - UUID uuid = player.getUniqueId(); - delay.add(uuid); - Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); - return null; + return super.onPacketInAsync(player, channel, packet); } + }; + } else { + new TinyProtocol(plugin) { - return super.onPacketInAsync(player, channel, packet); - } - }; + @Override + public Object onPacketInAsync(Player player, io.netty.channel.Channel channel, Object packet) { + + if (packetPlayInUseEntityClazz.isInstance(packet)) { + NPC npc = NPCManager.getAllNPCs().stream().filter( + check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) + .findFirst().orElse(null); + + if (npc == null) { + // Default player, not doing magic with the packet. + return super.onPacketInAsync(player, channel, packet); + } + + if (delay.contains(player.getUniqueId())) { + return null; + } + + ClickType clickType = actionField.get(packet).toString() + .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; + + Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); + + UUID uuid = player.getUniqueId(); + delay.add(uuid); + Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); + return null; + } + + return super.onPacketInAsync(player, channel, packet); + } + }; + } } } diff --git a/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java b/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java index f6ae8cd..93d6e03 100755 --- a/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java +++ b/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.holograms; -import com.comphenix.tinyprotocol.Reflection; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; +import tinyprotocol.Reflection; import java.util.ArrayList; import java.util.HashSet; diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java index b352b2d..116c5da 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_10_R1; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_10_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_10_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_10_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -101,4 +105,14 @@ public class NPC_v1_10_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 86a6457..013edcd 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_10_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_10_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 3a81184..f93494d 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_10_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_10_R1.DataWatcher; import net.minecraft.server.v1_10_R1.DataWatcherObject; import net.minecraft.server.v1_10_R1.DataWatcherRegistry; import net.minecraft.server.v1_10_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java index d07e54a..8eb3f76 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_10_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_10_R1.EnumGamemode; import net.minecraft.server.v1_10_R1.IChatBaseComponent; import net.minecraft.server.v1_10_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index d8a643a..862f917 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_10_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_10_R1.PacketPlayOutScoreboardTeam; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java index 9cab2e7..604bd18 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_11_R1; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_11_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_11_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_11_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -101,4 +105,14 @@ public class NPC_v1_11_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 6de5178..afb2b71 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_11_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_11_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index d6e1cff..6f8bc62 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_11_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_11_R1.DataWatcher; import net.minecraft.server.v1_11_R1.DataWatcherObject; import net.minecraft.server.v1_11_R1.DataWatcherRegistry; import net.minecraft.server.v1_11_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 52413e5..50cffa0 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_11_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_11_R1.EnumGamemode; import net.minecraft.server.v1_11_R1.IChatBaseComponent; import net.minecraft.server.v1_11_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 957b4e5..189cd28 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_11_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_11_R1.PacketPlayOutScoreboardTeam; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java index 348bd9d..a68aad6 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_12_R1; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_12_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_12_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_12_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -101,4 +105,14 @@ public class NPC_v1_12_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 2abba78..5150f55 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_12_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_12_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 323abde..4b523c0 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_12_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_12_R1.DataWatcher; import net.minecraft.server.v1_12_R1.DataWatcherObject; import net.minecraft.server.v1_12_R1.DataWatcherRegistry; import net.minecraft.server.v1_12_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java index f13a0a4..5934af8 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_12_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_12_R1.EnumGamemode; import net.minecraft.server.v1_12_R1.IChatBaseComponent; import net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 70a7b06..c1a72fd 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_12_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_12_R1.PacketPlayOutScoreboardTeam; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java index b64b767..3f19b4e 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_13_R1; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_13_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -13,12 +15,12 @@ import net.jitse.npclib.nms.v1_13_R1.packets.PacketPlayOutScoreboardTeamWrapper; import net.jitse.npclib.skin.Skin; import net.minecraft.server.v1_13_R1.*; import org.bukkit.Bukkit; - import org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -31,6 +33,7 @@ public class NPC_v1_13_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_13_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -102,4 +105,14 @@ public class NPC_v1_13_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index b9b91f7..54343a4 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_13_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 151619d..e27bcb1 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R1.DataWatcher; import net.minecraft.server.v1_13_R1.DataWatcherObject; import net.minecraft.server.v1_13_R1.DataWatcherRegistry; import net.minecraft.server.v1_13_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 578efb0..298a164 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_13_R1.EnumGamemode; import net.minecraft.server.v1_13_R1.IChatBaseComponent; import net.minecraft.server.v1_13_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 71b3bb0..f6b4760 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_13_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R1.ChatComponentText; import net.minecraft.server.v1_13_R1.IChatBaseComponent; import net.minecraft.server.v1_13_R1.PacketPlayOutScoreboardTeam; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/.NPC_v1_13_R2.java.swp b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/.NPC_v1_13_R2.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..4de2afeb7e79fb5da4cf0840c6c6a33ea6383d9b GIT binary patch literal 16384 zcmeHNU2Gl26`qDbp%g-a2P#@Lagf*>IeYCuD3Ag%u^~zGWBDf}6_PdH9pAh5-ksI# ztbL8+An^b^@Id}a#w#q1km$`?#2~P#9ynTH7;L%{Q9rcp- z>iEL=y$dsY+llnrJr+dmWt3<~T(y^VjqND*!lo?BFBAn`E#EZ4-dhH)S_W<+_wF6f zLVefBPI}v|^H(hsw&9im%YbFTGGH073|Iy%1D1iSkpUHNBhR7X+w#WG=D$B^{9cpa z@5+DY8t?O4`(qif3|Iy%1C{~HfMvikU>UFsSOzQumI2Ga{~-g+C*&uvYfUfsvHxGJ z|G(Wq$UlL<0iOf!0q+7Y0`tIqz;@vMn+bUe*a7_cCPLl<65up&7x3+mQ6BgV_!ICu z;2q#?;3eRB;52Xwco4XFBO$*9ehz$!GYBsOU7!PO13tNdkdJ|nfDeGzfhT~U0(Ssk zTu(>@^ngj=>mQ;{;2q%Cz=i7wIS;%5+z;#n{&g)OuK}+DQ@|g$6Y>Y(954dx1inB5 z6(%%2g8Y0=hxa>-hbvmW=2s@a&Gxhx&pATAF_OJc(J zFUN>kPe{HfnDpm3>&@^^kSH#psox$`Mac?n(nKGoj&o45C1pfgxkStDaCL}9e#o7c z+bm@Wi_^t0@aU=te5%==?TRyo@x(FO3T5<}%%TG)R=Jdc&y9g+`(_sOyPo7s@%c#R zZPD#=B5>W>Pup!e*A1jkO?OfyvRd7~7S#cwQnEPa z(rJ}kqW)R#iKuA+4H7z1tJXALckB%BiB&%0mRi;uX}oBXCrXO7L6+479G>~_VK|It zyU5kwuTx}4&S&qJkMjV^F%+>{M+r=ql1-s!Y|nd=yFtab1@znJ&DbAGAppwTYfy2FL7> zF344G5+Z|4D=F=pRnCoBn=7FW1sxu7i2?hGGT!IdcT*!{Qn69h@3SWWRf3xGjZt2#24HZc8-HMZbP>J&S6Em74C`&Z{@<0aQ@_O8{y)IKf!_mjz;WOh@F?(KtoPpp-T+Pk zw*$8U-(byu5%>q7^8oh)=drH;E3gI#AON}m1-?SPUjiQjzXB$J1Hj$DU4XXhPQYH4 z0n318z%pPNunbrRECZH-|1|?9&0i+_C0D78>M4sXv7r-SrI@~}WSjJUMENiK=yZj;ivuo(I!Kv1n1)o8o?5$$%7^UYJvpM>8oPlSD7cJXWim;xu1r5^Tm~E zG{=&aqsVuasW_)a_dG(Xc4b>Lk#Dl3*p6XzF;FzrrD!6u-40_j^#xC&dlYt#c=lN5 zDXF7(M^u;LaU7yxl5O);b|f;FD9oz)L$R=R^UW3H3-zWR8rL^)%WO?&MaylY3PW4g zQOo01tuV?<=g7C_Di5yUPM}VanmkEkCvcQ53K4RK{AZO;-Itqg4sMx)bv(k`#wui9 Qva6MS+3)TwD_?f@cjDd$3jhEB literal 0 HcmV?d00001 diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java index 0efa24f..430b7e4 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_13_R2; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_13_R2.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_13_R2 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_13_R2(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -101,4 +105,14 @@ public class NPC_v1_13_R2 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java index cbfc542..153de2d 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_13_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R2.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java index e0ab83b..3428361 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R2.DataWatcher; import net.minecraft.server.v1_13_R2.DataWatcherObject; import net.minecraft.server.v1_13_R2.DataWatcherRegistry; import net.minecraft.server.v1_13_R2.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java index 79e1fbb..1062e71 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_13_R2.EnumGamemode; import net.minecraft.server.v1_13_R2.IChatBaseComponent; import net.minecraft.server.v1_13_R2.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java index 9beae2c..559569b 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_13_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R2.ChatComponentText; import net.minecraft.server.v1_13_R2.IChatBaseComponent; import net.minecraft.server.v1_13_R2.PacketPlayOutScoreboardTeam; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_7_R4/pom.xml b/nms/v1_7_R4/pom.xml index 5324123..a8da360 100755 --- a/nms/v1_7_R4/pom.xml +++ b/nms/v1_7_R4/pom.xml @@ -25,11 +25,5 @@ 2.8.5 compile - - io.netty - netty-all - 4.0.23.Final - compile - diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java index a8af781..eee28e8 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_7_R4.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 95823a7..094a6b6 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_7_R4.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.DataWatcher; import net.minecraft.server.v1_7_R4.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java index 3673d16..de5002e 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_7_R4.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.PacketPlayOutPlayerInfo; import net.minecraft.util.com.mojang.authlib.GameProfile; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java index 31002f1..5be25bb 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_7_R4.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java index 44987ec..c3f06c2 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_8_R1; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_8_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_8_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_8_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -100,4 +104,14 @@ public class NPC_v1_8_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 4d6eb40..2ad82c1 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index eac29db..51b544d 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_8_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R1.DataWatcher; import net.minecraft.server.v1_8_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 283b46e..da25dbc 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_8_R1.*; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index e682a39..7d58571 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R1.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java index 978f409..a72645e 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_8_R2; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_8_R2.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_8_R2 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_8_R2(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -100,4 +104,14 @@ public class NPC_v1_8_R2 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java index 5ac6220..90e8460 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R2.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java index f48b8c8..6ae1f99 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_8_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R2.DataWatcher; import net.minecraft.server.v1_8_R2.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java index bca9688..5391f9b 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,11 +4,11 @@ package net.jitse.npclib.nms.v1_8_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_8_R2.IChatBaseComponent; import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_8_R2.WorldSettings; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java index 89a6e7a..4a34e33 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R2.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java index 4a8af07..39327b2 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_8_R3; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_8_R3.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_8_R3 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_8_R3(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -101,4 +105,14 @@ public class NPC_v1_8_R3 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java index e50ebb9..c402e3e 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R3.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R3.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java index b23b72b..ba0d2d8 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_8_R3.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R3.DataWatcher; import net.minecraft.server.v1_8_R3.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java index 3c411df..efa002f 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,11 +4,11 @@ package net.jitse.npclib.nms.v1_8_R3.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_8_R3.IChatBaseComponent; import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_8_R3.WorldSettings; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java index 3b6b53c..eba0912 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R3.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R3.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java index dd89e26..33b5a5f 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_9_R1; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_9_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_9_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_9_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -101,4 +105,14 @@ public class NPC_v1_9_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 72b2a04..9533973 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_9_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index d0a2504..af1ae34 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R1.DataWatcher; import net.minecraft.server.v1_9_R1.DataWatcherObject; import net.minecraft.server.v1_9_R1.DataWatcherRegistry; import net.minecraft.server.v1_9_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 43695c7..3db1b63 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_9_R1.IChatBaseComponent; import net.minecraft.server.v1_9_R1.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_9_R1.WorldSettings; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 41e6873..9bdac53 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_9_R1.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R1.PacketPlayOutScoreboardTeam; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java index d254033..7de3eea 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java @@ -4,6 +4,8 @@ package net.jitse.npclib.nms.v1_9_R2; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_9_R2.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -18,6 +20,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; +import java.util.UUID; /** * @author Jitse Boonstra @@ -30,6 +33,7 @@ public class NPC_v1_9_R2 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private GameProfile gameProfile; public NPC_v1_9_R2(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -101,4 +105,14 @@ public class NPC_v1_9_R2 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } + + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } } diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java index 6b2d008..455c7ce 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_9_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R2.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; +import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 39f5a3c..5c79f9d 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R2.DataWatcher; import net.minecraft.server.v1_9_R2.DataWatcherObject; import net.minecraft.server.v1_9_R2.DataWatcherRegistry; import net.minecraft.server.v1_9_R2.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; +import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java index 67afd64..c5e2863 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_9_R2.IChatBaseComponent; import net.minecraft.server.v1_9_R2.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_9_R2.WorldSettings; import org.bukkit.ChatColor; +import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java index 7856b63..6751de4 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_9_R2.packets; -import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R2.PacketPlayOutScoreboardTeam; +import tinyprotocol.Reflection; import java.util.Collection; diff --git a/tinyprotocol-legacy/pom.xml b/tinyprotocol-legacy/pom.xml new file mode 100644 index 0000000..f55b7c4 --- /dev/null +++ b/tinyprotocol-legacy/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + pom + + + net.jitse + npclib + 1.3 + + + npclib-tinyprotocol-legacy + + + + org.spigotmc + spigot + 1.7.10-R0.1-SNAPSHOT + provided + + + diff --git a/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java b/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java new file mode 100755 index 0000000..eb52597 --- /dev/null +++ b/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.comphenix.tinyprotocol; + +import org.bukkit.Bukkit; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * An utility class that simplifies reflection in Bukkit plugins. + * + * @author Kristian + */ +public final class Reflection { + /** + * An interface for invoking a specific constructor. + */ + public interface ConstructorInvoker { + /** + * Invoke a constructor for a specific class. + * + * @param arguments - the arguments to pass to the constructor. + * @return The constructed object. + */ + Object invoke(Object... arguments); + } + + /** + * An interface for invoking a specific method. + */ + public interface MethodInvoker { + /** + * Invoke a method on a specific target object. + * + * @param target - the target object, or NULL for a static method. + * @param arguments - the arguments to pass to the method. + * @return The return value, or NULL if is void. + */ + Object invoke(Object target, Object... arguments); + } + + /** + * An interface for retrieving the field content. + * + * @param - field type. + */ + public interface FieldAccessor { + /** + * Retrieve the content of a field. + * + * @param target - the target object, or NULL for a static field. + * @return The value of the field. + */ + T get(Object target); + + /** + * Set the content of a field. + * + * @param target - the target object, or NULL for a static field. + * @param value - the new value of the field. + */ + void set(Object target, Object value); + + /** + * Determine if the given object has this field. + * + * @param target - the object to test. + * @return TRUE if it does, FALSE otherwise. + */ + boolean hasField(Object target); + } + + // Deduce the net.minecraft.server.v* package + private static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName(); + private static String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server"); + private static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", ""); + + // Variable replacement + private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^}]+)\\}"); + + private Reflection() { + // Seal class + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param target - the target type. + * @param name - the name of the field, or NULL to ignore. + * @param fieldType - a compatible field type. + * @return The field accessor. + */ + public static FieldAccessor getField(Class target, String name, Class fieldType) { + return getField(target, name, fieldType, 0); + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param name - the name of the field, or NULL to ignore. + * @param fieldType - a compatible field type. + * @return The field accessor. + */ + public static FieldAccessor getField(String className, String name, Class fieldType) { + return getField(getClass(className), name, fieldType, 0); + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param target - the target type. + * @param fieldType - a compatible field type. + * @param index - the number of compatible fields to skip. + * @return The field accessor. + */ + public static FieldAccessor getField(Class target, Class fieldType, int index) { + return getField(target, null, fieldType, index); + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param fieldType - a compatible field type. + * @param index - the number of compatible fields to skip. + * @return The field accessor. + */ + public static FieldAccessor getField(String className, Class fieldType, int index) { + return getField(getClass(className), fieldType, index); + } + + // Common method + private static FieldAccessor getField(Class target, String name, Class fieldType, int index) { + for (final Field field : target.getDeclaredFields()) { + if ((name == null || field.getName().equals(name)) && fieldType.isAssignableFrom(field.getType()) && index-- <= 0) { + field.setAccessible(true); + + // A function for retrieving a specific field value + return new FieldAccessor() { + + @Override + @SuppressWarnings("unchecked") + public T get(Object target) { + try { + return (T) field.get(target); + } catch (IllegalAccessException e) { + throw new RuntimeException("Cannot access reflection.", e); + } + } + + @Override + public void set(Object target, Object value) { + try { + field.set(target, value); + } catch (IllegalAccessException e) { + throw new RuntimeException("Cannot access reflection.", e); + } + } + + @Override + public boolean hasField(Object target) { + // target instanceof DeclaringClass + return field.getDeclaringClass().isAssignableFrom(target.getClass()); + } + }; + } + } + + // Search in parent classes + if (target.getSuperclass() != null) + return getField(target.getSuperclass(), name, fieldType, index); + + throw new IllegalArgumentException("Cannot find field with type " + fieldType); + } + + /** + * Search for the first publicly and privately defined method of the given name and parameter count. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param methodName - the method name, or NULL to skip. + * @param params - the expected parameters. + * @return An object that invokes this specific method. + * @throws IllegalStateException If we cannot find this method. + */ + public static MethodInvoker getMethod(String className, String methodName, Class... params) { + return getTypedMethod(getClass(className), methodName, null, params); + } + + /** + * Search for the first publicly and privately defined method of the given name and parameter count. + * + * @param clazz - a class to start with. + * @param methodName - the method name, or NULL to skip. + * @param params - the expected parameters. + * @return An object that invokes this specific method. + * @throws IllegalStateException If we cannot find this method. + */ + public static MethodInvoker getMethod(Class clazz, String methodName, Class... params) { + return getTypedMethod(clazz, methodName, null, params); + } + + /** + * Search for the first publicly and privately defined method of the given name and parameter count. + * + * @param clazz - a class to start with. + * @param methodName - the method name, or NULL to skip. + * @param returnType - the expected return type, or NULL to ignore. + * @param params - the expected parameters. + * @return An object that invokes this specific method. + * @throws IllegalStateException If we cannot find this method. + */ + public static MethodInvoker getTypedMethod(Class clazz, String methodName, Class returnType, Class... params) { + for (final Method method : clazz.getDeclaredMethods()) { + if ((methodName == null || method.getName().equals(methodName)) + && (returnType == null || method.getReturnType().equals(returnType)) + && Arrays.equals(method.getParameterTypes(), params)) { + method.setAccessible(true); + + return (target, arguments) -> { + try { + return method.invoke(target, arguments); + } catch (Exception e) { + throw new RuntimeException("Cannot invoke method " + method, e); + } + }; + } + } + + // Search in every superclass + if (clazz.getSuperclass() != null) + return getMethod(clazz.getSuperclass(), methodName, params); + + throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params))); + } + + /** + * Search for the first publically and privately defined constructor of the given name and parameter count. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param params - the expected parameters. + * @return An object that invokes this constructor. + * @throws IllegalStateException If we cannot find this method. + */ + public static ConstructorInvoker getConstructor(String className, Class... params) { + return getConstructor(getClass(className), params); + } + + /** + * Search for the first publicly and privately defined constructor of the given name and parameter count. + * + * @param clazz - a class to start with. + * @param params - the expected parameters. + * @return An object that invokes this constructor. + * @throws IllegalStateException If we cannot find this method. + */ + public static ConstructorInvoker getConstructor(Class clazz, Class... params) { + for (final Constructor constructor : clazz.getDeclaredConstructors()) { + if (Arrays.equals(constructor.getParameterTypes(), params)) { + constructor.setAccessible(true); + + return arguments -> { + try { + return constructor.newInstance(arguments); + } catch (Exception e) { + throw new RuntimeException("Cannot invoke constructor " + constructor, e); + } + }; + } + } + + throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params))); + } + + /** + * Retrieve a class from its full name, without knowing its type on compile time. + *

+ * This is useful when looking up fields by a NMS or OBC type. + *

+ * + * @param lookupName - the class name with variables. + * @return The class. + * @see {@link #getClass()} for more information. + */ + public static Class getUntypedClass(String lookupName) { + @SuppressWarnings({"rawtypes", "unchecked"}) + Class clazz = (Class) getClass(lookupName); + return clazz; + } + + /** + * Retrieve a class from its full name. + *

+ * Strings enclosed with curly brackets - such as {TEXT} - will be replaced according to the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
VariableContent
{nms}Actual package name of net.minecraft.server.VERSION
{obc}Actual pacakge name of org.bukkit.craftbukkit.VERSION
{version}The current Minecraft package VERSION, if any.
+ * + * @param lookupName - the class name with variables. + * @return The looked up class. + * @throws IllegalArgumentException If a variable or class could not be found. + */ + public static Class getClass(String lookupName) { + return getCanonicalClass(expandVariables(lookupName)); + } + + /** + * Retrieve a class in the net.minecraft.server.VERSION.* package. + * + * @param name - the name of the class, excluding the package. + * @throws IllegalArgumentException If the class doesn't exist. + */ + public static Class getMinecraftClass(String name) { + return getCanonicalClass(NMS_PREFIX + "." + name); + } + + /** + * Retrieve a class in the org.bukkit.craftbukkit.VERSION.* package. + * + * @param name - the name of the class, excluding the package. + * @throws IllegalArgumentException If the class doesn't exist. + */ + public static Class getCraftBukkitClass(String name) { + return getCanonicalClass(OBC_PREFIX + "." + name); + } + + /** + * Retrieve a class by its canonical name. + * + * @param canonicalName - the canonical name. + * @return The class. + */ + private static Class getCanonicalClass(String canonicalName) { + try { + return Class.forName(canonicalName); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Cannot find " + canonicalName, e); + } + } + + /** + * Expand variables such as "{nms}" and "{obc}" to their corresponding packages. + * + * @param name - the full name of the class. + * @return The expanded string. + */ + private static String expandVariables(String name) { + StringBuffer output = new StringBuffer(); + Matcher matcher = MATCH_VARIABLE.matcher(name); + + while (matcher.find()) { + String variable = matcher.group(1); + String replacement; + + // Expand all detected variables + if ("nms".equalsIgnoreCase(variable)) + replacement = NMS_PREFIX; + else if ("obc".equalsIgnoreCase(variable)) + replacement = OBC_PREFIX; + else if ("version".equalsIgnoreCase(variable)) + replacement = VERSION; + else + throw new IllegalArgumentException("Unknown variable: " + variable); + + // Assume the expanded variables are all packages, and append a dot + if (replacement.length() > 0 && matcher.end() < name.length() && name.charAt(matcher.end()) != '.') + replacement += "."; + matcher.appendReplacement(output, Matcher.quoteReplacement(replacement)); + } + + matcher.appendTail(output); + return output.toString(); + } +} \ No newline at end of file diff --git a/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java b/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java new file mode 100755 index 0000000..9fc2a39 --- /dev/null +++ b/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.comphenix.tinyprotocol; + +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.mojang.authlib.GameProfile; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; + +/** + * Represents a very tiny alternative to ProtocolLib. + *

+ * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! + * + * @author Kristian + */ +public abstract class TinyProtocol { + private static final AtomicInteger ID = new AtomicInteger(0); + + // Used in order to lookup a channel + private static final Reflection.MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); + private static final Reflection.FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class); + private static final Reflection.FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class); + private static final Reflection.FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0); + + // Looking up ServerConnection + private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer"); + private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection"); + private static final Reflection.FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); + private static final Reflection.FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); + private static final Reflection.MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); + + // Packets we have to intercept + private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); + private static final Reflection.FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); + + // Speedup channel lookup + private Map channelLookup = new MapMaker().weakValues().makeMap(); + private Listener listener; + + // Channels that have already been removed + private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + + // List of network markers + private List networkManagers; + + // Injected channel handlers + private List serverChannels = Lists.newArrayList(); + private ChannelInboundHandlerAdapter serverChannelHandler; + private ChannelInitializer beginInitProtocol; + private ChannelInitializer endInitProtocol; + + // Current handler name + private String handlerName; + + protected volatile boolean closed; + protected Plugin plugin; + + /** + * Construct a new instance of com.comphenix.tinyprotocol.TinyProtocol, and start intercepting packets for all connected clients and future clients. + *

+ * You can construct multiple instances per plugin. + * + * @param plugin - the plugin. + */ + public TinyProtocol(final Plugin plugin) { + this.plugin = plugin; + + // Compute handler name + this.handlerName = getHandlerName(); + + // Prepare existing players + registerBukkitEvents(); + + try { + registerChannelHandler(); + registerPlayers(plugin); + } catch (IllegalArgumentException ex) { + // Damn you, late bind + plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Delaying server channel injection due to late bind."); + + new BukkitRunnable() { + @Override + public void run() { + registerChannelHandler(); + registerPlayers(plugin); + plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Late bind injection successful."); + } + }.runTask(plugin); + } + } + + private void createServerChannelHandler() { + // Handle connected channels + endInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + try { + // This can take a while, so we need to stop the main thread from interfering + synchronized (networkManagers) { + // Stop injecting channels + if (!closed) { + channel.eventLoop().submit(() -> injectChannelInternal(channel)); + } + } + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); + } + } + + }; + + // This is executed before Minecraft's channel handler + beginInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + channel.pipeline().addLast(endInitProtocol); + } + + }; + + serverChannelHandler = new ChannelInboundHandlerAdapter() { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + Channel channel = (Channel) msg; + + // Prepare to initialize ths channel + channel.pipeline().addFirst(beginInitProtocol); + ctx.fireChannelRead(msg); + } + + }; + } + + /** + * Register bukkit events. + */ + private void registerBukkitEvents() { + listener = new Listener() { + + @EventHandler(priority = EventPriority.LOWEST) + public final void onPlayerLogin(PlayerLoginEvent e) { + if (closed) + return; + + Channel channel = getChannel(e.getPlayer()); + + // Don't inject players that have been explicitly uninjected + if (!uninjectedChannels.contains(channel)) { + injectPlayer(e.getPlayer()); + } + } + + @EventHandler + public final void onPluginDisable(PluginDisableEvent e) { + if (e.getPlugin().equals(plugin)) { + close(); + } + } + + }; + + plugin.getServer().getPluginManager().registerEvents(listener, plugin); + } + + @SuppressWarnings("unchecked") + private void registerChannelHandler() { + Object mcServer = getMinecraftServer.get(Bukkit.getServer()); + Object serverConnection = getServerConnection.get(mcServer); + boolean looking = true; + + // We need to synchronize against this list + networkManagers = (List) getNetworkMarkers.invoke(null, serverConnection); + createServerChannelHandler(); + + // Find the correct list, or implicitly throw an exception + for (int i = 0; looking; i++) { + List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); + + for (Object item : list) { + if (!ChannelFuture.class.isInstance(item)) + break; + + // Channel future that contains the server connection + Channel serverChannel = ((ChannelFuture) item).channel(); + + serverChannels.add(serverChannel); + serverChannel.pipeline().addFirst(serverChannelHandler); + looking = false; + } + } + } + + private void unregisterChannelHandler() { + if (serverChannelHandler == null) + return; + + for (Channel serverChannel : serverChannels) { + final ChannelPipeline pipeline = serverChannel.pipeline(); + + // Remove channel handler + serverChannel.eventLoop().execute(new Runnable() { + + @Override + public void run() { + try { + pipeline.remove(serverChannelHandler); + } catch (NoSuchElementException e) { + // That's fine + } + } + + }); + } + } + + private void registerPlayers(Plugin plugin) { + for (Player player : plugin.getServer().getOnlinePlayers()) { + injectPlayer(player); + } + } + + /** + * Invoked when the server is starting to send a packet to a player. + *

+ * Note that this is not executed on the main thread. + * + * @param receiver - the receiving player, NULL for early login/status packets. + * @param channel - the channel that received the packet. Never NULL. + * @param packet - the packet being sent. + * @return The packet to send instead, or NULL to cancel the transmission. + */ + public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { + return packet; + } + + /** + * Invoked when the server has received a packet from a given player. + *

+ * Use {@link Channel#remoteAddress()} to get the remote address of the client. + * + * @param sender - the player that sent the packet, NULL for early login/status packets. + * @param channel - channel that received the packet. Never NULL. + * @param packet - the packet being received. + * @return The packet to recieve instead, or NULL to cancel. + */ + public Object onPacketInAsync(Player sender, Channel channel, Object packet) { + return packet; + } + + /** + * Send a packet to a particular player. + *

+ * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param player - the destination player. + * @param packet - the packet to send. + */ + public void sendPacket(Player player, Object packet) { + sendPacket(getChannel(player), packet); + } + + /** + * Send a packet to a particular client. + *

+ * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet to send. + */ + public void sendPacket(Channel channel, Object packet) { + channel.pipeline().writeAndFlush(packet); + } + + /** + * Pretend that a given packet has been received from a player. + *

+ * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param player - the player that sent the packet. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Player player, Object packet) { + receivePacket(getChannel(player), packet); + } + + /** + * Pretend that a given packet has been received from a given client. + *

+ * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Channel channel, Object packet) { + channel.pipeline().context("encoder").fireChannelRead(packet); + } + + /** + * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. + *

+ * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. + * + * @return A unique channel handler name. + */ + protected String getHandlerName() { + return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); + } + + /** + * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. + *

+ * This will automatically be called when a player has logged in. + * + * @param player - the player to inject. + */ + public void injectPlayer(Player player) { + injectChannelInternal(getChannel(player)).player = player; + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + */ + public void injectChannel(Channel channel) { + injectChannelInternal(channel); + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + * @return The packet interceptor. + */ + private PacketInterceptor injectChannelInternal(Channel channel) { + try { + PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); + + // Inject our packet interceptor + if (interceptor == null) { + interceptor = new PacketInterceptor(); + channel.pipeline().addBefore("packet_handler", handlerName, interceptor); + uninjectedChannels.remove(channel); + } + + return interceptor; + } catch (IllegalArgumentException e) { + // Try again + return (PacketInterceptor) channel.pipeline().get(handlerName); + } + } + + /** + * Retrieve the Netty channel associated with a player. This is cached. + * + * @param player - the player. + * @return The Netty channel. + */ + public Channel getChannel(Player player) { + Channel channel = channelLookup.get(player.getName()); + + // Lookup channel again + if (channel == null) { + Object connection = getConnection.get(getPlayerHandle.invoke(player)); + Object manager = getManager.get(connection); + + channelLookup.put(player.getName(), channel = getChannel.get(manager)); + } + + return channel; + } + + /** + * Uninject a specific player. + * + * @param player - the injected player. + */ + public void uninjectPlayer(Player player) { + uninjectChannel(getChannel(player)); + } + + /** + * Uninject a specific channel. + *

+ * This will also disable the automatic channel injection that occurs when a player has properly logged in. + * + * @param channel - the injected channel. + */ + public void uninjectChannel(final Channel channel) { + // No need to guard against this if we're closing + if (!closed) { + uninjectedChannels.add(channel); + } + + // See ChannelInjector in ProtocolLib, line 590 + channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); + } + + /** + * Determine if the given player has been injected by com.comphenix.tinyprotocol.TinyProtocol. + * + * @param player - the player. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Player player) { + return hasInjected(getChannel(player)); + } + + /** + * Determine if the given channel has been injected by com.comphenix.tinyprotocol.TinyProtocol. + * + * @param channel - the channel. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Channel channel) { + return channel.pipeline().get(handlerName) != null; + } + + /** + * Cease listening for packets. This is called automatically when your plugin is disabled. + */ + public final void close() { + if (!closed) { + closed = true; + + // Remove our handlers + for (Player player : plugin.getServer().getOnlinePlayers()) { + uninjectPlayer(player); + } + + // Clean up Bukkit + HandlerList.unregisterAll(listener); + unregisterChannelHandler(); + } + } + + /** + * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. + * + * @author Kristian + */ + private final class PacketInterceptor extends ChannelDuplexHandler { + // Updated by the login event + public volatile Player player; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // Intercept channel + final Channel channel = ctx.channel(); + handleLoginStart(channel, msg); + + try { + msg = onPacketInAsync(player, channel, msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); + } + + if (msg != null) { + super.channelRead(ctx, msg); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + try { + msg = onPacketOutAsync(player, ctx.channel(), msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); + } + + if (msg != null) { + super.write(ctx, msg, promise); + } + } + + private void handleLoginStart(Channel channel, Object packet) { + if (PACKET_LOGIN_IN_START.isInstance(packet)) { + GameProfile profile = getGameProfile.get(packet); + channelLookup.put(profile.getName(), channel); + } + } + } +} \ No newline at end of file diff --git a/tinyprotocol/pom.xml b/tinyprotocol/pom.xml new file mode 100644 index 0000000..7a3e612 --- /dev/null +++ b/tinyprotocol/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + pom + + + net.jitse + npclib + 1.3 + + + npclib-tinyprotocol + + + + org.spigotmc + spigot + 1.13.2-R0.1-SNAPSHOT + provided + + + diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java b/tinyprotocol/src/main/java/LegacyTinyProtocol.java old mode 100755 new mode 100644 similarity index 94% rename from commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java rename to tinyprotocol/src/main/java/LegacyTinyProtocol.java index 5623c08..c3c54db --- a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/tinyprotocol/src/main/java/LegacyTinyProtocol.java @@ -1,11 +1,13 @@ -package com.comphenix.tinyprotocol; +/* + * Copyright (c) 2018 Jitse Boonstra + */ -import com.comphenix.tinyprotocol.Reflection.FieldAccessor; -import com.comphenix.tinyprotocol.Reflection.MethodInvoker; +import Reflection.FieldAccessor; +import Reflection.MethodInvoker; +import com.comphenix.tinyprotocol.Reflection; import com.google.common.collect.Lists; import com.google.common.collect.MapMaker; -import com.mojang.authlib.GameProfile; -import io.netty.channel.*; +import net.minecraft.util.com.mojang.authlib.GameProfile; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -28,7 +30,7 @@ import java.util.logging.Level; * * @author Kristian */ -public abstract class TinyProtocol { +public abstract class LegacyTinyProtocol { private static final AtomicInteger ID = new AtomicInteger(0); // Used in order to lookup a channel @@ -71,13 +73,13 @@ public abstract class TinyProtocol { protected Plugin plugin; /** - * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. + * Construct a new instance of com.comphenix.tinyprotocol.TinyProtocol, and start intercepting packets for all connected clients and future clients. *

* You can construct multiple instances per plugin. * * @param plugin - the plugin. */ - public TinyProtocol(final Plugin plugin) { + public LegacyTinyProtocol(final Plugin plugin) { this.plugin = plugin; // Compute handler name @@ -91,14 +93,14 @@ public abstract class TinyProtocol { registerPlayers(plugin); } catch (IllegalArgumentException ex) { // Damn you, late bind - plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind."); + plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Delaying server channel injection due to late bind."); new BukkitRunnable() { @Override public void run() { registerChannelHandler(); registerPlayers(plugin); - plugin.getLogger().info("[TinyProtocol] Late bind injection successful."); + plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Late bind injection successful."); } }.runTask(plugin); } @@ -415,7 +417,7 @@ public abstract class TinyProtocol { } /** - * Determine if the given player has been injected by TinyProtocol. + * Determine if the given player has been injected by com.comphenix.tinyprotocol.TinyProtocol. * * @param player - the player. * @return TRUE if it is, FALSE otherwise. @@ -425,7 +427,7 @@ public abstract class TinyProtocol { } /** - * Determine if the given channel has been injected by TinyProtocol. + * Determine if the given channel has been injected by com.comphenix.tinyprotocol.TinyProtocol. * * @param channel - the channel. * @return TRUE if it is, FALSE otherwise. diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/Reflection.java b/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/Reflection.java similarity index 99% rename from commons/src/main/java/com/comphenix/tinyprotocol/Reflection.java rename to tinyprotocol/src/main/java/com/comphenix/tinyprotocol/Reflection.java index acf0c5f..c2bbbec 100755 --- a/commons/src/main/java/com/comphenix/tinyprotocol/Reflection.java +++ b/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/Reflection.java @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + package com.comphenix.tinyprotocol; import org.bukkit.Bukkit; diff --git a/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java b/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java new file mode 100755 index 0000000..a9b6e59 --- /dev/null +++ b/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java @@ -0,0 +1,499 @@ +package com.comphenix.tinyprotocol; + +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.mojang.authlib.GameProfile; +import io.netty.channel.*; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; + +/** + * Represents a very tiny alternative to ProtocolLib. + *

+ * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! + * + * @author Kristian + */ +public abstract class TinyProtocol { + private static final AtomicInteger ID = new AtomicInteger(0); + + // Used in order to lookup a channel + private static final Reflection.MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); + private static final Reflection.FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class); + private static final Reflection.FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class); + private static final Reflection.FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0); + + // Looking up ServerConnection + private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer"); + private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection"); + private static final Reflection.FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); + private static final Reflection.FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); + private static final Reflection.MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); + + // Packets we have to intercept + private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); + private static final Reflection.FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); + + // Speedup channel lookup + private Map channelLookup = new MapMaker().weakValues().makeMap(); + private Listener listener; + + // Channels that have already been removed + private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + + // List of network markers + private List networkManagers; + + // Injected channel handlers + private List serverChannels = Lists.newArrayList(); + private ChannelInboundHandlerAdapter serverChannelHandler; + private ChannelInitializer beginInitProtocol; + private ChannelInitializer endInitProtocol; + + // Current handler name + private String handlerName; + + protected volatile boolean closed; + protected Plugin plugin; + + /** + * Construct a new instance of com.comphenix.tinyprotocol.TinyProtocol, and start intercepting packets for all connected clients and future clients. + *

+ * You can construct multiple instances per plugin. + * + * @param plugin - the plugin. + */ + public TinyProtocol(final Plugin plugin) { + this.plugin = plugin; + + // Compute handler name + this.handlerName = getHandlerName(); + + // Prepare existing players + registerBukkitEvents(); + + try { + registerChannelHandler(); + registerPlayers(plugin); + } catch (IllegalArgumentException ex) { + // Damn you, late bind + plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Delaying server channel injection due to late bind."); + + new BukkitRunnable() { + @Override + public void run() { + registerChannelHandler(); + registerPlayers(plugin); + plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Late bind injection successful."); + } + }.runTask(plugin); + } + } + + private void createServerChannelHandler() { + // Handle connected channels + endInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + try { + // This can take a while, so we need to stop the main thread from interfering + synchronized (networkManagers) { + // Stop injecting channels + if (!closed) { + channel.eventLoop().submit(() -> injectChannelInternal(channel)); + } + } + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); + } + } + + }; + + // This is executed before Minecraft's channel handler + beginInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + channel.pipeline().addLast(endInitProtocol); + } + + }; + + serverChannelHandler = new ChannelInboundHandlerAdapter() { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + Channel channel = (Channel) msg; + + // Prepare to initialize ths channel + channel.pipeline().addFirst(beginInitProtocol); + ctx.fireChannelRead(msg); + } + + }; + } + + /** + * Register bukkit events. + */ + private void registerBukkitEvents() { + listener = new Listener() { + + @EventHandler(priority = EventPriority.LOWEST) + public final void onPlayerLogin(PlayerLoginEvent e) { + if (closed) + return; + + Channel channel = getChannel(e.getPlayer()); + + // Don't inject players that have been explicitly uninjected + if (!uninjectedChannels.contains(channel)) { + injectPlayer(e.getPlayer()); + } + } + + @EventHandler + public final void onPluginDisable(PluginDisableEvent e) { + if (e.getPlugin().equals(plugin)) { + close(); + } + } + + }; + + plugin.getServer().getPluginManager().registerEvents(listener, plugin); + } + + @SuppressWarnings("unchecked") + private void registerChannelHandler() { + Object mcServer = getMinecraftServer.get(Bukkit.getServer()); + Object serverConnection = getServerConnection.get(mcServer); + boolean looking = true; + + // We need to synchronize against this list + networkManagers = (List) getNetworkMarkers.invoke(null, serverConnection); + createServerChannelHandler(); + + // Find the correct list, or implicitly throw an exception + for (int i = 0; looking; i++) { + List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); + + for (Object item : list) { + if (!ChannelFuture.class.isInstance(item)) + break; + + // Channel future that contains the server connection + Channel serverChannel = ((ChannelFuture) item).channel(); + + serverChannels.add(serverChannel); + serverChannel.pipeline().addFirst(serverChannelHandler); + looking = false; + } + } + } + + private void unregisterChannelHandler() { + if (serverChannelHandler == null) + return; + + for (Channel serverChannel : serverChannels) { + final ChannelPipeline pipeline = serverChannel.pipeline(); + + // Remove channel handler + serverChannel.eventLoop().execute(new Runnable() { + + @Override + public void run() { + try { + pipeline.remove(serverChannelHandler); + } catch (NoSuchElementException e) { + // That's fine + } + } + + }); + } + } + + private void registerPlayers(Plugin plugin) { + for (Player player : plugin.getServer().getOnlinePlayers()) { + injectPlayer(player); + } + } + + /** + * Invoked when the server is starting to send a packet to a player. + *

+ * Note that this is not executed on the main thread. + * + * @param receiver - the receiving player, NULL for early login/status packets. + * @param channel - the channel that received the packet. Never NULL. + * @param packet - the packet being sent. + * @return The packet to send instead, or NULL to cancel the transmission. + */ + public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { + return packet; + } + + /** + * Invoked when the server has received a packet from a given player. + *

+ * Use {@link Channel#remoteAddress()} to get the remote address of the client. + * + * @param sender - the player that sent the packet, NULL for early login/status packets. + * @param channel - channel that received the packet. Never NULL. + * @param packet - the packet being received. + * @return The packet to recieve instead, or NULL to cancel. + */ + public Object onPacketInAsync(Player sender, Channel channel, Object packet) { + return packet; + } + + /** + * Send a packet to a particular player. + *

+ * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param player - the destination player. + * @param packet - the packet to send. + */ + public void sendPacket(Player player, Object packet) { + sendPacket(getChannel(player), packet); + } + + /** + * Send a packet to a particular client. + *

+ * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet to send. + */ + public void sendPacket(Channel channel, Object packet) { + channel.pipeline().writeAndFlush(packet); + } + + /** + * Pretend that a given packet has been received from a player. + *

+ * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param player - the player that sent the packet. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Player player, Object packet) { + receivePacket(getChannel(player), packet); + } + + /** + * Pretend that a given packet has been received from a given client. + *

+ * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Channel channel, Object packet) { + channel.pipeline().context("encoder").fireChannelRead(packet); + } + + /** + * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. + *

+ * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. + * + * @return A unique channel handler name. + */ + protected String getHandlerName() { + return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); + } + + /** + * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. + *

+ * This will automatically be called when a player has logged in. + * + * @param player - the player to inject. + */ + public void injectPlayer(Player player) { + injectChannelInternal(getChannel(player)).player = player; + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + */ + public void injectChannel(Channel channel) { + injectChannelInternal(channel); + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + * @return The packet interceptor. + */ + private PacketInterceptor injectChannelInternal(Channel channel) { + try { + PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); + + // Inject our packet interceptor + if (interceptor == null) { + interceptor = new PacketInterceptor(); + channel.pipeline().addBefore("packet_handler", handlerName, interceptor); + uninjectedChannels.remove(channel); + } + + return interceptor; + } catch (IllegalArgumentException e) { + // Try again + return (PacketInterceptor) channel.pipeline().get(handlerName); + } + } + + /** + * Retrieve the Netty channel associated with a player. This is cached. + * + * @param player - the player. + * @return The Netty channel. + */ + public Channel getChannel(Player player) { + Channel channel = channelLookup.get(player.getName()); + + // Lookup channel again + if (channel == null) { + Object connection = getConnection.get(getPlayerHandle.invoke(player)); + Object manager = getManager.get(connection); + + channelLookup.put(player.getName(), channel = getChannel.get(manager)); + } + + return channel; + } + + /** + * Uninject a specific player. + * + * @param player - the injected player. + */ + public void uninjectPlayer(Player player) { + uninjectChannel(getChannel(player)); + } + + /** + * Uninject a specific channel. + *

+ * This will also disable the automatic channel injection that occurs when a player has properly logged in. + * + * @param channel - the injected channel. + */ + public void uninjectChannel(final Channel channel) { + // No need to guard against this if we're closing + if (!closed) { + uninjectedChannels.add(channel); + } + + // See ChannelInjector in ProtocolLib, line 590 + channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); + } + + /** + * Determine if the given player has been injected by com.comphenix.tinyprotocol.TinyProtocol. + * + * @param player - the player. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Player player) { + return hasInjected(getChannel(player)); + } + + /** + * Determine if the given channel has been injected by com.comphenix.tinyprotocol.TinyProtocol. + * + * @param channel - the channel. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Channel channel) { + return channel.pipeline().get(handlerName) != null; + } + + /** + * Cease listening for packets. This is called automatically when your plugin is disabled. + */ + public final void close() { + if (!closed) { + closed = true; + + // Remove our handlers + for (Player player : plugin.getServer().getOnlinePlayers()) { + uninjectPlayer(player); + } + + // Clean up Bukkit + HandlerList.unregisterAll(listener); + unregisterChannelHandler(); + } + } + + /** + * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. + * + * @author Kristian + */ + private final class PacketInterceptor extends ChannelDuplexHandler { + // Updated by the login event + public volatile Player player; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // Intercept channel + final Channel channel = ctx.channel(); + handleLoginStart(channel, msg); + + try { + msg = onPacketInAsync(player, channel, msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); + } + + if (msg != null) { + super.channelRead(ctx, msg); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + try { + msg = onPacketOutAsync(player, ctx.channel(), msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); + } + + if (msg != null) { + super.write(ctx, msg, promise); + } + } + + private void handleLoginStart(Channel channel, Object packet) { + if (PACKET_LOGIN_IN_START.isInstance(packet)) { + GameProfile profile = getGameProfile.get(packet); + channelLookup.put(profile.getName(), channel); + } + } + } +} \ No newline at end of file From d741db78dec18c56010c66c23de21ba1d9c8550d Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Fri, 14 Dec 2018 14:44:37 +0100 Subject: [PATCH 3/9] Revert "Unpushed work." This reverts commit ddf90fe005d1c68305d2b8d5cd9b96f6d6ff0a56. --- commons/pom.xml | 6 - .../comphenix/tinyprotocol/Reflection.java | 4 - .../comphenix/tinyprotocol/TinyProtocol.java | 26 +- .../main/java/net/jitse/npclib/api/NPC.java | 14 + .../npclib/listeners/PacketListener.java | 91 +--- .../jitse/npclib/nms/holograms/Hologram.java | 2 +- .../npclib/nms/v1_10_R1/NPC_v1_10_R1.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../npclib/nms/v1_11_R1/NPC_v1_11_R1.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../npclib/nms/v1_12_R1/NPC_v1_12_R1.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../npclib/nms/v1_13_R1/NPC_v1_13_R1.java | 15 +- ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../nms/v1_13_R2/.NPC_v1_13_R2.java.swp | Bin 16384 -> 0 bytes .../npclib/nms/v1_13_R2/NPC_v1_13_R2.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- nms/v1_7_R4/pom.xml | 6 + ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- .../jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java | 14 - ...acketPlayOutEntityHeadRotationWrapper.java | 2 +- .../PacketPlayOutNamedEntitySpawnWrapper.java | 2 +- .../PacketPlayOutPlayerInfoWrapper.java | 2 +- .../PacketPlayOutScoreboardTeamWrapper.java | 2 +- tinyprotocol-legacy/pom.xml | 24 - .../comphenix/tinyprotocol/Reflection.java | 397 -------------- .../comphenix/tinyprotocol/TinyProtocol.java | 502 ------------------ tinyprotocol/pom.xml | 24 - .../comphenix/tinyprotocol/TinyProtocol.java | 499 ----------------- 67 files changed, 105 insertions(+), 1719 deletions(-) rename {tinyprotocol => commons}/src/main/java/com/comphenix/tinyprotocol/Reflection.java (99%) rename tinyprotocol/src/main/java/LegacyTinyProtocol.java => commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java (94%) mode change 100644 => 100755 delete mode 100644 nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/.NPC_v1_13_R2.java.swp delete mode 100644 tinyprotocol-legacy/pom.xml delete mode 100755 tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java delete mode 100755 tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java delete mode 100644 tinyprotocol/pom.xml delete mode 100755 tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java diff --git a/commons/pom.xml b/commons/pom.xml index aa1ea8c..f7e75d9 100755 --- a/commons/pom.xml +++ b/commons/pom.xml @@ -19,11 +19,5 @@ 1.13.2-R0.1-SNAPSHOT provided - - org.spigotmc - spigot - 1.7.10-R0.1-SNAPSHOT - provided - diff --git a/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/Reflection.java b/commons/src/main/java/com/comphenix/tinyprotocol/Reflection.java similarity index 99% rename from tinyprotocol/src/main/java/com/comphenix/tinyprotocol/Reflection.java rename to commons/src/main/java/com/comphenix/tinyprotocol/Reflection.java index c2bbbec..acf0c5f 100755 --- a/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/Reflection.java +++ b/commons/src/main/java/com/comphenix/tinyprotocol/Reflection.java @@ -1,7 +1,3 @@ -/* - * Copyright (c) 2018 Jitse Boonstra - */ - package com.comphenix.tinyprotocol; import org.bukkit.Bukkit; diff --git a/tinyprotocol/src/main/java/LegacyTinyProtocol.java b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java old mode 100644 new mode 100755 similarity index 94% rename from tinyprotocol/src/main/java/LegacyTinyProtocol.java rename to commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java index c3c54db..5623c08 --- a/tinyprotocol/src/main/java/LegacyTinyProtocol.java +++ b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java @@ -1,13 +1,11 @@ -/* - * Copyright (c) 2018 Jitse Boonstra - */ +package com.comphenix.tinyprotocol; -import Reflection.FieldAccessor; -import Reflection.MethodInvoker; -import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.Reflection.FieldAccessor; +import com.comphenix.tinyprotocol.Reflection.MethodInvoker; import com.google.common.collect.Lists; import com.google.common.collect.MapMaker; -import net.minecraft.util.com.mojang.authlib.GameProfile; +import com.mojang.authlib.GameProfile; +import io.netty.channel.*; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -30,7 +28,7 @@ import java.util.logging.Level; * * @author Kristian */ -public abstract class LegacyTinyProtocol { +public abstract class TinyProtocol { private static final AtomicInteger ID = new AtomicInteger(0); // Used in order to lookup a channel @@ -73,13 +71,13 @@ public abstract class LegacyTinyProtocol { protected Plugin plugin; /** - * Construct a new instance of com.comphenix.tinyprotocol.TinyProtocol, and start intercepting packets for all connected clients and future clients. + * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. *

* You can construct multiple instances per plugin. * * @param plugin - the plugin. */ - public LegacyTinyProtocol(final Plugin plugin) { + public TinyProtocol(final Plugin plugin) { this.plugin = plugin; // Compute handler name @@ -93,14 +91,14 @@ public abstract class LegacyTinyProtocol { registerPlayers(plugin); } catch (IllegalArgumentException ex) { // Damn you, late bind - plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Delaying server channel injection due to late bind."); + plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind."); new BukkitRunnable() { @Override public void run() { registerChannelHandler(); registerPlayers(plugin); - plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Late bind injection successful."); + plugin.getLogger().info("[TinyProtocol] Late bind injection successful."); } }.runTask(plugin); } @@ -417,7 +415,7 @@ public abstract class LegacyTinyProtocol { } /** - * Determine if the given player has been injected by com.comphenix.tinyprotocol.TinyProtocol. + * Determine if the given player has been injected by TinyProtocol. * * @param player - the player. * @return TRUE if it is, FALSE otherwise. @@ -427,7 +425,7 @@ public abstract class LegacyTinyProtocol { } /** - * Determine if the given channel has been injected by com.comphenix.tinyprotocol.TinyProtocol. + * Determine if the given channel has been injected by TinyProtocol. * * @param channel - the channel. * @return TRUE if it is, FALSE otherwise. diff --git a/commons/src/main/java/net/jitse/npclib/api/NPC.java b/commons/src/main/java/net/jitse/npclib/api/NPC.java index 7b099e8..7856759 100755 --- a/commons/src/main/java/net/jitse/npclib/api/NPC.java +++ b/commons/src/main/java/net/jitse/npclib/api/NPC.java @@ -4,6 +4,8 @@ package net.jitse.npclib.api; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.jitse.npclib.NPCManager; import net.jitse.npclib.events.NPCDestroyEvent; import net.jitse.npclib.events.NPCSpawnEvent; @@ -37,6 +39,7 @@ public abstract class NPC implements PacketHandler, ActionHandler { protected final List lines; protected JavaPlugin plugin; + protected GameProfile gameProfile; protected Location location; public NPC(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { @@ -48,6 +51,17 @@ public abstract class NPC implements PacketHandler, ActionHandler { NPCManager.add(this); } + protected GameProfile generateGameProfile(UUID uuid, String name) { + GameProfile gameProfile = new GameProfile(uuid, name); + + if (skin != null) { + gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + + return gameProfile; + } + + public void destroy() { destroy(true); } diff --git a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java index 453a11a..cb07d28 100755 --- a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java +++ b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java @@ -4,6 +4,9 @@ package net.jitse.npclib.listeners; +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import io.netty.channel.Channel; import net.jitse.npclib.NPCManager; import net.jitse.npclib.api.NPC; import net.jitse.npclib.events.NPCInteractEvent; @@ -11,9 +14,6 @@ import net.jitse.npclib.events.click.ClickType; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; -import tinyprotocol.LegacyTinyProtocol; -import tinyprotocol.Reflection; -import tinyprotocol.TinyProtocol; import java.util.HashSet; import java.util.Set; @@ -35,75 +35,38 @@ public class PacketListener { private final Set delay = new HashSet<>(); public void start(JavaPlugin plugin) { - String versionName = plugin.getServer().getClass().getPackage().getName().split("\\.")[3]; - if (versionName.equals("v1_7_R4")) { - new LegacyTinyProtocol(plugin) { + new TinyProtocol(plugin) { - @Override - public Object onPacketInAsync(Player player, net.minecraft.util.io.netty.channel.Channel channel, Object packet) { + @Override + public Object onPacketInAsync(Player player, Channel channel, Object packet) { - if (packetPlayInUseEntityClazz.isInstance(packet)) { - NPC npc = NPCManager.getAllNPCs().stream().filter( - check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) - .findFirst().orElse(null); + if (packetPlayInUseEntityClazz.isInstance(packet)) { + NPC npc = NPCManager.getAllNPCs().stream().filter( + check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) + .findFirst().orElse(null); - if (npc == null) { - // Default player, not doing magic with the packet. - return super.onPacketInAsync(player, channel, packet); - } + if (npc == null) { + // Default player, not doing magic with the packet. + return super.onPacketInAsync(player, channel, packet); + } - if (delay.contains(player.getUniqueId())) { - return null; - } - - ClickType clickType = actionField.get(packet).toString() - .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; - - Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); - - UUID uuid = player.getUniqueId(); - delay.add(uuid); - Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); + if (delay.contains(player.getUniqueId())) { return null; } - return super.onPacketInAsync(player, channel, packet); + ClickType clickType = actionField.get(packet).toString() + .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; + + Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); + + UUID uuid = player.getUniqueId(); + delay.add(uuid); + Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); + return null; } - }; - } else { - new TinyProtocol(plugin) { - @Override - public Object onPacketInAsync(Player player, io.netty.channel.Channel channel, Object packet) { - - if (packetPlayInUseEntityClazz.isInstance(packet)) { - NPC npc = NPCManager.getAllNPCs().stream().filter( - check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) - .findFirst().orElse(null); - - if (npc == null) { - // Default player, not doing magic with the packet. - return super.onPacketInAsync(player, channel, packet); - } - - if (delay.contains(player.getUniqueId())) { - return null; - } - - ClickType clickType = actionField.get(packet).toString() - .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; - - Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); - - UUID uuid = player.getUniqueId(); - delay.add(uuid); - Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); - return null; - } - - return super.onPacketInAsync(player, channel, packet); - } - }; - } + return super.onPacketInAsync(player, channel, packet); + } + }; } } diff --git a/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java b/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java index 93d6e03..f6ae8cd 100755 --- a/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java +++ b/commons/src/main/java/net/jitse/npclib/nms/holograms/Hologram.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.holograms; +import com.comphenix.tinyprotocol.Reflection; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; -import tinyprotocol.Reflection; import java.util.ArrayList; import java.util.HashSet; diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java index 116c5da..b352b2d 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_10_R1; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_10_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_10_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_10_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +101,4 @@ public class NPC_v1_10_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 013edcd..86a6457 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_10_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_10_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index f93494d..3a81184 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_10_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_10_R1.DataWatcher; import net.minecraft.server.v1_10_R1.DataWatcherObject; import net.minecraft.server.v1_10_R1.DataWatcherRegistry; import net.minecraft.server.v1_10_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 8eb3f76..d07e54a 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_10_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_10_R1.EnumGamemode; import net.minecraft.server.v1_10_R1.IChatBaseComponent; import net.minecraft.server.v1_10_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 862f917..d8a643a 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_10_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_10_R1.PacketPlayOutScoreboardTeam; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java index 604bd18..9cab2e7 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_11_R1; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_11_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_11_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_11_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +101,4 @@ public class NPC_v1_11_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index afb2b71..6de5178 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_11_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_11_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 6f8bc62..d6e1cff 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_11_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_11_R1.DataWatcher; import net.minecraft.server.v1_11_R1.DataWatcherObject; import net.minecraft.server.v1_11_R1.DataWatcherRegistry; import net.minecraft.server.v1_11_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 50cffa0..52413e5 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_11_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_11_R1.EnumGamemode; import net.minecraft.server.v1_11_R1.IChatBaseComponent; import net.minecraft.server.v1_11_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 189cd28..957b4e5 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_11_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_11_R1.PacketPlayOutScoreboardTeam; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java index a68aad6..348bd9d 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_12_R1; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_12_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_12_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_12_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +101,4 @@ public class NPC_v1_12_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 5150f55..2abba78 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_12_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_12_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 4b523c0..323abde 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_12_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_12_R1.DataWatcher; import net.minecraft.server.v1_12_R1.DataWatcherObject; import net.minecraft.server.v1_12_R1.DataWatcherRegistry; import net.minecraft.server.v1_12_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 5934af8..f13a0a4 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_12_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_12_R1.EnumGamemode; import net.minecraft.server.v1_12_R1.IChatBaseComponent; import net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index c1a72fd..70a7b06 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_12_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_12_R1.PacketPlayOutScoreboardTeam; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java index 3f19b4e..b64b767 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_13_R1; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_13_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -15,12 +13,12 @@ import net.jitse.npclib.nms.v1_13_R1.packets.PacketPlayOutScoreboardTeamWrapper; import net.jitse.npclib.skin.Skin; import net.minecraft.server.v1_13_R1.*; import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +31,6 @@ public class NPC_v1_13_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_13_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +102,4 @@ public class NPC_v1_13_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 54343a4..b9b91f7 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_13_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index e27bcb1..151619d 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R1.DataWatcher; import net.minecraft.server.v1_13_R1.DataWatcherObject; import net.minecraft.server.v1_13_R1.DataWatcherRegistry; import net.minecraft.server.v1_13_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 298a164..578efb0 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_13_R1.EnumGamemode; import net.minecraft.server.v1_13_R1.IChatBaseComponent; import net.minecraft.server.v1_13_R1.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index f6b4760..71b3bb0 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_13_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R1.ChatComponentText; import net.minecraft.server.v1_13_R1.IChatBaseComponent; import net.minecraft.server.v1_13_R1.PacketPlayOutScoreboardTeam; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/.NPC_v1_13_R2.java.swp b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/.NPC_v1_13_R2.java.swp deleted file mode 100644 index 4de2afeb7e79fb5da4cf0840c6c6a33ea6383d9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeHNU2Gl26`qDbp%g-a2P#@Lagf*>IeYCuD3Ag%u^~zGWBDf}6_PdH9pAh5-ksI# ztbL8+An^b^@Id}a#w#q1km$`?#2~P#9ynTH7;L%{Q9rcp- z>iEL=y$dsY+llnrJr+dmWt3<~T(y^VjqND*!lo?BFBAn`E#EZ4-dhH)S_W<+_wF6f zLVefBPI}v|^H(hsw&9im%YbFTGGH073|Iy%1D1iSkpUHNBhR7X+w#WG=D$B^{9cpa z@5+DY8t?O4`(qif3|Iy%1C{~HfMvikU>UFsSOzQumI2Ga{~-g+C*&uvYfUfsvHxGJ z|G(Wq$UlL<0iOf!0q+7Y0`tIqz;@vMn+bUe*a7_cCPLl<65up&7x3+mQ6BgV_!ICu z;2q#?;3eRB;52Xwco4XFBO$*9ehz$!GYBsOU7!PO13tNdkdJ|nfDeGzfhT~U0(Ssk zTu(>@^ngj=>mQ;{;2q%Cz=i7wIS;%5+z;#n{&g)OuK}+DQ@|g$6Y>Y(954dx1inB5 z6(%%2g8Y0=hxa>-hbvmW=2s@a&Gxhx&pATAF_OJc(J zFUN>kPe{HfnDpm3>&@^^kSH#psox$`Mac?n(nKGoj&o45C1pfgxkStDaCL}9e#o7c z+bm@Wi_^t0@aU=te5%==?TRyo@x(FO3T5<}%%TG)R=Jdc&y9g+`(_sOyPo7s@%c#R zZPD#=B5>W>Pup!e*A1jkO?OfyvRd7~7S#cwQnEPa z(rJ}kqW)R#iKuA+4H7z1tJXALckB%BiB&%0mRi;uX}oBXCrXO7L6+479G>~_VK|It zyU5kwuTx}4&S&qJkMjV^F%+>{M+r=ql1-s!Y|nd=yFtab1@znJ&DbAGAppwTYfy2FL7> zF344G5+Z|4D=F=pRnCoBn=7FW1sxu7i2?hGGT!IdcT*!{Qn69h@3SWWRf3xGjZt2#24HZc8-HMZbP>J&S6Em74C`&Z{@<0aQ@_O8{y)IKf!_mjz;WOh@F?(KtoPpp-T+Pk zw*$8U-(byu5%>q7^8oh)=drH;E3gI#AON}m1-?SPUjiQjzXB$J1Hj$DU4XXhPQYH4 z0n318z%pPNunbrRECZH-|1|?9&0i+_C0D78>M4sXv7r-SrI@~}WSjJUMENiK=yZj;ivuo(I!Kv1n1)o8o?5$$%7^UYJvpM>8oPlSD7cJXWim;xu1r5^Tm~E zG{=&aqsVuasW_)a_dG(Xc4b>Lk#Dl3*p6XzF;FzrrD!6u-40_j^#xC&dlYt#c=lN5 zDXF7(M^u;LaU7yxl5O);b|f;FD9oz)L$R=R^UW3H3-zWR8rL^)%WO?&MaylY3PW4g zQOo01tuV?<=g7C_Di5yUPM}VanmkEkCvcQ53K4RK{AZO;-Itqg4sMx)bv(k`#wui9 Qva6MS+3)TwD_?f@cjDd$3jhEB diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java index 430b7e4..0efa24f 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_13_R2; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_13_R2.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_13_R2 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_13_R2(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +101,4 @@ public class NPC_v1_13_R2 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java index 153de2d..cbfc542 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_13_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R2.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 3428361..e0ab83b 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R2.DataWatcher; import net.minecraft.server.v1_13_R2.DataWatcherObject; import net.minecraft.server.v1_13_R2.DataWatcherRegistry; import net.minecraft.server.v1_13_R2.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java index 1062e71..79e1fbb 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_13_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_13_R2.EnumGamemode; import net.minecraft.server.v1_13_R2.IChatBaseComponent; import net.minecraft.server.v1_13_R2.PacketPlayOutPlayerInfo; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java index 559569b..9beae2c 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_13_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_13_R2.ChatComponentText; import net.minecraft.server.v1_13_R2.IChatBaseComponent; import net.minecraft.server.v1_13_R2.PacketPlayOutScoreboardTeam; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_7_R4/pom.xml b/nms/v1_7_R4/pom.xml index a8da360..5324123 100755 --- a/nms/v1_7_R4/pom.xml +++ b/nms/v1_7_R4/pom.xml @@ -25,5 +25,11 @@ 2.8.5 compile + + io.netty + netty-all + 4.0.23.Final + compile + diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java index eee28e8..a8af781 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_7_R4.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 094a6b6..95823a7 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_7_R4.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.DataWatcher; import net.minecraft.server.v1_7_R4.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java index de5002e..3673d16 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_7_R4.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.PacketPlayOutPlayerInfo; import net.minecraft.util.com.mojang.authlib.GameProfile; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java index 5be25bb..31002f1 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_7_R4.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java index c3f06c2..44987ec 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_8_R1; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_8_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_8_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_8_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -104,14 +100,4 @@ public class NPC_v1_8_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 2ad82c1..4d6eb40 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 51b544d..eac29db 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_8_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R1.DataWatcher; import net.minecraft.server.v1_8_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java index da25dbc..283b46e 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_8_R1.*; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 7d58571..e682a39 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R1.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java index a72645e..978f409 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_8_R2; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_8_R2.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_8_R2 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_8_R2(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -104,14 +100,4 @@ public class NPC_v1_8_R2 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java index 90e8460..5ac6220 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R2.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 6ae1f99..f48b8c8 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_8_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R2.DataWatcher; import net.minecraft.server.v1_8_R2.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java index 5391f9b..bca9688 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,11 +4,11 @@ package net.jitse.npclib.nms.v1_8_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_8_R2.IChatBaseComponent; import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_8_R2.WorldSettings; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java index 4a34e33..89a6e7a 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R2.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java index 39327b2..4a8af07 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_8_R3; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_8_R3.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_8_R3 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_8_R3(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +101,4 @@ public class NPC_v1_8_R3 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java index c402e3e..e50ebb9 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R3.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R3.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java index ba0d2d8..b23b72b 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,10 +4,10 @@ package net.jitse.npclib.nms.v1_8_R3.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R3.DataWatcher; import net.minecraft.server.v1_8_R3.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java index efa002f..3c411df 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,11 +4,11 @@ package net.jitse.npclib.nms.v1_8_R3.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_8_R3.IChatBaseComponent; import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_8_R3.WorldSettings; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java index eba0912..3b6b53c 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_8_R3.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_8_R3.PacketPlayOutScoreboardTeam; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java index 33b5a5f..dd89e26 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_9_R1; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_9_R1.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_9_R1 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_9_R1(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +101,4 @@ public class NPC_v1_9_R1 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java index 9533973..72b2a04 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_9_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R1.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java index af1ae34..d0a2504 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R1.DataWatcher; import net.minecraft.server.v1_9_R1.DataWatcherObject; import net.minecraft.server.v1_9_R1.DataWatcherRegistry; import net.minecraft.server.v1_9_R1.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 3db1b63..43695c7 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_9_R1.IChatBaseComponent; import net.minecraft.server.v1_9_R1.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_9_R1.WorldSettings; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java index 9bdac53..41e6873 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_9_R1.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R1.PacketPlayOutScoreboardTeam; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java index 7de3eea..d254033 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java @@ -4,8 +4,6 @@ package net.jitse.npclib.nms.v1_9_R2; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.api.NPC; import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_9_R2.packets.PacketPlayOutEntityHeadRotationWrapper; @@ -20,7 +18,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.List; -import java.util.UUID; /** * @author Jitse Boonstra @@ -33,7 +30,6 @@ public class NPC_v1_9_R2 extends NPC { private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; - private GameProfile gameProfile; public NPC_v1_9_R2(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); @@ -105,14 +101,4 @@ public class NPC_v1_9_R2 extends NPC { playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); } } - - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); - - if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } - - return gameProfile; - } } diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java index 455c7ce..6b2d008 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutEntityHeadRotationWrapper.java @@ -4,9 +4,9 @@ package net.jitse.npclib.nms.v1_9_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R2.PacketPlayOutEntityHeadRotation; import org.bukkit.Location; -import tinyprotocol.Reflection; /** * @author Jitse Boonstra diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 5c79f9d..39f5a3c 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R2.DataWatcher; import net.minecraft.server.v1_9_R2.DataWatcherObject; import net.minecraft.server.v1_9_R2.DataWatcherRegistry; import net.minecraft.server.v1_9_R2.PacketPlayOutNamedEntitySpawn; import org.bukkit.Location; -import tinyprotocol.Reflection; import java.util.UUID; diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java index c5e2863..67afd64 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -4,12 +4,12 @@ package net.jitse.npclib.nms.v1_9_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import net.minecraft.server.v1_9_R2.IChatBaseComponent; import net.minecraft.server.v1_9_R2.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_9_R2.WorldSettings; import org.bukkit.ChatColor; -import tinyprotocol.Reflection; import java.util.List; diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java index 6751de4..7856b63 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -4,8 +4,8 @@ package net.jitse.npclib.nms.v1_9_R2.packets; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_9_R2.PacketPlayOutScoreboardTeam; -import tinyprotocol.Reflection; import java.util.Collection; diff --git a/tinyprotocol-legacy/pom.xml b/tinyprotocol-legacy/pom.xml deleted file mode 100644 index f55b7c4..0000000 --- a/tinyprotocol-legacy/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - 4.0.0 - pom - - - net.jitse - npclib - 1.3 - - - npclib-tinyprotocol-legacy - - - - org.spigotmc - spigot - 1.7.10-R0.1-SNAPSHOT - provided - - - diff --git a/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java b/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java deleted file mode 100755 index eb52597..0000000 --- a/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/Reflection.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (c) 2018 Jitse Boonstra - */ - -package net.comphenix.tinyprotocol; - -import org.bukkit.Bukkit; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * An utility class that simplifies reflection in Bukkit plugins. - * - * @author Kristian - */ -public final class Reflection { - /** - * An interface for invoking a specific constructor. - */ - public interface ConstructorInvoker { - /** - * Invoke a constructor for a specific class. - * - * @param arguments - the arguments to pass to the constructor. - * @return The constructed object. - */ - Object invoke(Object... arguments); - } - - /** - * An interface for invoking a specific method. - */ - public interface MethodInvoker { - /** - * Invoke a method on a specific target object. - * - * @param target - the target object, or NULL for a static method. - * @param arguments - the arguments to pass to the method. - * @return The return value, or NULL if is void. - */ - Object invoke(Object target, Object... arguments); - } - - /** - * An interface for retrieving the field content. - * - * @param - field type. - */ - public interface FieldAccessor { - /** - * Retrieve the content of a field. - * - * @param target - the target object, or NULL for a static field. - * @return The value of the field. - */ - T get(Object target); - - /** - * Set the content of a field. - * - * @param target - the target object, or NULL for a static field. - * @param value - the new value of the field. - */ - void set(Object target, Object value); - - /** - * Determine if the given object has this field. - * - * @param target - the object to test. - * @return TRUE if it does, FALSE otherwise. - */ - boolean hasField(Object target); - } - - // Deduce the net.minecraft.server.v* package - private static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName(); - private static String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server"); - private static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", ""); - - // Variable replacement - private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^}]+)\\}"); - - private Reflection() { - // Seal class - } - - /** - * Retrieve a field accessor for a specific field type and name. - * - * @param target - the target type. - * @param name - the name of the field, or NULL to ignore. - * @param fieldType - a compatible field type. - * @return The field accessor. - */ - public static FieldAccessor getField(Class target, String name, Class fieldType) { - return getField(target, name, fieldType, 0); - } - - /** - * Retrieve a field accessor for a specific field type and name. - * - * @param className - lookup name of the class, see {@link #getClass(String)}. - * @param name - the name of the field, or NULL to ignore. - * @param fieldType - a compatible field type. - * @return The field accessor. - */ - public static FieldAccessor getField(String className, String name, Class fieldType) { - return getField(getClass(className), name, fieldType, 0); - } - - /** - * Retrieve a field accessor for a specific field type and name. - * - * @param target - the target type. - * @param fieldType - a compatible field type. - * @param index - the number of compatible fields to skip. - * @return The field accessor. - */ - public static FieldAccessor getField(Class target, Class fieldType, int index) { - return getField(target, null, fieldType, index); - } - - /** - * Retrieve a field accessor for a specific field type and name. - * - * @param className - lookup name of the class, see {@link #getClass(String)}. - * @param fieldType - a compatible field type. - * @param index - the number of compatible fields to skip. - * @return The field accessor. - */ - public static FieldAccessor getField(String className, Class fieldType, int index) { - return getField(getClass(className), fieldType, index); - } - - // Common method - private static FieldAccessor getField(Class target, String name, Class fieldType, int index) { - for (final Field field : target.getDeclaredFields()) { - if ((name == null || field.getName().equals(name)) && fieldType.isAssignableFrom(field.getType()) && index-- <= 0) { - field.setAccessible(true); - - // A function for retrieving a specific field value - return new FieldAccessor() { - - @Override - @SuppressWarnings("unchecked") - public T get(Object target) { - try { - return (T) field.get(target); - } catch (IllegalAccessException e) { - throw new RuntimeException("Cannot access reflection.", e); - } - } - - @Override - public void set(Object target, Object value) { - try { - field.set(target, value); - } catch (IllegalAccessException e) { - throw new RuntimeException("Cannot access reflection.", e); - } - } - - @Override - public boolean hasField(Object target) { - // target instanceof DeclaringClass - return field.getDeclaringClass().isAssignableFrom(target.getClass()); - } - }; - } - } - - // Search in parent classes - if (target.getSuperclass() != null) - return getField(target.getSuperclass(), name, fieldType, index); - - throw new IllegalArgumentException("Cannot find field with type " + fieldType); - } - - /** - * Search for the first publicly and privately defined method of the given name and parameter count. - * - * @param className - lookup name of the class, see {@link #getClass(String)}. - * @param methodName - the method name, or NULL to skip. - * @param params - the expected parameters. - * @return An object that invokes this specific method. - * @throws IllegalStateException If we cannot find this method. - */ - public static MethodInvoker getMethod(String className, String methodName, Class... params) { - return getTypedMethod(getClass(className), methodName, null, params); - } - - /** - * Search for the first publicly and privately defined method of the given name and parameter count. - * - * @param clazz - a class to start with. - * @param methodName - the method name, or NULL to skip. - * @param params - the expected parameters. - * @return An object that invokes this specific method. - * @throws IllegalStateException If we cannot find this method. - */ - public static MethodInvoker getMethod(Class clazz, String methodName, Class... params) { - return getTypedMethod(clazz, methodName, null, params); - } - - /** - * Search for the first publicly and privately defined method of the given name and parameter count. - * - * @param clazz - a class to start with. - * @param methodName - the method name, or NULL to skip. - * @param returnType - the expected return type, or NULL to ignore. - * @param params - the expected parameters. - * @return An object that invokes this specific method. - * @throws IllegalStateException If we cannot find this method. - */ - public static MethodInvoker getTypedMethod(Class clazz, String methodName, Class returnType, Class... params) { - for (final Method method : clazz.getDeclaredMethods()) { - if ((methodName == null || method.getName().equals(methodName)) - && (returnType == null || method.getReturnType().equals(returnType)) - && Arrays.equals(method.getParameterTypes(), params)) { - method.setAccessible(true); - - return (target, arguments) -> { - try { - return method.invoke(target, arguments); - } catch (Exception e) { - throw new RuntimeException("Cannot invoke method " + method, e); - } - }; - } - } - - // Search in every superclass - if (clazz.getSuperclass() != null) - return getMethod(clazz.getSuperclass(), methodName, params); - - throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params))); - } - - /** - * Search for the first publically and privately defined constructor of the given name and parameter count. - * - * @param className - lookup name of the class, see {@link #getClass(String)}. - * @param params - the expected parameters. - * @return An object that invokes this constructor. - * @throws IllegalStateException If we cannot find this method. - */ - public static ConstructorInvoker getConstructor(String className, Class... params) { - return getConstructor(getClass(className), params); - } - - /** - * Search for the first publicly and privately defined constructor of the given name and parameter count. - * - * @param clazz - a class to start with. - * @param params - the expected parameters. - * @return An object that invokes this constructor. - * @throws IllegalStateException If we cannot find this method. - */ - public static ConstructorInvoker getConstructor(Class clazz, Class... params) { - for (final Constructor constructor : clazz.getDeclaredConstructors()) { - if (Arrays.equals(constructor.getParameterTypes(), params)) { - constructor.setAccessible(true); - - return arguments -> { - try { - return constructor.newInstance(arguments); - } catch (Exception e) { - throw new RuntimeException("Cannot invoke constructor " + constructor, e); - } - }; - } - } - - throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params))); - } - - /** - * Retrieve a class from its full name, without knowing its type on compile time. - *

- * This is useful when looking up fields by a NMS or OBC type. - *

- * - * @param lookupName - the class name with variables. - * @return The class. - * @see {@link #getClass()} for more information. - */ - public static Class getUntypedClass(String lookupName) { - @SuppressWarnings({"rawtypes", "unchecked"}) - Class clazz = (Class) getClass(lookupName); - return clazz; - } - - /** - * Retrieve a class from its full name. - *

- * Strings enclosed with curly brackets - such as {TEXT} - will be replaced according to the following table: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
VariableContent
{nms}Actual package name of net.minecraft.server.VERSION
{obc}Actual pacakge name of org.bukkit.craftbukkit.VERSION
{version}The current Minecraft package VERSION, if any.
- * - * @param lookupName - the class name with variables. - * @return The looked up class. - * @throws IllegalArgumentException If a variable or class could not be found. - */ - public static Class getClass(String lookupName) { - return getCanonicalClass(expandVariables(lookupName)); - } - - /** - * Retrieve a class in the net.minecraft.server.VERSION.* package. - * - * @param name - the name of the class, excluding the package. - * @throws IllegalArgumentException If the class doesn't exist. - */ - public static Class getMinecraftClass(String name) { - return getCanonicalClass(NMS_PREFIX + "." + name); - } - - /** - * Retrieve a class in the org.bukkit.craftbukkit.VERSION.* package. - * - * @param name - the name of the class, excluding the package. - * @throws IllegalArgumentException If the class doesn't exist. - */ - public static Class getCraftBukkitClass(String name) { - return getCanonicalClass(OBC_PREFIX + "." + name); - } - - /** - * Retrieve a class by its canonical name. - * - * @param canonicalName - the canonical name. - * @return The class. - */ - private static Class getCanonicalClass(String canonicalName) { - try { - return Class.forName(canonicalName); - } catch (ClassNotFoundException e) { - throw new IllegalArgumentException("Cannot find " + canonicalName, e); - } - } - - /** - * Expand variables such as "{nms}" and "{obc}" to their corresponding packages. - * - * @param name - the full name of the class. - * @return The expanded string. - */ - private static String expandVariables(String name) { - StringBuffer output = new StringBuffer(); - Matcher matcher = MATCH_VARIABLE.matcher(name); - - while (matcher.find()) { - String variable = matcher.group(1); - String replacement; - - // Expand all detected variables - if ("nms".equalsIgnoreCase(variable)) - replacement = NMS_PREFIX; - else if ("obc".equalsIgnoreCase(variable)) - replacement = OBC_PREFIX; - else if ("version".equalsIgnoreCase(variable)) - replacement = VERSION; - else - throw new IllegalArgumentException("Unknown variable: " + variable); - - // Assume the expanded variables are all packages, and append a dot - if (replacement.length() > 0 && matcher.end() < name.length() && name.charAt(matcher.end()) != '.') - replacement += "."; - matcher.appendReplacement(output, Matcher.quoteReplacement(replacement)); - } - - matcher.appendTail(output); - return output.toString(); - } -} \ No newline at end of file diff --git a/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java b/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java deleted file mode 100755 index 9fc2a39..0000000 --- a/tinyprotocol-legacy/src/main/java/net/comphenix/tinyprotocol/TinyProtocol.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (c) 2018 Jitse Boonstra - */ - -package net.comphenix.tinyprotocol; - -import com.google.common.collect.Lists; -import com.google.common.collect.MapMaker; -import com.mojang.authlib.GameProfile; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.server.PluginDisableEvent; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; - -/** - * Represents a very tiny alternative to ProtocolLib. - *

- * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! - * - * @author Kristian - */ -public abstract class TinyProtocol { - private static final AtomicInteger ID = new AtomicInteger(0); - - // Used in order to lookup a channel - private static final Reflection.MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); - private static final Reflection.FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class); - private static final Reflection.FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class); - private static final Reflection.FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0); - - // Looking up ServerConnection - private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer"); - private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection"); - private static final Reflection.FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); - private static final Reflection.FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); - private static final Reflection.MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); - - // Packets we have to intercept - private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); - private static final Reflection.FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); - - // Speedup channel lookup - private Map channelLookup = new MapMaker().weakValues().makeMap(); - private Listener listener; - - // Channels that have already been removed - private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); - - // List of network markers - private List networkManagers; - - // Injected channel handlers - private List serverChannels = Lists.newArrayList(); - private ChannelInboundHandlerAdapter serverChannelHandler; - private ChannelInitializer beginInitProtocol; - private ChannelInitializer endInitProtocol; - - // Current handler name - private String handlerName; - - protected volatile boolean closed; - protected Plugin plugin; - - /** - * Construct a new instance of com.comphenix.tinyprotocol.TinyProtocol, and start intercepting packets for all connected clients and future clients. - *

- * You can construct multiple instances per plugin. - * - * @param plugin - the plugin. - */ - public TinyProtocol(final Plugin plugin) { - this.plugin = plugin; - - // Compute handler name - this.handlerName = getHandlerName(); - - // Prepare existing players - registerBukkitEvents(); - - try { - registerChannelHandler(); - registerPlayers(plugin); - } catch (IllegalArgumentException ex) { - // Damn you, late bind - plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Delaying server channel injection due to late bind."); - - new BukkitRunnable() { - @Override - public void run() { - registerChannelHandler(); - registerPlayers(plugin); - plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Late bind injection successful."); - } - }.runTask(plugin); - } - } - - private void createServerChannelHandler() { - // Handle connected channels - endInitProtocol = new ChannelInitializer() { - - @Override - protected void initChannel(Channel channel) throws Exception { - try { - // This can take a while, so we need to stop the main thread from interfering - synchronized (networkManagers) { - // Stop injecting channels - if (!closed) { - channel.eventLoop().submit(() -> injectChannelInternal(channel)); - } - } - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); - } - } - - }; - - // This is executed before Minecraft's channel handler - beginInitProtocol = new ChannelInitializer() { - - @Override - protected void initChannel(Channel channel) throws Exception { - channel.pipeline().addLast(endInitProtocol); - } - - }; - - serverChannelHandler = new ChannelInboundHandlerAdapter() { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - Channel channel = (Channel) msg; - - // Prepare to initialize ths channel - channel.pipeline().addFirst(beginInitProtocol); - ctx.fireChannelRead(msg); - } - - }; - } - - /** - * Register bukkit events. - */ - private void registerBukkitEvents() { - listener = new Listener() { - - @EventHandler(priority = EventPriority.LOWEST) - public final void onPlayerLogin(PlayerLoginEvent e) { - if (closed) - return; - - Channel channel = getChannel(e.getPlayer()); - - // Don't inject players that have been explicitly uninjected - if (!uninjectedChannels.contains(channel)) { - injectPlayer(e.getPlayer()); - } - } - - @EventHandler - public final void onPluginDisable(PluginDisableEvent e) { - if (e.getPlugin().equals(plugin)) { - close(); - } - } - - }; - - plugin.getServer().getPluginManager().registerEvents(listener, plugin); - } - - @SuppressWarnings("unchecked") - private void registerChannelHandler() { - Object mcServer = getMinecraftServer.get(Bukkit.getServer()); - Object serverConnection = getServerConnection.get(mcServer); - boolean looking = true; - - // We need to synchronize against this list - networkManagers = (List) getNetworkMarkers.invoke(null, serverConnection); - createServerChannelHandler(); - - // Find the correct list, or implicitly throw an exception - for (int i = 0; looking; i++) { - List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); - - for (Object item : list) { - if (!ChannelFuture.class.isInstance(item)) - break; - - // Channel future that contains the server connection - Channel serverChannel = ((ChannelFuture) item).channel(); - - serverChannels.add(serverChannel); - serverChannel.pipeline().addFirst(serverChannelHandler); - looking = false; - } - } - } - - private void unregisterChannelHandler() { - if (serverChannelHandler == null) - return; - - for (Channel serverChannel : serverChannels) { - final ChannelPipeline pipeline = serverChannel.pipeline(); - - // Remove channel handler - serverChannel.eventLoop().execute(new Runnable() { - - @Override - public void run() { - try { - pipeline.remove(serverChannelHandler); - } catch (NoSuchElementException e) { - // That's fine - } - } - - }); - } - } - - private void registerPlayers(Plugin plugin) { - for (Player player : plugin.getServer().getOnlinePlayers()) { - injectPlayer(player); - } - } - - /** - * Invoked when the server is starting to send a packet to a player. - *

- * Note that this is not executed on the main thread. - * - * @param receiver - the receiving player, NULL for early login/status packets. - * @param channel - the channel that received the packet. Never NULL. - * @param packet - the packet being sent. - * @return The packet to send instead, or NULL to cancel the transmission. - */ - public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { - return packet; - } - - /** - * Invoked when the server has received a packet from a given player. - *

- * Use {@link Channel#remoteAddress()} to get the remote address of the client. - * - * @param sender - the player that sent the packet, NULL for early login/status packets. - * @param channel - channel that received the packet. Never NULL. - * @param packet - the packet being received. - * @return The packet to recieve instead, or NULL to cancel. - */ - public Object onPacketInAsync(Player sender, Channel channel, Object packet) { - return packet; - } - - /** - * Send a packet to a particular player. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the destination player. - * @param packet - the packet to send. - */ - public void sendPacket(Player player, Object packet) { - sendPacket(getChannel(player), packet); - } - - /** - * Send a packet to a particular client. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet to send. - */ - public void sendPacket(Channel channel, Object packet) { - channel.pipeline().writeAndFlush(packet); - } - - /** - * Pretend that a given packet has been received from a player. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the player that sent the packet. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Player player, Object packet) { - receivePacket(getChannel(player), packet); - } - - /** - * Pretend that a given packet has been received from a given client. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Channel channel, Object packet) { - channel.pipeline().context("encoder").fireChannelRead(packet); - } - - /** - * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. - *

- * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. - * - * @return A unique channel handler name. - */ - protected String getHandlerName() { - return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); - } - - /** - * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. - *

- * This will automatically be called when a player has logged in. - * - * @param player - the player to inject. - */ - public void injectPlayer(Player player) { - injectChannelInternal(getChannel(player)).player = player; - } - - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - */ - public void injectChannel(Channel channel) { - injectChannelInternal(channel); - } - - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The packet interceptor. - */ - private PacketInterceptor injectChannelInternal(Channel channel) { - try { - PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); - - // Inject our packet interceptor - if (interceptor == null) { - interceptor = new PacketInterceptor(); - channel.pipeline().addBefore("packet_handler", handlerName, interceptor); - uninjectedChannels.remove(channel); - } - - return interceptor; - } catch (IllegalArgumentException e) { - // Try again - return (PacketInterceptor) channel.pipeline().get(handlerName); - } - } - - /** - * Retrieve the Netty channel associated with a player. This is cached. - * - * @param player - the player. - * @return The Netty channel. - */ - public Channel getChannel(Player player) { - Channel channel = channelLookup.get(player.getName()); - - // Lookup channel again - if (channel == null) { - Object connection = getConnection.get(getPlayerHandle.invoke(player)); - Object manager = getManager.get(connection); - - channelLookup.put(player.getName(), channel = getChannel.get(manager)); - } - - return channel; - } - - /** - * Uninject a specific player. - * - * @param player - the injected player. - */ - public void uninjectPlayer(Player player) { - uninjectChannel(getChannel(player)); - } - - /** - * Uninject a specific channel. - *

- * This will also disable the automatic channel injection that occurs when a player has properly logged in. - * - * @param channel - the injected channel. - */ - public void uninjectChannel(final Channel channel) { - // No need to guard against this if we're closing - if (!closed) { - uninjectedChannels.add(channel); - } - - // See ChannelInjector in ProtocolLib, line 590 - channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); - } - - /** - * Determine if the given player has been injected by com.comphenix.tinyprotocol.TinyProtocol. - * - * @param player - the player. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Player player) { - return hasInjected(getChannel(player)); - } - - /** - * Determine if the given channel has been injected by com.comphenix.tinyprotocol.TinyProtocol. - * - * @param channel - the channel. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Channel channel) { - return channel.pipeline().get(handlerName) != null; - } - - /** - * Cease listening for packets. This is called automatically when your plugin is disabled. - */ - public final void close() { - if (!closed) { - closed = true; - - // Remove our handlers - for (Player player : plugin.getServer().getOnlinePlayers()) { - uninjectPlayer(player); - } - - // Clean up Bukkit - HandlerList.unregisterAll(listener); - unregisterChannelHandler(); - } - } - - /** - * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. - * - * @author Kristian - */ - private final class PacketInterceptor extends ChannelDuplexHandler { - // Updated by the login event - public volatile Player player; - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // Intercept channel - final Channel channel = ctx.channel(); - handleLoginStart(channel, msg); - - try { - msg = onPacketInAsync(player, channel, msg); - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); - } - - if (msg != null) { - super.channelRead(ctx, msg); - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - try { - msg = onPacketOutAsync(player, ctx.channel(), msg); - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); - } - - if (msg != null) { - super.write(ctx, msg, promise); - } - } - - private void handleLoginStart(Channel channel, Object packet) { - if (PACKET_LOGIN_IN_START.isInstance(packet)) { - GameProfile profile = getGameProfile.get(packet); - channelLookup.put(profile.getName(), channel); - } - } - } -} \ No newline at end of file diff --git a/tinyprotocol/pom.xml b/tinyprotocol/pom.xml deleted file mode 100644 index 7a3e612..0000000 --- a/tinyprotocol/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - 4.0.0 - pom - - - net.jitse - npclib - 1.3 - - - npclib-tinyprotocol - - - - org.spigotmc - spigot - 1.13.2-R0.1-SNAPSHOT - provided - - - diff --git a/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java b/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java deleted file mode 100755 index a9b6e59..0000000 --- a/tinyprotocol/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java +++ /dev/null @@ -1,499 +0,0 @@ -package com.comphenix.tinyprotocol; - -import com.google.common.collect.Lists; -import com.google.common.collect.MapMaker; -import com.mojang.authlib.GameProfile; -import io.netty.channel.*; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.server.PluginDisableEvent; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; - -/** - * Represents a very tiny alternative to ProtocolLib. - *

- * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! - * - * @author Kristian - */ -public abstract class TinyProtocol { - private static final AtomicInteger ID = new AtomicInteger(0); - - // Used in order to lookup a channel - private static final Reflection.MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); - private static final Reflection.FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class); - private static final Reflection.FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class); - private static final Reflection.FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0); - - // Looking up ServerConnection - private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer"); - private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection"); - private static final Reflection.FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); - private static final Reflection.FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); - private static final Reflection.MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); - - // Packets we have to intercept - private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); - private static final Reflection.FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); - - // Speedup channel lookup - private Map channelLookup = new MapMaker().weakValues().makeMap(); - private Listener listener; - - // Channels that have already been removed - private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); - - // List of network markers - private List networkManagers; - - // Injected channel handlers - private List serverChannels = Lists.newArrayList(); - private ChannelInboundHandlerAdapter serverChannelHandler; - private ChannelInitializer beginInitProtocol; - private ChannelInitializer endInitProtocol; - - // Current handler name - private String handlerName; - - protected volatile boolean closed; - protected Plugin plugin; - - /** - * Construct a new instance of com.comphenix.tinyprotocol.TinyProtocol, and start intercepting packets for all connected clients and future clients. - *

- * You can construct multiple instances per plugin. - * - * @param plugin - the plugin. - */ - public TinyProtocol(final Plugin plugin) { - this.plugin = plugin; - - // Compute handler name - this.handlerName = getHandlerName(); - - // Prepare existing players - registerBukkitEvents(); - - try { - registerChannelHandler(); - registerPlayers(plugin); - } catch (IllegalArgumentException ex) { - // Damn you, late bind - plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Delaying server channel injection due to late bind."); - - new BukkitRunnable() { - @Override - public void run() { - registerChannelHandler(); - registerPlayers(plugin); - plugin.getLogger().info("[com.comphenix.tinyprotocol.TinyProtocol] Late bind injection successful."); - } - }.runTask(plugin); - } - } - - private void createServerChannelHandler() { - // Handle connected channels - endInitProtocol = new ChannelInitializer() { - - @Override - protected void initChannel(Channel channel) throws Exception { - try { - // This can take a while, so we need to stop the main thread from interfering - synchronized (networkManagers) { - // Stop injecting channels - if (!closed) { - channel.eventLoop().submit(() -> injectChannelInternal(channel)); - } - } - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); - } - } - - }; - - // This is executed before Minecraft's channel handler - beginInitProtocol = new ChannelInitializer() { - - @Override - protected void initChannel(Channel channel) throws Exception { - channel.pipeline().addLast(endInitProtocol); - } - - }; - - serverChannelHandler = new ChannelInboundHandlerAdapter() { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - Channel channel = (Channel) msg; - - // Prepare to initialize ths channel - channel.pipeline().addFirst(beginInitProtocol); - ctx.fireChannelRead(msg); - } - - }; - } - - /** - * Register bukkit events. - */ - private void registerBukkitEvents() { - listener = new Listener() { - - @EventHandler(priority = EventPriority.LOWEST) - public final void onPlayerLogin(PlayerLoginEvent e) { - if (closed) - return; - - Channel channel = getChannel(e.getPlayer()); - - // Don't inject players that have been explicitly uninjected - if (!uninjectedChannels.contains(channel)) { - injectPlayer(e.getPlayer()); - } - } - - @EventHandler - public final void onPluginDisable(PluginDisableEvent e) { - if (e.getPlugin().equals(plugin)) { - close(); - } - } - - }; - - plugin.getServer().getPluginManager().registerEvents(listener, plugin); - } - - @SuppressWarnings("unchecked") - private void registerChannelHandler() { - Object mcServer = getMinecraftServer.get(Bukkit.getServer()); - Object serverConnection = getServerConnection.get(mcServer); - boolean looking = true; - - // We need to synchronize against this list - networkManagers = (List) getNetworkMarkers.invoke(null, serverConnection); - createServerChannelHandler(); - - // Find the correct list, or implicitly throw an exception - for (int i = 0; looking; i++) { - List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); - - for (Object item : list) { - if (!ChannelFuture.class.isInstance(item)) - break; - - // Channel future that contains the server connection - Channel serverChannel = ((ChannelFuture) item).channel(); - - serverChannels.add(serverChannel); - serverChannel.pipeline().addFirst(serverChannelHandler); - looking = false; - } - } - } - - private void unregisterChannelHandler() { - if (serverChannelHandler == null) - return; - - for (Channel serverChannel : serverChannels) { - final ChannelPipeline pipeline = serverChannel.pipeline(); - - // Remove channel handler - serverChannel.eventLoop().execute(new Runnable() { - - @Override - public void run() { - try { - pipeline.remove(serverChannelHandler); - } catch (NoSuchElementException e) { - // That's fine - } - } - - }); - } - } - - private void registerPlayers(Plugin plugin) { - for (Player player : plugin.getServer().getOnlinePlayers()) { - injectPlayer(player); - } - } - - /** - * Invoked when the server is starting to send a packet to a player. - *

- * Note that this is not executed on the main thread. - * - * @param receiver - the receiving player, NULL for early login/status packets. - * @param channel - the channel that received the packet. Never NULL. - * @param packet - the packet being sent. - * @return The packet to send instead, or NULL to cancel the transmission. - */ - public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { - return packet; - } - - /** - * Invoked when the server has received a packet from a given player. - *

- * Use {@link Channel#remoteAddress()} to get the remote address of the client. - * - * @param sender - the player that sent the packet, NULL for early login/status packets. - * @param channel - channel that received the packet. Never NULL. - * @param packet - the packet being received. - * @return The packet to recieve instead, or NULL to cancel. - */ - public Object onPacketInAsync(Player sender, Channel channel, Object packet) { - return packet; - } - - /** - * Send a packet to a particular player. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the destination player. - * @param packet - the packet to send. - */ - public void sendPacket(Player player, Object packet) { - sendPacket(getChannel(player), packet); - } - - /** - * Send a packet to a particular client. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet to send. - */ - public void sendPacket(Channel channel, Object packet) { - channel.pipeline().writeAndFlush(packet); - } - - /** - * Pretend that a given packet has been received from a player. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the player that sent the packet. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Player player, Object packet) { - receivePacket(getChannel(player), packet); - } - - /** - * Pretend that a given packet has been received from a given client. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Channel channel, Object packet) { - channel.pipeline().context("encoder").fireChannelRead(packet); - } - - /** - * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. - *

- * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. - * - * @return A unique channel handler name. - */ - protected String getHandlerName() { - return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); - } - - /** - * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. - *

- * This will automatically be called when a player has logged in. - * - * @param player - the player to inject. - */ - public void injectPlayer(Player player) { - injectChannelInternal(getChannel(player)).player = player; - } - - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - */ - public void injectChannel(Channel channel) { - injectChannelInternal(channel); - } - - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The packet interceptor. - */ - private PacketInterceptor injectChannelInternal(Channel channel) { - try { - PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); - - // Inject our packet interceptor - if (interceptor == null) { - interceptor = new PacketInterceptor(); - channel.pipeline().addBefore("packet_handler", handlerName, interceptor); - uninjectedChannels.remove(channel); - } - - return interceptor; - } catch (IllegalArgumentException e) { - // Try again - return (PacketInterceptor) channel.pipeline().get(handlerName); - } - } - - /** - * Retrieve the Netty channel associated with a player. This is cached. - * - * @param player - the player. - * @return The Netty channel. - */ - public Channel getChannel(Player player) { - Channel channel = channelLookup.get(player.getName()); - - // Lookup channel again - if (channel == null) { - Object connection = getConnection.get(getPlayerHandle.invoke(player)); - Object manager = getManager.get(connection); - - channelLookup.put(player.getName(), channel = getChannel.get(manager)); - } - - return channel; - } - - /** - * Uninject a specific player. - * - * @param player - the injected player. - */ - public void uninjectPlayer(Player player) { - uninjectChannel(getChannel(player)); - } - - /** - * Uninject a specific channel. - *

- * This will also disable the automatic channel injection that occurs when a player has properly logged in. - * - * @param channel - the injected channel. - */ - public void uninjectChannel(final Channel channel) { - // No need to guard against this if we're closing - if (!closed) { - uninjectedChannels.add(channel); - } - - // See ChannelInjector in ProtocolLib, line 590 - channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); - } - - /** - * Determine if the given player has been injected by com.comphenix.tinyprotocol.TinyProtocol. - * - * @param player - the player. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Player player) { - return hasInjected(getChannel(player)); - } - - /** - * Determine if the given channel has been injected by com.comphenix.tinyprotocol.TinyProtocol. - * - * @param channel - the channel. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Channel channel) { - return channel.pipeline().get(handlerName) != null; - } - - /** - * Cease listening for packets. This is called automatically when your plugin is disabled. - */ - public final void close() { - if (!closed) { - closed = true; - - // Remove our handlers - for (Player player : plugin.getServer().getOnlinePlayers()) { - uninjectPlayer(player); - } - - // Clean up Bukkit - HandlerList.unregisterAll(listener); - unregisterChannelHandler(); - } - } - - /** - * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. - * - * @author Kristian - */ - private final class PacketInterceptor extends ChannelDuplexHandler { - // Updated by the login event - public volatile Player player; - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - // Intercept channel - final Channel channel = ctx.channel(); - handleLoginStart(channel, msg); - - try { - msg = onPacketInAsync(player, channel, msg); - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); - } - - if (msg != null) { - super.channelRead(ctx, msg); - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - try { - msg = onPacketOutAsync(player, ctx.channel(), msg); - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); - } - - if (msg != null) { - super.write(ctx, msg, promise); - } - } - - private void handleLoginStart(Channel channel, Object packet) { - if (PACKET_LOGIN_IN_START.isInstance(packet)) { - GameProfile profile = getGameProfile.get(packet); - channelLookup.put(profile.getName(), channel); - } - } - } -} \ No newline at end of file From bff059abaed8e6f4cba8f66743625c28992bf21d Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Fri, 14 Dec 2018 15:28:28 +0100 Subject: [PATCH 4/9] Made NPCs spawn for 1.7.10 (1.7 R4) (#10). Disabled TinyProtocol to work on some other things first. --- .../main/java/net/jitse/npclib/api/NPC.java | 2 +- .../npclib/listeners/PacketListener.java | 74 +++++++++---------- .../jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java | 22 ++---- .../PacketPlayOutNamedEntitySpawnWrapper.java | 9 +-- .../PacketPlayOutScoreboardTeamWrapper.java | 34 +++++---- 5 files changed, 63 insertions(+), 78 deletions(-) diff --git a/commons/src/main/java/net/jitse/npclib/api/NPC.java b/commons/src/main/java/net/jitse/npclib/api/NPC.java index 7856759..af7d786 100755 --- a/commons/src/main/java/net/jitse/npclib/api/NPC.java +++ b/commons/src/main/java/net/jitse/npclib/api/NPC.java @@ -25,11 +25,11 @@ import java.util.*; public abstract class NPC implements PacketHandler, ActionHandler { protected final UUID uuid = UUID.randomUUID(); - protected final String name = uuid.toString().replace("-", "").substring(0, 10); // Below was previously = (int) Math.ceil(Math.random() * 100000) + 100000 (new is experimental). protected final int entityId = Integer.MAX_VALUE - NPCManager.getAllNPCs().size(); protected double cosFOV = Math.cos(Math.toRadians(60)); + protected String name = uuid.toString().replace("-", "").substring(0, 10); private final Set shown = new HashSet<>(); private final Set autoHidden = new HashSet<>(); diff --git a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java index cb07d28..e3e3857 100755 --- a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java +++ b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java @@ -5,14 +5,6 @@ package net.jitse.npclib.listeners; import com.comphenix.tinyprotocol.Reflection; -import com.comphenix.tinyprotocol.TinyProtocol; -import io.netty.channel.Channel; -import net.jitse.npclib.NPCManager; -import net.jitse.npclib.api.NPC; -import net.jitse.npclib.events.NPCInteractEvent; -import net.jitse.npclib.events.click.ClickType; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.HashSet; @@ -35,38 +27,38 @@ public class PacketListener { private final Set delay = new HashSet<>(); public void start(JavaPlugin plugin) { - new TinyProtocol(plugin) { - - @Override - public Object onPacketInAsync(Player player, Channel channel, Object packet) { - - if (packetPlayInUseEntityClazz.isInstance(packet)) { - NPC npc = NPCManager.getAllNPCs().stream().filter( - check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) - .findFirst().orElse(null); - - if (npc == null) { - // Default player, not doing magic with the packet. - return super.onPacketInAsync(player, channel, packet); - } - - if (delay.contains(player.getUniqueId())) { - return null; - } - - ClickType clickType = actionField.get(packet).toString() - .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; - - Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); - - UUID uuid = player.getUniqueId(); - delay.add(uuid); - Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); - return null; - } - - return super.onPacketInAsync(player, channel, packet); - } - }; +// new TinyProtocol(plugin) { +// +// @Override +// public Object onPacketInAsync(Player player, Channel channel, Object packet) { +// +// if (packetPlayInUseEntityClazz.isInstance(packet)) { +// NPC npc = NPCManager.getAllNPCs().stream().filter( +// check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) +// .findFirst().orElse(null); +// +// if (npc == null) { +// // Default player, not doing magic with the packet. +// return super.onPacketInAsync(player, channel, packet); +// } +// +// if (delay.contains(player.getUniqueId())) { +// return null; +// } +// +// ClickType clickType = actionField.get(packet).toString() +// .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; +// +// Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); +// +// UUID uuid = player.getUniqueId(); +// delay.add(uuid); +// Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); +// return null; +// } +// +// return super.onPacketInAsync(player, channel, packet); +// } +// }; } } diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java index 3ddfb17..1cfbdc1 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java @@ -5,7 +5,6 @@ package net.jitse.npclib.nms.v1_7_R4; import net.jitse.npclib.api.NPC; -import net.jitse.npclib.nms.holograms.Hologram; import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutEntityHeadRotationWrapper; import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutNamedEntitySpawnWrapper; import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutPlayerInfoWrapper; @@ -27,7 +26,6 @@ import java.util.UUID; */ public class NPC_v1_7_R4 extends NPC { - private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; @@ -38,31 +36,29 @@ public class NPC_v1_7_R4 extends NPC { public NPC_v1_7_R4(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); + this.name = lines.get(0); } @Override public void createPackets() { - this.hologram = new Hologram(location.clone().add(0, 0.5, 0), lines); - hologram.generatePackets(false, false); - - this.legacyGameProfile = generateLegacyGameProfile(uuid, name); + this.legacyGameProfile = generateLegacyGameProfile(uuid, name.length() < 16 ? name : name.substring(0, 15)); PacketPlayOutPlayerInfoWrapper packetPlayOutPlayerInfoWrapper = new PacketPlayOutPlayerInfoWrapper(); // Packets for spawning the NPC: this.packetPlayOutScoreboardTeamRegister = new PacketPlayOutScoreboardTeamWrapper() - .createRegisterTeam(name); // First packet to send. + .createRegisterTeam(legacyGameProfile.getId().toString().replace("-", "").substring(0, 10), name); // First packet to send. this.packetPlayOutPlayerInfoAdd = packetPlayOutPlayerInfoWrapper - .create(0, legacyGameProfile, name); // Second packet to send. + .create(0, legacyGameProfile, name.length() < 16 ? name : name.length() < 16 ? name : name.substring(0, 15)); // Second packet to send. this.packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawnWrapper() - .create(uuid, location, entityId); // Third packet to send. + .create(legacyGameProfile, location, entityId); // Third packet to send. this.packetPlayOutEntityHeadRotation = new PacketPlayOutEntityHeadRotationWrapper() .create(location, entityId); // Fourth packet to send. this.packetPlayOutPlayerInfoRemove = packetPlayOutPlayerInfoWrapper - .create(4, legacyGameProfile, name); // Fifth packet to send (delayed). + .create(4, legacyGameProfile, name.length() < 16 ? name : name.substring(0, 15)); // Fifth packet to send (delayed). // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. @@ -70,7 +66,7 @@ public class NPC_v1_7_R4 extends NPC { // Second packet to send is "packetPlayOutPlayerInfoRemove". this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + .createUnregisterTeam(legacyGameProfile.getId().toString().replace("-", "").substring(0, 10)); // Third packet to send. } @Override @@ -82,8 +78,6 @@ public class NPC_v1_7_R4 extends NPC { playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); - hologram.spawn(player); - Bukkit.getScheduler().runTaskLater(plugin, () -> playerConnection.sendPacket(packetPlayOutPlayerInfoRemove), 50); } @@ -95,8 +89,6 @@ public class NPC_v1_7_R4 extends NPC { playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - if (scheduler) { // Sending this a bit later so the player doesn't see the name (for that split second). Bukkit.getScheduler().runTaskLater(plugin, () -> diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java index 95823a7..61b47a5 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java @@ -7,22 +7,21 @@ package net.jitse.npclib.nms.v1_7_R4.packets; import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.DataWatcher; import net.minecraft.server.v1_7_R4.PacketPlayOutNamedEntitySpawn; +import net.minecraft.util.com.mojang.authlib.GameProfile; import org.bukkit.Location; -import java.util.UUID; - /** * @author Jitse Boonstra */ public class PacketPlayOutNamedEntitySpawnWrapper { - public PacketPlayOutNamedEntitySpawn create(UUID uuid, Location location, int entityId) { + public PacketPlayOutNamedEntitySpawn create(GameProfile gameProfile, Location location, int entityId) { PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawn(); Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "a", int.class) .set(packetPlayOutNamedEntitySpawn, entityId); - Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "b", UUID.class) - .set(packetPlayOutNamedEntitySpawn, uuid); + Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "b", GameProfile.class) + .set(packetPlayOutNamedEntitySpawn, gameProfile); Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "c", int.class) .set(packetPlayOutNamedEntitySpawn, (int) Math.floor(location.getX() * 32.0D)); Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "d", int.class) diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java index 31002f1..2547cdc 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java @@ -6,7 +6,6 @@ package net.jitse.npclib.nms.v1_7_R4.packets; import com.comphenix.tinyprotocol.Reflection; import net.minecraft.server.v1_7_R4.PacketPlayOutScoreboardTeam; -import org.bukkit.ChatColor; import java.util.Collection; @@ -15,38 +14,41 @@ import java.util.Collection; */ public class PacketPlayOutScoreboardTeamWrapper { - public PacketPlayOutScoreboardTeam createRegisterTeam(String name) { + public PacketPlayOutScoreboardTeam createRegisterTeam(String uuidName, String name) { PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeam = new PacketPlayOutScoreboardTeam(); - Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "h", int.class) + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "f", int.class) .set(packetPlayOutScoreboardTeam, 0); Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "b", String.class) - .set(packetPlayOutScoreboardTeam, name); + .set(packetPlayOutScoreboardTeam, name.length() < 16 ? name : name.substring(0, 15)); Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "a", String.class) - .set(packetPlayOutScoreboardTeam, name); - Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "e", String.class) - .set(packetPlayOutScoreboardTeam, "never"); - Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "i", int.class) + .set(packetPlayOutScoreboardTeam, uuidName); + if (name.length() > 16) { + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "d", String.class) + .set(packetPlayOutScoreboardTeam, name.substring(15)); + } + if (name.length() > 32) { + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "c", String.class) + .set(packetPlayOutScoreboardTeam, name.substring(31)); + } + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "g", int.class) .set(packetPlayOutScoreboardTeam, 1); - // Could not get this working in the PacketPlayOutPlayerInfoWrapper class. - Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "c", String.class) - .set(packetPlayOutScoreboardTeam, ChatColor.BLUE + "[NPC] "); Reflection.FieldAccessor collectionFieldAccessor = Reflection.getField( - packetPlayOutScoreboardTeam.getClass(), "g", Collection.class); + packetPlayOutScoreboardTeam.getClass(), "e", Collection.class); Collection collection = collectionFieldAccessor.get(packetPlayOutScoreboardTeam); - collection.add(name); + collection.add(name.length() < 16 ? name : name.substring(0, 15)); collectionFieldAccessor.set(packetPlayOutScoreboardTeam, collection); return packetPlayOutScoreboardTeam; } - public PacketPlayOutScoreboardTeam createUnregisterTeam(String name) { + public PacketPlayOutScoreboardTeam createUnregisterTeam(String uuidName) { PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeam = new PacketPlayOutScoreboardTeam(); - Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "h", int.class) + Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "f", int.class) .set(packetPlayOutScoreboardTeam, 1); Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "a", String.class) - .set(packetPlayOutScoreboardTeam, name); + .set(packetPlayOutScoreboardTeam, uuidName); return packetPlayOutScoreboardTeam; } From ab5f07b976670017adcb75682a8b33c20d4a61a6 Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Wed, 2 Jan 2019 11:48:23 +0100 Subject: [PATCH 5/9] Updated README. --- README.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1098f86..99feee9 100755 --- a/README.md +++ b/README.md @@ -4,15 +4,13 @@ NPCLib – Basic non-player character library.
[![Build Status](https://travis-ci.com/JitseB/NPCLib.svg?branch=master)](https://travis-ci.com/JitseB/NPCLib) [![JDK](https://img.shields.io/badge/Using-Java%208-blue.svg)](http://jdk.java.net/8/) [![Versions](https://img.shields.io/badge/MC-1.8%20--%201.13.2-blue.svg)](https://github.com/JitseB/NPCLib/releases) +[![Thread](https://img.shields.io/badge/SpigotMC-Resource-orange.svg)](https://www.spigotmc.org/resources/npclib.55884/) +[![Thread](https://img.shields.io/badge/SpigotMC-Thread-orange.svg)](https://www.spigotmc.org/threads/npclib-–-basic-non-player-character-library.314460/) = This is an API made specifically for spigot servers (Minecraft). Current supported versions: **1.8 - 1.13.2**. Lightweight replacement for Citizens. NPCLib only uses packets instead of registering the entity in the actual Minecraft server. -**SpigotMC Resource** https://www.spigotmc.org/resources/npclib.55884/
-**SpigotMC Thread** https://www.spigotmc.org/threads/npclib-–-basic-non-player-character-library.314460/ - -**Preview** (click to play video) - +### Preview (click to play video) [![YouTube Video](http://img.youtube.com/vi/LqwdqIxPIvE/0.jpg)](http://www.youtube.com/watch?v=LqwdqIxPIvE "NPCLib – Basic non-player character library (Minecraft).") ## Donate @@ -21,6 +19,19 @@ This is an API made specifically for spigot servers (Minecraft). Current support Alternatively, you can help the project by starring the repository or telling others about NPCLib. :smile: +## Roadmap + +- :heavy_check_mark: Spawn and destroy NPC (version 1.8 - latest). +- :heavy_check_mark: Autohide NPC when out of range. +- :construction: Option to rotate head to player (when nearby). +- :construction: Add support for 1.7.10 (1.7 R4). +- :x: Give NPC armor and items in hand. + +### Roadmad Legend +:heavy_check_mark: Feature is fully implemented and functional.
+:construction: Feature is still in development (or experimental).
+:x: Development of feature has yet to be started.
+ ## Developers ### Usage From 71015423280ac27316f9d4e49e050757295e7a22 Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Wed, 13 Feb 2019 11:42:12 +0100 Subject: [PATCH 6/9] Added 1.7.10 NPC interaction support (for #10). --- commons/pom.xml | 10 +- .../tinyprotocol/LegacyTinyProtocol.java | 515 ++++++++++++++++++ .../comphenix/tinyprotocol/TinyProtocol.java | 20 +- .../main/java/net/jitse/npclib/NPCLib.java | 9 +- .../main/java/net/jitse/npclib/api/NPC.java | 11 +- .../api/wrapper/GameProfileWrapper.java | 54 ++ .../listeners/LegacyPacketListener.java | 71 +++ .../npclib/listeners/PacketListener.java | 74 +-- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- .../PacketPlayOutPlayerInfoWrapper.java | 5 +- 18 files changed, 757 insertions(+), 57 deletions(-) create mode 100755 commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java create mode 100644 commons/src/main/java/net/jitse/npclib/api/wrapper/GameProfileWrapper.java create mode 100755 commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java diff --git a/commons/pom.xml b/commons/pom.xml index f7e75d9..952033b 100755 --- a/commons/pom.xml +++ b/commons/pom.xml @@ -16,8 +16,16 @@ org.spigotmc spigot - 1.13.2-R0.1-SNAPSHOT + 1.7.10-R0.1-SNAPSHOT provided + + + io.netty + netty-all + 4.1.33.Final + provided + + diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java b/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java new file mode 100755 index 0000000..105a00d --- /dev/null +++ b/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java @@ -0,0 +1,515 @@ +package com.comphenix.tinyprotocol; + +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.io.netty.channel.*; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; + +/** + * Represents a very tiny alternative to ProtocolLib. + *

+ * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! + * + * @author Kristian + */ +public abstract class LegacyTinyProtocol { + private static final AtomicInteger ID = new AtomicInteger(0); + + // Used in order to lookup a channel + private static final Reflection.MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); + private static final Reflection.FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class); + private static final Reflection.FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class); + private static final Reflection.FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0); + + // Looking up ServerConnection + private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer"); + private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection"); + private static final Reflection.FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); + private static final Reflection.FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); + private static final Reflection.MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); + + // Packets we have to intercept + private static final Class PACKET_SET_PROTOCOL = Reflection.getMinecraftClass("PacketHandshakingInSetProtocol"); + private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); + private static final Reflection.FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); + private static final Reflection.FieldAccessor protocolId = Reflection.getField(PACKET_SET_PROTOCOL, int.class, 0); + private static final Reflection.FieldAccessor protocolType = Reflection.getField(PACKET_SET_PROTOCOL, Enum.class, 0); + + + // Speedup channel lookup + private Map channelLookup = new MapMaker().weakValues().makeMap(); + private Map protocolLookup = new MapMaker().weakKeys().makeMap(); + private Listener listener; + + // Channels that have already been removed + private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + + // List of network markers + private List networkManagers; + + // Injected channel handlers + private List serverChannels = Lists.newArrayList(); + private ChannelInboundHandlerAdapter serverChannelHandler; + private ChannelInitializer beginInitProtocol; + private ChannelInitializer endInitProtocol; + + // Current handler name + private String handlerName; + + protected volatile boolean closed; + protected Plugin plugin; + + /** + * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. + *

+ * You can construct multiple instances per plugin. + * + * @param plugin - the plugin. + */ + public LegacyTinyProtocol(final Plugin plugin) { + this.plugin = plugin; + + // Compute handler name + this.handlerName = getHandlerName(); + + // Prepare existing players + registerBukkitEvents(); + + try { + System.out.println("Attempting to inject into netty"); + registerChannelHandler(); + registerPlayers(plugin); + } catch (IllegalArgumentException ex) { + // Damn you, late bind + plugin.getLogger().info("Attempting to delay injection."); + + new BukkitRunnable() { + @Override + public void run() { + registerChannelHandler(); + registerPlayers(plugin); + plugin.getLogger().info("Injection complete."); + } + }.runTask(plugin); + } + } + + private void createServerChannelHandler() { + // Handle connected channels + endInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + try { + // This can take a while, so we need to stop the main thread from interfering + synchronized (networkManagers) { + // Stop injecting channels + if (!closed) { + channel.eventLoop().submit(() -> injectChannelInternal(channel)); + } + } + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); + } + } + + }; + + // This is executed before Minecraft's channel handler + beginInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + channel.pipeline().addLast(endInitProtocol); + } + + }; + + serverChannelHandler = new ChannelInboundHandlerAdapter() { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + Channel channel = (Channel) msg; + + channel.pipeline().addFirst(beginInitProtocol); + ctx.fireChannelRead(msg); + } + + }; + } + + /** + * Register bukkit events. + */ + private void registerBukkitEvents() { + listener = new Listener() { + + @EventHandler(priority = EventPriority.LOWEST) + public final void onPlayerLogin(PlayerJoinEvent e) { + if (closed) + return; + + Channel channel = getChannel(e.getPlayer()); + + // Don't inject players that have been explicitly uninjected + if (!uninjectedChannels.contains(channel)) { + injectPlayer(e.getPlayer()); + } + } + + @EventHandler + public final void onPluginDisable(PluginDisableEvent e) { + if (e.getPlugin().equals(plugin)) { + close(); + } + } + + }; + + plugin.getServer().getPluginManager().registerEvents(listener, plugin); + } + + @SuppressWarnings("unchecked") + private void registerChannelHandler() { + Object mcServer = getMinecraftServer.get(Bukkit.getServer()); + Object serverConnection = getServerConnection.get(mcServer); + boolean looking = true; + + // We need to synchronize against this list + networkManagers = (List) getNetworkMarkers.invoke(null, serverConnection); + createServerChannelHandler(); + + // Find the correct list, or implicitly throw an exception + for (int i = 0; looking; i++) { + List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); + + for (Object item : list) { + //if (!ChannelFuture.class.isInstance(item)) + // break; + + // Channel future that contains the server connection + Channel serverChannel = ((ChannelFuture) item).channel(); + + serverChannels.add(serverChannel); + ; + serverChannel.pipeline().addFirst(serverChannelHandler); + System.out.println("Server channel handler injected (" + serverChannel + ")"); + looking = false; + } + } + } + + private void unregisterChannelHandler() { + if (serverChannelHandler == null) + return; + + for (Channel serverChannel : serverChannels) { + final ChannelPipeline pipeline = serverChannel.pipeline(); + + // Remove channel handler + serverChannel.eventLoop().execute(() -> { + try { + pipeline.remove(serverChannelHandler); + } catch (NoSuchElementException e) { + // That's fine + } + }); + } + } + + private void registerPlayers(Plugin plugin) { + for (Player player : plugin.getServer().getOnlinePlayers()) { + injectPlayer(player); + } + } + + /** + * Invoked when the server is starting to send a packet to a player. + *

+ * Note that this is not executed on the main thread. + * + * @param receiver - the receiving player, NULL for early login/status packets. + * @param packet - the packet being sent. + * @return The packet to send instead, or NULL to cancel the transmission. + */ + public Object onPacketOutAsync(Player receiver, Object packet) { + return packet; + } + + /** + * Invoked when the server has received a packet from a given player. + *

+ * Use {@link Channel#remoteAddress()} to get the remote address of the client. + * + * @param sender - the player that sent the packet, NULL for early login/status packets. + * @param packet - the packet being received. + * @return The packet to recieve instead, or NULL to cancel. + */ + public Object onPacketInAsync(Player sender, Object packet) { + return packet; + } + + /** + * Send a packet to a particular player. + *

+ * Note that {@link #onPacketOutAsync(Player, Object)} will be invoked with this packet. + * + * @param player - the destination player. + * @param packet - the packet to send. + */ + public void sendPacket(Player player, Object packet) { + sendPacket(getChannel(player), packet); + } + + /** + * Send a packet to a particular client. + *

+ * Note that {@link #onPacketOutAsync(Player, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet to send. + */ + public void sendPacket(Channel channel, Object packet) { + channel.pipeline().writeAndFlush(packet); + } + + /** + * Pretend that a given packet has been received from a player. + *

+ * Note that {@link #onPacketInAsync(Player, Object)} will be invoked with this packet. + * + * @param player - the player that sent the packet. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Player player, Object packet) { + receivePacket(getChannel(player), packet); + } + + /** + * Pretend that a given packet has been received from a given client. + *

+ * Note that {@link #onPacketInAsync(Player, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Channel channel, Object packet) { + channel.pipeline().context("encoder").fireChannelRead(packet); + } + + /** + * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. + *

+ * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. + * + * @return A unique channel handler name. + */ + protected String getHandlerName() { + return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); + } + + /** + * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. + *

+ * This will automatically be called when a player has logged in. + * + * @param player - the player to inject. + */ + public void injectPlayer(Player player) { + injectChannelInternal(getChannel(player)).player = player; + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + * @return The intercepted channel, or NULL if it has already been injected. + */ + public void injectChannel(Channel channel) { + injectChannelInternal(channel); + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + * @return The packet interceptor. + */ + private PacketInterceptor injectChannelInternal(Channel channel) { + try { + PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); + + // Inject our packet interceptor + if (interceptor == null) { + interceptor = new PacketInterceptor(); + channel.pipeline().addBefore("packet_handler", handlerName, interceptor); + uninjectedChannels.remove(channel); + } + + return interceptor; + } catch (IllegalArgumentException e) { + // Try again + return (PacketInterceptor) channel.pipeline().get(handlerName); + } + } + + /** + * Retrieve the Netty channel associated with a player. This is cached. + * + * @param player - the player. + * @return The Netty channel. + */ + public Channel getChannel(Player player) { + Channel channel = channelLookup.get(player.getName()); + + // Lookup channel again + if (channel == null) { + Object connection = getConnection.get(getPlayerHandle.invoke(player)); + Object manager = getManager.get(connection); + + channelLookup.put(player.getName(), channel = getChannel.get(manager)); + } + + return channel; + } + + public int getProtocolVersion(Player player) { + Channel channel = channelLookup.get(player.getName()); + + // Lookup channel again + if (channel == null) { + Object connection = getConnection.get(getPlayerHandle.invoke(player)); + Object manager = getManager.get(connection); + + channelLookup.put(player.getName(), channel = getChannel.get(manager)); + } + + return protocolLookup.get(channel); + } + + /** + * Uninject a specific player. + * + * @param player - the injected player. + */ + public void uninjectPlayer(Player player) { + uninjectChannel(getChannel(player)); + } + + /** + * Uninject a specific channel. + *

+ * This will also disable the automatic channel injection that occurs when a player has properly logged in. + * + * @param channel - the injected channel. + */ + public void uninjectChannel(final Channel channel) { + // No need to guard against this if we're closing + if (!closed) { + uninjectedChannels.add(channel); + } + + // See ChannelInjector in ProtocolLib, line 590 + channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); + } + + /** + * Determine if the given player has been injected by TinyProtocol. + * + * @param player - the player. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Player player) { + return hasInjected(getChannel(player)); + } + + /** + * Determine if the given channel has been injected by TinyProtocol. + * + * @param channel - the channel. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Channel channel) { + return channel.pipeline().get(handlerName) != null; + } + + /** + * Cease listening for packets. This is called automatically when your plugin is disabled. + */ + public final void close() { + if (!closed) { + closed = true; + + // Remove our handlers + for (Player player : plugin.getServer().getOnlinePlayers()) { + uninjectPlayer(player); + } + + // Clean up Bukkit + HandlerList.unregisterAll(listener); + unregisterChannelHandler(); + } + } + + /** + * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. + * + * @author Kristian + */ + private final class PacketInterceptor extends ChannelDuplexHandler { + // Updated by the login event + public volatile Player player; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // Intercept channel + final Channel channel = ctx.channel(); + if (PACKET_LOGIN_IN_START.isInstance(msg)) { + GameProfile profile = getGameProfile.get(msg); + channelLookup.put(profile.getName(), channel); + } else if (PACKET_SET_PROTOCOL.isInstance(msg)) { + String protocol = protocolType.get(msg).name(); + if (protocol.equalsIgnoreCase("LOGIN")) { + protocolLookup.put(channel, protocolId.get(msg)); + } + } + + try { + msg = onPacketInAsync(player, msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); + } + + if (msg != null) { + super.channelRead(ctx, msg); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + try { + msg = onPacketOutAsync(player, msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); + } + + if (msg != null) { + super.write(ctx, msg, promise); + } + } + } +} \ No newline at end of file diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java index 5623c08..2198573 100755 --- a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java @@ -4,7 +4,6 @@ import com.comphenix.tinyprotocol.Reflection.FieldAccessor; import com.comphenix.tinyprotocol.Reflection.MethodInvoker; import com.google.common.collect.Lists; import com.google.common.collect.MapMaker; -import com.mojang.authlib.GameProfile; import io.netty.channel.*; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -46,14 +45,15 @@ public abstract class TinyProtocol { // Packets we have to intercept private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); - private static final FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); + private static final FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, + Reflection.getClass("com.mojang.authlib.GameProfile"), 0); // Speedup channel lookup private Map channelLookup = new MapMaker().weakValues().makeMap(); private Listener listener; // Channels that have already been removed - private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); // List of network markers private List networkManagers; @@ -339,6 +339,7 @@ public abstract class TinyProtocol { * Add a custom channel handler to the given channel. * * @param channel - the channel to inject. + * @return The intercepted channel, or NULL if it has already been injected. */ public void injectChannel(Channel channel) { injectChannelInternal(channel); @@ -411,7 +412,14 @@ public abstract class TinyProtocol { } // See ChannelInjector in ProtocolLib, line 590 - channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); + channel.eventLoop().execute(new Runnable() { + + @Override + public void run() { + channel.pipeline().remove(handlerName); + } + + }); } /** @@ -493,8 +501,8 @@ public abstract class TinyProtocol { private void handleLoginStart(Channel channel, Object packet) { if (PACKET_LOGIN_IN_START.isInstance(packet)) { - GameProfile profile = getGameProfile.get(packet); - channelLookup.put(profile.getName(), channel); + Object profile = getGameProfile.get(packet); + channelLookup.put((String) Reflection.getMethod(profile.getClass(), "getName").invoke(profile), channel); } } } diff --git a/commons/src/main/java/net/jitse/npclib/NPCLib.java b/commons/src/main/java/net/jitse/npclib/NPCLib.java index 2ebfa9e..43b541a 100755 --- a/commons/src/main/java/net/jitse/npclib/NPCLib.java +++ b/commons/src/main/java/net/jitse/npclib/NPCLib.java @@ -6,9 +6,11 @@ package net.jitse.npclib; import net.jitse.npclib.api.NPC; import net.jitse.npclib.listeners.ChunkListener; +import net.jitse.npclib.listeners.LegacyPacketListener; import net.jitse.npclib.listeners.PacketListener; import net.jitse.npclib.listeners.PlayerListener; import net.jitse.npclib.skin.Skin; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Server; import org.bukkit.plugin.PluginManager; @@ -64,7 +66,12 @@ public class NPCLib { pluginManager.registerEvents(new PlayerListener(), plugin); pluginManager.registerEvents(new ChunkListener(), plugin); - new PacketListener().start(plugin); + // Boot the according packet listener. + if (Bukkit.getBukkitVersion().contains("1.7")) { + new LegacyPacketListener().start(plugin); + } else { + new PacketListener().start(plugin); + } } /** diff --git a/commons/src/main/java/net/jitse/npclib/api/NPC.java b/commons/src/main/java/net/jitse/npclib/api/NPC.java index af7d786..5d3d59d 100755 --- a/commons/src/main/java/net/jitse/npclib/api/NPC.java +++ b/commons/src/main/java/net/jitse/npclib/api/NPC.java @@ -4,9 +4,8 @@ package net.jitse.npclib.api; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import net.jitse.npclib.NPCManager; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.jitse.npclib.events.NPCDestroyEvent; import net.jitse.npclib.events.NPCSpawnEvent; import net.jitse.npclib.events.trigger.TriggerType; @@ -39,7 +38,7 @@ public abstract class NPC implements PacketHandler, ActionHandler { protected final List lines; protected JavaPlugin plugin; - protected GameProfile gameProfile; + protected GameProfileWrapper gameProfile; protected Location location; public NPC(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { @@ -51,11 +50,11 @@ public abstract class NPC implements PacketHandler, ActionHandler { NPCManager.add(this); } - protected GameProfile generateGameProfile(UUID uuid, String name) { - GameProfile gameProfile = new GameProfile(uuid, name); + protected GameProfileWrapper generateGameProfile(UUID uuid, String name) { + GameProfileWrapper gameProfile = new GameProfileWrapper(uuid, name); if (skin != null) { - gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + gameProfile.addSkin(skin); } return gameProfile; diff --git a/commons/src/main/java/net/jitse/npclib/api/wrapper/GameProfileWrapper.java b/commons/src/main/java/net/jitse/npclib/api/wrapper/GameProfileWrapper.java new file mode 100644 index 0000000..5443ac1 --- /dev/null +++ b/commons/src/main/java/net/jitse/npclib/api/wrapper/GameProfileWrapper.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.jitse.npclib.api.wrapper; + +import com.comphenix.tinyprotocol.Reflection; +import com.google.common.collect.ForwardingMultimap; +import net.jitse.npclib.skin.Skin; +import org.bukkit.Bukkit; + +import java.util.UUID; + +public class GameProfileWrapper { + + // Written because of issue#10 (https://github.com/JitseB/NPCLib/issues/10). + // This class acts as an NMS reflection wrapper for the GameProfileWrapper class. + + // TODO: Add this class to the v1_7_R4 module of NPCLib. + + private final boolean is1_7 = Bukkit.getBukkitVersion().contains("1.7"); + private final Class gameProfileClazz = Reflection.getClass((is1_7 ? "net.minecraft.util." : "") + "com.mojang.authlib.GameProfile"); + + Object gameProfile; + + public GameProfileWrapper(UUID uuid, String name) { + // Only need to check if the version is 1.7, as NPCLib doesn't support any version below this version. + this.gameProfile = Reflection.getConstructor(gameProfileClazz, UUID.class, String.class).invoke(uuid, name); + } + + public void addSkin(Skin skin) { + // Create a new property with the skin data. + Class propertyClazz = Reflection.getClass((is1_7 ? "net.minecraft.util." : "") + "com.mojang.authlib.properties.Property"); + Object property = Reflection.getConstructor(propertyClazz, + String.class, String.class, String.class).invoke("textures", skin.getValue(), skin.getSignature()); + + // Get the property map from the GameProfileWrapper object. + Class propertyMapClazz = Reflection.getClass((is1_7 ? "net.minecraft.util." : "") + "com.mojang.authlib.properties.PropertyMap"); + Reflection.FieldAccessor propertyMapGetter = Reflection.getField(gameProfileClazz, "properties", + propertyMapClazz); + Object propertyMap = propertyMapGetter.get(gameProfile); + + // Add our new property to the property map. + Reflection.getMethod(ForwardingMultimap.class, "put", Object.class, Object.class) + .invoke(propertyMap, "textures", property); + + // Finally set the property map back in the GameProfileWrapper object. + propertyMapGetter.set(gameProfile, propertyMap); + } + + public Object getGameProfile() { + return gameProfile; + } +} diff --git a/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java new file mode 100755 index 0000000..fcbdc81 --- /dev/null +++ b/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018 Jitse Boonstra + */ + +package net.jitse.npclib.listeners; + +import com.comphenix.tinyprotocol.LegacyTinyProtocol; +import com.comphenix.tinyprotocol.Reflection; +import net.jitse.npclib.NPCManager; +import net.jitse.npclib.api.NPC; +import net.jitse.npclib.events.NPCInteractEvent; +import net.jitse.npclib.events.click.ClickType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +/** + * @author Jitse Boonstra + */ +public class LegacyPacketListener { + + // Classes: + private final Class packetPlayInUseEntityClazz = Reflection.getMinecraftClass("PacketPlayInUseEntity"); + + // Fields: + private final Reflection.FieldAccessor entityIdField = Reflection.getField(packetPlayInUseEntityClazz, "a", int.class); + private final Reflection.FieldAccessor actionField = Reflection.getField(packetPlayInUseEntityClazz, "action", Object.class); + + // Prevent players from clicking at very high speeds. + private final Set delay = new HashSet<>(); + + public void start(JavaPlugin plugin) { + new LegacyTinyProtocol(plugin) { + + @Override + public Object onPacketInAsync(Player player, Object packet) { + + if (packetPlayInUseEntityClazz.isInstance(packet)) { + NPC npc = NPCManager.getAllNPCs().stream().filter( + check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) + .findFirst().orElse(null); + + if (npc == null) { + // Default player, not doing magic with the packet. + return super.onPacketInAsync(player, packet); + } + + if (delay.contains(player.getUniqueId())) { + return null; + } + + ClickType clickType = actionField.get(packet).toString() + .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; + + Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); + + UUID uuid = player.getUniqueId(); + delay.add(uuid); + Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); + return null; + } + + return super.onPacketInAsync(player, packet); + } + }; + } +} diff --git a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java index e3e3857..cb07d28 100755 --- a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java +++ b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java @@ -5,6 +5,14 @@ package net.jitse.npclib.listeners; import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import io.netty.channel.Channel; +import net.jitse.npclib.NPCManager; +import net.jitse.npclib.api.NPC; +import net.jitse.npclib.events.NPCInteractEvent; +import net.jitse.npclib.events.click.ClickType; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.HashSet; @@ -27,38 +35,38 @@ public class PacketListener { private final Set delay = new HashSet<>(); public void start(JavaPlugin plugin) { -// new TinyProtocol(plugin) { -// -// @Override -// public Object onPacketInAsync(Player player, Channel channel, Object packet) { -// -// if (packetPlayInUseEntityClazz.isInstance(packet)) { -// NPC npc = NPCManager.getAllNPCs().stream().filter( -// check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) -// .findFirst().orElse(null); -// -// if (npc == null) { -// // Default player, not doing magic with the packet. -// return super.onPacketInAsync(player, channel, packet); -// } -// -// if (delay.contains(player.getUniqueId())) { -// return null; -// } -// -// ClickType clickType = actionField.get(packet).toString() -// .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; -// -// Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); -// -// UUID uuid = player.getUniqueId(); -// delay.add(uuid); -// Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); -// return null; -// } -// -// return super.onPacketInAsync(player, channel, packet); -// } -// }; + new TinyProtocol(plugin) { + + @Override + public Object onPacketInAsync(Player player, Channel channel, Object packet) { + + if (packetPlayInUseEntityClazz.isInstance(packet)) { + NPC npc = NPCManager.getAllNPCs().stream().filter( + check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) + .findFirst().orElse(null); + + if (npc == null) { + // Default player, not doing magic with the packet. + return super.onPacketInAsync(player, channel, packet); + } + + if (delay.contains(player.getUniqueId())) { + return null; + } + + ClickType clickType = actionField.get(packet).toString() + .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; + + Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); + + UUID uuid = player.getUniqueId(); + delay.add(uuid); + Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); + return null; + } + + return super.onPacketInAsync(player, channel, packet); + } + }; } } diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java index d07e54a..d5a77df 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_10_R1.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_10_R1.EnumGamemode; import net.minecraft.server.v1_10_R1.IChatBaseComponent; import net.minecraft.server.v1_10_R1.PacketPlayOutPlayerInfo; @@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper { private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz, packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class); - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 52413e5..cb2a3de 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_11_R1.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_11_R1.EnumGamemode; import net.minecraft.server.v1_11_R1.IChatBaseComponent; import net.minecraft.server.v1_11_R1.PacketPlayOutPlayerInfo; @@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper { private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz, packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class); - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java index f13a0a4..e24f311 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_12_R1.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_12_R1.EnumGamemode; import net.minecraft.server.v1_12_R1.IChatBaseComponent; import net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo; @@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper { private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz, packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class); - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 578efb0..24b0d6a 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_13_R1.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_13_R1.EnumGamemode; import net.minecraft.server.v1_13_R1.IChatBaseComponent; import net.minecraft.server.v1_13_R1.PacketPlayOutPlayerInfo; @@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper { private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz, packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class); - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java index 79e1fbb..bd8103d 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_13_R2.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_13_R2.EnumGamemode; import net.minecraft.server.v1_13_R2.IChatBaseComponent; import net.minecraft.server.v1_13_R2.PacketPlayOutPlayerInfo; @@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper { private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz, packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class); - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 283b46e..bab9bfb 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_8_R1.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_8_R1.*; import java.util.List; @@ -15,7 +16,9 @@ import java.util.List; */ public class PacketPlayOutPlayerInfoWrapper { - public PacketPlayOutPlayerInfo create(EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java index bca9688..9afaaca 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_8_R2.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_8_R2.IChatBaseComponent; import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_8_R2.WorldSettings; @@ -17,7 +18,9 @@ import java.util.List; */ public class PacketPlayOutPlayerInfoWrapper { - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java index 3c411df..24a7cc0 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_8_R3.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_8_R3.IChatBaseComponent; import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_8_R3.WorldSettings; @@ -17,7 +18,9 @@ import java.util.List; */ public class PacketPlayOutPlayerInfoWrapper { - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java index 43695c7..0f9a478 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_9_R1.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_9_R1.IChatBaseComponent; import net.minecraft.server.v1_9_R1.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_9_R1.WorldSettings; @@ -18,7 +19,9 @@ import java.util.List; */ public class PacketPlayOutPlayerInfoWrapper { - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java index 67afd64..6ba09e6 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java @@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_9_R2.packets; import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; +import net.jitse.npclib.api.wrapper.GameProfileWrapper; import net.minecraft.server.v1_9_R2.IChatBaseComponent; import net.minecraft.server.v1_9_R2.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_9_R2.WorldSettings; @@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper { private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz, packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, WorldSettings.EnumGamemode.class, IChatBaseComponent.class); - public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) { + public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) { + GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile(); + PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo(); Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class) .set(packetPlayOutPlayerInfo, action); From 06cec6c0bf48228ed8942e97420dfd22d377a52a Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Fri, 15 Feb 2019 19:59:38 +0100 Subject: [PATCH 7/9] Cleaned up some code (#10). --- .../tinyprotocol/LegacyTinyProtocol.java | 234 ++-------------- .../comphenix/tinyprotocol/TinyProtocol.java | 260 +++--------------- .../main/java/net/jitse/npclib/NPCLib.java | 7 +- .../listeners/LegacyPacketListener.java | 71 ----- .../npclib/listeners/PacketListener.java | 90 ++++-- 5 files changed, 121 insertions(+), 541 deletions(-) delete mode 100755 commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java b/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java index 105a00d..5453571 100755 --- a/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java +++ b/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java @@ -20,11 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; /** - * Represents a very tiny alternative to ProtocolLib. - *

- * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! - * - * @author Kristian + * Minimized version of TinyProtocol by Kristian suited for NPCLib. */ public abstract class LegacyTinyProtocol { private static final AtomicInteger ID = new AtomicInteger(0); @@ -56,7 +52,7 @@ public abstract class LegacyTinyProtocol { private Listener listener; // Channels that have already been removed - private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); // List of network markers private List networkManagers; @@ -70,39 +66,32 @@ public abstract class LegacyTinyProtocol { // Current handler name private String handlerName; - protected volatile boolean closed; + private volatile boolean closed; protected Plugin plugin; - /** - * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. - *

- * You can construct multiple instances per plugin. - * - * @param plugin - the plugin. - */ - public LegacyTinyProtocol(final Plugin plugin) { + protected LegacyTinyProtocol(final Plugin plugin) { this.plugin = plugin; // Compute handler name - this.handlerName = getHandlerName(); + this.handlerName = "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); // Prepare existing players registerBukkitEvents(); try { - System.out.println("Attempting to inject into netty"); + System.out.println("[NPCLib] Attempting to inject into netty."); registerChannelHandler(); registerPlayers(plugin); } catch (IllegalArgumentException ex) { // Damn you, late bind - plugin.getLogger().info("Attempting to delay injection."); + plugin.getLogger().info("[NPCLib] Attempting to delay injection."); new BukkitRunnable() { @Override public void run() { registerChannelHandler(); registerPlayers(plugin); - plugin.getLogger().info("Injection complete."); + plugin.getLogger().info("[NPCLib] Injection complete."); } }.runTask(plugin); } @@ -112,6 +101,7 @@ public abstract class LegacyTinyProtocol { // Handle connected channels endInitProtocol = new ChannelInitializer() { + @SuppressWarnings("all") @Override protected void initChannel(Channel channel) throws Exception { try { @@ -123,7 +113,7 @@ public abstract class LegacyTinyProtocol { } } } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); + plugin.getLogger().log(Level.SEVERE, "[NPCLib] Cannot inject incomming channel " + channel, e); } } @@ -132,6 +122,7 @@ public abstract class LegacyTinyProtocol { // This is executed before Minecraft's channel handler beginInitProtocol = new ChannelInitializer() { + @SuppressWarnings("all") @Override protected void initChannel(Channel channel) throws Exception { channel.pipeline().addLast(endInitProtocol); @@ -141,6 +132,7 @@ public abstract class LegacyTinyProtocol { serverChannelHandler = new ChannelInboundHandlerAdapter() { + @SuppressWarnings("all") @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { Channel channel = (Channel) msg; @@ -152,12 +144,10 @@ public abstract class LegacyTinyProtocol { }; } - /** - * Register bukkit events. - */ private void registerBukkitEvents() { listener = new Listener() { + @SuppressWarnings("unused") @EventHandler(priority = EventPriority.LOWEST) public final void onPlayerLogin(PlayerJoinEvent e) { if (closed) @@ -171,6 +161,7 @@ public abstract class LegacyTinyProtocol { } } + @SuppressWarnings("unused") @EventHandler public final void onPluginDisable(PluginDisableEvent e) { if (e.getPlugin().equals(plugin)) { @@ -205,9 +196,9 @@ public abstract class LegacyTinyProtocol { Channel serverChannel = ((ChannelFuture) item).channel(); serverChannels.add(serverChannel); - ; + serverChannel.pipeline().addFirst(serverChannelHandler); - System.out.println("Server channel handler injected (" + serverChannel + ")"); + System.out.println("[NPCLib] Server channel handler injected (" + serverChannel + ")"); looking = false; } } @@ -237,118 +228,14 @@ public abstract class LegacyTinyProtocol { } } - /** - * Invoked when the server is starting to send a packet to a player. - *

- * Note that this is not executed on the main thread. - * - * @param receiver - the receiving player, NULL for early login/status packets. - * @param packet - the packet being sent. - * @return The packet to send instead, or NULL to cancel the transmission. - */ - public Object onPacketOutAsync(Player receiver, Object packet) { - return packet; - } - - /** - * Invoked when the server has received a packet from a given player. - *

- * Use {@link Channel#remoteAddress()} to get the remote address of the client. - * - * @param sender - the player that sent the packet, NULL for early login/status packets. - * @param packet - the packet being received. - * @return The packet to recieve instead, or NULL to cancel. - */ public Object onPacketInAsync(Player sender, Object packet) { return packet; } - /** - * Send a packet to a particular player. - *

- * Note that {@link #onPacketOutAsync(Player, Object)} will be invoked with this packet. - * - * @param player - the destination player. - * @param packet - the packet to send. - */ - public void sendPacket(Player player, Object packet) { - sendPacket(getChannel(player), packet); - } - - /** - * Send a packet to a particular client. - *

- * Note that {@link #onPacketOutAsync(Player, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet to send. - */ - public void sendPacket(Channel channel, Object packet) { - channel.pipeline().writeAndFlush(packet); - } - - /** - * Pretend that a given packet has been received from a player. - *

- * Note that {@link #onPacketInAsync(Player, Object)} will be invoked with this packet. - * - * @param player - the player that sent the packet. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Player player, Object packet) { - receivePacket(getChannel(player), packet); - } - - /** - * Pretend that a given packet has been received from a given client. - *

- * Note that {@link #onPacketInAsync(Player, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Channel channel, Object packet) { - channel.pipeline().context("encoder").fireChannelRead(packet); - } - - /** - * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. - *

- * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. - * - * @return A unique channel handler name. - */ - protected String getHandlerName() { - return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); - } - - /** - * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. - *

- * This will automatically be called when a player has logged in. - * - * @param player - the player to inject. - */ - public void injectPlayer(Player player) { + private void injectPlayer(Player player) { injectChannelInternal(getChannel(player)).player = player; } - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The intercepted channel, or NULL if it has already been injected. - */ - public void injectChannel(Channel channel) { - injectChannelInternal(channel); - } - - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The packet interceptor. - */ private PacketInterceptor injectChannelInternal(Channel channel) { try { PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); @@ -367,13 +254,7 @@ public abstract class LegacyTinyProtocol { } } - /** - * Retrieve the Netty channel associated with a player. This is cached. - * - * @param player - the player. - * @return The Netty channel. - */ - public Channel getChannel(Player player) { + private Channel getChannel(Player player) { Channel channel = channelLookup.get(player.getName()); // Lookup channel again @@ -387,37 +268,7 @@ public abstract class LegacyTinyProtocol { return channel; } - public int getProtocolVersion(Player player) { - Channel channel = channelLookup.get(player.getName()); - - // Lookup channel again - if (channel == null) { - Object connection = getConnection.get(getPlayerHandle.invoke(player)); - Object manager = getManager.get(connection); - - channelLookup.put(player.getName(), channel = getChannel.get(manager)); - } - - return protocolLookup.get(channel); - } - - /** - * Uninject a specific player. - * - * @param player - the injected player. - */ - public void uninjectPlayer(Player player) { - uninjectChannel(getChannel(player)); - } - - /** - * Uninject a specific channel. - *

- * This will also disable the automatic channel injection that occurs when a player has properly logged in. - * - * @param channel - the injected channel. - */ - public void uninjectChannel(final Channel channel) { + private void uninjectChannel(final Channel channel) { // No need to guard against this if we're closing if (!closed) { uninjectedChannels.add(channel); @@ -427,36 +278,13 @@ public abstract class LegacyTinyProtocol { channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); } - /** - * Determine if the given player has been injected by TinyProtocol. - * - * @param player - the player. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Player player) { - return hasInjected(getChannel(player)); - } - - /** - * Determine if the given channel has been injected by TinyProtocol. - * - * @param channel - the channel. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Channel channel) { - return channel.pipeline().get(handlerName) != null; - } - - /** - * Cease listening for packets. This is called automatically when your plugin is disabled. - */ - public final void close() { + private void close() { if (!closed) { closed = true; // Remove our handlers for (Player player : plugin.getServer().getOnlinePlayers()) { - uninjectPlayer(player); + uninjectChannel(getChannel(player)); } // Clean up Bukkit @@ -465,11 +293,6 @@ public abstract class LegacyTinyProtocol { } } - /** - * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. - * - * @author Kristian - */ private final class PacketInterceptor extends ChannelDuplexHandler { // Updated by the login event public volatile Player player; @@ -491,25 +314,12 @@ public abstract class LegacyTinyProtocol { try { msg = onPacketInAsync(player, msg); } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); + plugin.getLogger().log(Level.SEVERE, "[NPCLib] Error in onPacketInAsync().", e); } if (msg != null) { super.channelRead(ctx, msg); } } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - try { - msg = onPacketOutAsync(player, msg); - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); - } - - if (msg != null) { - super.write(ctx, msg, promise); - } - } } } \ No newline at end of file diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java index 2198573..f2a936b 100755 --- a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java @@ -21,11 +21,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; /** - * Represents a very tiny alternative to ProtocolLib. - *

- * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! - * - * @author Kristian + * Minimized version of TinyProtocol by Kristian suited for NPCLib. */ public abstract class TinyProtocol { private static final AtomicInteger ID = new AtomicInteger(0); @@ -53,7 +49,7 @@ public abstract class TinyProtocol { private Listener listener; // Channels that have already been removed - private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); // List of network markers private List networkManagers; @@ -67,38 +63,32 @@ public abstract class TinyProtocol { // Current handler name private String handlerName; - protected volatile boolean closed; + private volatile boolean closed; protected Plugin plugin; - /** - * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. - *

- * You can construct multiple instances per plugin. - * - * @param plugin - the plugin. - */ - public TinyProtocol(final Plugin plugin) { + protected TinyProtocol(final Plugin plugin) { this.plugin = plugin; // Compute handler name - this.handlerName = getHandlerName(); + this.handlerName = "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); // Prepare existing players registerBukkitEvents(); try { + System.out.println("[NPCLib] Attempting to inject into netty."); registerChannelHandler(); registerPlayers(plugin); } catch (IllegalArgumentException ex) { // Damn you, late bind - plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind."); + plugin.getLogger().info("[NPCLib] Attempting to delay injection."); new BukkitRunnable() { @Override public void run() { registerChannelHandler(); registerPlayers(plugin); - plugin.getLogger().info("[TinyProtocol] Late bind injection successful."); + plugin.getLogger().info("[NPCLib] Injection complete."); } }.runTask(plugin); } @@ -108,6 +98,7 @@ public abstract class TinyProtocol { // Handle connected channels endInitProtocol = new ChannelInitializer() { + @SuppressWarnings("all") @Override protected void initChannel(Channel channel) throws Exception { try { @@ -119,7 +110,7 @@ public abstract class TinyProtocol { } } } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); + plugin.getLogger().log(Level.SEVERE, "[NPCLib] Cannot inject incomming channel " + channel, e); } } @@ -128,6 +119,7 @@ public abstract class TinyProtocol { // This is executed before Minecraft's channel handler beginInitProtocol = new ChannelInitializer() { + @SuppressWarnings("all") @Override protected void initChannel(Channel channel) throws Exception { channel.pipeline().addLast(endInitProtocol); @@ -137,6 +129,7 @@ public abstract class TinyProtocol { serverChannelHandler = new ChannelInboundHandlerAdapter() { + @SuppressWarnings("all") @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { Channel channel = (Channel) msg; @@ -149,12 +142,10 @@ public abstract class TinyProtocol { }; } - /** - * Register bukkit events. - */ private void registerBukkitEvents() { listener = new Listener() { + @SuppressWarnings("unused") @EventHandler(priority = EventPriority.LOWEST) public final void onPlayerLogin(PlayerLoginEvent e) { if (closed) @@ -168,6 +159,7 @@ public abstract class TinyProtocol { } } + @SuppressWarnings("unused") @EventHandler public final void onPluginDisable(PluginDisableEvent e) { if (e.getPlugin().equals(plugin)) { @@ -195,7 +187,7 @@ public abstract class TinyProtocol { List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); for (Object item : list) { - if (!ChannelFuture.class.isInstance(item)) + if (!(item instanceof ChannelFuture)) break; // Channel future that contains the server connection @@ -216,17 +208,12 @@ public abstract class TinyProtocol { final ChannelPipeline pipeline = serverChannel.pipeline(); // Remove channel handler - serverChannel.eventLoop().execute(new Runnable() { - - @Override - public void run() { - try { - pipeline.remove(serverChannelHandler); - } catch (NoSuchElementException e) { - // That's fine - } + serverChannel.eventLoop().execute(() -> { + try { + pipeline.remove(serverChannelHandler); + } catch (NoSuchElementException e) { + // That's fine } - }); } } @@ -237,120 +224,14 @@ public abstract class TinyProtocol { } } - /** - * Invoked when the server is starting to send a packet to a player. - *

- * Note that this is not executed on the main thread. - * - * @param receiver - the receiving player, NULL for early login/status packets. - * @param channel - the channel that received the packet. Never NULL. - * @param packet - the packet being sent. - * @return The packet to send instead, or NULL to cancel the transmission. - */ - public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { + public Object onPacketInAsync(Player sender, Object packet) { return packet; } - /** - * Invoked when the server has received a packet from a given player. - *

- * Use {@link Channel#remoteAddress()} to get the remote address of the client. - * - * @param sender - the player that sent the packet, NULL for early login/status packets. - * @param channel - channel that received the packet. Never NULL. - * @param packet - the packet being received. - * @return The packet to recieve instead, or NULL to cancel. - */ - public Object onPacketInAsync(Player sender, Channel channel, Object packet) { - return packet; - } - - /** - * Send a packet to a particular player. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the destination player. - * @param packet - the packet to send. - */ - public void sendPacket(Player player, Object packet) { - sendPacket(getChannel(player), packet); - } - - /** - * Send a packet to a particular client. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet to send. - */ - public void sendPacket(Channel channel, Object packet) { - channel.pipeline().writeAndFlush(packet); - } - - /** - * Pretend that a given packet has been received from a player. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the player that sent the packet. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Player player, Object packet) { - receivePacket(getChannel(player), packet); - } - - /** - * Pretend that a given packet has been received from a given client. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet that will be received by the server. - */ - public void receivePacket(Channel channel, Object packet) { - channel.pipeline().context("encoder").fireChannelRead(packet); - } - - /** - * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. - *

- * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. - * - * @return A unique channel handler name. - */ - protected String getHandlerName() { - return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); - } - - /** - * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. - *

- * This will automatically be called when a player has logged in. - * - * @param player - the player to inject. - */ - public void injectPlayer(Player player) { + private void injectPlayer(Player player) { injectChannelInternal(getChannel(player)).player = player; } - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The intercepted channel, or NULL if it has already been injected. - */ - public void injectChannel(Channel channel) { - injectChannelInternal(channel); - } - - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The packet interceptor. - */ private PacketInterceptor injectChannelInternal(Channel channel) { try { PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); @@ -369,13 +250,7 @@ public abstract class TinyProtocol { } } - /** - * Retrieve the Netty channel associated with a player. This is cached. - * - * @param player - the player. - * @return The Netty channel. - */ - public Channel getChannel(Player player) { + private Channel getChannel(Player player) { Channel channel = channelLookup.get(player.getName()); // Lookup channel again @@ -389,69 +264,20 @@ public abstract class TinyProtocol { return channel; } - /** - * Uninject a specific player. - * - * @param player - the injected player. - */ - public void uninjectPlayer(Player player) { - uninjectChannel(getChannel(player)); - } - - /** - * Uninject a specific channel. - *

- * This will also disable the automatic channel injection that occurs when a player has properly logged in. - * - * @param channel - the injected channel. - */ - public void uninjectChannel(final Channel channel) { - // No need to guard against this if we're closing - if (!closed) { - uninjectedChannels.add(channel); - } - - // See ChannelInjector in ProtocolLib, line 590 - channel.eventLoop().execute(new Runnable() { - - @Override - public void run() { - channel.pipeline().remove(handlerName); - } - - }); - } - - /** - * Determine if the given player has been injected by TinyProtocol. - * - * @param player - the player. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Player player) { - return hasInjected(getChannel(player)); - } - - /** - * Determine if the given channel has been injected by TinyProtocol. - * - * @param channel - the channel. - * @return TRUE if it is, FALSE otherwise. - */ - public boolean hasInjected(Channel channel) { - return channel.pipeline().get(handlerName) != null; - } - - /** - * Cease listening for packets. This is called automatically when your plugin is disabled. - */ - public final void close() { + private void close() { if (!closed) { closed = true; // Remove our handlers for (Player player : plugin.getServer().getOnlinePlayers()) { - uninjectPlayer(player); + // No need to guard against this if we're closing + Channel channel = getChannel(player); + if (!closed) { + uninjectedChannels.add(channel); + } + + // See ChannelInjector in ProtocolLib, line 590 + channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); } // Clean up Bukkit @@ -460,11 +286,6 @@ public abstract class TinyProtocol { } } - /** - * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. - * - * @author Kristian - */ private final class PacketInterceptor extends ChannelDuplexHandler { // Updated by the login event public volatile Player player; @@ -476,9 +297,9 @@ public abstract class TinyProtocol { handleLoginStart(channel, msg); try { - msg = onPacketInAsync(player, channel, msg); + msg = onPacketInAsync(player, msg); } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); + plugin.getLogger().log(Level.SEVERE, "[NPCLib] Error in onPacketInAsync().", e); } if (msg != null) { @@ -486,19 +307,6 @@ public abstract class TinyProtocol { } } - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - try { - msg = onPacketOutAsync(player, ctx.channel(), msg); - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); - } - - if (msg != null) { - super.write(ctx, msg, promise); - } - } - private void handleLoginStart(Channel channel, Object packet) { if (PACKET_LOGIN_IN_START.isInstance(packet)) { Object profile = getGameProfile.get(packet); diff --git a/commons/src/main/java/net/jitse/npclib/NPCLib.java b/commons/src/main/java/net/jitse/npclib/NPCLib.java index 43b541a..d304d0c 100755 --- a/commons/src/main/java/net/jitse/npclib/NPCLib.java +++ b/commons/src/main/java/net/jitse/npclib/NPCLib.java @@ -6,7 +6,6 @@ package net.jitse.npclib; import net.jitse.npclib.api.NPC; import net.jitse.npclib.listeners.ChunkListener; -import net.jitse.npclib.listeners.LegacyPacketListener; import net.jitse.npclib.listeners.PacketListener; import net.jitse.npclib.listeners.PlayerListener; import net.jitse.npclib.skin.Skin; @@ -67,11 +66,7 @@ public class NPCLib { pluginManager.registerEvents(new ChunkListener(), plugin); // Boot the according packet listener. - if (Bukkit.getBukkitVersion().contains("1.7")) { - new LegacyPacketListener().start(plugin); - } else { - new PacketListener().start(plugin); - } + new PacketListener().start(plugin, Bukkit.getBukkitVersion().contains("1.7")); } /** diff --git a/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java deleted file mode 100755 index fcbdc81..0000000 --- a/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2018 Jitse Boonstra - */ - -package net.jitse.npclib.listeners; - -import com.comphenix.tinyprotocol.LegacyTinyProtocol; -import com.comphenix.tinyprotocol.Reflection; -import net.jitse.npclib.NPCManager; -import net.jitse.npclib.api.NPC; -import net.jitse.npclib.events.NPCInteractEvent; -import net.jitse.npclib.events.click.ClickType; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; - -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -/** - * @author Jitse Boonstra - */ -public class LegacyPacketListener { - - // Classes: - private final Class packetPlayInUseEntityClazz = Reflection.getMinecraftClass("PacketPlayInUseEntity"); - - // Fields: - private final Reflection.FieldAccessor entityIdField = Reflection.getField(packetPlayInUseEntityClazz, "a", int.class); - private final Reflection.FieldAccessor actionField = Reflection.getField(packetPlayInUseEntityClazz, "action", Object.class); - - // Prevent players from clicking at very high speeds. - private final Set delay = new HashSet<>(); - - public void start(JavaPlugin plugin) { - new LegacyTinyProtocol(plugin) { - - @Override - public Object onPacketInAsync(Player player, Object packet) { - - if (packetPlayInUseEntityClazz.isInstance(packet)) { - NPC npc = NPCManager.getAllNPCs().stream().filter( - check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) - .findFirst().orElse(null); - - if (npc == null) { - // Default player, not doing magic with the packet. - return super.onPacketInAsync(player, packet); - } - - if (delay.contains(player.getUniqueId())) { - return null; - } - - ClickType clickType = actionField.get(packet).toString() - .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; - - Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); - - UUID uuid = player.getUniqueId(); - delay.add(uuid); - Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); - return null; - } - - return super.onPacketInAsync(player, packet); - } - }; - } -} diff --git a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java index cb07d28..5e700d0 100755 --- a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java +++ b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java @@ -4,9 +4,9 @@ package net.jitse.npclib.listeners; +import com.comphenix.tinyprotocol.LegacyTinyProtocol; import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.TinyProtocol; -import io.netty.channel.Channel; import net.jitse.npclib.NPCManager; import net.jitse.npclib.api.NPC; import net.jitse.npclib.events.NPCInteractEvent; @@ -34,39 +34,77 @@ public class PacketListener { // Prevent players from clicking at very high speeds. private final Set delay = new HashSet<>(); - public void start(JavaPlugin plugin) { - new TinyProtocol(plugin) { + public void start(JavaPlugin plugin, boolean is1_7) { + if (is1_7) { + // 1.7 R4 packet interaction. + new LegacyTinyProtocol(plugin) { - @Override - public Object onPacketInAsync(Player player, Channel channel, Object packet) { + @Override + public Object onPacketInAsync(Player player, Object packet) { - if (packetPlayInUseEntityClazz.isInstance(packet)) { - NPC npc = NPCManager.getAllNPCs().stream().filter( - check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) - .findFirst().orElse(null); + if (packetPlayInUseEntityClazz.isInstance(packet)) { + NPC npc = NPCManager.getAllNPCs().stream().filter( + check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) + .findFirst().orElse(null); - if (npc == null) { - // Default player, not doing magic with the packet. - return super.onPacketInAsync(player, channel, packet); - } + if (npc == null) { + // Default player, not doing magic with the packet. + return super.onPacketInAsync(player, packet); + } - if (delay.contains(player.getUniqueId())) { + if (delay.contains(player.getUniqueId())) { + return null; + } + + ClickType clickType = actionField.get(packet).toString() + .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; + + Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); + + UUID uuid = player.getUniqueId(); + delay.add(uuid); + Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); return null; } - ClickType clickType = actionField.get(packet).toString() - .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; - - Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); - - UUID uuid = player.getUniqueId(); - delay.add(uuid); - Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); - return null; + return super.onPacketInAsync(player, packet); } + }; + } else { + // 1.8 (and above) packet interaction. + new TinyProtocol(plugin) { - return super.onPacketInAsync(player, channel, packet); - } - }; + @Override + public Object onPacketInAsync(Player player, Object packet) { + + if (packetPlayInUseEntityClazz.isInstance(packet)) { + NPC npc = NPCManager.getAllNPCs().stream().filter( + check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) + .findFirst().orElse(null); + + if (npc == null) { + // Default player, not doing magic with the packet. + return super.onPacketInAsync(player, packet); + } + + if (delay.contains(player.getUniqueId())) { + return null; + } + + ClickType clickType = actionField.get(packet).toString() + .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK; + + Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); + + UUID uuid = player.getUniqueId(); + delay.add(uuid); + Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); + return null; + } + + return super.onPacketInAsync(player, packet); + } + }; + } } } From d018b8d97bd98ec1295e2e3b8fef70444b39ac9c Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Fri, 15 Feb 2019 20:18:00 +0100 Subject: [PATCH 8/9] For v1.4 (#10) (added support for 1.7.10). --- .travis.yml | 2 ++ README.md | 9 ++++++--- api/pom.xml | 2 +- commons/pom.xml | 2 +- nms/pom.xml | 2 +- nms/v1_10_R1/pom.xml | 2 +- nms/v1_11_R1/pom.xml | 2 +- nms/v1_12_R1/pom.xml | 2 +- nms/v1_13_R1/pom.xml | 2 +- nms/v1_13_R2/pom.xml | 2 +- nms/v1_7_R4/pom.xml | 8 +------- .../java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java | 1 + nms/v1_8_R1/pom.xml | 2 +- nms/v1_8_R2/pom.xml | 2 +- nms/v1_8_R3/pom.xml | 2 +- nms/v1_9_R1/pom.xml | 2 +- nms/v1_9_R2/pom.xml | 2 +- plugin/pom.xml | 2 +- pom.xml | 2 +- 19 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index b81ba3c..b3d3c84 100755 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ cache: - $HOME/.m2/ install: - wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar +- wget http://central.maven.org/maven2/io/netty/netty-all/4.1.33.Final/netty-all-4.1.33.Final.jar + mvn install:install-file -Dfile=netty-all-4.1.33.Final.jar -DgroupId=io.netty -DartifactId=netty-all -Dversion=4.1.33.Final -Dpackaging=jar - wget https://github.com/Sarabveer/CraftBukkit-Spigot-Binary/blob/master/spigot-1.7.10-R0.1/spigot-1.7.10-R0.1-1649.jar - mvn install:install-file -Dfile=spigot-1.7.10-R0.1-1649.jar -DgroupId=org.spigotmc -DartifactId=spigot -Dversion=1.7.10-R0.1-SNAPSHOT -Dpackaging=jar - ls $HOME/.m2/repository/org/spigotmc/spigot/1.8-R0.1-SNAPSHOT >> /dev/null 2>&1 || java -jar BuildTools.jar --rev 1.8 >> /dev/null 2>&1 diff --git a/README.md b/README.md index 99feee9..979f825 100755 --- a/README.md +++ b/README.md @@ -3,12 +3,12 @@ NPCLib – Basic non-player character library.
[![Release](https://jitpack.io/v/JitseB/NPCLib.svg)](https://github.com/JitseB/NPCLib/releases) [![Build Status](https://travis-ci.com/JitseB/NPCLib.svg?branch=master)](https://travis-ci.com/JitseB/NPCLib) [![JDK](https://img.shields.io/badge/Using-Java%208-blue.svg)](http://jdk.java.net/8/) -[![Versions](https://img.shields.io/badge/MC-1.8%20--%201.13.2-blue.svg)](https://github.com/JitseB/NPCLib/releases) +[![Versions](https://img.shields.io/badge/MC-1.7.10%20--%201.13.2-blue.svg)](https://github.com/JitseB/NPCLib/releases) [![Thread](https://img.shields.io/badge/SpigotMC-Resource-orange.svg)](https://www.spigotmc.org/resources/npclib.55884/) [![Thread](https://img.shields.io/badge/SpigotMC-Thread-orange.svg)](https://www.spigotmc.org/threads/npclib-–-basic-non-player-character-library.314460/) = -This is an API made specifically for spigot servers (Minecraft). Current supported versions: **1.8 - 1.13.2**. Lightweight replacement for Citizens. NPCLib only uses packets instead of registering the entity in the actual Minecraft server. +This is an API made specifically for spigot servers (Minecraft). Current supported versions: **1.7.10 - 1.13.2**. Lightweight replacement for Citizens. NPCLib only uses packets instead of registering the entity in the actual Minecraft server. ### Preview (click to play video) [![YouTube Video](http://img.youtube.com/vi/LqwdqIxPIvE/0.jpg)](http://www.youtube.com/watch?v=LqwdqIxPIvE "NPCLib – Basic non-player character library (Minecraft).") @@ -23,9 +23,11 @@ Alternatively, you can help the project by starring the repository or telling ot - :heavy_check_mark: Spawn and destroy NPC (version 1.8 - latest). - :heavy_check_mark: Autohide NPC when out of range. +- :heavy_check_mark: Add support for 1.7.10 (1.7 R4). - :construction: Option to rotate head to player (when nearby). -- :construction: Add support for 1.7.10 (1.7 R4). +- :construction: Add support for animated text (update-able holograms). - :x: Give NPC armor and items in hand. +- :x: Multi-line text support for 1.7.10 (1.7 R4). ### Roadmad Legend :heavy_check_mark: Feature is fully implemented and functional.
@@ -51,6 +53,7 @@ Alternatively, you can put `npclib-plugin-v*.jar` under your `plugins` folder. B ```Java // Creating a new NPC instance. + // MC 1.7.10 (1.7 R4) only supports single-line text. NPC npc = lib.createNPC(skin, lines); // Then let the library generate the necessary packets. diff --git a/api/pom.xml b/api/pom.xml index 3f4c2b3..0404f9c 100755 --- a/api/pom.xml +++ b/api/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib - 1.3 + 1.4 npclib-api diff --git a/commons/pom.xml b/commons/pom.xml index 952033b..ee0e809 100755 --- a/commons/pom.xml +++ b/commons/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib - 1.3 + 1.4 npclib-commons diff --git a/nms/pom.xml b/nms/pom.xml index 39613f0..7aa51d8 100755 --- a/nms/pom.xml +++ b/nms/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib - 1.3 + 1.4 npclib-nms diff --git a/nms/v1_10_R1/pom.xml b/nms/v1_10_R1/pom.xml index d59f6a9..30ace41 100755 --- a/nms/v1_10_R1/pom.xml +++ b/nms/v1_10_R1/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_10_R1 diff --git a/nms/v1_11_R1/pom.xml b/nms/v1_11_R1/pom.xml index e38a305..98a3ee5 100755 --- a/nms/v1_11_R1/pom.xml +++ b/nms/v1_11_R1/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_11_R1 diff --git a/nms/v1_12_R1/pom.xml b/nms/v1_12_R1/pom.xml index 09b3df4..1203094 100755 --- a/nms/v1_12_R1/pom.xml +++ b/nms/v1_12_R1/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_12_R1 diff --git a/nms/v1_13_R1/pom.xml b/nms/v1_13_R1/pom.xml index 45a1e74..271c83d 100755 --- a/nms/v1_13_R1/pom.xml +++ b/nms/v1_13_R1/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_13_R1 diff --git a/nms/v1_13_R2/pom.xml b/nms/v1_13_R2/pom.xml index c3651fc..f7d67a5 100755 --- a/nms/v1_13_R2/pom.xml +++ b/nms/v1_13_R2/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_13_R2 diff --git a/nms/v1_7_R4/pom.xml b/nms/v1_7_R4/pom.xml index 5324123..9cbf492 100755 --- a/nms/v1_7_R4/pom.xml +++ b/nms/v1_7_R4/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_7_R4 @@ -25,11 +25,5 @@ 2.8.5 compile - - io.netty - netty-all - 4.0.23.Final - compile - diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java index 1cfbdc1..bb5cd9d 100755 --- a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java +++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java @@ -36,6 +36,7 @@ public class NPC_v1_7_R4 extends NPC { public NPC_v1_7_R4(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { super(plugin, skin, autoHideDistance, lines); + // TODO: Add multi-line text support. this.name = lines.get(0); } diff --git a/nms/v1_8_R1/pom.xml b/nms/v1_8_R1/pom.xml index 25d62d1..7adb9ec 100755 --- a/nms/v1_8_R1/pom.xml +++ b/nms/v1_8_R1/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_8_R1 diff --git a/nms/v1_8_R2/pom.xml b/nms/v1_8_R2/pom.xml index 4936191..feda596 100755 --- a/nms/v1_8_R2/pom.xml +++ b/nms/v1_8_R2/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_8_R2 diff --git a/nms/v1_8_R3/pom.xml b/nms/v1_8_R3/pom.xml index 3445740..cfdf521 100755 --- a/nms/v1_8_R3/pom.xml +++ b/nms/v1_8_R3/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_8_R3 diff --git a/nms/v1_9_R1/pom.xml b/nms/v1_9_R1/pom.xml index 1e450c9..550baf2 100755 --- a/nms/v1_9_R1/pom.xml +++ b/nms/v1_9_R1/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_9_R1 diff --git a/nms/v1_9_R2/pom.xml b/nms/v1_9_R2/pom.xml index 62d69bc..e5aaeb3 100755 --- a/nms/v1_9_R2/pom.xml +++ b/nms/v1_9_R2/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib-nms - 1.3 + 1.4 npclib-nms-v1_9_R2 diff --git a/plugin/pom.xml b/plugin/pom.xml index f9f3393..8e2e1fc 100755 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -7,7 +7,7 @@ net.jitse npclib - 1.3 + 1.4 npclib-plugin diff --git a/pom.xml b/pom.xml index 2987d62..5e9bb07 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ net.jitse npclib - 1.3 + 1.4 NPCLib https://github.com/JitseB/NPCLib From 45f64ff31a7c865c93538685e974ee52fd822a71 Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Fri, 15 Feb 2019 20:19:40 +0100 Subject: [PATCH 9/9] Fixed travis file (#10). --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b3d3c84..f4a42f3 100755 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ cache: install: - wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar - wget http://central.maven.org/maven2/io/netty/netty-all/4.1.33.Final/netty-all-4.1.33.Final.jar - mvn install:install-file -Dfile=netty-all-4.1.33.Final.jar -DgroupId=io.netty -DartifactId=netty-all -Dversion=4.1.33.Final -Dpackaging=jar +- mvn install:install-file -Dfile=netty-all-4.1.33.Final.jar -DgroupId=io.netty -DartifactId=netty-all -Dversion=4.1.33.Final -Dpackaging=jar - wget https://github.com/Sarabveer/CraftBukkit-Spigot-Binary/blob/master/spigot-1.7.10-R0.1/spigot-1.7.10-R0.1-1649.jar - mvn install:install-file -Dfile=spigot-1.7.10-R0.1-1649.jar -DgroupId=org.spigotmc -DartifactId=spigot -Dversion=1.7.10-R0.1-SNAPSHOT -Dpackaging=jar - ls $HOME/.m2/repository/org/spigotmc/spigot/1.8-R0.1-SNAPSHOT >> /dev/null 2>&1 || java -jar BuildTools.jar --rev 1.8 >> /dev/null 2>&1