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 }