【MC1.12Modding】初心者研修編 - 早速プログラムを書いてみる


# 初心者研修編リンク
- [新規Modの作成からビルドまで](https://qiita.com/Katatsumuri_Pan/items/fec8344fa51b79261381)
- [早速プログラムを書いてみる](https://qiita.com/Katatsumuri_Pan/items/21f4b5f08aadec2eac17) ← here
- [ItemとItemStackの違い](https://qiita.com/Katatsumuri_Pan/items/c5c04973e66a42451c63)
- BlockとIBlockStateとTileEntityは一緒です（大嘘）
- Modを国際化する
- デバッグを実践する
- イベント購読
- 音とか粒子とか
- ワールドとディメンションは何が違うんだ
- 「メタデータ」ってかっこいいな
- Entityを少しだけ操る
- 強敵NBT
- [メインページへ戻る](https://qiita.com/Katatsumuri_Pan/items/e3fd7fec471ee66fa17a)

# はじめに

この記事では（初めての方にとっては）初めてのプログラミングとModdingを体験していただきます。
とはいっても身構える必要はありません。
全てじっくり説明しながら進めていきますので、頑張っていきましょう。

記事中でのJavaプログラミングの説明については、Moddingに必要な部分の必要最低限だけを雑に何となくで分かる説明をします。
厳密で正確なプログラミングの説明を知りたい方は別サイトで学んでください。


:::note info

エディタ（Intellij IDEA）の画面の色や見た目は設定でいくらでも自分好みに変更できます。
そのため、文字の色や背景色等が自分で使っているものと画像とでは異なります。
見づらい等のお問い合わせはコメントへお願いいたします。

:::

# 今回の題材

今回、Moddingとプログラミングの練習として「クラフトレシピの追加」をやっていただきます。

レシピ追加自体はリソースパックでも可能な代物[^1]ですが、初めてModdingとプログラミングをやってみるという方には丁度良い難易度となっています。

[^1]: 極めればリソースパックでは実現し得ないこともできる
例えばNBT付きの成果品やレシピの自動生成等

# 目次
- [1. 準備](#1-準備)
- [2. とりあえずプログラムを書いて（コピペ）動かす](#2-とりあえずプログラムを書いてコピペ動かす)
- [3. 少しだけ改造してみる](#3-少しだけ改造してみる)
- [4. 定形レシピもコピペして動かす](#4-定形レシピもコピペして動かす)
- [5. 終わりに](#5-終わりに)


# 1. 準備

## 簡易目次
- [`MyMod.java`を開く](#mymodjavaを開く)
- [ソースコードの折り畳みを使いこなす](#ソースコードの折り畳みを使いこなす)

## `MyMod.java`を開く

まずは`MyMod.java`を開きましょう。
プロジェクトビューから`src`＞`main`＞`java`＞(前回の記事で決めたパッケージ)＞`MyMod`をたどって開きましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/30557f5c-0687-1930-3876-3b97cb476f61.png)

<details><summary>赤線が引かれていたり、赤い文字が含まれている</summary>

`6. Build Jars`を実行していない場合は下の画像のようにエラーが出てしまいますので、`6. Build Jars`を実行してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0b7aae63-182f-29f8-e336-58e275fe03ba.png)

<font color="gray">└赤線が引かれていたり、赤い文字が含まれている終わり</font>
</details>


ソースコードがぶわっと出てきますが、恐れる必要はありません。
今は書いてあることを理解する必要は一切無いです。

:::note info

プログラミングにおいて、「ここに何か書いてあるけどよくわからないし放っておこう」という考えは大事です。
全てを理解するまで少しも次には進まないぞ！みたいな思考で突き進もうとすると先に寿命が尽きてしまいます。
いずれ全て理解できるようになりますので、まずは

:::

## ソースコードの折り畳みを使いこなす

開いたMyMod.javaの行番号をよく見てみると……変ですね、番号が跳んでいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/7b2d6b43-787f-79c5-f965-3664b5b84f9f.png)
これはIntellij IDEAの機能で、まとまった部分を1行に折り畳むということが行われています。

プロジェクトビューでも、フォルダの中身を展開する・畳むということができましたが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/2fb7f4f0-e604-7485-c0fa-f450c24feb08.png)
これと同じことをテキストに対してもやったら便利じゃね！？ということでソースコードも部分的に折り畳むことができます。


では試しに3行目のソースコードを展開してみましょう。
行番号の右にある`>`（矢印）をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0918558d-a8fd-669c-820c-8a2b4ff8941c.png)

わあ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/657c4051-c0bf-1a91-bdd1-f249ee52e840.png)

閉じて見なかったことにしましょう。
折り畳んだときは`…`として表示される[^10]んですね。
このまましばらく封印しておきましょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/459fcc52-dcfe-b396-0496-4be02eb93ab3.png)

[^10]: この折り畳まれている、色の変化した部分をクリックするだけでも展開できる



# 2. とりあえずプログラムを書いて（コピペ）動かす

では自由にプログラムを書いてください！

.

..

...

....

.....
<font color="white">この隠し文字に良く気づきましたね…</font>
......
<font color="white">まさかダークモードではないだろうな！？</font>

と言われても困ります。Moddingもプログラミングも初心者では手も足も出ません。~~経験者であってもさすがに非情な行為~~

なのでまずはお手本を見ましょう。

## 簡易目次

- [33行目の折り畳みを開く](#33行目の折り畳みを開く)
- [ソースコードをコピペ](#ソースコードをコピペ)
- [ソースコードを眺めてみる](#ソースコードを眺めてみる)
- [実際に動かしてみる](#実際に動かしてみる)

## 33行目の折り畳みを開く

プログラムを書く場所は33行目にある`registerRecipes`というメソッド[^20]の中です。
まずは33行目の左端の矢印からメソッドの中身を展開表示しておいてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/d663993d-a67a-288c-9581-50f4e1d5b108.png)

[^20]: 実はメソッド名は`registerRecipes`から変更しても動作する
31行目にある`@SubscribeEvent`と引数の`RegistryEvent.Register<IRecipe>`だけで正しいメソッドかどうかを判断してたりするからである~~という非常にハイレベルな話~~
~~（え！？ジェネリクスの型は消去されるのにそれで大丈夫なんですか！？……なるほど、コンパイル時のメソッドの引数の型の型変数ならリフレクションで取ってこれるからそれでif挿んでるのか…とか言ってる玄人は呼んでません）~~

以下のように34-35行目が表示されていればokです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/cc160a97-cea3-ec32-93f2-3bd88c5e9791.png)

## ソースコードをコピペ

Moddingで使うJavaプログラミングは、基本的に中かっこ[^21]（`{`と`}`）に囲まれた領域にコードを書きます[^22]。
まずは以下のコードを（最初と最後の`{` `}`含めて）34行目に貼り付けてください。


[^21]: 波かっことも呼ぶし、IT系ならそっちの方が多いかも

[^22]: 大嘘だが、初心者にとってはこのくらい端的な方がありがたい
~~「`#include`ってどういう意味なんですか？」~~

```java: 不定形レシピのプログラム
        {
            //--------------------不定形レシピの追加--------------------

            // クラフト材料の設定（アイテムの指定は順不同）
            NonNullList<Ingredient> ingredients = NonNullList.create();
            ingredients.add(Ingredient.fromItem(Items.APPLE));      // リンゴ
            ingredients.add(Ingredient.fromItem(Items.GOLD_INGOT)); // 金インゴット

            // クラフト成果品の設定
            ItemStack output = new ItemStack(Items.GOLDEN_APPLE, 2); // 金リンゴ×2

            // レシピの作成
            ShapelessRecipes recipe = new ShapelessRecipes("", output, ingredients); // groupと成果品と材料からレシピ作成

            // レシピの登録
            recipe.setRegistryName(new ResourceLocation(Tags.MODID, "apple_plus_gold_ingot")); // 登録時の内部レシピ名指定
            event.getRegistry().register(recipe); // 登録
        }
```

コピペする際は、ソースコード部（黒背景）の右上のボタンをクリックするのがおすすめです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/384eea2c-917c-38b4-6ee3-0b04947681c3.png)
クリックするだけで勝手にコピーされるので、後はIntellij IDEAの34行目にCtrl+Vしましょう。
マウスで範囲選択は結構面倒な上にミスりやすいので非推奨（n敗）。

以下のようになればOKです。
~~57行目と58行目で中かっこが2つもあるんだがええんか！？その状態でお願いします。おう分かったで～。~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0d3765c4-d6bd-c878-4ce3-6ed0ab7d20f3.png)

もし、エラー（赤文字）だらけ[^24]の場合は、別の行をクリックすると自動で直るはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/07a8cddf-d256-e3e2-cccd-bd8088b21108.png)

[^24]: これはクラスをインポートしていないのが原因
初期設定ではコピペ時に自動でインポートを挿入してくれる…はず

<details><summary>直らん！</summary>

一つひとつ直してもいいのですが、面倒なので便利な設定を施しておきましょう。

Intellijの設定を開きまして、

`エディター`＞`一般`＞`自動インポート`のページを開きます。
`Java`という節の中にある`貼り付け時にインポートを挿入`を`常時`にし、`明確なインポートをオンザフライで追加する`にチェックを入れて`OK`を押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/6a3f9346-5fa3-b3e8-e35a-c4a1f2e5333c.png)

すると少し待つだけで自動でエラーを直してくれます。
~~かがくのちからってすげー！~~

<font color="gray">└直らん！終わり</font>
</details>

## ソースコードを眺めてみる

説明とかいいから早く動かしたい！って人は先に[実際に動かしてみる](#実際に動かしてみる)を実施しましょう。

### 全体

コピペしたコードをまじまじと見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0d3765c4-d6bd-c878-4ce3-6ed0ab7d20f3.png)

まず処理の全体が39行目の`{`と58行目の`}`で囲まれています。
さらにもう一段階、40行目と57行目の`{}`で囲まれています。
（2重にした理由は後で分かります。）
Javaでは、中かっこを使うことでブロック（ひとまとまり）を作ることができます。
これらの中かっこも折り畳みできますので、ぜひ試してみてください。

<details><summary>実際に試した時のイメージ図</summary>

- 39行目で閉じた場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/962cad2d-6cd6-53be-406d-5e82bbb0dc67.png)

- 40行目で閉じた場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/780a13d3-80c8-2546-75d1-3f477868ed06.png)

<font color="gray">└実際に試した時のイメージ図終わり</font>
</details>

### コメントの説明と45行目の理解

さらにコードをまじまじと見ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0d3765c4-d6bd-c878-4ce3-6ed0ab7d20f3.png)

41行目や43行目など、がっつり日本語で説明が書かれています。
これはプログラミング用語で「コメント」と呼びます。

:::note info

Javaでは、`//`（スラッシュ2つ）以降から行の終わりまでがコメントとして扱われ、何を書いても一切プログラムの動作に影響を与えません[^25]。

:::

[^25]: 昔はsjisのダメ文字をコメントの最後に書くことで「（コメントは動作に影響を与えないはずなのに）このコメントが無いとなぜかプログラムがバグる！！」という事故が話題になったとかいう薀蓄は締め切らせていただきました

大抵は書いたコードの内容を分かりやすく簡潔にコメントとして残します。
コメントは**嘘さえ書かなければ**害は無いので、積極的に書くことが推奨されます。
（特に数か月経った後の自分が一番恩恵を受ける[^26]）

[^26]: ~~記憶とは諸行無常である~~

呪文みたいなJavaのソースコードは分からなくても、コメントを見るだけで何となく動きが分かるはずです。

例えば、45行目に着目してみましょう。
```java: 45行目のみ抜粋
ingredients.add(Ingredient.fromItem(Items.APPLE));      // リンゴ
```

コメントで「リンゴ」と書いてありますが、コードをよく読むと`Items.APPLE`と書かれています。

「なるほど、アイテムのリンゴを何かしら設定してるな」ということが読み取れます。
43行目には`// クラフト材料の設定（アイテムの指定は順不同）`と書かれていたため、「クラフトレシピの材料の1つがリンゴなんだろうな」と想像できます。

プログラミング・Modding初心者であっても、コメントを読めば何となくコードの中身が少しずつ読めてきます。
Javaのソースコードも大半が英語由来[^27]なので、**何となくでもいいから英語さえ分かれば**何とかなります。
（逆に英語に拒否反応がある場合は何とかして克服してください。）

[^27]: 英語圏で発明されたから仕方のないところ
日本語のプログラミング言語もあるが、結局PC上での日本語入力のしづらさもあって英語でええやん！となる
命名を英語にするかとかなんとかの議論はまた今度

:::note info

今の時代はChatGPT等のチャットAIもありますので、このソースコードをそのままChatGPTに渡して「説明して」と頼めばいくらでも教えてくれるので便利です。（ただし**嘘もかなり多い**ので鵜呑みにはしないようにしましょう。）

:::

### コメントから全体像の把握

先ほどは45行目だけピンポイントで何となく少しだけわかりましたが、今度はコメントを読んで全体の流れをつかんでみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0d3765c4-d6bd-c878-4ce3-6ed0ab7d20f3.png)

41行目に`不定形レシピの追加`とあるので、40~57行目全体で不定形レシピの追加を実現しているのでしょう。

43行目には`クラフト材料の設定`とあります。
44~46行目を指していそうです。
45行目と46行目にそれぞれ`リンゴ`と`金インゴット`と書かれていますが、先ほどの`クラフト材料の設定`というコメントと総合して考えると、クラフトのレシピに「リンゴ」と「金インゴット」が含まれていると予想できます。

48行目の`クラフト成果品の設定`というコメントは、49行目の話をしており、`金リンゴ×2`というコメントから察するにクラフトによって金リンゴが2個手に入るのでしょう。

51行目に`レシピの作成`というコメントがあり、52行目のことを指していると思われます。
52行目のコメントは読んでもピンとこないので無視します[^28]。

[^28]: グループと成果品と材料を引数にとってレシピのインスタンスが作成されているけど、そんなこと初心者に言われてもわからん
グループの説明は後で出てくる

54行目のコメントが`レシピの登録`となっているので、55~56行目がレシピの登録部分のようです。

まとめますと、

- 全体は不定形レシピの追加処理
- 処理は順に
    - クラフト材料の設定
    - クラフト成果品の設定
    - レシピの作成
    - レシピの登録

    の順でおこなっている様子
- 「リンゴ」と「金インゴット」から「金リンゴ2つ」ができる不定形レシピがおそらく追加される

ということが読み取れます。


このように、呪文のようなソースコードを解読しなくとも、コメントを読むだけで処理内容とその流れが把握できます。
ソースコードの中身がよくわからない初心者であっても何とかなりそうですね！
~~現実にはコメントが一切書かれてない不親切なソースコードも多々あるのが悲しいところ~~


## 実際に動かしてみる

マイクラを起動してみましょう。
`2. Run Client`を実行してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0e08de46-b3e6-96ce-1089-c77174eb5786.png)

<details><summary>エラーになって起動できない</summary>

十中八九、`MyMod.java`のファイル中に余計な文字を打ち込んでいます。（もしくは誤って削除）

`Ctrl+Z`で最初まで戻せれば一番楽です。（ファイルを閉じてしまうとこれが使えなくなる。）

または見つけて直せれば良いのですが、見つからないこともしばしばあります。（全角スペースとかその代表）

コピペで増やした40行目から57行目をいったん削除し、再びコピペしなおすことで、大抵は解決するでしょう。

万が一完全に別の行を壊していた場合は、現状Modの作成からやり直ししかありません。
もしGitのバージョン管理（環境構築編で解説済み）を行っていればそれに従ってすぐに復元できるのですが…

<details><summary>最初からやり直しはヤダ！！！！！</summary>

今回ばかりは、ここに`MyMod.java`の元のソースコードを貼っておきましょう。
こういうことが起こらないように、バージョン管理を使ってください。
（`package`のある1行目だけは自分で決めたパッケージ名に合わせる必要があります。）
```java: MyMod.java
package my_first_mod;

import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.crafting.IRecipe;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@Mod(modid = Tags.MODID, version = Tags.VERSION, name = Tags.MODNAME, acceptedMinecraftVersions = "[1.12.2]")
public class MyMod {

    public static final Logger LOGGER = LogManager.getLogger(Tags.MODID);

    @EventHandler
    // preInit "Run before anything else. Read your config, create blocks, items, etc. (Remove if not needed)
    public void preInit(FMLPreInitializationEvent event) {
        // register to the event bus so that we can listen to events
        MinecraftForge.EVENT_BUS.register(this);
        LOGGER.info("I am " + Tags.MODNAME + " + at version " + Tags.VERSION);
    }

    @SubscribeEvent
    // Register recipes here (Remove if not needed)
    public void registerRecipes(RegistryEvent.Register<IRecipe> event) {

    }

    @SubscribeEvent
    // Register items here (Remove if not needed)
    public void registerItems(RegistryEvent.Register<Item> event) {

    }

    @SubscribeEvent
    // Register blocks here (Remove if not needed)
    public void registerBlocks(RegistryEvent.Register<Block> event) {

    }

    @EventHandler
    // load "Do your mod setup. Build whatever data structures you care about." (Remove if not needed)
    public void init(FMLInitializationEvent event) {
    }

    @EventHandler
    // postInit "Handle interaction with other mods, complete your setup based on this." (Remove if not needed)
    public void postInit(FMLPostInitializationEvent event) {
    }

    @EventHandler
    // register server commands in this event handler (Remove if not needed)
    public void serverStarting(FMLServerStartingEvent event) {
    }
}
```

<font color="gray">└最初からやり直しはヤダ！！！！！終わり</font>
</details>


<font color="gray">└エラーになって起動できない終わり</font>
</details>


新規ワールドを（もちろんクリエイティブで）作成して入ります。
謎のアイテムを持った状態でスポーンしますが捨てて良いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/72317ee7-53ec-a336-dced-a98d43a7f06e.png)

リンゴと金インゴット（と作業台[^29]）を取り出し、クラフトしてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/d7d5eb53-1d13-f639-dc74-5368a1733418.png)

[^29]: 手元の2×2クラフトでも良いが、クリエイティブモードでは作業台の方が楽

本当に金リンゴ2つがクラフトできますね！

不定形レシピなので、どのような置き方をしても金リンゴが作れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/c6543efa-f4e4-9016-b9f7-6ff8fe08578f.png)

<details><summary>JEIでレシピを見る</summary>

Moddingで用いているGregTechCEu製のBuildscriptsが初期設定でJEIを入れてくれているため、デバッグ環境でも何の苦労もすることなくJEIが使えます。

インベントリ画面の右側でページ送りして（マウスホイールが楽）リンゴを探し、右クリックしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/c507ac53-1d85-53cd-eb59-fa3c60bc8269.png)

レシピがちゃんと登録されていますね！
不定形レシピなので、それを表すアイコン（クロス矢印）が付いています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/4d8b6132-e53e-76ad-06cb-c7fcca9678fa.png)

<font color="gray">└JEIでレシピを見る終わり</font>
</details>


# 3. 少しだけ改造してみる

とりあえずコピペしたコードをそのまま動かしました。
どうせならこのコードを少しカスタマイズして、自分の思い通りに動かしたいものです。

<details><summary>1. 成果品の個数を変えてみる</summary>

成果品の設定を行っている49行目を見てみましょう。
```java: MyMod.javaの49行目抜粋
ItemStack output = new ItemStack(Items.GOLDEN_APPLE, 2); // 金リンゴ×2
```

ここでは金リンゴが2つ作成されるように設定するプログラムコードが書かれています。

…… Javaのプログラミングを知らなくても何となく読み取れませんか？
特に個数を指定してそうな場所ありますよね？

そうです、`2`が使われている唯一のここです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/82afd634-4a40-d354-9b59-f6f56dda0cac.png)
（直前に`amount:`と書かれていますが、これはIntellij IDEAのお節介機能[^30]で表示しているゴーストであり、この文字列が入力されているわけではありません[^31]。）

[^30]: メソッドの実引数にリテラルを与えた場合に、その仮引数の名前を表示してくれる機能

[^31]: BackspaceやDeleteしても消えない・消せない
この部分をコピペしてもきれいさっぱり無かったことになる


この部分を別の数に書き換えて保存（当然`Ctrl+S`）し、マイクラを起動してみましょう。

<details><summary>実際の書き換え例</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/31ad763f-8f77-859b-9740-6a744c0cd043.png)

<font color="gray">└実際の書き換え例終わり</font>
</details>

:::note warn

全角数字だとエラーになります。
必ず半角数字で入力してください。

:::

ゲーム内でアイテムを作業台に置いてみると、見事に変化していることが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/0fc92d1e-c2ff-b2c6-660b-51863fffb03c.png)

これで完成品の個数を自由に設定させることができるようになりました！

<font color="gray">└1. 成果品の個数を変えてみる終わり</font>
</details>

<details><summary>2. 成果品を別アイテムにする</summary>

成果品の設定を行っている49行目をもう一度見てみます。
```java: MyMod.javaの49行目抜粋
ItemStack output = new ItemStack(Items.GOLDEN_APPLE, 2); // 金リンゴ×2
```

ここでは金リンゴが2つ作成されるように設定するプログラムコードが書かれています。

…… Javaのプログラミングを知らなくても何となく読み取れませんか？
「金リンゴ」は英語でGolden Appleと呼びますが、「金リンゴ」を指定してそうな場所ありますよね？


そうです、`GOLDEN_APPLE`と書かれていたらそりゃもう、それです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/2ac31c30-79b5-145b-e86a-88d6f80987b5.png)

ここを自由に変更！と行きたいところですが、この部分[^32]はルールに従って書く必要があります。
例えば、`GOLDEN_APPLE`ではなく、`GOLD_APPLE`と書いたらどうなるか試してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/565765d4-2474-2a79-5805-ffbc43a81d20.png)
見事に赤字のエラーになっており、このままでは`2. Run Client`も失敗します。

[^32]: この部分はItemsクラスのstaticフィールドである

<details><summary>失敗してる図</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/157a4086-db6f-d804-69f9-2c726882f2a4.png)

~~文字化けについての対処方法も調べて書かねば~~

<font color="gray">└失敗してる図終わり</font>
</details>

ちなみに小文字でもダメです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/6b1db2ee-f38f-2243-fc46-60adbf2f6ddd.png)

つまり、完璧に一字一句正しいものを書かないとエラーになります。

:::note info

プログラミングでは、基本的に一字一句完全に正しく書く必要がある場合がほとんどです。
大文字小文字、全角半角、空白や_を入れる位置等を厳密に書くようにしましょう。

:::

さて、「金リンゴ」の代わりに「ネザースター」が作成されるように改造したいとしましょう。
ですが、ネザースターの「正しい書き方[^33]」が分からないとエラーになってしまいます。
いちいちネザースターの正しい書き方なんて憶えてられません。

[^33]: ここでの正しい書き方とは、「Itemsクラスで」という条件が付く
つまり、別の場所ではまた違う書き方が正しい書き方となる

そこでIntellij IDEAの機能を活用します。

まずは`GOLDEN_APPLE`を消します。
（この時`Items.`と`,`が隣り合うはずです。消しすぎたら`Ctrl+Z`で戻しましょう。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/81beb981-903a-6503-5f28-6d3582f7c0f9.png)

次に`Items.`の直後にキャレット（≒マウスカーソル[^34]）を置き、キーボードで`Ctrl+Space`（Ctrlキーとスペースキー[^35]）を押します。
すると、正しい書き方の候補がズラッと並びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/13d22402-d34e-c3e7-de14-af6e4921dc64.png)

[^34]: マウスカーソルはマウスの位置であり、キャレットはテキストの入力位置（点滅する`|`）を指す

[^35]: 普通、CtrlキーやShiftキーとの同時押しは、完全に同時というよりもCtrlやShiftのような特殊キーを先に押しっぱなしにしながら他のキーを押す

後はマウスホイールでスクロールし、お目当てが見つかったらダブルクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/c25d58db-d291-e66a-ab48-a664b7861d2e.png)
（候補が多すぎて探すのが面倒な場合は、欲しい選択肢に含まれるアルファベット（ネザースターなら`NE`など）を追加で入力すると候補を絞れます。）

`NETHER_STAR`と正しい書き方が自動入力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/4bf361ba-93a2-023b-9c36-c07e04c4174c.png)

:::note info

`Ctrl+Space`というショートカットによる候補の表示と自動入力はぜひたくさん活用してください。
これだけで何倍もプログラムを書く効率が変わります。

:::

後は保存してマイクラを起動して確かめてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/bcf5f2c3-e1ff-c85a-edc9-9b0778e9f384.png)

<font color="gray">└2. 成果品を別アイテムにする終わり</font>
</details>

<details><summary>3. 材料も別アイテムにする</summary>

今度は成果品ではなく、材料を変更してみましょう。
材料の設定は44行目から46行目です。

```java: MyMod.javaの44～46行目抜粋
NonNullList<Ingredient> ingredients = NonNullList.create();
ingredients.add(Ingredient.fromItem(Items.APPLE));      // リンゴ
ingredients.add(Ingredient.fromItem(Items.GOLD_INGOT)); // 金インゴット
```

謎な部分もたくさんありますが、リンゴと金インゴットを指定している部分がありますね？

そう、ここです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/b176f726-0f1d-70bc-505b-67141fbb1401.png)

よく見たら、成果品の時と同じ`Items.（アイテム名）`という形です。
つまり成果品の時と同じ方法で変更できます。

ではここで練習問題を解いてみましょうか。
＜練習問題＞　ネザーウォートと砂糖からクモの目が3つ作成できるレシピを登録してください。

<details><summary>ヒント集（ネザーウォート）</summary>

<details><summary>ヒント１</summary>

ネザーウォートは英語でNether Wartと書きます。
もしかしたらプログラムでも似たように書くかもしれませんね。
近いものを`Ctrl+Space`の候補表示で探してみましょう。

<font color="gray">└ヒント１終わり</font>
</details>

<details><summary>ヒント２</summary>

ネザーウォートはプログラムでは`Items.NETHER_WART`と書きます。

<font color="gray">└ヒント２終わり</font>
</details>

<font color="gray">└ヒント集（ネザーウォート）終わり</font>
</details>

<details><summary>ヒント集（砂糖）</summary>

<details><summary>ヒント１</summary>

砂糖は英語でSugarと書きます。
もしかしたらプログラムでも似たように書くかもしれませんね。
近いものを`Ctrl+Space`の候補表示で探してみましょう。

<font color="gray">└ヒント１終わり</font>
</details>

<details><summary>ヒント２</summary>

砂糖はプログラムでは`Items.SUGAR`と書きます。

<font color="gray">└ヒント２終わり</font>
</details>

<font color="gray">└ヒント集（砂糖）終わり</font>
</details>

<details><summary>ヒント集（クモの目）</summary>

<details><summary>ヒント１</summary>

クモの目は英語でSpider Eyeと書きます。
もしかしたらプログラムでも似たように書くかもしれませんね。
近いものを`Ctrl+Space`の候補表示で探してみましょう。

<font color="gray">└ヒント１終わり</font>
</details>

<details><summary>ヒント２</summary>

クモの目はプログラムでは`Items.SPIDER_EYE`と書きます。
あとは全てを組み合わせるだけです。
個数の変更を忘れないようにしましょう。

<font color="gray">└ヒント２終わり</font>
</details>

<font color="gray">└ヒント集（クモの目）終わり</font>
</details>

<details><summary>模範解答</summary>

コメントを書き換えるのは必須ではありませんが、嘘コメントは良くないのでちゃんと書き換えましょう。

```java: MyMod.javaの43～49行目抜粋
// クラフト材料の設定（アイテムの指定は順不同）
NonNullList<Ingredient> ingredients = NonNullList.create();
ingredients.add(Ingredient.fromItem(Items.NETHER_WART)); // ネザーウォート
ingredients.add(Ingredient.fromItem(Items.SUGAR));       // 砂糖

// クラフト成果品の設定
ItemStack output = new ItemStack(Items.SPIDER_EYE, 3); // クモの目×3
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/2c4c4292-c10a-37c9-a98c-e939d547c8a8.png)

<font color="gray">└模範解答終わり</font>
</details>

できあがったものをゲーム内で試してみると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/7edd815c-5aa9-cb7f-b699-70f2ff0fd847.png)
無事成功しました。

<font color="gray">└3. 材料も別アイテムにする終わり</font>
</details>

<details><summary>4. 材料の種類数を変更する</summary>

今まで材料は2種類固定でしたが、もうちょっと自在に設定したいものです。

今回のコードで、材料の種類が2種類になってしまうのはどの部分が関係しているでしょうか。

材料の設定をする部分を抜き出しました。
```java: 43～46行目
43 // クラフト材料の設定（アイテムの指定は順不同）
44 NonNullList<Ingredient> ingredients = NonNullList.create();
45 ingredients.add(Ingredient.fromItem(Items.APPLE));      // リンゴ
46 ingredients.add(Ingredient.fromItem(Items.GOLD_INGOT)); // 金インゴット
```

44行目はよく分からないから置いとくとして、
45行目と46行目で各行1アイテムを登録しています。
もしかしたら**コードの行数を増減させる**だけでうまくいくかもしれません。

46行目（金インゴットの行）をコピペして次の行に増やしちゃいましょう。
こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/7cf626d3-23c8-ecad-38a9-449afe2ee24c.png)
新たに47行目が増えました。

この状態でマイクラを起動してみましょうか。
今までのレシピが使えなくなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/91aa4155-95e0-8864-f066-5a599dd41fb8.png)

そして、リンゴ、金インゴット、金インゴットの新レシピが使えるようになっています。
（同じ材料が複数あっても直感通りに動作するんですね。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/1b6d6dee-1c80-ceee-a534-d75539a9d0c2.png)

今度は行を削ってみましょう。
リンゴの行だけ残しました。（金インゴットは元からレシピがあるので却下）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/26c96f40-0297-fb8c-f564-cade88114559.png)

これでマイクラを起動しますと、リンゴ単体で金リンゴ2つに変身する~~チートすぎる~~レシピができあがりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/9b7a7ae0-1200-1102-2890-cfeddf59a29e.png)

まとめると、
```java
ingredients.add(Ingredient.fromItem(Items.ここはアイテムによって変える));
```
を書いた行数だけ材料が設定されるということですね。

<font color="gray">└4. 材料の種類数を変更する終わり</font>
</details>

<details><summary>5. ブロックもクラフトに含む</summary>

今までずっと隠してきたことなのですが、`Items.`からアイテムを探すやり方では、ブロックを材料や完成品に指定することができません。

そこでブロックも設定できるようにする方法を伝授します。
`Items.なんたら`の代わりに、
```java: ブロックを指定
Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)
```
を書きます。
**よく見ると`Items`ではなく`Item`に変わっています。**
紛らわしいことこの上ないですが、そういうルールと決まっているので間違えないようにしましょう。（当然間違えるとエラーです。）

`Blocks.`の後ろにブロック名が来てますが、これも`Items.`で説明した時と同様、正しい書き方候補を`Ctrl+Space`で表示できますのでぜひ活用してくださあい。

それでは実際にブロックも含めたレシピを登録してみましょう。
レシピの材料と成果品は、ブロックとアイテムを好きなように組み合わせられます。
例えば、金ブロックとダイアモンド3個ででダイアモンドブロックができる不定形レシピは、
```java: 金ブロック＋ダイアモンド×3 → ダイアモンドブロック
// クラフト材料の設定（アイテムの指定は順不同）
NonNullList<Ingredient> ingredients = NonNullList.create();
ingredients.add(Ingredient.fromItem(Item.getItemFromBlock(Blocks.GOLD_BLOCK)));     // 金ブロック
ingredients.add(Ingredient.fromItem(Items.DIAMOND));                                // ダイアモンド
ingredients.add(Ingredient.fromItem(Items.DIAMOND));                                // ダイアモンド
ingredients.add(Ingredient.fromItem(Items.DIAMOND));                                // ダイアモンド

// クラフト成果品の設定
ItemStack output = new ItemStack(Item.getItemFromBlock(Blocks.DIAMOND_BLOCK), 1);   // ダイアモンドブロック
```
のように書けます。
かっこの個数が増えるので、間違えないようにしましょう。
1個でも過不足があるとエラーになります。

Intellij IDEA上ではこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/8a152d3f-8c2a-7487-3eda-7d316ad937af.png)
エラーが出ている場合は、何かしらの記述ミスが発生しています。
`Ctrl+Z`するなりコードのコピペをし直すなりして画像通りの状態にしてください。

あとはマイクラを起動して確かめてみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/1ae46478-5eef-700d-07c9-953c430ce252.png)

うまくいったのであれば、ちょっと練習問題でも解いてみましょう。

＜練習問題＞サボテン＋コーラスフルーツ＋コーラスフルーツ＋種 → コーラスフラワーの不定形レシピを登録してください。

以下のような不定形レシピが登録できたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/8a9b754a-4b44-4138-8761-1130efe2c7df.png)

<details><summary>ヒント集（サボテン）</summary>

<details><summary>ヒント１</summary>

サボテンは英語でCactusと書きます。
もしかしたらプログラムでも似たように書くかもしれませんね。

<font color="gray">└ヒント１終わり</font>
</details>

<details><summary>ヒント２</summary>

サボテンは**ブロック**です。
つまり、
```
Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)
```
の形で書く必要があるでしょう。
`DIAMOND_BLOCK`の部分を消し、`Blocks.（ここにキャレット）`の状態で`Ctrl+Space`を押し、候補表示でそれっぽいものを探してみましょう。

<font color="gray">└ヒント２終わり</font>
</details>

<details><summary>ヒント３</summary>

サボテンはプログラムでは`Item.getItemFromBlock(Blocks.CACTUS)`と書きます。

<font color="gray">└ヒント３終わり</font>
</details>

<font color="gray">└ヒント集（サボテン）終わり</font>
</details>

<details><summary>ヒント集（コーラスフルーツ）</summary>

<details><summary>ヒント１</summary>

コーラスフルーツは英語でChorus Fruitと書きます。
もしかしたらプログラムでも似たように書くかもしれませんね。

<font color="gray">└ヒント１終わり</font>
</details>

<details><summary>ヒント２</summary>

コーラスフルーツは**アイテム**です。
つまり、
```
Items.APPLE
```
の形で書く必要があるでしょう。
`APPLE`の部分を消し、`Items.（ここにキャレット）`の状態で`Ctrl+Space`を押し、候補表示でそれっぽいものを探してみましょう。

<font color="gray">└ヒント２終わり</font>
</details>

<details><summary>ヒント３</summary>

コーラスフルーツはプログラムでは`Items.CHORUS_FRUIT`と書きます。
今回は2つ必要なので2行分書きましょう。

<font color="gray">└ヒント３終わり</font>
</details>

<font color="gray">└ヒント集（コーラスフルーツ）終わり</font>
</details>

<details><summary>ヒント集（種）</summary>

<details><summary>ヒント１</summary>

種は英語でSeedsと書きます。
ただし、プログラムでも同じように書くとは限りません…

ちなみに小麦は英語でWheatです。

<font color="gray">└ヒント１終わり</font>
</details>

<details><summary>ヒント２</summary>

種は**アイテム**です。
つまり、
```
Items.APPLE
```
の形で書く必要があるでしょう。
`APPLE`の部分を消し、`Items.（ここにキャレット）`の状態で`Ctrl+Space`を押し、候補表示でそれっぽいものを探してみましょう。
ただし、SEEDSで出てくるとは限りません…

<font color="gray">└ヒント２終わり</font>
</details>

<details><summary>ヒント３</summary>

種はプログラムでは`Items.WHEAT_SEEDS`と書きます。
「小麦の」種なので納得はできますね。

<font color="gray">└ヒント３終わり</font>
</details>

<font color="gray">└ヒント集（種）終わり</font>
</details>

<details><summary>ヒント集（コーラスフラワー）</summary>

<details><summary>ヒント１</summary>

コーラスフラワーは英語でChorus Flowerと書きます。
もしかしたらプログラムでも似たように書くかもしれませんね。

<font color="gray">└ヒント１終わり</font>
</details>

<details><summary>ヒント２</summary>

コーラスフラワーは**ブロック**です。
つまり、
```
Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)
```
の形で書く必要があるでしょう。
`DIAMOND_BLOCK`の部分を消し、`Blocks.（ここにキャレット）`の状態で`Ctrl+Space`を押し、候補表示でそれっぽいものを探してみましょう。

<font color="gray">└ヒント２終わり</font>
</details>

<details><summary>ヒント３</summary>

コーラスフラワーはプログラムでは`Item.getItemFromBlock(Blocks.CHORUS_FLOWER)`と書きます。

<font color="gray">└ヒント３終わり</font>
</details>

<font color="gray">└ヒント集（コーラスフラワー）終わり</font>
</details>

<details><summary>模範解答</summary>

コメントを書き換えるのは必須ではありませんが、嘘コメントは良くないのでちゃんと書き換えましょう。

```java: MyMod.javaの44～52行目抜粋
// クラフト材料の設定（アイテムの指定は順不同）
NonNullList<Ingredient> ingredients = NonNullList.create();
ingredients.add(Ingredient.fromItem(Item.getItemFromBlock(Blocks.CACTUS)));     // サボテン
ingredients.add(Ingredient.fromItem(Items.CHORUS_FRUIT));                       // コーラスフルーツ
ingredients.add(Ingredient.fromItem(Items.CHORUS_FRUIT));                       // コーラスフルーツ
ingredients.add(Ingredient.fromItem(Items.WHEAT_SEEDS));                        // （小麦の）種

// クラフト成果品の設定
ItemStack output = new ItemStack(Item.getItemFromBlock(Blocks.CHORUS_FLOWER), 1); // コーラスフラワー
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/f697ba0f-e08d-686c-7c6f-9d00449a5e8e.png)

できあがったものをゲーム内で試してみると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/8a9b754a-4b44-4138-8761-1130efe2c7df.png)
無事成功しました。

<font color="gray">└模範解答終わり</font>
</details>

<font color="gray">└5. ブロックもクラフトに含む終わり</font>
</details>

<details><summary>6. レシピを複数登録する</summary>

現状、レシピを何種類も生み出しているのに、1つしか登録されていません。
それもそのはず、レシピを追加するコードは`MyMod.java`の中に1つしか書いていません。
今まではずっとその一つを使いまわしてきましたが、ついにレシピ追加コードを増殖させましょう。

最初のコードはこれでした。
```java: 不定形レシピのプログラム
        {
            //--------------------不定形レシピの追加--------------------

            // クラフト材料の設定（アイテムの指定は順不同）
            NonNullList<Ingredient> ingredients = NonNullList.create();
            ingredients.add(Ingredient.fromItem(Items.APPLE));      // リンゴ
            ingredients.add(Ingredient.fromItem(Items.GOLD_INGOT)); // 金インゴット

            // クラフト成果品の設定
            ItemStack output = new ItemStack(Items.GOLDEN_APPLE, 2); // 金リンゴ×2

            // レシピの作成
            ShapelessRecipes recipe = new ShapelessRecipes("", output, ingredients); // groupと成果品と材料からレシピ作成

            // レシピの登録
            recipe.setRegistryName(new ResourceLocation(Tags.MODID, "apple_plus_gold_ingot")); // 登録時の内部レシピ名指定
            event.getRegistry().register(recipe); // 登録
        }
```
これを`MyMod.java`に1回だけコピペしてきましたが、これを複数回コピペしてみましょう。

こんな感じにコピペします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/d3e0b787-6862-577d-6817-9858bbb0afc5.png)
2連続ペーストです。

中かっこがあるおかげで、2つそれぞれのまとまりが分かりやすくなっています。
何なら中かっこなので折り畳みも可能です。

<details><summary>1つ目だけ折り畳み</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/037bd0e1-bc78-bdca-49e5-44bcedbc39d7.png)

<font color="gray">└1つ目だけ折り畳み終わり</font>
</details>

<details><summary>2つ目だけ折り畳み</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/ea78f1c4-0d62-bb05-14fa-bae94936611e.png)

<font color="gray">└2つ目だけ折り畳み終わり</font>
</details>

<details><summary>両方折り畳み</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/665ad9b8-b64b-75cf-50e6-72f22b2e7ec9.png)

<font color="gray">└両方折り畳み終わり</font>
</details>

同じレシピを二重に登録しても意味は無いので、片方のレシピを変更しておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/ffca196c-db17-98f1-2036-02145cda053e.png)
2つ目のレシピの材料に金インゴットを1つ増やし、完成品の個数を3個に増やしました。

これでマイクラを起動して試してみましょう[^360]。

[^360]: この時点でエラーになりそうと思った方は賢い
特にどこがエラーになりそうかを言えたらそれはもう初心者ではない


あれ？
1つ目のレシピが正しく動きません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/46d0a370-79b7-d9c7-8a35-99e60fc3c8fe.png)

2つ目のレシピはちゃんと動いているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/3bd7b078-6684-1ddf-7f62-e3ab59301740.png)

どうやら2つ目のレシピを登録した段階で1つ目のレシピが上書きされてしまっているようです。
「残念だけど、レシピの複数登録は無理なのかなあ…」と諦めてはいけません。

レシピ登録部分のコードを抜粋します。
```java: レシピ登録部分抜粋
// レシピの登録
recipe.setRegistryName(new ResourceLocation(Tags.MODID, "apple_plus_gold_ingot")); // 登録時の内部レシピ名指定
event.getRegistry().register(recipe); // 登録
```

コメントを読むと、`登録時の内部レシピ名指定`と書かれています。
どうやらレシピに名前を付けているようです。
その名前は`apple_plus_gold_ingot`です[^361]。

[^361]: 厳密にはそれの頭にModIDを付けたもの
ModIDが付いているので同名のレシピが複数Modで登録されても大丈夫

2回コピペをし、材料や完成品を書き換えましたが、「レシピの名前」なるものを書き換えたことは一度もありません。

……もしかして同じ名前だと上書きしてしまうのでしょうか？


では名前を書き換えてみましょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/9fd0d009-deff-05df-4de2-b16234a9151f.png)
先ほどの変更に加えて、2つ目のレシピの名前を`apple_plus_2_gold_ingots`にしてみました。

これでマイクラを起動してみましょう。

1つ目のレシピがちゃんと動作しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/43132548-06ea-2706-bcb7-3c6cbd80df78.png)

そして2つ目のレシピも正しく動作しているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/6c9745a8-28be-77de-8112-c4b3a7346570.png)

つまり、
**レシピ名が重複すると上書きされる**
ことが分かりました[^362]。

[^362]: じゃあ別Modのレシピやバニラのレシピも上書きできるのか！？と思ったなら実際に試してみなさい
うまくやれば多分できるんじゃないかな
ただ実際のModdingでレシピを置き換えたいなと思ったときは、レシピの上書きよりも削除＋追加をやる方がオーソドックス

今回は2レシピしか登録しませんでしたが、3レシピ以上もコピペでどんどん増やせます。
ぜひ自分好みのレシピをたくさん登録してください。

<font color="gray">└6. レシピを複数登録する終わり</font>
</details>

<details><summary>要点まとめ</summary>

### 成果品の個数を変更する

`amount:`と出ている直後の数値を書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/82afd634-4a40-d354-9b59-f6f56dda0cac.png)

### 成果品を別アイテムにする

成果品設定の行の`Items.`の直後を書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/2ac31c30-79b5-145b-e86a-88d6f80987b5.png)
書ける候補は`Items.`の直後にキャレット（≒マウスカーソル）がある状態で`Ctrl+Space`を押すことで表示できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/13d22402-d34e-c3e7-de14-af6e4921dc64.png)

### 材料も別アイテムにする

材料設定の行の`Items.`の直後を書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/b176f726-0f1d-70bc-505b-67141fbb1401.png)

### 材料の種類数を変更する

```java: 材料品を設定する1行分
ingredients.add(Ingredient.fromItem(Items.ここはアイテムによって変える));
```
の行を材料の数だけ書きます。

### ブロックもクラフトに含む

材料や製作品を設定する部分の`Items.なんたら`の代わりに、
```java: ブロックを指定
Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)
```
を書きます。

### レシピを複数登録する

レシピ追加コードを全体丸ごとコピペして増やします。
ただし、レシピ名はユニーク（＝一意＝重複しない）になるように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/39da021f-1a1d-9c62-39ad-fc68af5f8982.png)


<font color="gray">└要点まとめ終わり</font>
</details>



# 4. 定形レシピもコピペして動かす

定形レシピもコピペで簡単に追加できます。
以下のコードをコピーしましょう。
```java: 3×3定形レシピの登録
{
    //--------------------定形レシピの追加--------------------

    // クラフト材料の設定
    // 3×3のクラフトグリッドのどの位置にアイテムを置くかを番号で示す
    // 0 1 2
    // 3 4 5
    // 6 7 8
    int width = 3;
    int height = 3;
    NonNullList<Ingredient> ingredients = NonNullList.withSize(width * height, Ingredient.EMPTY);
    ingredients.set(1, Ingredient.fromItem(Items.DIAMOND));     // ダイアモンド
    ingredients.set(3, Ingredient.fromItem(Items.IRON_INGOT));  // 鉄インゴット
    ingredients.set(4, Ingredient.fromItem(Items.ENDER_PEARL)); // エンダーパール
    ingredients.set(5, Ingredient.fromItem(Items.GOLD_INGOT));  // 金インゴット
    ingredients.set(7, Ingredient.fromItem(Items.EMERALD));     // エメラルド

    // クラフト成果品の設定
    ItemStack output = new ItemStack(Items.GHAST_TEAR, 4); // ガストの涙×4

    // レシピの作成
    ShapedRecipes recipe = new ShapedRecipes("", width, height, ingredients, output); // groupとクラフトグリッドの幅と高さと材料と成果品からレシピ作成

    // レシピの登録
    recipe.setRegistryName(new ResourceLocation(Tags.MODID, "craft_ghast_tear")); // 登録時の内部レシピ名指定
    event.getRegistry().register(recipe); // 登録
}
```

コピペした時の様子はこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/dacd936a-5e50-3780-2a67-d5c21b0be57a.png)

マイクラを起動して見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/187e6b59-12a5-e972-64c3-6d8f842e37e1.png)
レシピが登録されていますね。

定形レシピのため、並びが異なると作成はできません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/a998b685-97c7-a14b-267c-78aa9ab9aeba.png)

定形レシピ追加のコードについての詳細な解説はここでは行いません。
自分なりにアレンジを加えてみると良いでしょう。
この程度の変更ではPCやゲーム、データ等は壊れません。
~~そんな危ないこと好き勝手やらせるわけない~~

<details><summary>2×2定形レシピの例</summary>

```java: 2×2定形レシピの登録
{
    //--------------------定形レシピの追加--------------------

    // クラフト材料の設定
    // 2×2のクラフトグリッドのどの位置にアイテムを置くかを番号で示す
    // 0 1
    // 2 3
    int width = 2;
    int height = 2;
    NonNullList<Ingredient> ingredients = NonNullList.withSize(width * height, Ingredient.EMPTY);
    ingredients.set(0, Ingredient.fromItem(Item.getItemFromBlock(Blocks.COAL_BLOCK)));     // 石炭ブロック
    ingredients.set(2, Ingredient.fromItem(Items.STICK));                                  // 棒

    // クラフト成果品の設定
    ItemStack output = new ItemStack(Item.getItemFromBlock(Blocks.TORCH), 40); // 松明×40

    // レシピの作成
    ShapedRecipes recipe = new ShapedRecipes("", width, height, ingredients, output); // groupとクラフトグリッドの幅と高さと材料と成果品からレシピ作成

    // レシピの登録
    recipe.setRegistryName(new ResourceLocation(Tags.MODID, "torch_from_coal_block_and_stick")); // 登録時の内部レシピ名指定
    event.getRegistry().register(recipe); // 登録
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/559fc6d9-8d0e-8d4d-e65b-a91399a83180.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835470/95205909-830b-4ac4-d05d-0ec061bf05ad.png)

<font color="gray">└2×2定形レシピの例終わり</font>
</details>


# 5. 終わりに

初めてのModdingとプログラミングを体験していただきましたが、どうだったでしょうか。
プログラミングもModdingも「全てを理解しないとうまく動かせない」わけではありません。
何となく分かる部分をたくさんいじりながら、少しずつ分かる範囲を広げていってあげれば良いです。

自分のペースで頑張ってください。
Webページは逃げませんし、追い立てても来ません。


<details><summary>もっと簡潔なレシピ追加</summary>

実は、不定形レシピ[^500]を登録するだけなら1行で済みます。
```java: net.minecraftforge.fml.common.registry.GameRegistryのaddShapelessRecipeを使った例
GameRegistry.addShapelessRecipe(new ResourceLocation(Tags.MODID, "apple_plus_gold_ingot"), null, new ItemStack(Items.GOLDEN_APPLE, 2), Ingredient.fromItem(Items.APPLE), Ingredient.fromItem(Items.GOLD_INGOT));
```
[^500]: 定形レシピなら`GameRegistry.addShapedRecipe`を使う（材料の指定方法に注意）

レシピの登録方法が何となく分かってきた今でこそある程度このコードの意図を理解できますが、このコードが突然1行だけ出てきて「学んでください」と言われても難しいでしょう[^501]。

[^501]: 1行で書く場合、引数の順番と可変長な引数の説明も同時に行う必要がある上にコメントが書きづらいので説明には不向き
ローカル変数を使えば解決するが、配列のnew時の要素数指定の説明が必要になるのでやっぱり向かない

<font color="gray">└もっと簡潔なレシピ追加終わり</font>
</details>



---
[初心者研修編 - デバッグを実践するに続く](https://qiita.com/Katatsumuri_Pan/items/c5c04973e66a42451c63)

[メインページに戻る](https://qiita.com/Katatsumuri_Pan/items/e3fd7fec471ee66fa17a)