From a46b1f440b07e4f207aa2b31a836701f70024320 Mon Sep 17 00:00:00 2001 From: fullwall Date: Sat, 3 Jan 2015 13:37:34 +0800 Subject: [PATCH] Try playerlist handling via EntityTrackerEntry instead of adhoc event listening --- .../java/net/citizensnpcs/EventListen.java | 71 ------------------- .../net/citizensnpcs/npc/CitizensNPC.java | 3 + .../npc/entity/EntityHumanNPC.java | 4 +- .../npc/entity/HumanController.java | 10 --- .../npc/entity/WitherController.java | 22 +++--- src/main/java/net/citizensnpcs/util/NMS.java | 60 +++++++--------- .../util/nms/PlayerlistTrackerEntry.java | 53 ++++++++++++++ 7 files changed, 96 insertions(+), 127 deletions(-) create mode 100644 src/main/java/net/citizensnpcs/util/nms/PlayerlistTrackerEntry.java diff --git a/src/main/java/net/citizensnpcs/EventListen.java b/src/main/java/net/citizensnpcs/EventListen.java index 1715aa253..00b1434a3 100644 --- a/src/main/java/net/citizensnpcs/EventListen.java +++ b/src/main/java/net/citizensnpcs/EventListen.java @@ -49,10 +49,7 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityTargetEvent; import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.vehicle.VehicleEnterEvent; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkUnloadEvent; @@ -275,30 +272,6 @@ public class EventListen implements Listener { Bukkit.getPluginManager().callEvent(rightClickEvent); } - @EventHandler(ignoreCancelled = true) - public void onPlayerJoin(final PlayerJoinEvent event) { - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - for (NPC npc : getAllNPCs()) { - if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) { - NMS.sendPlayerlistPacket(true, event.getPlayer(), npc); - } - } - } - }, 10); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - for (NPC npc : getAllNPCs()) { - if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) { - NMS.sendPlayerlistPacket(false, event.getPlayer(), npc); - } - } - } - }, 60); - } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerQuit(PlayerQuitEvent event) { Editor.leave(event.getPlayer()); @@ -310,50 +283,6 @@ public class EventListen implements Listener { } } - @EventHandler - public void onPlayerTeleports(PlayerTeleportEvent event) { - Location from = roundLocation(event.getFrom()); - Location to = roundLocation(event.getTo()); - if (from.equals(to)) { - return; // Don't fire on every movement, just full block+. - } - int maxRad = 50 * 50; // TODO: Adjust me to perfection - Location npcPos = new Location(null, 0, 0, 0); - for (final NPC npc : getAllNPCs()) { - if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) { - npc.getEntity().getLocation(npcPos); - if ((to.getWorld() == npcPos.getWorld() && npcPos.distanceSquared(to) < maxRad) - && ((from.getWorld() == npcPos.getWorld() && npcPos.distanceSquared(from) > maxRad) || from - .getWorld() != to.getWorld())) { - NMS.showNPCReset(event.getPlayer(), npc); - } - } - } - } - - @EventHandler - public void onPlayerWalks(final PlayerMoveEvent event) { - Location from = roundLocation(event.getFrom()); - Location to = roundLocation(event.getTo()); - if (from.equals(to)) { - return; - } - if (from.getWorld() != to.getWorld()) { - return; // Ignore cross-world movement - } - int maxRad = 50 * 50; // TODO: Adjust me to perfection - Location loc = new Location(null, 0, 0, 0); - for (final NPC npc : getAllNPCs()) { - if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) { - npc.getEntity().getLocation(loc); - if (from.getWorld() == loc.getWorld() && loc.distanceSquared(to) < maxRad - && loc.distanceSquared(from) > maxRad) { - NMS.showNPCReset(event.getPlayer(), npc); - } - } - } - } - @EventHandler(ignoreCancelled = true) public void onVehicleEnter(VehicleEnterEvent event) { if (!npcRegistry.isNPC(event.getEntered())) diff --git a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java b/src/main/java/net/citizensnpcs/npc/CitizensNPC.java index 9d8782055..a6cb9cc7b 100644 --- a/src/main/java/net/citizensnpcs/npc/CitizensNPC.java +++ b/src/main/java/net/citizensnpcs/npc/CitizensNPC.java @@ -215,6 +215,9 @@ public class CitizensNPC extends AbstractNPC { if (NMS.getStepHeight(entity) < 1) { NMS.setStepHeight(NMS.getHandle(entity), 1); } + if (getEntity() instanceof Player) { + NMS.replaceTrackerEntry((Player) getEntity()); + } } return true; } diff --git a/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java index 0a685a719..4ce3215e6 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/EntityHumanNPC.java @@ -291,9 +291,9 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder { break; } } - // NMS.sendToOnline(getListPacket(getBukkitEntity(), true)); + NMS.sendPlayerlistPacket(true, getBukkitEntity(), npc); if (otherOnline != null) { - // NMS.sendToOnline(getListPacket(otherOnline, false)); + NMS.sendPlayerlistPacket(false, otherOnline, npc); } NMS.sendPacketsNearby(getBukkitEntity(), current, packets); } diff --git a/src/main/java/net/citizensnpcs/npc/entity/HumanController.java b/src/main/java/net/citizensnpcs/npc/entity/HumanController.java index 9f59ed17f..0ce2c5c16 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/HumanController.java +++ b/src/main/java/net/citizensnpcs/npc/entity/HumanController.java @@ -26,7 +26,6 @@ import org.bukkit.Location; import org.bukkit.craftbukkit.v1_8_R1.CraftServer; import org.bukkit.craftbukkit.v1_8_R1.CraftWorld; import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import com.google.common.collect.Iterables; @@ -83,15 +82,6 @@ public class HumanController extends AbstractEntityController { } }, 1); handle.getBukkitEntity().setSleepingIgnored(true); - NMS.sendPlayerlistPacket(true, null, handle.getBukkitEntity()); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) { - NMS.sendPlayerlistPacket(false, null, npc); - } - } - }, 2); return handle.getBukkitEntity(); } diff --git a/src/main/java/net/citizensnpcs/npc/entity/WitherController.java b/src/main/java/net/citizensnpcs/npc/entity/WitherController.java index 9561f497f..40a563974 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/WitherController.java +++ b/src/main/java/net/citizensnpcs/npc/entity/WitherController.java @@ -81,17 +81,9 @@ public class WitherController extends MobEntityController { } @Override - protected void D() { + protected void E() { if (npc == null) { - super.D(); - } - } - - @Override - public void doTick() { - super.doTick(); - if (npc != null) { - npc.update(); + super.E(); } } @@ -129,6 +121,16 @@ public class WitherController extends MobEntityController { return npc; } + @Override + public void m() { + if (npc == null) { + super.m(); + } else { + NMS.updateAI(this); + npc.update(); + } + } + @Override protected String z() { return npc == null || !npc.data().has(NPC.AMBIENT_SOUND_METADATA) ? super.z() : npc.data().get( diff --git a/src/main/java/net/citizensnpcs/util/NMS.java b/src/main/java/net/citizensnpcs/util/NMS.java index 7b5977945..46165a1d6 100644 --- a/src/main/java/net/citizensnpcs/util/NMS.java +++ b/src/main/java/net/citizensnpcs/util/NMS.java @@ -8,15 +8,16 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Set; import java.util.WeakHashMap; -import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.command.exception.CommandException; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.util.Messaging; import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.entity.EntityHumanNPC; import net.citizensnpcs.npc.network.EmptyChannel; +import net.citizensnpcs.util.nms.PlayerlistTrackerEntry; import net.minecraft.server.v1_8_R1.AttributeInstance; import net.minecraft.server.v1_8_R1.Block; import net.minecraft.server.v1_8_R1.BlockPosition; @@ -30,6 +31,8 @@ import net.minecraft.server.v1_8_R1.EntityInsentient; import net.minecraft.server.v1_8_R1.EntityLiving; import net.minecraft.server.v1_8_R1.EntityMinecartAbstract; import net.minecraft.server.v1_8_R1.EntityPlayer; +import net.minecraft.server.v1_8_R1.EntityTracker; +import net.minecraft.server.v1_8_R1.EntityTrackerEntry; import net.minecraft.server.v1_8_R1.EntityTypes; import net.minecraft.server.v1_8_R1.EnumPlayerInfoAction; import net.minecraft.server.v1_8_R1.GenericAttributes; @@ -37,11 +40,10 @@ import net.minecraft.server.v1_8_R1.MathHelper; import net.minecraft.server.v1_8_R1.NavigationAbstract; import net.minecraft.server.v1_8_R1.NetworkManager; import net.minecraft.server.v1_8_R1.Packet; -import net.minecraft.server.v1_8_R1.PacketPlayOutEntityDestroy; -import net.minecraft.server.v1_8_R1.PacketPlayOutNamedEntitySpawn; import net.minecraft.server.v1_8_R1.PacketPlayOutPlayerInfo; import net.minecraft.server.v1_8_R1.PathfinderGoalSelector; import net.minecraft.server.v1_8_R1.World; +import net.minecraft.server.v1_8_R1.WorldServer; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; @@ -353,9 +355,25 @@ public class NMS { ((CraftServer) Bukkit.getServer()).getHandle().players.remove(handle); } - private static void sendDestroyPacket(final Player player, final NPC npc) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutEntityDestroy(npc.getEntity() - .getEntityId())); + @SuppressWarnings("rawtypes") + public static void replaceTrackerEntry(Player player) { + WorldServer server = (WorldServer) NMS.getHandle(player).getWorld(); + EntityTrackerEntry entry = (EntityTrackerEntry) server.getTracker().trackedEntities.get(player.getEntityId()); + if (entry == null) + return; + PlayerlistTrackerEntry replace = new PlayerlistTrackerEntry(entry); + server.getTracker().trackedEntities.a(player.getEntityId(), replace); + if (TRACKED_ENTITY_SET != null) { + try { + Set set = (Set) TRACKED_ENTITY_SET.get(server.getTracker()); + set.remove(entry); + set.add(replace); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } } public static void sendPacket(Player player, Packet packet) { @@ -413,11 +431,6 @@ public class NMS { } } - private static void sendSpawnPacket(final Player player, final NPC npc) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutNamedEntitySpawn( - ((CraftPlayer) npc.getEntity()).getHandle())); - } - public static void sendToOnline(Packet... packets) { Validate.notNull(packets, "packets cannot be null"); for (Player player : Bukkit.getOnlinePlayers()) { @@ -493,29 +506,6 @@ public class NMS { return false; } - public static void showNPCReset(final Player player, final NPC npc) { - sendDestroyPacket(player, npc); - sendPlayerlistPacket(true, player, npc); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - if (player.isOnline() && player.isValid() && npc.isSpawned() - && npc.getEntity().getType() == EntityType.PLAYER) { - sendSpawnPacket(player, npc); - } - } - }, 1); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - if (player.isOnline() && player.isValid() && npc.isSpawned() - && npc.getEntity().getType() == EntityType.PLAYER) { - sendPlayerlistPacket(false, player, npc); - } - } - }, 10); - } - public static org.bukkit.entity.Entity spawnCustomEntity(org.bukkit.World world, Location at, Class clazz, EntityType type) { World handle = ((CraftWorld) world).getHandle(); @@ -605,6 +595,7 @@ public class NMS { } private static final float DEFAULT_SPEED = 1F; + private static Map, Integer> ENTITY_CLASS_TO_INT; private static Map, String> ENTITY_CLASS_TO_NAME; private static final Map, Constructor> ENTITY_CONSTRUCTOR_CACHE = new WeakHashMap, Constructor>(); @@ -619,6 +610,7 @@ public class NMS { private static final Location PACKET_CACHE_LOCATION = new Location(null, 0, 0, 0); private static Field PATHFINDING_RANGE = getField(NavigationAbstract.class, "a"); private static final Random RANDOM = Util.getFastRandom(); + private static Field TRACKED_ENTITY_SET = NMS.getField(EntityTracker.class, "c"); static { try { diff --git a/src/main/java/net/citizensnpcs/util/nms/PlayerlistTrackerEntry.java b/src/main/java/net/citizensnpcs/util/nms/PlayerlistTrackerEntry.java new file mode 100644 index 000000000..682ddc726 --- /dev/null +++ b/src/main/java/net/citizensnpcs/util/nms/PlayerlistTrackerEntry.java @@ -0,0 +1,53 @@ +package net.citizensnpcs.util.nms; + +import java.lang.reflect.Field; + +import net.citizensnpcs.util.NMS; +import net.minecraft.server.v1_8_R1.Entity; +import net.minecraft.server.v1_8_R1.EntityPlayer; +import net.minecraft.server.v1_8_R1.EntityTrackerEntry; +import net.minecraft.server.v1_8_R1.EnumPlayerInfoAction; +import net.minecraft.server.v1_8_R1.PacketPlayOutPlayerInfo; + +import org.bukkit.entity.Player; + +public class PlayerlistTrackerEntry extends EntityTrackerEntry { + public PlayerlistTrackerEntry(Entity entity, int i, int j, boolean flag) { + super(entity, i, j, flag); + } + + public PlayerlistTrackerEntry(EntityTrackerEntry entry) { + this(entry.tracker, entry.b, entry.c, getU(entry)); + } + + @Override + public void updatePlayer(EntityPlayer entityplayer) { + if (entityplayer != this.tracker && c(entityplayer)) { + if (!this.trackedPlayers.contains(entityplayer) + && ((entityplayer.u().getPlayerChunkMap().a(entityplayer, this.tracker.ae, this.tracker.ag)) || (this.tracker.attachedToPlayer))) { + if ((this.tracker instanceof EntityPlayer)) { + Player player = ((EntityPlayer) this.tracker).getBukkitEntity(); + if (!entityplayer.getBukkitEntity().canSee(player)) { + return; + } + entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo( + EnumPlayerInfoAction.ADD_PLAYER, (EntityPlayer) this.tracker)); + } + } + } + super.updatePlayer(entityplayer); + } + + private static boolean getU(EntityTrackerEntry entry) { + try { + return (Boolean) U.get(entry); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return false; + } + + private static Field U = NMS.getField(EntityTrackerEntry.class, "u"); +}