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 }