001 package net.minecraft.src;
002
003 import cpw.mods.fml.common.Side;
004 import cpw.mods.fml.common.asm.SideOnly;
005 import java.util.List;
006 import net.minecraft.client.Minecraft;
007 import org.lwjgl.input.Keyboard;
008 import org.lwjgl.opengl.GL11;
009 import org.lwjgl.opengl.GL12;
010
011 @SideOnly(Side.CLIENT)
012 public abstract class GuiContainer extends GuiScreen
013 {
014 /** Stacks renderer. Icons, stack size, health, etc... */
015 protected static RenderItem itemRenderer = new RenderItem();
016
017 /** The X size of the inventory window in pixels. */
018 protected int xSize = 176;
019
020 /** The Y size of the inventory window in pixels. */
021 protected int ySize = 166;
022
023 /** A list of the players inventory slots. */
024 public Container inventorySlots;
025
026 /**
027 * Starting X position for the Gui. Inconsistent use for Gui backgrounds.
028 */
029 protected int guiLeft;
030
031 /**
032 * Starting Y position for the Gui. Inconsistent use for Gui backgrounds.
033 */
034 protected int guiTop;
035 private Slot theSlot;
036 private Slot field_85051_p = null;
037 private boolean field_90018_r = false;
038 private ItemStack field_85050_q = null;
039 private int field_85049_r = 0;
040 private int field_85048_s = 0;
041 private Slot field_85047_t = null;
042 private long field_85046_u = 0L;
043 private ItemStack field_85045_v = null;
044
045 public GuiContainer(Container par1Container)
046 {
047 this.inventorySlots = par1Container;
048 }
049
050 /**
051 * Adds the buttons (and other controls) to the screen in question.
052 */
053 public void initGui()
054 {
055 super.initGui();
056 this.mc.thePlayer.craftingInventory = this.inventorySlots;
057 this.guiLeft = (this.width - this.xSize) / 2;
058 this.guiTop = (this.height - this.ySize) / 2;
059 }
060
061 /**
062 * Draws the screen and all the components in it.
063 */
064 public void drawScreen(int par1, int par2, float par3)
065 {
066 this.drawDefaultBackground();
067 int var4 = this.guiLeft;
068 int var5 = this.guiTop;
069 this.drawGuiContainerBackgroundLayer(par3, par1, par2);
070 GL11.glDisable(GL12.GL_RESCALE_NORMAL);
071 RenderHelper.disableStandardItemLighting();
072 GL11.glDisable(GL11.GL_LIGHTING);
073 GL11.glDisable(GL11.GL_DEPTH_TEST);
074 super.drawScreen(par1, par2, par3);
075 RenderHelper.enableGUIStandardItemLighting();
076 GL11.glPushMatrix();
077 GL11.glTranslatef((float)var4, (float)var5, 0.0F);
078 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
079 GL11.glEnable(GL12.GL_RESCALE_NORMAL);
080 this.theSlot = null;
081 short var6 = 240;
082 short var7 = 240;
083 OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)var6 / 1.0F, (float)var7 / 1.0F);
084 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
085 int var8;
086 int var9;
087
088 for (int var13 = 0; var13 < this.inventorySlots.inventorySlots.size(); ++var13)
089 {
090 Slot var14 = (Slot)this.inventorySlots.inventorySlots.get(var13);
091 this.drawSlotInventory(var14);
092
093 if (this.isMouseOverSlot(var14, par1, par2))
094 {
095 this.theSlot = var14;
096 GL11.glDisable(GL11.GL_LIGHTING);
097 GL11.glDisable(GL11.GL_DEPTH_TEST);
098 var8 = var14.xDisplayPosition;
099 var9 = var14.yDisplayPosition;
100 this.drawGradientRect(var8, var9, var8 + 16, var9 + 16, -2130706433, -2130706433);
101 GL11.glEnable(GL11.GL_LIGHTING);
102 GL11.glEnable(GL11.GL_DEPTH_TEST);
103 }
104 }
105
106 this.drawGuiContainerForegroundLayer(par1, par2);
107 InventoryPlayer var15 = this.mc.thePlayer.inventory;
108 ItemStack var16 = this.field_85050_q == null ? var15.getItemStack() : this.field_85050_q;
109
110 if (var16 != null)
111 {
112 var8 = this.field_85050_q == null ? 8 : 0;
113
114 if (this.field_85050_q != null && this.field_90018_r)
115 {
116 var16 = var16.copy();
117 var16.stackSize = MathHelper.ceiling_float_int((float)var16.stackSize / 2.0F);
118 }
119
120 this.func_85044_b(var16, par1 - var4 - var8, par2 - var5 - var8);
121 }
122
123 if (this.field_85045_v != null)
124 {
125 float var17 = (float)(Minecraft.getSystemTime() - this.field_85046_u) / 100.0F;
126
127 if (var17 >= 1.0F)
128 {
129 var17 = 1.0F;
130 this.field_85045_v = null;
131 }
132
133 var9 = this.field_85047_t.xDisplayPosition - this.field_85049_r;
134 int var10 = this.field_85047_t.yDisplayPosition - this.field_85048_s;
135 int var11 = this.field_85049_r + (int)((float)var9 * var17);
136 int var12 = this.field_85048_s + (int)((float)var10 * var17);
137 this.func_85044_b(this.field_85045_v, var11, var12);
138 }
139
140 if (var15.getItemStack() == null && this.theSlot != null && this.theSlot.getHasStack())
141 {
142 ItemStack var18 = this.theSlot.getStack();
143 this.func_74184_a(var18, par1 - var4 + 8, par2 - var5 + 8);
144 }
145
146 GL11.glPopMatrix();
147 GL11.glEnable(GL11.GL_LIGHTING);
148 GL11.glEnable(GL11.GL_DEPTH_TEST);
149 RenderHelper.enableStandardItemLighting();
150 }
151
152 private void func_85044_b(ItemStack par1ItemStack, int par2, int par3)
153 {
154 GL11.glTranslatef(0.0F, 0.0F, 32.0F);
155 this.zLevel = 200.0F;
156 itemRenderer.zLevel = 200.0F;
157 itemRenderer.renderItemAndEffectIntoGUI(this.fontRenderer, this.mc.renderEngine, par1ItemStack, par2, par3);
158 itemRenderer.renderItemOverlayIntoGUI(this.fontRenderer, this.mc.renderEngine, par1ItemStack, par2, par3);
159 this.zLevel = 0.0F;
160 itemRenderer.zLevel = 0.0F;
161 }
162
163 protected void func_74184_a(ItemStack par1ItemStack, int par2, int par3)
164 {
165 GL11.glDisable(GL12.GL_RESCALE_NORMAL);
166 RenderHelper.disableStandardItemLighting();
167 GL11.glDisable(GL11.GL_LIGHTING);
168 GL11.glDisable(GL11.GL_DEPTH_TEST);
169 List var4 = par1ItemStack.getTooltip(this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips);
170
171 if (!var4.isEmpty())
172 {
173 int var5 = 0;
174 int var6;
175 int var7;
176
177 for (var6 = 0; var6 < var4.size(); ++var6)
178 {
179 var7 = this.fontRenderer.getStringWidth((String)var4.get(var6));
180
181 if (var7 > var5)
182 {
183 var5 = var7;
184 }
185 }
186
187 var6 = par2 + 12;
188 var7 = par3 - 12;
189 int var9 = 8;
190
191 if (var4.size() > 1)
192 {
193 var9 += 2 + (var4.size() - 1) * 10;
194 }
195
196 this.zLevel = 300.0F;
197 itemRenderer.zLevel = 300.0F;
198 int var10 = -267386864;
199 this.drawGradientRect(var6 - 3, var7 - 4, var6 + var5 + 3, var7 - 3, var10, var10);
200 this.drawGradientRect(var6 - 3, var7 + var9 + 3, var6 + var5 + 3, var7 + var9 + 4, var10, var10);
201 this.drawGradientRect(var6 - 3, var7 - 3, var6 + var5 + 3, var7 + var9 + 3, var10, var10);
202 this.drawGradientRect(var6 - 4, var7 - 3, var6 - 3, var7 + var9 + 3, var10, var10);
203 this.drawGradientRect(var6 + var5 + 3, var7 - 3, var6 + var5 + 4, var7 + var9 + 3, var10, var10);
204 int var11 = 1347420415;
205 int var12 = (var11 & 16711422) >> 1 | var11 & -16777216;
206 this.drawGradientRect(var6 - 3, var7 - 3 + 1, var6 - 3 + 1, var7 + var9 + 3 - 1, var11, var12);
207 this.drawGradientRect(var6 + var5 + 2, var7 - 3 + 1, var6 + var5 + 3, var7 + var9 + 3 - 1, var11, var12);
208 this.drawGradientRect(var6 - 3, var7 - 3, var6 + var5 + 3, var7 - 3 + 1, var11, var11);
209 this.drawGradientRect(var6 - 3, var7 + var9 + 2, var6 + var5 + 3, var7 + var9 + 3, var12, var12);
210
211 for (int var13 = 0; var13 < var4.size(); ++var13)
212 {
213 String var14 = (String)var4.get(var13);
214
215 if (var13 == 0)
216 {
217 var14 = "\u00a7" + Integer.toHexString(par1ItemStack.getRarity().rarityColor) + var14;
218 }
219 else
220 {
221 var14 = "\u00a77" + var14;
222 }
223
224 this.fontRenderer.drawStringWithShadow(var14, var6, var7, -1);
225
226 if (var13 == 0)
227 {
228 var7 += 2;
229 }
230
231 var7 += 10;
232 }
233
234 this.zLevel = 0.0F;
235 itemRenderer.zLevel = 0.0F;
236 }
237 }
238
239 /**
240 * Draws the text when mouse is over creative inventory tab. Params: current creative tab to be checked, current
241 * mouse x position, current mouse y position.
242 */
243 protected void drawCreativeTabHoveringText(String par1Str, int par2, int par3)
244 {
245 GL11.glDisable(GL12.GL_RESCALE_NORMAL);
246 RenderHelper.disableStandardItemLighting();
247 GL11.glDisable(GL11.GL_LIGHTING);
248 GL11.glDisable(GL11.GL_DEPTH_TEST);
249 int var4 = this.fontRenderer.getStringWidth(par1Str);
250 int var5 = par2 + 12;
251 int var6 = par3 - 12;
252 byte var8 = 8;
253 this.zLevel = 300.0F;
254 itemRenderer.zLevel = 300.0F;
255 int var9 = -267386864;
256 this.drawGradientRect(var5 - 3, var6 - 4, var5 + var4 + 3, var6 - 3, var9, var9);
257 this.drawGradientRect(var5 - 3, var6 + var8 + 3, var5 + var4 + 3, var6 + var8 + 4, var9, var9);
258 this.drawGradientRect(var5 - 3, var6 - 3, var5 + var4 + 3, var6 + var8 + 3, var9, var9);
259 this.drawGradientRect(var5 - 4, var6 - 3, var5 - 3, var6 + var8 + 3, var9, var9);
260 this.drawGradientRect(var5 + var4 + 3, var6 - 3, var5 + var4 + 4, var6 + var8 + 3, var9, var9);
261 int var10 = 1347420415;
262 int var11 = (var10 & 16711422) >> 1 | var10 & -16777216;
263 this.drawGradientRect(var5 - 3, var6 - 3 + 1, var5 - 3 + 1, var6 + var8 + 3 - 1, var10, var11);
264 this.drawGradientRect(var5 + var4 + 2, var6 - 3 + 1, var5 + var4 + 3, var6 + var8 + 3 - 1, var10, var11);
265 this.drawGradientRect(var5 - 3, var6 - 3, var5 + var4 + 3, var6 - 3 + 1, var10, var10);
266 this.drawGradientRect(var5 - 3, var6 + var8 + 2, var5 + var4 + 3, var6 + var8 + 3, var11, var11);
267 this.fontRenderer.drawStringWithShadow(par1Str, var5, var6, -1);
268 this.zLevel = 0.0F;
269 itemRenderer.zLevel = 0.0F;
270 GL11.glEnable(GL11.GL_LIGHTING);
271 GL11.glEnable(GL11.GL_DEPTH_TEST);
272 RenderHelper.enableStandardItemLighting();
273 GL11.glEnable(GL12.GL_RESCALE_NORMAL);
274 }
275
276 /**
277 * Draw the foreground layer for the GuiContainer (everything in front of the items)
278 */
279 protected void drawGuiContainerForegroundLayer(int par1, int par2) {}
280
281 /**
282 * Draw the background layer for the GuiContainer (everything behind the items)
283 */
284 protected abstract void drawGuiContainerBackgroundLayer(float var1, int var2, int var3);
285
286 /**
287 * Draws an inventory slot
288 */
289 private void drawSlotInventory(Slot par1Slot)
290 {
291 int var2 = par1Slot.xDisplayPosition;
292 int var3 = par1Slot.yDisplayPosition;
293 ItemStack var4 = par1Slot.getStack();
294 boolean var5 = par1Slot == this.field_85051_p && this.field_85050_q != null && !this.field_90018_r;
295
296 if (par1Slot == this.field_85051_p && this.field_85050_q != null && this.field_90018_r && var4 != null)
297 {
298 var4 = var4.copy();
299 var4.stackSize /= 2;
300 }
301
302 this.zLevel = 100.0F;
303 itemRenderer.zLevel = 100.0F;
304
305 if (var4 == null)
306 {
307 int var6 = par1Slot.getBackgroundIconIndex();
308
309 if (var6 >= 0)
310 {
311 GL11.glDisable(GL11.GL_LIGHTING);
312 this.mc.renderEngine.bindTexture(this.mc.renderEngine.getTexture(par1Slot.getBackgroundIconTexture()));
313 this.drawTexturedModalRect(var2, var3, var6 % 16 * 16, var6 / 16 * 16, 16, 16);
314 GL11.glEnable(GL11.GL_LIGHTING);
315 var5 = true;
316 }
317 }
318
319 if (!var5)
320 {
321 GL11.glEnable(GL11.GL_DEPTH_TEST);
322 itemRenderer.renderItemAndEffectIntoGUI(this.fontRenderer, this.mc.renderEngine, var4, var2, var3);
323 itemRenderer.renderItemOverlayIntoGUI(this.fontRenderer, this.mc.renderEngine, var4, var2, var3);
324 }
325
326 itemRenderer.zLevel = 0.0F;
327 this.zLevel = 0.0F;
328 }
329
330 /**
331 * Returns the slot at the given coordinates or null if there is none.
332 */
333 private Slot getSlotAtPosition(int par1, int par2)
334 {
335 for (int var3 = 0; var3 < this.inventorySlots.inventorySlots.size(); ++var3)
336 {
337 Slot var4 = (Slot)this.inventorySlots.inventorySlots.get(var3);
338
339 if (this.isMouseOverSlot(var4, par1, par2))
340 {
341 return var4;
342 }
343 }
344
345 return null;
346 }
347
348 /**
349 * Called when the mouse is clicked.
350 */
351 protected void mouseClicked(int par1, int par2, int par3)
352 {
353 super.mouseClicked(par1, par2, par3);
354 boolean var4 = par3 == this.mc.gameSettings.keyBindPickBlock.keyCode + 100;
355
356 if (par3 == 0 || par3 == 1 || var4)
357 {
358 Slot var5 = this.getSlotAtPosition(par1, par2);
359 int var6 = this.guiLeft;
360 int var7 = this.guiTop;
361 boolean var8 = par1 < var6 || par2 < var7 || par1 >= var6 + this.xSize || par2 >= var7 + this.ySize;
362 int var9 = -1;
363
364 if (var5 != null)
365 {
366 var9 = var5.slotNumber;
367 }
368
369 if (var8)
370 {
371 var9 = -999;
372 }
373
374 if (this.mc.gameSettings.field_85185_A && var8 && this.mc.thePlayer.inventory.getItemStack() == null)
375 {
376 this.mc.displayGuiScreen((GuiScreen)null);
377 return;
378 }
379
380 if (var9 != -1)
381 {
382 if (this.mc.gameSettings.field_85185_A)
383 {
384 if (var5 != null && var5.getHasStack())
385 {
386 this.field_85051_p = var5;
387 this.field_85050_q = null;
388 this.field_90018_r = par3 == 1;
389 }
390 else
391 {
392 this.field_85051_p = null;
393 }
394 }
395 else if (var4)
396 {
397 this.handleMouseClick(var5, var9, par3, 3);
398 }
399 else
400 {
401 boolean var10 = var9 != -999 && (Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54));
402 this.handleMouseClick(var5, var9, par3, var10 ? 1 : 0);
403 }
404 }
405 }
406 }
407
408 protected void func_85041_a(int par1, int par2, int par3, long par4)
409 {
410 if (this.field_85051_p != null && this.mc.gameSettings.field_85185_A && this.field_85050_q == null)
411 {
412 if (par3 == 0 || par3 == 1)
413 {
414 Slot var6 = this.getSlotAtPosition(par1, par2);
415
416 if (var6 != this.field_85051_p)
417 {
418 this.field_85050_q = this.field_85051_p.getStack();
419 }
420 }
421 }
422 }
423
424 /**
425 * Called when the mouse is moved or a mouse button is released. Signature: (mouseX, mouseY, which) which==-1 is
426 * mouseMove, which==0 or which==1 is mouseUp
427 */
428 protected void mouseMovedOrUp(int par1, int par2, int par3)
429 {
430 if (this.field_85051_p != null && this.mc.gameSettings.field_85185_A)
431 {
432 if (par3 == 0 || par3 == 1)
433 {
434 Slot var4 = this.getSlotAtPosition(par1, par2);
435 int var5 = this.guiLeft;
436 int var6 = this.guiTop;
437 boolean var7 = par1 < var5 || par2 < var6 || par1 >= var5 + this.xSize || par2 >= var6 + this.ySize;
438 int var8 = -1;
439
440 if (var4 != null)
441 {
442 var8 = var4.slotNumber;
443 }
444
445 if (var7)
446 {
447 var8 = -999;
448 }
449
450 if (this.field_85050_q == null && var4 != this.field_85051_p)
451 {
452 this.field_85050_q = this.field_85051_p.getStack();
453 }
454
455 boolean var9 = var4 == null || !var4.getHasStack();
456
457 if (var4 != null && var4.getHasStack() && this.field_85050_q != null && ItemStack.areItemStackTagsEqual(var4.getStack(), this.field_85050_q))
458 {
459 var9 |= var4.getStack().stackSize + this.field_85050_q.stackSize <= this.field_85050_q.getMaxStackSize();
460 }
461
462 if (var8 != -1 && this.field_85050_q != null && var9)
463 {
464 this.handleMouseClick(this.field_85051_p, this.field_85051_p.slotNumber, par3, 0);
465 this.handleMouseClick(var4, var8, 0, 0);
466
467 if (this.mc.thePlayer.inventory.getItemStack() != null)
468 {
469 this.handleMouseClick(this.field_85051_p, this.field_85051_p.slotNumber, par3, 0);
470 this.field_85049_r = par1 - var5;
471 this.field_85048_s = par2 - var6;
472 this.field_85047_t = this.field_85051_p;
473 this.field_85045_v = this.field_85050_q;
474 this.field_85046_u = Minecraft.getSystemTime();
475 }
476 else
477 {
478 this.field_85045_v = null;
479 }
480 }
481 else if (this.field_85050_q != null)
482 {
483 this.field_85049_r = par1 - var5;
484 this.field_85048_s = par2 - var6;
485 this.field_85047_t = this.field_85051_p;
486 this.field_85045_v = this.field_85050_q;
487 this.field_85046_u = Minecraft.getSystemTime();
488 }
489
490 this.field_85050_q = null;
491 this.field_85051_p = null;
492 }
493 }
494 }
495
496 /**
497 * Returns if the passed mouse position is over the specified slot.
498 */
499 private boolean isMouseOverSlot(Slot par1Slot, int par2, int par3)
500 {
501 return this.func_74188_c(par1Slot.xDisplayPosition, par1Slot.yDisplayPosition, 16, 16, par2, par3);
502 }
503
504 protected boolean func_74188_c(int par1, int par2, int par3, int par4, int par5, int par6)
505 {
506 int var7 = this.guiLeft;
507 int var8 = this.guiTop;
508 par5 -= var7;
509 par6 -= var8;
510 return par5 >= par1 - 1 && par5 < par1 + par3 + 1 && par6 >= par2 - 1 && par6 < par2 + par4 + 1;
511 }
512
513 protected void handleMouseClick(Slot par1Slot, int par2, int par3, int par4)
514 {
515 if (par1Slot != null)
516 {
517 par2 = par1Slot.slotNumber;
518 }
519
520 this.mc.playerController.windowClick(this.inventorySlots.windowId, par2, par3, par4, this.mc.thePlayer);
521 }
522
523 /**
524 * Fired when a key is typed. This is the equivalent of KeyListener.keyTyped(KeyEvent e).
525 */
526 protected void keyTyped(char par1, int par2)
527 {
528 if (par2 == 1 || par2 == this.mc.gameSettings.keyBindInventory.keyCode)
529 {
530 this.mc.thePlayer.closeScreen();
531 }
532
533 this.func_82319_a(par2);
534
535 if (par2 == this.mc.gameSettings.keyBindPickBlock.keyCode && this.theSlot != null && this.theSlot.getHasStack())
536 {
537 this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, this.ySize, 3);
538 }
539 }
540
541 protected boolean func_82319_a(int par1)
542 {
543 if (this.mc.thePlayer.inventory.getItemStack() == null && this.theSlot != null)
544 {
545 for (int var2 = 0; var2 < 9; ++var2)
546 {
547 if (par1 == 2 + var2)
548 {
549 this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, var2, 2);
550 return true;
551 }
552 }
553 }
554
555 return false;
556 }
557
558 /**
559 * Called when the screen is unloaded. Used to disable keyboard repeat events
560 */
561 public void onGuiClosed()
562 {
563 if (this.mc.thePlayer != null)
564 {
565 this.inventorySlots.onCraftGuiClosed(this.mc.thePlayer);
566 }
567 }
568
569 /**
570 * Returns true if this GUI should pause the game when it is displayed in single-player
571 */
572 public boolean doesGuiPauseGame()
573 {
574 return false;
575 }
576
577 /**
578 * Called from the main game loop to update the screen.
579 */
580 public void updateScreen()
581 {
582 super.updateScreen();
583
584 if (!this.mc.thePlayer.isEntityAlive() || this.mc.thePlayer.isDead)
585 {
586 this.mc.thePlayer.closeScreen();
587 }
588 }
589 }