    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.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
    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        private 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    }