SSCL Wiki

Example Project

This is a small example project showing how to use SSCL in your mod classes.

It covers a basic config, list values, reading values, changing values, reacting to changes, and using multiple config files.

ExampleMod.java

package com.example.mymod;

import net.fabricmc.api.ModInitializer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExampleMod implements ModInitializer {
	public static final String MOD_ID = "mymod";
	public static final Logger LOGGER =
			LoggerFactory.getLogger(MOD_ID);

	@Override
	public void onInitialize() {
		ExampleModConfig.initialize();

		LOGGER.info("MyMod initialized.");
	}
}

ExampleModConfig.java

package com.example.mymod;

import smilenotalive.sscl.SSCL;
import smilenotalive.sscl.config.BooleanValue;
import smilenotalive.sscl.config.Config;
import smilenotalive.sscl.config.ConfigCategory;
import smilenotalive.sscl.config.ConfigSide;
import smilenotalive.sscl.config.DoubleValue;
import smilenotalive.sscl.config.IntValue;
import smilenotalive.sscl.config.ListValue;

import java.util.List;

public final class ExampleModConfig {
	public static final Config CONFIG = SSCL.create(
			ExampleMod.MOD_ID,
			"mod-config.toml", // or like `MyMod/config.toml`
			ConfigSide.COMMON
	);

	public static final ConfigCategory GENERAL = CONFIG
			.category("general")
			.comment("General mod settings");

	public static final BooleanValue ENABLED = GENERAL
			.bool("enabled", true)
			.comment("Whether the mod is enabled")
			.tooltip(Component.translatable("mymod.config.enabled.tooltip"));

	public static final IntValue DISTANCE = GENERAL
			.intValue("distance", 8)
			.min(1)
			.max(32)
			.comment("Maximum working distance")
			.tooltip("Controls how far the mod can reach");

	public static final DoubleValue SCALE = GENERAL
			.doubleValue("scale", 1.0)
			.min(0.5)
			.max(2.0)
			.decimals(2)
			.comment("Interface scale")
			.tooltip(Component.translatable("mymod.config.scale.tooltip"));

	public static final ListValue<String> NAMES = GENERAL
			.stringList(
					"names",
					List.of("Steve", "Alex")
			)
			.comment("Names used by the mod")
			.tooltip("Names available to the feature");

	public static void initialize() {
	}

	private ExampleModConfig() {
	}
}

Translated Tooltips

SSCL supports Minecraft's translation system for tooltips. Instead of writing the tooltip text directly, you can reference a translation key:

.tooltip(Component.translatable("mymod.config.enabled.tooltip"))

Add the corresponding entry to src/main/resources/assets/mymod/lang/en_us.json:

{
    "mymod.config.enabled.tooltip": "Turns the mod on or off"
}

Replace mymod with your mod's actual namespace. You can add the same key to other language files to provide translations for more languages.

Normal string tooltips are still supported:

.tooltip("Turns the mod on or off")

Using the Values

The values can be accessed anywhere in the mod:

if (ExampleModConfig.ENABLED.get()) {
	int distance = ExampleModConfig.DISTANCE.get();
	double scale = ExampleModConfig.SCALE.get();
	List<String> names = ExampleModConfig.NAMES.get();
}

Changing Values

Values can be changed at runtime:

ExampleModConfig.ENABLED.set(false);
ExampleModConfig.DISTANCE.set(16);
ExampleModConfig.SCALE.set(1.25);

ExampleModConfig.NAMES.set(
		List.of("Steve", "Alex", "Herobrine")
);

Changes are held in memory until the config is saved.

ExampleModConfig.CONFIG.save();

Reacting to Changes

A mod can register a listener to react when a config value actually changes.

ExampleModConfig.ENABLED.onChange((oldValue, newValue) -> {
	ExampleMod.LOGGER.info(
			"Enabled changed: {} -> {}",
			oldValue,
			newValue
	);
});

The listener receives both the old and new values.

The listener is only called when the value changes. Setting the same value again does not trigger it.

ExampleModConfig.ENABLED.set(true);

If the value is already true, the listener is not called.

Change listeners also work with list values:

ExampleModConfig.NAMES.onChange((oldValue, newValue) -> {
	ExampleMod.LOGGER.info(
			"Names changed: {} -> {}",
			oldValue,
			newValue
	);
});

SSCL only reports the change. It does not perform networking or synchronization automatically. The mod decides what to do when a value changes.

Multiple Configs

A mod can use multiple independent config files.

For example:

public static final Config CLIENT_CONFIG = SSCL.create(
		ExampleMod.MOD_ID,
		"mod-config-client.toml", // or like `MyMod/client.toml`
		ConfigSide.CLIENT
);

public static final Config SERVER_CONFIG = SSCL.create(
		ExampleMod.MOD_ID,
		"mod-config-server.toml", // or like `MyMod/server.toml`
		ConfigSide.SERVER
);

This creates:

config/
├── mod-config-client.toml
└── mod-config-server.toml

Each config can have its own categories and values.

When a mod has multiple configs, SSCL displays them as separate tabs in Mod Menu:

Client | Server

A mod with only one config does not display the tab bar.

Resulting TOML

The basic example produces:

[general]

# General mod settings

# Whether the mod is enabled
enabled = true

# Maximum working distance
# Range: 1 - 32
distance = 8

# Interface scale
# Range: 0.5 - 2.0
scale = 1.0

# Names used by the mod
names = ["Steve", "Alex"]

The file is located at:

config/mod-config.toml