Skip to main content

config

Config Data Class

You must create a class that has fields for all the data you want to retrieve from your config file.

Your config data class must have a constructor with no parameters that initializes the default config values. The first time someone plays with your mod, these values will be written to a config file that they can edit for future use.

Even above 1.16, it can NOT be a record (the version of Gson shipped with Minecraft does not support them) or have any final fields. Since you need to have a no parameter constructor that sets default values anyway, the record limitation doesn't really add more code.. Json serialization will be handled automatically.

See Serialization for more information on what types of data are supported.

Adding Comments

If you use the @Comment("description") annotation on one of your fields, that text will be added as a comment above the field in the generated default config json (created when the file does not exist, the first time someone uses your mod).

Building a ConfigWrapper

ConfigWrapper has three initialization methods depending what side you want to read the config from. Each requires the data class that should be read from the config file.

  • ConfigWrapper.synced(ConfigData.class): Will be read from the world/serverconfig directory of the server then synced to all clients. Available on both sides.
  • ConfigWrapper.server(ConfigData.class): Will be read from the world/serverconfig directory of the server. Only available from the logical server.
  • ConfigWrapper.client(ConfigData.class): Will be read from the minecraft/config directory of the client. Only available from the logical client.

Each of these options returns a ConfigWrapper<ConfigData> that can be stored in a static variable. The methods described below are set up like a Builder so they can be chained.

File Location

  • You must call the ConfigWrapper#named method to set the name of the file to read config from.
  • The file name actually used for your config will include the logical side (from when you created the ConfigWrapper).
  • You can put your config file in a subdirectory of its normal location by calling ConfigWrapper#dir
  • If you call ConfigWrapper#named with a resource location, instead of a string, the path will be used as the file name and the namespace will be used for the subdirectory.
  • The file extension can be set by calling ConfigWrapper#ext (this does not actually change the data format!) but generally leaving it as the default (json5) is fine.

The file will be in [dir]/[name]-[side].[ext].

Lists & Maps

Calling ConfigWrapper#listOf will cause your config to load a list of your originally specified type instead of just one object. The config value will default to an empty list unless you call ConfigWrapper#setDefaultValue to change it.

Calling ConfigWrapper#mapOf will cause your config to load a map of strings to your originally specified type instead of just one object. The config value will default to an empty map unless you call ConfigWrapper#setDefaultValue to change it.

If you pass a class to ConfigWrapper#mapOf it will be used as the key type. The toString method of this class must preform the json serialization. The normal type adapter will not be called unless you use Gson#enableComplexMapSerialization (you can set the Gson instance to use with ConfigWrapper#withGson). Examples that work by default: String, UUID, ResourceLocation.

Config Loading

As long as your ConfigWrapper is constructed in time (ie. it is in your mod initializer class or its parent class gets class loaded during your mod initializer), the config values will automatically be loaded at a reasonable time with no extra work from you.

  • client configs can safely be retrieved at any time.
  • server or synced configs are loaded during ServerStartingEvent / ServerLifecycleEvents.SERVER_STARTING.
  • When a player joins a server, any synced configs will be sent their client.

If you try to read server or synced configs early, no MinecraftServer instance will be available, so it won't where to find the world folder. Default values will be returned and an error will be logged.

When a server or synced config loads but cannot find its file in world/serverconfig it checks in minecraft/defaultconfigs before generating the default file. This allows modpacks to ship their own default configs for your mods.

Reading Config Values

Simply call ConfigWrapper#get to retrieve an object of your data class with the values loaded from your config file.

Reloading

By default, server and synced configs will be reloaded when the /reload command is used (before data packs are reloaded). Synced configs are also resynced to all players. Note this does not update the previous config object, it creates a new one. So you should call ConfigWrapper#get every time you need it, in case the values have changed, instead of caching its result. If the changed config file cannot be parsed, it will be ignored and the old value will continue being used.

If you want to prevent a certain config from being reloaded, call ConfigWrapper#noReload during setup.

onLoad(Runnable)

Call this method during setup with a runnable to be called immediately after loading your config.

  • server or synced: when the server starts or when the /reload command is used
  • client: when the client starts

Simple Example

This creates an item that will deal a configurable amount of damage (item registration omitted).

// ExampleModMain.java
public static final Supplier<ExampleConfigData> CONFIG = ConfigWrapper.server(ExampleConfigData.class).named(MOD_ID);

// ExampleConfigData.java
public class ExampleConfigData {
public int needleDamage = 5;
}

// NeedleItem.java
@Override
public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
if (!target.level.isClientSide()) target.hurt(DamageSource.GENERIC, ExampleModMain.CONFIG.get().needleDamage);
}