Привет! Сегодня добавим целый ряд предметов, а именно топоры, кирки, лопаты и т.д. А также пару новых материалов для инструментов и бонусом их рецепты.
Для полного понимания происходящего настоятельно рекомендую глянуть создание обычного предмета, т.к. в этом гайде регистрация предметов, как и некоторые иные базовые вещи затронуты не будут. Вкладки смотрите там же.
Поехали!
Немножечко об инструментах
В чём отличие инструментов от обычных предметов? Сейчас мы исключаем их особенности, вроде вспахивания земли или создания тропинок, а говорим об общем для всех. Они более эффективны на определённых блоках (даже мотыга, с 1.16). Поэтому у нас есть класс ToolItem, где и происходит указание новой скорости разрушения для подходящих инструменту блоков, двойной урон по состоянию инструмента при использовании его как оружия и т.д. Сами же блоки, как и особенные взаимодействия конкретных инструментов прописаны в дочерних классах от ToolItem. Для лопаты это ShovelItem, для топора – AxeItem, для кирки – PickaxeItem, мотыга – HoeItem. Кстати, меча тут нет, он ведь не инструмент. Но его мы сегодня тоже добавим. Дело в том, что для SwordItem родительским классом является TieredItem, он же родитель для ToolItem. По сути, эти предметы требуют для создания не только Item.Properties(), а и «тир» предмета, урон и скорость атаки. Что за тир предмета вы должны понимать, это алмазный, железный и т.д.
Так что для новых инструментов мы в первую очередь создадим новый «тир», даже два. А потом просто несколько объектов соответствующих классов.
JAVA-часть
В первую очередь нужно добавить пару простых предметов, которые будут из себя представлять материалы для новых инструментов.
1 2 |
public static final RegistryObject<Item> STEEL_INGOT = ITEMS.register("steel_ingot", () -> new Item(new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> MOON_INGOT = ITEMS.register("moon_ingot", () -> new Item(new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); |
Хорошо. В папку item добавляем ModItemTier.class, он буквально копирует существующий ItemTier.class из игры (смотрите папку item), но вместо существующих элементов мы пишем эти. Никаких иных регистраций или вроде того сейчас делать не нужно. Для нормальной работы важно, чтобы эти статические свойства наследовали класс IItemTier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
package mod.astler.tutorial_mod_gs.item; import net.minecraft.item.IItemTier; import net.minecraft.item.crafting.Ingredient; import net.minecraft.tags.ItemTags; import net.minecraft.util.LazyValue; import java.util.function.Supplier; public enum ModItemTier implements IItemTier { STEEL(2, 350, 6.5F, 2.3F, 12, () -> { return Ingredient.fromItems(ModItems.STEEL_INGOT.get()); }), MOON_STONE(3, 1061, 8.0F, 3.0F, 18, () -> { return Ingredient.fromItems(ModItems.MOON_INGOT.get()); }); private final int harvestLevel; private final int maxUses; private final float efficiency; private final float attackDamage; private final int enchantability; private final LazyValue<Ingredient> repairMaterial; ModItemTier(int harvestLevelIn, int maxUsesIn, float efficiencyIn, float attackDamageIn, int enchantabilityIn, Supplier<Ingredient> repairMaterialIn) { this.harvestLevel = harvestLevelIn; this.maxUses = maxUsesIn; this.efficiency = efficiencyIn; this.attackDamage = attackDamageIn; this.enchantability = enchantabilityIn; this.repairMaterial = new LazyValue<>(repairMaterialIn); } public int getMaxUses() { return this.maxUses; } public float getEfficiency() { return this.efficiency; } public float getAttackDamage() { return this.attackDamage; } public int getHarvestLevel() { return this.harvestLevel; } public int getEnchantability() { return this.enchantability; } public Ingredient getRepairMaterial() { return this.repairMaterial.getValue(); } } |
Фактически это enum тип с набором параметров, которые будут определять эффективность, прочность и т.д.
Если по порядку в конструкторе, то первое – уровень материала. В зависимости от этого значения новая кирка сможет или нет добывать обсидиант или незерит. Второе – максимальное количество использований. Далее эффективность, влияет на скорость добычи. Четвёртое – урон от атаки, а пятое – зачаровываемость. Последнее это материал, при помощи которого можно будет починить инструменты с этим материалом.
А теперь добавляем и сами инструменты:
1 2 3 4 5 6 7 8 9 10 11 |
public static final RegistryObject<Item> STEEL_AXE = ITEMS.register("steel_axe", () -> new AxeItem(ModItemTier.STEEL, 6.0F, -3.1F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> STEEL_SHOVEL = ITEMS.register("steel_shovel", () -> new ShovelItem(ModItemTier.STEEL, 1.5F, -3.0F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> STEEL_SWORD = ITEMS.register("steel_sword", () -> new SwordItem(ModItemTier.STEEL, 3, -2.4F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> STEEL_PICKAXE = ITEMS.register("steel_pickaxe", () -> new PickaxeItem(ModItemTier.STEEL, 1, -2.8F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> STEEL_HOE = ITEMS.register("steel_hoe", () -> new HoeItem(ModItemTier.STEEL, -2, -1F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> MOON_AXE = ITEMS.register("moon_axe", () -> new AxeItem(ModItemTier.MOON_STONE, 6.0F, -3.1F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> MOON_SHOVEL = ITEMS.register("moon_shovel", () -> new ShovelItem(ModItemTier.MOON_STONE, 1.5F, -3.0F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> MOON_SWORD = ITEMS.register("moon_sword", () -> new SwordItem(ModItemTier.MOON_STONE, 3, -2.4F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> MOON_PICKAXE = ITEMS.register("moon_pickaxe", () -> new PickaxeItem(ModItemTier.MOON_STONE, 1, -2.8F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); public static final RegistryObject<Item> MOON_HOE = ITEMS.register("moon_hoe", () -> new HoeItem(ModItemTier.MOON_STONE, -2, -1F, new Item.Properties().group(ModItemGroups.MOD_ITEMS_ITEM_GROUP))); |
На этом с кодом всё. Теперь нужно добавить локализацию, текстуры и модели, всё, как и с каменной палкой из прошлого гайда.
Правда родителем модели нужно указать minecraft:item/handheld:
1 2 3 4 5 6 |
{ "parent": "minecraft:item/handheld", "textures": { "layer0": "tutorial_mod_gs:item/moon_axe" } } |
Если вы оставите модель как для обычного предмета, то выглядеть они будут не особо:
Рецепты
Бонусом я обещал наконец-то рассказать о рецептах. А то мы добавили уже предмет, еду, но получить их в выживании всё ещё нельзя. В этот раз рассмотрим только верстак, и то, только рецепты с фиксированным положением ингредиентов.
Для начала нужно создать папку ресурсов для рецептов. В отличие от текстур и моделей – рецепты находятся по такому пути: src\ main\ resources\ data\ tutorial_mod_gs\ recipes. И вот в последнюю и нужно собирать ваши рецепты.
Имена рецептов не принципиальны, но должны соответствовать общем правилам, вроде никаких специальных символов, пробелов и т.д. Для примера вот вам рецепт топора:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "type": "minecraft:crafting_shaped", "pattern": [ "XX", "X#", " #" ], "key": { "#": { "item": "minecraft:stick" }, "X": { "item": "tutorial_mod_gs:moon_ingot" } }, "result": { "item": "tutorial_mod_gs:moon_axe" } } |
Тип определяет рабочий стол. Это может быть рецепт для верстака, печи, камнереза и т.д. Рецепты для верстака могут иметь чёткую форму, а могут свободную. Топор – имеет чёткую, а соединения различных красителей – свободную, это значит, что они могут находиться в любой ячейке крафта без потери результата.
Далее в рецепте следует «шаблон». Он есть только у форменных рецептов крафта.
После можно увидеть расшифровку символов шаблона, где символам присваиваются предметы. Если символу не присвоить никаких предметов, то в рецепте ячейка будет пустой.
В конце файла видим результат, новый топор.
Прошу обратить внимание, что для использования предметов из игры нужно писать перед именем предмета minecraft:, а для доступа к нашим предметам: tutorial_mod_gs:.
Остальные рецепты выглядят абсолютно так же, разница только в шаблоне и результате. Кирка тому пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "type": "minecraft:crafting_shaped", "pattern": [ "XXX", " # ", " # " ], "key": { "#": { "item": "minecraft:stick" }, "X": { "item": "tutorial_mod_gs:moon_ingot" } }, "result": { "item": "tutorial_mod_gs:moon_pickaxe" } } |
Запускаем!
Пингбэк: Создание модов для Minecraft 1.15 – GeekStand