概要
TNT Moddersが作成した、MOD開発の始め方に関する解説です。Javaの基礎知識を前提とし、その解説は行っておりませんのでご了承ください。
準備から入門編までの各項目は、それまでのコードに追加する形になっており、「ビルド」まででMODを一つ完成させます。初級編以降の各項目は、入門編のコードを基準として追加を行います。
利用ライセンス
本開発講座は、本webページ上の他の記事と同様にTNT Moddersがすべての権利を留保しています。 但し、本開発講座上のコード部分のみ、ユーザーのMOD開発のために部分的に改変した上で組み込み、自由に利用することを許可します。
具体例
○本開発講座のコードをコピーし、実装したアイテムを自分のMODのものに置き換えた上で利用する
○本開発講座のコードを参考にし、自分のMODにエンティティを追加する処理を実装する
×本開発講座のテクスチャをそのまま利用し二次配布する
×本開発講座の内容を正当な引用ではなく無断で転載する
MODの開発は自己責任で行ってください。この講座により生じたいかなる損害についても、TNT Moddersは一切責任を負いません。
ページ一覧
2022年5月29日時点でのForge開発チームによるサポート対象は1.18.2と1.16.5です。最新の情報はForgeのフォーラムを確認してください。
1.18.2
入門編
1.16.5
入門編
初級編
1.16.4
入門編
初級編
1.14.4
入門編
1.12.2 (Forge 14.23.0.2491)
入門編
初級編
1.7.10 (Forge 10.13.4.1558)
1.7.10の環境構築はGradleで問題が発生しており、動作を確認できていません。詳しくは「環境構築 2 (1.7.10)」のコメント欄をご覧ください。
準備
入門編
初級編
中級編
上級編
解説の追加要望について
このページのコメント欄では追加要望を受け付けていますが、TNT Modders側の都合により断らせていただく場合があります。 また、要望を承った後、実際に追加するまで時間がかかる場合があります。 ご了承ください。
コメント欄
このページのコメント欄には、解説の追加要望や開発講座全体に関する意見などを投稿してください。個別の解説をご要望の際は、Minecraftのバージョンと求める動作の詳しい説明も記載してください。
解説ページのコメント欄には、それぞれの解説に関する質問などを投稿してください。また、解説の誤りや、より良い方法などがありましたら、お知らせください。
“MOD開発講座” への86件のフィードバック
またすいません。
(ctrl + H)での購読とは何でしょうか?
探しても出てきません。
残り時間とコメントアウトされているところに、WorldTickEventと書いたら
Ecpresion Exception とエラーが出てきてしまいました。
エラー内容を調べてみると。異例の処理と出てきました。
「Ctrl + H」はIntelliJ IDEAのショートカットで、この機能を使うと
Event
を継承しているクラスの一覧を表示できます。英語や日本語でヘルプがあるので確認してください。イベントの利用の解説記事もご覧ください。また、該当のコメント部分にはintで残り時間を入れてください。クラス名を入れるとJavaの文法が間違っていると表示されるはずです。
求める機能の実現にはもう少しJavaの基礎知識が必要になるでしょう。初心者向けに解説しているwebサイト(例:Let'sプログラミング)や動画、書籍などが豊富にあるので、特にクラスやオブジェクト、メソッドなどについて調べてください。
基礎をもう一回見直しながらやったら、
@SubscribeEvent
public void TickEvent(EntityPlayer player, World world, TickEvent.WorldTickEvent e){}
こうすればいいんじゃないかと思いました。
このEventをTickArmor外に配置して、TickEventの中に
world.setBlock(BPos.get(player.dimension),Blocks.air,3);
を書いて、TickEventが実行されるたびに、HashMap内に収納されている座標たちがairで置換されていくと思ったのですが、メソッドが解決しないと言われまして、
BPosがHashMapだからかなと思ってHashMapからintへの変換方法を探したら、
HashMapはオブジェクト型でintに変換するにはStringでvalueOfをしてHashMapをStringの文字列にして、Stringをintに変換するためにInteger.parseIntをしてあげるとできると書いてあったのですが、そのintをsetBlockの座標として書くとメソッドが解決しませんと出ます。
なので、System.out.printでBPosのintを出力してみたところ出力されませんでした。
出力されないのはTickArmorで繰り返しされているからだと思うんですけど、どうやったらTickArmor内に@SubscribeEvent
public void TickEvent(EntityPlayer player, World world, TickEvent.WorldTickEvent e){}
を入れられるのでしょうか?
そして、HashMapからどのようにしてint(座標)に変換すればよいのでしょうか?
教えて頂きたいです。
まず、
onArmorTick
メソッドはその種類の防具がプレイヤーに装備されている間しか呼ばれません。ブロックの破壊処理をこのメソッド内に書いてしまうと、防具が外されたらブロックが消えなくなってしまいます。そのため、ワールドが読み込まれている間は常に呼ばれるよう、TickEvent
を利用する必要があるのです。イベントの利用の記事で解説されているように、
@SubscribeEvent
がついていて引数がEvent
を継承したクラス一つのみのメソッドは、Forgeに登録することでイベントが発生したときに呼ばれるようになります。World
のインスタンスは引数のWorldTickEvent
から取得できるはずです。以前説明したように、World
からもディメンションIDを取得できるので、EntityPlayer
のインスタンスは必要ありません。BPos
はHashMap<Integer, HashMap<BlockPos, Integer>>
なので、BPos.get
によって返されるのはHashMap<BlockPos, Integer>
のインスタンスです。HashMap
とその使い方については調べてください。今回は座標と残り時間のそれぞれの組(Entry)について、値(Value)にあたる残り時間を減らし、0になったら対象座標のブロックを破壊するという処理を書きます。BlockPos
は三つのintで表現されるブロック座標をまとめて扱うためのクラスなので、x, y, z
を取得してsetBlock
に渡す必要があります。「メソッドが解決しない」など、IntelliJ IDEAで赤く警告表示されるのはコンパイルエラーです。カーソルを合わせると理由が表示されるので、今回は
setBlock
の引数が間違っているとわかるはずです。できれば英語を機械翻訳なども活用して読んでほしいのですが、日本語化も可能です。@SubScribeEventのTickEventはなんとかできました。
ですが、次の段階の
""BPosはHashMap<Integer, HashMap<BlockPos, Integer>>なので、BPos.getによって返されるのはHashMap<BlockPos, Integer>のインスタンスです。HashMapとその使い方については調べてください。今回は座標と残り時間のそれぞれの組(Entry)について、値(Value)にあたる残り時間を減らし、0になったら対象座標のブロックを破壊するという処理を書きます。BlockPosは三つのintで表現されるブロック座標をまとめて扱うためのクラスなので、x, y, zを取得してsetBlockに渡す必要があります。""
この部分が、わかりません。
HashMapの使い方は改めてみてわかりましたが、BPosからの(X・Y・Z)の取得方法がわかりません。
試したことは、
BlockPosのようなまとまったクラスからint値を抽出する方法を検索してみましたが、ヒットせず
BlockPosのjavaファイルを見ながらequalsやcopy()をやってみましたが駄目でした。
次に、BPosでequalsをBPos.equals(X)このようにして、書いてみてエラーが出ず実行してみたらfalseが出力されて、オブジェクト?がないと言われたと思います(プログラムの解釈)
BPos.get(null) //null
BPos.get(BPos) //null
BPos.get(map) //null
BPos.size //1
上記の4つも試してみましたが、座標らしきものは表示されず
唯一BPosだけで実行してみたところ、
@fffe797e=2
という出力され、16進数みたいだったので変換してみたら、絶対座標ではない桁の数が出てきました。
どのようにしたら、座標をBlockPosから抽出すればよいのでしょうか?
そもそも
HashMap
が何か理解できていますか? これもJavaの知識なので自分で詳しく調べてほしいのですが、HashMap<K, V>
は、それぞれのK
のインスタンス(鍵)に対応させてV
のインスタンス(値)を保持します。今回はディメンションごとに座標と残り時間を管理しなければならないので、外側のHashMap
であるBPos
の鍵はディメンションID、値はHashMap<BlockPos, Integer>
になっています。HashMap.get
とHashMap.put
の意味がわかったら、HashMap.entrySet
や、Javaのコレクション(今回はSet
)の使い方についても調べてみてください。次に進むためには、BlockPos
とInteger
の組(Entry)でループする操作が必要です。確認したところ、オファレンMODの
BlockPos
はHashMap
の鍵として使うには不完全でした。HashMap
の鍵には不変性が要求されるので、以下のようにBlockPos
とx, y, z
をfinal
にしてください。今回の変更の有無にかかわらず、x, y, z
はpublic
なメンバ変数なので、外部から直接アクセスできます。HashMapから座標取得は出来ました!
ですが次の課題で、その座標を保持してValueの2を減らしていて消す処理なんですが、まず座標保持からでHashMapのキーとvalueのキーの部分が座標でvalueが常に2になっています。
なので、座標が保持されません。
HashMapから出た座標をHashSetに入れて格納したのですが、次はHashSetからvalueを減少の2秒後の処理が調べてもわかりませんでした。
今のコードがどのような状態になっているのか、何をしようとしているのか、何を答えてほしいのかわかりません。MOD開発の知識や技術は私のできる限りお伝えしたいのですが、前提となるJavaの知識や技術が、実現したいことの難しさに対して足りていないように思います。
もし思うようにMOD開発が進まなかったら、一旦手を止めて、Javaの入門講座を一通り習ってみてはいかがでしょうか。以前紹介したようにJavaの解説は豊富にあるので、費用や媒体など自分にあった方法で、コードを書いてその意味を理解する練習をするとよいと思います。
すみません、アイテムの表示サイズの変更方法をご教授願えないでしょうか。
Minecraft1.7.10です
「アイテムの表示サイズの変更」とは具体的にどのような動作でしょうか。アイテムが表示される状況には、以下のようなものがあります。
これらのうち、通常のアイテムはGUIのみ2Dで、他は3Dで描画されます。
カスタムモデルを持ったアイテムを追加したいということであれば、オファレンMODのレーザーピストルが参考になると思います。他に求める動作と似た要素を持つMODがあれば、その実装を参考にしてください。
1.16.5でアイテムに鉱石辞書を登録したいのですがどうすれば良いでしょうか
"net.minecraftforge.oredict.OreDictionary"が存在しないので方法が分かりません
ご教授お願いします
1.16.5にはForgeの鉱石辞書APIがありません。代わりに、バニラのデータパックにあるタグシステムを使います。
Forgeのドキュメントにコード側での使い方や鉱石辞書からの移行について説明されているので、Minecraftの公式Wiki(日本語版)とともにご覧ください。
ありがとうございます