    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    }