====== Добавление блока ======
Добавление блоков в ваш мод следует аналогичному процессу, описанному в [[ru:tutorial:items|добавлении предметов]]. Вы можете создать экземпляр ''Block'' или пользовательский класс, а затем зарегистрировать его в разделе ''Registry.BLOCK''. Вам также необходимо предоставить текстуру и файл модели/состояний блока для создания визуальных эффектов вашего блока. Для получения дополнительной информации о формате блочной модели просмотрите [[https://minecraft.gamepedia.com/Model|Страницу википедии Minecraft о моделях (англ.)]].
===== Создание блока =====
Начните с создания экземпляра ''Block''. Он может храниться в любом месте, но мы начнем с верхней части вашего ''ModInitializer''. Для конструктора ''Block'' требуется экземпляр ''AbstractBlock.Settings'', который представляет собой конструктор для настройки свойств блока. Fabric предоставляет класс-конструктор ''FabricBlockSettings'' с большим количеством доступных опций.
public class ExampleMod implements ModInitializer {
/* Объявляем и инициализируем наш пользовательский экземпляр блока.
Мы устанавливаем для нашего материала значение `METAL`, для эффективного разрушения которого требуется кирка.
`strength` устанавливает как твердость, так и сопротивление блока на одно и то же значение.
Твердость определяет, сколько времени требуется блоку для разрушения, а сопротивление определяет, насколько прочен блок против повреждений от взрыва (например, взрывов).
Камень имеет твердость 1,5f и сопротивление 6,0f, в то время как обсидиан имеет твердость 50,0 f и сопротивление 1200,0 f.
Вы можете найти статистику всех блоков ванилы в классе `Blocks`, где вы также можете ссылаться на другие блоки.
*/
public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).strength(4.0f));
@Override
public void onInitialize() {
}
}
==== Регистрация вашего блока ====
Блоки должны быть зарегистрированы в реестре ''Registry.BLOCK''. Вызовите ''Registry.//register//'' и передайте соответствующие аргументы. Вы можете либо зарегистрировать блок в методе ''onInitialize'' либо непосредственно при создании экземпляра блока в статическом контексте, так как метод ''register'' также возвращает экземпляр блока.
public class ExampleMod implements ModInitializer {
public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).strength(4.0f));
@Override
public void onInitialize() {
Registry.register(Registry.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK);
}
}
Ваш блок пока //не// будет доступен как предмет, но его можно увидеть в игре, используя команду ''/setblock tutorial:example_block''.
==== Регистрация предмета для вашего блока ====
В большинстве случаев вы хотите иметь возможность разместить свой блок с помощью элемента. Для этого вам необходимо зарегистрировать соответствующий ''BlockItem'' в реестре элементов. Вы можете сделать это, зарегистрировав экземпляр ''BlockItem'' в разделе ''Registry.ITEM''. Имя предмета в реестре обычно должно совпадать с именем реестра блока.
public class ExampleMod implements ModInitializer {
public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).strength(4.0f));
@Override
public void onInitialize() {
Registry.register(Registry.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK);
Registry.register(Registry.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new FabricItemSettings().group(ItemGroup.MISC)));
}
}
===== Предоставление визуальных эффектов вашего блока =====
На этом этапе ваш новый блок появится в игре в виде фиолетово-черного шахматного рисунка. Это способ Minecraft показать вам, что что-то пошло не так при загрузке ресурсов блока (или визуальных элементов). Полный список проблем будет напечатан в ваших логах при запуске вашего клиента. Вам понадобятся эти файлы, чтобы придать вашему блоку визуальные эффекты:
* Файл состояния блока
* Файл модели блока
* Текстура
* Файл модели предмета (если с блоком связан предмет).
Файлы должны быть расположены здесь:
Состояние блока: src/main/resources/assets/tutorial/blockstates/example_block.json
Модель блока: src/main/resources/assets/tutorial/models/block/example_block.json
Модель предмета: src/main/resources/assets/tutorial/models/item/example_block.json
Текстура блока: src/main/resources/assets/tutorial/textures/block/example_block.png
Файл blockstate определяет, какую модель должен использовать блок, в зависимости от его состояния блока. У нашего блока нет никаких потенциальных состояний, поэтому мы пишем так: ''""''.
{
"variants": {
"": { "model": "tutorial:block/example_block" }
}
}
Файл модели блока определяет форму и текстуру вашего блока. Наша модель будет иметь ''block/cube_all''в качестве родительского элемента, который применяет текстуру ''all'' ко //всем// сторонам блока.
{
"parent": "block/cube_all",
"textures": {
"all": "tutorial:block/example_block"
}
}
В большинстве случаев вы захотите, чтобы блок выглядел одинаково в форме предмета. Вы можете создать модель предмета, которая имеет файл модели блока в качестве родительского элемента, что делает его похожим на блок:
{
"parent": "tutorial:block/example_block"
}
Загрузите Minecraft, и у вашего блока должны быть визуальные эффекты!
===== Настройка выпадения блока =====
Чтобы заставить ваш блок отбрасывать предметы при разрыве, вам понадобится //таблица выпадений//. Следующий файл приведет к тому, что ваш блок удалит соответствующую форму предмета при разрыве:
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "tutorial:example_block"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}
В minecraft 1.17 произошли изменения для разбивания блоков. Теперь, чтобы определить инструменты сбора урожая и уровни сбора урожая, нам нужно использовать теги. Читайте о тегах здесь: [[ru:tutorial:tags|Теги]]. Теги, к которым нам нужно добавить блок, следующие:
Инструмент для сбора урожая: src/main/resources/data/minecraft/tags/blocks/mineable/.json, где 'tooltype' может быть любым из: 'axe', 'pickaxe', 'shovel' или 'hoe'
Уровень сбора урожая: src/main/resources/data/minecraft/tags/blocks/needs__tool.json, где 'tier' может быть любым из: 'stone', 'iron' или 'diamond'
{
"replace": false,
"values": [
"example:example_block"
]
}
{
"replace": false,
"values": [
"example:example_block"
]
}
Чтобы теги уровня сбора урожая (needs_stone_tool, needs_iron_tool и needs_diamond_tool) вступили в силу, добавьте ''requiresTool()'' в ''FabricToolSettings'' в объявлении блока:
public static final Block EXAMPLE_BLOCK = new ExampleBlock(FabricBlockSettings.of(Material.METAL).strength(4.0f).requiresTool());
===== Создание пользовательского класса блоков =====
Описанный выше подход хорошо работает для простых блоков, но не подходит, когда вам нужен блок с //уникальной// механикой. Для этого мы создадим //отдельный// класс, который расширяет ''Block'' . Классу нужен конструктор, который принимает аргумент ''AbstractBlock.Settings'':
public class ExampleBlock extends Block {
public ExampleBlock(Settings settings) {
super(settings);
}
}
Вы можете переопределять методы в классе блока для пользовательских функций. Вот реализация метода ''onUse'', который вызывается, когда вы щелкаете правой кнопкой мыши по блоку. Мы проверяем, происходит ли взаимодействие на сервере, а затем отправляем игроку сообщение со словами: // "Hello, world!"//
public class ExampleBlock extends Block {
public ExampleBlock(Settings settings) {
super(settings);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!world.isClient) {
player.sendMessage(new LiteralText("Hello, world!"), false);
}
return ActionResult.SUCCESS;
}
}
Чтобы использовать свой пользовательский класс блоков, замените ''new Block'' на ''new ExampleBlock'':
public class ExampleMod implements ModInitializer {
public static final ExampleBlock EXAMPLE_BLOCK = new ExampleBlock(FabricBlockSettings.of(Material.STONE).hardness(4.0f));
@Override
public void onInitialize() {
Registry.register(Registry.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK);
Registry.register(Registry.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings().group(ItemGroup.MISC)));
}
}
==== VoxelShape ====
При использовании моделей блока, которые //не полностью// заполняют блок (например: Наковальня, Плита, Лестница), у соседних блоков пропадают стороны:
{{:tutorial:voxelshape_wrong.png?200|}}
Чтобы исправить это, мы должны определить ''VoxelShape'' нового блока:
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext context) {
return VoxelShapes.cuboid(0f, 0f, 0f, 1f, 1.0f, 0.5f);
}
Обратите внимание, что //форма столкновения// блока по умолчанию имеет форму контура, если она не указана.
{{:tutorial:voxelshape_fixed.png?200|}}
===== Следующие шаги =====
[[ru:tutorial:blockstate|Добавление простого состояния блока, например целых чисел и логических значений]].
[[ru:tutorial:blockentity|Предоставление блокам сущности, чтобы они могли иметь расширенное состояние, подобное инвентарю]]. Также необходим для многих вещей, таких как графический интерфейс и рендеринг пользовательских блоков.