====== Добавление блока ====== Добавление блоков в ваш мод следует аналогичному процессу, описанному в [[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|Предоставление блокам сущности, чтобы они могли иметь расширенное состояние, подобное инвентарю]]. Также необходим для многих вещей, таких как графический интерфейс и рендеринг пользовательских блоков.