    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.theServerData = new ServerData(var9.serverName, var9.serverIP);
    197                    this.theServerData.func_82819_b(var9.func_82820_d());
    198                    this.mc.displayGuiScreen(new GuiScreenAddServer(this, this.theServerData));
    199                }
    200                else if (par1GuiButton.id == 0)
    201                {
    202                    this.mc.displayGuiScreen(this.parentScreen);
    203                }
    204                else if (par1GuiButton.id == 8)
    205                {
    206                    this.mc.displayGuiScreen(new GuiMultiplayer(this.parentScreen));
    207                }
    208                else
    209                {
    210                    this.serverSlotContainer.actionPerformed(par1GuiButton);
    211                }
    212            }
    213        }
    214
    215        public void confirmClicked(boolean par1, int par2)
    216        {
    217            if (this.deleteClicked)
    218            {
    219                this.deleteClicked = false;
    220
    221                if (par1)
    222                {
    223                    this.internetServerList.removeServerData(par2);
    224                    this.internetServerList.saveServerList();
    225                    this.selectedServer = -1;
    226                }
    227
    228                this.mc.displayGuiScreen(this);
    229            }
    230            else if (this.directClicked)
    231            {
    232                this.directClicked = false;
    233
    234                if (par1)
    235                {
    236                    this.func_74002_a(this.theServerData);
    237                }
    238                else
    239                {
    240                    this.mc.displayGuiScreen(this);
    241                }
    242            }
    243            else if (this.addClicked)
    244            {
    245                this.addClicked = false;
    246
    247                if (par1)
    248                {
    249                    this.internetServerList.addServerData(this.theServerData);
    250                    this.internetServerList.saveServerList();
    251                    this.selectedServer = -1;
    252                }
    253
    254                this.mc.displayGuiScreen(this);
    255            }
    256            else if (this.editClicked)
    257            {
    258                this.editClicked = false;
    259
    260                if (par1)
    261                {
    262                    ServerData var3 = this.internetServerList.getServerData(this.selectedServer);
    263                    var3.serverName = this.theServerData.serverName;
    264                    var3.serverIP = this.theServerData.serverIP;
    265                    var3.func_82819_b(this.theServerData.func_82820_d());
    266                    this.internetServerList.saveServerList();
    267                }
    268
    269                this.mc.displayGuiScreen(this);
    270            }
    271        }
    272
    273        /**
    274         * Fired when a key is typed. This is the equivalent of KeyListener.keyTyped(KeyEvent e).
    275         */
    276        protected void keyTyped(char par1, int par2)
    277        {
    278            int var3 = this.selectedServer;
    279
    280            if (par2 == 59)
    281            {
    282                this.mc.gameSettings.hideServerAddress = !this.mc.gameSettings.hideServerAddress;
    283                this.mc.gameSettings.saveOptions();
    284            }
    285            else
    286            {
    287                if (isShiftKeyDown() && par2 == 200)
    288                {
    289                    if (var3 > 0 && var3 < this.internetServerList.countServers())
    290                    {
    291                        this.internetServerList.swapServers(var3, var3 - 1);
    292                        --this.selectedServer;
    293
    294                        if (var3 < this.internetServerList.countServers() - 1)
    295                        {
    296                            this.serverSlotContainer.func_77208_b(-this.serverSlotContainer.slotHeight);
    297                        }
    298                    }
    299                }
    300                else if (isShiftKeyDown() && par2 == 208)
    301                {
    302                    if (var3 < this.internetServerList.countServers() - 1)
    303                    {
    304                        this.internetServerList.swapServers(var3, var3 + 1);
    305                        ++this.selectedServer;
    306
    307                        if (var3 > 0)
    308                        {
    309                            this.serverSlotContainer.func_77208_b(this.serverSlotContainer.slotHeight);
    310                        }
    311                    }
    312                }
    313                else if (par1 == 13)
    314                {
    315                    this.actionPerformed((GuiButton)this.controlList.get(2));
    316                }
    317                else
    318                {
    319                    super.keyTyped(par1, par2);
    320                }
    321            }
    322        }
    323
    324        /**
    325         * Draws the screen and all the components in it.
    326         */
    327        public void drawScreen(int par1, int par2, float par3)
    328        {
    329            this.lagTooltip = null;
    330            StringTranslate var4 = StringTranslate.getInstance();
    331            this.drawDefaultBackground();
    332            this.serverSlotContainer.drawScreen(par1, par2, par3);
    333            this.drawCenteredString(this.fontRenderer, var4.translateKey("multiplayer.title"), this.width / 2, 20, 16777215);
    334            super.drawScreen(par1, par2, par3);
    335
    336            if (this.lagTooltip != null)
    337            {
    338                this.func_74007_a(this.lagTooltip, par1, par2);
    339            }
    340        }
    341
    342        /**
    343         * Join server by slot index
    344         */
    345        private void joinServer(int par1)
    346        {
    347            if (par1 < this.internetServerList.countServers())
    348            {
    349                this.func_74002_a(this.internetServerList.getServerData(par1));
    350            }
    351            else
    352            {
    353                par1 -= this.internetServerList.countServers();
    354
    355                if (par1 < this.field_74026_B.size())
    356                {
    357                    LanServer var2 = (LanServer)this.field_74026_B.get(par1);
    358                    this.func_74002_a(new ServerData(var2.func_77487_a(), var2.func_77488_b()));
    359                }
    360            }
    361        }
    362
    363        private void func_74002_a(ServerData par1ServerData)
    364        {
    365            this.mc.displayGuiScreen(new GuiConnecting(this.mc, par1ServerData));
    366        }
    367
    368        private static void func_74017_b(ServerData par1ServerData) throws IOException
    369        {
    370            ServerAddress var1 = ServerAddress.func_78860_a(par1ServerData.serverIP);
    371            Socket var2 = null;
    372            DataInputStream var3 = null;
    373            DataOutputStream var4 = null;
    374
    375            try
    376            {
    377                var2 = new Socket();
    378                var2.setSoTimeout(3000);
    379                var2.setTcpNoDelay(true);
    380                var2.setTrafficClass(18);
    381                var2.connect(new InetSocketAddress(var1.getIP(), var1.getPort()), 3000);
    382                var3 = new DataInputStream(var2.getInputStream());
    383                var4 = new DataOutputStream(var2.getOutputStream());
    384                var4.write(254);
    385                var4.write(1);
    386
    387                if (var3.read() != 255)
    388                {
    389                    throw new IOException("Bad message");
    390                }
    391
    392                String var5 = Packet.readString(var3, 256);
    393                char[] var6 = var5.toCharArray();
    394
    395                for (int var7 = 0; var7 < var6.length; ++var7)
    396                {
    397                    if (var6[var7] != 167 && var6[var7] != 0 && ChatAllowedCharacters.allowedCharacters.indexOf(var6[var7]) < 0)
    398                    {
    399                        var6[var7] = 63;
    400                    }
    401                }
    402
    403                var5 = new String(var6);
    404                int var8;
    405                int var9;
    406                String[] var26;
    407
    408                if (var5.startsWith("\u00a7") && var5.length() > 1)
    409                {
    410                    var26 = var5.substring(1).split("\u0000");
    411
    412                    if (MathHelper.func_82715_a(var26[0], 0) == 1)
    413                    {
    414                        par1ServerData.serverMOTD = var26[3];
    415                        par1ServerData.field_82821_f = MathHelper.func_82715_a(var26[1], par1ServerData.field_82821_f);
    416                        par1ServerData.gameVersion = var26[2];
    417                        var8 = MathHelper.func_82715_a(var26[4], 0);
    418                        var9 = MathHelper.func_82715_a(var26[5], 0);
    419
    420                        if (var8 >= 0 && var9 >= 0)
    421                        {
    422                            par1ServerData.populationInfo = "\u00a77" + var8 + "\u00a78/\u00a77" + var9;
    423                        }
    424                        else
    425                        {
    426                            par1ServerData.populationInfo = "\u00a78???";
    427                        }
    428                    }
    429                    else
    430                    {
    431                        par1ServerData.gameVersion = "???";
    432                        par1ServerData.serverMOTD = "\u00a78???";
    433                        par1ServerData.field_82821_f = 50;
    434                        par1ServerData.populationInfo = "\u00a78???";
    435                    }
    436                }
    437                else
    438                {
    439                    var26 = var5.split("\u00a7");
    440                    var5 = var26[0];
    441                    var8 = -1;
    442                    var9 = -1;
    443
    444                    try
    445                    {
    446                        var8 = Integer.parseInt(var26[1]);
    447                        var9 = Integer.parseInt(var26[2]);
    448                    }
    449                    catch (Exception var24)
    450                    {
    451                        ;
    452                    }
    453
    454                    par1ServerData.serverMOTD = "\u00a77" + var5;
    455
    456                    if (var8 >= 0 && var9 > 0)
    457                    {
    458                        par1ServerData.populationInfo = "\u00a77" + var8 + "\u00a78/\u00a77" + var9;
    459                    }
    460                    else
    461                    {
    462                        par1ServerData.populationInfo = "\u00a78???";
    463                    }
    464
    465                    par1ServerData.gameVersion = "1.3";
    466                    par1ServerData.field_82821_f = 48;
    467                }
    468            }
    469            finally
    470            {
    471                try
    472                {
    473                    if (var3 != null)
    474                    {
    475                        var3.close();
    476                    }
    477                }
    478                catch (Throwable var23)
    479                {
    480                    ;
    481                }
    482
    483                try
    484                {
    485                    if (var4 != null)
    486                    {
    487                        var4.close();
    488                    }
    489                }
    490                catch (Throwable var22)
    491                {
    492                    ;
    493                }
    494
    495                try
    496                {
    497                    if (var2 != null)
    498                    {
    499                        var2.close();
    500                    }
    501                }
    502                catch (Throwable var21)
    503                {
    504                    ;
    505                }
    506            }
    507        }
    508
    509        protected void func_74007_a(String par1Str, int par2, int par3)
    510        {
    511            if (par1Str != null)
    512            {
    513                int var4 = par2 + 12;
    514                int var5 = par3 - 12;
    515                int var6 = this.fontRenderer.getStringWidth(par1Str);
    516                this.drawGradientRect(var4 - 3, var5 - 3, var4 + var6 + 3, var5 + 8 + 3, -1073741824, -1073741824);
    517                this.fontRenderer.drawStringWithShadow(par1Str, var4, var5, -1);
    518            }
    519        }
    520
    521        static ServerList func_74006_a(GuiMultiplayer par0GuiMultiplayer)
    522        {
    523            return par0GuiMultiplayer.internetServerList;
    524        }
    525
    526        static List func_74003_b(GuiMultiplayer par0GuiMultiplayer)
    527        {
    528            return par0GuiMultiplayer.field_74026_B;
    529        }
    530
    531        static int func_74020_c(GuiMultiplayer par0GuiMultiplayer)
    532        {
    533            return par0GuiMultiplayer.selectedServer;
    534        }
    535
    536        static int func_74015_a(GuiMultiplayer par0GuiMultiplayer, int par1)
    537        {
    538            return par0GuiMultiplayer.selectedServer = par1;
    539        }
    540
    541        /**
    542         * Return buttonSelect GuiButton
    543         */
    544        static GuiButton getButtonSelect(GuiMultiplayer par0GuiMultiplayer)
    545        {
    546            return par0GuiMultiplayer.buttonSelect;
    547        }
    548
    549        /**
    550         * Return buttonEdit GuiButton
    551         */
    552        static GuiButton getButtonEdit(GuiMultiplayer par0GuiMultiplayer)
    553        {
    554            return par0GuiMultiplayer.buttonEdit;
    555        }
    556
    557        /**
    558         * Return buttonDelete GuiButton
    559         */
    560        static GuiButton getButtonDelete(GuiMultiplayer par0GuiMultiplayer)
    561        {
    562            return par0GuiMultiplayer.buttonDelete;
    563        }
    564
    565        static void func_74008_b(GuiMultiplayer par0GuiMultiplayer, int par1)
    566        {
    567            par0GuiMultiplayer.joinServer(par1);
    568        }
    569
    570        static int func_74010_g(GuiMultiplayer par0GuiMultiplayer)
    571        {
    572            return par0GuiMultiplayer.field_74039_z;
    573        }
    574
    575        static Object func_74011_h()
    576        {
    577            return lock;
    578        }
    579
    580        static int func_74012_i()
    581        {
    582            return threadsPending;
    583        }
    584
    585        static int func_74021_j()
    586        {
    587            return threadsPending++;
    588        }
    589
    590        static void func_82291_a(ServerData par0ServerData) throws IOException
    591        {
    592            func_74017_b(par0ServerData);
    593        }
    594
    595        static int func_74018_k()
    596        {
    597            return threadsPending--;
    598        }
    599
    600        static String func_74009_a(GuiMultiplayer par0GuiMultiplayer, String par1Str)
    601        {
    602            return par0GuiMultiplayer.lagTooltip = par1Str;
    603        }
    604    }