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    }