GUI создание

Версия Minecraft
1.7.10
128
12
Можно-ли ссылочку на годный гайд по созданию GUI? Можно и на английском, и на русском. Очень нужно.
 
Решение
Короче, дело такое (разумеется, объясняю создание GUI для инвентарных TileEntity):

Делаешь класс, наследующий Container:

Java:
package <пакет>;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ICrafting;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

import <пакет>.TileEntityTest;

public class ContainerTest extends Container {
    private TileEntityTest tile;

  /**
   * В аргументы указывается инвентарь игрока и TileEntity, который мы открыли
   */
    public...
1,057
50
234
1.12 != 1.7.10
 
128
12
1,200
37
237
Короче, дело такое (разумеется, объясняю создание GUI для инвентарных TileEntity):

Делаешь класс, наследующий Container:

Java:
package <пакет>;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ICrafting;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

import <пакет>.TileEntityTest;

public class ContainerTest extends Container {
    private TileEntityTest tile;

  /**
   * В аргументы указывается инвентарь игрока и TileEntity, который мы открыли
   */
    public ContainerTest(InventoryPlayer player, TileEntityTest 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);
    }
}

Затем, создаешь класс для самого GUI:

Java:
package <пакет>;

import org.lwjgl.opengl.GL11;

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 <пакет>.TileEntityTest;
import <пакет>.ContainerTest;

public class GuiTest extends GuiContainer {
  /** Текстура GUI */
    private static final ResourceLocation textures = new ResourceLocation(
            MODID, "textures/gui/container/<name>.png");

    private TileEntityTest tile;

    public GuiTest(InventoryPlayer player, TileEntityTest tileTest) {
    // Сюда указать объект контейнера.
        super(new ContainerTest(player, tile));
    // Сохраняем 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);
    }
}

Теперь, чтобы всё это работало нужно создать GuiHandler:

Java:
package <пакет>;

import cpw.mods.fml.common.network.IGuiHandler;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

import <пакет>.TileEntityTest;
import <пакет>.ContainerTest;
import <пакет>.GuiTest;

public class TestGuiHandler 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 TileEntityTest)
            return new ContainerTest(player.inventory, (TileEntityTest) 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 TileEntityTest)
            return new GuiTest(player.inventory, (TileEntityTest) tile);
        return null;
    }
}

Не забудь зарегистрировать его:

Java:
public void init(FMLInitializationEvent event) {
  // Инстанция мода и объект GuiHandler'а.
  NetworkRegistry.INSTANCE.registerGuiHandler(TESTMOD.instance, new TestGuiHandler());
}

Чтобы вызвать GUI кликом по блоку, добавь этот код в свой блок:

Java:
@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(TESTMOD.instance, GUIID, world, x, y, z);
      return true;
        }
    }
    return false;
}

-----------

Да, тебе придётся немного подкорректировать. Кстати, могут быть недочёты, я писал в блокноте ¯\_(ツ)_/¯
 
128
12
Короче, дело такое (разумеется, объясняю создание GUI для инвентарных TileEntity):

Делаешь класс, наследующий Container:

Java:
package <пакет>;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ICrafting;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

import <пакет>.TileEntityTest;

public class ContainerTest extends Container {
    private TileEntityTest tile;

  /**
   * В аргументы указывается инвентарь игрока и TileEntity, который мы открыли
   */
    public ContainerTest(InventoryPlayer player, TileEntityTest 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);
    }
}

Затем, создаешь класс для самого GUI:

Java:
package <пакет>;

import org.lwjgl.opengl.GL11;

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 <пакет>.TileEntityTest;
import <пакет>.ContainerTest;

public class GuiTest extends GuiContainer {
  /** Текстура GUI */
    private static final ResourceLocation textures = new ResourceLocation(
            MODID, "textures/gui/container/<name>.png");

    private TileEntityTest tile;

    public GuiTest(InventoryPlayer player, TileEntityTest tileTest) {
    // Сюда указать объект контейнера.
        super(new ContainerTest(player, tile));
    // Сохраняем 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);
    }
}

Теперь, чтобы всё это работало нужно создать GuiHandler:

Java:
package <пакет>;

import cpw.mods.fml.common.network.IGuiHandler;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

import <пакет>.TileEntityTest;
import <пакет>.ContainerTest;
import <пакет>.GuiTest;

public class TestGuiHandler 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 TileEntityTest)
            return new ContainerTest(player.inventory, (TileEntityTest) 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 TileEntityTest)
            return new GuiTest(player.inventory, (TileEntityTest) tile);
        return null;
    }
}

Не забудь зарегистрировать его:

Java:
public void init(FMLInitializationEvent event) {
  // Инстанция мода и объект GuiHandler'а.
  NetworkRegistry.INSTANCE.registerGuiHandler(TESTMOD.instance, new TestGuiHandler());
}

Чтобы вызвать GUI кликом по блоку, добавь этот код в свой блок:

Java:
@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(TESTMOD.instance, GUIID, world, x, y, z);
      return true;
        }
    }
    return false;
}

-----------

Да, тебе придётся немного подкорректировать. Кстати, могут быть недочёты, я писал в блокноте ¯\_(ツ)_/¯
Сейчас этим занялся, у меня вопрос, что за TileEntity? :/
 
1,159
38
544
Сейчас этим занялся, у меня вопрос, что за TileEntity? :/
TileEntity - это "сущность" (само название говорит). Она нужна для того чтобы хранить в себе данные (для игрока, например, - это мана и HP) и обновляться каждый тик. Я думаю, что тебе следует немного покурить мануалы вот тут, перед тем как заниматься GUI.
Возможно что-то сказал неверно, но кажись в целом все так

UPD: Вот тебе мануал и другие мануалы от этого автора. По мне, так очень годные.
 
Последнее редактирование:
1,038
57
229
Ответ у тебя перед носом, на сообщение выше.
А также пакеты между клиентом и сервером.
 
Подскажите кто знает, что отвечает за область в которой предметы не выбрасываются, а в которой выбрасывают (столкнулся с тем, что из хотбара предметы не берутся, а просто выбрасываются, будто находятся вне gui)
 
Сверху