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