001    package net.minecraft.src;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    import java.io.DataInputStream;
006    import java.io.DataOutputStream;
007    import java.io.IOException;
008    import java.net.InetSocketAddress;
009    import java.net.Socket;
010    import java.util.Collections;
011    import java.util.List;
012    import org.lwjgl.input.Keyboard;
013    
014    @SideOnly(Side.CLIENT)
015    public class GuiMultiplayer extends GuiScreen
016    {
017        /** Number of outstanding ThreadPollServers threads */
018        private static int threadsPending = 0;
019    
020        /** Lock object for use with synchronized() */
021        private static Object lock = new Object();
022    
023        /**
024         * A reference to the screen object that created this. Used for navigating between screens.
025         */
026        private GuiScreen parentScreen;
027    
028        /** Slot container for the server list */
029        private GuiSlotServer serverSlotContainer;
030        private ServerList internetServerList;
031    
032        /** Index of the currently selected server */
033        private int selectedServer = -1;
034    
035        /** The 'Edit' button */
036        private GuiButton buttonEdit;
037    
038        /** The 'Join Server' button */
039        private GuiButton buttonSelect;
040    
041        /** The 'Delete' button */
042        private GuiButton buttonDelete;
043    
044        /** The 'Delete' button was clicked */
045        private boolean deleteClicked = false;
046    
047        /** The 'Add server' button was clicked */
048        private boolean addClicked = false;
049    
050        /** The 'Edit' button was clicked */
051        private boolean editClicked = false;
052    
053        /** The 'Direct Connect' button was clicked */
054        private boolean directClicked = false;
055    
056        /** This GUI's lag tooltip text or null if no lag icon is being hovered. */
057        private String lagTooltip = null;
058    
059        /** Instance of ServerData. */
060        private ServerData theServerData = null;
061        private LanServerList localNetworkServerList;
062        private ThreadLanServerFind localServerFindThread;
063        private int field_74039_z;
064        private boolean field_74024_A;
065        private List field_74026_B = Collections.emptyList();
066    
067        public GuiMultiplayer(GuiScreen par1GuiScreen)
068        {
069            this.parentScreen = par1GuiScreen;
070        }
071    
072        /**
073         * Adds the buttons (and other controls) to the screen in question.
074         */
075        public void initGui()
076        {
077            Keyboard.enableRepeatEvents(true);
078            this.controlList.clear();
079    
080            if (!this.field_74024_A)
081            {
082                this.field_74024_A = true;
083                this.internetServerList = new ServerList(this.mc);
084                this.internetServerList.loadServerList();
085                this.localNetworkServerList = new LanServerList();
086    
087                try
088                {
089                    this.localServerFindThread = new ThreadLanServerFind(this.localNetworkServerList);
090                    this.localServerFindThread.start();
091                }
092                catch (Exception var2)
093                {
094                    System.out.println("Unable to start LAN server detection: " + var2.getMessage());
095                }
096    
097                this.serverSlotContainer = new GuiSlotServer(this);
098            }
099            else
100            {
101                this.serverSlotContainer.func_77207_a(this.width, this.height, 32, this.height - 64);
102            }
103    
104            this.initGuiControls();
105        }
106    
107        /**
108         * Populate the GuiScreen controlList
109         */
110        public void initGuiControls()
111        {
112            StringTranslate var1 = StringTranslate.getInstance();
113            this.controlList.add(this.buttonEdit = new GuiButton(7, this.width / 2 - 154, this.height - 28, 70, 20, var1.translateKey("selectServer.edit")));
114            this.controlList.add(this.buttonDelete = new GuiButton(2, this.width / 2 - 74, this.height - 28, 70, 20, var1.translateKey("selectServer.delete")));
115            this.controlList.add(this.buttonSelect = new GuiButton(1, this.width / 2 - 154, this.height - 52, 100, 20, var1.translateKey("selectServer.select")));
116            this.controlList.add(new GuiButton(4, this.width / 2 - 50, this.height - 52, 100, 20, var1.translateKey("selectServer.direct")));
117            this.controlList.add(new GuiButton(3, this.width / 2 + 4 + 50, this.height - 52, 100, 20, var1.translateKey("selectServer.add")));
118            this.controlList.add(new GuiButton(8, this.width / 2 + 4, this.height - 28, 70, 20, var1.translateKey("selectServer.refresh")));
119            this.controlList.add(new GuiButton(0, this.width / 2 + 4 + 76, this.height - 28, 75, 20, var1.translateKey("gui.cancel")));
120            boolean var2 = this.selectedServer >= 0 && this.selectedServer < this.serverSlotContainer.getSize();
121            this.buttonSelect.enabled = var2;
122            this.buttonEdit.enabled = var2;
123            this.buttonDelete.enabled = var2;
124        }
125    
126        /**
127         * Called from the main game loop to update the screen.
128         */
129        public void updateScreen()
130        {
131            super.updateScreen();
132            ++this.field_74039_z;
133    
134            if (this.localNetworkServerList.func_77553_a())
135            {
136                this.field_74026_B = this.localNetworkServerList.func_77554_c();
137                this.localNetworkServerList.func_77552_b();
138            }
139        }
140    
141        /**
142         * Called when the screen is unloaded. Used to disable keyboard repeat events
143         */
144        public void onGuiClosed()
145        {
146            Keyboard.enableRepeatEvents(false);
147    
148            if (this.localServerFindThread != null)
149            {
150                this.localServerFindThread.interrupt();
151                this.localServerFindThread = null;
152            }
153        }
154    
155        /**
156         * Fired when a control is clicked. This is the equivalent of ActionListener.actionPerformed(ActionEvent e).
157         */
158        protected void actionPerformed(GuiButton par1GuiButton)
159        {
160            if (par1GuiButton.enabled)
161            {
162                if (par1GuiButton.id == 2)
163                {
164                    String var2 = this.internetServerList.getServerData(this.selectedServer).serverName;
165    
166                    if (var2 != null)
167                    {
168                        this.deleteClicked = true;
169                        StringTranslate var3 = StringTranslate.getInstance();
170                        String var4 = var3.translateKey("selectServer.deleteQuestion");
171                        String var5 = "\'" + var2 + "\' " + var3.translateKey("selectServer.deleteWarning");
172                        String var6 = var3.translateKey("selectServer.deleteButton");
173                        String var7 = var3.translateKey("gui.cancel");
174                        GuiYesNo var8 = new GuiYesNo(this, var4, var5, var6, var7, this.selectedServer);
175                        this.mc.displayGuiScreen(var8);
176                    }
177                }
178                else if (par1GuiButton.id == 1)
179                {
180                    this.joinServer(this.selectedServer);
181                }
182                else if (par1GuiButton.id == 4)
183                {
184                    this.directClicked = true;
185                    this.mc.displayGuiScreen(new GuiScreenServerList(this, this.theServerData = new ServerData(StatCollector.translateToLocal("selectServer.defaultName"), "")));
186                }
187                else if (par1GuiButton.id == 3)
188                {
189                    this.addClicked = true;
190                    this.mc.displayGuiScreen(new GuiScreenAddServer(this, this.theServerData = new ServerData(StatCollector.translateToLocal("selectServer.defaultName"), "")));
191                }
192                else if (par1GuiButton.id == 7)
193                {
194                    this.editClicked = true;
195                    ServerData var9 = this.internetServerList.getServerData(this.selectedServer);
196                    this.mc.displayGuiScreen(new GuiScreenAddServer(this, this.theServerData = new ServerData(var9.serverName, var9.serverIP)));
197                }
198                else if (par1GuiButton.id == 0)
199                {
200                    this.mc.displayGuiScreen(this.parentScreen);
201                }
202                else if (par1GuiButton.id == 8)
203                {
204                    this.mc.displayGuiScreen(new GuiMultiplayer(this.parentScreen));
205                }
206                else
207                {
208                    this.serverSlotContainer.actionPerformed(par1GuiButton);
209                }
210            }
211        }
212    
213        public void confirmClicked(boolean par1, int par2)
214        {
215            if (this.deleteClicked)
216            {
217                this.deleteClicked = false;
218    
219                if (par1)
220                {
221                    this.internetServerList.removeServerData(par2);
222                    this.internetServerList.saveServerList();
223                    this.selectedServer = -1;
224                }
225    
226                this.mc.displayGuiScreen(this);
227            }
228            else if (this.directClicked)
229            {
230                this.directClicked = false;
231    
232                if (par1)
233                {
234                    this.func_74002_a(this.theServerData);
235                }
236                else
237                {
238                    this.mc.displayGuiScreen(this);
239                }
240            }
241            else if (this.addClicked)
242            {
243                this.addClicked = false;
244    
245                if (par1)
246                {
247                    this.internetServerList.addServerData(this.theServerData);
248                    this.internetServerList.saveServerList();
249                    this.selectedServer = -1;
250                }
251    
252                this.mc.displayGuiScreen(this);
253            }
254            else if (this.editClicked)
255            {
256                this.editClicked = false;
257    
258                if (par1)
259                {
260                    ServerData var3 = this.internetServerList.getServerData(this.selectedServer);
261                    var3.serverName = this.theServerData.serverName;
262                    var3.serverIP = this.theServerData.serverIP;
263                    this.internetServerList.saveServerList();
264                }
265    
266                this.mc.displayGuiScreen(this);
267            }
268        }
269    
270        /**
271         * Fired when a key is typed. This is the equivalent of KeyListener.keyTyped(KeyEvent e).
272         */
273        protected void keyTyped(char par1, int par2)
274        {
275            int var3 = this.selectedServer;
276    
277            if (par2 == 59)
278            {
279                this.mc.gameSettings.hideServerAddress = !this.mc.gameSettings.hideServerAddress;
280                this.mc.gameSettings.saveOptions();
281            }
282            else
283            {
284                if (isShiftKeyDown() && par2 == 200)
285                {
286                    if (var3 > 0 && var3 < this.internetServerList.countServers())
287                    {
288                        this.internetServerList.swapServers(var3, var3 - 1);
289                        --this.selectedServer;
290    
291                        if (var3 < this.internetServerList.countServers() - 1)
292                        {
293                            this.serverSlotContainer.func_77208_b(-this.serverSlotContainer.slotHeight);
294                        }
295                    }
296                }
297                else if (isShiftKeyDown() && par2 == 208)
298                {
299                    if (var3 < this.internetServerList.countServers() - 1)
300                    {
301                        this.internetServerList.swapServers(var3, var3 + 1);
302                        ++this.selectedServer;
303    
304                        if (var3 > 0)
305                        {
306                            this.serverSlotContainer.func_77208_b(this.serverSlotContainer.slotHeight);
307                        }
308                    }
309                }
310                else if (par1 == 13)
311                {
312                    this.actionPerformed((GuiButton)this.controlList.get(2));
313                }
314            }
315        }
316    
317        /**
318         * Draws the screen and all the components in it.
319         */
320        public void drawScreen(int par1, int par2, float par3)
321        {
322            this.lagTooltip = null;
323            StringTranslate var4 = StringTranslate.getInstance();
324            this.drawDefaultBackground();
325            this.serverSlotContainer.drawScreen(par1, par2, par3);
326            this.drawCenteredString(this.fontRenderer, var4.translateKey("multiplayer.title"), this.width / 2, 20, 16777215);
327            super.drawScreen(par1, par2, par3);
328    
329            if (this.lagTooltip != null)
330            {
331                this.func_74007_a(this.lagTooltip, par1, par2);
332            }
333        }
334    
335        /**
336         * Join server by slot index
337         */
338        private void joinServer(int par1)
339        {
340            if (par1 < this.internetServerList.countServers())
341            {
342                this.func_74002_a(this.internetServerList.getServerData(par1));
343            }
344            else
345            {
346                par1 -= this.internetServerList.countServers();
347    
348                if (par1 < this.field_74026_B.size())
349                {
350                    LanServer var2 = (LanServer)this.field_74026_B.get(par1);
351                    this.func_74002_a(new ServerData(var2.func_77487_a(), var2.func_77488_b()));
352                }
353            }
354        }
355    
356        private void func_74002_a(ServerData par1ServerData)
357        {
358            this.mc.displayGuiScreen(new GuiConnecting(this.mc, par1ServerData));
359        }
360    
361        private void func_74017_b(ServerData par1ServerData) throws IOException
362        {
363            ServerAddress var2 = ServerAddress.func_78860_a(par1ServerData.serverIP);
364            Socket var3 = null;
365            DataInputStream var4 = null;
366            DataOutputStream var5 = null;
367    
368            try
369            {
370                var3 = new Socket();
371                var3.setSoTimeout(3000);
372                var3.setTcpNoDelay(true);
373                var3.setTrafficClass(18);
374                var3.connect(new InetSocketAddress(var2.getIP(), var2.getPort()), 3000);
375                var4 = new DataInputStream(var3.getInputStream());
376                var5 = new DataOutputStream(var3.getOutputStream());
377                var5.write(254);
378    
379                if (var4.read() != 255)
380                {
381                    throw new IOException("Bad message");
382                }
383    
384                String var6 = Packet.readString(var4, 256);
385                char[] var7 = var6.toCharArray();
386    
387                for (int var8 = 0; var8 < var7.length; ++var8)
388                {
389                    if (var7[var8] != 167 && ChatAllowedCharacters.allowedCharacters.indexOf(var7[var8]) < 0)
390                    {
391                        var7[var8] = 63;
392                    }
393                }
394    
395                var6 = new String(var7);
396                String[] var27 = var6.split("\u00a7");
397                var6 = var27[0];
398                int var9 = -1;
399                int var10 = -1;
400    
401                try
402                {
403                    var9 = Integer.parseInt(var27[1]);
404                    var10 = Integer.parseInt(var27[2]);
405                }
406                catch (Exception var25)
407                {
408                    ;
409                }
410    
411                par1ServerData.serverMOTD = "\u00a77" + var6;
412    
413                if (var9 >= 0 && var10 > 0)
414                {
415                    par1ServerData.populationInfo = "\u00a77" + var9 + "\u00a78/\u00a77" + var10;
416                }
417                else
418                {
419                    par1ServerData.populationInfo = "\u00a78???";
420                }
421            }
422            finally
423            {
424                try
425                {
426                    if (var4 != null)
427                    {
428                        var4.close();
429                    }
430                }
431                catch (Throwable var24)
432                {
433                    ;
434                }
435    
436                try
437                {
438                    if (var5 != null)
439                    {
440                        var5.close();
441                    }
442                }
443                catch (Throwable var23)
444                {
445                    ;
446                }
447    
448                try
449                {
450                    if (var3 != null)
451                    {
452                        var3.close();
453                    }
454                }
455                catch (Throwable var22)
456                {
457                    ;
458                }
459            }
460        }
461    
462        protected void func_74007_a(String par1Str, int par2, int par3)
463        {
464            if (par1Str != null)
465            {
466                int var4 = par2 + 12;
467                int var5 = par3 - 12;
468                int var6 = this.fontRenderer.getStringWidth(par1Str);
469                this.drawGradientRect(var4 - 3, var5 - 3, var4 + var6 + 3, var5 + 8 + 3, -1073741824, -1073741824);
470                this.fontRenderer.drawStringWithShadow(par1Str, var4, var5, -1);
471            }
472        }
473    
474        static ServerList func_74006_a(GuiMultiplayer par0GuiMultiplayer)
475        {
476            return par0GuiMultiplayer.internetServerList;
477        }
478    
479        static List func_74003_b(GuiMultiplayer par0GuiMultiplayer)
480        {
481            return par0GuiMultiplayer.field_74026_B;
482        }
483    
484        static int func_74020_c(GuiMultiplayer par0GuiMultiplayer)
485        {
486            return par0GuiMultiplayer.selectedServer;
487        }
488    
489        static int func_74015_a(GuiMultiplayer par0GuiMultiplayer, int par1)
490        {
491            return par0GuiMultiplayer.selectedServer = par1;
492        }
493    
494        /**
495         * Return buttonSelect GuiButton
496         */
497        static GuiButton getButtonSelect(GuiMultiplayer par0GuiMultiplayer)
498        {
499            return par0GuiMultiplayer.buttonSelect;
500        }
501    
502        /**
503         * Return buttonEdit GuiButton
504         */
505        static GuiButton getButtonEdit(GuiMultiplayer par0GuiMultiplayer)
506        {
507            return par0GuiMultiplayer.buttonEdit;
508        }
509    
510        /**
511         * Return buttonDelete GuiButton
512         */
513        static GuiButton getButtonDelete(GuiMultiplayer par0GuiMultiplayer)
514        {
515            return par0GuiMultiplayer.buttonDelete;
516        }
517    
518        static void func_74008_b(GuiMultiplayer par0GuiMultiplayer, int par1)
519        {
520            par0GuiMultiplayer.joinServer(par1);
521        }
522    
523        static int func_74010_g(GuiMultiplayer par0GuiMultiplayer)
524        {
525            return par0GuiMultiplayer.field_74039_z;
526        }
527    
528        static Object func_74011_h()
529        {
530            return lock;
531        }
532    
533        static int func_74012_i()
534        {
535            return threadsPending;
536        }
537    
538        static int func_74021_j()
539        {
540            return threadsPending++;
541        }
542    
543        static void func_74013_a(GuiMultiplayer par0GuiMultiplayer, ServerData par1ServerData) throws IOException
544        {
545            par0GuiMultiplayer.func_74017_b(par1ServerData);
546        }
547    
548        static int func_74018_k()
549        {
550            return threadsPending--;
551        }
552    
553        static String func_74009_a(GuiMultiplayer par0GuiMultiplayer, String par1Str)
554        {
555            return par0GuiMultiplayer.lagTooltip = par1Str;
556        }
557    }