Skip to content

How To Use

CrazedAerialCable edited this page Jan 20, 2024 · 5 revisions

3 main classes you should be concerned about.

  • ConfigObj, which you use to read and recreate config of a single item. This will contain the config data for your item.
  • ConfigObjAdapterConfig, which is a necessary evil used by Gson. :p
  • ItemFigApi, which you use to register config objects and their adapters configs, then read data using them.

ConfigObj

Start by extending the ConfigObj class. It is advised to use the class types here that start with upper case letter (i.e. Float, Int, etc.) as these can be checked against null values. Start with defining what values will you be configuring. An example of values for weapons in Weaponworks can be seen below:

public abstract class WeaponConfigObj extends ConfigObj {
    public String tier;
    public Integer damage;
    /**Attack speed*/
    public Float speed;
    public Boolean fire_resistant;
    public Integer durability;
}

Next is overrides. If you are using a good IDE, it should tell you to:

  • override chkDefaultValues() method inside your newly created config class. This is where you assign default values in case the config did not have them. An example from Weaponworks:
    //Inside WeaponConfigObj class
    //...
    @Override
    public void chkDefaultValues() {
        if(damage == null){
            damage = getDefaultDamage();
        }
        //...
    }
    protected abstract String getDefaultDamage();
    //...
  • create base constructor. It will be used for reading values from json and has to take in the exact type of your item, just like its ID (the same you use in MC). Example:
    //Inside WeaponConfigObj class
    //...
    public WeaponConfigObj(Type myType, String myID) {
        super(myType, myID);
    }
  • in the end, start creating item representing config classes that extend your new config object. Additionally, you will need one more constructor here that accepts a single argument in form of a string. Another example from Weaponworks, starring the diamond spear config object:
    //Of course you can put more levels of polymorphism. In Weaponworks you will find
    //another level in form of SpearConfigObj class, here it is simplified.
    public class DiamondSpearConfigObj extends WeaponConfigObj {

    public DiamondSpearConfigObj(Type myType, String myID) {
        super(myType, myID);
    }
    //Note how the constructor below utilizes the type of above one. This is how ItemFig will recognize what type of item will be read.
    public DiamondSpearConfigObj(String myId){
        super(DiamondSpearConfigObj.class, myId);
    }

    @Override
    protected Integer getDefaultDamage() {
        return DIAMOND_SPEAR_DEFAULT_DMG;
    }
    //...
}

And that is pretty much it in terms of config objects themselves.

ConfigObjAdapterConfig

This is what Gson is forcing to use, we have to comply. Do not worry, it will be mostly copy-paste and change 4 places.

Akin to ConfigObj case, you need to create main adapter config class that extends ConfigObjAdapterConfig. Starring, yet again, the Diamond Spear from Weaponworks:

public abstract class WeaponConfigObjAdapterConfig<T extends WeaponConfigObj> extends ConfigObjAdapterConfig<T> {

}

In above example we tell ItemFig we will be using WeaponConfigObj type that we declared earlier as the main config object.

Next, create the proper adapter config class for your item. Like here:

    //We are using the DiamondSpearConfigObj type that extends WeaponConfigObj type.
    public class DiamondSpearObjAdapterConfig extends WeaponConfigObjAdapterConfig<DiamondSpearConfigObj> {
    @Override
    public Class getConfigObjClass() {
        return DiamondSpearConfigObj.class; //Note the type! It will change for different items.
    }
    //As name implies, we are retrieving the mentioned before single string argumented constructor to be able to recreate the config object dynamically. Note the class type in brackets!
    @Override
    public Constructor<DiamondSpearConfigObj> getConstructorForDeserialization() throws NoSuchMethodException {
        return DiamondSpearConfigObj.class.getConstructor(String.class); //Note the type! It will change for different items.
    }
}

Pretty much, DiamondSpearConfigObj will change between adapter configs to types of config objects they concern. A necessary evil of bloat code. And that's it. Adapter config created.

ItemFigApi

Configuration

Once you have created the config objects and adapter configs that describe them, it is time to register these in ItemFig. Each adapter config has to be registered together with the config object it concerns. You can register the pairs either one by one with the ItemFigApi.registerObject() method or in bulk, using ItemFigApi.registerObjects() method. An example from Weaponworks can be seen below where the first case is used:

    private static void registerConfigObj(ObjectAdaptersConfigsFactory adapterConfigFactory, ConfigObjectFactory configObjFactory, WeaponTypesEnum weaponType, Tiers tier) throws Exception {
    //The factories accept the weapon type (for example spear) and their material tier as arguments, then spit out 
    //corresponding object that fits the criteria. If you do not know what a factory is, I advise checking out this 
    //design pattern. It may come in handy here, especially if you want to configure a lot of items.
        var adapterConfig = adapterConfigFactory.createObjectAdapterConfig(weaponType, tier);
        var configObj = configObjFactory.createObjectConfig(weaponType, tier);

        ItemFigApi.registerObject(configObj, adapterConfig);
    }

After registering all your objects and their adapters, you can configure:

  • the name of the config file, using ItemFigApi.setConfigFileName() method (.json extension will be automatically added if not provided).
  • register warning and error messages handlers if you want to perform some additional actions using the registerSaveErrorHandler(), registerSaveWarningHandler(), registerReadErrorHandler() and registerReadWarningHandler() methods from ItemFigApi class. ItemFig will log such messages on its own though. Detailed descriptions on when which registered methods will be called can be found in the aforementioned registering methods' descriptions.

Read and write

In order to read (and write) a config you need to call the ItemFigApi.readConfig() method. Make sure to call it AFTER you configure everything.

    ItemFigApi.readConfig();

readConfig() does actually a bit more than just read.

  • if no config is present, it will recreate it using default values you provided in config objects hierarchy. The same applies to single missing objects or even missing fields in the objects. This includes newly added config objects.
  • it will, of course, read values from present config.

After reading the contents, you can access them with methods ItemFigApi.getItemConfig() or ItemFigApi.<T>getItemConfigAutoCast(). You will have to cast it (or provide cast type in place of T in <T> for the latter case) to given proper object type yourself, but since it uses the item's ID to find it, you know what you will get from there.

That is all. From here, it is up to you what will you do with the retrieved config information.

Good luck and keep your feet on the ground! :j

Clone this wiki locally