[1.7.10] GUI меню от блок

Версия Minecraft
1.7.10
API
Forge
делал GUI по этой теме тык но тут проблемка не могу открыть её по блоку

TestBlock:
package spokers.block;

import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import spokers.Entity.TileEntityTest;
import spokers.Spokers;
import spokers.block.gui.GuiHandlerP;
import spokers.block.gui.GuiP;

public class Tst extends Block implements ITileEntityProvider {

    public Tst() {
        super(Material.circuits);
        setCreativeTab(Spokers.spokerstab);
        setHardness(0.25F);
        setStepSound(soundTypeMetal);
        setBlockTextureName("iron_block");
        setBlockName(Spokers.MODID + ".block_techne1");
    }

    @Override
    public TileEntity createNewTileEntity(World world, int metadata) {
        return new TileEntityTest();
    }

    public int getRenderType() {
        return -1;
    }

    public boolean isOpaqueCube() {
        return false;
    }

    public boolean renderAsNormalBlock() {
        return false;
    }

    @Override
    public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float clickX,
                                    float clickY, float clickZ) {
        Block block = world.getBlock(x, y, z);
        TileEntity entity = world.getTileEntity(x, y, z);
        // Открыть GUI только, если игрок, блок и TileEntity не равны нулю, а также TileEntity является инстанцией нужного.
        if (block != null && entity instanceof TileEntityTest && player != null) {
            // Открыть GUI, если игрок не сидит.
            if (!player.isSneaking()) {
                // Открыть у игрока GUI из мода (первый аргумент) под id (второй аргумент).
                player.openGui(Spokers.instance, 0, world, x, y, z);
                return true;
            }
        }
        return false;
    }
}

ContainerP:
package spokers.block.Container;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import spokers.block.Entity.TileEntityP;

public class ContainerP extends Container {
    private TileEntityP tile;

    /**
     * В аргументы указывается инвентарь игрока и TileEntity, который мы открыли
     */
    public ContainerP(InventoryPlayer player, TileEntityP testTile) {
    /* Назначаем локальный TileEntity на тот, откуда открывается контейнер. Нужно для методов,
    что требуют TileEntity. */
        tile = testTile;
        //Переменная, отвечающая за id слота, да, они не должны повторятся.
        int i = 0;
    /* Метод, отвечающий за добавление слота, для конструктора обычного слота используется:
    IInventory (Тут - инвентарь TileEntity), id слота (будет использовать getStackInSlot, или как его там),
    два целых числа, обозначающие местонахождение слота. */
        addSlotToContainer(new Slot(testTile, i++, 8, 38));
        //Второй слот инвентаря
        addSlotToContainer(new Slot(testTile, i++, 44, 21));
    /* Два цикла, отвечающие за добавление инвентаря игрока (второй - его хотбар) в привычные места
    интерфейса (и контейнера). Да, just copy paste. */
        for (i = 0; i < 3; ++i) {
            for (int j = 0; j < 9; ++j) {
                this.addSlotToContainer(new Slot(player, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
            }
        }
        for (i = 0; i < 9; ++i) {
            this.addSlotToContainer(new Slot(player, i, 8 + i * 18, 142));
        }
    }


    /**
     * Метод, который выполняется до открытия контейнера и GUI, обычно используется для проверки расстояния
     * между игроком и TileEntity (и отмены открытия, если оно слишком большое).
     */
    @Override
    public boolean canInteractWith(EntityPlayer player) {
        return tile.isUseableByPlayer(player);
    }
}

GuiP:
package spokers.block.gui;

import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import spokers.Spokers;
import spokers.block.Container.ContainerP;
import spokers.block.Entity.TileEntityP;

public class GuiP extends GuiContainer {

    private static final ResourceLocation textures = new ResourceLocation(
            Spokers.MODID, "textures/gui/container/GUI.png");

    private TileEntityP tile;

    public GuiP(InventoryPlayer player, TileEntityP tileTest) {
        // Сюда указать объект контейнера.
        super(new ContainerP(player, tileTest));
        // Сохраняем TileEntity в объекте GUI для использования другими методами.
        tile = tileTest;
    }

    /**
     * Метод для отрисовки текстов и etc.
     */
    @Override
    protected void drawGuiContainerForegroundLayer(int x, int y) {
        // Отрисовать название инвентаря игрока, где оно обычно находится.
        fontRendererObj.drawString(I18n.format("container.inventory", new Object[0]), 8, ySize - 96 + 2,
                4210752);
        // Отрисовать название GUI (TileEntity), учитывая его переименование и локализацию.
        String s = tile.hasCustomInventoryName() ? tile.getInventoryName()
                : I18n.format(tile.getInventoryName(), new Object[0]);
        fontRendererObj.drawString(s, 6, 6, 4210752);
    }

    /**
     * Метод отрисовки задника GUI (фон, etc).
     */
    @Override
    public void drawGuiContainerBackgroundLayer(float size, int x, int y) {
        // Окрасить все в белый цвет и в полную непрозрачность, не уверен в нужности.
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        // Привязать текстуру
        mc.getTextureManager().bindTexture(textures);
    }
}
GuiHandlerP:
package spokers.block.gui;

import cpw.mods.fml.common.network.IGuiHandler;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import spokers.block.Container.ContainerP;
import spokers.block.Entity.TileEntityP;

public class GuiHandlerP implements IGuiHandler {
    /**
     * Вызов контейнера при его открытии.
     */
    @Override
    public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        // Получить TileEntity, из которого вызван контейнер.
        TileEntity tile = world.getTileEntity(x, y, z);
    /* Проверяем id контейнера на ноль (первый), можно вынести id контейнеров в константы.
    Также проверяем, что TileEntity является тем, для которого сделан контейнер. */
        if (ID == 0 && tile instanceof TileEntityP)
            return new ContainerP(player.inventory, (TileEntityP) tile);
        // Ничего не возвращаем, сли не один из контейнеров не был вызван.
        return null;
    }

    /**
     * Вызов GUI для контейнера.
     */
    @Override
    public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        // Получить TileEntity, из которого вызван GUI.
        TileEntity tile = world.getTileEntity(x, y, z);
        // Проверить id (оно должно совпадать с id контейнера) и TileEntity на принадлежность к GUI.
        if (ID == 0 && tile instanceof TileEntityP)
            return new GuiP(player.inventory, (TileEntityP) tile);
        return null;
    }
}
TileEntityP:
package spokers.block.Entity;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;

public class TileEntityP extends TileEntity implements IInventory {

    public TileEntityP() {

    }

    @Override
    public int getSizeInventory() {
        return 8;
    }

    @Override
    public ItemStack getStackInSlot(int i) {
        return null;
    }

    @Override
    public ItemStack decrStackSize(int i, int i1) {
        return null;
    }

    @Override
    public ItemStack getStackInSlotOnClosing(int i) {
        return null;
    }

    @Override
    public void setInventorySlotContents(int i, ItemStack itemStack) {

    }

    @Override
    public String getInventoryName() {
        return "null";
    }

    @Override
    public boolean hasCustomInventoryName() {
        return false;
    }

    @Override
    public int getInventoryStackLimit() {
        return 64;
    }

    @Override
    public boolean isUseableByPlayer(EntityPlayer entityPlayer) {
        return false;
    }

    @Override
    public void openInventory() {

    }

    @Override
    public void closeInventory() {

    }

    @Override
    public boolean isItemValidForSlot(int i, ItemStack itemStack) {
        return false;
    }
}
Spokers:
package spokers;


import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkRegistry;
import net.minecraft.creativetab.CreativeTabs;
import spokers.CreativeTab.SpokersTab;
import spokers.Recipes.Recipe;
import spokers.block.Blocks;
import spokers.block.gui.GuiHandlerP;
import spokers.items.Items;

@Mod(modid = Spokers.MODID, version = Spokers.VERSION, name = Spokers.NAME)

public class Spokers {
    public static final String MODID = "Spokers";
    public static final String VERSION = "1";
    public static final String NAME = "Spokerss";

    @Mod.Instance(Spokers.MODID) public static Spokers instance;
    @SidedProxy(modId = Spokers.MODID, clientSide = "spokers.ProxyClient", serverSide = "spokers.ProxyCommon")
    public static ProxyCommon proxy;

    public static CreativeTabs spokerstab = new SpokersTab("11");

    @Mod.EventHandler
    public void init(FMLInitializationEvent event)
    {
        proxy.init();
        NetworkRegistry.INSTANCE.registerGuiHandler(Spokers.instance, new GuiHandlerP());
    }

    @Mod.EventHandler
    public void preload(FMLPreInitializationEvent event){
        Recipe.registerRecipes();
    }

    @Mod.EventHandler
    public void preInit(FMLPreInitializationEvent event) {

        Items.registerItems();
        Blocks.registerBlock();

        proxy.preInit();

    }

}

Возникает вопрос ещё что вставлять сюда
Testblokc (Tst)
player.openGui(Spokers.instance, 0, world, x, y, z);
 
390
7
27
Spokers написал(а):
и итемы по шифту +пкм кидаются в первые 3 слота (линию)
Для этого есть метод transferStackInSlot в твоем контейнере. Посмотри, как это устроено в ванильных классах (пр. та же печь), там довольно просто: если id слота такой-то, то попытаться скинуть стак в промежуток таких-то id слотов в зависимости от того, как тебе надо, чтобы раскидывалось и твоих айдишников.
 

sk9zist :l

Исправился
981
18
157
390
7
27
Spokers написал(а):
В гуи проверяешь, что твой слот с результатом не пустой и отрисовываешь нужный кусок текстуры на нужной тебе позиции
Например, как-то так:
Java:
if(tile.stackResult[ид слота] != null) drawTexturedModalRect(x, y, начало текстуры по х, начало текстуры по у, ширина текстуры, высота текстуры);
 

sk9zist :l

Исправился
981
18
157
Последнее редактирование:
Происходит краш при открытие гуи
GuiP:
package spokers.block.gui;

import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import spokers.block.Container.ContainerP;
import spokers.block.Entity.TileEntityP;

public class GuiP extends GuiContainer {

    private static final ResourceLocation texture = new ResourceLocation("spokers:textures/gui/GUI.png");
    private InventoryPlayer inventory;
    private TileEntityP tile;

    public GuiP(InventoryPlayer player, TileEntityP tileTest) {
        super(new ContainerP(player, tileTest));
        inventory = player.player.inventory;
        tile = tileTest;
    }

    @Override
    public void drawGuiContainerBackgroundLayer(float size, int x, int y) {
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        mc.getTextureManager().bindTexture(texture);
        int j = (super.width - super.xSize) / 2;
        int k = (super.height - super.ySize) / 2;
        drawTexturedModalRect(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);
        if(tile.stackResult[15] != null) {
            int i1 = this.tile.getPowerScaled(24);
            drawTexturedModalRect(j + 79, k + 34, 176, 14, i1 + 1, 16);
        }
    }
}
TileEntityP:
package spokers.block.Entity;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.Constants.NBT;
import spokers.Recipes.PressRecipes;


public class TileEntityP extends TileEntity implements ISidedInventory {

    public ItemStack[] stackResult = new ItemStack[15];
    private String custom_name;
    private PressRecipes.Recipe recipe = null;
    private static final int[]
            topSlots = new int[] {13},
            sideSlots = new int[] {14};
    public int time = 0, time_max = 0;
    public int tickPowerTime = 0;
    public int speedreamaningTime = 1000;


    public TileEntityP()
    {

    }

    @Override
    public void updateEntity() {
        if (worldObj.isRemote) return;
        ItemStack input = getStackInSlot(0);
        ItemStack output = getStackInSlot(1);

        if (time == 0) {

            if (recipe != null) {
                if (output == null) {
                    setInventorySlotContents(1, recipe.output.copy());
                    recipe = null;
                    time_max = 0;
                } else if (output.isItemEqual(recipe.output) && ItemStack.areItemStackTagsEqual(output, recipe.output) && recipe.output.stackSize + output.stackSize <= 64) {
                    output.stackSize += recipe.output.stackSize;
                    setInventorySlotContents(1, output);
                    recipe = null;
                    time_max = 0;
                }
            } else {
                recipe = PressRecipes.getRecipe(input);

                if (recipe != null) {
                    time_max = time = recipe.time;
                    if (input != null && input.getItem().hasContainerItem(input)) {
                        setInventorySlotContents(0, input.getItem().getContainerItem(input));
                    } else {
                        input.stackSize -= recipe.input.stackSize;
                        if (input.stackSize <= 0)
                            setInventorySlotContents(0, null);
                        else
                            setInventorySlotContents(0, input);
                    }
                }
            }

        } else {
            --time;
        }

    }
    @Override
    public int getSizeInventory() {
        return 15;
    }
    @Override
    public ItemStack getStackInSlot(int i)
    {
        return this.stackResult[i];
    }

    @Override
    public ItemStack decrStackSize(int i, int s)
    {
        if (this.stackResult[i] != null)
        {
            ItemStack is;

            if (this.stackResult[i].stackSize <= s)
            {
                is = this.stackResult[i];
                this.stackResult[i] = null;
                return is;
            }
            else
            {
                is = this.stackResult[i].splitStack(s);

                if (this.stackResult[i].stackSize == 0)
                {
                    this.stackResult[i] = null;
                }

                return is;
            }
        }
        else
        {
            return null;
        }
    }

    @Override
    public ItemStack getStackInSlotOnClosing(int i)
    {
        if (this.stackResult[i] != null)
        {
            ItemStack is = this.stackResult[i];
            this.stackResult[i] = null;
            return is;
        }
        else
        {
            return null;
        }
    }

    @SideOnly(Side.CLIENT)
    public int getPowerScaled(int i) {
        if (this.tickPowerTime <= 0) {
            return 0;
        } else {
            int r = this.tickPowerTime * i / this.speedreamaningTime;
            if (r > i) {
                r = i;
            }

            return r;
        }
    }

    @Override
    public String getInventoryName() {
        return "Namer";
    }

    @Override
    public boolean hasCustomInventoryName() {
         return true;
    }

    @Override
    public int getInventoryStackLimit() {
        return 64;
    }
    @Override
    public void setInventorySlotContents(int s, ItemStack i)
    {
        this.stackResult[s] = i;

        if (i != null && i.stackSize > this.getInventoryStackLimit())
        {
            i.stackSize = this.getInventoryStackLimit();
        }
    }

    public void setInventoryName(String name) {
        custom_name = name;
    }

    @Override
    public void writeToNBT(NBTTagCompound nbt) {
        super.writeToNBT(nbt);
        NBTTagList list = new NBTTagList();
        for (int i = 0; i < getSizeInventory(); ++i) {
            if (getStackInSlot(i) == null) continue;
            NBTTagCompound slot_nbt = new NBTTagCompound();
            getStackInSlot(i).writeToNBT(slot_nbt);
            slot_nbt.setByte("Slot", (byte)i);
            list.appendTag(slot_nbt);
        }
        nbt.setTag("Inventory", list);
        if (hasCustomInventoryName()) nbt.setString("CustomName", getInventoryName());
    }

    @Override
    public void readFromNBT(NBTTagCompound nbt) {
        super.readFromNBT(nbt);
        if (nbt.hasKey("Inventory", NBT.TAG_LIST)) {
            NBTTagList list = nbt.getTagList("Inventory", NBT.TAG_COMPOUND);
            for (int i = 0; i < list.tagCount(); ++i) {
                NBTTagCompound slot_nbt = list.getCompoundTagAt(i);
                setInventorySlotContents((slot_nbt.getByte("Slot") & 255), ItemStack.loadItemStackFromNBT(slot_nbt));
            }
        }
        if (nbt.hasKey("CustomName", NBT.TAG_STRING)) setInventoryName(nbt.getString("CustomName"));
    }

    @Override
    public boolean isUseableByPlayer(EntityPlayer entityPlayer) {
        return this.worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false: entityPlayer.getDistanceSq((double)this.xCoord + 0.5D,(double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
    }

    @Override
    public void openInventory() {}

    @Override
    public void closeInventory() {}

    @Override
    public boolean isItemValidForSlot(int slotID, ItemStack itemStack) {
        if (PressRecipes.getRecipe(itemStack) == null)
            return false;
        return true;
    }

    @Override
    public int[] getAccessibleSlotsFromSide(int side) {
        return side == 0 ? topSlots : sideSlots;
    }

    @Override
    public boolean canInsertItem(int slotID, ItemStack itemStack, int side) {
        return side != 0 && isItemValidForSlot(slotID, itemStack);
    }

    @Override
    public boolean canExtractItem(int slotID, ItemStack itemStack, int side) {
        return side == 0;
    }
}
 

sk9zist :l

Исправился
981
18
157
это 0, 1, 2, 3...14, а у тебя в проверке стоит 15
+. Тебе нужно цикл сделать и в проверке поставить переменную цикла.
Сделай у себя вот эти методы:

Java:
private int getBurnLeftScaled(int pixels)
    {
        int i = this.tileentity.getField(1);
        if(i == 0) i = 200;
        return this.tileentity.getField(0) * pixels / i;
    }
 
    private int getCookProgressScaled(int pixels, int slot, int slot2)
    {
        int i = this.tileentity.getField(slot);
        int j = this.tileentity.getField(slot2);
        return j != 0 && i != 0 ? i * pixels / j : 0;
    }
А потом замени свой код на этот, и поставь свои значения:

Java:
if(TileEntitySimpleFurnace.isBurning(tileentity))
        {
            // 13 - ширина и высота модели огня
            int k = this.getBurnLeftScaled(13);
        
            // 57 - от левого края до огня
            // 37 - от верхней точки до огня
            this.drawTexturedModalRect(this.guiLeft + 57, this.guiTop + 37 + 12 - k, 176, 12 - k, 14, k + 1);
        }
    
        // 24 - ширина модели прогресс бара готовки
        int l = this.getCookProgressScaled(24, 2, 3);
    
        // 80 - от левого края до прогресс бара
        // 21 - от верхней точки до прогресс бара
        this.drawTexturedModalRect(this.guiLeft + 80, this.guiTop + 21, 176, 14, l + 1, 16);
(у меня вариант без цикла, но если хочешь то можешь завернуть сразу всё это в цикл)
 

sk9zist :l

Исправился
981
18
157
У тебя ошибка "ArrayIndexOutOfBoundsException: 13"
- вышло за пределы массива, увеличь размер массива (у тебя ячеек больше чем массив)
 
Сверху