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