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    }