summaryrefslogtreecommitdiffstats
path: root/nms-patches/PacketStatusListener.patch
blob: 9de1eba10857e5c72b5ef509e81ae5eb8aeca8cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
--- ../work/decompile-8eb82bde//net/minecraft/server/PacketStatusListener.java	2015-02-05 19:03:06.828858157 +0000
+++ src/main/java/net/minecraft/server/PacketStatusListener.java	2015-02-05 19:03:06.828858157 +0000
@@ -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.aE()));
+        // this.networkManager.handle(new PacketStatusOutServerInfo(this.minecraftServer.aE()));
+        // 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<Player> iterator() throws UnsupportedOperationException {
+                return new Iterator<Player>() {
+                    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<GameProfile> profiles = new java.util.ArrayList<GameProfile>(players.length);
+        for (Object player : players) {
+            if (player != null) {
+                profiles.add(((EntityPlayer) player).getProfile());
+            }
+        }
+
+        ServerPingPlayerSample playerSample = new 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 ServerPingServerData(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
     }
 }