(大学サークルでの発表資料(原稿)となります。スライド資料はこちら)
これさえ覚えれば一通りそれっぽいのが組めるみたいなところまでの内容を取り扱います。
対象レベル
- 必須
- Minecraftをプレイしたことがある
- オブジェクト指向設計、デザインパターン関係の用語を理解できる(初級)
- Minecraft Forgeのインストールを完了している
- 高度
- Scala、Kotlin言語への知識がある(初級)
Minecraftワールドの構成クラス
ここからしばらく概念的な話になります。ワールドを構成するクラスは他にも
いろいろありますが、中でも必須なのが
- Item(
net.minecraft.item.Item
) - Block(
net.minecraft.block.Block
)
の2つとなります。このうち、実際にプログラムすべきなのは片方だけの場合がほとんどです。
Item
Itemはインベントリ内に入れられるものを表します。Blockはそのままではインベントリに格納することができず、アイテムとして扱う必要がある場合には変換を必要とします1。
通常はItemBlockというクラスが対応するブロックの登録時に自動で登録されますが、特殊なアイコンを使用したり、ツールチップに特別な情報を表示したり、複数のブロックを一括召喚したりする必要がある場合は自前でItemを実装する必要があります。
Block
Blockはワールドにおける、個々のブロックの情報・特性を表します。ブロックの特性とは、例えば採掘するのに最適な素材レベルだったり、爆発体制だったりといったものを指します。ブロックの情報とは名前や見た目といったものを指します。
これらに関して最も知っておくべきことは、これらの派生クラスはゲーム内でインスタンスが一つしか存在しないということです(つまりシングルトンクラスです)。そのため、ブロック内に座標ごとの固有アイテムや固有データを持たせるためには別の手段を講じる必要があります。また、シングルトンを言語レベルでサポートしているScala、Kotlinにおいては、class
の代わりにobject
として定義することが可能です。というか個人的にこれを推奨します。object
で宣言すれば「システム内でオブジェクトが一つしか存在しない」ということを保証することができるためです。
オブジェクトの登録
Itemの解説時に「登録」という語が出てきましたが、Minecraftに登場するアイテム、ブロック、モブキャラクターといったものはすべて特定の場所に登録されています。Mod側で用意するものに関しても例外ではなく、すべて登録を行う必要があります。
バニラのものはそれぞれ専用のレジストリに直接登録されますが、Mod側からは一般化された専用のレジストリから登録を行います。それがGameRegistryクラス(cpw.mods.fml.common.registry.GameRegistry
)です。それぞれ次のメソッドで登録を行います。
メソッド | 機能 |
---|---|
registerItem(アイテム、アイテム名) | アイテムを登録する |
registerBlock(ブロック、ブロック名) | ブロックを登録する |
このとき、アイテム名およびブロック名は実際に表示されるものとは別扱いになるので注意が必要です。表示される名前を設定する場合には、別途setUnlocalizedName
(アイテムの場合)かsetBlockName
(ブロックの場合)をインスタンスに対して呼ぶ必要があります。
クラフトレシピの追加
Minecraftの特徴的なシステムとして「3x3のグリッドに特定のアイテムを配置することにより新たなアイテムを取得できる」というものがあります。ダンジョンチェストからの発掘やレアドロップ扱い、または作物扱いのアイテムでない限り、ゲーム内ではクラフトによる入手がアイテムの唯一の入手手段となります。
クラフティンググリッドには2x2のものと3x3のものが存在しますが、レシピ登録の手順に差はありません。これもバニラ側には専用のレジストリが存在しますが、Mod側からはGameRegistryクラスを経由して登録することになります。レシピ登録は複雑なので詳細な説明を交えて解説を行います。
GameRegistry.addRecipe
定型レシピを追加します。引数が少し複雑で、最初が結果のアイテム、次がStringの3つまでの可変長引数で、その後ろがObjectの可変長引数になっています。
具体例で解説しますが、例えばチェストのレシピは以下のようになります。
GameRegistry.addRecipe(new ItemStack(Blocks.chest),
"xxx",
"x x",
"xxx",
'x', new ItemStack(Blocks.planks));
最初が結果のアイテム(チェスト)、次がアイテムの配置を文字であらわしたもの(行ごとに分かれています)、最後に「どの文字がどのアイテムに対応するか」を指定しています。
また、行と列それぞれ3に満たないように指定することも可能で、その場合は2x2グリッドでクラフトできたり3x3グリッドで、形さえ保っていればどこにアイテムを配置してもクラフトできるようになります。
GameRegistry.addRecipe(new ItemStack(Blocks.workbench),
"xx",
"xx",
'x', new ItemStack(Blocks.planks));
GameRegistry.addShapelessRecipe
こちらは不定形レシピを追加するものになります。不定形レシピといわれてもあまりピンと来ないかもしれませんが、羊毛に対して色つけを行ったりする際に、どのような配置でアイテムをおいても認識されるレシピなどのことです。こちらの引数は先ほどより簡単で、最初が結果のアイテム、その後ろに要求するアイテムの可変長引数が続きます。
例として、羊毛の色を移すレシピは以下のようになります。
GameRegistry.addShapelessRecipe(new ItemStack(Items.wool, 2),
Items.wool, new ItemStack(Items.wool, 1, 0));
おしまい
おおざっぱですが、以上で基本的なModdingに関係する(概念的な)解説はおしまいにします。
テクスチャ関係について話していませんが、それを話すとまた長くなってしまうのでこことか自分で調べてください。