feat: config migrations #7
7 changed files with 221 additions and 97 deletions
src/main/java/land/chipmunk/chipmunkmod
|
@ -1,5 +1,7 @@
|
|||
package land.chipmunk.chipmunkmod;
|
||||
|
||||
import land.chipmunk.chipmunkmod.config.ChipmunkModMigrations;
|
||||
import land.chipmunk.chipmunkmod.config.Configuration;
|
||||
import land.chipmunk.chipmunkmod.modules.KaboomCheck;
|
||||
import land.chipmunk.chipmunkmod.modules.SelfCare;
|
||||
import land.chipmunk.chipmunkmod.util.configurate.ConfigurateUtilities;
|
||||
|
@ -45,6 +47,7 @@ public class ChipmunkMod implements ModInitializer {
|
|||
}
|
||||
|
||||
public static Configuration loadConfig() throws IOException {
|
||||
final ChipmunkModMigrations migrations = new ChipmunkModMigrations();
|
||||
final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder()
|
||||
.defaultNamingScheme(NamingSchemes.CAMEL_CASE)
|
||||
.build();
|
||||
|
@ -61,14 +64,19 @@ public class ChipmunkMod implements ModInitializer {
|
|||
|
||||
// Configurate will create parent directories for us, so we don't need to do it
|
||||
final BasicConfigurationNode node = loader.load();
|
||||
final boolean isBlank = node.empty();
|
||||
if (node.empty()) { // Config empty, fill it with defaults
|
||||
final Configuration defaults = new Configuration();
|
||||
node.set(Configuration.class, defaults);
|
||||
migrations.setLatest(node);
|
||||
loader.save(node);
|
||||
|
||||
final Configuration config = node.get(Configuration.class);
|
||||
if (isBlank) {
|
||||
node.set(Configuration.class, config);
|
||||
return defaults;
|
||||
}
|
||||
|
||||
if (migrations.migrate(node)) { // Migrated, write new config
|
||||
loader.save(node);
|
||||
}
|
||||
|
||||
return config;
|
||||
return node.get(Configuration.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package land.chipmunk.chipmunkmod.config;
|
||||
|
||||
import land.chipmunk.chipmunkmod.config.migration.AbstractMigrationManager;
|
||||
import land.chipmunk.chipmunkmod.config.migrations.MigrationV0;
|
||||
|
||||
public final class ChipmunkModMigrations extends AbstractMigrationManager {
|
||||
public ChipmunkModMigrations() {
|
||||
super("version");
|
||||
|
||||
this.register(new MigrationV0()); // unversioned -> v0
|
||||
}
|
||||
}
|
|
@ -1,90 +1,89 @@
|
|||
package land.chipmunk.chipmunkmod;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class Configuration {
|
||||
public CommandManager commands = new CommandManager();
|
||||
public CommandCore core = new CommandCore();
|
||||
public Bots bots = new Bots();
|
||||
public CustomChat customChat = new CustomChat();
|
||||
public boolean fullbright = false; // unused, but it is here for old configs
|
||||
public String autoSkinUsername = "off";
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CommandManager {
|
||||
public String prefix = ".";
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CommandCore {
|
||||
public BlockBox relativeArea = BlockBox.create(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15));
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class Bots {
|
||||
public BotInfo hbot = new BotInfo("#", null);
|
||||
public BotInfo sbot = new BotInfo(":", null);
|
||||
public BotInfo chipmunk = new BotInfo("'", null);
|
||||
public ChomeNSBotInfo chomens = new ChomeNSBotInfo("*", null, null, null);
|
||||
public BotInfo fnfboyfriend = new BotInfo("~", null);
|
||||
public BotInfo nbot = new BotInfo("?", null);
|
||||
public BotInfo kittycorp = new BotInfo("^", null);
|
||||
public TestBotInfo testbot = new TestBotInfo("-", null);
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class ChomeNSBotInfo {
|
||||
public String prefix;
|
||||
public @Nullable String key;
|
||||
public @Nullable String authKey;
|
||||
public @Nullable String formatKey;
|
||||
|
||||
public ChomeNSBotInfo() {}
|
||||
public ChomeNSBotInfo (String prefix, @Nullable String key, @Nullable String authKey, @Nullable String formatKey) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
this.authKey = authKey;
|
||||
this.formatKey = formatKey;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class TestBotInfo {
|
||||
public String prefix;
|
||||
public @Nullable String webhookUrl;
|
||||
|
||||
public TestBotInfo() {}
|
||||
public TestBotInfo (String prefix, @Nullable String webhookUrl) {
|
||||
this.prefix = prefix;
|
||||
this.webhookUrl = webhookUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class BotInfo {
|
||||
public String prefix;
|
||||
public @Nullable String key;
|
||||
|
||||
public BotInfo() {}
|
||||
public BotInfo (String prefix, @Nullable String key) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CustomChat {
|
||||
public @NotNull Component format =
|
||||
Component.translatable("chat.type.text",
|
||||
Component.selector("UUID"),
|
||||
Component.empty()
|
||||
.append(Component.text("MESSAGE"))
|
||||
);
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.config;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class Configuration {
|
||||
public CommandManager commands = new CommandManager();
|
||||
public CommandCore core = new CommandCore();
|
||||
public Bots bots = new Bots();
|
||||
public CustomChat customChat = new CustomChat();
|
||||
public String autoSkinUsername = "off";
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CommandManager {
|
||||
public String prefix = ".";
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CommandCore {
|
||||
public BlockBox relativeArea = BlockBox.create(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15));
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class Bots {
|
||||
public BotInfo hbot = new BotInfo("#", null);
|
||||
public BotInfo sbot = new BotInfo(":", null);
|
||||
public BotInfo chipmunk = new BotInfo("'", null);
|
||||
public ChomeNSBotInfo chomens = new ChomeNSBotInfo("*", null, null, null);
|
||||
public BotInfo fnfboyfriend = new BotInfo("~", null);
|
||||
public BotInfo nbot = new BotInfo("?", null);
|
||||
public BotInfo kittycorp = new BotInfo("^", null);
|
||||
public TestBotInfo testbot = new TestBotInfo("-", null);
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class ChomeNSBotInfo {
|
||||
public String prefix;
|
||||
public @Nullable String key;
|
||||
public @Nullable String authKey;
|
||||
public @Nullable String formatKey;
|
||||
|
||||
public ChomeNSBotInfo() {}
|
||||
public ChomeNSBotInfo (String prefix, @Nullable String key, @Nullable String authKey, @Nullable String formatKey) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
this.authKey = authKey;
|
||||
this.formatKey = formatKey;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class TestBotInfo {
|
||||
public String prefix;
|
||||
public @Nullable String webhookUrl;
|
||||
|
||||
public TestBotInfo() {}
|
||||
public TestBotInfo (String prefix, @Nullable String webhookUrl) {
|
||||
this.prefix = prefix;
|
||||
this.webhookUrl = webhookUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class BotInfo {
|
||||
public String prefix;
|
||||
public @Nullable String key;
|
||||
|
||||
public BotInfo() {}
|
||||
public BotInfo (String prefix, @Nullable String key) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CustomChat {
|
||||
public @NotNull Component format =
|
||||
Component.translatable("chat.type.text",
|
||||
Component.selector("UUID"),
|
||||
Component.empty()
|
||||
.append(Component.text("MESSAGE"))
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package land.chipmunk.chipmunkmod.config.migration;
|
||||
|
||||
import land.chipmunk.chipmunkmod.ChipmunkMod;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
// Makes it easier for forks to add their own config versioning structure
|
||||
public abstract class AbstractMigrationManager {
|
||||
private final List<ConfigMigration> migrations = new ArrayList<>();
|
||||
private final Object[] versionKey;
|
||||
|
||||
public AbstractMigrationManager(final Object... versionKey) {
|
||||
this.versionKey = versionKey;
|
||||
}
|
||||
|
||||
protected void register(final ConfigMigration migration) {
|
||||
this.migrations.add(migration);
|
||||
}
|
||||
|
||||
protected void registerFrom(final int version, final Supplier<ConfigurationTransformation> supplier) {
|
||||
this.migrations.add(ConfigMigration.from(version, supplier));
|
||||
}
|
||||
|
||||
public ConfigurationTransformation.Versioned create() {
|
||||
final ConfigurationTransformation.VersionedBuilder builder = ConfigurationTransformation.versionedBuilder()
|
||||
.versionKey(versionKey);
|
||||
|
||||
this.migrations.forEach(migration -> builder.addVersion(migration.version(), migration.create()));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public <N extends ConfigurationNode> void setLatest(final N config) throws ConfigurateException {
|
||||
final ConfigurationTransformation.Versioned transforms = this.create();
|
||||
config.node(transforms.versionKey()).set(Integer.class, transforms.latestVersion());
|
||||
}
|
||||
|
||||
public <N extends ConfigurationNode> boolean migrate(final N config) throws ConfigurateException {
|
||||
final ConfigurationTransformation.Versioned transforms = this.create();
|
||||
final int version = transforms.version(config);
|
||||
|
||||
if (version > transforms.latestVersion()) {
|
||||
ChipmunkMod.LOGGER.warn("Latest config version is {}, but yours is {}! Are you from the future?",
|
||||
transforms.latestVersion(), version);
|
||||
return false;
|
||||
}
|
||||
|
||||
transforms.apply(config);
|
||||
|
||||
final int newVersion = transforms.version(config);
|
||||
if (version != newVersion) {
|
||||
ChipmunkMod.LOGGER.info("Migrated config from version {} to {}!", version, newVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package land.chipmunk.chipmunkmod.config.migration;
|
||||
|
||||
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface ConfigMigration {
|
||||
int version();
|
||||
|
||||
ConfigurationTransformation create();
|
||||
|
||||
static ConfigMigration from(final int version, final Supplier<ConfigurationTransformation> supplier) {
|
||||
return new ConfigMigrationImpl(version, supplier);
|
||||
}
|
||||
|
||||
record ConfigMigrationImpl(int version, Supplier<ConfigurationTransformation> supplier) implements ConfigMigration {
|
||||
@Override
|
||||
public ConfigurationTransformation create() {
|
||||
return this.supplier.get();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package land.chipmunk.chipmunkmod.config.migrations;
|
||||
|
||||
import land.chipmunk.chipmunkmod.config.migration.ConfigMigration;
|
||||
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
||||
import org.spongepowered.configurate.transformation.TransformAction;
|
||||
|
||||
import static org.spongepowered.configurate.NodePath.path;
|
||||
|
||||
public final class MigrationV0 implements ConfigMigration {
|
||||
@Override
|
||||
public int version() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationTransformation create() {
|
||||
return ConfigurationTransformation.builder()
|
||||
.addAction(path("fullbright"), TransformAction.remove())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -2,8 +2,7 @@ package land.chipmunk.chipmunkmod.util;
|
|||
|
||||
import com.mojang.brigadier.Command;
|
||||
import land.chipmunk.chipmunkmod.ChipmunkMod;
|
||||
import land.chipmunk.chipmunkmod.Configuration;
|
||||
import land.chipmunk.chipmunkmod.commands.SayCommand;
|
||||
import land.chipmunk.chipmunkmod.config.Configuration;
|
||||
import land.chipmunk.chipmunkmod.modules.Chat;
|
||||
import land.chipmunk.chipmunkmod.modules.CustomChat;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue