提供: Minecraft Modding Wiki
移動先: 案内検索

Configとは、ハードコーディングを避け利用者側で設定を変更する手段を提供するための機能である。
ここでは、Forgeによって提供されるConfig機能について説明する。

基本

旧来のConfig生成について解説する。

簡易的なサンプルを以下に示す。

package com.example.config;

import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.Mod;

@Mod(modid = ConfigSample.MODID, name = "ConfigSample", version = "1.0", acceptableRemoteVersions = "*")
public class ConfigSample {
    public static final String MODID = "config_sample";
    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        Configuration cfg = new Configuration(event.getSuggestedConfigurationFile());
        cfg.load();//コンフィグをロード
        /*ここでConfigの値の取得。*/
        cfg.save();//セーブ
    }
}

Configurationクラスを通してPropertyにアクセスすることで値を取得できる。
Propertyや値は各種getメソッドを利用して取得できるので場合に応じたメソッドを使えばよいだろう。
Configuration#loadでは非検査例外が投げられる可能性があるが、ファイル操作はこの時点で行われていないためハンドルする必要はない。(むしろハンドルすると中途半端に読み込まれ挙動がおかしくなる)
この方法ではConfigファイルは自由な場所に生成できるが、通常はFMLPreInitializationEvent#getSuggestedConfigurationFileを利用するのが良いだろう。

アノテーション利用

1.10.2-12.18.2.2103からConfigアノテーションが追加され、かつてあったModLoaderというModの機能の一つであるMLPropと同じ感覚でConfigシステムを利用することができるようになった。
すべてのプリミティブ型(とラッパークラス)、String、それらの配列、さらに付随してEnumとカテゴリーとして通常のクラスまで扱うことができる。
Configアノテーションが付与されたクラスごとにConfigファイルが生成される。

サンプル

Minecraft ForgeによるDebug用サンプルを改変したものを用いて示す。

コード

package com.example.config;

import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.Config.*;
import net.minecraftforge.fml.common.Mod;

@Mod(modid = ConfigSample.MODID, name = "ConfigSample", version = "1.0", acceptableRemoteVersions = "*")
public class ConfigSample {
    public static final String MODID = "config_sample";

    @Config(modid = MODID, type = Type.INSTANCE, name = MODID + "_types")
    public static class CONFIG_TYPES {
        public static boolean     bool = false;
        public static boolean[]   boolA = {false, true};
        public static Boolean     Bool = false;
        public static Boolean[]   BoolA = {false, true};
        public static float       flt = 1.0f;
        public static float[]     fltA = {1.0f, 2.0f};
        public static Float       Flt = 1.0f;
        public static Float[]     FltA = {1.0f, 2.0f};
        public static double      dbl = 1.0d;
        public static double[]    dblA = {1.0d, 2.0d};
        public static Double      Dbl = 1.0D;
        public static Double[]    DblA = {1.0D, 2.0D};
        public static byte        byt = 1;
        public static byte[]      bytA = {1, 2};
        public static Byte        Byt = 1;
        public static Byte[]      BytA = {1, 2};
        public static char        chr = 'a';
        public static char[]      chrA = {'a', 'b'};
        public static Character   Chr = 'A';
        public static Character[] ChrA = {'A', 'B'};
        public static short       srt = 1;
        public static short[]     srtA = {1, 2};
        public static Short       Srt = 1;
        public static Short[]     SrtA = {1, 2};
        public static int         int_ = 1;
        public static int[]       intA = {1, 2};
        public static Integer     Int = 1;
        public static Integer[]   IntA = {1, 2};
        public static String      Str = "STRING!";
        public static String[]    StrA = {"STR", "ING!"};
        public static TEST        enu = TEST.BIG;
        public static NestedType  Inner = new NestedType();

        public enum TEST { BIG, BAD, WOLF; }
        public static class NestedType {
            public String HeyLook = "I'm Inside!";
        }
    }
    
    @Config(modid = MODID)
    public static class CONFIG_ANNOTATIONS {
        @RangeDouble(min = -10.5, max = 100.5)
        public static double DoubleRange = 10.0;

        @RangeInt(min = -10, max = 100)
        public static double IntRange = 10;

        @LangKey("this.is.not.a.good.key")
        @Comment({"This is a really long", "Multi-line comment"})
        public static String Comments = "Hi Tv!";
    }
}

解説

@Config(modid = MODID, type = Type.INSTANCE, name = MODID + "_types")
public static class CONFIG_TYPES {
    public static boolean     bool = false;
    public static boolean[]   boolA = {false, true};
    public static Boolean     Bool = false;
    public static Boolean[]   BoolA = {false, true};
    public static float       flt = 1.0f;
    public static float[]     fltA = {1.0f, 2.0f};
    public static Float       Flt = 1.0f;
    public static Float[]     FltA = {1.0f, 2.0f};
    public static double      dbl = 1.0d;
    public static double[]    dblA = {1.0d, 2.0d};
    public static Double      Dbl = 1.0D;
    public static Double[]    DblA = {1.0D, 2.0D};
    public static byte        byt = 1;
    public static byte[]      bytA = {1, 2};
    public static Byte        Byt = 1;
    public static Byte[]      BytA = {1, 2};
    public static char        chr = 'a';
    public static char[]      chrA = {'a', 'b'};
    public static Character   Chr = 'A';
    public static Character[] ChrA = {'A', 'B'};
    public static short       srt = 1;
    public static short[]     srtA = {1, 2};
    public static Short       Srt = 1;
    public static Short[]     SrtA = {1, 2};
    public static int         int_ = 1;
    public static int[]       intA = {1, 2};
    public static Integer     Int = 1;
    public static Integer[]   IntA = {1, 2};
    public static String      Str = "STRING!";
    public static String[]    StrA = {"STR", "ING!"};
    public static TEST        enu = TEST.BIG;
    public static NestedType  Inner = new NestedType();
     public enum TEST { BIG, BAD, WOLF; }
    public static class NestedType {
        public String HeyLook = "I'm Inside!";
    }
}

Configにおいて扱えるすべての型である。
生成されるConfigファイルは以下の通り。

  • config_sample_types.cfg
# Configuration file

general {
    B:Bool=false
    B:BoolA <
        false
        true
     >
    I:Byt=1
    I:BytA <
        1
        2
     >
    I:Chr=65
    I:ChrA <
        65
        66
     >
    D:Dbl=1.0
    D:DblA <
        1.0
        2.0
     >
    D:Flt=1.0
    D:FltA <
        1.0
        2.0
     >
    I:Int=1
    I:IntA <
        1
        2
     >
    I:Srt=1
    I:SrtA <
        1
        2
     >
    S:Str=STRING!
    S:StrA <
        STR
        ING!
     >
    B:bool=false
    B:boolA <
        false
        true
     >
    I:byt=1
    I:bytA <
        1
        2
     >
    I:chr=97
    I:chrA <
        97
        98
     >
    D:dbl=1.0
    D:dblA <
        1.0
        2.0
     >
    S:enu=BIG
    D:flt=1.0
    D:fltA <
        1.0
        2.0
     >
    I:intA <
        1
        2
     >
    I:int_=1
    I:srt=1
    I:srtA <
        1
        2
     >

    inner {
        S:HeyLook=I'm Inside!
    }

}

Configアノテーションで指定したnameがそのままファイル名になっている。(nameを指定しない場合はModidとなる。)
各プロパティ名はフィールド名に基づいており、初期化時の値がConfigの既定値に設定される。
また、カテゴリ名に大文字を使用できないためInnerという名前のフィールドで生成されたカテゴリはinnerという名前となる。

@Config(modid = MODID)
public static class CONFIG_ANNOTATIONS {
    @RangeDouble(min = -10.5, max = 100.5)
    public static double DoubleRange = 10.0;

    @RangeInt(min = -10, max = 100)
    public static double IntRange = 10;

    @LangKey("this.is.not.a.good.key")
    @Comment({"This is a really long", "Multi-line comment"})
    public static String Comments = "Hi Tv!";
}

Configにさらなる付加情報を与えるために利用できるアノテーションの利用サンプルである。
RangeDouble/RangeIntアノテーションではdouble/int型のプロパティに対し範囲を定めることができ、コメントも添えられる。
LangKeyアノテーションでは、ConfigGUIで用いられるツールチップ等の翻訳キーを指定できる。ConfigGUIを利用しないのであれば必要ない。
Commentアノテーションでは、プロパティに添えるコメントを指定できる。
生成されるConfigファイルは以下の通り。

  • config_sample.cfg
# Configuration file

general {
    # This is a really long
    # Multi-line comment
    S:Comments=Hi Tv!

    # Min: -10.5
    # Max: 100.5
    D:DoubleRange=10.0

    # Min: -10
    # Max: 100
    D:IntRange=10.0
}

ConfigGUI利用

ModアノテーションのguiFactoryにおいてIModGuiFactory実装クラスを指定することで利用可能になる機能である。
Mod一覧の各ModのページからConfigGUIは開くことができる。
FMLConfigGuiFactoryがサンプルとなっているので参考にすると良いだろう。