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 }