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