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