diff --git a/api/src/main/java/net/jitse/npclib/api/NPC.java b/api/src/main/java/net/jitse/npclib/api/NPC.java index 9b4d687..3312cf7 100644 --- a/api/src/main/java/net/jitse/npclib/api/NPC.java +++ b/api/src/main/java/net/jitse/npclib/api/NPC.java @@ -6,6 +6,7 @@ package net.jitse.npclib.api; import net.jitse.npclib.api.skin.Skin; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.entity.Player; public interface NPC { @@ -35,6 +36,13 @@ public interface NPC { */ Location getLocation(); + /** + * Get the world the NPC is located in. + * + * @return The world the NPC is located in. + */ + World getWorld(); + /** * Create all necessary packets for the NPC so it can be shown to players. * diff --git a/api/src/main/java/net/jitse/npclib/hologram/Hologram.java b/api/src/main/java/net/jitse/npclib/hologram/Hologram.java index ae464a4..bf91b78 100644 --- a/api/src/main/java/net/jitse/npclib/hologram/Hologram.java +++ b/api/src/main/java/net/jitse/npclib/hologram/Hologram.java @@ -87,9 +87,9 @@ public class Hologram { Reflection.getMethod(ENTITY_CLAZZ, "setNoGravity", boolean.class) : Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, "setGravity", boolean.class)); - Reflection.MethodInvoker customNameMethod = (version.isAboveOrEqual(MinecraftVersion.V1_12_R1) ? - Reflection.getMethod(ENTITY_CLAZZ, "setCustomName", CHAT_BASE_COMPONENT_CLAZZ) : - Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, "setCustomName", String.class)); + Reflection.MethodInvoker customNameMethod = (version.isAboveOrEqual(MinecraftVersion.V1_12_R1) + ? Reflection.getMethod(ENTITY_CLAZZ, "setCustomName", version.isAboveOrEqual(MinecraftVersion.V1_13_R1) ? CHAT_BASE_COMPONENT_CLAZZ : String.class) + : Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, "setCustomName", String.class)); Reflection.MethodInvoker customNameVisibilityMethod = (version.isAboveOrEqual(MinecraftVersion.V1_12_R1) ? Reflection.getMethod(ENTITY_CLAZZ, "setCustomNameVisible", boolean.class) : @@ -115,7 +115,7 @@ public class Hologram { SET_LOCATION_METHOD.invoke(entityArmorStand, location.getX(), location.getY(), location.getZ(), 0, 0); } - customNameMethod.invoke(entityArmorStand, version.isAboveOrEqual(MinecraftVersion.V1_12_R1) ? + customNameMethod.invoke(entityArmorStand, version.isAboveOrEqual(MinecraftVersion.V1_13_R1) ? CHAT_COMPONENT_TEXT_CONSTRUCTOR.invoke(line) : line); customNameVisibilityMethod.invoke(entityArmorStand, true); gravityMethod.invoke(entityArmorStand, version.isAboveOrEqual(MinecraftVersion.V1_9_R2)); diff --git a/api/src/main/java/net/jitse/npclib/internal/PacketHandler.java b/api/src/main/java/net/jitse/npclib/internal/PacketHandler.java index 5257bd4..2c4ea29 100755 --- a/api/src/main/java/net/jitse/npclib/internal/PacketHandler.java +++ b/api/src/main/java/net/jitse/npclib/internal/PacketHandler.java @@ -15,5 +15,5 @@ interface PacketHandler { void sendShowPackets(Player player); - void sendHidePackets(Player player, boolean scheduler); + void sendHidePackets(Player player); } diff --git a/api/src/main/java/net/jitse/npclib/internal/SimpleNPC.java b/api/src/main/java/net/jitse/npclib/internal/SimpleNPC.java index 0049b76..497dc2b 100644 --- a/api/src/main/java/net/jitse/npclib/internal/SimpleNPC.java +++ b/api/src/main/java/net/jitse/npclib/internal/SimpleNPC.java @@ -13,6 +13,7 @@ import net.jitse.npclib.api.events.NPCShowEvent; import net.jitse.npclib.api.skin.Skin; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.util.Vector; @@ -57,20 +58,14 @@ public abstract class SimpleNPC implements NPC, PacketHandler { this.skin = skin; gameProfile.getProperties().get("textures").clear(); - - if (skin != null) { + if (skin != null) gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); - } return this; } @Override public void destroy() { - destroy(true); - } - - public void destroy(boolean scheduler) { NPCManager.remove(this); // Destroy NPC for every player that is still seeing it. @@ -79,7 +74,7 @@ public abstract class SimpleNPC implements NPC, PacketHandler { continue; } - hide(Bukkit.getPlayer(uuid), true, scheduler); + hide(Bukkit.getPlayer(uuid), true); } } @@ -104,6 +99,11 @@ public abstract class SimpleNPC implements NPC, PacketHandler { return location; } + @Override + public World getWorld() { + return location != null ? location.getWorld() : null; + } + public int getEntityId() { return entityId; } @@ -125,6 +125,11 @@ public abstract class SimpleNPC implements NPC, PacketHandler { return this; } + public void onLogout(Player player) { + getAutoHidden().remove(player.getUniqueId()); + getShown().remove(player.getUniqueId()); // Don't need to use NPC#hide since the entity is not registered in the NMS server. + } + @Override public void show(Player player) { show(player, false); @@ -175,10 +180,10 @@ public abstract class SimpleNPC implements NPC, PacketHandler { @Override public void hide(Player player) { - hide(player, false, true); + hide(player, false); } - public void hide(Player player, boolean auto, boolean scheduler) { + public void hide(Player player, boolean auto) { NPCHideEvent event = new NPCHideEvent(this, player, auto); Bukkit.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -186,7 +191,7 @@ public abstract class SimpleNPC implements NPC, PacketHandler { } if (auto) { - sendHidePackets(player, scheduler); + sendHidePackets(player); } else { if (!shown.contains(player.getUniqueId())) { throw new RuntimeException("Cannot call hide method without calling NPC#show."); @@ -196,7 +201,7 @@ public abstract class SimpleNPC implements NPC, PacketHandler { if (player.getWorld().equals(location.getWorld()) && player.getLocation().distance(location) <= instance.getAutoHideDistance()) { - sendHidePackets(player, scheduler); + sendHidePackets(player); } else { autoHidden.remove(player.getUniqueId()); } diff --git a/api/src/main/java/net/jitse/npclib/listeners/ChunkListener.java b/api/src/main/java/net/jitse/npclib/listeners/ChunkListener.java index 10d7902..ab42b7d 100755 --- a/api/src/main/java/net/jitse/npclib/listeners/ChunkListener.java +++ b/api/src/main/java/net/jitse/npclib/listeners/ChunkListener.java @@ -9,12 +9,14 @@ import net.jitse.npclib.internal.NPCManager; import net.jitse.npclib.internal.SimpleNPC; import org.bukkit.Bukkit; import org.bukkit.Chunk; +import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkUnloadEvent; +import java.util.Objects; import java.util.UUID; /** @@ -33,20 +35,18 @@ public class ChunkListener implements Listener { Chunk chunk = event.getChunk(); for (SimpleNPC npc : NPCManager.getAllNPCs()) { - Chunk npcChunk = npc.getLocation().getChunk(); + if (!isSameChunk(npc.getLocation(), chunk)) + continue; // We aren't unloading the chunk with the NPC in it. - if (chunk.equals(npcChunk)) { - // Unloaded chunk with NPC in it. Hiding it from all players currently shown to. - - for (UUID uuid : npc.getShown()) { - // Safety check so it doesn't send packets if the NPC has already - // been automatically despawned by the system. - if (npc.getAutoHidden().contains(uuid)) { - continue; - } - - npc.hide(Bukkit.getPlayer(uuid), true, true); + // We found an NPC in the chunk being unloaded. Time to hide this NPC from all players. + for (UUID uuid : npc.getShown()) { + // Safety check so it doesn't send packets if the NPC has already + // been automatically despawned by the system. + if (npc.getAutoHidden().contains(uuid)) { + continue; } + + npc.hide(Bukkit.getPlayer(uuid), true); } } } @@ -56,33 +56,45 @@ public class ChunkListener implements Listener { Chunk chunk = event.getChunk(); for (SimpleNPC npc : NPCManager.getAllNPCs()) { - Chunk npcChunk = npc.getLocation().getChunk(); + if (!isSameChunk(npc.getLocation(), chunk)) + continue; // The NPC is not in the loaded chunk. - if (chunk.equals(npcChunk)) { - // Loaded chunk with NPC in it. Showing it to the players again. + // The chunk being loaded has this NPC in it. Showing it to all the players again. + for (UUID uuid : npc.getShown()) { + // Make sure not to respawn a not-hidden NPC. + if (!npc.getAutoHidden().contains(uuid)) { + continue; + } - for (UUID uuid : npc.getShown()) { - // Make sure not to respawn a not-hidden NPC. - if (!npc.getAutoHidden().contains(uuid)) { - continue; - } + Player player = Bukkit.getPlayer(uuid); + if (player == null) + continue; // Couldn't find the player, so skip. - Player player = Bukkit.getPlayer(uuid); + if (!Objects.equals(npc.getWorld(), player.getWorld())) { + continue; // Player and NPC are not in the same world. + } - if (!npcChunk.getWorld().equals(player.getWorld())) { - continue; // Player and NPC are not in the same world. - } + double hideDistance = instance.getAutoHideDistance(); + double distanceSquared = player.getLocation().distanceSquared(npc.getLocation()); + boolean inRange = distanceSquared <= (hideDistance * hideDistance) || distanceSquared <= (Bukkit.getViewDistance() << 4); - double hideDistance = instance.getAutoHideDistance(); - double distanceSquared = player.getLocation().distanceSquared(npc.getLocation()); - boolean inRange = distanceSquared <= (hideDistance * hideDistance) || distanceSquared <= (Bukkit.getViewDistance() << 4); - - // Show the NPC (if in range). - if (inRange) { - npc.show(player, true); - } + // Show the NPC (if in range). + if (inRange) { + npc.show(player, true); } } } } + + + private static int getChunkCoordinate(int coordinate) { + return coordinate >> 4; + } + + // Using Location#getChunk will load the chunk, which is a pretty hefty task, so we'll want to avoid it. + // Using Location#getChunk would effectively mean we'd load every chunk an NPC is located in when any chunk is unloaded. + private static boolean isSameChunk(Location loc, Chunk chunk) { + return getChunkCoordinate(loc.getBlockX()) == chunk.getX() + && getChunkCoordinate(loc.getBlockZ()) == chunk.getZ(); + } } diff --git a/api/src/main/java/net/jitse/npclib/listeners/PacketListener.java b/api/src/main/java/net/jitse/npclib/listeners/PacketListener.java index 36a6431..7f1ce9e 100755 --- a/api/src/main/java/net/jitse/npclib/listeners/PacketListener.java +++ b/api/src/main/java/net/jitse/npclib/listeners/PacketListener.java @@ -11,10 +11,12 @@ import net.jitse.npclib.api.events.NPCInteractEvent; import net.jitse.npclib.internal.NPCManager; import net.jitse.npclib.internal.SimpleNPC; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import java.util.HashSet; +import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -48,32 +50,64 @@ public class PacketListener { } private boolean handleInteractPacket(Player player, Object packet) { - if (packetPlayInUseEntityClazz.isInstance(packet)) { - SimpleNPC npc = NPCManager.getAllNPCs().stream().filter( - check -> check.isShown(player) && check.getEntityId() == (int) entityIdField.get(packet)) - .findFirst().orElse(null); + if (!packetPlayInUseEntityClazz.isInstance(packet)) + return true; // We aren't handling the packet. - if (npc == null) { - // Default player, not doing magic with the packet. - return true; + SimpleNPC npc = null; + int packetEntityId = (int) entityIdField.get(packet); + + // Not using streams here is an intentional choice. + // Packet listeners is one of the few places where it is important to write optimized code. + // Lambdas (And the stream api) create a massive amount of objects, especially if it isn't a static lambda. + // So, we're avoiding them here. + // ~ Kneesnap, 9 / 20 / 2019. + + for (SimpleNPC testNPC : NPCManager.getAllNPCs()) { + if (testNPC.isShown(player) && testNPC.getEntityId() == packetEntityId) { + npc = testNPC; + break; } + } - if (delay.contains(player.getUniqueId())) { - return false; - } + if (npc == null) { + // Default player, not doing magic with the packet. + return true; + } - NPCInteractEvent.ClickType clickType = actionField.get(packet).toString().equals("ATTACK") - ? NPCInteractEvent.ClickType.LEFT_CLICK : NPCInteractEvent.ClickType.RIGHT_CLICK; - - Bukkit.getScheduler().runTask(plugin, () -> - Bukkit.getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc))); - - UUID uuid = player.getUniqueId(); - delay.add(uuid); - Bukkit.getScheduler().runTask(plugin, () -> delay.remove(uuid)); + if (delay.contains(player.getUniqueId())) { // There is an active delay. return false; } - return true; + NPCInteractEvent.ClickType clickType = actionField.get(packet).toString().equals("ATTACK") + ? NPCInteractEvent.ClickType.LEFT_CLICK : NPCInteractEvent.ClickType.RIGHT_CLICK; + + delay.add(player.getUniqueId()); + Bukkit.getScheduler().runTask(plugin, new TaskCallNpcInteractEvent(new NPCInteractEvent(player, clickType, npc), this)); + return false; + } + + // This would be a non-static lambda, and its usage matters, so we'll make it a full class. + private static final class TaskCallNpcInteractEvent implements Runnable { + private NPCInteractEvent eventToCall; + private PacketListener listener; + + private static Location playerLocation = new Location(null, 0, 0, 0); + + TaskCallNpcInteractEvent(NPCInteractEvent eventToCall, PacketListener listener) { + this.eventToCall = eventToCall; + this.listener = listener; + } + + @Override + public void run() { + Player player = eventToCall.getWhoClicked(); + this.listener.delay.remove(player.getUniqueId()); // Remove the NPC from the interact cooldown. + if (!Objects.equals(player.getWorld(), eventToCall.getNPC().getWorld())) + return; // If the NPC and player are not in the same world, abort! + + double distance = player.getLocation(playerLocation).distanceSquared(eventToCall.getNPC().getLocation()); + if (distance <= 64) // Only handle the interaction if the player is within interaction range. This way, hacked clients can't interact with NPCs that they shouldn't be able to interact with. + Bukkit.getPluginManager().callEvent(this.eventToCall); + } } } diff --git a/api/src/main/java/net/jitse/npclib/listeners/PlayerListener.java b/api/src/main/java/net/jitse/npclib/listeners/PlayerListener.java index dcd418b..2393124 100755 --- a/api/src/main/java/net/jitse/npclib/listeners/PlayerListener.java +++ b/api/src/main/java/net/jitse/npclib/listeners/PlayerListener.java @@ -8,14 +8,13 @@ import net.jitse.npclib.NPCLib; import net.jitse.npclib.internal.NPCManager; import net.jitse.npclib.internal.SimpleNPC; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.*; /** * @author Jitse Boonstra @@ -30,13 +29,17 @@ public class PlayerListener implements Listener { @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { - Player player = event.getPlayer(); - for (SimpleNPC npc : NPCManager.getAllNPCs()) { - npc.getAutoHidden().remove(player.getUniqueId()); + onPlayerLeave(event.getPlayer()); + } - // Don't need to use NPC#hide since the entity is not registered in the NMS server. - npc.getShown().remove(player.getUniqueId()); - } + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPlayerKick(PlayerKickEvent event) { + onPlayerLeave(event.getPlayer()); + } + + private void onPlayerLeave(Player player) { + for (SimpleNPC npc : NPCManager.getAllNPCs()) + npc.onLogout(player); } @EventHandler @@ -46,10 +49,10 @@ public class PlayerListener implements Listener { // The PlayerTeleportEvent is call, and will handle visibility in the new world. for (SimpleNPC npc : NPCManager.getAllNPCs()) { - if (npc.getLocation().getWorld().equals(from)) { + if (npc.getWorld().equals(from)) { if (!npc.getAutoHidden().contains(player.getUniqueId())) { npc.getAutoHidden().add(player.getUniqueId()); - npc.hide(player, true, false); + npc.hide(player, true); } } } @@ -57,7 +60,12 @@ public class PlayerListener implements Listener { @EventHandler public void onPlayerMove(PlayerMoveEvent event) { - handleMove(event.getPlayer()); + Location from = event.getFrom(); + Location to = event.getTo(); + if (to == null || (from.getBlockX() != to.getBlockX() + || from.getBlockY() != to.getBlockY() + || from.getBlockZ() != to.getBlockZ())) + handleMove(event.getPlayer()); // Verify the player changed which block they are on. Since PlayerMoveEvent is one of the most called events, this is worth it. } @EventHandler @@ -72,7 +80,7 @@ public class PlayerListener implements Listener { continue; // NPC was never supposed to be shown to the player. } - if (!npc.getLocation().getWorld().equals(world)) { + if (!npc.getWorld().equals(world)) { continue; // NPC is not in the same world. } @@ -80,8 +88,9 @@ public class PlayerListener implements Listener { // This will cause issues otherwise (e.g. custom skin disappearing). double hideDistance = instance.getAutoHideDistance(); double distanceSquared = player.getLocation().distanceSquared(npc.getLocation()); - boolean inRange = distanceSquared <= (Math.pow(hideDistance, 2)) - && distanceSquared <= (Math.pow(Bukkit.getViewDistance() << 4, 2)); + + int tempRange = Bukkit.getViewDistance() << 4; + boolean inRange = distanceSquared <= (hideDistance * hideDistance) && distanceSquared <= (tempRange * tempRange); // Avoids Math.pow due to how intensive it is. Could make a static utility function for it. if (npc.getAutoHidden().contains(player.getUniqueId())) { // Check if the player and NPC are within the range to sendShowPackets it again. if (inRange) { @@ -92,7 +101,7 @@ public class PlayerListener implements Listener { // Check if the player and NPC are out of range to sendHidePackets it. if (!inRange) { npc.getAutoHidden().add(player.getUniqueId()); - npc.hide(player, true, true); + npc.hide(player, true); } } } diff --git a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java index 3438a45..cc1b3df 100755 --- a/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java +++ b/nms/v1_10_R1/src/main/java/net/jitse/npclib/nms/v1_10_R1/NPC_v1_10_R1.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_10_R1 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_10_R1(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +64,20 @@ public class NPC_v1_10_R1 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -84,20 +90,11 @@ public class NPC_v1_10_R1 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java index 055de27..31b0472 100755 --- a/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java +++ b/nms/v1_11_R1/src/main/java/net/jitse/npclib/nms/v1_11_R1/NPC_v1_11_R1.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_11_R1 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_11_R1(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +64,20 @@ public class NPC_v1_11_R1 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -84,20 +90,11 @@ public class NPC_v1_11_R1 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java index ee47131..eebda05 100755 --- a/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java +++ b/nms/v1_12_R1/src/main/java/net/jitse/npclib/nms/v1_12_R1/NPC_v1_12_R1.java @@ -17,19 +17,22 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra */ public class NPC_v1_12_R1 extends SimpleNPC { - private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_12_R1(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +63,20 @@ public class NPC_v1_12_R1 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -83,20 +88,11 @@ public class NPC_v1_12_R1 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java index db05c74..e54bccf 100755 --- a/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java +++ b/nms/v1_13_R1/src/main/java/net/jitse/npclib/nms/v1_13_R1/NPC_v1_13_R1.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_13_R1 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_13_R1(NPCLib instance, List lines) { super(instance, lines); @@ -60,44 +64,36 @@ public class NPC_v1_13_R1 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); hologram.spawn(player); - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> playerConnection.sendPacket(packetPlayOutPlayerInfoRemove), 50); } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java index 54ac946..ef456e5 100755 --- a/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java +++ b/nms/v1_13_R2/src/main/java/net/jitse/npclib/nms/v1_13_R2/NPC_v1_13_R2.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_13_R2 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_13_R2(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +64,20 @@ public class NPC_v1_13_R2 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -84,20 +90,11 @@ public class NPC_v1_13_R2 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_14_R1/src/main/java/net/jitse/npclib/nms/v1_14_R1/NPC_v1_14_R1.java b/nms/v1_14_R1/src/main/java/net/jitse/npclib/nms/v1_14_R1/NPC_v1_14_R1.java index bb799d6..19125b5 100755 --- a/nms/v1_14_R1/src/main/java/net/jitse/npclib/nms/v1_14_R1/NPC_v1_14_R1.java +++ b/nms/v1_14_R1/src/main/java/net/jitse/npclib/nms/v1_14_R1/NPC_v1_14_R1.java @@ -13,7 +13,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -22,10 +25,11 @@ public class NPC_v1_14_R1 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_14_R1(NPCLib instance, List lines) { super(instance, lines); @@ -56,18 +60,20 @@ public class NPC_v1_14_R1 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -80,20 +86,11 @@ public class NPC_v1_14_R1 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java index 5554652..b60bdd5 100755 --- a/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java +++ b/nms/v1_8_R1/src/main/java/net/jitse/npclib/nms/v1_8_R1/NPC_v1_8_R1.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_8_R1 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_8_R1(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +64,20 @@ public class NPC_v1_8_R1 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -83,20 +89,12 @@ public class NPC_v1_8_R1 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java index 94e51ca..8357855 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_8_R2 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_8_R2(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +64,20 @@ public class NPC_v1_8_R2 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -83,20 +89,11 @@ public class NPC_v1_8_R2 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java index 0b4d990..b7742b6 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_8_R3 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_8_R3(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +64,20 @@ public class NPC_v1_8_R3 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -84,20 +90,11 @@ public class NPC_v1_8_R3 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java index 1bb2f2e..42ea977 100755 --- a/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java +++ b/nms/v1_9_R1/src/main/java/net/jitse/npclib/nms/v1_9_R1/NPC_v1_9_R1.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_9_R1 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_9_R1(NPCLib instance, List lines) { super(instance, lines); @@ -60,44 +64,36 @@ public class NPC_v1_9_R1 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); hologram.spawn(player); - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> playerConnection.sendPacket(packetPlayOutPlayerInfoRemove), 50); } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } } diff --git a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java index 550af84..e5bd316 100755 --- a/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java +++ b/nms/v1_9_R2/src/main/java/net/jitse/npclib/nms/v1_9_R2/NPC_v1_9_R2.java @@ -17,7 +17,10 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; /** * @author Jitse Boonstra @@ -26,10 +29,11 @@ public class NPC_v1_9_R2 extends SimpleNPC { private Hologram hologram; private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; - private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister, packetPlayOutScoreboardTeamUnregister; + private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; + private Set hasTeamRegistered = new HashSet<>(); public NPC_v1_9_R2(NPCLib instance, List lines) { super(instance, lines); @@ -60,18 +64,20 @@ public class NPC_v1_9_R2 extends SimpleNPC { // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. + } - // Second packet to send is "packetPlayOutPlayerInfoRemove". - - this.packetPlayOutScoreboardTeamUnregister = new PacketPlayOutScoreboardTeamWrapper() - .createUnregisterTeam(name); // Third packet to send. + @Override + public void onLogout(Player player) { + super.onLogout(player); + hasTeamRegistered.remove(player.getUniqueId()); } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); + if (hasTeamRegistered.add(player.getUniqueId())) + playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); @@ -84,20 +90,11 @@ public class NPC_v1_9_R2 extends SimpleNPC { } @Override - public void sendHidePackets(Player player, boolean scheduler) { + public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); - hologram.destroy(player); - - if (scheduler) { - // Sending this a bit later so the player doesn't see the name (for that split second). - Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister), 5); - } else { - playerConnection.sendPacket(packetPlayOutScoreboardTeamUnregister); - } } }