--- /home/matt/mc-dev-private//net/minecraft/server/PacketStatusListener.java 2015-05-05 21:53:39.601104451 +0100 +++ src/main/java/net/minecraft/server/PacketStatusListener.java 2015-05-05 21:53:39.601104451 +0100 @@ -1,5 +1,16 @@ package net.minecraft.server; +// CraftBukkit start +import com.mojang.authlib.GameProfile; +import io.netty.channel.ChannelFutureListener; +import java.net.InetSocketAddress; +import java.util.Iterator; + +import org.bukkit.craftbukkit.util.CraftIconCache; +import org.bukkit.entity.Player; + +// CraftBukkit end + public class PacketStatusListener implements PacketStatusInListener { private final MinecraftServer minecraftServer; @@ -12,11 +23,116 @@ public void a(IChatBaseComponent ichatbasecomponent) {} + // CraftBukkit start + private static final int WAITING = 0; + private static final int PING = 1; + private static final int DONE = 2; + private int state = WAITING; + // CraftBukkit end + public void a(PacketStatusInStart packetstatusinstart) { - this.networkManager.handle(new PacketStatusOutServerInfo(this.minecraftServer.aG())); + // this.networkManager.handle(new PacketStatusOutServerInfo(this.minecraftServer.aG())); + // CraftBukkit start - fire ping event + if (state != WAITING) { + networkManager.close(null); + return; + } + state = PING; + final Object[] players = minecraftServer.getPlayerList().players.toArray(); + class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { + CraftIconCache icon = minecraftServer.server.getServerIcon(); + + ServerListPingEvent() { + super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.getMotd(), minecraftServer.getPlayerList().getMaxPlayers()); + } + + @Override + public void setServerIcon(org.bukkit.util.CachedServerIcon icon) { + if (!(icon instanceof CraftIconCache)) { + throw new IllegalArgumentException(icon + " was not created by " + org.bukkit.craftbukkit.CraftServer.class); + } + this.icon = (CraftIconCache) icon; + } + + @Override + public Iterator iterator() throws UnsupportedOperationException { + return new Iterator() { + int i; + int ret = Integer.MIN_VALUE; + EntityPlayer player; + + @Override + public boolean hasNext() { + if (player != null) { + return true; + } + final Object[] currentPlayers = players; + for (int length = currentPlayers.length, i = this.i; i < length; i++) { + final EntityPlayer player = (EntityPlayer) currentPlayers[i]; + if (player != null) { + this.i = i + 1; + this.player = player; + return true; + } + } + return false; + } + + @Override + public Player next() { + if (!hasNext()) { + throw new java.util.NoSuchElementException(); + } + final EntityPlayer player = this.player; + this.player = null; + this.ret = this.i - 1; + return player.getBukkitEntity(); + } + + @Override + public void remove() { + final Object[] currentPlayers = players; + final int i = this.ret; + if (i < 0 || currentPlayers[i] == null) { + throw new IllegalStateException(); + } + currentPlayers[i] = null; + } + }; + } + } + + ServerListPingEvent event = new ServerListPingEvent(); + this.minecraftServer.server.getPluginManager().callEvent(event); + + java.util.List profiles = new java.util.ArrayList(players.length); + for (Object player : players) { + if (player != null) { + profiles.add(((EntityPlayer) player).getProfile()); + } + } + + ServerPing.ServerPingPlayerSample playerSample = new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size()); + playerSample.a(profiles.toArray(new GameProfile[profiles.size()])); + + ServerPing ping = new ServerPing(); + ping.setFavicon(event.icon.value); + ping.setMOTD(new ChatComponentText(event.getMotd())); + ping.setPlayerSample(playerSample); + ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), 47)); // TODO: Update when protocol changes + + this.networkManager.handle(new PacketStatusOutServerInfo(ping)); + // CraftBukkit end } public void a(PacketStatusInPing packetstatusinping) { - this.networkManager.handle(new PacketStatusOutPong(packetstatusinping.a())); + // CraftBukkit start + if (state != PING) { + networkManager.close(null); + return; + } + state = DONE; + this.networkManager.a(new PacketStatusOutPong(packetstatusinping.a()), ChannelFutureListener.CLOSE); // Close on completion + // CraftBukkit end } }