diff --git a/commons/pom.xml b/commons/pom.xml
index f7e75d9..952033b 100755
--- a/commons/pom.xml
+++ b/commons/pom.xml
@@ -16,8 +16,16 @@
org.spigotmc
spigot
- 1.13.2-R0.1-SNAPSHOT
+ 1.7.10-R0.1-SNAPSHOT
provided
+
+
+ io.netty
+ netty-all
+ 4.1.33.Final
+ provided
+
+
diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java b/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java
new file mode 100755
index 0000000..105a00d
--- /dev/null
+++ b/commons/src/main/java/com/comphenix/tinyprotocol/LegacyTinyProtocol.java
@@ -0,0 +1,515 @@
+package com.comphenix.tinyprotocol;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.MapMaker;
+import net.minecraft.util.com.mojang.authlib.GameProfile;
+import net.minecraft.util.io.netty.channel.*;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.server.PluginDisableEvent;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+
+/**
+ * Represents a very tiny alternative to ProtocolLib.
+ *
+ * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)!
+ *
+ * @author Kristian
+ */
+public abstract class LegacyTinyProtocol {
+ private static final AtomicInteger ID = new AtomicInteger(0);
+
+ // Used in order to lookup a channel
+ private static final Reflection.MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
+ private static final Reflection.FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class);
+ private static final Reflection.FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class);
+ private static final Reflection.FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0);
+
+ // Looking up ServerConnection
+ private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer");
+ private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection");
+ private static final Reflection.FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0);
+ private static final Reflection.FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0);
+ private static final Reflection.MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass);
+
+ // Packets we have to intercept
+ private static final Class> PACKET_SET_PROTOCOL = Reflection.getMinecraftClass("PacketHandshakingInSetProtocol");
+ private static final Class> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
+ private static final Reflection.FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
+ private static final Reflection.FieldAccessor protocolId = Reflection.getField(PACKET_SET_PROTOCOL, int.class, 0);
+ private static final Reflection.FieldAccessor protocolType = Reflection.getField(PACKET_SET_PROTOCOL, Enum.class, 0);
+
+
+ // Speedup channel lookup
+ private Map channelLookup = new MapMaker().weakValues().makeMap();
+ private Map protocolLookup = new MapMaker().weakKeys().makeMap();
+ private Listener listener;
+
+ // Channels that have already been removed
+ private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
+
+ // List of network markers
+ private List networkManagers;
+
+ // Injected channel handlers
+ private List serverChannels = Lists.newArrayList();
+ private ChannelInboundHandlerAdapter serverChannelHandler;
+ private ChannelInitializer beginInitProtocol;
+ private ChannelInitializer endInitProtocol;
+
+ // Current handler name
+ private String handlerName;
+
+ protected volatile boolean closed;
+ protected Plugin plugin;
+
+ /**
+ * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients.
+ *
+ * You can construct multiple instances per plugin.
+ *
+ * @param plugin - the plugin.
+ */
+ public LegacyTinyProtocol(final Plugin plugin) {
+ this.plugin = plugin;
+
+ // Compute handler name
+ this.handlerName = getHandlerName();
+
+ // Prepare existing players
+ registerBukkitEvents();
+
+ try {
+ System.out.println("Attempting to inject into netty");
+ registerChannelHandler();
+ registerPlayers(plugin);
+ } catch (IllegalArgumentException ex) {
+ // Damn you, late bind
+ plugin.getLogger().info("Attempting to delay injection.");
+
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ registerChannelHandler();
+ registerPlayers(plugin);
+ plugin.getLogger().info("Injection complete.");
+ }
+ }.runTask(plugin);
+ }
+ }
+
+ private void createServerChannelHandler() {
+ // Handle connected channels
+ endInitProtocol = new ChannelInitializer() {
+
+ @Override
+ protected void initChannel(Channel channel) throws Exception {
+ try {
+ // This can take a while, so we need to stop the main thread from interfering
+ synchronized (networkManagers) {
+ // Stop injecting channels
+ if (!closed) {
+ channel.eventLoop().submit(() -> injectChannelInternal(channel));
+ }
+ }
+ } catch (Exception e) {
+ plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
+ }
+ }
+
+ };
+
+ // This is executed before Minecraft's channel handler
+ beginInitProtocol = new ChannelInitializer() {
+
+ @Override
+ protected void initChannel(Channel channel) throws Exception {
+ channel.pipeline().addLast(endInitProtocol);
+ }
+
+ };
+
+ serverChannelHandler = new ChannelInboundHandlerAdapter() {
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+ Channel channel = (Channel) msg;
+
+ channel.pipeline().addFirst(beginInitProtocol);
+ ctx.fireChannelRead(msg);
+ }
+
+ };
+ }
+
+ /**
+ * Register bukkit events.
+ */
+ private void registerBukkitEvents() {
+ listener = new Listener() {
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public final void onPlayerLogin(PlayerJoinEvent e) {
+ if (closed)
+ return;
+
+ Channel channel = getChannel(e.getPlayer());
+
+ // Don't inject players that have been explicitly uninjected
+ if (!uninjectedChannels.contains(channel)) {
+ injectPlayer(e.getPlayer());
+ }
+ }
+
+ @EventHandler
+ public final void onPluginDisable(PluginDisableEvent e) {
+ if (e.getPlugin().equals(plugin)) {
+ close();
+ }
+ }
+
+ };
+
+ plugin.getServer().getPluginManager().registerEvents(listener, plugin);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void registerChannelHandler() {
+ Object mcServer = getMinecraftServer.get(Bukkit.getServer());
+ Object serverConnection = getServerConnection.get(mcServer);
+ boolean looking = true;
+
+ // We need to synchronize against this list
+ networkManagers = (List) getNetworkMarkers.invoke(null, serverConnection);
+ createServerChannelHandler();
+
+ // Find the correct list, or implicitly throw an exception
+ for (int i = 0; looking; i++) {
+ List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
+
+ for (Object item : list) {
+ //if (!ChannelFuture.class.isInstance(item))
+ // break;
+
+ // Channel future that contains the server connection
+ Channel serverChannel = ((ChannelFuture) item).channel();
+
+ serverChannels.add(serverChannel);
+ ;
+ serverChannel.pipeline().addFirst(serverChannelHandler);
+ System.out.println("Server channel handler injected (" + serverChannel + ")");
+ looking = false;
+ }
+ }
+ }
+
+ private void unregisterChannelHandler() {
+ if (serverChannelHandler == null)
+ return;
+
+ for (Channel serverChannel : serverChannels) {
+ final ChannelPipeline pipeline = serverChannel.pipeline();
+
+ // Remove channel handler
+ serverChannel.eventLoop().execute(() -> {
+ try {
+ pipeline.remove(serverChannelHandler);
+ } catch (NoSuchElementException e) {
+ // That's fine
+ }
+ });
+ }
+ }
+
+ private void registerPlayers(Plugin plugin) {
+ for (Player player : plugin.getServer().getOnlinePlayers()) {
+ injectPlayer(player);
+ }
+ }
+
+ /**
+ * Invoked when the server is starting to send a packet to a player.
+ *
+ * Note that this is not executed on the main thread.
+ *
+ * @param receiver - the receiving player, NULL for early login/status packets.
+ * @param packet - the packet being sent.
+ * @return The packet to send instead, or NULL to cancel the transmission.
+ */
+ public Object onPacketOutAsync(Player receiver, Object packet) {
+ return packet;
+ }
+
+ /**
+ * Invoked when the server has received a packet from a given player.
+ *
+ * Use {@link Channel#remoteAddress()} to get the remote address of the client.
+ *
+ * @param sender - the player that sent the packet, NULL for early login/status packets.
+ * @param packet - the packet being received.
+ * @return The packet to recieve instead, or NULL to cancel.
+ */
+ public Object onPacketInAsync(Player sender, Object packet) {
+ return packet;
+ }
+
+ /**
+ * Send a packet to a particular player.
+ *
+ * Note that {@link #onPacketOutAsync(Player, Object)} will be invoked with this packet.
+ *
+ * @param player - the destination player.
+ * @param packet - the packet to send.
+ */
+ public void sendPacket(Player player, Object packet) {
+ sendPacket(getChannel(player), packet);
+ }
+
+ /**
+ * Send a packet to a particular client.
+ *
+ * Note that {@link #onPacketOutAsync(Player, Object)} will be invoked with this packet.
+ *
+ * @param channel - client identified by a channel.
+ * @param packet - the packet to send.
+ */
+ public void sendPacket(Channel channel, Object packet) {
+ channel.pipeline().writeAndFlush(packet);
+ }
+
+ /**
+ * Pretend that a given packet has been received from a player.
+ *
+ * Note that {@link #onPacketInAsync(Player, Object)} will be invoked with this packet.
+ *
+ * @param player - the player that sent the packet.
+ * @param packet - the packet that will be received by the server.
+ */
+ public void receivePacket(Player player, Object packet) {
+ receivePacket(getChannel(player), packet);
+ }
+
+ /**
+ * Pretend that a given packet has been received from a given client.
+ *
+ * Note that {@link #onPacketInAsync(Player, Object)} will be invoked with this packet.
+ *
+ * @param channel - client identified by a channel.
+ * @param packet - the packet that will be received by the server.
+ */
+ public void receivePacket(Channel channel, Object packet) {
+ channel.pipeline().context("encoder").fireChannelRead(packet);
+ }
+
+ /**
+ * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID.
+ *
+ * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances.
+ *
+ * @return A unique channel handler name.
+ */
+ protected String getHandlerName() {
+ return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet();
+ }
+
+ /**
+ * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
+ *
+ * This will automatically be called when a player has logged in.
+ *
+ * @param player - the player to inject.
+ */
+ public void injectPlayer(Player player) {
+ injectChannelInternal(getChannel(player)).player = player;
+ }
+
+ /**
+ * Add a custom channel handler to the given channel.
+ *
+ * @param channel - the channel to inject.
+ * @return The intercepted channel, or NULL if it has already been injected.
+ */
+ public void injectChannel(Channel channel) {
+ injectChannelInternal(channel);
+ }
+
+ /**
+ * Add a custom channel handler to the given channel.
+ *
+ * @param channel - the channel to inject.
+ * @return The packet interceptor.
+ */
+ private PacketInterceptor injectChannelInternal(Channel channel) {
+ try {
+ PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName);
+
+ // Inject our packet interceptor
+ if (interceptor == null) {
+ interceptor = new PacketInterceptor();
+ channel.pipeline().addBefore("packet_handler", handlerName, interceptor);
+ uninjectedChannels.remove(channel);
+ }
+
+ return interceptor;
+ } catch (IllegalArgumentException e) {
+ // Try again
+ return (PacketInterceptor) channel.pipeline().get(handlerName);
+ }
+ }
+
+ /**
+ * Retrieve the Netty channel associated with a player. This is cached.
+ *
+ * @param player - the player.
+ * @return The Netty channel.
+ */
+ public Channel getChannel(Player player) {
+ Channel channel = channelLookup.get(player.getName());
+
+ // Lookup channel again
+ if (channel == null) {
+ Object connection = getConnection.get(getPlayerHandle.invoke(player));
+ Object manager = getManager.get(connection);
+
+ channelLookup.put(player.getName(), channel = getChannel.get(manager));
+ }
+
+ return channel;
+ }
+
+ public int getProtocolVersion(Player player) {
+ Channel channel = channelLookup.get(player.getName());
+
+ // Lookup channel again
+ if (channel == null) {
+ Object connection = getConnection.get(getPlayerHandle.invoke(player));
+ Object manager = getManager.get(connection);
+
+ channelLookup.put(player.getName(), channel = getChannel.get(manager));
+ }
+
+ return protocolLookup.get(channel);
+ }
+
+ /**
+ * Uninject a specific player.
+ *
+ * @param player - the injected player.
+ */
+ public void uninjectPlayer(Player player) {
+ uninjectChannel(getChannel(player));
+ }
+
+ /**
+ * Uninject a specific channel.
+ *
+ * This will also disable the automatic channel injection that occurs when a player has properly logged in.
+ *
+ * @param channel - the injected channel.
+ */
+ public void uninjectChannel(final Channel channel) {
+ // No need to guard against this if we're closing
+ if (!closed) {
+ uninjectedChannels.add(channel);
+ }
+
+ // See ChannelInjector in ProtocolLib, line 590
+ channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
+ }
+
+ /**
+ * Determine if the given player has been injected by TinyProtocol.
+ *
+ * @param player - the player.
+ * @return TRUE if it is, FALSE otherwise.
+ */
+ public boolean hasInjected(Player player) {
+ return hasInjected(getChannel(player));
+ }
+
+ /**
+ * Determine if the given channel has been injected by TinyProtocol.
+ *
+ * @param channel - the channel.
+ * @return TRUE if it is, FALSE otherwise.
+ */
+ public boolean hasInjected(Channel channel) {
+ return channel.pipeline().get(handlerName) != null;
+ }
+
+ /**
+ * Cease listening for packets. This is called automatically when your plugin is disabled.
+ */
+ public final void close() {
+ if (!closed) {
+ closed = true;
+
+ // Remove our handlers
+ for (Player player : plugin.getServer().getOnlinePlayers()) {
+ uninjectPlayer(player);
+ }
+
+ // Clean up Bukkit
+ HandlerList.unregisterAll(listener);
+ unregisterChannelHandler();
+ }
+ }
+
+ /**
+ * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
+ *
+ * @author Kristian
+ */
+ private final class PacketInterceptor extends ChannelDuplexHandler {
+ // Updated by the login event
+ public volatile Player player;
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+ // Intercept channel
+ final Channel channel = ctx.channel();
+ if (PACKET_LOGIN_IN_START.isInstance(msg)) {
+ GameProfile profile = getGameProfile.get(msg);
+ channelLookup.put(profile.getName(), channel);
+ } else if (PACKET_SET_PROTOCOL.isInstance(msg)) {
+ String protocol = protocolType.get(msg).name();
+ if (protocol.equalsIgnoreCase("LOGIN")) {
+ protocolLookup.put(channel, protocolId.get(msg));
+ }
+ }
+
+ try {
+ msg = onPacketInAsync(player, msg);
+ } catch (Exception e) {
+ plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
+ }
+
+ if (msg != null) {
+ super.channelRead(ctx, msg);
+ }
+ }
+
+ @Override
+ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+ try {
+ msg = onPacketOutAsync(player, msg);
+ } catch (Exception e) {
+ plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
+ }
+
+ if (msg != null) {
+ super.write(ctx, msg, promise);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java
index 5623c08..2198573 100755
--- a/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java
+++ b/commons/src/main/java/com/comphenix/tinyprotocol/TinyProtocol.java
@@ -4,7 +4,6 @@ import com.comphenix.tinyprotocol.Reflection.FieldAccessor;
import com.comphenix.tinyprotocol.Reflection.MethodInvoker;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
-import com.mojang.authlib.GameProfile;
import io.netty.channel.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -46,14 +45,15 @@ public abstract class TinyProtocol {
// Packets we have to intercept
private static final Class> PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart");
- private static final FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
+ private static final FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START,
+ Reflection.getClass("com.mojang.authlib.GameProfile"), 0);
// Speedup channel lookup
private Map channelLookup = new MapMaker().weakValues().makeMap();
private Listener listener;
// Channels that have already been removed
- private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
+ private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
// List of network markers
private List networkManagers;
@@ -339,6 +339,7 @@ public abstract class TinyProtocol {
* Add a custom channel handler to the given channel.
*
* @param channel - the channel to inject.
+ * @return The intercepted channel, or NULL if it has already been injected.
*/
public void injectChannel(Channel channel) {
injectChannelInternal(channel);
@@ -411,7 +412,14 @@ public abstract class TinyProtocol {
}
// See ChannelInjector in ProtocolLib, line 590
- channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
+ channel.eventLoop().execute(new Runnable() {
+
+ @Override
+ public void run() {
+ channel.pipeline().remove(handlerName);
+ }
+
+ });
}
/**
@@ -493,8 +501,8 @@ public abstract class TinyProtocol {
private void handleLoginStart(Channel channel, Object packet) {
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
- GameProfile profile = getGameProfile.get(packet);
- channelLookup.put(profile.getName(), channel);
+ Object profile = getGameProfile.get(packet);
+ channelLookup.put((String) Reflection.getMethod(profile.getClass(), "getName").invoke(profile), channel);
}
}
}
diff --git a/commons/src/main/java/net/jitse/npclib/NPCLib.java b/commons/src/main/java/net/jitse/npclib/NPCLib.java
index 2ebfa9e..43b541a 100755
--- a/commons/src/main/java/net/jitse/npclib/NPCLib.java
+++ b/commons/src/main/java/net/jitse/npclib/NPCLib.java
@@ -6,9 +6,11 @@ package net.jitse.npclib;
import net.jitse.npclib.api.NPC;
import net.jitse.npclib.listeners.ChunkListener;
+import net.jitse.npclib.listeners.LegacyPacketListener;
import net.jitse.npclib.listeners.PacketListener;
import net.jitse.npclib.listeners.PlayerListener;
import net.jitse.npclib.skin.Skin;
+import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.plugin.PluginManager;
@@ -64,7 +66,12 @@ public class NPCLib {
pluginManager.registerEvents(new PlayerListener(), plugin);
pluginManager.registerEvents(new ChunkListener(), plugin);
- new PacketListener().start(plugin);
+ // Boot the according packet listener.
+ if (Bukkit.getBukkitVersion().contains("1.7")) {
+ new LegacyPacketListener().start(plugin);
+ } else {
+ new PacketListener().start(plugin);
+ }
}
/**
diff --git a/commons/src/main/java/net/jitse/npclib/api/NPC.java b/commons/src/main/java/net/jitse/npclib/api/NPC.java
index af7d786..5d3d59d 100755
--- a/commons/src/main/java/net/jitse/npclib/api/NPC.java
+++ b/commons/src/main/java/net/jitse/npclib/api/NPC.java
@@ -4,9 +4,8 @@
package net.jitse.npclib.api;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
import net.jitse.npclib.NPCManager;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.jitse.npclib.events.NPCDestroyEvent;
import net.jitse.npclib.events.NPCSpawnEvent;
import net.jitse.npclib.events.trigger.TriggerType;
@@ -39,7 +38,7 @@ public abstract class NPC implements PacketHandler, ActionHandler {
protected final List lines;
protected JavaPlugin plugin;
- protected GameProfile gameProfile;
+ protected GameProfileWrapper gameProfile;
protected Location location;
public NPC(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) {
@@ -51,11 +50,11 @@ public abstract class NPC implements PacketHandler, ActionHandler {
NPCManager.add(this);
}
- protected GameProfile generateGameProfile(UUID uuid, String name) {
- GameProfile gameProfile = new GameProfile(uuid, name);
+ protected GameProfileWrapper generateGameProfile(UUID uuid, String name) {
+ GameProfileWrapper gameProfile = new GameProfileWrapper(uuid, name);
if (skin != null) {
- gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
+ gameProfile.addSkin(skin);
}
return gameProfile;
diff --git a/commons/src/main/java/net/jitse/npclib/api/wrapper/GameProfileWrapper.java b/commons/src/main/java/net/jitse/npclib/api/wrapper/GameProfileWrapper.java
new file mode 100644
index 0000000..5443ac1
--- /dev/null
+++ b/commons/src/main/java/net/jitse/npclib/api/wrapper/GameProfileWrapper.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018 Jitse Boonstra
+ */
+
+package net.jitse.npclib.api.wrapper;
+
+import com.comphenix.tinyprotocol.Reflection;
+import com.google.common.collect.ForwardingMultimap;
+import net.jitse.npclib.skin.Skin;
+import org.bukkit.Bukkit;
+
+import java.util.UUID;
+
+public class GameProfileWrapper {
+
+ // Written because of issue#10 (https://github.com/JitseB/NPCLib/issues/10).
+ // This class acts as an NMS reflection wrapper for the GameProfileWrapper class.
+
+ // TODO: Add this class to the v1_7_R4 module of NPCLib.
+
+ private final boolean is1_7 = Bukkit.getBukkitVersion().contains("1.7");
+ private final Class> gameProfileClazz = Reflection.getClass((is1_7 ? "net.minecraft.util." : "") + "com.mojang.authlib.GameProfile");
+
+ Object gameProfile;
+
+ public GameProfileWrapper(UUID uuid, String name) {
+ // Only need to check if the version is 1.7, as NPCLib doesn't support any version below this version.
+ this.gameProfile = Reflection.getConstructor(gameProfileClazz, UUID.class, String.class).invoke(uuid, name);
+ }
+
+ public void addSkin(Skin skin) {
+ // Create a new property with the skin data.
+ Class> propertyClazz = Reflection.getClass((is1_7 ? "net.minecraft.util." : "") + "com.mojang.authlib.properties.Property");
+ Object property = Reflection.getConstructor(propertyClazz,
+ String.class, String.class, String.class).invoke("textures", skin.getValue(), skin.getSignature());
+
+ // Get the property map from the GameProfileWrapper object.
+ Class> propertyMapClazz = Reflection.getClass((is1_7 ? "net.minecraft.util." : "") + "com.mojang.authlib.properties.PropertyMap");
+ Reflection.FieldAccessor propertyMapGetter = Reflection.getField(gameProfileClazz, "properties",
+ propertyMapClazz);
+ Object propertyMap = propertyMapGetter.get(gameProfile);
+
+ // Add our new property to the property map.
+ Reflection.getMethod(ForwardingMultimap.class, "put", Object.class, Object.class)
+ .invoke(propertyMap, "textures", property);
+
+ // Finally set the property map back in the GameProfileWrapper object.
+ propertyMapGetter.set(gameProfile, propertyMap);
+ }
+
+ public Object getGameProfile() {
+ return gameProfile;
+ }
+}
diff --git a/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java
new file mode 100755
index 0000000..fcbdc81
--- /dev/null
+++ b/commons/src/main/java/net/jitse/npclib/listeners/LegacyPacketListener.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018 Jitse Boonstra
+ */
+
+package net.jitse.npclib.listeners;
+
+import com.comphenix.tinyprotocol.LegacyTinyProtocol;
+import com.comphenix.tinyprotocol.Reflection;
+import net.jitse.npclib.NPCManager;
+import net.jitse.npclib.api.NPC;
+import net.jitse.npclib.events.NPCInteractEvent;
+import net.jitse.npclib.events.click.ClickType;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author Jitse Boonstra
+ */
+public class LegacyPacketListener {
+
+ // Classes:
+ private final Class> packetPlayInUseEntityClazz = Reflection.getMinecraftClass("PacketPlayInUseEntity");
+
+ // Fields:
+ private final Reflection.FieldAccessor entityIdField = Reflection.getField(packetPlayInUseEntityClazz, "a", int.class);
+ private final Reflection.FieldAccessor actionField = Reflection.getField(packetPlayInUseEntityClazz, "action", Object.class);
+
+ // Prevent players from clicking at very high speeds.
+ private final Set delay = new HashSet<>();
+
+ public void start(JavaPlugin plugin) {
+ new LegacyTinyProtocol(plugin) {
+
+ @Override
+ public Object onPacketInAsync(Player player, Object packet) {
+
+ if (packetPlayInUseEntityClazz.isInstance(packet)) {
+ NPC npc = NPCManager.getAllNPCs().stream().filter(
+ check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet))
+ .findFirst().orElse(null);
+
+ if (npc == null) {
+ // Default player, not doing magic with the packet.
+ return super.onPacketInAsync(player, packet);
+ }
+
+ if (delay.contains(player.getUniqueId())) {
+ return null;
+ }
+
+ ClickType clickType = actionField.get(packet).toString()
+ .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK;
+
+ Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc));
+
+ UUID uuid = player.getUniqueId();
+ delay.add(uuid);
+ Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid));
+ return null;
+ }
+
+ return super.onPacketInAsync(player, packet);
+ }
+ };
+ }
+}
diff --git a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java
index e3e3857..cb07d28 100755
--- a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java
+++ b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java
@@ -5,6 +5,14 @@
package net.jitse.npclib.listeners;
import com.comphenix.tinyprotocol.Reflection;
+import com.comphenix.tinyprotocol.TinyProtocol;
+import io.netty.channel.Channel;
+import net.jitse.npclib.NPCManager;
+import net.jitse.npclib.api.NPC;
+import net.jitse.npclib.events.NPCInteractEvent;
+import net.jitse.npclib.events.click.ClickType;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.HashSet;
@@ -27,38 +35,38 @@ public class PacketListener {
private final Set delay = new HashSet<>();
public void start(JavaPlugin plugin) {
-// new TinyProtocol(plugin) {
-//
-// @Override
-// public Object onPacketInAsync(Player player, Channel channel, Object packet) {
-//
-// if (packetPlayInUseEntityClazz.isInstance(packet)) {
-// NPC npc = NPCManager.getAllNPCs().stream().filter(
-// check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet))
-// .findFirst().orElse(null);
-//
-// if (npc == null) {
-// // Default player, not doing magic with the packet.
-// return super.onPacketInAsync(player, channel, packet);
-// }
-//
-// if (delay.contains(player.getUniqueId())) {
-// return null;
-// }
-//
-// ClickType clickType = actionField.get(packet).toString()
-// .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK;
-//
-// Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc));
-//
-// UUID uuid = player.getUniqueId();
-// delay.add(uuid);
-// Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid));
-// return null;
-// }
-//
-// return super.onPacketInAsync(player, channel, packet);
-// }
-// };
+ new TinyProtocol(plugin) {
+
+ @Override
+ public Object onPacketInAsync(Player player, Channel channel, Object packet) {
+
+ if (packetPlayInUseEntityClazz.isInstance(packet)) {
+ NPC npc = NPCManager.getAllNPCs().stream().filter(
+ check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet))
+ .findFirst().orElse(null);
+
+ if (npc == null) {
+ // Default player, not doing magic with the packet.
+ return super.onPacketInAsync(player, channel, packet);
+ }
+
+ if (delay.contains(player.getUniqueId())) {
+ return null;
+ }
+
+ ClickType clickType = actionField.get(packet).toString()
+ .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK;
+
+ Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc));
+
+ UUID uuid = player.getUniqueId();
+ delay.add(uuid);
+ Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid));
+ return null;
+ }
+
+ return super.onPacketInAsync(player, channel, packet);
+ }
+ };
}
}
diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java
index d07e54a..d5a77df 100755
--- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_10_R1.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_10_R1.EnumGamemode;
import net.minecraft.server.v1_10_R1.IChatBaseComponent;
import net.minecraft.server.v1_10_R1.PacketPlayOutPlayerInfo;
@@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper {
private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz,
packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class);
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java
index 52413e5..cb2a3de 100755
--- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_11_R1.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_11_R1.EnumGamemode;
import net.minecraft.server.v1_11_R1.IChatBaseComponent;
import net.minecraft.server.v1_11_R1.PacketPlayOutPlayerInfo;
@@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper {
private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz,
packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class);
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java
index f13a0a4..e24f311 100755
--- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_12_R1.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_12_R1.EnumGamemode;
import net.minecraft.server.v1_12_R1.IChatBaseComponent;
import net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo;
@@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper {
private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz,
packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class);
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java
index 578efb0..24b0d6a 100755
--- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_13_R1.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_13_R1.EnumGamemode;
import net.minecraft.server.v1_13_R1.IChatBaseComponent;
import net.minecraft.server.v1_13_R1.PacketPlayOutPlayerInfo;
@@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper {
private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz,
packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class);
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java
index 79e1fbb..bd8103d 100755
--- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_13_R2.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_13_R2.EnumGamemode;
import net.minecraft.server.v1_13_R2.IChatBaseComponent;
import net.minecraft.server.v1_13_R2.PacketPlayOutPlayerInfo;
@@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper {
private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz,
packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, EnumGamemode.class, IChatBaseComponent.class);
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java
index 283b46e..bab9bfb 100755
--- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_8_R1.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_8_R1.*;
import java.util.List;
@@ -15,7 +16,9 @@ import java.util.List;
*/
public class PacketPlayOutPlayerInfoWrapper {
- public PacketPlayOutPlayerInfo create(EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java
index bca9688..9afaaca 100755
--- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_8_R2.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_8_R2.IChatBaseComponent;
import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo;
import net.minecraft.server.v1_8_R2.WorldSettings;
@@ -17,7 +18,9 @@ import java.util.List;
*/
public class PacketPlayOutPlayerInfoWrapper {
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java
index 3c411df..24a7cc0 100755
--- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_8_R3.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_8_R3.IChatBaseComponent;
import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo;
import net.minecraft.server.v1_8_R3.WorldSettings;
@@ -17,7 +18,9 @@ import java.util.List;
*/
public class PacketPlayOutPlayerInfoWrapper {
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java
index 43695c7..0f9a478 100755
--- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_9_R1.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_9_R1.IChatBaseComponent;
import net.minecraft.server.v1_9_R1.PacketPlayOutPlayerInfo;
import net.minecraft.server.v1_9_R1.WorldSettings;
@@ -18,7 +19,9 @@ import java.util.List;
*/
public class PacketPlayOutPlayerInfoWrapper {
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);
diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java
index 67afd64..6ba09e6 100755
--- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java
+++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -6,6 +6,7 @@ package net.jitse.npclib.nms.v1_9_R2.packets;
import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
+import net.jitse.npclib.api.wrapper.GameProfileWrapper;
import net.minecraft.server.v1_9_R2.IChatBaseComponent;
import net.minecraft.server.v1_9_R2.PacketPlayOutPlayerInfo;
import net.minecraft.server.v1_9_R2.WorldSettings;
@@ -23,7 +24,9 @@ public class PacketPlayOutPlayerInfoWrapper {
private final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClazz,
packetPlayOutPlayerInfoClazz, GameProfile.class, int.class, WorldSettings.EnumGamemode.class, IChatBaseComponent.class);
- public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfile gameProfile, String name) {
+ public PacketPlayOutPlayerInfo create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action, GameProfileWrapper gameProfileWrapper, String name) {
+ GameProfile gameProfile = (GameProfile) gameProfileWrapper.getGameProfile();
+
PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
Reflection.getField(packetPlayOutPlayerInfo.getClass(), "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class)
.set(packetPlayOutPlayerInfo, action);