Версия(и) Minecraft
1.12-1.12.2
Гайд для тех, кто уже умеет кодить на 1.7.10 и хочет перейти на новую версию, для новичков есть учебник.

Существенные изменения
  • Теперь даже стандартные блок и предмет(с обычной моделькой) должны иметь модель(об этом в главе 2)
  • Модели блоков и предметов описываются в json файлах, также блоки теперь имеют блокстейты (об этом в главе 3)
  • Поскольку вид предмета и блока описывается в json файлах, то классы IIcon и IIconRegistry удалены
  • Взамен трём координатам x, y и z местоположение теперь описываеться в BlockPos'ах(Подробнее под списком)
  • IEEP больше нет, вместо них можно использовать Capability(Подробнее о Capability)
Функции BlockPos'ов:
Java:
BlockPos pos = new BlockPos(x, y, z);
pos.down(); //Получить позицию нижнего блока
pos.up(); //Получить позицию верхнего блока
pos.east(); //Получить позицию восточного блока
pos.west(); //Получить позицию западного блока
pos.south(); //Получить позицию южного блока
pos.north(); //Получить позицию северного блока
//Все выше перечисленные методы можно использовать также так:
//pos.up(какой по счёту блок с верху);
//Например:
pos.up(3); //третий блок сверху
//
pos.getX();
pos.getY();
pos.getZ();
//получить x/y/z из блокпоза
//
pos.add(x, y, z); //увеличить коорды по трём осям
//Например:
pos.add(3, -1, 0) //увеличить на 3 по оси x, уменьшить на один по оси y.
JSON модели
Все модели хранятся по пути assets/модид/models/. Модели предметов хранятся в models/item, а блоков в models/block.
Вы можете создавать свои уникальные json модели с помощью редакторов моделей, например
Blockbench(инфа+краткий учебник).
Но в этом уроке речь пойдёт о простых моделях.
Рассмотрим структуру json-файла модели:

JSON:
{
    "parent": "родительская модель например block/block, стандартная пустая модель",
    "elements": ["много текста"]
    /*элементы модели, в этом разделе храниться как
    выглядят модели, этот текст генерирует редактор моделей,
    вручную создавать его сложно*/
    "display": {"много текста"}
    /* здесь отображаеться как выглядит модель в разных местах
    в руке/в другой руке/в инвентаре
    эта информация вложена в самый базовые модели,
    если вы наследуете модель от какой-нибудь стандартной модели,
    то эа информация уже включена, также некоторые редакторы json-моделей
    позволяют менять эти параметры*/
    "textures": {"назначения текстур"}
    /* в этом разделе настраиваются текстуры,
    подробнее его мы рассмотрим ниже, на примерах*/
    }
}
Сначала рассмотрим как создать простую модель предмета, для примера приведу предмет из моего мода:
JSON:
{
  "parent": "item/generated",
//тут я указываю родительскую модель
  "textures": {
    "layer0": "wizardrynt:items/wand_of_mystical_energy0"
      //тут я указываю текстуру
  }
}
Родительская модель ванильная, поэтому я не указываю модид, как в случае с текстурой. Далее я указываю, что наследую от модели предмета
с названием generated. Соответственно если я написал бы block/какая-нибудь модель, то майнкрафт искал бы модель среди моделей блоков. Модели предметов можно наследовать от моделей блоков и наоборот.
Далее я указываю текстуру, текстура имеет индентификатор layer0, можно переопределить индентификатор написав "layer0": "#новыйиндентификатор" но это врятли вам пригодится, поскольку текстура теперь моя, то я указываю модид моего мода и двоеточие, затем я указываю что моя текстура лежит в подпапке items/ и её название. Майнкрафт будет брать текстуру из файла assets/модид/textures/items/wand_of_mystical_energy0.png.
Заметьте, что расширения файлов никогда не указываются в json-файлах.

2018-08-03_12.45.11.png
JSON:
//пример модели бревна
{
    "parent": "block/cube_column",
    "textures": {
        "end": "wizardrynt:blocks/mystical_oak_log_top",
        "side": "wizardrynt:blocks/mystical_oak_log"
    }
}
Теперь полезные модели из майнкрафта, от которых можно наследовать свою модель:
  • item/generated, простой предмет, индентификатор текстуры layer0
  • block/cube_all, простой блок с одинаковыми сторонами, индентификатор текстуры all
  • block/cube_column, столб, может использоваться для брёвен и колонн, текстура стороны side, текстура низа и верха end.
  • block/cross текстура перекрещенная сама с собой, используется в цветка, индентификатор текстуры cross.
Блокстейты
Блокстейты, это состояния блоков, используются для хранения информации о варианте блока и о его положении, например в какую сторону он повёрнут.
Для простого блока(без каких-либо вариаций) блокстейт выглядит так(взят случайный из ваниллы):

JSON:
{
    "variants": {
    //внутри объекта variants указываються варианты
        "normal": { "model": "orchid" }
        //вариант normal это стандартный вариант
        //в него можно поставить модель если у блока только одно состояние
    }
}
Json-файлы блокстейтов располагаются по пути assets\модид\blockstates\*регистрационное имя блока(об этом поговрим позже)*.json
Если у вас блок с одним состоянием, то в коде не нужно ничего писать дополнительно.
Сейчас мы рассмотрим реализацию 4 типов блоков в одном, на примере моего блока.
Первым делом вам нужно создать объект(ы) свойств(а) (Property):

Java:
public class BlockRunicStone extends Block implements NikitatBlock, INeedManyNames{

    public static final PropertyInteger TYPE = PropertyInteger.create("type", 0, 3);

//код блока

}
В данном случае я как старовер(который любит мету) создаю свойство типа Integer, со значениями от 0 до 3(всего 4 значения) и названием type, это будет тип блока.
Виды пропертей и как их создавать:

Java:
//PropertyInteger(число)
PropertyInteger.create("название", минимальное значение, максимальное значение);
//PropertyDirection(направление)
PropertyDirection.create("название", коллекция с допустимыми значениями EnumFacing);
//PropertyBool(истина/ложь)
PropertyBool.create("название");
//PropertyEnum(элемент перечесления)
PropertyEnum.<Енум>create("название", Енум.class);
PropertyEnum.<Енум>create("название", Енум.class, коллекция с допустимыми значениями Enum);
//Классы Property'ей находятся в пакете net.minecraft.block.properties.
Далее нам нужно переопределить метод protected BlockStateContainer createBlockState() у блока. В нем мы указываем какие свойства будут у блокстейта.
Java:
protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {здесь объекты проперти через запятую});
    }
В моём случае:
Java:
protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {TYPE});
    }
Далее нам нужно переопределить методы:
Java:
public IBlockState getStateFromMeta(int meta)
public int getMetaFromState(IBlockState state)
Метод getStateFromMeta получает блокстейт из меты(мета сохраняется в мир), а второй метод делает наоборот, вы можете написать свой алгоритм(но обычно он очень простой), но имейте ввиду мета ограничена 16 значениями(от 0 до 15), в 1.13 ограничения не будет, т.к. будут сохраняться сразу блокстейты.
В моём случае методы переопределены так:

Java:
    public IBlockState getStateFromMeta(int meta)
    {
        return this.getDefaultState().withProperty(TYPE, meta);
    }


    public int getMetaFromState(IBlockState state)
    {
        return ((Integer)state.getValue(TYPE)).intValue();
    }
Как вы видите я использую методы withProperty и getValue.
Как ими пользоваться:

Java:
withProperty(Объект проперти, новое значение);
//Изменяет значение проперти, можно использовать только объекты проперти
//Которые вы указали в createBlockState()
getValue(Объект проперти);
//получает значение проперти
Java:
// также в конструкторе блока нужно указать значение по умолчанию
//Методом this.setDefaultState(блокстейт);
//Например
this.setDefaultState(this.blockState.getBaseState().withProperty(TYPE, 0);
//this.blockState.getBaseState() базовое значение.
//Можно также указать просто this.blockState.getBaseState()
Вот и всё, теперь мы переходим к json-файлу для блокстейта.
Он у меня такой:

JSON:
{
  "variants": {
    "type=0": { "model": "wizardrynt:runic_stone0" },
    "type=1": { "model": "wizardrynt:runic_stone1" },
    "type=2": { "model": "wizardrynt:runic_stone2" },
    "type=3": { "model": "wizardrynt:runic_stone3" }
    //как можно заметить я назначаю каждому типу свою модель
  }
}
Блокстейт файлы берут модели из папки models/block, поэтому я её не указываю как в файле модели.
Код модели runic_stone0(все остальные такие-же, просто с другой текстурой):

JSON:
{
  "parent": "block/cube_all",
  "textures": {
    "all": "wizardrynt:blocks/low_quality_runic_stone"
  }
}
Эти же файлы моделей я скопировал в папку item, для айтеблока, также модель айтемблока можно просто унаследовать от модели блока.
Такую-же модель я скопировал в папку item для айтем-блока
Вот и всё, мы сделали блок с 4 вариациями, вариации можно делать не только числами а например енумами, как в
этом туториале.
Также енумами делаются повороты, например дерева(то можно посмотреть уже в сорцах майна)
Несколько функций, для блокстейтов которые можно переопределить:

Java:
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
//возвращает блокстейт который ставиться айтемблоком
//стандартно возвращает результат действия метода getStateFromeMeta,
//куда передаёт мету предмета
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
//возвращает актуальное состояние, тоесть например если блок должен меняться
//стандартно возвращает тот же блокстейт что и передали
Регистрация предметов и блоков
Регистрацию предметов и блоков рассмотри на примере предыдущего блока.
Итак, для начала в преинициализации нам нужно вызвать две строчки:

Java:
ForgeRegistries.BLOCKS.register(block);
//Регистраиця блока
ForgeRegistries.ITEMS.register(new ItemBlock(block).setRegistryName(block.getRegistryName()));
//Регистрация айтем блока
В конструкторе блока нужно поставить ему имя регистрации(програмное название), это не тоже самое что и unlocalizedname.
У моего блока я установил так: this.setRegistryName("wizardrynt", "runic_stone");
Первая строка это модид, вторая название.
Если у вас свой айтемблок а не стандартный, то у него должно быть имя такое-же как и у блока.
Далее регистрация модели. Рекомендую делать это через эвент.
Вам нужно зарегистрировать эвенхандлер на стандартную шину форджа как и в 1.7.10, и отловить эвент ModelRegistryEvent event, после чего в нём вызвать такой метод для каждой вариации айтемблока:
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(экземпляр айтемблока), мета, new ModelResourceLocation("модид:названиемодели(модель должна быть в папке item)", "inventory"));
Если вы этого не сделаете, то будет использоваться модель по пути assets/minecraft/models/item/*регистрационное_имя*.json
а этого вам не надо.
Регистрация блока ничем не отличается от регистрации айтемблока(только в этом случае не нужно регистрировать блок)

2018-08-04_11.08.10.png
О ошибках и опечатках, а также о чём ещё можно написать пишите в обсуждение.
  • Like
Реакции: Neftianik
Автор
Nikitat0
Просмотры
1,473
Первый выпуск
Обновление
Оценка
5.00 звёзд 3 оценок

Последние обновления

  1. Главы 3 и 4

    Я доделал главы 3 и 4.
  2. Добавлена Глава 2

    ...

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

Перфект! Ждем доделок
Давно хотел что-то подобное. Спасибо за ресурс, ибо json то ещё мучение) Ну а в целом, будет полезно всем.
Как юзверь 1.12, говорю, что годно!
Сверху