Добавление блоков в ваш мод следует аналогичному процессу, описанному в добавлении предметов. Вы можете создать экземпляр Block
или пользовательский класс, а затем зарегистрировать его в разделе Registry.BLOCK
. Вам также необходимо предоставить текстуру и файл модели/состояний блока для создания визуальных эффектов вашего блока. Для получения дополнительной информации о формате блочной модели просмотрите Страницу википедии 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() { } }
Ваш блок пока не будет доступен как предмет, но его можно увидеть в игре, используя команду /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() { } }
На этом этапе ваш новый блок появится в игре в виде фиолетово-черного шахматного рисунка. Это способ 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 произошли изменения для разбивания блоков. Теперь, чтобы определить инструменты сбора урожая и уровни сбора урожая, нам нужно использовать теги. Читайте о тегах здесь: Теги. Теги, к которым нам нужно добавить блок, следующие:
Инструмент для сбора урожая: src/main/resources/data/minecraft/tags/blocks/mineable/<tooltype>.json, где 'tooltype' может быть любым из: 'axe', 'pickaxe', 'shovel' или 'hoe' Уровень сбора урожая: src/main/resources/data/minecraft/tags/blocks/needs_<tier>_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() { } }
При использовании моделей блока, которые не полностью заполняют блок (например: Наковальня, Плита, Лестница), у соседних блоков пропадают стороны:
Чтобы исправить это, мы должны определить VoxelShape
нового блока:
@Override public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext context) { return VoxelShapes.cuboid(0f, 0f, 0f, 1f, 1.0f, 0.5f); }
Обратите внимание, что форма столкновения блока по умолчанию имеет форму контура, если она не указана.
Добавление простого состояния блока, например целых чисел и логических значений.
Предоставление блокам сущности, чтобы они могли иметь расширенное состояние, подобное инвентарю. Также необходим для многих вещей, таких как графический интерфейс и рендеринг пользовательских блоков.