From ddf90fe005d1c68305d2b8d5cd9b96f6d6ff0a56 Mon Sep 17 00:00:00 2001 From: Jitse Boonstra Date: Tue, 11 Dec 2018 21:51:37 +0100 Subject: [PATCH] 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