2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Java]MinecraftのModを作成しよう 1.14.4【4. ツールの追加】

Last updated at Posted at 2020-08-04

(この記事は一連の解説記事の一つになります)

先頭記事:入門編
前の記事:3. クリエイティブタブの追加
次の記事:5. 防具の追加

ツールの追加

1. アイテムの追加では何の機能も持たない単純なアイテムを追加しました。今度は剣やピッケルといった役割を持ったツールを追加してみましょう。

\src\main\java\jp\koteko\example_mod\
   ├ items
   │   ├ ItemExampleAxe.java
   │   ├ ItemExampleHoe.java
   │   ├ ItemExamplePickaxe.java
   │   ├ ItemExampleShovel.java
   │   └ ItemExampleSword.java
   ├ lists
   │   └ ItemList.java
   ├ ExampleItemGroup.java
   └ ExampleMod.java

itemsフォルダを作り、各アイテムのクラスを作ります。
今の時点では継承元のクラスとほぼ変わらないため、新たにクラスを作る必要はほとんどないですが、あとで色々とカスタマイズすることを想定して別クラスとしました。

ItemExampleAxe.java
package jp.koteko.example_mod.items;

import net.minecraft.item.AxeItem;
import net.minecraft.item.ItemTier;

public class ItemExampleAxe extends AxeItem {
    public ItemExampleAxe(Properties properties) {
        super(ItemTier.IRON, 5, -3.0F, properties);
    }
}
ItemExampleHoe.java
package jp.koteko.example_mod.items;

import net.minecraft.item.HoeItem;
import net.minecraft.item.ItemTier;

public class ItemExampleHoe extends HoeItem {
    public ItemExampleHoe(Properties properties) {
        super(ItemTier.IRON, 0, properties);
    }
}
ItemExamplePickaxe.java
package jp.koteko.example_mod.items;

import net.minecraft.item.ItemTier;
import net.minecraft.item.PickaxeItem;

public class ItemExamplePickaxe extends PickaxeItem {
    public ItemExamplePickaxe(Properties properties) {
        super(ItemTier.IRON, 1, -2.8F, properties);
    }
}
ItemExampleShovel.java
package jp.koteko.example_mod.items;

import net.minecraft.item.ItemTier;
import net.minecraft.item.ShovelItem;

public class ItemExampleShovel extends ShovelItem {
    public ItemExampleShovel(Properties properties) {
        super(ItemTier.IRON, 1.5F, -3.0F, properties);
    }
}
ItemExampleSword.java
package jp.koteko.example_mod.items;

import net.minecraft.item.ItemTier;
import net.minecraft.item.SwordItem;

public class ItemExampleSword extends SwordItem {
    public ItemExampleSword(Properties properties) {
        super(ItemTier.IRON, 3, -2.4F, properties);
    }
}

継承元のコンストラクタに渡す引数は順に以下の通りです。Propertiesだけインスタンス化時に渡して、あとはここで決めてしまうようにしました。後述の「発展」の項も参照してください。

IItemTier tier : アイテムティア(いわゆるレア度・グレード的なもの)。
int attackDamageInあるいはfloat attackDamageIn : 攻撃力。なぜかツールによってint, floatが異なる。Hoeには存在しない。
float attackSpeedIn : 攻撃速度。
Properties builder : アイテムプロパティ。今までクリエイティブタブの設定に使ってきたやつ。


アイテムリストに追加して登録していきます。

ItemList.java
package jp.koteko.example_mod.lists;

import jp.koteko.example_mod.ExampleItemGroup;
import jp.koteko.example_mod.ExampleMod;
import jp.koteko.example_mod.items.*;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

@Mod.EventBusSubscriber(modid = ExampleMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ItemList {
    public static Item ExampleIngot = new Item(new Item.Properties().group(ExampleItemGroup.DEFAULT))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_ingot"));
    public static Item ExampleAxe = new ItemExampleAxe(new Item.Properties().group(ExampleItemGroup.DEFAULT))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_axe"));
    public static Item ExampleHoe = new ItemExampleHoe(new Item.Properties().group(ExampleItemGroup.DEFAULT))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_hoe"));
    public static Item ExamplePickaxe = new ItemExamplePickaxe(new Item.Properties().group(ExampleItemGroup.DEFAULT))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_pickaxe"));
    public static Item ExampleShovel = new ItemExampleShovel(new Item.Properties().group(ExampleItemGroup.DEFAULT))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_shovel"));
    public static Item ExampleSword = new ItemExampleSword(new Item.Properties().group(ExampleItemGroup.DEFAULT))
            .setRegistryName(new ResourceLocation(ExampleMod.MOD_ID, "example_sword"));

    @SubscribeEvent
    public static void registerItems(RegistryEvent.Register<Item> event) {
        event.getRegistry().registerAll(
                ExampleIngot,
                ExampleAxe,
                ExampleHoe,
                ExamplePickaxe,
                ExampleShovel,
                ExampleSword
        );
    }
}


続いて設定をしていきます。

\src\main\resources\assets\example_mod
   ├ blockstates
   ├ lang
   │  └ en_us.json
   │  └ ja_jp.json
   ├ models
   │  ├ block
   │  └ item
   │     ├ example_axe.json
   │     ├ example_hoe.json
   │     ├ example_pickaxe.json
   │     ├ example_shovel.json
   │     └ example_sword.json
   └ textures
      ├ blocks
      └ items
         ├ example_axe.png
         ├ example_hoe.png
         ├ example_pickaxe.png
         ├ example_shovel.png
         └ example_sword.png
en_us.json
{
  "item.example_mod.example_axe": "Example Axe",
  "item.example_mod.example_hoe": "Example Hoe",
  "item.example_mod.example_pickaxe": "Example Pickaxe",
  "item.example_mod.example_shovel": "Example Shovel",
  "item.example_mod.example_sword": "Example Sword"
}
ja_jp.json
{
  "item.example_mod.example_axe": "例の斧",
  "item.example_mod.example_hoe": "例の鍬",
  "item.example_mod.example_pickaxe": "例のピッケル",
  "item.example_mod.example_shovel": "例のスコップ",
  "item.example_mod.example_sword": "例の剣",
}

(なんかいわくつきの武器みたいな名前になってしまった…)

example_axe.json
{
  "parent": "item/handheld",
  "textures": {
    "layer0": "example_mod:items/example_axe"
  }
}
example_hoe.json
{
  "parent": "item/handheld",
  "textures": {
    "layer0": "example_mod:items/example_hoe"
  }
}
example_pickaxe.json
{
  "parent": "item/handheld",
  "textures": {
    "layer0": "example_mod:items/example_pickaxe"
  }
}
example_shovel.json
{
  "parent": "item/handheld",
  "textures": {
    "layer0": "example_mod:items/example_shovel"
  }
}
example_sword.json
{
  "parent": "item/handheld",
  "textures": {
    "layer0": "example_mod:items/example_sword"
  }
}

parentにはitem/handheldを指定することで手に持つタイプのアイテムとなります。

テクスチャも配置したらゲームを起動します。
キャプチャ.PNG
キャプチャ.PNG
(クリエイティブで撮ったので耐久が減ってません)

ツールの追加ができました!

発展

Q. なんか攻撃力と攻撃速度の設定が値と違うんだけど?
Q. なんで攻撃速度マイナスなの?
A. 攻撃力は、[IItemTierの値]+[各ツールでの値]+1、攻撃速度は4.0+[各ツールでの値]で求まるようです。
今回追加したツールクラスの継承元クラスの1つSwordItem.javaを見てみましょう。

SwordItem.java
//...
public class SwordItem extends TieredItem {
   private final float attackDamage;
   private final float attackSpeed;

   public SwordItem(IItemTier tier, int attackDamageIn, float attackSpeedIn, Item.Properties builder) {
      super(tier, builder);
      this.attackSpeed = attackSpeedIn;
      this.attackDamage = (float)attackDamageIn + tier.getAttackDamage();
   }
   //...
}

(float)attackDamageIn + tier.getAttackDamage()と計算しているのが分かります。
(なお実際GUI上での表示が+1されている理由がわかるコードは見つけられませんでしたが、バニラのアイテムもこのような式で求められる値に合致していました。表示上+1されているのか、内部計算的にも+1されているのかは不明です。)
(攻撃速度についても同様に、4.0のオフセットから計算している部分が見つけられていません。)

続いてItemTierを見てみましょう。

ItemTier.java
//...
public enum ItemTier implements IItemTier {
   WOOD(0, 59, 2.0F, 0.0F, 15, () -> {
      return Ingredient.fromTag(ItemTags.PLANKS);
   }),
   STONE(1, 131, 4.0F, 1.0F, 5, () -> {
      return Ingredient.fromItems(Blocks.COBBLESTONE);
   }),
   IRON(2, 250, 6.0F, 2.0F, 14, () -> {
      return Ingredient.fromItems(Items.IRON_INGOT);
   }),
   DIAMOND(3, 1561, 8.0F, 3.0F, 10, () -> {
      return Ingredient.fromItems(Items.DIAMOND);
   }),
   GOLD(0, 32, 12.0F, 0.0F, 22, () -> {
      return Ingredient.fromItems(Items.GOLD_INGOT);
   });
   //...
   private ItemTier(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 LazyLoadBase<>(repairMaterialIn);
   }
   //...
}

このようにTierごとに値が定まっています。

例えば、今回追加したExample Swordでは、ItemTier.IRONなので、
攻撃力
[IItemTierの値]+[各ツールでの値]+1 = 2 + 3 + 1 = 6
攻撃速度
4.0+[各ツールでの値] = 4.0 - 2.4 = 1.6
となります。


Q. 石とか鉄とかじゃなくて、ちゃんと固有の素材にしたい
Q. 耐久値の設定ってどこ?
A. 新しくItemTierを作りましょう。
上で触れたItemTierのEnumを新しく定義します。

\src\main\java\jp\koteko\example_mod\
   ├ items
   │   └ ExampleItemTier.java
   ├ lists
   ├ ExampleItemGroup.java
   └ ExampleMod.java
ExampleItemTier.java
package jp.koteko.example_mod.items;

import jp.koteko.example_mod.lists.ItemList;
import net.minecraft.item.IItemTier;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.LazyLoadBase;

import java.util.function.Supplier;

public enum ExampleItemTier implements IItemTier {
    EXAMPLE(4, 3122, 10.0F, 4.0F, 25, () -> {
        return Ingredient.fromItems(ItemList.ExampleIngot);
    });

    private final int harvestLevel;
    private final int maxUses;
    private final float efficiency;
    private final float attackDamage;
    private final int enchantability;
    private final LazyLoadBase<Ingredient> repairMaterial;

    private ExampleItemTier(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 LazyLoadBase<>(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();
    }
}

引数は順に、採取レベル、耐久値、効率、攻撃力、エンチャント効率、修理素材(のリスト的なもの)です。
ダイヤモンドのDIAMOND(3, 1561, 8.0F, 3.0F, 10, ...)より良い値にしてみました。

ツールクラスのTierを変更します。

ItemExampleSword.java
package jp.koteko.example_mod.items;

import net.minecraft.item.SwordItem;

public class ItemExampleSword extends SwordItem {
    public ItemExampleSword(Properties properties) {
        super(ExampleItemTier.EXAMPLE, 3, -2.4F, properties);
    }
}

キャプチャ.PNG
きちんと攻撃力、耐久値が伸びています。(F3でデバック表示をしてF3+Hで耐久値などが表示できます。)


Q. 雷や炎の出るぼくのかんがえたさいきょうのぶきがつくりたい!
A. 私もまだ難しくてわからないので一緒に勉強しましょう。(解説予定なし)

参考

Minecraft 1.14.4 Forge Modの作成 その6 【5種ツールの追加】

次の記事

5. 防具の追加

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?