- Версия(и) Minecraft
- 1.12-1.12.2
Гайд для тех, кто уже умеет кодить на 1.7.10 и хочет перейти на новую версию, для новичков есть учебник.
Вы можете создавать свои уникальные json модели с помощью редакторов моделей, например Blockbench(инфа+краткий учебник).
Но в этом уроке речь пойдёт о простых моделях.
Рассмотрим структуру json-файла модели:
Сначала рассмотрим как создать простую модель предмета, для примера приведу предмет из моего мода:
Родительская модель ванильная, поэтому я не указываю модид, как в случае с текстурой. Далее я указываю, что наследую от модели предмета
с названием generated. Соответственно если я написал бы block/какая-нибудь модель, то майнкрафт искал бы модель среди моделей блоков. Модели предметов можно наследовать от моделей блоков и наоборот.
Далее я указываю текстуру, текстура имеет индентификатор layer0, можно переопределить индентификатор написав
Заметьте, что расширения файлов никогда не указываются в json-файлах.
Теперь полезные модели из майнкрафта, от которых можно наследовать свою модель:
Для простого блока(без каких-либо вариаций) блокстейт выглядит так(взят случайный из ваниллы):
Json-файлы блокстейтов располагаются по пути assets\модид\blockstates\*регистрационное имя блока(об этом поговрим позже)*.json
Если у вас блок с одним состоянием, то в коде не нужно ничего писать дополнительно.
Сейчас мы рассмотрим реализацию 4 типов блоков в одном, на примере моего блока.
Первым делом вам нужно создать объект(ы) свойств(а) (Property):
В данном случае я как старовер(который любит мету) создаю свойство типа Integer, со значениями от 0 до 3(всего 4 значения) и названием type, это будет тип блока.
Виды пропертей и как их создавать:
Далее нам нужно переопределить метод
В моём случае:
Далее нам нужно переопределить методы:
Метод getStateFromMeta получает блокстейт из меты(мета сохраняется в мир), а второй метод делает наоборот, вы можете написать свой алгоритм(но обычно он очень простой), но имейте ввиду мета ограничена 16 значениями(от 0 до 15), в 1.13 ограничения не будет, т.к. будут сохраняться сразу блокстейты.
В моём случае методы переопределены так:
Как вы видите я использую методы withProperty и getValue.
Как ими пользоваться:
Вот и всё, теперь мы переходим к json-файлу для блокстейта.
Он у меня такой:
Блокстейт файлы берут модели из папки models/block, поэтому я её не указываю как в файле модели.
Код модели runic_stone0(все остальные такие-же, просто с другой текстурой):
Эти же файлы моделей я скопировал в папку item, для айтеблока, также модель айтемблока можно просто унаследовать от модели блока.
Такую-же модель я скопировал в папку item для айтем-блока
Вот и всё, мы сделали блок с 4 вариациями, вариации можно делать не только числами а например енумами, как в этом туториале.
Также енумами делаются повороты, например дерева(то можно посмотреть уже в сорцах майна)
Несколько функций, для блокстейтов которые можно переопределить:
Итак, для начала в преинициализации нам нужно вызвать две строчки:
В конструкторе блока нужно поставить ему имя регистрации(програмное название), это не тоже самое что и unlocalizedname.
У моего блока я установил так: this.setRegistryName("wizardrynt", "runic_stone");
Первая строка это модид, вторая название.
Если у вас свой айтемблок а не стандартный, то у него должно быть имя такое-же как и у блока.
Далее регистрация модели. Рекомендую делать это через эвент.
Вам нужно зарегистрировать эвенхандлер на стандартную шину форджа как и в 1.7.10, и отловить эвент ModelRegistryEvent event, после чего в нём вызвать такой метод для каждой вариации айтемблока:
Если вы этого не сделаете, то будет использоваться модель по пути assets/minecraft/models/item/*регистрационное_имя*.json
а этого вам не надо.
Регистрация блока ничем не отличается от регистрации айтемблока(только в этом случае не нужно регистрировать блок)
О ошибках и опечатках, а также о чём ещё можно написать пишите в обсуждение.
Существенные изменения
- Теперь даже стандартные блок и предмет(с обычной моделькой) должны иметь модель(об этом в главе 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-файлах.
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 это стандартный вариант
//в него можно поставить модель если у блока только одно состояние
}
}
Если у вас блок с одним состоянием, то в коде не нужно ничего писать дополнительно.
Сейчас мы рассмотрим реализацию 4 типов блоков в одном, на примере моего блока.
Первым делом вам нужно создать объект(ы) свойств(а) (Property):
Java:
public class BlockRunicStone extends Block implements NikitatBlock, INeedManyNames{
public static final PropertyInteger TYPE = PropertyInteger.create("type", 0, 3);
//код блока
}
Виды пропертей и как их создавать:
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)
В моём случае методы переопределены так:
Java:
public IBlockState getStateFromMeta(int meta)
{
return this.getDefaultState().withProperty(TYPE, meta);
}
public int getMetaFromState(IBlockState state)
{
return ((Integer)state.getValue(TYPE)).intValue();
}
Как ими пользоваться:
Java:
withProperty(Объект проперти, новое значение);
//Изменяет значение проперти, можно использовать только объекты проперти
//Которые вы указали в createBlockState()
getValue(Объект проперти);
//получает значение проперти
Java:
// также в конструкторе блока нужно указать значение по умолчанию
//Методом this.setDefaultState(блокстейт);
//Например
this.setDefaultState(this.blockState.getBaseState().withProperty(TYPE, 0);
//this.blockState.getBaseState() базовое значение.
//Можно также указать просто this.blockState.getBaseState()
Он у меня такой:
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" }
//как можно заметить я назначаю каждому типу свою модель
}
}
Код модели runic_stone0(все остальные такие-же, просто с другой текстурой):
JSON:
{
"parent": "block/cube_all",
"textures": {
"all": "wizardrynt:blocks/low_quality_runic_stone"
}
}
Такую-же модель я скопировал в папку 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()));
//Регистрация айтем блока
У моего блока я установил так: this.setRegistryName("wizardrynt", "runic_stone");
Первая строка это модид, вторая название.
Если у вас свой айтемблок а не стандартный, то у него должно быть имя такое-же как и у блока.
Далее регистрация модели. Рекомендую делать это через эвент.
Вам нужно зарегистрировать эвенхандлер на стандартную шину форджа как и в 1.7.10, и отловить эвент ModelRegistryEvent event, после чего в нём вызвать такой метод для каждой вариации айтемблока:
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(экземпляр айтемблока), мета, new ModelResourceLocation("модид:названиемодели(модель должна быть в папке item)", "inventory"));
Если вы этого не сделаете, то будет использоваться модель по пути assets/minecraft/models/item/*регистрационное_имя*.json
а этого вам не надо.
Регистрация блока ничем не отличается от регистрации айтемблока(только в этом случае не нужно регистрировать блок)