MODのメイン部分を作る
ここで行うことは、メインクラス作成含め、MODの基幹部分のクラスを作ること。
メインクラスとは?
Forge環境でMODを作るためには、ひとつのMODIDにつき必ず1つだけ、メインクラスが必須です。
これは、追加したいアイテムやブロックのクラスをゲーム内に登場させるための"登録処理"にも必要です。追加したいアイテムやブロックのソースは、ただパッケージに同梱されているだけでは機能せず、所定の書式に従って、登録出来るメソッド内に登録の記述をしないとゲームには反映されません。
- メインクラス
- @Modアノテーションを含むクラスで、MODIDなどのMODの基本情報や、起動時のローディングイベントを含みます。
レシピ追加のみのようなごく小さいMODであればこのクラスだけでも機能しますが、このMODの場合は他にいくつかのクラスを追加します。 - プロキシ
- プロキシはサーバ側、クライアント側で別々の処理を行いたい場合に便利なシステムで、私は多用しています。
登録は、@SidedProxyアノテーションを用いてサーバー側・クライアント側それぞれメインクラス内でおこないます。
アイテムなどの追加物が出来るに従い、メイン部分にも記述が増えていきますので、 まずベース部分を作ります。
パッケージ構成を考える
プロキシ登録の際にパッケージの階層を決めておく必要があるので、ついでにここで大まかに決めておきます。
後で変更することも一応可能ですが、eclipse等の補助機能が無いとimport先の記述を手作業で直すハメになるので、少々辛くなります。
今回は、おおざっぱにクライアント系(描画関連やGUIが多い)とコモン系(クラサバ共通の登録処理)、
それからItemやEntityなどの各クラスのパッケージを分けることにしました。
パッケージ名は他と被らない方が都合が良いので、作者名とMODの固有名を入れて、
- defeatedcrow/flamethrower
- メインクラス等
- client
- ClientProxyクラス
- モデルやレンダーのクラス
- common
- CommonProxyのクラス
- entity
- エンティティのクラス
- item
- アイテムのクラス
パッケージはWindowsのエクスプローラ上で新規フォルダ作成の操作でも作れますが、eclipseの場合は、(たとえばソースを入れるフォルダを新規作成したい場合は、src/main/java以下の階層で)フォルダを作りたい階層を右クリック→「新規」→「パッケージ」でも作成できます。
メインクラス
基本の流れは、何かMODで作りたいクラスを作る→メインクラスで読み込むForgeのローディングイベント内で登録する、という流れです。
登録時には、要求されるクラスの構造や型を満たしておく必要があります。
たとえば、アイテムを登録するためには、登録するアイテムがItem.classを継承している必要がある、など。
今はまだ追加物用のクラスをつくっていませんので、骨組みだけ作ります。
- FlameCore.class
package defeatedcrow.flamethrower; import java.io.IOException; import net.minecraft.creativetab.CreativeTabs; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.Mod.Instance; import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import defeatedcrow.flamethrower.common.CommonProxyF; /* * @Modアノテーションです。 * MODのID、表示名、起動に必要な他MODなどを記述するところ。 */ @Mod(modid = "DCsFlame", name = "Flamethrower", version = "1.7.10_1.0a", dependencies = "required*after:Forge@[10.13.2.1291,)") public class FlameCore { // プロキシの登録 @SidedProxy(clientSide = "defeatedcrow.flamethrower.client.ClientProxyF", serverSide = "defeatedcrow.flamethrower.common.CommonProxyF") public static CommonProxyF proxy; // インスタンスの生成 // @InstanceのStringにはMODのIDを入れます。 @Instance("DCsFlame") public static FlameCore instance; /* Loggerクラス * 必須ではありませんが、エラー箇所の調査時など、一時的にコンソールログを出したいときに使用しています。 * たとえば、FlameCore.logger.info("ログの内容の文字列")のような形でログを出します。 */ public static Logger logger = LogManager.getLogger("Flamethrower"); @EventHandler public void preInit(FMLPreInitializationEvent event) { /* * FMLPreInitializationEventです。 * このメソッドをはじめとしたローディングイベントは、マインクラフトの起動時、Forgeによって所定のタイミングで呼ばれます。 * 実際どんなことが起きているかはコンソールログにでてくるので、 * 興味があればVersions/logsフォルダにあるfml*client*latest.logを眺めてみると良いです。 * * アイテムやブロックの登録などは、基本的にはここで行われます。 */ // conf Configuration cfg = new Configuration(event.getSuggestedConfigurationFile()); try { cfg.load(); /* * Configの項目の生成と読み込み。 * この段階では、まだ項目はありません。 */ } catch (Exception e) { e.printStackTrace(); } finally { cfg.save(); } // アイテムやブロックの登録はこのあたりで行う予定。 } @EventHandler public void init(FMLInitializationEvent event) throws IOException { /* * FMLInitializationEventです。全てのMODのPreInitの後、順にInitが呼ばれます。 * 私の場合、ここではEntity、TileEntity、Render関係、ForgeやFMLのイベント登録などを行っています。 * レシピもこのあたりで登録することが多いですが、このMODの場合は諸事情によりPostInitで登録します。 */ } @EventHandler public void postInit(FMLPostInitializationEvent event) { /* * FMLPostInitializationEventです。全てのMODのInitとIMCEventの後、順に呼ばれます。 * アイテムやブロックなど色々なMODの追加物が揃っていることが多いため、MOD間の連携要素の読み込みによく利用されます。 */ } }
プロキシクラス
今の段階では、特に何も使用されていません。アイテムやEntityを作成し、登録する段階で必要になります。
- CommonProxyF.class
package defeatedcrow.flamethrower.common; /* * CommonProxyはサーバ側で呼ばれるクラスです。 * Renderまわりの登録処理など、クライアント側で読み込まれて欲しくないものは、 * このプロキシを利用し、Common側のメソッドを空にしておくことでクライアント側に限定できます。 * * 今はまだ何も登録するものがないので空のクラスです。 */ public class CommonProxyF { }
- ClientProxyF.class
package defeatedcrow.flamethrower.client; import defeatedcrow.flamethrower.common.CommonProxyF; /* * Client側のプロキシです。 * CommonProxyF.classを継承させ、CommonProxyにあるメソッドをオーバーライドして内容を変えることで、 * クライアント限定の処理部分を作ります。 */ public class ClientProxyF extends CommonProxyF { }