refactor: use configurate for config

This commit is contained in:
amyavi 2024-12-31 20:54:07 -03:00
parent 3c83eedd09
commit 1d09eab935
Signed by: amy
SSH key fingerprint: SHA256:CoLIqZWDYPZEhs1j1HQWwV0j1JhC3BFWcaUF7ZLZHJA
11 changed files with 252 additions and 209 deletions

View file

@ -16,13 +16,21 @@ dependencies {
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
// Fabric API
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// LuaJ
include(implementation("org.luaj:luaj-jse:3.0.1"))
// Configurate
include(implementation("org.spongepowered:configurate-core:4.1.2"))
include(implementation("org.spongepowered:configurate-gson:4.1.2"))
include(implementation("io.leangen.geantyref:geantyref:1.3.16"))
// Adventure
include(modImplementation("net.kyori:adventure-platform-fabric:6.2.0"))
include(implementation("net.kyori:adventure-text-serializer-gson:4.18.0"))
include(implementation("net.kyori:adventure-text-serializer-legacy:4.18.0"))
include(implementation("org.luaj:luaj-jse:3.0.1"))
}
processResources {

View file

@ -1,85 +1,74 @@
package land.chipmunk.chipmunkmod;
import com.google.gson.GsonBuilder;
import land.chipmunk.chipmunkmod.modules.KaboomCheck;
import land.chipmunk.chipmunkmod.modules.SelfCare;
import land.chipmunk.chipmunkmod.util.gson.BlockBoxTypeAdapter;
import land.chipmunk.chipmunkmod.util.gson.BlockPosTypeAdapter;
import land.chipmunk.chipmunkmod.util.configurate.ConfigurateUtilities;
import net.fabricmc.api.ModInitializer;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import net.fabricmc.loader.api.FabricLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.configurate.BasicConfigurationNode;
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
import org.spongepowered.configurate.objectmapping.ObjectMapper;
import org.spongepowered.configurate.util.NamingSchemes;
import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
public class ChipmunkMod implements ModInitializer {
// This logger is used to write text to the console and the log file.
// It is considered best practice to use your mod id as the logger's name.
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
public static Configuration CONFIG;
private static File CONFIG_DIR = new File("config");
private static File CONFIG_FILE = new File(CONFIG_DIR, "chipmunkmod.json");
private static final Path CONFIG_PATH = FabricLoader.getInstance()
.getConfigDir().resolve("chipmunkmod.json");
public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
public static Configuration CONFIG;
@Override
public void onInitialize () {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
try {
CONFIG = loadConfig();
} catch (IOException exception) {
throw new RuntimeException("Could not load the config", exception);
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
try {
CONFIG = loadConfig();
} catch (IOException exception) {
throw new RuntimeException("Could not load the config", exception);
}
KaboomCheck.INSTANCE.init();
SelfCare.INSTANCE.init();
LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
}
KaboomCheck.INSTANCE.init();
SelfCare.INSTANCE.init();
public static Configuration loadConfig() throws IOException {
final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder()
.defaultNamingScheme(NamingSchemes.CAMEL_CASE)
.build();
LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
}
final GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
.defaultOptions(options -> options
.serializers(build -> build
.registerAnnotatedObjects(customFactory)
.registerAll(ConfigurateUtilities.customSerializers()))
.shouldCopyDefaults(true))
.indent(4)
.path(CONFIG_PATH)
.build();
public static Configuration loadConfig () throws IOException {
CONFIG_DIR.mkdirs();
// 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();
final Gson gson = new GsonBuilder()
.registerTypeAdapter(BlockPos.class, new BlockPosTypeAdapter())
.registerTypeAdapter(BlockBox.class, new BlockBoxTypeAdapter())
.create();
final File file = CONFIG_FILE;
final Configuration config = node.get(Configuration.class);
if (isBlank) {
node.set(Configuration.class, config);
loader.save(node);
}
if (!file.exists()) {
InputStream is = ChipmunkMod.class.getClassLoader().getResourceAsStream("default_config.json");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
final StringBuilder sb = new StringBuilder();
while (reader.ready()) sb.append((char) reader.read());
final String defaultConfig = sb.toString();
// Write the default config
BufferedWriter configWriter = new BufferedWriter(new FileWriter(file));
configWriter.write(defaultConfig);
configWriter.close();
return gson.fromJson(defaultConfig, Configuration.class);
return config;
}
InputStream is = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
return gson.fromJson(reader, Configuration.class);
}
}

View file

@ -1,26 +1,32 @@
package land.chipmunk.chipmunkmod;
import com.google.gson.JsonObject;
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 = true; // unused, but it is here for old configs
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);
@ -32,13 +38,15 @@ public class Configuration {
public TestBotInfo testbot = new TestBotInfo("-", null);
}
@ConfigSerializable
public static class ChomeNSBotInfo {
public String prefix;
public String key;
public String authKey;
public String formatKey;
public @Nullable String key;
public @Nullable String authKey;
public @Nullable String formatKey;
public ChomeNSBotInfo (String prefix, String key, String authKey, 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;
@ -46,27 +54,35 @@ public class Configuration {
}
}
@ConfigSerializable
public static class TestBotInfo {
public String prefix;
public String webhookUrl;
public @Nullable String webhookUrl;
public TestBotInfo (String prefix, 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 String key;
public @Nullable String key;
public BotInfo (String prefix, String key) {
public BotInfo() {}
public BotInfo (String prefix, @Nullable String key) {
this.prefix = prefix;
this.key = key;
}
}
@ConfigSerializable
public static class CustomChat {
public JsonObject format;
public @NotNull Component format =
Component.translatable("chat.type.text",
Component.selector("UUID"),
Component.text("MESSAGE"));
}
}

View file

@ -1,7 +1,6 @@
package land.chipmunk.chipmunkmod.modules;
import com.google.common.hash.Hashing;
import com.google.gson.JsonElement;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import net.kyori.adventure.text.Component;
@ -17,6 +16,8 @@ import java.util.Timer;
import java.util.TimerTask;
public class CustomChat {
private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson();
private final MinecraftClient client;
public static final CustomChat INSTANCE = new CustomChat(MinecraftClient.getInstance());
@ -69,10 +70,7 @@ public class CustomChat {
}
public void reloadFormat () {
final JsonElement formatString = ChipmunkMod.CONFIG.customChat.format;
if (formatString == null) format = "{\"translate\":\"chat.type.text\",\"with\":[\"USERNAME\",\"MESSAGE\"]}";
else format = formatString.toString();
this.format = GSON.serializeToTree(ChipmunkMod.CONFIG.customChat.format).toString();
}
public void chat (String message) {

View file

@ -0,0 +1,40 @@
package land.chipmunk.chipmunkmod.util.configurate;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class BlockBoxTypeSerializer implements TypeSerializer<BlockBox> {
private static final String START = "start";
private static final String END = "end";
public static final BlockBoxTypeSerializer INSTANCE = new BlockBoxTypeSerializer();
private BlockBoxTypeSerializer() {
}
@Override
public BlockBox deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final BlockPos start = ConfigurateUtilities.getNodeOrThrow(source, START).require(BlockPos.class);
final BlockPos end = ConfigurateUtilities.getNodeOrThrow(source, END).require(BlockPos.class);
return BlockBox.create(start, end);
}
@Override
public void serialize(final Type type, final @Nullable BlockBox box,
final ConfigurationNode target) throws SerializationException {
if (box == null) {
target.raw(null);
return;
}
target.node(START).set(BlockPos.class, new BlockPos(box.getMinX(), box.getMinY(), box.getMinZ()));
target.node(END).set(BlockPos.class, new BlockPos(box.getMaxX(), box.getMaxY(), box.getMaxZ()));
}
}

View file

@ -0,0 +1,42 @@
package land.chipmunk.chipmunkmod.util.configurate;
import net.minecraft.util.math.BlockPos;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class BlockPosTypeSerializer implements TypeSerializer<BlockPos> {
private static final String X = "x";
private static final String Y = "y";
private static final String Z = "z";
public static final BlockPosTypeSerializer INSTANCE = new BlockPosTypeSerializer();
private BlockPosTypeSerializer() {
}
@Override
public BlockPos deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final int x = ConfigurateUtilities.getNodeOrThrow(source, X).getInt();
final int y = ConfigurateUtilities.getNodeOrThrow(source, Y).getInt();
final int z = ConfigurateUtilities.getNodeOrThrow(source, Z).getInt();
return new BlockPos(x, y, z);
}
@Override
public void serialize(final Type type, final @Nullable BlockPos pos,
final ConfigurationNode target) throws SerializationException {
if (pos == null) {
target.raw(null);
return;
}
target.node(X).set(pos.getX());
target.node(Y).set(pos.getY());
target.node(Z).set(pos.getZ());
}
}

View file

@ -0,0 +1,41 @@
package land.chipmunk.chipmunkmod.util.configurate;
import com.google.gson.JsonElement;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class ComponentTypeSerializer implements TypeSerializer<Component> {
private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson();
public static final ComponentTypeSerializer INSTANCE = new ComponentTypeSerializer();
private ComponentTypeSerializer() {
}
@Override
public Component deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final JsonElement elem = source.get(JsonElement.class);
if (elem == null) {
return null;
}
return GSON.deserializeFromTree(elem);
}
@Override
public void serialize(final Type type, final @Nullable Component component,
final ConfigurationNode target) throws SerializationException {
if (component == null) {
target.raw(null);
return;
}
final JsonElement elem = GSON.serializeToTree(component);
target.set(JsonElement.class, elem);
}
}

View file

@ -0,0 +1,35 @@
package land.chipmunk.chipmunkmod.util.configurate;
import net.kyori.adventure.text.Component;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializerCollection;
import java.util.Arrays;
public final class ConfigurateUtilities {
private static final TypeSerializerCollection CUSTOM_SERIALIZER_COLLECTION = TypeSerializerCollection.builder()
.registerAll(GsonConfigurationLoader.gsonSerializers())
.register(BlockPos.class, BlockPosTypeSerializer.INSTANCE)
.register(BlockBox.class, BlockBoxTypeSerializer.INSTANCE)
.register(Component.class, ComponentTypeSerializer.INSTANCE)
.build();
private ConfigurateUtilities() {
}
public static TypeSerializerCollection customSerializers() {
return CUSTOM_SERIALIZER_COLLECTION;
}
public static ConfigurationNode getNodeOrThrow(final ConfigurationNode source, final Object... path) throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException("Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
}

View file

@ -1,46 +0,0 @@
package land.chipmunk.chipmunkmod.util.gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import java.io.IOException;
public class BlockBoxTypeAdapter extends TypeAdapter<BlockBox> {
private final BlockPosTypeAdapter blockPosAdapter = new BlockPosTypeAdapter();
@Override
public BlockBox read(JsonReader reader) throws IOException {
BlockPos start = null;
BlockPos end = null;
reader.beginObject();
while (!reader.peek().equals(JsonToken.END_OBJECT)) {
if (reader.peek().equals(JsonToken.NAME)) {
String name = reader.nextName();
switch (name) {
case "start" -> start = blockPosAdapter.read(reader);
case "end" -> end = blockPosAdapter.read(reader);
default -> reader.skipValue();
}
}
}
reader.endObject();
if (start == null || end == null) return null;
return BlockBox.create(start, end);
}
@Override
public void write(JsonWriter writer, BlockBox box) {
// TODO
}
}

View file

@ -1,41 +0,0 @@
package land.chipmunk.chipmunkmod.util.gson;
import net.minecraft.util.math.BlockPos;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
public class BlockPosTypeAdapter extends TypeAdapter<BlockPos> {
@Override
public BlockPos read (JsonReader reader) throws IOException {
int x = 0;
int y = 0;
int z = 0;
reader.beginObject();
while (!reader.peek().equals(JsonToken.END_OBJECT)) {
if (reader.peek().equals(JsonToken.NAME)) {
String name = reader.nextName();
switch (name) {
case "x" -> x = reader.nextInt();
case "y" -> y = reader.nextInt();
case "z" -> z = reader.nextInt();
default -> reader.skipValue();
}
}
}
reader.endObject();
return new BlockPos(x, y, z);
}
@Override
public void write (JsonWriter out, BlockPos vec) throws IOException {
// TODO: make this do something lmfaooo
}
}

View file

@ -1,39 +0,0 @@
{
"commands": {
"prefix": "."
},
"core": {
"relativeArea": {
"start": { "x": 0, "y": 0, "z": 0 },
"end": { "x": 15, "y": 0, "z": 15 }
}
},
"bots": {
"hbot": { "prefix": "#", "key": null },
"sbot": { "prefix": ":", "key": null },
"chipmunk": { "prefix": "'", "key": null },
"chomens": { "prefix": "*", "key": null, "authKey": null, "formatKey": null },
"fnfboyfriend": { "prefix": "~", "key": null },
"nbot": { "prefix": "?", "key": null },
"kittycorp": { "prefix": "^", "key": null },
"testbot": { "prefix": "-", "webhookUrl": null }
},
"customChat": {
"format": {
"translate": "chat.type.text",
"with": [
{
"selector": "UUID"
},
{
"text": "MESSAGE"
}
]
}
},
"autoSkinUsername": "off"
}