list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
for (Object item : list) {
- if (!ChannelFuture.class.isInstance(item))
+ if (!(item instanceof ChannelFuture))
break;
// Channel future that contains the server connection
@@ -216,17 +208,12 @@ public abstract class TinyProtocol {
final ChannelPipeline pipeline = serverChannel.pipeline();
// Remove channel handler
- serverChannel.eventLoop().execute(new Runnable() {
-
- @Override
- public void run() {
- try {
- pipeline.remove(serverChannelHandler);
- } catch (NoSuchElementException e) {
- // That's fine
- }
+ serverChannel.eventLoop().execute(() -> {
+ try {
+ pipeline.remove(serverChannelHandler);
+ } catch (NoSuchElementException e) {
+ // That's fine
}
-
});
}
}
@@ -237,119 +224,14 @@ public abstract class TinyProtocol {
}
}
- /**
- * Invoked when the server is starting to send a packet to a player.
- *
- * Note that this is not executed on the main thread.
- *
- * @param receiver - the receiving player, NULL for early login/status packets.
- * @param channel - the channel that received the packet. Never NULL.
- * @param packet - the packet being sent.
- * @return The packet to send instead, or NULL to cancel the transmission.
- */
- public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
+ public Object onPacketInAsync(Player sender, Object packet) {
return packet;
}
- /**
- * Invoked when the server has received a packet from a given player.
- *
- * Use {@link Channel#remoteAddress()} to get the remote address of the client.
- *
- * @param sender - the player that sent the packet, NULL for early login/status packets.
- * @param channel - channel that received the packet. Never NULL.
- * @param packet - the packet being received.
- * @return The packet to recieve instead, or NULL to cancel.
- */
- public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
- return packet;
- }
-
- /**
- * Send a packet to a particular player.
- *
- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
- *
- * @param player - the destination player.
- * @param packet - the packet to send.
- */
- public void sendPacket(Player player, Object packet) {
- sendPacket(getChannel(player), packet);
- }
-
- /**
- * Send a packet to a particular client.
- *
- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet.
- *
- * @param channel - client identified by a channel.
- * @param packet - the packet to send.
- */
- public void sendPacket(Channel channel, Object packet) {
- channel.pipeline().writeAndFlush(packet);
- }
-
- /**
- * Pretend that a given packet has been received from a player.
- *
- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
- *
- * @param player - the player that sent the packet.
- * @param packet - the packet that will be received by the server.
- */
- public void receivePacket(Player player, Object packet) {
- receivePacket(getChannel(player), packet);
- }
-
- /**
- * Pretend that a given packet has been received from a given client.
- *
- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet.
- *
- * @param channel - client identified by a channel.
- * @param packet - the packet that will be received by the server.
- */
- public void receivePacket(Channel channel, Object packet) {
- channel.pipeline().context("encoder").fireChannelRead(packet);
- }
-
- /**
- * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID.
- *
- * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances.
- *
- * @return A unique channel handler name.
- */
- protected String getHandlerName() {
- return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet();
- }
-
- /**
- * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets.
- *
- * This will automatically be called when a player has logged in.
- *
- * @param player - the player to inject.
- */
- public void injectPlayer(Player player) {
+ private void injectPlayer(Player player) {
injectChannelInternal(getChannel(player)).player = player;
}
- /**
- * Add a custom channel handler to the given channel.
- *
- * @param channel - the channel to inject.
- */
- 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);
@@ -368,13 +250,7 @@ public abstract class TinyProtocol {
}
}
- /**
- * Retrieve the Netty channel associated with a player. This is cached.
- *
- * @param player - the player.
- * @return The Netty channel.
- */
- public Channel getChannel(Player player) {
+ private Channel getChannel(Player player) {
Channel channel = channelLookup.get(player.getName());
// Lookup channel again
@@ -388,62 +264,20 @@ public abstract class TinyProtocol {
return channel;
}
- /**
- * Uninject a specific player.
- *
- * @param player - the injected player.
- */
- public void uninjectPlayer(Player player) {
- uninjectChannel(getChannel(player));
- }
-
- /**
- * Uninject a specific channel.
- *
- * This will also disable the automatic channel injection that occurs when a player has properly logged in.
- *
- * @param channel - the injected channel.
- */
- public void uninjectChannel(final Channel channel) {
- // No need to guard against this if we're closing
- if (!closed) {
- uninjectedChannels.add(channel);
- }
-
- // See ChannelInjector in ProtocolLib, line 590
- channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
- }
-
- /**
- * Determine if the given player has been injected by TinyProtocol.
- *
- * @param player - the player.
- * @return TRUE if it is, FALSE otherwise.
- */
- public boolean hasInjected(Player player) {
- return hasInjected(getChannel(player));
- }
-
- /**
- * Determine if the given channel has been injected by TinyProtocol.
- *
- * @param channel - the channel.
- * @return TRUE if it is, FALSE otherwise.
- */
- public boolean hasInjected(Channel channel) {
- return channel.pipeline().get(handlerName) != null;
- }
-
- /**
- * Cease listening for packets. This is called automatically when your plugin is disabled.
- */
- public final void close() {
+ private void close() {
if (!closed) {
closed = true;
// Remove our handlers
for (Player player : plugin.getServer().getOnlinePlayers()) {
- uninjectPlayer(player);
+ // No need to guard against this if we're closing
+ Channel channel = getChannel(player);
+ if (!closed) {
+ uninjectedChannels.add(channel);
+ }
+
+ // See ChannelInjector in ProtocolLib, line 590
+ channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
}
// Clean up Bukkit
@@ -452,11 +286,6 @@ public abstract class TinyProtocol {
}
}
- /**
- * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets.
- *
- * @author Kristian
- */
private final class PacketInterceptor extends ChannelDuplexHandler {
// Updated by the login event
public volatile Player player;
@@ -468,9 +297,9 @@ public abstract class TinyProtocol {
handleLoginStart(channel, msg);
try {
- msg = onPacketInAsync(player, channel, msg);
+ msg = onPacketInAsync(player, msg);
} catch (Exception e) {
- plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e);
+ plugin.getLogger().log(Level.SEVERE, "[NPCLib] Error in onPacketInAsync().", e);
}
if (msg != null) {
@@ -478,23 +307,10 @@ public abstract class TinyProtocol {
}
}
- @Override
- public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
- try {
- msg = onPacketOutAsync(player, ctx.channel(), msg);
- } catch (Exception e) {
- plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e);
- }
-
- if (msg != null) {
- super.write(ctx, msg, promise);
- }
- }
-
private void handleLoginStart(Channel channel, Object packet) {
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
- 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..d304d0c 100755
--- a/commons/src/main/java/net/jitse/npclib/NPCLib.java
+++ b/commons/src/main/java/net/jitse/npclib/NPCLib.java
@@ -9,6 +9,7 @@ import net.jitse.npclib.listeners.ChunkListener;
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 +65,8 @@ public class NPCLib {
pluginManager.registerEvents(new PlayerListener(), plugin);
pluginManager.registerEvents(new ChunkListener(), plugin);
- new PacketListener().start(plugin);
+ // Boot the according packet listener.
+ new PacketListener().start(plugin, Bukkit.getBukkitVersion().contains("1.7"));
}
/**
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..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;
@@ -25,11 +24,11 @@ import java.util.*;
public abstract class NPC implements PacketHandler, ActionHandler {
protected final UUID uuid = UUID.randomUUID();
- protected final String name = uuid.toString().replace("-", "").substring(0, 10);
// Below was previously = (int) Math.ceil(Math.random() * 100000) + 100000 (new is experimental).
protected final int entityId = Integer.MAX_VALUE - NPCManager.getAllNPCs().size();
protected double cosFOV = Math.cos(Math.toRadians(60));
+ protected String name = uuid.toString().replace("-", "").substring(0, 10);
private final Set shown = new HashSet<>();
private final Set autoHidden = new HashSet<>();
@@ -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/PacketListener.java b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java
index cb07d28..5e700d0 100755
--- a/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java
+++ b/commons/src/main/java/net/jitse/npclib/listeners/PacketListener.java
@@ -4,9 +4,9 @@
package net.jitse.npclib.listeners;
+import com.comphenix.tinyprotocol.LegacyTinyProtocol;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
-import io.netty.channel.Channel;
import net.jitse.npclib.NPCManager;
import net.jitse.npclib.api.NPC;
import net.jitse.npclib.events.NPCInteractEvent;
@@ -34,39 +34,77 @@ public class PacketListener {
// Prevent players from clicking at very high speeds.
private final Set delay = new HashSet<>();
- public void start(JavaPlugin plugin) {
- new TinyProtocol(plugin) {
+ public void start(JavaPlugin plugin, boolean is1_7) {
+ if (is1_7) {
+ // 1.7 R4 packet interaction.
+ new LegacyTinyProtocol(plugin) {
- @Override
- public Object onPacketInAsync(Player player, Channel channel, Object packet) {
+ @Override
+ public Object onPacketInAsync(Player player, Object packet) {
- if (packetPlayInUseEntityClazz.isInstance(packet)) {
- NPC npc = NPCManager.getAllNPCs().stream().filter(
- check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet))
- .findFirst().orElse(null);
+ if (packetPlayInUseEntityClazz.isInstance(packet)) {
+ NPC npc = NPCManager.getAllNPCs().stream().filter(
+ check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet))
+ .findFirst().orElse(null);
- if (npc == null) {
- // Default player, not doing magic with the packet.
- return super.onPacketInAsync(player, channel, packet);
- }
+ if (npc == null) {
+ // Default player, not doing magic with the packet.
+ return super.onPacketInAsync(player, packet);
+ }
- if (delay.contains(player.getUniqueId())) {
+ if (delay.contains(player.getUniqueId())) {
+ return null;
+ }
+
+ ClickType clickType = actionField.get(packet).toString()
+ .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK;
+
+ Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc));
+
+ UUID uuid = player.getUniqueId();
+ delay.add(uuid);
+ Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid));
return null;
}
- ClickType clickType = actionField.get(packet).toString()
- .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK;
-
- Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc));
-
- UUID uuid = player.getUniqueId();
- delay.add(uuid);
- Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid));
- return null;
+ return super.onPacketInAsync(player, packet);
}
+ };
+ } else {
+ // 1.8 (and above) packet interaction.
+ new TinyProtocol(plugin) {
- return super.onPacketInAsync(player, channel, packet);
- }
- };
+ @Override
+ public Object onPacketInAsync(Player player, Object packet) {
+
+ if (packetPlayInUseEntityClazz.isInstance(packet)) {
+ NPC npc = NPCManager.getAllNPCs().stream().filter(
+ check -> check.isActuallyShown(player) && check.getEntityId() == (int) entityIdField.get(packet))
+ .findFirst().orElse(null);
+
+ if (npc == null) {
+ // Default player, not doing magic with the packet.
+ return super.onPacketInAsync(player, packet);
+ }
+
+ if (delay.contains(player.getUniqueId())) {
+ return null;
+ }
+
+ ClickType clickType = actionField.get(packet).toString()
+ .equals("ATTACK") ? ClickType.LEFT_CLICK : ClickType.RIGHT_CLICK;
+
+ Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc));
+
+ UUID uuid = player.getUniqueId();
+ delay.add(uuid);
+ Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid));
+ return null;
+ }
+
+ return super.onPacketInAsync(player, packet);
+ }
+ };
+ }
}
}
diff --git a/nms/pom.xml b/nms/pom.xml
index 93bb047..7aa51d8 100755
--- a/nms/pom.xml
+++ b/nms/pom.xml
@@ -7,12 +7,13 @@
net.jitse
npclib
- 1.3
+ 1.4
npclib-nms
+ v1_7_R4
v1_8_R1
v1_8_R2
v1_8_R3
diff --git a/nms/v1_10_R1/pom.xml b/nms/v1_10_R1/pom.xml
index d59f6a9..30ace41 100755
--- a/nms/v1_10_R1/pom.xml
+++ b/nms/v1_10_R1/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_10_R1
diff --git a/nms/v1_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/pom.xml b/nms/v1_11_R1/pom.xml
index e38a305..98a3ee5 100755
--- a/nms/v1_11_R1/pom.xml
+++ b/nms/v1_11_R1/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_11_R1
diff --git a/nms/v1_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/pom.xml b/nms/v1_12_R1/pom.xml
index 09b3df4..1203094 100755
--- a/nms/v1_12_R1/pom.xml
+++ b/nms/v1_12_R1/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_12_R1
diff --git a/nms/v1_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/pom.xml b/nms/v1_13_R1/pom.xml
index 45a1e74..271c83d 100755
--- a/nms/v1_13_R1/pom.xml
+++ b/nms/v1_13_R1/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_13_R1
diff --git a/nms/v1_13_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/pom.xml b/nms/v1_13_R2/pom.xml
index c3651fc..f7d67a5 100755
--- a/nms/v1_13_R2/pom.xml
+++ b/nms/v1_13_R2/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_13_R2
diff --git a/nms/v1_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_7_R4/pom.xml b/nms/v1_7_R4/pom.xml
new file mode 100755
index 0000000..9cbf492
--- /dev/null
+++ b/nms/v1_7_R4/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+
+
+ net.jitse
+ npclib-nms
+ 1.4
+
+
+ npclib-nms-v1_7_R4
+
+
+
+ org.spigotmc
+ spigot
+ 1.7.10-R0.1-SNAPSHOT
+ provided
+
+
+ com.google.code.gson
+ gson
+ 2.8.5
+ compile
+
+
+
diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java
new file mode 100755
index 0000000..bb5cd9d
--- /dev/null
+++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/NPC_v1_7_R4.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2018 Jitse Boonstra
+ */
+
+package net.jitse.npclib.nms.v1_7_R4;
+
+import net.jitse.npclib.api.NPC;
+import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutEntityHeadRotationWrapper;
+import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutNamedEntitySpawnWrapper;
+import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutPlayerInfoWrapper;
+import net.jitse.npclib.nms.v1_7_R4.packets.PacketPlayOutScoreboardTeamWrapper;
+import net.jitse.npclib.skin.Skin;
+import net.minecraft.server.v1_7_R4.*;
+import net.minecraft.util.com.mojang.authlib.GameProfile;
+import net.minecraft.util.com.mojang.authlib.properties.Property;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @author Jitse Boonstra
+ */
+public class NPC_v1_7_R4 extends NPC {
+
+ private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn;
+ private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister;
+ private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove;
+ private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation;
+ private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy;
+
+ private GameProfile legacyGameProfile;
+
+ public NPC_v1_7_R4(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) {
+ super(plugin, skin, autoHideDistance, lines);
+ // TODO: Add multi-line text support.
+ this.name = lines.get(0);
+ }
+
+ @Override
+ public void createPackets() {
+ this.legacyGameProfile = generateLegacyGameProfile(uuid, name.length() < 16 ? name : name.substring(0, 15));
+ PacketPlayOutPlayerInfoWrapper packetPlayOutPlayerInfoWrapper = new PacketPlayOutPlayerInfoWrapper();
+
+ // Packets for spawning the NPC:
+ this.packetPlayOutScoreboardTeamRegister = new PacketPlayOutScoreboardTeamWrapper()
+ .createRegisterTeam(legacyGameProfile.getId().toString().replace("-", "").substring(0, 10), name); // First packet to send.
+
+ this.packetPlayOutPlayerInfoAdd = packetPlayOutPlayerInfoWrapper
+ .create(0, legacyGameProfile, name.length() < 16 ? name : name.length() < 16 ? name : name.substring(0, 15)); // Second packet to send.
+
+ this.packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawnWrapper()
+ .create(legacyGameProfile, location, entityId); // Third packet to send.
+
+ this.packetPlayOutEntityHeadRotation = new PacketPlayOutEntityHeadRotationWrapper()
+ .create(location, entityId); // Fourth packet to send.
+
+ this.packetPlayOutPlayerInfoRemove = packetPlayOutPlayerInfoWrapper
+ .create(4, legacyGameProfile, name.length() < 16 ? name : name.substring(0, 15)); // Fifth packet to send (delayed).
+
+ // Packet for destroying the NPC:
+ this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send.
+
+ // Second packet to send is "packetPlayOutPlayerInfoRemove".
+
+ this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper()
+ .createUnregisterTeam(legacyGameProfile.getId().toString().replace("-", "").substring(0, 10)); // Third packet to send.
+ }
+
+ @Override
+ public void sendShowPackets(Player player) {
+ PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
+
+ playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister);
+ playerConnection.sendPacket(packetPlayOutPlayerInfoAdd);
+ playerConnection.sendPacket(packetPlayOutNamedEntitySpawn);
+ playerConnection.sendPacket(packetPlayOutEntityHeadRotation);
+
+ Bukkit.getScheduler().runTaskLater(plugin, () ->
+ playerConnection.sendPacket(packetPlayOutPlayerInfoRemove), 50);
+ }
+
+ @Override
+ public void sendHidePackets(Player player, boolean scheduler) {
+ PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
+
+ playerConnection.sendPacket(packetPlayOutEntityDestroy);
+ playerConnection.sendPacket(packetPlayOutPlayerInfoRemove);
+
+ if (scheduler) {
+ // Sending this a bit later so the player doesn't see the name (for that split second).
+ Bukkit.getScheduler().runTaskLater(plugin, () ->
+ playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5);
+ } else {
+ playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister);
+ }
+ }
+
+ private GameProfile generateLegacyGameProfile(UUID uuid, String name) {
+ GameProfile gameProfile = new GameProfile(uuid, name);
+
+ if (skin != null) {
+ gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
+ }
+
+ return gameProfile;
+ }
+}
diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java
new file mode 100755
index 0000000..a8af781
--- /dev/null
+++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutEntityHeadRotationWrapper.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018 Jitse Boonstra
+ */
+
+package net.jitse.npclib.nms.v1_7_R4.packets;
+
+import com.comphenix.tinyprotocol.Reflection;
+import net.minecraft.server.v1_7_R4.PacketPlayOutEntityHeadRotation;
+import org.bukkit.Location;
+
+/**
+ * @author Jitse Boonstra
+ */
+public class PacketPlayOutEntityHeadRotationWrapper {
+
+ public PacketPlayOutEntityHeadRotation create(Location location, int entityId) {
+ PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation = new PacketPlayOutEntityHeadRotation();
+
+ Reflection.getField(packetPlayOutEntityHeadRotation.getClass(), "a", int.class).
+ set(packetPlayOutEntityHeadRotation, entityId);
+ Reflection.getField(packetPlayOutEntityHeadRotation.getClass(), "b", byte.class)
+ .set(packetPlayOutEntityHeadRotation, (byte) ((int) location.getYaw() * 256.0F / 360.0F));
+
+ return packetPlayOutEntityHeadRotation;
+ }
+}
diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java
new file mode 100755
index 0000000..61b47a5
--- /dev/null
+++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutNamedEntitySpawnWrapper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Jitse Boonstra
+ */
+
+package net.jitse.npclib.nms.v1_7_R4.packets;
+
+import com.comphenix.tinyprotocol.Reflection;
+import net.minecraft.server.v1_7_R4.DataWatcher;
+import net.minecraft.server.v1_7_R4.PacketPlayOutNamedEntitySpawn;
+import net.minecraft.util.com.mojang.authlib.GameProfile;
+import org.bukkit.Location;
+
+/**
+ * @author Jitse Boonstra
+ */
+public class PacketPlayOutNamedEntitySpawnWrapper {
+
+ public PacketPlayOutNamedEntitySpawn create(GameProfile gameProfile, Location location, int entityId) {
+ PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawn();
+
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "a", int.class)
+ .set(packetPlayOutNamedEntitySpawn, entityId);
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "b", GameProfile.class)
+ .set(packetPlayOutNamedEntitySpawn, gameProfile);
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "c", int.class)
+ .set(packetPlayOutNamedEntitySpawn, (int) Math.floor(location.getX() * 32.0D));
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "d", int.class)
+ .set(packetPlayOutNamedEntitySpawn, (int) Math.floor(location.getY() * 32.0D));
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "e", int.class)
+ .set(packetPlayOutNamedEntitySpawn, (int) Math.floor(location.getZ() * 32.0D));
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "f", byte.class)
+ .set(packetPlayOutNamedEntitySpawn, (byte) ((int) (location.getYaw() * 256.0F / 360.0F)));
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "g", byte.class)
+ .set(packetPlayOutNamedEntitySpawn, (byte) ((int) (location.getPitch() * 256.0F / 360.0F)));
+
+ DataWatcher dataWatcher = new DataWatcher(null);
+ dataWatcher.a(10, (byte) 127);
+
+ Reflection.getField(packetPlayOutNamedEntitySpawn.getClass(), "i", DataWatcher.class)
+ .set(packetPlayOutNamedEntitySpawn, dataWatcher);
+
+ return packetPlayOutNamedEntitySpawn;
+ }
+}
diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java
new file mode 100755
index 0000000..3673d16
--- /dev/null
+++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutPlayerInfoWrapper.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Jitse Boonstra
+ */
+
+package net.jitse.npclib.nms.v1_7_R4.packets;
+
+import com.comphenix.tinyprotocol.Reflection;
+import net.minecraft.server.v1_7_R4.PacketPlayOutPlayerInfo;
+import net.minecraft.util.com.mojang.authlib.GameProfile;
+
+/**
+ * @author Jitse Boonstra
+ */
+public class PacketPlayOutPlayerInfoWrapper {
+
+ public PacketPlayOutPlayerInfo create(int action, GameProfile gameProfile, String name) {
+ PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = new PacketPlayOutPlayerInfo();
+
+ // Action values:
+ // 0 = Add player
+ // 1 = Update gamemode
+ // 2 = Update latency
+ // 3 = Update display name
+ // 4 = Remove player
+ Reflection.getField(packetPlayOutPlayerInfo.getClass(), "action", int.class)
+ .set(packetPlayOutPlayerInfo, action);
+ Reflection.getField(packetPlayOutPlayerInfo.getClass(), "player", GameProfile.class)
+ .set(packetPlayOutPlayerInfo, gameProfile);
+ Reflection.getField(packetPlayOutPlayerInfo.getClass(), "username", String.class)
+ .set(packetPlayOutPlayerInfo, name);
+ Reflection.getField(packetPlayOutPlayerInfo.getClass(), "ping", int.class)
+ .set(packetPlayOutPlayerInfo, 0);
+ Reflection.getField(packetPlayOutPlayerInfo.getClass(), "gamemode", int.class)
+ .set(packetPlayOutPlayerInfo, 1);
+
+ return packetPlayOutPlayerInfo;
+ }
+}
diff --git a/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java
new file mode 100755
index 0000000..2547cdc
--- /dev/null
+++ b/nms/v1_7_R4/src/main/java/net/jitse/npclib/nms/v1_7_R4/packets/PacketPlayOutScoreboardTeamWrapper.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Jitse Boonstra
+ */
+
+package net.jitse.npclib.nms.v1_7_R4.packets;
+
+import com.comphenix.tinyprotocol.Reflection;
+import net.minecraft.server.v1_7_R4.PacketPlayOutScoreboardTeam;
+
+import java.util.Collection;
+
+/**
+ * @author Jitse Boonstra
+ */
+public class PacketPlayOutScoreboardTeamWrapper {
+
+ public PacketPlayOutScoreboardTeam createRegisterTeam(String uuidName, String name) {
+ PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeam = new PacketPlayOutScoreboardTeam();
+
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "f", int.class)
+ .set(packetPlayOutScoreboardTeam, 0);
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "b", String.class)
+ .set(packetPlayOutScoreboardTeam, name.length() < 16 ? name : name.substring(0, 15));
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "a", String.class)
+ .set(packetPlayOutScoreboardTeam, uuidName);
+ if (name.length() > 16) {
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "d", String.class)
+ .set(packetPlayOutScoreboardTeam, name.substring(15));
+ }
+ if (name.length() > 32) {
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "c", String.class)
+ .set(packetPlayOutScoreboardTeam, name.substring(31));
+ }
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "g", int.class)
+ .set(packetPlayOutScoreboardTeam, 1);
+ Reflection.FieldAccessor collectionFieldAccessor = Reflection.getField(
+ packetPlayOutScoreboardTeam.getClass(), "e", Collection.class);
+ Collection collection = collectionFieldAccessor.get(packetPlayOutScoreboardTeam);
+ collection.add(name.length() < 16 ? name : name.substring(0, 15));
+ collectionFieldAccessor.set(packetPlayOutScoreboardTeam, collection);
+
+ return packetPlayOutScoreboardTeam;
+ }
+
+ public PacketPlayOutScoreboardTeam createUnregisterTeam(String uuidName) {
+ PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeam = new PacketPlayOutScoreboardTeam();
+
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "f", int.class)
+ .set(packetPlayOutScoreboardTeam, 1);
+ Reflection.getField(packetPlayOutScoreboardTeam.getClass(), "a", String.class)
+ .set(packetPlayOutScoreboardTeam, uuidName);
+
+ return packetPlayOutScoreboardTeam;
+ }
+}
diff --git a/nms/v1_8_R1/pom.xml b/nms/v1_8_R1/pom.xml
index 25d62d1..7adb9ec 100755
--- a/nms/v1_8_R1/pom.xml
+++ b/nms/v1_8_R1/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_8_R1
diff --git a/nms/v1_8_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/pom.xml b/nms/v1_8_R2/pom.xml
index 4936191..feda596 100755
--- a/nms/v1_8_R2/pom.xml
+++ b/nms/v1_8_R2/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_8_R2
diff --git a/nms/v1_8_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/pom.xml b/nms/v1_8_R3/pom.xml
index 3445740..cfdf521 100755
--- a/nms/v1_8_R3/pom.xml
+++ b/nms/v1_8_R3/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_8_R3
diff --git a/nms/v1_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/pom.xml b/nms/v1_9_R1/pom.xml
index 1e450c9..550baf2 100755
--- a/nms/v1_9_R1/pom.xml
+++ b/nms/v1_9_R1/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_9_R1
diff --git a/nms/v1_9_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/pom.xml b/nms/v1_9_R2/pom.xml
index 62d69bc..e5aaeb3 100755
--- a/nms/v1_9_R2/pom.xml
+++ b/nms/v1_9_R2/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib-nms
- 1.3
+ 1.4
npclib-nms-v1_9_R2
diff --git a/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);
diff --git a/plugin/pom.xml b/plugin/pom.xml
index f9f3393..8e2e1fc 100755
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -7,7 +7,7 @@
net.jitse
npclib
- 1.3
+ 1.4
npclib-plugin
diff --git a/pom.xml b/pom.xml
index 2987d62..5e9bb07 100755
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
net.jitse
npclib
- 1.3
+ 1.4
NPCLib
https://github.com/JitseB/NPCLib