MOD製作チュートリアル > Configの追加

概要

Forgeのシステムを利用してコンフィグ(Config, Configuration: 設定)を追加する。
FMLのコンフィグGUIを利用し、Minecraftを起動したままゲーム内で変更できるようにする。
「Mods」ボタンで表示されるリストからMODを選択し、左下の「Config」ボタンを押すことで画面を開くことができる。
また、コンフィグファイルはデフォルトでは".minecraft/config/AluminiumMod.cfg"に保存されるが、これを直接編集しても設定を変更できる。
(開発環境では"C:/forge/eclipse/config/AluminiumMod.cfg")

利用例がソースコード内で示されているが、ブロックやアイテムを追加していないため、コメントアウトを解除しただけでは動作しない。

Minecraft: 1.7.10
Forge: 10.13.4.1558
前提:MODの情報の登録

ソースコード

  • AluminiumMod.java
package tutorial.aluminiummod.common;
 
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Metadata;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import tutorial.aluminiummod.common.core.AluminiumModConfigCore;
import tutorial.aluminiummod.common.core.AluminiumModInfoCore;
import tutorial.aluminiummod.common.generator.AluminiumOreGenerator;
import tutorial.aluminiummod.common.handler.AluminiumModEventHandler;
 
@Mod(modid = AluminiumMod.MOD_ID, name = AluminiumMod.MOD_NAME, version = AluminiumMod.MOD_VERSION, guiFactory = "tutorial.aluminiummod.client.gui.AluminiumModGuiFactory")
public class AluminiumMod {
	public static final String MOD_ID = "AluminiumMod";
	public static final String MOD_NAME = "Aluminium Mod";
	public static final String MOD_VERSION = "1.0.0";
	@Metadata(MOD_ID)
	private static ModMetadata meta;
 
	@EventHandler
	public void perInit(FMLPreInitializationEvent event) {
		// MODの情報を登録する。
		AluminiumModInfoCore.registerInfo(meta);
		// コンフィグを読み込む。
		AluminiumModConfigCore.loadConfig(event);
		// ブロックやアイテムの追加はここで行う。
	}
 
	@EventHandler
	public void init(FMLInitializationEvent event) {
		// EventHandlerを登録する。
		FMLCommonHandler.instance().bus().register(new AluminiumModEventHandler());
		// 利用のサンプル。「レシピの追加」を参照。簡潔化のためこのチュートリアルではアルミニウム鉱石やアルミニウムインゴットは追加していない。
		// GameRegistry.addSmelting(AluminiumMod.oreAluminium, new ItemStack(AluminiumMod.ingotAluminium, AluminiumModConfigCore.amountSmelting), 0.7F);
		// 利用のサンプル。「鉱石の追加」を参照。
		GameRegistry.registerWorldGenerator(new AluminiumOreGenerator(), 0);
	}
}
 

  • AluminiumModGuiFactory.java
package tutorial.aluminiummod.client.gui;
 
import cpw.mods.fml.client.IModGuiFactory;
import cpw.mods.fml.client.config.GuiConfig;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.common.config.ConfigElement;
import tutorial.aluminiummod.common.AluminiumMod;
import tutorial.aluminiummod.common.core.AluminiumModConfigCore;
 
import java.util.Set;
 
public class AluminiumModGuiFactory implements IModGuiFactory {
	@Override
	public void initialize(Minecraft minecraftInstance) {
	}
 
	@Override
	public Class<? extends GuiScreen> mainConfigGuiClass() {
		return AluminiumModConfigGui.class;
	}
 
	@Override
	public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() {
		return null;
	}
 
	@Override
	public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) {
		return null;
	}
 
	public static class AluminiumModConfigGui extends GuiConfig {
		public AluminiumModConfigGui(GuiScreen parent) {
			super(parent, (new ConfigElement<Object>(AluminiumModConfigCore.cfg.getCategory(AluminiumModConfigCore.GENERAL))).getChildElements(), AluminiumMod.MOD_ID, false, false, AluminiumMod.MOD_NAME);
		}
	}
}
 

  • AluminiumModInfoCore.java
package tutorial.aluminiummod.common.core;
 
import cpw.mods.fml.common.ModMetadata;
import tutorial.aluminiummod.common.AluminiumMod;
 
public class AluminiumModInfoCore {
	public static void registerInfo(ModMetadata meta) {
		meta.modId = AluminiumMod.MOD_ID;
		meta.name = AluminiumMod.MOD_NAME;
		meta.description = "This mod adds Aluminium.";
		meta.version = AluminiumMod.MOD_VERSION;
		meta.url = "http://www.tntmodders.com";
		meta.authorList.add("Akasata Nahama");
		meta.authorList.add("Tom Kate");
		meta.credits = "";
		meta.logoFile = "assets/aluminiummod/logo.png";
		meta.autogenerated = false;
	}
}
 

  • AluminiumModConfigCore.java
package tutorial.aluminiummod.common.core;
 
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.common.config.Configuration;
import tutorial.aluminiummod.common.AluminiumMod;
 
public class AluminiumModConfigCore {
	public static final String GENERAL = "General";
	private static final String DIFFICULTY = GENERAL + ".Difficulty";
	public static Configuration cfg;
	public static boolean isGeneratorEnabled = true;
	public static byte amountSmelting = 1;
 
	public static void loadConfig(FMLPreInitializationEvent event) {
		// net.minecraftforge.common.config.Configurationのインスタンスを生成する。
		cfg = new Configuration(event.getSuggestedConfigurationFile(), AluminiumMod.MOD_VERSION, true);
		// 初期化する。
		initConfig();
		// コンフィグファイルの内容を変数と同期させる。
		syncConfig();
	}
 
	/** コンフィグを初期化する。 */
	private static void initConfig() {
		// カテゴリのコメントなどを設定する。
		// General
		cfg.addCustomCategoryComment(GENERAL, "A settings of Aluminium Mod.");
		cfg.setCategoryLanguageKey(GENERAL, "config.aluminium.category.general");
		// Difficulty
		cfg.addCustomCategoryComment(DIFFICULTY, "The settings of difficulty.");
		cfg.setCategoryLanguageKey(DIFFICULTY, "config.aluminium.category.difficulty");
		cfg.setCategoryRequiresMcRestart(DIFFICULTY, true);
	}
 
	/** コンフィグを同期する。 */
	public static void syncConfig() {
		// 各項目の設定値を反映させる。
		// General
		isGeneratorEnabled = cfg.getBoolean("enabledGenerator", GENERAL, isGeneratorEnabled, "Aluminium Ore will be generated when this setting is true.", "config.aluminium.prop.enabledGenerator");
		// Difficulty
		amountSmelting = (byte) cfg.getInt("amountSmelting", DIFFICULTY, amountSmelting, 1, Byte.MAX_VALUE, "Smelting amount of Aluminium Ingot from Aluminium Ore.", "config.aluminium.prop.amountSmelting");
		// 設定内容をコンフィグファイルに保存する。
		cfg.save();
	}
}
 

  • AluminiumModEventHandler.java
package tutorial.aluminiummod.common.handler;
 
import cpw.mods.fml.client.event.ConfigChangedEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import tutorial.aluminiummod.common.AluminiumMod;
import tutorial.aluminiummod.common.core.AluminiumModConfigCore;
 
public class AluminiumModEventHandler {
	@SubscribeEvent
	public void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent event) {
		// コンフィグが変更された時に呼ばれる。
		if (event.modID.equals(AluminiumMod.MOD_ID))
			AluminiumModConfigCore.syncConfig();
	}
}
 

  • AluminiumOreGenerator.java
package tutorial.aluminiummod.common.generator;
 
import cpw.mods.fml.common.IWorldGenerator;
import net.minecraft.world.World;
import net.minecraft.world.WorldProviderSurface;
import net.minecraft.world.chunk.IChunkProvider;
import tutorial.aluminiummod.common.core.AluminiumModConfigCore;
 
import java.util.Random;
 
public class AluminiumOreGenerator implements IWorldGenerator {
	@Override
	public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
		// コンフィグで有効化されていれば生成を行う。
		if (AluminiumModConfigCore.isGeneratorEnabled && world.provider instanceof WorldProviderSurface)
			generateOre(world, random, chunkX << 4, chunkZ << 4);
	}
 
	private void generateOre(World world, Random random, int x, int z) {
		for (int i = 0; i < 10; i++) {
			int genX = x + random.nextInt(16);
			int genY = 1 + random.nextInt(15);
			int genZ = z + random.nextInt(16);
			// サンプル。簡潔化のためこのチュートリアルではアルミニウム鉱石を追加していない。
			// new WorldGenMinable(AluminiumMod.oreAluminium, 0, 20, Blocks.stone).generate(world, random, genX, genY, genZ);
		}
	}
}
 

  • en_US.lang
// Config
config.aluminium.category.general=Localized General Category
config.aluminium.category.general.tooltip=Localized General Category Tooltip
config.aluminium.prop.enabledGenerator=Localized Generator Enabled
config.aluminium.prop.enabledGenerator.tooltip=Localized Generator Enabled Tooltip
config.aluminium.category.difficulty=Localized Difficulty Category
config.aluminium.category.difficulty.tooltip=Localized Difficulty Category Tooltip
config.aluminium.prop.amountSmelting=Localized Smelting Amount
config.aluminium.prop.amountSmelting.tooltip=Localized Smelting Amount Tooltip
 

  • ja_JP.lang
// コンフィグ
config.aluminium.category.general=全般
config.aluminium.category.general.tooltip=全般のツールチップ
config.aluminium.prop.enabledGenerator=鉱石生成の有効化
config.aluminium.prop.enabledGenerator.tooltip=鉱石生成の有効化のツールチップ
config.aluminium.category.difficulty=難易度
config.aluminium.category.difficulty.tooltip=難易度のツールチップ
config.aluminium.prop.amountSmelting=製錬量
config.aluminium.prop.amountSmelting.tooltip=製錬量のツールチップ
 

解説

AluminiumModConfigCore

void initConfig()

コンフィグを初期化するメソッド。
カテゴリの設定や説明文を変更する。

void syncConfig()

コンフィグを同期するメソッド。
AluminiumModConfigCoreの変数を更新し、cfgファイルを保存する。

AluminiumModEventHandler

指定したイベントが発生したとき、そのイベントを引数としたメソッドが呼び出される。
今回はFMLのシステムにのみ登録しているが、Forgeにも多くのイベントが用意されている。
チュートリアル「Eventの利用」は今後作成予定。

void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent event)

コンフィグGUIで項目が変更されたとき、Eventを受け取って呼び出される。
このMODのコンフィグGUIが更新されたなら、コンフィグを同期する。
コンフィグGUIのメイン画面で「Done」ボタンが押されたとき、変更があれば呼び出されている。

@Mod

このアノテーションを付けたクラスがFMLに認識される。

String guiFactory

MODのGuiFactoryを登録する。
IModGuiFactoryを継承したクラスのパスを渡す。

FMLPreInitializationEvent

preInitの引数で渡されている。

File getSuggestedConfigurationFile()

推奨されるコンフィグファイルのFile。
"(プロフィールフォルダ)/config/(modid).cfg"を返す。

Configuration

Forgeが用意しているクラス。
cfgファイルから読み込んだデータを保持し、操作を受け付ける。

コンストラクタ(File file, String configVersion, boolean caseSensitiveCustomCategories)

fileはcfgファイルの位置。(必須)
configVersionは読み込み時cfgファイルの冒頭に記載される文字列。(任意)
caseSensitiveCustomCategoriesをtrueにするとカテゴリ名に小文字が使える。falseだとすべて大文字になる。(任意、デフォルトfalse)

void addCustomCategoryComment(String category, String comment)

categoryのカテゴリコメントを指定する。
保存時に上書きされる。

Configuration setCategoryLanguageKey(String category, String langKey)

categoryの言語キーを指定する。
コンフィグGUIでの表示に利用される。

Configuration setCategoryRequiresMcRestart(String category, boolean requiresMcRestart)

category内の項目の変更を反映する際、Minecraftの再起動が必要かどうか設定する。
trueにすると、コンフィグGUIでのTooltipや変更時にメッセージが表示される。
setCategoryRequiresWorldRestartもある。

boolean getBoolean(String name, String category, boolean defaultValue, String comment, String langKey)

カテゴリ「category」内の項目名「name」で設定された値を取得する。
値が読み込まれていなかった場合(新規生成時など)はdefaultValueが返ってきて、保存時に新しくその値で生成される。
コメントは、保存時に「comment」に上書きされる。
langファイルで「langKey」の翻訳を指定しておくことで、コンフィグGUIで翻訳されて表示される。

int getInt(String name, String category, int defaultValue, int minValue, int maxValue, String comment, String langKey)

getBooleanのint版。
値はminValue以上maxValue以下で返ってくるが、cfgファイルでの設定値は上書きされない。
コンフィグGUIの設定変更では範囲に収まるように上書きされる。
boolean, intの他にfloat, String, String[]なども用意されている。

void save()

変更された設定を反映し、cfgファイルに保存する。

GuiConfig

コンフィグGUIのためのベースクラス。

コンストラクタ(GuiScreen parentScreen, List<IConfigElement> configElements, String modID, boolean allRequireWorldRestart, boolean allRequireMcRestart, String title)

configElementsはコンフィグの要素のリスト。
「allRequireWorldRestart」、「allRequireMcRestart」はtrueにするとTooltipにメッセージが追加される。
titleはGUI上部に表示されるタイトル文字列。

ConfigElement

Forgeのコメントには、「FMLのConfigGuiとForgeのConfigurationクラスの間の不一致を埋める」と書いてある。
総称型。

List<IConfigElement> getChildElements()

カテゴリ内の項目やカテゴリをリストにして返す。

EventBus

イベントとそのリスナーを管理するためのクラス。

void register(Object target)

イベントのリスナーを登録する。
targetのクラス内にある@SubscribeEventがつけられたメソッドが、その引数によって対応したイベントに紐づけられる。

使用例

オファレンMODの[1.7.10]2.0.0のソースコードを掲載予定です。
しばらくお待ちください。

コメント

この項目に関する質問などをどうぞ。
  • コンパイル時に、"ブートストラップ・クラスパスが-source 1.6と一緒に設定されていません"と出るのですがどうしたら良いのでしょうか? - mod初心者 2017-04-21 15:03:12
    • ちなみに上のはgradleの[compileJava, compileTestJava].eachのit.options.compilerArgs += ['-source', '1.7', '-target', '1.7']で直りましたけど、 - mod初心者 2017-04-21 15:26:51
    • 「入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。」が残ってます。上のは間違えました、['-source', '1.8', '-target', '1.8']です。 - mod初心者 2017-04-21 15:51:17
    • 言い直すと、build.gradleの[compileJava, compileTestJava].eachのit.options.compilerArgs += ['-source', '1.8', '-target', '1.8']で直りましたが、「入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。」が残ってます。 - mod初心者 2017-05-14 17:35:57
    • 返信が遅くなってしまい申し訳ありません。
      ビルドが成功しているなら、そのままでも動作はするはずです。
      今回の場合、ConfigElementが総称型であるためにAluminiumModConfigGuiのコンストラクタにある以下の部分で警告が出ているようです。
      :    (new ConfigElement(/* 略 */)).getChildElements()
      チュートリアルの該当部分を以下のように修正しましたので、ご確認ください。
      :    (new ConfigElement<Object>(/* 略 */)).getChildElements()
      同様の警告は、以下をbuild.gradle内に追記することで、詳細を表示できます。
      :    compileJava {options.compilerArgs += '-Xlint:unchecked'}
      また、"ブートストラップ・クラスパスが…"の警告は、ビルド時に指定されたJavaのバージョンとビルドに使用しているバージョンが違うために発生しているようです。 - 赤砂蛇凪浜 2017-05-17 17:12:16
      • 直りました!ありがとうございました! - Mod初心者 2017-05-18 18:32:47
        • メニュー画面のmodボタンを押しAluminiumModを選択すると、「disable」が赤くなります。 - mod初心者 2017-05-21 07:15:11
          • それは、FMLのMOD無効化ボタンです。
            MOD側が対応していないため赤くなるようです。
            @ModでcanBeDeactivatedをtrueにすると白くできます。
            しかし、FMLが機能を完成させておらず、利用できません。
            完成してもほとんどのMODが利用できないため、今後の更新も無いようです。 - 赤砂蛇凪浜 2017-05-24 14:18:02
            • そうなんですね。 - mod初心者 2017-05-24 15:14:13
            • 分かりました。 - mod初心者 2017-05-24 15:14:43
名前: