見出し画像

Minecraft Mod開発日記② -アイテム実装-


前書き(読まなくていいよん)

前回のつづき。予定通りアイテム追加します。
先に今回の最終的なファイル構造を載せときます。

ファイル構造

src/
├── main/
│   ├── java/
│   │   └── com/
│   │       └── example/
│   │           └── kmod/
│   │               ├── kmod.java
│   │               └── item/
│   │                   └── kmoditems.java
│   └── resources/
│       └── assets/
│           └── kmod/
│               ├── lang/
│               │   ├── en_us.json
│               │   └── ja_jp.json
│               ├── models/
│               │   └── item/
│               │       └── test_item.json
│               └── textures/
│                   └── item/
│                       └── test_item.png

本編

アイテムの追加

Javaさんではレジストリにアイテムをぶち込んで管理するとのことです。

いや、レジストリってなに?

簡単に言うと箱らしい。pythonで言えば辞書に近いのかな?書いてる感覚は関数の切り出しに似てるかも。
まぁ、複数のデータをまとめておくとこです。
言わずもがなコードが見やすくなるよね。

アイテム増やしてくこと考えれば使ったほうが楽そう。
では、レジストリ作ってアイテム部分がこちら!

//レジストリの追加
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);

    // 新しいアイテムの登録
    public static final RegistryObject<Item> TEST_ITEM = ITEMS.register("test_item", 
    () -> new Item(new Item.Properties()
    ));

ノリでやってるので詳しい関数はよう分かりません。
C言語始めた時だってそんな感じだったしね。
公式さんのサンプルからコピペしながらなんとか完成。


アイテムだけ切り出したい

このまま"kmod.java"に直書きでもいいんです。
ただアイテムを複数追加すること考えると別のファイルに書いておきたい。
と言うことでサクッと移動させたものがこちらです。

ってやりたかったよ…私も…ははっ…
エラーの嵐だったので解決までの道程を見てってね。

問題箇所:1 インポート先のミス

src/main/java/com/example/kmod/item/kmoditems エラー:シンボルを見つけられません
import com.example.kmod;
                  ^
  シンボル:   クラス kmod
  場所: パッケージ com.example

原因分析

"src/main/java/com/example/kmod/kmod.java"という構造。
この書き方だと"kmod.java"ではなく"kmod"というフォルダをインポートしている。

修正後

import com.example.kmod.kmod;

問題箇所:2 インポート忘れ①

src/main/java/com/example/kmod/item/kmoditems エラー:シンボルを見つけられません
    public static void register(IEventBus eventBus);{
                                ^
  シンボル:   クラス IEventBus
  場所: クラス kmoditems

原因分析

インポートせずに"IEventBus"を使おうとしていた。

追加

import net.minecraftforge.eventbus.api.IEventBus;

問題箇所:3 スペルミス①

/Users/takumatamaki/code/mkmod/ModsWorkspace/Kmod-ver.1/src/main/java/com/example/kmod/item/kmoditems.java:5: エラー: パッケージnet.minecraftforge.eventBus.apiは存在しません
import net.minecraftforge.eventBus.api.IEventBus;
                                      ^

原因分析

スペルミス。"eventBus"->"eventbus"

修正後

import net.minecraftforge.eventbus.api.IEventBus;

問題箇所:4 スペルミス②

src/main/java/com/example/kmod/kmod エラー:シンボルを見つけられません
        kmoditemsitems.register(modEventBus);
        ^
  シンボル:   変数 kmoditemsitems
  場所: クラス kmod

原因分析

スペルミスの再来。"kmoditemsitems"->"kmoditems"

修正後

kmoditems.register(modEventBus);

問題箇所:5 インポート忘れ②

src/main/java/com/example/kmod/kmod エラー:シンボルを見つけられません
        kmoditems.register(modEventBus);
        ^
  シンボル:   変数 kmoditems
  場所: クラス kmod

原因分析

4番目と同じエラーに見えるが、"com.example.kmod.item.kmoditems"のインポートし忘れが原因。ファイルを作っただけで読み込んでくれるほどコンピュータは賢くないのだ…

追加

import com.example.kmod.item.kmoditems;

問題箇所:6 アドレスの修正漏れ①

src/main/java/com/example/kmod/kmod エラー:シンボルを見つけられません
            event.accept(TEST_ITEM); // クリエイティブタブにアイテムを追加
                         ^
  シンボル:   変数 TEST_ITEM
  場所: クラス kmod

原因分析

"kmod/kmod.java"にあるテスト用アイテムを"kmod/item/kmoditems"のレジストリに移動した際に変更すべき箇所の修正漏れ。簡単に言えば、引っ越したことを知らないまま佐藤さんに荷物を届けに行ったら家ごとなくなっていたみたいな感じ。転居先(kmoditems)も書いてあげましょう。

修正後

event.accept(kmoditems.TEST_ITEM); // クリエイティブタブにアイテムを追加

問題箇所:7 アドレスの修正漏れ②

src/main/java/com/example/kmod/item/kmoditems エラー:シンボルを見つけられません
    public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
                                                                                                      ^
  シンボル:   変数 MODID
  場所: クラス kmoditems

原因分析

6番目の逆。実家に送りたいなら実家の住所を書いてください。

修正後

public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, kmod.MODID);

問題箇所:8 抽象メソッド

src/main/java/com/example/kmod/item/kmoditems エラー:メソッド本体がないか、abstractとして宣言されています
    public static void register(IEventBus eventBus);{
                       ^

問題分析

ようやくJavaっぽいエラーに出会いました。
"public static void register(IEventBus eventBus)"の後ろに";"が来ると"抽象メソッド"というものになるらしい。

抽象メソッドですか。ふむふむ…?

抽象メソッドとは、「処理の中身を持たず、サブクラスで必ず実装されることを約束したメソッド」 です。(chatGPT)

どうやらそうらしいです。まぁ、エラーと関係あるのは処理の中身がないという部分でしょう。サブクラス云々は後々やろう、うん。
つまりは、";"がいらないらしい。

修正後

public static void register(IEventBus eventBus) { ITEMS.register(eventBus); }

アイテム名

langファイルの中に表示させたいアイテム名を書いた.jsonファイルを置くだけ。
簡単だね。

langファイルの位置

src/
├── main/
│   └── resources/
│       └── assets/
│           └── kmod/
│               ├── lang/
│               │   ├── en_us.json
│               │   └── ja_jp.json

en_us.json/ja_jp.jsonの中身

{
  "item.kmod.test_item": "My Item"
}

-----------------------------------------

{
  "item.kmod.test_item": "テスト用アイテム"
}

モデル

テクスチャを貼り付ける担当さん。

モデルの位置

src/
│   └── resources/
│       └── assets/
│           └── kmod/
│               ├── lang/
│               │   ├── en_us.json
│               │   └── ja_jp.json
│               ├── models/
│               │   └── item/
│               │       └── test_item.json

test_item.jsonの中身

{
    "parent": "item/generated",
    "textures": {
      "layer0": "kmod:item/test_item"
    }
 }

テクスチャ

画像ファイルを貼ればいいよん。
16x16だって情報があったんだけど、32x32じゃないと認識してくれなかったから要注意。

test_item.pngの場所

src/
│   └── resources/
│       └── assets/
│           └── kmod/
│               ├── lang/
│               │   ├── en_us.json
│               │   └── ja_jp.json
│               ├── models/
│               │   └── item/
│               │       └── test_item.json
│               └── textures/
│                   └── item/
│                       └── test_item.png

test_item.png


32x32

プロパティ

requiredFeatures

このプロパティを使うと、アイテムがクリエイティブモードの特定のタブに表示されます。

new Item(new Item.Properties().requiredFeatures(FeatureFlags.BASIC));

durability

最大耐久値が設定できる。0より大きい場合、そのアイテムはダメージを受けることが可能。

new Item(new Item.Properties().durability(250)); // 耐久値250のアイテム

stacksTo

アイテムの最大スタックサイズの設定。
耐久性があるアイテムには、設定できない。

new Item(new Item.Properties().stacksTo(64)); // 最大64個スタック可能

setNoRepair

アイテムが修理不可能になる。
修理可能アイテムでも、修理できなくなる。

new Item(new Item.Properties().durability(250).setNoRepair());

craftRemainder

クラフト後に返却されるアイテムを設定できる。
例) 溶岩バケツを使用した際に空のバケツを返却する仕組み

new Item(new Item.Properties().craftRemainder(Items.BUCKET));

後書き

エラー読むのめちゃくちゃ辛いけどエラーが消えた瞬間の快感えぐい。
次回はアイテムのプロパティについてやる予定。
スタック数とかね。

プロパティの追記(12/25)

いいなと思ったら応援しよう!