Holograph1c Attract0r

日々の数学やプログラミングに関係する話。

Minecraftで学ぶJavaプログラミング入門 #2: アイテムの追加

MinecraftのMod開発講座、第2回です。

 

mikan-alpha.hatenablog.com

 

前回は、開発を始まるまでの下準備を行いました。
今回から実際にゲームに触れてみましょう。

 

1. プロジェクトのインポート

Eclipseを起動します。

ロードの途中で、ワークスペースを選択するウィンドウが出ますので、適当なディレクトリをワークスペースにしておきます。
私はMod開発用に新規でディレクトリを作成してそれを選択しました。

ロードが完了したら、エディターが開きます。

f:id:mikan_alpha:20201113224738p:plain

初期状態

ここで、前回用意したプロジェクトを開きます。

メニューのファイルから、インポートを選択します。
ここで、「既存のGradleプロジェクト」を選びます。

f:id:mikan_alpha:20201113225130p:plain

検索すると、はやい!

次の画面で、前回用意したForgeのディレクトリを指定します。

f:id:mikan_alpha:20201113225440p:plain

あとは、完了を押して待ちます。

インポートが完了したあと、こんな感じで色々ずらっと増えていたらOKです。

f:id:mikan_alpha:20201113230254p:plain

読み込み後

試しに、src/main/javaの中の、com.example.examplemodパッケージに入っているEampleMod.javaを開いてみます。

f:id:mikan_alpha:20201113230918p:plain

Javaの世界へようこそ

こんな風に中身が問題なく表示できれば良いです。

ここから、開発を始めていきましょう。

2. Javaの基礎の話

一応Javaに触れたことない人にも読んでもらうことを目指しているので、今回出てくる要素の解説をざっくりと。

プログラムの書き方

Javaにおいては、セミコロン(;)で処理のまとまりを区切ってプログラムを書いていきます。基本的には、行の先頭からその行のセミコロンまでを処理のひとまとまり(最小単位)だと思っておけば問題ないでしょう。
このセミコロンの前に記述してある内容が、コンピューターへの命令となるわけです。

この処理がいくつか集まって、{}で囲まれたブロックのことを、Javaではメソッド(関数)と呼びます。細胞の集合が組織みたいなものです。
関数と書いたとおり、数学の経験がある人は数学の関数と同じと思ってもらって構いません。
何か入力を受け取って、中でなんらかの処理をして、そして値を返します*1

上で見たソースコードには、たくさん関数が記述されています。

f:id:mikan_alpha:20201114102100p:plain

先頭に修飾子、返り値の型(void)、メソッド名、引数の情報があり、{}で囲まれている範囲がこのメソッドの処理内容です。修飾子については詳しくは触れませんが、どこからこのメソッドにアクセスができるか、などのような情報を表すタグのようなものです。

さらにこのメソッドがいくつか集まってできるのが、クラスです。
Javaでプログラミングをしていく際の基本単位です。

先程のソースコードでは一番外側にこのように書かれています。

f:id:mikan_alpha:20201114102836p:plain

メソッドと同様に、修飾子が付いていてその後にclass、そしてクラス名となっていて、{}で囲んだブロックがこのクラスになります。

変数(メンバ変数、ローカル変数)

プログラミングに欠かせない要素の1つが、変数です。

これも、数学の変数と同じものと思ってもらっていいでしょう。

ただ一つ違う点があるとすれば、変数の中身が「数字」とは限らない、という点です。

例えば、「hello」という文字列を変数に代入することもできるし、何かオリジナルのオブジェクトを代入することもできます。このあたりは、この後すぐ出会うことになります。

 

こんな風に変数に色んなものを入れておけるので、中に何が入ってるのかコンピューターに教えるために、変数には「型」という概念があります。

変数を宣言したいときには、「型名 変数名;」というように記述します。

例えば、「int x;」と書くと(32bit)整数型の変数が一つ確保されます。
上の例で出した文字列の変数を宣言したければ、「String str;」というように。
変数名は、1文字でなくても良いです。というより、むしろプログラミングにおいては分かりやすい名前にしておくべきでしょう*2

 

上で見たソースコードにおいては、例えばこれが変数です。

f:id:mikan_alpha:20201114000731p:plain

変数の例

先頭の紫文字は今は無視して、型名と変数名を見ましょう。
この変数の型は「Logger」で、変数名は「LOGGER」ということになります。

またこの例のように、宣言と同時に変数に何か代入しておくこともできます。
Javaにおいては、「=」は(右辺を左辺に)代入の意味になりますので、プログラミングを始めたばかりの人は注意すべきポイントです。

 

また、変数には2種類あって、メンバ変数ローカル変数というものがあります。

この先で出てくる内容を含みますが、一応説明をしておくと、メンバ変数はクラス内かつメソッド外で宣言される変数、ローカル変数はメソッド内で宣言される変数という定義です。メンバ変数は、クラス内のメソッドだけでなくクラス外からも参照できたりしますが、ローカル変数は宣言されたそのメソッド内からのみ参照できる変数となります。(変数のスコープ)

3. Modをゲームに認識させる

先程開いたExampleMod.javaをそのまま書き換えていっても良いのですが、一応パッケージだけ作り直しておきます。

f:id:mikan_alpha:20201114104253p:plain

Javaの一般的な命名規則に従いました

ここで、これから作るModのIDを決めます。ユニークな文字列である必要があります。他のModと被らないものにしましょう。

決めたら、IDと同じ名前のパッケージを作ってそこにExampleMod.javaをコピーしておきます。

f:id:mikan_alpha:20201114105109p:plain

IDは「tutmod」にしました

リネームもしておきました。元々あったパッケージは削除して構いません。

さて、このプログラムをゲームに認識させるために、少しだけやることがあります。

f:id:mikan_alpha:20201114105455p:plain

まずこのクラスに付いているアノテーションの値を、先程自分で決めたIDに書き換えます。

 

次に、mods.tomlを開きます。

f:id:mikan_alpha:20201114105621p:plain

開いたら、modId=のところの値も自分のIDに書き換えます。

f:id:mikan_alpha:20201114105757p:plain

必要に応じて、他のところも書き換えておきましょう。
ここではdisplayName(表示名)だけ変えておきました。

他にもModのロゴ画像を表示できたり、公式サイトを載せたりできるので、確認してみてください。

 

最後に、メニューの「プロジェクト」からプロパティを開きます。

実行/デバッグ設定を開くと、以下のように予め3種類の起動構成が用意されているはずです。

f:id:mikan_alpha:20201114110038p:plain

ここで、「runClient」と「runServer」とそれぞれ編集します。

「環境」タブを開いて、MOD_CLASSESの「examplemod」と書いてある部分を自分のIDに置換してください。

f:id:mikan_alpha:20201114110330p:plain

終わったら、適用を押して閉じます。

 

準備が終わったので、この状態でデバッグをしてみましょう!

今編集した「runClient」を実行してみます。

f:id:mikan_alpha:20201114110652p:plain

 

こんな感じにMinecraftが起動できれば問題なしです。

f:id:mikan_alpha:20201114111044p:plain

 

Modsを開いて、今開発しているModが読み込まれていることを確認します。

lorem ipsumが読めます。

f:id:mikan_alpha:20201114111240p:plain

 

4. 無機能アイテムを追加する

Modを開発する準備も完璧に整いました。
ここから実際にアイテムを作ってみましょう。

 

アイテム本体

まずはアイテム本体のクラスを準備します。
管理のためにitemというパッケージを新しく作成して、そこにアイテムのクラスを入れていくことにします。

f:id:mikan_alpha:20201114133945p:plain

クラス名はMinecraft本体の命名規則に従っています

クラスを新規作成すると、最低限の記述のみのソースが自動で生成されます。

ここで、Minecraft本体のItem(net.minecraft.item.Item)クラスを継承します。

f:id:mikan_alpha:20201114134418p:plain

Eclipseの機能でコンストラクタも簡単に生成してくれます

こうするだけで、Minecraftのアイテムの最小限の機能だけを持ったアイテムが作れます!

右クリックしたときの処理を追加するとか、そういった独自の機能を持たせたい場合にはこのクラスでItemクラスのメソッドをオーバーライドしていきます。

 

アイテムの基本の設定だけしましょう。

コンストラクタにあるProperties(Item.Properties)の設定をします。これは名前の通りで、アイテムが最大で何個スタックできるか、耐久値はいくつか、どのクリエイティブタブに属するか、のような情報を持つクラスです。

今は飛ばしてしまうので、インスタンスだけスーパークラスに投げておきます。

f:id:mikan_alpha:20201114140436p:plain

次の行で、このアイテムのシステム内名称を設定しています。これは必ず設定しなければなりません。setRegistryNameの第1引数はMODのId、第2引数にアイテムの名前を渡します。

f:id:mikan_alpha:20201114140714p:plain

メインクラスでMODのIdを管理するようにしました

これで、アイテム自体は完成です。

 

アイテム登録用クラス

次にこのアイテムをゲームに登録します。
ModItemsというクラスを作って、そこでアイテムのインスタンス管理をすることにします。

f:id:mikan_alpha:20201114140937p:plain

こんな感じにアイテムを入れる変数とメソッドを定義してあげて、ゲームの初期化時にこのinit()を呼んであげればよいです。

f:id:mikan_alpha:20201114142202p:plain

publicにするのを忘れずに

外からアクセスするものなので、publicにします。

ゲーム初期化時にアイテムを登録する

Modのメインクラスに戻ります。下の方にいくと、RegistryEventsというクラスがあると思います。

ここにブロック登録用のメソッドが予め書かれているので、これを真似してアイテム用のメソッドを作ります。

f:id:mikan_alpha:20201114142601p:plain

ここでアイテムやブロックを登録します

onItemsRegistryの中で、ModItems.init()を呼び出して、そしてアイテムを登録します。

f:id:mikan_alpha:20201114143455p:plain

初期化を忘れるとぬるぽになる

これでゲームにアイテムが追加できたので、Minecraftを起動してみます。

giveコマンドでアイテムを召喚するとこんな風になると思います。

f:id:mikan_alpha:20201114143744p:plain

視界の1/4が謎の物体で埋まります。

ここから、テクスチャやアイテム名のローカライズの設定をしましょう。

5. アイテム名などを設定する

アイテム名などの設定は、あまりプログラムを使わずにできます。

src/main/javaではなくて、src/main/resourcesの方を開いて、以下のようにパッケージを作ります。
リソースパックなどに触れたことがある人は馴染みがあると思いますが、assetsの後ろがminecraftではなくてModのIdになるので気をつけましょう。

f:id:mikan_alpha:20201114144238p:plain

リソースパックと同じ

アイテム名を設定する

アイテム名のローカライズは、JSONを利用します。

以下のように、例として英語用の言語ファイルを作ってみます。

f:id:mikan_alpha:20201114144819p:plain

日本語ならja_jp.json

記法はJSONそのままです。左側にローカライズ前の文字列、右側にローカライズ後の文字列を書けばあとは勝手にゲーム側で書き換えてくれます。

f:id:mikan_alpha:20201114145028p:plain

アイテム名以外のローカライズにも使います。書き方は全部同じです。

このようにちゃんとローカライズされていたらOKです。

f:id:mikan_alpha:20201114145428p:plain

テクスチャを設定する

テクスチャの設定もJSONです。models.itemの中にアイテムのRegistryNameと同じ名前のファイルを置いておくだけで勝手に読み込んでくれます。

f:id:mikan_alpha:20201114150239p:plain

コピペ

ファイルの中身はバニラのリンゴからコピペしました。

自作のテクスチャにしたい場合には、layer0の値を書き換えます。

f:id:mikan_alpha:20201114150617p:plain

できた

6. 次回予告

今回はアイテムをやったので、次回はブロックの追加をします。

実は、結構似ているので次回は楽かもしれません。その後はレシピかな?

それではまた次回。

*1:ただし入力を受け取らない関数や値を返さない関数もあります

*2:変数名の長さは重要度に比例し、使用頻度に反比例すると良いです。