From a2af8f0a730c11af84d995ccfcf36544ddb4eea0 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Thu, 27 Apr 2017 21:53:31 -0700 Subject: [PATCH] SPIGOT-3207: Fix hiding players in a BukkitRunnable after joining This happened because "joining" wasn't cleared until the player was ticked. Runnables (presumably) ran _after_ the player list packet was sent, but before the player was ticked; thus, the player list packet was sent, but not cleared. The fix is to replace joining with hasSentListPacket, which is set immediately before sending any player list packets (thus, if hidePlayer is called after, it sees that the list packet has been sent and sends a new one to reset it). With this fix, the player is added to the list and then removed shortly afterwards. The reason why running /hideall in the example wouldn't fix the invisibility is because the server already thinks the player's been removed from the list (as they're hidden), and thus doesn't want to send another hide packet. This is correct behavior assuming that they get hidden correctly the first time, which they now do. --- nms-patches/EntityPlayer.patch | 55 ++++++++++--------- nms-patches/PlayerList.patch | 41 +++++++------- .../craftbukkit/entity/CraftPlayer.java | 4 +- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/nms-patches/EntityPlayer.patch b/nms-patches/EntityPlayer.patch index 17c735d2f7..dfbb51c142 100644 --- a/nms-patches/EntityPlayer.patch +++ b/nms-patches/EntityPlayer.patch @@ -23,7 +23,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { private static final Logger bR = LogManager.getLogger(); -@@ -44,6 +60,18 @@ +@@ -44,6 +60,19 @@ public int ping; public boolean viewingCredits; @@ -37,12 +37,13 @@ + public boolean keepLevel = false; + public double maxHealthCache; + public boolean joining = true; ++ public boolean sentListPacket = false; + // CraftBukkit end + public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { super(worldserver, gameprofile); playerinteractmanager.player = this; -@@ -67,13 +95,18 @@ +@@ -67,13 +96,18 @@ this.server = minecraftserver; this.bU = minecraftserver.getPlayerList().a((EntityHuman) this); @@ -62,7 +63,7 @@ } public void a(NBTTagCompound nbttagcompound) { -@@ -86,6 +119,7 @@ +@@ -86,6 +120,7 @@ } } @@ -70,7 +71,7 @@ } public static void a(DataConverterManager dataconvertermanager) { -@@ -119,8 +153,33 @@ +@@ -119,8 +154,33 @@ nbttagcompound1.set("Entity", nbttagcompound2); nbttagcompound.set("RootVehicle", nbttagcompound1); } @@ -104,7 +105,7 @@ public void levelDown(int i) { super.levelDown(i); -@@ -151,6 +210,11 @@ +@@ -151,6 +211,11 @@ } public void A_() { @@ -116,7 +117,7 @@ this.playerInteractManager.a(); --this.invulnerableTicks; if (this.noDamageTicks > 0) { -@@ -210,7 +274,7 @@ +@@ -210,7 +275,7 @@ } if (this.getHealth() != this.lastHealthSent || this.cc != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.cd) { @@ -125,7 +126,7 @@ this.lastHealthSent = this.getHealth(); this.cc = this.foodData.getFoodLevel(); this.cd = this.foodData.getSaturationLevel() == 0.0F; -@@ -231,6 +295,12 @@ +@@ -231,6 +296,12 @@ this.a(IScoreboardCriteria.i, MathHelper.f((float) this.bX)); } @@ -138,7 +139,7 @@ if (this.getArmorStrength() != this.bY) { this.bY = this.getArmorStrength(); this.a(IScoreboardCriteria.j, MathHelper.f((float) this.bY)); -@@ -255,6 +325,16 @@ +@@ -255,6 +326,16 @@ this.o(); } @@ -155,7 +156,7 @@ } catch (Throwable throwable) { CrashReport crashreport = CrashReport.a(throwable, "Ticking player"); CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Player being ticked"); -@@ -265,12 +345,11 @@ +@@ -265,12 +346,11 @@ } private void a(IScoreboardCriteria iscoreboardcriteria, int i) { @@ -170,7 +171,7 @@ scoreboardscore.setScore(i); } -@@ -319,31 +398,61 @@ +@@ -319,31 +399,61 @@ boolean flag = this.world.getGameRules().getBoolean("showDeathMessages"); this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, flag)); @@ -246,7 +247,7 @@ scoreboardscore.incrementScore(); } -@@ -402,13 +511,16 @@ +@@ -402,13 +512,16 @@ } private boolean canPvP() { @@ -265,7 +266,7 @@ this.world.kill(this); if (!this.viewingCredits) { this.viewingCredits = true; -@@ -429,7 +541,10 @@ +@@ -429,7 +542,10 @@ this.b((Statistic) AchievementList.y); } @@ -277,7 +278,7 @@ this.playerConnection.sendPacket(new PacketPlayOutWorldEvent(1032, BlockPosition.ZERO, 0, false)); this.lastSentExp = -1; this.lastHealthSent = -1.0F; -@@ -474,6 +589,7 @@ +@@ -474,6 +590,7 @@ } public void a(boolean flag, boolean flag1, boolean flag2) { @@ -285,7 +286,7 @@ if (this.isSleeping()) { this.x().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(this, 2)); } -@@ -552,23 +668,55 @@ +@@ -552,23 +669,55 @@ this.playerConnection.sendPacket(new PacketPlayOutOpenSignEditor(tileentitysign.getPosition())); } @@ -344,7 +345,7 @@ if (iinventory instanceof ILootable && ((ILootable) iinventory).b() != null && this.isSpectator()) { this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).setChatModifier((new ChatModifier()).setColor(EnumChatFormat.RED)), true); } else { -@@ -582,18 +730,21 @@ +@@ -582,18 +731,21 @@ if (itileinventory.isLocked() && !this.a(itileinventory.getLock()) && !this.isSpectator()) { this.playerConnection.sendPacket(new PacketPlayOutChat(new ChatMessage("container.isLocked", new Object[] { iinventory.getScoreboardDisplayName()}), (byte) 2)); this.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.Y, SoundCategory.BLOCKS, this.locX, this.locY, this.locZ, 1.0F, 1.0F)); @@ -368,7 +369,7 @@ this.activeContainer.windowId = this.containerCounter; this.activeContainer.addSlotListener(this); -@@ -601,8 +752,14 @@ +@@ -601,8 +753,14 @@ } public void openTrade(IMerchant imerchant) { @@ -384,7 +385,7 @@ this.activeContainer.windowId = this.containerCounter; this.activeContainer.addSlotListener(this); InventoryMerchant inventorymerchant = ((ContainerMerchant) this.activeContainer).e(); -@@ -622,13 +779,20 @@ +@@ -622,13 +780,20 @@ } public void openHorseInventory(EntityHorseAbstract entityhorseabstract, IInventory iinventory) { @@ -406,7 +407,7 @@ this.activeContainer.windowId = this.containerCounter; this.activeContainer.addSlotListener(this); } -@@ -665,6 +829,11 @@ +@@ -665,6 +830,11 @@ public void a(Container container, NonNullList nonnulllist) { this.playerConnection.sendPacket(new PacketPlayOutWindowItems(container.windowId, nonnulllist)); this.playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, this.inventory.getCarried())); @@ -418,7 +419,7 @@ } public void setContainerData(Container container, int i, int j) { -@@ -679,6 +848,7 @@ +@@ -679,6 +849,7 @@ } public void closeInventory() { @@ -426,7 +427,7 @@ this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); this.s(); } -@@ -760,7 +930,16 @@ +@@ -760,7 +931,16 @@ public void triggerHealthUpdate() { this.lastHealthSent = -1.0E8F; @@ -443,7 +444,7 @@ public void a(IChatBaseComponent ichatbasecomponent, boolean flag) { this.playerConnection.sendPacket(new PacketPlayOutChat(ichatbasecomponent, (byte) (flag ? 2 : 0))); -@@ -821,6 +1000,18 @@ +@@ -821,6 +1001,18 @@ } public void a(EnumGamemode enumgamemode) { @@ -462,7 +463,7 @@ this.playerInteractManager.setGameMode(enumgamemode); this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(3, (float) enumgamemode.getId())); if (enumgamemode == EnumGamemode.SPECTATOR) { -@@ -846,6 +1037,7 @@ +@@ -846,6 +1038,7 @@ } public boolean a(int i, String s) { @@ -470,7 +471,7 @@ if ("seed".equals(s) && !this.server.aa()) { return true; } else if (!"tell".equals(s) && !"help".equals(s) && !"me".equals(s) && !"trigger".equals(s)) { -@@ -859,6 +1051,15 @@ +@@ -859,6 +1052,15 @@ } else { return true; } @@ -486,7 +487,7 @@ } public String A() { -@@ -870,6 +1071,12 @@ +@@ -870,6 +1072,12 @@ } public void a(PacketPlayInSettings packetplayinsettings) { @@ -499,7 +500,7 @@ this.locale = packetplayinsettings.a(); this.cg = packetplayinsettings.c(); this.ch = packetplayinsettings.d(); -@@ -931,7 +1138,7 @@ +@@ -931,7 +1139,7 @@ this.cj = (Entity) (entity == null ? this : entity); if (entity1 != this.cj) { this.playerConnection.sendPacket(new PacketPlayOutCamera(this.cj)); @@ -508,7 +509,7 @@ } } -@@ -958,7 +1165,7 @@ +@@ -958,7 +1166,7 @@ @Nullable public IChatBaseComponent getPlayerListName() { @@ -517,7 +518,7 @@ } public void a(EnumHand enumhand) { -@@ -975,11 +1182,151 @@ +@@ -975,11 +1183,151 @@ } public void M() { diff --git a/nms-patches/PlayerList.patch b/nms-patches/PlayerList.patch index 143e23eca8..8e815d8c3a 100644 --- a/nms-patches/PlayerList.patch +++ b/nms-patches/PlayerList.patch @@ -167,7 +167,7 @@ NBTTagCompound nbttagcompound1; if (entityplayer.getName().equals(this.server.Q()) && nbttagcompound != null) { -@@ -252,28 +300,72 @@ +@@ -252,28 +300,73 @@ } @@ -211,6 +211,7 @@ + + entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer1})); } ++ entityplayer.sentListPacket = true; + // CraftBukkit end - worldserver.addEntity(entityplayer); @@ -246,7 +247,7 @@ this.savePlayerFile(entityplayer); if (entityplayer.isPassenger()) { Entity entity = entityplayer.getVehicle(); -@@ -305,13 +397,61 @@ +@@ -305,13 +398,61 @@ this.o.remove(uuid); } @@ -311,7 +312,7 @@ GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile); s = "You are banned from this server!\nReason: " + gameprofilebanentry.getReason(); -@@ -319,10 +459,12 @@ +@@ -319,10 +460,12 @@ s = s + "\nYour ban will be removed on " + PlayerList.g.format(gameprofilebanentry.getExpires()); } @@ -327,7 +328,7 @@ IpBanEntry ipbanentry = this.l.get(socketaddress); s = "Your IP address is banned from this server!\nReason: " + ipbanentry.getReason(); -@@ -330,13 +472,25 @@ +@@ -330,13 +473,25 @@ s = s + "\nYour ban will be removed on " + PlayerList.g.format(ipbanentry.getExpires()); } @@ -356,7 +357,7 @@ UUID uuid = EntityHuman.a(gameprofile); ArrayList arraylist = Lists.newArrayList(); -@@ -371,17 +525,27 @@ +@@ -371,17 +526,27 @@ } return new EntityPlayer(this.server, this.server.getWorldServer(0), gameprofile, (PlayerInteractManager) object); @@ -385,7 +386,7 @@ entityplayer.dimension = i; Object object; -@@ -392,6 +556,11 @@ +@@ -392,6 +557,11 @@ } EntityPlayer entityplayer1 = new EntityPlayer(this.server, this.server.getWorldServer(entityplayer.dimension), entityplayer.getProfile(), (PlayerInteractManager) object); @@ -397,7 +398,7 @@ entityplayer1.playerConnection = entityplayer.playerConnection; entityplayer1.copyTo(entityplayer, flag); -@@ -406,43 +575,157 @@ +@@ -406,43 +576,157 @@ entityplayer1.a(s); } @@ -572,7 +573,7 @@ public void f(EntityPlayer entityplayer) { GameProfile gameprofile = entityplayer.getProfile(); int i = this.isOp(gameprofile) ? this.operators.a(gameprofile) : 0; -@@ -481,12 +764,111 @@ +@@ -481,12 +765,111 @@ } public void changeWorld(Entity entity, int i, WorldServer worldserver, WorldServer worldserver1) { @@ -684,7 +685,7 @@ if (entity.dimension == -1) { d0 = MathHelper.a(d0 / 8.0D, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D); d1 = MathHelper.a(d1 / 8.0D, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D); -@@ -505,6 +887,8 @@ +@@ -505,6 +888,8 @@ BlockPosition blockposition; if (i == 1) { @@ -693,7 +694,7 @@ blockposition = worldserver1.getSpawn(); } else { blockposition = worldserver1.getDimensionSpawn(); -@@ -518,16 +902,27 @@ +@@ -518,16 +903,27 @@ worldserver.entityJoinedWorld(entity, false); } } @@ -724,7 +725,7 @@ worldserver1.entityJoinedWorld(entity, false); } -@@ -535,11 +930,23 @@ +@@ -535,11 +931,23 @@ } entity.spawnIn(worldserver1); @@ -749,7 +750,7 @@ this.u = 0; } -@@ -552,6 +959,25 @@ +@@ -552,6 +960,25 @@ } @@ -775,7 +776,7 @@ public void a(Packet packet, int i) { for (int j = 0; j < this.players.size(); ++j) { EntityPlayer entityplayer = (EntityPlayer) this.players.get(j); -@@ -650,11 +1076,23 @@ +@@ -650,11 +1077,23 @@ this.operators.add(new OpListEntry(gameprofile, this.server.q(), this.operators.b(gameprofile))); this.b(this.a(gameprofile.getId()), i); @@ -799,7 +800,7 @@ } private void b(EntityPlayer entityplayer, int i) { -@@ -679,7 +1117,7 @@ +@@ -679,7 +1118,7 @@ } public boolean isOp(GameProfile gameprofile) { @@ -808,7 +809,7 @@ } @Nullable -@@ -703,6 +1141,12 @@ +@@ -703,6 +1142,12 @@ for (int j = 0; j < this.players.size(); ++j) { EntityPlayer entityplayer = (EntityPlayer) this.players.get(j); @@ -821,7 +822,7 @@ if (entityplayer != entityhuman && entityplayer.dimension == i) { double d4 = d0 - entityplayer.locX; double d5 = d1 - entityplayer.locY; -@@ -750,7 +1194,7 @@ +@@ -750,7 +1195,7 @@ public void reloadWhitelist() {} public void b(EntityPlayer entityplayer, WorldServer worldserver) { @@ -830,7 +831,7 @@ entityplayer.playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE)); entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateTime(worldserver.getTime(), worldserver.getDayTime(), worldserver.getGameRules().getBoolean("doDaylightCycle"))); -@@ -758,16 +1202,21 @@ +@@ -758,16 +1203,21 @@ entityplayer.playerConnection.sendPacket(new PacketPlayOutSpawnPosition(blockposition)); if (worldserver.W()) { @@ -856,7 +857,7 @@ entityplayer.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); } -@@ -780,7 +1229,7 @@ +@@ -780,7 +1230,7 @@ } public String[] getSeenPlayers() { @@ -865,7 +866,7 @@ } public boolean getHasWhitelist() { -@@ -829,17 +1278,29 @@ +@@ -829,17 +1279,29 @@ } public void u() { @@ -898,7 +899,7 @@ } public void sendMessage(IChatBaseComponent ichatbasecomponent) { -@@ -876,8 +1337,10 @@ +@@ -876,8 +1338,10 @@ WorldServer[] aworldserver = this.server.worldServer; int j = aworldserver.length; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 9f3402d115..edf583b6eb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -911,8 +911,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { entry.clear(getHandle()); } - // Remove the hidden player from this player user list - if (!other.joining) { + // Remove the hidden player from this player user list, if they're on it + if (other.sentListPacket) { getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, other)); } }