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.openContainer = 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        protected 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    }