Учебное пособие - Как создать простую многоблочную структуру

Перевод Учебное пособие - Как создать простую многоблочную структуру

Нет прав для скачивания
Версия(и) Minecraft
1.6.x and 1.7.x
Источник
https://lomeli12.net/tutorials/tutorial-how-to-make-a-simple-multiblock-structure/
Учебное пособие - Как создать простую многоблочную структуру
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Minecraft Версия: Протестировано в 1.6.x и 1.7.x (используйте getTileEntity вместо getBlockTileEntity в 1.7.x)

Многоблочные структуры - хороший способ сделать улучшенные блоки без добавления множества рецептов, которые могут сделать рецепт создания этого блока дороже. Итак, как же создать собственную Многоблочную структуру? В этом учебном пособии вы узнаете, как создать базовую Многоблочную структуру 3x3x3 с полым центром с использованием системы "Master-Slave".

Это учебное пособие предполагает, что у вас есть базовые знания о том, как создать базовый мод, создать TileEntities и работать с данными NBT. Если вы этого не знаете, я рекомендую читать/смотреть учебные пособия Wuppy, они являются отличным источником информации, а также учебниками, которые я использовал, когда я впервые начал заниматься моддингом. ;)

Обратите внимание, что существует несколько способов создания многоблочных структур, и этот метод может быть не лучшим. Также обратите внимание, что способ, которым мы будем создавать многоблочную структуру, сделает его похожим на те, что есть в RailCraft, в котором все данные хранятся в нижнем центральном блоке структуры, поэтому имейте это в виду, если вы не хотите, чтобы ваша структура работала так.

Шаг 1: Создайте базовый TileEntity

Для того, чтобы начать работу, нам будет нужен в основной TileEntity, который я буду называть TileMultiBlock для этого учебного пособия. Я не буду рассказывать, для чего каждый метод, но просто обратите внимание, что это будет нашей отправной точкой.

Нам также понадобятся несколько переменных, два логических типа данных для tile, чтобы увидеть, есть ли у него master и/или если он является хозяином структуры и тремя целыми числами для координат master для ведомых устройств. Обязательно добавьте геттеры и сеттеры для каждого из них и сохраните их в Tile’s NBT данных.
Java:
package net.lomeli.tutorial;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;

public class TileMultiBlock extends TileEntity {
    private boolean hasMaster, isMaster;
    private int masterX, masterY, masterZ;

    @Override
    public void updateEntity() {
    }

    @Override
    public void writeToNBT(NBTTagCompound data) {
        super.writeToNBT(data);
        data.setInteger("masterX", masterX);
        data.setInteger("masterY", masterY);
        data.setInteger("masterZ", masterZ);
        data.setBoolean("hasMaster", hasMaster);
        data.setBoolean("isMaster", isMaster);
        if (hasMaster() && isMaster()) {
            // Любые другие значения должны СОХРАНЯТЬСЯ ТОЛЬКО ДЛЯ МАСТЕРА
        }
    }

    @Override
    public void readFromNBT(NBTTagCompound data) {
        super.readFromNBT(data);
        masterX = data.getInteger("masterX");
        masterY = data.getInteger("masterY");
        masterZ = data.getInteger("masterZ");
        hasMaster = data.getBoolean("hasMaster");
        isMaster = data.getBoolean("isMaster");
        if (hasMaster() && isMaster()) {
            // Любые другие значения должны быть ПРОЧИТАНЫ ТОЛЬКО МАСТЕРОМ
        }
    }

    public boolean hasMaster() {
        return hasMaster;
    }

    public boolean isMaster() {
        return isMaster;
    }

    public int getMasterX() {
        return masterX;
    }

    public int getMasterY() {
        return masterY;
    }

    public int getMasterZ() {
        return masterZ;
    }

    public void setHasMaster(boolean bool) {
        hasMaster = bool;
    }

    public void setIsMaster(boolean bool) {
        isMaster = bool;
    }

    public void setMasterCoords(int x, int y, int z) {
        masterX = x;
        masterY = y;
        masterZ = z;
    }
}

Шаг 2: Проверьте и сформируйте Многоблочную структуру

Следующим шагом является создание способа проверки правильности сформирования структуры. Самый простой способ - сделать три цикла for (для координат x, y и z) и проверить, есть ли TileEntity в каждой координате и считать ее, если это экземпляр TileMultiBlock. Затем подсчитываем их, чтобы увидеть, присутствует ли подходящее количество TileEntities и проверяем, свободен ли центр.
Java:
public boolean checkMultiBlockForm() {
    int i = 0;
    // Сканировать область 3x3x3, начиная с нижнего левого угла
    for (int x = xCoord - 1; x < xCoord + 2; x++)
        for (int y = yCoord; y < yCoord + 3; y++)
            for (int z = zCoord - 1; z < zCoord + 2; z++) {
                 TileEntity tile = worldObj.getBlockTileEntity(x, y, z);
                 // Удостоверьтесь, что tile не является нулевым, и является экземпляром одного и того же Tile и еще не является частью многоблочной структуры
                 if (tile != null && (tile instanceof TileMultiBlock)) {
                     if (this.isMaster()) {
                         if (((TileMultiBlock)tile).hasMaster())
                             i++;
                     } else if (!((TileMultiBlock)tile).hasMaster())
                         i++;
                 }
             }
     // Проверяем наличие 26 блоков ((3 * 3 * 3) - 1) и проверяем, что центральный блок пуст
     return i > 25 && worldObj.isAirBlock(xCoord, yCoord + 1, zCoord);
}
Нам также нужен способ рассказать всем тем tiles, что у них теперь есть master и где он находится. Вам также нужно будет сообщить нижнему центральному блоку, что это master. Этот метод будет использовать master только после того, как он обнаружит, что структура сформирована.
Java:
public void setupStructure() {
    for (int x = xCoord - 1; x < xCoord + 2; x++)
        for (int y = yCoord; y < yCoord + 3; y++)
            for (int z = zCoord - 1; z < zCoord + 2; z++) {
                TileEntity tile = worldObj.getBlockTileEntity(x, y, z);
                // Проверка: является ли блок, нижним центральным блоком
                boolean master = (x == xCoord && y == yCoord && z == zCoord);
                if (tile != null && (tile instanceof TileMultiBlock)) {
                    ((TileMultiBlock) tile).setMasterCoords(xCoord, yCoord, zCoord);
                    ((TileMultiBlock) tile).setHasMaster(true);
                    ((TileMultiBlock) tile).setIsMaster(master);
                }
            }
}

Шаг 3: Сброс блоков

Теперь нам нужны методы настройки, чтобы проверить, не является ли структура недействительной, и сбросить все части. Главный блок может повторно использовать метод checkMultiBlockForm для проверки структуры, но блоки из которой состоит структура также должны постоянно проверяться, что master все еще существует, если master сначала сломался, и для их сброса, если он больше не существует.
Java:
// Метод сброса, который должен запускаться, когда master ушел, или сообщает им
public void reset() {
    masterX = 0;
    masterY = 0;
    masterZ = 0;
    hasMaster = false;
    isMaster = false;
}

public boolean checkForMaster() {
    TileEntity tile = worldObj.getBlockTileEntity(masterX, masterY, masterZ);
    return (tile != null && (tile instanceof TileMultiBlock));
}
Нам также нужен метод, который master должен использовать, если checkMultiBlockForm возвращает false. Так как у нас уже есть метод сброса, мы можем просто сделать клон setupStructure, который сбрасывает вещи вместо этого.
Java:
public void resetStructure() {
    for (int x = xCoord - 1; x < xCoord + 2; x++)
        for (int y = yCoord; y < yCoord + 3; y++)
            for (int z = zCoord - 1; z < zCoord + 2; z++) {
                TileEntity tile = worldObj.getBlockTileEntity(x, y, z);
                if (tile != null && (tile instanceof TileMultiBlock))
                    ((TileMultiBlock) tile).reset();
            }
}

Шаг 4: Собираем все вместе

Теперь, когда у нас есть все части, которые нам нужны, все, что осталось, это его запустить. Нам в основном нужно, чтобы каждый блок постоянно проверял, сформирована ли структура до тех пор, пока она не будет сформирована. Как только это случиться, мы хотим, чтобы он проверял, когда происходит смена блока, в котором master проверяет, сформирована ли структура, и блоки структуры проверяют, существует ли master.

Во-первых, убедитесь, что наши tile проверяют структуру, и убедитесь, что работает только основной блок. Все это будет помещено в метод updateEntity.
Java:
@Override
public void updateEntity() {
    super.updateEntity();
    if (!worldObj.isRemote) {
        if (hasMaster()) {
            if (isMaster()) {
                // Вставьте вещи, которые вы хотите, чтобы мультиблок выполнил здесь!
            }
        } else {
            // Постоянно проверяйте, сформирована ли структура до ее появления.
            if (checkMultiBlockForm())
                setupStructure();
        }
    }
}
Теперь нужно запросить у главного блока структуры проверку, что структура всё ещё собрана, или у компонентов многоблока, что главный блок структуры всё ещё на месте, что мы делаем в классе блока в методе onNeighborBlockChange.
Java:
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {
    TileEntity tile = world.getTileEntity(x, y, z);
    if (tile != null && tile instanceof TileMultiBlock) {
        TileMultiBlock multiBlock = (TileMultiBlock) tile;
        if (multiBlock.hasMaster()) {
            if (multiBlock.isMaster()) {
                if (!multiBlock.checkMultiBlockForm())
                    multiBlock.resetStructure();
            } else {
                if (!multiBlock.checkForMaster())
                    multiBlock.reset();
            }
        }
    }
    super.onNeighborBlockChange(world, x, y, z, block);
}

Окончательный код

Java:
package net.lomeli.tutorial;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;

public class TileMultiBlock extends TileEntity {
    private boolean hasMaster, isMaster;
    private int masterX, masterY, masterZ;

    @Override
    public void updateEntity() {
        super.updateEntity();
        if (!worldObj.isRemote) {
            if (hasMaster()) {
                if (isMaster()) {
                    // Вставьте вещи, которые вы хотите, чтобы мультиблок выполнил здесь!
                }
            } else {
                // Постоянно проверяйте, сформирована ли структура до ее появления.
                if (checkMultiBlockForm())
                    setupStructure();
            }
        }
    }

    /** Убедитесь, что структура правильно сформирована*/
    public boolean checkMultiBlockForm() {
        int i = 0;
        // Сканировать область 3x3x3, начиная с нижнего левого угла
        for (int x = xCoord - 1; x < xCoord + 2; x++)
            for (int y = yCoord; y < yCoord + 3; y++)
                for (int z = zCoord - 1; z < zCoord + 2; z++) {
                    TileEntity tile = worldObj.getBlockTileEntity(x, y, z);
                    // Удостоверьтесь, что tile не является нулевым, и является экземпляром одного и того же Tile и еще не является частью многоблочной структуры
                    if (tile != null && (tile instanceof TileMultiBlock)) {
                        if (this.isMaster()) {
                            if (((TileMultiBlock)tile).hasMaster())
                                i++;
                        } else if (!((TileMultiBlock)tile).hasMaster())
                            i++;
                    }
            }
        // Проверить наличие 26 блоков ((3 * 3 * 3) - 1) и убедитесь, что центральный блок пуст
        return i > 25 && worldObj.isAirBlock(xCoord, yCoord + 1, zCoord);
    }

    /** Настройка всех блоков в структуре*/
    public void setupStructure() {
        for (int x = xCoord - 1; x < xCoord + 2; x++)
            for (int y = yCoord; y < yCoord + 3; y++)
                for (int z = zCoord - 1; z < zCoord + 2; z++) {
                    TileEntity tile = worldObj.getBlockTileEntity(x, y, z);
                    // Проверять: является ли блок, нижним центральным блоком
                    boolean master = (x == xCoord && y == yCoord && z == zCoord);
                    if (tile != null && (tile instanceof TileMultiBlock)) {
                        ((TileMultiBlock) tile).setMasterCoords(xCoord, yCoord, zCoord);
                        ((TileMultiBlock) tile).setHasMaster(true);
                        ((TileMultiBlock) tile).setIsMaster(master);
                    }
                }
    }

    /** Сбросить метод, который будет запускаться, когда master ушел или сообщает им */
    public void reset() {
        masterX = 0;
        masterY = 0;
        masterZ = 0;
        hasMaster = false;
        isMaster = false;
    }

    /** Убедитесь, что master существует */
    public boolean checkForMaster() {
        TileEntity tile = worldObj.getBlockTileEntity(masterX, masterY, masterZ);
        return (tile != null && (tile instanceof TileMultiBlock));
    }

    /** Сбросить все части структуры */
    public void resetStructure() {
        for (int x = xCoord - 1; x < xCoord + 2; x++)
            for (int y = yCoord; y < yCoord + 3; y++)
                for (int z = zCoord - 1; z < zCoord + 2; z++) {
                    TileEntity tile = worldObj.getBlockTileEntity(x, y, z);
                    if (tile != null && (tile instanceof TileMultiBlock))
                        ((TileMultiBlock) tile).reset();
                }
    }

    @Override
    public void writeToNBT(NBTTagCompound data) {
        super.writeToNBT(data);
        data.setInteger("masterX", masterX);
        data.setInteger("masterY", masterY);
        data.setInteger("masterZ", masterZ);
        data.setBoolean("hasMaster", hasMaster);
        data.setBoolean("isMaster", isMaster);
        if (hasMaster() && isMaster()) {
            // Любые другие значения должны СОХРАНЯТЬСЯ ТОЛЬКО ДЛЯ МАСТЕРА
        }
    }

    @Override
    public void readFromNBT(NBTTagCompound data) {
        super.readFromNBT(data);
        masterX = data.getInteger("masterX");
        masterY = data.getInteger("masterY");
        masterZ = data.getInteger("masterZ");
        hasMaster = data.getBoolean("hasMaster");
        isMaster = data.getBoolean("isMaster");
        if (hasMaster() && isMaster()) {
            // Любые другие значения должны быть ПРОЧИТАНЫ ТОЛЬКО МАСТЕРОМ
        }
    }

    public boolean hasMaster() {
        return hasMaster;
    }

    public boolean isMaster() {
        return isMaster;
    }

    public int getMasterX() {
        return masterX;
    }

    public int getMasterY() {
        return masterY;
    }

    public int getMasterZ() {
        return masterZ;
    }

    public void setHasMaster(boolean bool) {
        hasMaster = bool;
    }

    public void setIsMaster(boolean bool) {
        isMaster = bool;
    }

    public void setMasterCoords(int x, int y, int z) {
        masterX = x;
        masterY = y;
        masterZ = z;
    }
}
Java:
package net.lomeli.tutorial;

import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

public class BlockMultiBlock extends BlockContainer {
    public BlockMultiBlock(Material material) {
        super(material);
    }

    @Override
    public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {
        TileEntity tile = world.getBlockTileEntity(x, y, z);
        if (tile != null && tile instanceof TileMultiBlock) {
            TileMultiBlock multiBlock = (TileMultiBlock) tile;
            if (multiBlock.hasMaster()) {
                if (multiBlock.isMaster()) {
                    if (!multiBlock.checkMultiBlockForm())
                        multiBlock.resetStructure();
                } else {
                    if (!multiBlock.checkForMaster()) {
                        multiBlock.reset();
                        world.markBlockForUpdate(x, y, z);
                    }
                }
            }
        }
        super.onNeighborBlockChange(world, x, y, z, block);
    }

    @Override
    public TileEntity createNewTileEntity(World world, int meta) {
        return TileMultiBlock();
    }
}
И вот я подошёл к концу. Не слишком сложно, когда вы смотрите на него. Опять же, возможно, это не лучший способ сделать многоблочную структуру, но он работает. Помните, что master должен быть единственным, кто выполняет работу и сохраняет данные NBT, поэтому помните, что когда вы пишете свой код (я добавил комментарии для мест, где он должен быть помещен для элемента основного tile entity). Если я что-нибудь упустил или если вы не понимаете, оставьте комментарий или свяжитесь со мной.

Поскольку у некоторых людей возникли проблемы с пониманием этого без примера, я сделал примерный мод, основанный на этом учебнике. Вы можете посмотреть на него здесь: Lomeli12/MultiBlock-Tutorial
  • Like
Реакции: mousecray и IFernando
Автор
Garik
Скачивания
4
Просмотры
2,587
Первый выпуск
Обновление
Оценка
4.33 звёзд 3 оценок

Другие ресурсы пользователя Garik

Последние рецензии

Перевёл хорошо, хотелось бы на 1.15
Перевёл, вроде, неплохо, так что грац, на русском всё же чуть проще читать, но сам по себе гайд очень неполный. Допустим, нет рендера модельки; поворота структуры на угол/отражения; нет перенаправления взаимодействия на "мастер" ну и ещё мелкие неточности, которые устраняются в процессе копирования и исправления.
Garik
Garik
Спасибо за рецензию!
Перевод хорошо, эх, вот бы на 1.12 гайдом...
Garik
Garik
Спасибо за рецензию!
Сверху