Skip to content

Baking Tricks

Endor H edited this page Dec 13, 2022 · 3 revisions

Besides automatically mapped backing fields in Java, and delegated properties in Kotlin, there are a few more things you can do to bake config values after any config modifications.

Baking transformation

You may use the baked method on any entry builder to specify a baking transformation. These transformations are restricted to the same type, and affect both backing fields and Kotlin properties.

@ConfigClass(modId=ExampleMod.MOD_ID, type=Type.CLIENT)
public class ClientConfig {
    @Bind private static SimpleConfigBuilder build(SimpleConfigBuilder builder) {
        return builder
           .add("str", string("").baked(s -> s.toLowerCase()))
           .add("speed", number(1F).bakeScale(1/20F));
    }

    // The capitalization used by players will be ignored
    //   so this field will always be lowercase
    @Bind public static String str;
    // Players will edit the entry in m/s, while this field
    //   will be automatically converted to m/tick
    @Bind public static float speed;
}

Float and double entries have a bakeScale method, useful if you want to prescale the baked value for the entry. For example, you could multiply time measures in seconds by 20 before baking them to use them in ticks from your code.

Secondary backing fields

In Java, you may use the methods addField or add_field on entries to bind another field with a transformed value, or even transform the main backing field. The Kotlin equivalent are baked properties

@ConfigClass(modId=ExampleMod.MOD_ID, type=Type.CLIENT)
public class ClientConfig {
    @Bind private static SimpleConfigBuilder build(SimpleConfigBuilder builder) {
        return builder
           .add("speed", number(1F).add_field("m_tick", f -> f / 20F);
    }

    // The speed as edited by players (m/s)
    @Bind public static float speed;
    // The speed in m/tick
    @Bind public static float speed_m_tick;
}

Baking methods

If you define a bake method in your config class (or override the bake method in Kotlin), you'll be able to perform your own baking actions every time the config is modified, like for example precomputing some values that depend on config entries.

@Group public static class Sound {
    @Group.Caption public static @Min(0) @Max(1) @Slider float master = 1F;
    @Entry public static @Min(0) @Max(1) @Slider float music;
    @Entry public static @Min(0) @Max(1) @Slider float effects;

    @Bind private static void bake() {
        music *= master;
        effects *= master;
    }
}

Kotlin API features

Baked properties

With the Kotlin API, you can also easily define baked properties with the baked delegate provider, which, similar to lazy, receives an initializer that computes the value of the entry, but this initializer is run after every config change (after all normal properties have been updated).

object ClientKonfig : SimpleKonfig(Type.CLIENT) {
    val int by number(0)
    // Will always be updated with double the value of `int`
    val doubledInt by baked { int * 2 }
}

Baking transformations

Similar to the baked method of builders, with the Kotlin API you can call transform on entries to provide a transforming function that may map it to a different type.

object ClientKonfig : SimpleKonfig(Type.CLIENT) {
    val float: Float by number(1) transform { it.toFloat() / 20 }
}

Clone this wiki locally