Помощь в разборе простого кода

Версия Minecraft
1.7.10
81
3
Привет. Ниже были мои темы связанные с Тайлэнетити, вон еще парень спросил про инвентари.
В общем вопросы и найденные ссылки, советы других приводят к этому уроку: Форум

Начал разбирать. По началу все понятно но возникли вопросы следующие.

В мейн класее для регистрации/создания для мода блока используется:
Код:
    public static Block block_fabrication;

    @Mod.EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        block_fabrication = new BlockFabrication();

Вопрос в том, что я использовал что в уроках, что в своих пробах другой способ:
Java:
public static Block testblock;

    @EventHandler
    public void preLoad(FMLPreInitializationEvent event)
    {
        testblock = new TestBlock();


Если обратить внимание разница в:
public void preInit
public void preLoad

Есть ли разница между ними, что то влияющее не напимание мода или то как будет мод запускаться? Замудренно спросил да?=D

Крч, вообще в чем разница между инитом и прелоадом? Спрашиваю что бы понимать когда и что из них мне использовать. А то представьте, использовал всегда прелоад, а тут парень блок создает через преИнит.
======================

Второй вопрос связан уже с блоком который автор создает BlockFabrication
В классе блока я не нахожу регистрацию блока. Напомню что свои блоки в конце класса я регистрирую
Java:
GameRegistry.registerBlock(this, name); //Регистрируем блок. this, name можно убрать в зависимости от того как я общаюсь с мейном. Можно оставить скобки пустыми, ну я думаю вы и так знаете когда и что с ними делать.

А вот код автора, я не вижу что бы он регистрировал блок, во внимание тайл энетити и прочую работу с гуи и пр не берем в счет пока что, до этого еще мне предстоит дойти.
Java:
package timaxa007.fabrication.lesson3c;

import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

public class BlockFabrication extends Block implements ITileEntityProvider {

    public BlockFabrication() {
        super(Material.iron);
        this.setBlockName("block_fabrication");
        this.setBlockTextureName("fabrication:fabrication");
        this.setCreativeTab(CreativeTabs.tabBlock);
    }

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

    @Override
    public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entity, ItemStack itemStack) {
        if (itemStack.hasDisplayName())
            ((TileEntityFabrication)world.getTileEntity(x, y, z)).setInventoryName(itemStack.getDisplayName());
    }

    @Override
    public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) {
        if (!world.isRemote && world.getTileEntity(x, y, z) instanceof TileEntityFabrication)
            player.openGui(Fabrication.instance, 0, world, x, y, z);
        return true;
    }

}

Соотвественно блок не появляется совсем если сделать как делает автор.
Мне пришлось дописать регистрацию блока в его классе, и указать прочие мелочи типа чем ломается, звуки и пр. Только после этого блок заработал.

Дайте подсказки, почему так, может что то происходит с блоком и он регистрируется позже где либо, или фишка в том что используя public void preInit он автоматически регистрируется...?
Так же заметил что он так же использует public void init

Вот весь код мейна:
Java:
package timaxa007.fabrication.lesson0;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;

@Mod(modid = Fabrication.MODID, name = Fabrication.NAME, version = Fabrication.VERSION)
public final class Fabrication {

    public static final String
    MODID = "fabrication0",
    NAME = "Fabrication0",
    VERSION = "0.0";

    @Mod.Instance(MODID) public static Fabrication instance;

    public static Block block_fabrication;

    @Mod.EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        block_fabrication = new BlockFabrication();
        GameRegistry.registerBlock(block_fabrication, "block_fabrication0");
        GameRegistry.registerTileEntity(TileEntityFabrication.class, "TileEntityFabrication0");
    }

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

}

Надеюсь вы сможете объяснить почему у него все работает а у меня по его примеру даже блок в креативной вкладке не появился. Где он его регистрирует не пойму?
 
129
6
18
Если обратить внимание разница в:
public void preInit
public void preLoad

Есть ли разница между ними, что то влияющее не напимание мода или то как будет мод запускаться?
Разницы нет т.к. это всего лишь имя функции.(то-есть главное то что в скобках, если проще)
 
81
3
В контекте майна получается не важно что использую, ни на что не влияет?

Хорошо, но если будут пояснения разницы в целях образования, было бы то же хорошо.

А что насчет регистрации блока? У него нет регистрации я правильно понял, ничего не перепутал?
 

timaxa007

Модератор
5,831
409
672
81
3
В общем продолжаю разбирать твой код, по предыдущему все понятно. Предватильно написал конечно в личку, но продблирую вопрос здесь, с кодом.

В общем стал разбирать код Тайл энтити. Очень много мне не известно. В особенности замудренно идет работа с инпутом и экспортом, слотами и прочим. Понятно что там еще логика идет по забору вещи, выдаче. В общем я постарался прокомментировать код, все что примерно понял или около того. Буду признателен если меня поправят, объяснят. Хочу очень понимать логику. Со всякими if else и пр знаком.

Java:
package timaxa007.fabrication.lesson3c;

import java.util.ArrayList;

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;

public class TileEntityFabrication extends TileEntity implements ISidedInventory {//тут ты походу объявляешь о существовании инвенторя что ли или как такм...

    private final ItemStack[]//Я не знаю для чего нужен итем стак. Что бы игра понимала что можно положить стак а не один предмет?
            inventory_input = new ItemStack[9],//9 это номер слота или что то особое?Как я вижу это  прием предмета
            inventory_output = new ItemStack[9];// опять девятка, слот для выдачи. Сюда ничего положить по идее нельзя как это заведено в майне. Похо
    private static final int[]
            topSlots = new int[] {9, 10, 11, 12, 13, 14, 15, 16, 17},//топ слоты это слоты инвентаря игрока?
            sideSlots = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8};//Это слоты хотбара?
    private FabricationRecipes.Recipe recipe = null;//указываем отсуствие рецепта у блока? Вряд ли, однако что тогда говориться под рецептом?
    private String custom_name; //тут мы пишем имя чего? Окна, или которое видит игрок? Не очень пойму что за имя, чье оно
    public int time = 0, time_max = 0; //Что за переменные времени? Две штуки еще, походу где то ты будешь их применять. навыерное в скорости производства вещей
    private final ArrayList<ItemStack> temp = new ArrayList<ItemStack>();//Опять стаки, для чего это? Простая формальность или оно несет какую то пользу?

    public TileEntityFabrication() {} //Сам уже тайл энтити, но он пустой, видимо тут данная строка нужна как формальность и используется обычно в других задачах.

    @Override
    public void updateEntity() {//апдейт энтити, его проверка что ли или похожее
        if (worldObj.isRemote) return; //если... если что? при чем тут формат моделей obj? Уничтожен что ли?

        if (time == 0) {//та самая переменная , равна нулю... не Видимо ты где то будешь изменять переменную time, но в данном случае переменная уже нулевая и ты применяешь действия дальше
            if (recipe != null) {//Да что за условия с рецептом то, с пустым местом, тип если ничего нет ? Если нет, то где?

                if (!temp.isEmpty()) {//Эмпти, пустой. Где пустой?Темп - временное место хранения. Не думаю что я правильно логически понял для чего эта строка.
                    for (int i = 0; i < temp.size(); ++i) {//Простое выражение. Сначала объявил переменную i и сразу дал ей значение 0, После этого проверил i меньше  "темп" что выше, который я не понял что это? Если все верно, то присваиваешь +1 к i
                        if (addOutput(temp.get(i))) temp.remove(i);//Если ... вот тут ничего не понял addOutput и итд, не очень понял что происходит. Какая то очистка, видимо слоты чистим если забрать предмет что ли...
                    }
                    if (temp.isEmpty()) {//Если пустое слот что ли, или.. походу тем это то где мы храним предмет положив его в слот.
                        recipe = null;//рецепт пустота
                        time_max = 0;//а, откатываем работу нашего механизма в начало, присваивая i 0, что бы код что был выше работал заново и исправно.
                    }
                }

            } else {//Продолжается логика, прочту ниже что там дальше
                recipe = FabricationRecipes.getRecipe(inventory_input);//а, если рецепт, равен тому что лежит в выходном слоте, хотя я не видел регистрации  рецепта в целом, походу ты где то его хранишь в другом классе.

                if (recipe != null) {//не равно пустоте
                    time_max = time = recipe.time;//Приравниваем максимальное время(переменные) к времени, и говорим что это равно времени... Времени рецпта, что ?

                    if (recipe.output != null && recipe.output.length > 0) {// если выходной слот не равен пустоте и длинне? Количеству предметов что ли?
                        for (ItemStack output : recipe.output) {//А, тут я вижу что мы кладем рецепт, ну всмысле предмет и его количество в слот похоже, верно?
                            temp.add(output.copy());//Добавляем в темп , копию чего то не очень пойму
                        }
                    }

                    for (int i = 0; i < 9; ++i) {//Опять работа с переменными, добавляем +1 к i
                        if (this.recipe.input[i] == null) continue;//Если слот входной пустой
                        ItemStack int_input = inventory_input[i];//приравниваем количество предтов на входе и на инвентаря? А походу отдельно храняться данные о количестве что ли?
                        if (int_input != null) {//Если не равно нулю
                            if (int_input.getItem().hasContainerItem(int_input)) {
                                setInventorySlotContents(i, int_input.getItem().getContainerItem(int_input));//Ничего не понял что происходит со слотами
                            } else {
                                int_input.stackSize -= this.recipe.input[i].stackSize;
                                if (int_input.stackSize <= 0)
                                    setInventorySlotContents(i, null);
                                else
                                    setInventorySlotContents(i, int_input);
                            }
                        }
                    }

                }
            }
        } else {
            --time;//Для чего тут указанно переменная времени?
        }

    }

    private boolean addOutput(ItemStack itemStack) {//Туплю не понял ничего. Для чего тут булевая
        for (int i = 0; i < inventory_output.length; ++i) {//Походу идет опирация что выше но с выходом. Посути простая логика с условиями, но я не понимаю чем мы монипулируем. Сплошной текст о стак сайзе, инпуте и выходе.
            ItemStack output = inventory_output[i];
            if (output != null && output.isItemEqual(itemStack) && ItemStack.areItemStackTagsEqual(output, itemStack) && itemStack.stackSize + output.stackSize <= 64) {
                output.stackSize += itemStack.stackSize;
                setInventorySlotContents(i + 9, output);
                return true;
            } else if (output == null) {
                setInventorySlotContents(i + 9, itemStack);
                return true;
            }
        }
        return false;
    }

    @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 int getSizeInventory() {//размеры инвентаря?
        return inventory_input.length + inventory_output.length;
    }

    @Override
    public ItemStack getStackInSlot(int slotID) {
        if (slotID >= 0 && slotID < inventory_input.length)
            return inventory_input[slotID];
        else
            return inventory_output[slotID - inventory_input.length];
    }

    @Override
    public ItemStack decrStackSize(int slotID, int stackSize) {
        if (slotID >= 0 && slotID < inventory_input.length && inventory_input[slotID] != null) {
            ItemStack itemstack;

            if (inventory_input[slotID].stackSize <= stackSize) {
                itemstack = inventory_input[slotID];
                inventory_input[slotID] = null;
                return itemstack;
            } else {
                itemstack = inventory_input[slotID].splitStack(stackSize);

                if (inventory_input[slotID].stackSize == 0)
                    inventory_input[slotID] = null;

                return itemstack;
            }
        } else if (slotID >= inventory_input.length && inventory_output[slotID - inventory_input.length] != null) {
            ItemStack itemstack;

            if (inventory_output[slotID - inventory_input.length].stackSize <= stackSize) {
                itemstack = inventory_output[slotID - inventory_input.length];
                inventory_output[slotID - inventory_input.length] = null;
                return itemstack;
            } else {
                itemstack = inventory_output[slotID - inventory_input.length].splitStack(stackSize);

                if (inventory_output[slotID - inventory_input.length].stackSize == 0)
                    inventory_output[slotID - inventory_input.length] = null;

                return itemstack;
            }
        } else return null;
    }

    @Override
    public ItemStack getStackInSlotOnClosing(int slotID) {
        if (slotID >= 0 && slotID < inventory_input.length && inventory_input[slotID] != null) {
            ItemStack itemstack = inventory_input[slotID];
            inventory_input[slotID] = null;
            return itemstack;
        } else if (slotID >= inventory_input.length && inventory_output[slotID - inventory_input.length] != null) {
            ItemStack itemstack = inventory_output[slotID - inventory_input.length];
            inventory_output[slotID - inventory_input.length] = null;
            return itemstack;
        } else return null;
    }

    @Override
    public void setInventorySlotContents(int slotID, ItemStack itemStack) {
        if (slotID >= 0 && slotID < inventory_input.length)
            inventory_input[slotID] = itemStack;
        else
            inventory_output[slotID - inventory_input.length] = itemStack;
    }

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

    @Override
    public String getInventoryName() {
        return hasCustomInventoryName() ? custom_name : "inventory_fabrication";
    }

    @Override
    public boolean hasCustomInventoryName() {
        return custom_name != null && custom_name.length() > 0;
    }

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

    @Override
    public boolean isUseableByPlayer(EntityPlayer player) {
        return this.worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : player.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) {
        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;
    }

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

}
 
Сверху