Не могу отрисовать свой drawDefaultBackground

Версия Minecraft
1.7.10
1,159
38
544
Здравствуйте, делаю диалоговое меню для другого GUI. Сейчас это выглядит так
2018-06-24_14-17-20.png

Выглядит прикольно, но хочется еще красивее - хочу, чтобы позади диалога, но перед основным GUI вырисовывался тот же полупрозрачный темный экран, что и для всех стандартных майнкравтовских GUI. Известно, что за отрисовку этого полупрозрачного темного экрана отвечает метод GuiScreen#drawDefaultBackground().

Но в нем есть один недостаток, из-за которого я не могу его использовать - нет возможности задать определенных zLevel, где нужно отрисовать беграунд. Так что я копировал его и добавил нужный параметр:
Java:
/**
         * Draws a rectangle with a vertical gradient between the specified colors.
         */
        protected void drawGradientRectZLevel(int p_73733_1_, int p_73733_2_, int p_73733_3_, int p_73733_4_, int p_73733_5_, int p_73733_6_, float z)
        {
            float f = (float)(p_73733_5_ >> 24 & 255) / 255.0F;
            float f1 = (float)(p_73733_5_ >> 16 & 255) / 255.0F;
            float f2 = (float)(p_73733_5_ >> 8 & 255) / 255.0F;
            float f3 = (float)(p_73733_5_ & 255) / 255.0F;
            float f4 = (float)(p_73733_6_ >> 24 & 255) / 255.0F;
            float f5 = (float)(p_73733_6_ >> 16 & 255) / 255.0F;
            float f6 = (float)(p_73733_6_ >> 8 & 255) / 255.0F;
            float f7 = (float)(p_73733_6_ & 255) / 255.0F;
            GL11.glDisable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_BLEND);
            GL11.glDisable(GL11.GL_ALPHA_TEST);
            OpenGlHelper.glBlendFunc(770, 771, 1, 0);
            GL11.glShadeModel(GL11.GL_SMOOTH);
            Tessellator tessellator = Tessellator.instance;
            tessellator.startDrawingQuads();
            tessellator.setColorRGBA_F(f1, f2, f3, f);
            tessellator.addVertex((double)p_73733_3_, (double)p_73733_2_, (double)z);
            tessellator.addVertex((double)p_73733_1_, (double)p_73733_2_, (double)z);
            tessellator.setColorRGBA_F(f5, f6, f7, f4);
            tessellator.addVertex((double)p_73733_1_, (double)p_73733_4_, (double)z);
            tessellator.addVertex((double)p_73733_3_, (double)p_73733_4_, (double)z);
            tessellator.draw();
            GL11.glShadeModel(GL11.GL_FLAT);
            GL11.glDisable(GL11.GL_BLEND);
            GL11.glEnable(GL11.GL_ALPHA_TEST);
            GL11.glEnable(GL11.GL_TEXTURE_2D);
        }

Дальше все просто, выставляю нужный zLevel и уже был готов праздновать, как вдруг наблюдаю такое непонятное поведение
2018-06-24_14-26-28.png

Пропадает рендер всех предметов, рендер шрифтов, рендер текстур-болванок на слотах брони, но к великому удивлению, рендер модели игрока и рендер количества предметов в стаке остается. WTF тут происходит, собстна? Такое чувство, что Tessellator просто выкидывает из себя рендер стаков.

Я не очень силен в том, как майн работает с рендером, так что прошу вашей помощи. Мне прсто нужно отрисовать полупрозрачный бэкграунд с сохранением всего остального. Как это сделать?
 
Решение
Хм по идеи чтобы фон нормально смещался с айтем стаками нужно чтобы айтем стаки рендерелись первыми. Иначе выходит что ты рисуешь свой бэкграунд, он смешивается с тем что на данный моммент сзади него есть(и это не стаки), а потом когда дело доходит до стеков они не рисуются из-за того что не проходят Depth Test. Мораль: рисуй сначала айтем стэки.
2,505
81
397
Подними зетлевел побольше Там стаки как-то костыльно рендерятся на zLevel +200 и еще на +лвле рисуется текст. Почему не рендерится твой текст я без понятия. Возможно эта твоя пластинка тоже с зетлевелом рисуется.
 
1,159
38
544
1,111
47
420
Хм по идеи чтобы фон нормально смещался с айтем стаками нужно чтобы айтем стаки рендерелись первыми. Иначе выходит что ты рисуешь свой бэкграунд, он смешивается с тем что на данный моммент сзади него есть(и это не стаки), а потом когда дело доходит до стеков они не рисуются из-за того что не проходят Depth Test. Мораль: рисуй сначала айтем стэки.
 
1,159
38
544
давай тогда весь код
В студию!

Для начала, вот сам класс моего GUI. Именно его вы могли видеть в шапке темы:

Java:
package rsstats.client.gui;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import net.minecraftforge.client.event.GuiScreenEvent;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import rsstats.client.gui.advanced.AdvanceInventoryEffectRenderer;
import rsstats.client.gui.advanced.ZLevelFontRenderer;
import rsstats.client.gui.advanced.ZLevelGuiButton;
import rsstats.common.CommonProxy;
import rsstats.common.RSStats;
import rsstats.common.network.PacketShowSkillsByStat;
import rsstats.data.ExtendedPlayer;
import rsstats.inventory.SkillsInventory;
import rsstats.inventory.StatsInventory;
import rsstats.inventory.container.MainContainer;
import rsstats.inventory.tabs_inventory.TabHostInventory;
import rsstats.items.SkillItem;

import java.util.List;
import java.util.Timer;

/**
* GUI для основного окна мода, содержащее информацию о персонаже (имя, уровень, здоровье, защита, харизма,
* стойкость), панель предметов и панели статов, навыков и перков.
* @author RareScrap
*/
public class MainMenuGUI extends AdvanceInventoryEffectRenderer {
    /** Расположение фона GUI */
    private static final ResourceLocation background =
            new ResourceLocation(RSStats.MODID,"textures/gui/StatsAndInvTab_FIT.png");

    /*public static final float MainMenuGUIZLevel = 5.0F;
    public static final float DialogZLevel = 201.0F;
    public static final float AdvanceGuiContainerZLevel = 100.0F;
    public static final float ItemRenderZLevel = 100.0F;*/

    public static final float MainMenuGUIZLevel = 5.0F;
    public static float DialogZLevel = 900.0F;
    public static float DialogBacgroundZLevel = 800.0F;
    public static final float AdvanceGuiContainerZLevel = 100.0F;
    public static final float ItemRenderZLevel = 100.0F;

    /** Период обновления экрана в мс */
    private static final int UPDATE_PERIOD = 100;
    /** Игрок, открывший GUI */
    public ExtendedPlayer player;
    /** UnlocalozedName текущей выбранно статы */
    private String currentStat = "";
    /** Флаг, обозначающий намерение игрока закрыть окно, пока он все прокачивает статы/навыки */
    private boolean isPlayerTryExitWhileEditStats = false;
    /** Диалог закрытия окна */
    private Dialog exitDialog;

    /** Инвентарь для статов */
    // Could use IInventory type to be more generic, but this way will save an import...
    // Нужно для запроса кастомного имени инвентаря для отрисоки названия инвентаря
    //private final StatsInventory statsInventory;

    /** Таймер, выполняющий перерасчет параметров {@link ExtendedPlayer}'ра на стороне клиента.
     * Для этих целей можно использовать и пакет, который будет слаться при клике/заполнеии слота, но
     * зачем, когда можно обойтись и без пакета?*/
    private Timer timer; // TODO: Удалить


    public MainMenuGUI(ExtendedPlayer player, MainContainer mainContainer) {
        super(mainContainer);
        this.allowUserInput = true;
        this.player = player;

        // Высталяем размеры контейнера. Соответствует размерам GUI на текстуре.
        this.xSize = 340;
        this.ySize = 211;
        // Выставляем края контейнера (верхний и левый)
        this.guiLeft = this.width/2 - xSize/2;
        this.guiTop = this.height/2 - ySize/2;
    }

    /**
     * Свой аналог {@link #drawTexturedModalRect(int, int, int, int, int, int)}, способный работать с текстурами
     * разрешением более чем 256x256.
     * @param x Координата начала отрисовки относительно левого-верхнего угла экрана игрока
     * @param y Координата начала отрисовки относительно левого-верхнего угла экрана игрока
     * @param u Координата начала текстуры по оси X относительно левого-верхнего угла текстуры
     * @param v Координата начала текстуры по оси Y относительно левого-верхнего угла текстуры
     * @param width Ширина текстуры, которую нужно отрисовать
     * @param height Высота текстуры, которую нужно отрисовать
     * @param textureWidth Общая ширина текстуры (кол-во пикселей в файле)
     * @param textureHeight Общая высота текстуры (кол-во пикселей в файле)
     */
    // Взято отсюда: http://www.minecraftforge.net/forum/topic/20177-172-gui-cant-more-than-256256/
    private void drawTexturedRect(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) {
        float f = 1F / (float)textureWidth;
        float f1 = 1F / (float)textureHeight;
        Tessellator tessellator = Tessellator.instance;
        tessellator.startDrawingQuads();
        tessellator.addVertexWithUV((double)(x), (double)(y + height), 0, (double)((float)(u) * f), (double)((float)(v + height) * f1));
        tessellator.addVertexWithUV((double)(x + width), (double)(y + height), 0, (double)((float)(u + width) * f), (double)((float)(v + height) * f1));
        tessellator.addVertexWithUV((double)(x + width), (double)(y), 0, (double)((float)(u + width) * f), (double)((float)(v) * f1));
        tessellator.addVertexWithUV((double)(x), (double)(y), 0, (double)((float)(u) * f), (double)((float)(v) * f1));
        tessellator.draw();
    }

    /**
     * Draw the background layer for the GuiContainer (everything behind the items)
     * @param partialTicks
     * @param mouseX
     * @param mouseY
     */
    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        //GL11.glScalef(2.0F, 2.0F, 1.0F);
        this.mc.getTextureManager().bindTexture(background);

        // Отрисовываем текстуру GUI
        drawTexturedRect(this.guiLeft, this.guiTop, 0, 0, xSize, ySize, xSize, ySize);
        // Орисовываем превью игрока
        drawPlayerModel(this.guiLeft+30, this.guiTop+90, /*17*/ 40, (float)(this.guiLeft + 51) - mouseX, (float)(this.guiTop + 75 - 50) - mouseY, this.mc.thePlayer);

        // Это было в туторах, но я хз на что это влияет. Слоты и рендер предметов работают и без этого
        /*for (int i1 = 0; i1 < this.inventorySlots.inventorySlots.size(); ++i1)
        {
            Slot slot = (Slot)this.inventorySlots.inventorySlots.get(i1);
            //if (slot.getHasStack() && slot.getSlotStackLimit()==1)
            //{
                this.drawTexturedModalRect(k+slot.xDisplayPosition, l+slot.yDisplayPosition, 200, 0, 16, 16);
            //}
        }*/

        // TODO: Может стоить отрисовывать диалог в drawGuiContainerForegroundLayer()?
        if (isPlayerTryExitWhileEditStats == true) {
            //inventorySlots.inventorySlots.clear();
            drawGradientRectZLevel(0, 0, 1000/*this.width*/, 1000/*this.height*/, -1072689136, -804253680, MainMenuGUI.DialogBacgroundZLevel);
            exitDialog.drawScreen(mouseX, mouseY, partialTicks, xSize, ySize, guiLeft, guiTop);
            //System.out.println("\nMainMenuGUIZLevel " + MainMenuGUIZLevel + " DialogZLevel " + DialogZLevel + " DialogBacgroundZLevel " + DialogBacgroundZLevel + " AdvanceGuiContainerZLevel " + AdvanceGuiContainerZLevel + " ItemRenderZLevel " + ItemRenderZLevel);
        }
    }

    /**
     * Draw the foreground layer for the GuiContainer (everything in front of the items)
     *
     * @param p_146979_1_
     * @param p_146979_2_
     */
    @Override
    protected void drawGuiContainerForegroundLayer(int p_146979_1_, int p_146979_2_) {
        int textY = 123;
        mc.fontRenderer.drawString(StatCollector.translateToLocalFormatted("gui.step", player.getStep()), 8, textY, 0x444444, false);
        mc.fontRenderer.drawString(StatCollector.translateToLocalFormatted("gui.level", player.getLvl()), 60, textY, 0x444444, false);
        mc.fontRenderer.drawString(StatCollector.translateToLocalFormatted("gui.protection", player.getProtection()), 8, textY+=10, 0x444444, false);
        mc.fontRenderer.drawString(StatCollector.translateToLocalFormatted("gui.ExpPoints", player.getExp()), 60, textY, 0x444444, false);
        mc.fontRenderer.drawString(StatCollector.translateToLocalFormatted("gui.persistence", player.getPersistence()), 8, textY+=10, 0x444444, false);
        mc.fontRenderer.drawString(StatCollector.translateToLocalFormatted("gui.tiredness", player.getTiredness()), 60, textY, 0x444444, false);
        mc.fontRenderer.drawString(StatCollector.translateToLocalFormatted("gui.charisma", player.getCharisma()), 8, textY+=10, 0x444444, false);

        super.drawGuiContainerForegroundLayer(p_146979_1_, p_146979_2_);
    }

    /**
     * Отрисовывает превью игрока
     * @param x TODO
     * @param y TODO
     * @param scale Маштаб модели
     * @param yaw TODO
     * @param pitch TODO
     * @param playerdrawn TODO
     */
    private static void drawPlayerModel(int x, int y, int scale, float yaw, float pitch, EntityLivingBase playerdrawn) {
        GL11.glEnable(GL11.GL_COLOR_MATERIAL);
        GL11.glPushMatrix();
        GL11.glTranslatef((float)x, (float)y, 50.0F);
        GL11.glScalef((float)(-scale), (float)scale, (float)scale);
        GL11.glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
        float f2 = playerdrawn.renderYawOffset;
        float f3 = playerdrawn.rotationYaw;
        float f4 = playerdrawn.rotationPitch;
        float f5 = playerdrawn.prevRotationYawHead;
        float f6 = playerdrawn.rotationYawHead;
        GL11.glRotatef(135.0F, 0.0F, 1.0F, 0.0F);
        RenderHelper.enableStandardItemLighting();
        GL11.glRotatef(-135.0F, 0.0F, 1.0F, 0.0F);
        GL11.glRotatef(-((float)Math.atan((double)(pitch / 40.0F))) * 20.0F, 1.0F, 0.0F, 0.0F);
        playerdrawn.renderYawOffset = (float)Math.atan((double)(yaw / 40.0F)) * 20.0F;
        playerdrawn.rotationYaw = (float)Math.atan((double)(yaw / 40.0F)) * 40.0F;
        playerdrawn.rotationPitch = -((float)Math.atan((double)(pitch / 40.0F))) * 20.0F;
        playerdrawn.rotationYawHead = playerdrawn.rotationYaw;
        playerdrawn.prevRotationYawHead = playerdrawn.rotationYaw;
        GL11.glTranslatef(0.0F, playerdrawn.yOffset, 0.0F);
        RenderManager.instance.playerViewY = 180.0F;
        RenderManager.instance.renderEntityWithPosYaw(playerdrawn, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F);
        playerdrawn.renderYawOffset = f2;
        playerdrawn.rotationYaw = f3;
        playerdrawn.rotationPitch = f4;
        playerdrawn.prevRotationYawHead = f5;
        playerdrawn.rotationYawHead = f6;
        GL11.glPopMatrix();
        RenderHelper.disableStandardItemLighting();
        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
        OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
    }

    @Override
    public void handleMouseInput() {

        // GUI уже имеет дступ к этому полю. Не смсла взвать его так, когда можно взвать напрямую
        //MainContainer container = (MainContainer) player.getEntityPlayer().openContainer;

        // Mouse.getEventX() и Mouse.getEventY() возвращают сырой ввод мыши, так что нам нужно обработать его
        ScaledResolution scaledresolution = new ScaledResolution(this.mc, this.mc.displayWidth, this.mc.displayHeight);
        int width = scaledresolution.getScaledWidth();
        int height = scaledresolution.getScaledHeight();
        int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
        int mouseZ = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;

        // Проходим по всем слотам в поисках того, на который мы навели курсок
        for (Object inventorySlot : inventorySlots.inventorySlots) {
            Slot slot = (Slot) inventorySlot;

            if (isMouseOverSlot(slot, mouseX, mouseZ)) {

                // Действия, если курсор наведен на статы
                if (slot.inventory instanceof StatsInventory && !(slot.inventory instanceof SkillsInventory)) { // TODO: Найти способ делать проверку только на класс без учета наследования
                    try {
                        Item item = slot.getStack().getItem();

                        if (!item.getUnlocalizedName().equals(currentStat) && !(item instanceof SkillItem)) {
                            PacketShowSkillsByStat packet = new PacketShowSkillsByStat(item.getUnlocalizedName());
                            CommonProxy.INSTANCE.sendToServer(packet);
                            currentStat = item.getUnlocalizedName();
                        }
                    } catch (NullPointerException e) {
                        System.err.println("Не удалось определить запрос вкладки.");
                    }

                }

                // Действия, если курсор наведен на прочие вкладки
                if (slot.inventory instanceof TabHostInventory) {
                    try {
                        Item item = slot.getStack().getItem();
                        ((TabHostInventory) slot.inventory).setTab(item.getUnlocalizedName());

                    } catch (NullPointerException e) {
                        System.err.println("Не удалось определить запрос вкладки.");
                    }

                }


            }
        }

        super.handleMouseInput();
    }

    /**
     * см родителя
     */
    private boolean isMouseOverSlot(Slot slot, int mouseX, int mouseY) {
        return this.func_146978_c(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, mouseX, mouseY);
    }

    /**
     * Fired when a key is typed. This is the equivalent of KeyListener.keyTyped(KeyEvent e).
     *
     * @param p_73869_1_
     * @param p_73869_2_
     */
    @Override
    protected void keyTyped(char p_73869_1_, int p_73869_2_) {
        // TODO: Добавь отображение скиллов по нажатой цифре

        // Проверка на нажатие ESC во время прокачки
        if (p_73869_1_ == 27 && ((MainContainer) this.player.getEntityPlayer().openContainer).isEditMode) {
            isPlayerTryExitWhileEditStats = true;
            disableSlot = true;
            exitDialog.initGui();
        } else {
            super.keyTyped(p_73869_1_, p_73869_2_);
        }
    }

    /**
     * Called when the screen is unloaded. Used to disable keyboard repeat events.
     */
    @Override
    public void onGuiClosed() {
        super.onGuiClosed();
        //timer.cancel();
        //timer.purge();
    }

    /**
     * Adds the buttons (and other controls) to the screen in question.
     */
    @Override
    public void initGui() {
        exitDialog = new Dialog(this, this.xSize, this.ySize, this.guiLeft, this.guiTop, Minecraft.getMinecraft());
        exitDialog.initGui();
        this.zLevel = MainMenuGUI.MainMenuGUIZLevel;
        super.initGui();
        /*timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                player.updateParams();
                updateScreen();
            }
        }, 0, UPDATE_PERIOD);*/
    }

    @Override
    protected void mouseClicked(int p_73864_1_, int p_73864_2_, int p_73864_3_) {
        super.mouseClicked(p_73864_1_, p_73864_2_, p_73864_3_);

        // TODO: Затолкать в диалог т.к. нарушается инкапсуляция
        if (p_73864_3_ == 0)
        {
            for (int l = 0; l < exitDialog.getButtonList().size(); ++l)
            {
                GuiButton guibutton = (GuiButton) exitDialog.getButtonList().get(l);

                if (guibutton.mousePressed(this.mc, p_73864_1_, p_73864_2_))
                {
                    GuiScreenEvent.ActionPerformedEvent.Pre event = new GuiScreenEvent.ActionPerformedEvent.Pre(this, guibutton, this.buttonList);
                    /*if (MinecraftForge.EVENT_BUS.post(event)) // TODO: Нужно ли отсылать ивенты?
                        break;
                    this.selectedButton = event.button;*/
                    event.button.func_146113_a(this.mc.getSoundHandler());
                    exitDialog.actionPerformed(event.button);
                    /*if (this.equals(this.mc.currentScreen))
                        MinecraftForge.EVENT_BUS.post(new GuiScreenEvent.ActionPerformedEvent.Post(this, event.button, this.buttonList));
                    */
                }
            }
        }

        if (p_73864_3_ == 0 ) {
            System.out.println("DialogBacgroundZLevel " + ++DialogBacgroundZLevel);
        } else if (p_73864_3_ == 1 ) {
            System.out.println("DialogBacgroundZLevel " + --DialogBacgroundZLevel);
        }
    }



    /**
     * Диалоговое окно, способное отображаться поверх другого {@link GuiScreen}
     *
     * <p>Внимание! Не отображайте это GUI, используя:
     * <ul>
     *     <li>Minecraft.getMinecraft().displayGuiScreen(new Dialog());</li>
     *     <li>player.getEntityPlayer().openGui(RSStats.instance, RSStats.DIALOG_GUI_CODE, player.getEntityPlayer().worldObj, (int) player.getEntityPlayer().posX, (int) player.getEntityPlayer().posY, (int) player.getEntityPlayer().posZ);</li>
     *     <li>FMLClientHandler.instance().displayGuiScreen(this.player.getEntityPlayer(), new Dialog());</li>
     * </ul>
     * т.к. это закрвает предыдущее GUI и ваш диалог будет отрисован как новое окно, а не поверх старого.
     * </p>
     */
    public static class Dialog extends GuiScreen {
        /** Текстура диалогового окна */
        public static final ResourceLocation background =
                new ResourceLocation(RSStats.MODID,"textures/gui/dialog.png");
        /** Отрисовщик текста */
        ZLevelFontRenderer fontRenderer = new ZLevelFontRenderer(
                Minecraft.getMinecraft().gameSettings,
                new ResourceLocation("textures/font/ascii.png"),
                Minecraft.getMinecraft().renderEngine,
                false);

        /** The X size of the inventory window in pixels. */
        int xSize;
        /** The Y size of the inventory window in pixels. */
        int ySize;
        /** Starting X position for the Gui. Inconsistent use for Gui backgrounds. */
        int guiLeft;
        /** Starting Y position for the Gui. Inconsistent use for Gui backgrounds. */
        int guiTop;
        /** Родитель, поверх которого вызывается диалоговое окно. */
        GuiScreen parent;
        int parentGuiLeft;
        int parentGuiTop;
        int parentXSize;
        int parentYSize;

        ZLevelGuiButton positiveButton;
        ZLevelGuiButton negativeButton;
        ZLevelGuiButton cancelButton;


        public Dialog(GuiScreen parent, int parentXSize, int parentYSize, int parentGuiLeft, int parentGuiTop, Minecraft mc) {
            // Высталяем размеры GUI. Соответствует размерам GUI на текстуре.
            xSize = 228; // TODO: Заменить на width из родителя
            ySize = 64; // TODO: Заменить на height из родителя
            this.mc = mc; // TODO: Заменить на Minecraft.getMinecraft()
            this.zLevel = MainMenuGUI.DialogZLevel;

            this.parent = parent;
            this.parentGuiLeft = parentGuiLeft;
            this.parentGuiTop = parentGuiTop;
            this.parentXSize = parentXSize;
            this.parentYSize = parentYSize;
        }

        @Override
        public void initGui() {
            positiveButton = new ZLevelGuiButton(0, guiLeft+6, guiTop+35, 70, 20, StatCollector.translateToLocal("gui.MainMenu.CloseDialog.positive"));
            negativeButton = new ZLevelGuiButton(1, guiLeft+79, guiTop+35, 70, 20,StatCollector.translateToLocal("gui.MainMenu.CloseDialog.negative"));
            cancelButton = new ZLevelGuiButton(2, guiLeft+152, guiTop+35, 70, 20,StatCollector.translateToLocal("gui.MainMenu.CloseDialog.cancel"));

            positiveButton.setZLevel(this.zLevel);
            negativeButton.setZLevel(this.zLevel);
            cancelButton.setZLevel(this.zLevel);

            if (!buttonList.isEmpty()) {
                buttonList.clear(); // TODO: Есть подозрение, что это никогда не вызовется
            }

            buttonList.add(positiveButton);
            buttonList.add(negativeButton);
            buttonList.add(cancelButton);

        }

        public List getButtonList() {
            return buttonList;
        }

        /**
         * ДОЛЖЕН вызываться в {@link GuiScreen#drawScreen(int, int, float)} родителя!
         * Метод-обертка для {@link #drawScreen(int, int, float)},
         */
        public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_, int parentXSize, int parentYSize, int parentGuiLeft, int parentGuiTop) {
            // Централизируем GUI диалога
            guiLeft = (parentXSize - xSize)/2 + parentGuiLeft;
            guiTop = (parentYSize - ySize)/2 + parentGuiTop;

            // Обновляем корд кнопок // TODO: Зачем?
            //buttonList.clear(); // TODO: НО БЛЯТЬ НЕ ТАК ЖЕ ГРУБО!
            //initGui();
            positiveButton.xPosition = guiLeft+6;
            positiveButton.yPosition = guiTop+35;
            negativeButton.xPosition = guiLeft+79;
            negativeButton.yPosition = guiTop+35;
            cancelButton.xPosition = guiLeft+152;
            cancelButton.yPosition = guiTop+35;

            drawScreen(p_73863_1_, p_73863_2_, p_73863_3_);
        }

        /**
         * Не вызывайте этот метод напрямую. Используйте обертку {@link #drawScreen(int, int, float, int, int, int, int)}
         */
        @Override
        public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_) {
            //drawDefaultBackground(); // TODO: Не срабатвает
            //this.drawGradientRectZLevel(0, 0, 1000/*this.width*/, 1000/*this.height*/, -1072689136, -804253680, Dialog.this.zLevel + 5000);

            this.mc.getTextureManager().bindTexture(background);
            this.drawTexturedModalRect(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);

            // Увеличиваем zLevel текста, чтоб тот отрисовывался над кнопкой и рисуем строку
            fontRenderer.zLevel = zLevel + 1;
            fontRenderer.drawString(StatCollector.translateToLocal("gui.MainMenu.CloseDialog"),
                    guiLeft+31,
                    guiTop+15,
                    0x444444,
                    false);

            super.drawScreen(p_73863_1_, p_73863_2_, p_73863_3_);
        }

        @Override
        protected void actionPerformed(GuiButton guiButton) {
            switch (guiButton.id) {
                case 0: {
                    System.out.println("stub1");

                    // TODO: Сохранять прокачку навыков

                    // Закрываем GUI
                    Minecraft.getMinecraft().displayGuiScreen(null);

                    break;
                }
                case 1: {
                    System.out.println("stub2");

                    // TODO: Возвращаться к редактированию прокачки

                    ((MainMenuGUI) parent).disableSlot = false;
                    ((MainMenuGUI) parent).isPlayerTryExitWhileEditStats = false;

                    break;
                }
                case 2: {
                    System.out.println("stub3");

                    // TODO: Отбрасывать прокачку

                    break;
                }
            }
        }

    }
        /**
         * Draws a rectangle with a vertical gradient between the specified colors.
         */
        protected void drawGradientRectZLevel(int p_73733_1_, int p_73733_2_, int p_73733_3_, int p_73733_4_, int p_73733_5_, int p_73733_6_, float z)
        {
            float f = (float)(p_73733_5_ >> 24 & 255) / 255.0F;
            float f1 = (float)(p_73733_5_ >> 16 & 255) / 255.0F;
            float f2 = (float)(p_73733_5_ >> 8 & 255) / 255.0F;
            float f3 = (float)(p_73733_5_ & 255) / 255.0F;
            float f4 = (float)(p_73733_6_ >> 24 & 255) / 255.0F;
            float f5 = (float)(p_73733_6_ >> 16 & 255) / 255.0F;
            float f6 = (float)(p_73733_6_ >> 8 & 255) / 255.0F;
            float f7 = (float)(p_73733_6_ & 255) / 255.0F;
            GL11.glDisable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_BLEND);
            GL11.glDisable(GL11.GL_ALPHA_TEST);
            OpenGlHelper.glBlendFunc(770, 771, 1, 0);
            GL11.glShadeModel(GL11.GL_SMOOTH);
            Tessellator tessellator = Tessellator.instance;
            tessellator.startDrawingQuads();
            tessellator.setColorRGBA_F(f1, f2, f3, f);
            tessellator.addVertex((double)p_73733_3_, (double)p_73733_2_, (double)z);
            tessellator.addVertex((double)p_73733_1_, (double)p_73733_2_, (double)z);
            tessellator.setColorRGBA_F(f5, f6, f7, f4);
            tessellator.addVertex((double)p_73733_1_, (double)p_73733_4_, (double)z);
            tessellator.addVertex((double)p_73733_3_, (double)p_73733_4_, (double)z);
            tessellator.draw();
            GL11.glShadeModel(GL11.GL_FLAT);
            GL11.glDisable(GL11.GL_BLEND);
            GL11.glEnable(GL11.GL_ALPHA_TEST);
            GL11.glEnable(GL11.GL_TEXTURE_2D);
        }
}

Важно отметить, что этот класс наследуется от AdvanceInventoryEffectRenderer - моя реализация InventoryEffectRenderer, которая абсолютно идентична InventoryEffectRenderer, за исключением того, что наследуется от AdvanceGuiContainer, который тоже идентичен GuiContainer. Я сделал это для того, чтобы иметь возможность изменять методы из GuiContainer. Ниже я перечислю все мои реализации самых распространенных GUI классов Minecraft'а. Еще раз подчеркну, что они не несут в себе ничего нового и по сути представляют копипаст из аналога. Они просто нужны для внесения небольших изменений в рендеринге.

AdvanceGuiContainer
Код:
package rsstats.client.gui.advanced;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiLabel;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import rsstats.client.gui.MainMenuGUI;

import java.util.Iterator;

@SideOnly(Side.CLIENT)
public abstract class AdvanceGuiContainer extends GuiContainer {
    private Slot theSlot;
    /** Used when touchscreen is enabled */
    private ItemStack draggedStack;
    /** Used when touchscreen is enabled. */
    private boolean isRightMouseClick;
    private int field_146996_I;
    /** Used when touchscreen is enabled */
    private ItemStack returningStack;
    private long returningStackTime;
    private Slot returningStackDestSlot;
    private int field_147011_y;
    private int field_147010_z;
    /** Used when touchscreen is enabled. */
    private Slot clickedSlot;
    private int field_146987_F;
    private boolean field_146993_M;
    private Slot field_146998_K;
    private long field_146997_J;
    private int field_146992_L;
    private boolean field_146995_H;
    private ItemStack field_146994_N;
    private int field_146988_G;
    private Slot field_146985_D;
    private long field_146986_E;
    /** The button that was just pressed. */
    private GuiButton selectedButton;
    public boolean disableSlot = false;

    public AdvanceGuiContainer(Container p_i1072_1_) {
        super(p_i1072_1_);
        this.field_146995_H = true;
    }

    // Копипаст из родителя-GuiContainer
    @Override
    public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_) {
        this.drawDefaultBackground();
        int k = this.guiLeft;
        int l = this.guiTop;
        this.drawGuiContainerBackgroundLayer(p_73863_3_, p_73863_1_, p_73863_2_);
        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
        RenderHelper.disableStandardItemLighting();
        GL11.glDisable(GL11.GL_LIGHTING);
        GL11.glDisable(GL11.GL_DEPTH_TEST);

        //super.drawScreen(p_73863_1_, p_73863_2_, p_73863_3_);
        // копипаст супера супера
        int kk;
        for (kk = 0; kk < this.buttonList.size(); ++kk)
        {
            ((GuiButton)this.buttonList.get(kk)).drawButton(this.mc, p_73863_1_, p_73863_2_);
        }
        for (kk = 0; kk < this.labelList.size(); ++kk)
        {
            ((GuiLabel)this.labelList.get(kk)).func_146159_a(this.mc, p_73863_1_, p_73863_2_);
        }

        RenderHelper.enableGUIStandardItemLighting();
        GL11.glPushMatrix();
        GL11.glTranslatef((float)k, (float)l, 0.0F);
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
        this.theSlot = null;
        short short1 = 240;
        short short2 = 240;
        OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)short1 / 1.0F, (float)short2 / 1.0F);
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        int k1;

        for (int i1 = 0; i1 < this.inventorySlots.inventorySlots.size(); ++i1)
        {
            Slot slot = (Slot)this.inventorySlots.inventorySlots.get(i1);
            this.func_146977_a(slot);

            if (this.isMouseOverSlot(slot, p_73863_1_, p_73863_2_) && slot.func_111238_b() && !disableSlot)
            {
                this.theSlot = slot;
                GL11.glDisable(GL11.GL_LIGHTING);
                GL11.glDisable(GL11.GL_DEPTH_TEST);
                int j1 = slot.xDisplayPosition;
                k1 = slot.yDisplayPosition;
                GL11.glColorMask(true, true, true, false);
                this.drawGradientRect(j1, k1, j1 + 16, k1 + 16, -2130706433, -2130706433);
                GL11.glColorMask(true, true, true, true);
                GL11.glEnable(GL11.GL_LIGHTING);
                GL11.glEnable(GL11.GL_DEPTH_TEST);
            }
        }

        //Forge: Force lighting to be disabled as there are some issue where lighting would
        //incorrectly be applied based on items that are in the inventory.
        GL11.glDisable(GL11.GL_LIGHTING);
        this.drawGuiContainerForegroundLayer(p_73863_1_, p_73863_2_);
        GL11.glEnable(GL11.GL_LIGHTING);
        InventoryPlayer inventoryplayer = this.mc.thePlayer.inventory;
        ItemStack itemstack = this.draggedStack == null ? inventoryplayer.getItemStack() : this.draggedStack;

        if (itemstack != null)
        {
            byte b0 = 8;
            k1 = this.draggedStack == null ? 8 : 16;
            String s = null;

            if (this.draggedStack != null && this.isRightMouseClick)
            {
                itemstack = itemstack.copy();
                itemstack.stackSize = MathHelper.ceiling_float_int((float)itemstack.stackSize / 2.0F);
            }
            else if (this.field_147007_t && this.field_147008_s.size() > 1)
            {
                itemstack = itemstack.copy();
                itemstack.stackSize = this.field_146996_I;

                if (itemstack.stackSize == 0)
                {
                    s = "" + EnumChatFormatting.YELLOW + "0";
                }
            }

            this.drawItemStack(itemstack, p_73863_1_ - k - b0, p_73863_2_ - l - k1, s);
        }

        if (this.returningStack != null)
        {
            float f1 = (float)(Minecraft.getSystemTime() - this.returningStackTime) / 100.0F;

            if (f1 >= 1.0F)
            {
                f1 = 1.0F;
                this.returningStack = null;
            }

            k1 = this.returningStackDestSlot.xDisplayPosition - this.field_147011_y;
            int j2 = this.returningStackDestSlot.yDisplayPosition - this.field_147010_z;
            int l1 = this.field_147011_y + (int)((float)k1 * f1);
            int i2 = this.field_147010_z + (int)((float)j2 * f1);
            this.drawItemStack(this.returningStack, l1, i2, (String)null);
        }

        GL11.glPopMatrix();

        if (inventoryplayer.getItemStack() == null && this.theSlot != null && this.theSlot.getHasStack())
        {
            ItemStack itemstack1 = this.theSlot.getStack();
            this.renderToolTip(itemstack1, p_73863_1_, p_73863_2_);
        }

        GL11.glEnable(GL11.GL_LIGHTING);
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        RenderHelper.enableStandardItemLighting();
    }

    // Копипаст из родителя-GuiContainer
    /**
     * This function is what controls the hotbar shortcut check when you press a number key when hovering a stack.
     */
    @Override
    protected boolean checkHotbarKeys(int p_146983_1_)
    {
        if (this.mc.thePlayer.inventory.getItemStack() == null && this.theSlot != null)
        {
            for (int j = 0; j < 9; ++j)
            {
                if (p_146983_1_ == this.mc.gameSettings.keyBindsHotbar[j].getKeyCode())
                {
                    this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, j, 2);
                    return true;
                }
            }
        }

        return false;
    }

    // Копипаст из родителя-GuiContainer
    private void func_146977_a(Slot p_146977_1_)
    {
        int i = p_146977_1_.xDisplayPosition;
        int j = p_146977_1_.yDisplayPosition;
        ItemStack itemstack = p_146977_1_.getStack();
        boolean flag = false;
        boolean flag1 = p_146977_1_ == this.clickedSlot && this.draggedStack != null && !this.isRightMouseClick;
        ItemStack itemstack1 = this.mc.thePlayer.inventory.getItemStack();
        String s = null;

        if (p_146977_1_ == this.clickedSlot && this.draggedStack != null && this.isRightMouseClick && itemstack != null)
        {
            itemstack = itemstack.copy();
            itemstack.stackSize /= 2;
        }
        else if (this.field_147007_t && this.field_147008_s.contains(p_146977_1_) && itemstack1 != null)
        {
            if (this.field_147008_s.size() == 1)
            {
                return;
            }

            if (Container.func_94527_a(p_146977_1_, itemstack1, true) && this.inventorySlots.canDragIntoSlot(p_146977_1_))
            {
                itemstack = itemstack1.copy();
                flag = true;
                Container.func_94525_a(this.field_147008_s, this.field_146987_F, itemstack, p_146977_1_.getStack() == null ? 0 : p_146977_1_.getStack().stackSize);

                if (itemstack.stackSize > itemstack.getMaxStackSize())
                {
                    s = EnumChatFormatting.YELLOW + "" + itemstack.getMaxStackSize();
                    itemstack.stackSize = itemstack.getMaxStackSize();
                }

                if (itemstack.stackSize > p_146977_1_.getSlotStackLimit())
                {
                    s = EnumChatFormatting.YELLOW + "" + p_146977_1_.getSlotStackLimit();
                    itemstack.stackSize = p_146977_1_.getSlotStackLimit();
                }
            }
            else
            {
                this.field_147008_s.remove(p_146977_1_);
                this.func_146980_g();
            }
        }

        this.zLevel = MainMenuGUI.AdvanceGuiContainerZLevel;
        itemRender.zLevel = MainMenuGUI.ItemRenderZLevel;

        if (itemstack == null)
        {
            IIcon iicon = p_146977_1_.getBackgroundIconIndex();

            if (iicon != null)
            {
                GL11.glDisable(GL11.GL_LIGHTING);
                GL11.glEnable(GL11.GL_BLEND); // Forge: Blending needs to be enabled for this.
                this.mc.getTextureManager().bindTexture(TextureMap.locationItemsTexture);
                this.drawTexturedModelRectFromIcon(i, j, iicon, 16, 16);
                GL11.glDisable(GL11.GL_BLEND); // Forge: And clean that up
                GL11.glEnable(GL11.GL_LIGHTING);
                flag1 = true;
            }
        }

        if (!flag1)
        {
            if (flag)
            {
                drawRect(i, j, i + 16, j + 16, -2130706433);
            }
            //System.out.println("Рисую стак " + itemRender.zLevel);
            GL11.glEnable(GL11.GL_DEPTH_TEST);
            itemRender.renderItemAndEffectIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), itemstack, i, j);
            itemRender.renderItemOverlayIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), itemstack, i, j, s);
        }

        itemRender.zLevel = 0.0F;
        this.zLevel = 0.0F;
    }

    // Копипаст из родителя-GuiContainer
    /**
     * Returns if the passed mouse position is over the specified slot.
     */
    private boolean isMouseOverSlot(Slot p_146981_1_, int p_146981_2_, int p_146981_3_)
    {
        return this.func_146978_c(p_146981_1_.xDisplayPosition, p_146981_1_.yDisplayPosition, 16, 16, p_146981_2_, p_146981_3_);
    }

    // Копипаст из родителя-GuiContainer
    @Override
    protected boolean func_146978_c(int p_146978_1_, int p_146978_2_, int p_146978_3_, int p_146978_4_, int p_146978_5_, int p_146978_6_)
    {
        int k1 = this.guiLeft;
        int l1 = this.guiTop;
        p_146978_5_ -= k1;
        p_146978_6_ -= l1;
        return p_146978_5_ >= p_146978_1_ - 1 && p_146978_5_ < p_146978_1_ + p_146978_3_ + 1 && p_146978_6_ >= p_146978_2_ - 1 && p_146978_6_ < p_146978_2_ + p_146978_4_ + 1;
    }

    // Копипаст из родителя-GuiContainer
    private void drawItemStack(ItemStack p_146982_1_, int p_146982_2_, int p_146982_3_, String p_146982_4_)
    {
        // хз оно работает вообще?
        System.out.println("drawItemStack");
        GL11.glTranslatef(0.0F, 0.0F, 32.0F);
        this.zLevel = 200.0F;
        itemRender.zLevel = 200.0F;
        FontRenderer font = null;
        if (p_146982_1_ != null) font = p_146982_1_.getItem().getFontRenderer(p_146982_1_);
        if (font == null) font = fontRendererObj;
        itemRender.renderItemAndEffectIntoGUI(font, this.mc.getTextureManager(), p_146982_1_, p_146982_2_, p_146982_3_);
        itemRender.renderItemOverlayIntoGUI(font, this.mc.getTextureManager(), p_146982_1_, p_146982_2_, p_146982_3_ - (this.draggedStack == null ? 0 : 8), p_146982_4_);
        this.zLevel = 0.0F;
        itemRender.zLevel = 0.0F;
    }

    // Копипаст из родителя-GuiContainer
    /**
     * Called when the mouse is clicked.
     */
    @Override
    protected void mouseClicked(int p_73864_1_, int p_73864_2_, int p_73864_3_)
    {
        // Супер-супера
        //super.mouseClicked(p_73864_1_, p_73864_2_, p_73864_3_);
        if (p_73864_3_ == 0)
        {
            for (int l = 0; l < this.buttonList.size(); ++l)
            {
                GuiButton guibutton = (GuiButton)this.buttonList.get(l);

                if (guibutton.mousePressed(this.mc, p_73864_1_, p_73864_2_))
                {
                    GuiScreenEvent.ActionPerformedEvent.Pre event = new GuiScreenEvent.ActionPerformedEvent.Pre(this, guibutton, this.buttonList);
                    if (MinecraftForge.EVENT_BUS.post(event))
                        break;
                    this.selectedButton = event.button;
                    event.button.func_146113_a(this.mc.getSoundHandler());
                    this.actionPerformed(event.button);
                    if (this.equals(this.mc.currentScreen))
                        MinecraftForge.EVENT_BUS.post(new GuiScreenEvent.ActionPerformedEvent.Post(this, event.button, this.buttonList));
                }
            }
        }

        if (disableSlot) {
            return;
        }

        boolean flag = p_73864_3_ == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100;
        Slot slot = this.getSlotAtPosition(p_73864_1_, p_73864_2_);
        long l = Minecraft.getSystemTime();
        this.field_146993_M = this.field_146998_K == slot && l - this.field_146997_J < 250L && this.field_146992_L == p_73864_3_;
        this.field_146995_H = false;

        if (p_73864_3_ == 0 || p_73864_3_ == 1 || flag)
        {
            int i1 = this.guiLeft;
            int j1 = this.guiTop;
            boolean flag1 = p_73864_1_ < i1 || p_73864_2_ < j1 || p_73864_1_ >= i1 + this.xSize || p_73864_2_ >= j1 + this.ySize;
            int k1 = -1;

            if (slot != null)
            {
                k1 = slot.slotNumber;
            }

            if (flag1)
            {
                k1 = -999;
            }

            if (this.mc.gameSettings.touchscreen && flag1 && this.mc.thePlayer.inventory.getItemStack() == null)
            {
                this.mc.displayGuiScreen((GuiScreen)null);
                return;
            }

            if (k1 != -1)
            {
                if (this.mc.gameSettings.touchscreen)
                {
                    if (slot != null && slot.getHasStack())
                    {
                        this.clickedSlot = slot;
                        this.draggedStack = null;
                        this.isRightMouseClick = p_73864_3_ == 1;
                    }
                    else
                    {
                        this.clickedSlot = null;
                    }
                }
                else if (!this.field_147007_t)
                {
                    if (this.mc.thePlayer.inventory.getItemStack() == null)
                    {
                        if (p_73864_3_ == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100)
                        {
                            this.handleMouseClick(slot, k1, p_73864_3_, 3);
                        }
                        else
                        {
                            boolean flag2 = k1 != -999 && (Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54));
                            byte b0 = 0;

                            if (flag2)
                            {
                                this.field_146994_N = slot != null && slot.getHasStack() ? slot.getStack() : null;
                                b0 = 1;
                            }
                            else if (k1 == -999)
                            {
                                b0 = 4;
                            }

                            this.handleMouseClick(slot, k1, p_73864_3_, b0);
                        }

                        this.field_146995_H = true;
                    }
                    else
                    {
                        this.field_147007_t = true;
                        this.field_146988_G = p_73864_3_;
                        this.field_147008_s.clear();

                        if (p_73864_3_ == 0)
                        {
                            this.field_146987_F = 0;
                        }
                        else if (p_73864_3_ == 1)
                        {
                            this.field_146987_F = 1;
                        }
                    }
                }
            }
        }

        this.field_146998_K = slot;
        this.field_146997_J = l;
        this.field_146992_L = p_73864_3_;
    }

    // Копипаст из родителя-GuiContainer
    /**
     * Called when a mouse button is pressed and the mouse is moved around. Parameters are : mouseX, mouseY,
     * lastButtonClicked & timeSinceMouseClick.
     */
    @Override
    protected void mouseClickMove(int p_146273_1_, int p_146273_2_, int p_146273_3_, long p_146273_4_)
    {
        Slot slot = this.getSlotAtPosition(p_146273_1_, p_146273_2_);
        ItemStack itemstack = this.mc.thePlayer.inventory.getItemStack();

        if (this.clickedSlot != null && this.mc.gameSettings.touchscreen)
        {
            if (p_146273_3_ == 0 || p_146273_3_ == 1)
            {
                if (this.draggedStack == null)
                {
                    if (slot != this.clickedSlot)
                    {
                        this.draggedStack = this.clickedSlot.getStack().copy();
                    }
                }
                else if (this.draggedStack.stackSize > 1 && slot != null && Container.func_94527_a(slot, this.draggedStack, false))
                {
                    long i1 = Minecraft.getSystemTime();

                    if (this.field_146985_D == slot)
                    {
                        if (i1 - this.field_146986_E > 500L)
                        {
                            this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, 0, 0);
                            this.handleMouseClick(slot, slot.slotNumber, 1, 0);
                            this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, 0, 0);
                            this.field_146986_E = i1 + 750L;
                            --this.draggedStack.stackSize;
                        }
                    }
                    else
                    {
                        this.field_146985_D = slot;
                        this.field_146986_E = i1;
                    }
                }
            }
        }
        else if (this.field_147007_t && slot != null && itemstack != null && itemstack.stackSize > this.field_147008_s.size() && Container.func_94527_a(slot, itemstack, true) && slot.isItemValid(itemstack) && this.inventorySlots.canDragIntoSlot(slot))
        {
            this.field_147008_s.add(slot);
            this.func_146980_g();
        }
    }

    // Копипаст из родителя-GuiContainer
    /**
     * Called when the mouse is moved or a mouse button is released.  Signature: (mouseX, mouseY, which) which==-1 is
     * mouseMove, which==0 or which==1 is mouseUp
     */
    @Override
    protected void mouseMovedOrUp(int p_146286_1_, int p_146286_2_, int p_146286_3_)
    {
        // Супер-супера
        //super.mouseMovedOrUp(p_146286_1_, p_146286_2_, p_146286_3_); //Forge, Call parent to release buttons
        if (this.selectedButton != null && p_146286_3_ == 0)
        {
            this.selectedButton.mouseReleased(p_146286_1_, p_146286_2_);
            this.selectedButton = null;
        }

        Slot slot = this.getSlotAtPosition(p_146286_1_, p_146286_2_);
        int l = this.guiLeft;
        int i1 = this.guiTop;
        boolean flag = p_146286_1_ < l || p_146286_2_ < i1 || p_146286_1_ >= l + this.xSize || p_146286_2_ >= i1 + this.ySize;
        int j1 = -1;

        if (slot != null)
        {
            j1 = slot.slotNumber;
        }

        if (flag)
        {
            j1 = -999;
        }

        Slot slot1;
        Iterator iterator;

        if (this.field_146993_M && slot != null && p_146286_3_ == 0 && this.inventorySlots.func_94530_a((ItemStack)null, slot))
        {
            if (isShiftKeyDown())
            {
                if (slot != null && slot.inventory != null && this.field_146994_N != null)
                {
                    iterator = this.inventorySlots.inventorySlots.iterator();

                    while (iterator.hasNext())
                    {
                        slot1 = (Slot)iterator.next();

                        if (slot1 != null && slot1.canTakeStack(this.mc.thePlayer) && slot1.getHasStack() && slot1.inventory == slot.inventory && Container.func_94527_a(slot1, this.field_146994_N, true))
                        {
                            this.handleMouseClick(slot1, slot1.slotNumber, p_146286_3_, 1);
                        }
                    }
                }
            }
            else
            {
                this.handleMouseClick(slot, j1, p_146286_3_, 6);
            }

            this.field_146993_M = false;
            this.field_146997_J = 0L;
        }
        else
        {
            if (this.field_147007_t && this.field_146988_G != p_146286_3_)
            {
                this.field_147007_t = false;
                this.field_147008_s.clear();
                this.field_146995_H = true;
                return;
            }

            if (this.field_146995_H)
            {
                this.field_146995_H = false;
                return;
            }

            boolean flag1;

            if (this.clickedSlot != null && this.mc.gameSettings.touchscreen)
            {
                if (p_146286_3_ == 0 || p_146286_3_ == 1)
                {
                    if (this.draggedStack == null && slot != this.clickedSlot)
                    {
                        this.draggedStack = this.clickedSlot.getStack();
                    }

                    flag1 = Container.func_94527_a(slot, this.draggedStack, false);

                    if (j1 != -1 && this.draggedStack != null && flag1)
                    {
                        this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, p_146286_3_, 0);
                        this.handleMouseClick(slot, j1, 0, 0);

                        if (this.mc.thePlayer.inventory.getItemStack() != null)
                        {
                            this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, p_146286_3_, 0);
                            this.field_147011_y = p_146286_1_ - l;
                            this.field_147010_z = p_146286_2_ - i1;
                            this.returningStackDestSlot = this.clickedSlot;
                            this.returningStack = this.draggedStack;
                            this.returningStackTime = Minecraft.getSystemTime();
                        }
                        else
                        {
                            this.returningStack = null;
                        }
                    }
                    else if (this.draggedStack != null)
                    {
                        this.field_147011_y = p_146286_1_ - l;
                        this.field_147010_z = p_146286_2_ - i1;
                        this.returningStackDestSlot = this.clickedSlot;
                        this.returningStack = this.draggedStack;
                        this.returningStackTime = Minecraft.getSystemTime();
                    }

                    this.draggedStack = null;
                    this.clickedSlot = null;
                }
            }
            else if (this.field_147007_t && !this.field_147008_s.isEmpty())
            {
                this.handleMouseClick((Slot)null, -999, Container.func_94534_d(0, this.field_146987_F), 5);
                iterator = this.field_147008_s.iterator();

                while (iterator.hasNext())
                {
                    slot1 = (Slot)iterator.next();
                    this.handleMouseClick(slot1, slot1.slotNumber, Container.func_94534_d(1, this.field_146987_F), 5);
                }

                this.handleMouseClick((Slot)null, -999, Container.func_94534_d(2, this.field_146987_F), 5);
            }
            else if (this.mc.thePlayer.inventory.getItemStack() != null)
            {
                if (p_146286_3_ == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100)
                {
                    this.handleMouseClick(slot, j1, p_146286_3_, 3);
                }
                else
                {
                    flag1 = j1 != -999 && (Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54));

                    if (flag1)
                    {
                        this.field_146994_N = slot != null && slot.getHasStack() ? slot.getStack() : null;
                    }

                    this.handleMouseClick(slot, j1, p_146286_3_, flag1 ? 1 : 0);
                }
            }
        }

        if (this.mc.thePlayer.inventory.getItemStack() == null)
        {
            this.field_146997_J = 0L;
        }

        this.field_147007_t = false;
    }

    // Копипаст из родителя-GuiContainer
    private void func_146980_g()
    {
        ItemStack itemstack = this.mc.thePlayer.inventory.getItemStack();

        if (itemstack != null && this.field_147007_t)
        {
            this.field_146996_I = itemstack.stackSize;
            ItemStack itemstack1;
            int i;

            for (Iterator iterator = this.field_147008_s.iterator(); iterator.hasNext(); this.field_146996_I -= itemstack1.stackSize - i)
            {
                Slot slot = (Slot)iterator.next();
                itemstack1 = itemstack.copy();
                i = slot.getStack() == null ? 0 : slot.getStack().stackSize;
                Container.func_94525_a(this.field_147008_s, this.field_146987_F, itemstack1, i);

                if (itemstack1.stackSize > itemstack1.getMaxStackSize())
                {
                    itemstack1.stackSize = itemstack1.getMaxStackSize();
                }

                if (itemstack1.stackSize > slot.getSlotStackLimit())
                {
                    itemstack1.stackSize = slot.getSlotStackLimit();
                }
            }
        }
    }

    // Копипаст из родителя-GuiContainer
    /**
     * Returns the slot at the given coordinates or null if there is none.
     */
    private Slot getSlotAtPosition(int p_146975_1_, int p_146975_2_)
    {
        for (int k = 0; k < this.inventorySlots.inventorySlots.size(); ++k)
        {
            Slot slot = (Slot)this.inventorySlots.inventorySlots.get(k);

            if (this.isMouseOverSlot(slot, p_146975_1_, p_146975_2_))
            {
                return slot;
            }
        }

        return null;
    }
}

AdvanceInventoryEffectRenderer
Код:
package rsstats.client.gui.advanced;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.resources.I18n;
import net.minecraft.inventory.Container;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import org.lwjgl.opengl.GL11;

import java.util.Collection;
import java.util.Iterator;

@SideOnly(Side.CLIENT)
public abstract class AdvanceInventoryEffectRenderer extends AdvanceGuiContainer {
    private boolean field_147045_u;
    private static final String __OBFID = "CL_00000755";

    public AdvanceInventoryEffectRenderer(Container p_i1089_1_)
    {
        super(p_i1089_1_);
    }

    /**
     * Adds the buttons (and other controls) to the screen in question.
     */
    public void initGui()
    {
        super.initGui();

        if (!this.mc.thePlayer.getActivePotionEffects().isEmpty())
        {
            this.guiLeft = 160 + (this.width - this.xSize - 200) / 2;
            this.field_147045_u = true;
        }
    }

    /**
     * Draws the screen and all the components in it.
     */
    public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_)
    {
        super.drawScreen(p_73863_1_, p_73863_2_, p_73863_3_);

        if (this.field_147045_u)
        {
            this.func_147044_g();
        }
    }

    private void func_147044_g()
    {
        int i = this.guiLeft - 124;
        int j = this.guiTop;
        boolean flag = true;
        Collection collection = this.mc.thePlayer.getActivePotionEffects();

        if (!collection.isEmpty())
        {
            GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
            GL11.glDisable(GL11.GL_LIGHTING);
            int k = 33;

            if (collection.size() > 5)
            {
                k = 132 / (collection.size() - 1);
            }

            for (Iterator iterator = this.mc.thePlayer.getActivePotionEffects().iterator(); iterator.hasNext(); j += k)
            {
                PotionEffect potioneffect = (PotionEffect)iterator.next();
                Potion potion = Potion.potionTypes[potioneffect.getPotionID()];
                GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
                this.mc.getTextureManager().bindTexture(field_147001_a);
                this.drawTexturedModalRect(i, j, 0, 166, 140, 32);

                if (potion.hasStatusIcon())
                {
                    int l = potion.getStatusIconIndex();
                    this.drawTexturedModalRect(i + 6, j + 7, 0 + l % 8 * 18, 198 + l / 8 * 18, 18, 18);
                }

                potion.renderInventoryEffect(i, j, potioneffect, mc);
                if (!potion.shouldRenderInvText(potioneffect)) continue;
                String s1 = I18n.format(potion.getName(), new Object[0]);

                if (potioneffect.getAmplifier() == 1)
                {
                    s1 = s1 + " " + I18n.format("enchantment.level.2", new Object[0]);
                }
                else if (potioneffect.getAmplifier() == 2)
                {
                    s1 = s1 + " " + I18n.format("enchantment.level.3", new Object[0]);
                }
                else if (potioneffect.getAmplifier() == 3)
                {
                    s1 = s1 + " " + I18n.format("enchantment.level.4", new Object[0]);
                }

                this.fontRendererObj.drawStringWithShadow(s1, i + 10 + 18, j + 6, 16777215);
                String s = Potion.getDurationString(potioneffect);
                this.fontRendererObj.drawStringWithShadow(s, i + 10 + 18, j + 6 + 10, 8355711);
            }
        }
    }
}

ZLevelFontRenderer

Код:
package rsstats.client.gui.advanced;

import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;

/**
* {@link FontRenderer} с настраиваемой высотой отрисовки.
*/
public class ZLevelFontRenderer extends FontRenderer {
    // cм родителя. Скопировано из-за private
    private static final ResourceLocation[] unicodePageLocations = new ResourceLocation[256];
    public float zLevel;

    public ZLevelFontRenderer(GameSettings gameSettings, ResourceLocation resourceLocation, TextureManager textureManager, boolean unicodeFlag) {
        super(gameSettings, resourceLocation, textureManager, unicodeFlag);
    }

    // Копипаст из родителя из-за private
    private ResourceLocation getUnicodePageLocation(int p_111271_1_)
    {
        if (unicodePageLocations[p_111271_1_] == null)
        {
            unicodePageLocations[p_111271_1_] = new ResourceLocation(String.format("textures/font/unicode_page_%02x.png", new Object[] {Integer.valueOf(p_111271_1_)}));
        }

        return unicodePageLocations[p_111271_1_];
    }

    // Копипаст из родителя с добавлено поддержкой zLevel
    @Override
    protected float renderUnicodeChar(char p_78277_1_, boolean p_78277_2_) {
        if (this.glyphWidth[p_78277_1_] == 0)
        {
            return 0.0F;
        }
        else
        {
            int i = p_78277_1_ / 256;

            //this.loadGlyphTexture(i); // Из родителя
            bindTexture(this.getUnicodePageLocation(i)); // Мой реализация loadGlyphTexture() в обход кодительского private

            int j = this.glyphWidth[p_78277_1_] >>> 4;
            int k = this.glyphWidth[p_78277_1_] & 15;
            float f = (float)j;
            float f1 = (float)(k + 1);
            float f2 = (float)(p_78277_1_ % 16 * 16) + f;
            float f3 = (float)((p_78277_1_ & 255) / 16 * 16);
            float f4 = f1 - f - 0.02F;
            float f5 = p_78277_2_ ? 1.0F : 0.0F;
            GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
            GL11.glTexCoord2f(f2 / 256.0F, f3 / 256.0F);
            GL11.glVertex3f(this.posX + f5, this.posY, zLevel);
            GL11.glTexCoord2f(f2 / 256.0F, (f3 + 15.98F) / 256.0F);
            GL11.glVertex3f(this.posX - f5, this.posY + 7.99F, zLevel);
            GL11.glTexCoord2f((f2 + f4) / 256.0F, f3 / 256.0F);
            GL11.glVertex3f(this.posX + f4 / 2.0F + f5, this.posY, zLevel);
            GL11.glTexCoord2f((f2 + f4) / 256.0F, (f3 + 15.98F) / 256.0F);
            GL11.glVertex3f(this.posX + f4 / 2.0F - f5, this.posY + 7.99F, zLevel);
            GL11.glEnd();
            return (f1 - f) / 2.0F + 1.0F;
        }
    }
}

ZLevelGuiButton

Код:
package rsstats.client.gui.advanced;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;

/**
* Кнопка, с настраиваемой высотой отрисовки.
*/
public class ZLevelGuiButton extends GuiButton {
    /** Отрисовщик текста с настраиваемой высотой отрисовки */
    ZLevelFontRenderer fontrenderer = new ZLevelFontRenderer(Minecraft.getMinecraft().gameSettings, new ResourceLocation("textures/font/ascii.png"), Minecraft.getMinecraft().renderEngine, false);

    public ZLevelGuiButton(int id, int xPosition, int yPosition, String displayString) {
        super(id, xPosition, yPosition, displayString);
    }

    public ZLevelGuiButton(int id, int xPosition, int yPosition, int width, int height, String displayString) {
        super(id, xPosition, yPosition, width, height, displayString);
    }

    /**
     * Геттер для поля {@link #zLevel}
     * @param zLevel Высота отрисовки кнопки
     */
    public void setZLevel(float zLevel) {
        this.zLevel = zLevel;
    }

    // Копипаст из родителя с измененным fontRenderer'ом
    @Override
    public void drawButton(Minecraft p_146112_1_, int p_146112_2_, int p_146112_3_) {
        fontrenderer.zLevel = zLevel + 1;

        if (this.visible)
        {
            p_146112_1_.getTextureManager().bindTexture(buttonTextures);
            GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
            this.field_146123_n = p_146112_2_ >= this.xPosition && p_146112_3_ >= this.yPosition && p_146112_2_ < this.xPosition + this.width && p_146112_3_ < this.yPosition + this.height;
            int k = this.getHoverState(this.field_146123_n);
            GL11.glEnable(GL11.GL_BLEND);
            OpenGlHelper.glBlendFunc(770, 771, 1, 0);
            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
            this.drawTexturedModalRect(this.xPosition, this.yPosition, 0, 46 + k * 20, this.width / 2, this.height);
            this.drawTexturedModalRect(this.xPosition + this.width / 2, this.yPosition, 200 - this.width / 2, 46 + k * 20, this.width / 2, this.height);
            this.mouseDragged(p_146112_1_, p_146112_2_, p_146112_3_);
            int l = 14737632;

            if (packedFGColour != 0)
            {
                l = packedFGColour;
            }
            else if (!this.enabled)
            {
                l = 10526880;
            }
            else if (this.field_146123_n)
            {
                l = 16777120;
            }

            this.drawCenteredString(fontrenderer, this.displayString, this.xPosition + this.width / 2, this.yPosition + (this.height - 8) / 2, l);
        }
    }
}


!!!!!!----------------------------------------------------------------------------------------!!!!!!
когда дело доходит до стеков они не рисуются из-за того что не проходят Depth Test
Похоже, что ты прав. Забавы ради я попробовал вообще отключить Depth Test при отрисовке скаков и результат стал больше похож на тот, что мне нужно
ф.png
См функцию GuiContainer#func_146977_a. Именно там я это отключил

Код:
if (!flag1)
        {
            if (flag)
            {
                drawRect(i, j, i + 16, j + 16, -2130706433);
            }
            //System.out.println("Рисую стак " + itemRender.zLevel);
            //GL11.glEnable(GL11.GL_DEPTH_TEST); // ОТКЛЮЧАЮ!
            itemRender.renderItemAndEffectIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), itemstack, i, j);
            itemRender.renderItemOverlayIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), itemstack, i, j, s);
        }

Но появилась новая напасть. Если хоть в одном слоте есть стак с несколькими предметами, то снова получает отсутствие прорисовки сткаков
a3.png
 
Последнее редактирование:
1,159
38
544
Хм по идеи чтобы фон нормально смещался с айтем стаками нужно чтобы айтем стаки рендерелись первыми. Иначе выходит что ты рисуешь свой бэкграунд, он смешивается с тем что на данный моммент сзади него есть(и это не стаки), а потом когда дело доходит до стеков они не рисуются из-за того что не проходят Depth Test. Мораль: рисуй сначала айтем стэки.
Все! Я все понял. Спасибо тебе мужик. Только возникает вопрос: какой смысл в zLevel, если отрисовка идет в том порядке, в каком устанавливает его программист?
 
Только возникает вопрос: какой смысл в zLevel
Чтобы объекты не "проваливались" друг в друга, такое возможно если объект трехмерный. Например моделька игрока в инвентаре.
 
Сверху