0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-09-08

初心者研修編リンク

はじめに

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

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

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

今回の題材

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

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

目次

1. 準備

簡易目次

MyMod.javaを開く

まずはMyMod.javaを開きましょう。
プロジェクトビューからsrcmainjava>(前回の記事で決めたパッケージ)>MyModをたどって開きましょう。
image.png

赤線が引かれていたり、赤い文字が含まれている

6. Build Jarsを実行していない場合は下の画像のようにエラーが出てしまいますので、6. Build Jarsを実行してください。
image.png

└赤線が引かれていたり、赤い文字が含まれている終わり

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

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

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

開いたMyMod.javaの行番号をよく見てみると……変ですね、番号が跳んでいます。
image.png
これはIntellij IDEAの機能で、まとまった部分を1行に折り畳むということが行われています。

プロジェクトビューでも、フォルダの中身を展開する・畳むということができましたが、
image.png
これと同じことをテキストに対してもやったら便利じゃね!?ということでソースコードも部分的に折り畳むことができます。

では試しに3行目のソースコードを展開してみましょう。
行番号の右にある>(矢印)をクリックしてください。
image.png

わあ
image.png

閉じて見なかったことにしましょう。
折り畳んだときはとして表示される2んですね。
このまましばらく封印しておきましょうか。
image.png

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

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

.

..

...

....

.....
この隠し文字に良く気づきましたね…
......
まさかダークモードではないだろうな!?

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

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

簡易目次

33行目の折り畳みを開く

プログラムを書く場所は33行目にあるregisterRecipesというメソッド3の中です。
まずは33行目の左端の矢印からメソッドの中身を展開表示しておいてください。
image.png

以下のように34-35行目が表示されていればokです。
image.png

ソースコードをコピペ

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

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

            // クラフト材料の設定(アイテムの指定は順不同)
            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
クリックするだけで勝手にコピーされるので、後はIntellij IDEAの34行目にCtrl+Vしましょう。
マウスで範囲選択は結構面倒な上にミスりやすいので非推奨(n敗)。

以下のようになればOKです。
57行目と58行目で中かっこが2つもあるんだがええんか!?その状態でお願いします。おう分かったで~。
image.png

もし、エラー(赤文字)だらけ6の場合は、別の行をクリックすると自動で直るはずです。
image.png

直らん!

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

Intellijの設定を開きまして、

エディター一般自動インポートのページを開きます。
Javaという節の中にある貼り付け時にインポートを挿入常時にし、明確なインポートをオンザフライで追加するにチェックを入れてOKを押してください。
image.png

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

└直らん!終わり

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

説明とかいいから早く動かしたい!って人は先に実際に動かしてみるを実施しましょう。

全体

コピペしたコードをまじまじと見てみましょう。
image.png

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

実際に試した時のイメージ図
  • 39行目で閉じた場合
    image.png

  • 40行目で閉じた場合
    image.png

└実際に試した時のイメージ図終わり

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

さらにコードをまじまじと見ます。
image.png

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

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

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

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

例えば、45行目に着目してみましょう。

45行目のみ抜粋
ingredients.add(Ingredient.fromItem(Items.APPLE));      // リンゴ

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

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

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

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

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

先ほどは45行目だけピンポイントで何となく少しだけわかりましたが、今度はコメントを読んで全体の流れをつかんでみましょう。
image.png

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

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

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

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

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

まとめますと、

  • 全体は不定形レシピの追加処理

  • 処理は順に

    • クラフト材料の設定
    • クラフト成果品の設定
    • レシピの作成
    • レシピの登録

    の順でおこなっている様子

  • 「リンゴ」と「金インゴット」から「金リンゴ2つ」ができる不定形レシピがおそらく追加される

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

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

実際に動かしてみる

マイクラを起動してみましょう。
2. Run Clientを実行してください。
image.png

エラーになって起動できない

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

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

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

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

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

最初からやり直しはヤダ!!!!!

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

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) {
    }
}

└最初からやり直しはヤダ!!!!!終わり

└エラーになって起動できない終わり

新規ワールドを(もちろんクリエイティブで)作成して入ります。
謎のアイテムを持った状態でスポーンしますが捨てて良いです。
image.png

リンゴと金インゴット(と作業台11)を取り出し、クラフトしてみましょう。
image.png

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

不定形レシピなので、どのような置き方をしても金リンゴが作れます。
image.png

JEIでレシピを見る

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

インベントリ画面の右側でページ送りして(マウスホイールが楽)リンゴを探し、右クリックしましょう。
image.png

レシピがちゃんと登録されていますね!
不定形レシピなので、それを表すアイコン(クロス矢印)が付いています。
image.png

└JEIでレシピを見る終わり

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

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

1. 成果品の個数を変えてみる

成果品の設定を行っている49行目を見てみましょう。

MyMod.javaの49行目抜粋
ItemStack output = new ItemStack(Items.GOLDEN_APPLE, 2); // 金リンゴ×2

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

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

そうです、2が使われている唯一のここです。
image.png
(直前にamount:と書かれていますが、これはIntellij IDEAのお節介機能12で表示しているゴーストであり、この文字列が入力されているわけではありません13。)

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

実際の書き換え例

image.png

└実際の書き換え例終わり

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

ゲーム内でアイテムを作業台に置いてみると、見事に変化していることが分かります。
image.png

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

└1. 成果品の個数を変えてみる終わり

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

成果品の設定を行っている49行目をもう一度見てみます。

MyMod.javaの49行目抜粋
ItemStack output = new ItemStack(Items.GOLDEN_APPLE, 2); // 金リンゴ×2

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

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

そうです、GOLDEN_APPLEと書かれていたらそりゃもう、それです。
image.png

ここを自由に変更!と行きたいところですが、この部分14はルールに従って書く必要があります。
例えば、GOLDEN_APPLEではなく、GOLD_APPLEと書いたらどうなるか試してみます。
image.png
見事に赤字のエラーになっており、このままでは2. Run Clientも失敗します。

失敗してる図

image.png

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

└失敗してる図終わり

ちなみに小文字でもダメです。
image.png

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

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

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

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

まずはGOLDEN_APPLEを消します。
(この時Items.,が隣り合うはずです。消しすぎたらCtrl+Zで戻しましょう。)
image.png

次にItems.の直後にキャレット(≒マウスカーソル16)を置き、キーボードでCtrl+Space(Ctrlキーとスペースキー17)を押します。
すると、正しい書き方の候補がズラッと並びます。
image.png

後はマウスホイールでスクロールし、お目当てが見つかったらダブルクリックしてください。
image.png
(候補が多すぎて探すのが面倒な場合は、欲しい選択肢に含まれるアルファベット(ネザースターならNEなど)を追加で入力すると候補を絞れます。)

NETHER_STARと正しい書き方が自動入力されます。
image.png

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

後は保存してマイクラを起動して確かめてみましょう。
image.png

└2. 成果品を別アイテムにする終わり

3. 材料も別アイテムにする

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

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

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

そう、ここです。
image.png

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

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

ヒント集(ネザーウォート)
ヒント1

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

└ヒント1終わり

ヒント2

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

└ヒント2終わり

└ヒント集(ネザーウォート)終わり

ヒント集(砂糖)
ヒント1

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

└ヒント1終わり

ヒント2

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

└ヒント2終わり

└ヒント集(砂糖)終わり

ヒント集(クモの目)
ヒント1

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

└ヒント1終わり

ヒント2

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

└ヒント2終わり

└ヒント集(クモの目)終わり

模範解答

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

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

└模範解答終わり

できあがったものをゲーム内で試してみると…
image.png
無事成功しました。

└3. 材料も別アイテムにする終わり

4. 材料の種類数を変更する

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

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

材料の設定をする部分を抜き出しました。

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
新たに47行目が増えました。

この状態でマイクラを起動してみましょうか。
今までのレシピが使えなくなりました。
image.png

そして、リンゴ、金インゴット、金インゴットの新レシピが使えるようになっています。
(同じ材料が複数あっても直感通りに動作するんですね。)
image.png

今度は行を削ってみましょう。
リンゴの行だけ残しました。(金インゴットは元からレシピがあるので却下)
image.png

これでマイクラを起動しますと、リンゴ単体で金リンゴ2つに変身するチートすぎるレシピができあがりました。
image.png

まとめると、

ingredients.add(Ingredient.fromItem(Items.ここはアイテムによって変える));

を書いた行数だけ材料が設定されるということですね。

└4. 材料の種類数を変更する終わり

5. ブロックもクラフトに含む

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

そこでブロックも設定できるようにする方法を伝授します。
Items.なんたらの代わりに、

ブロックを指定
Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)

を書きます。
よく見るとItemsではなくItemに変わっています。
紛らわしいことこの上ないですが、そういうルールと決まっているので間違えないようにしましょう。(当然間違えるとエラーです。)

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

それでは実際にブロックも含めたレシピを登録してみましょう。
レシピの材料と成果品は、ブロックとアイテムを好きなように組み合わせられます。
例えば、金ブロックとダイアモンド3個ででダイアモンドブロックができる不定形レシピは、

金ブロック+ダイアモンド×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
エラーが出ている場合は、何かしらの記述ミスが発生しています。
Ctrl+Zするなりコードのコピペをし直すなりして画像通りの状態にしてください。

あとはマイクラを起動して確かめてみてください。
image.png

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

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

以下のような不定形レシピが登録できたら成功です。
image.png

ヒント集(サボテン)
ヒント1

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

└ヒント1終わり

ヒント2

サボテンはブロックです。
つまり、

Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)

の形で書く必要があるでしょう。
DIAMOND_BLOCKの部分を消し、Blocks.(ここにキャレット)の状態でCtrl+Spaceを押し、候補表示でそれっぽいものを探してみましょう。

└ヒント2終わり

ヒント3

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

└ヒント3終わり

└ヒント集(サボテン)終わり

ヒント集(コーラスフルーツ)
ヒント1

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

└ヒント1終わり

ヒント2

コーラスフルーツはアイテムです。
つまり、

Items.APPLE

の形で書く必要があるでしょう。
APPLEの部分を消し、Items.(ここにキャレット)の状態でCtrl+Spaceを押し、候補表示でそれっぽいものを探してみましょう。

└ヒント2終わり

ヒント3

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

└ヒント3終わり

└ヒント集(コーラスフルーツ)終わり

ヒント集(種)
ヒント1

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

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

└ヒント1終わり

ヒント2

種はアイテムです。
つまり、

Items.APPLE

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

└ヒント2終わり

ヒント3

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

└ヒント3終わり

└ヒント集(種)終わり

ヒント集(コーラスフラワー)
ヒント1

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

└ヒント1終わり

ヒント2

コーラスフラワーはブロックです。
つまり、

Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)

の形で書く必要があるでしょう。
DIAMOND_BLOCKの部分を消し、Blocks.(ここにキャレット)の状態でCtrl+Spaceを押し、候補表示でそれっぽいものを探してみましょう。

└ヒント2終わり

ヒント3

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

└ヒント3終わり

└ヒント集(コーラスフラワー)終わり

模範解答

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

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

できあがったものをゲーム内で試してみると…
image.png
無事成功しました。

└模範解答終わり

└5. ブロックもクラフトに含む終わり

6. レシピを複数登録する

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

最初のコードはこれでした。

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

            // クラフト材料の設定(アイテムの指定は順不同)
            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
2連続ペーストです。

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

1つ目だけ折り畳み

image.png

└1つ目だけ折り畳み終わり

2つ目だけ折り畳み

image.png

└2つ目だけ折り畳み終わり

両方折り畳み

image.png

└両方折り畳み終わり

同じレシピを二重に登録しても意味は無いので、片方のレシピを変更しておきましょう。
image.png
2つ目のレシピの材料に金インゴットを1つ増やし、完成品の個数を3個に増やしました。

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

あれ?
1つ目のレシピが正しく動きません。
image.png

2つ目のレシピはちゃんと動いているようです。
image.png

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

レシピ登録部分のコードを抜粋します。

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

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

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

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

では名前を書き換えてみましょうか。
image.png
先ほどの変更に加えて、2つ目のレシピの名前をapple_plus_2_gold_ingotsにしてみました。

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

1つ目のレシピがちゃんと動作しています。
image.png

そして2つ目のレシピも正しく動作しているようです。
image.png

つまり、
レシピ名が重複すると上書きされる
ことが分かりました20

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

└6. レシピを複数登録する終わり

要点まとめ

成果品の個数を変更する

amount:と出ている直後の数値を書き換えます。
image.png

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

成果品設定の行のItems.の直後を書き換えます。
image.png
書ける候補はItems.の直後にキャレット(≒マウスカーソル)がある状態でCtrl+Spaceを押すことで表示できます。
image.png

材料も別アイテムにする

材料設定の行のItems.の直後を書き換えます。
image.png

材料の種類数を変更する

材料品を設定する1行分
ingredients.add(Ingredient.fromItem(Items.ここはアイテムによって変える));

の行を材料の数だけ書きます。

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

材料や製作品を設定する部分のItems.なんたらの代わりに、

ブロックを指定
Item.getItemFromBlock(Blocks.DIAMOND_BLOCK)

を書きます。

レシピを複数登録する

レシピ追加コードを全体丸ごとコピペして増やします。
ただし、レシピ名はユニーク(=一意=重複しない)になるように設定します。
image.png

└要点まとめ終わり

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

定形レシピもコピペで簡単に追加できます。
以下のコードをコピーしましょう。

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

マイクラを起動して見てみます。
image.png
レシピが登録されていますね。

定形レシピのため、並びが異なると作成はできません。
image.png

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

2×2定形レシピの例
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

image.png

└2×2定形レシピの例終わり

5. 終わりに

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

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

もっと簡潔なレシピ追加

実は、不定形レシピ21を登録するだけなら1行で済みます。

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));

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

└もっと簡潔なレシピ追加終わり


初心者研修編 - デバッグを実践するに続く

メインページに戻る

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

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

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

  4. 波かっことも呼ぶし、IT系ならそっちの方が多いかも

  5. 大嘘だが、初心者にとってはこのくらい端的な方がありがたい
    #includeってどういう意味なんですか?」

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

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

  8. 記憶とは諸行無常である

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

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

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

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

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

  14. この部分はItemsクラスのstaticフィールドである

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

  16. マウスカーソルはマウスの位置であり、キャレットはテキストの入力位置(点滅する|)を指す

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

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

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

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

  21. 定形レシピならGameRegistry.addShapedRecipeを使う(材料の指定方法に注意)

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

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?