Skip to content

Commit

Permalink
add comments to configs
Browse files Browse the repository at this point in the history
  • Loading branch information
ToCraft committed Aug 31, 2024
1 parent b4fe2a4 commit a77f5b7
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 24 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
craftedcore 5.5
================
- merge configs to JSON5 format
- add comments to configs
- update to MixinExtras 0.4.1

craftedcore 5.4
================

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import tocraft.craftedcore.config.Config;
import tocraft.craftedcore.config.ConfigLoader;
import tocraft.craftedcore.config.annotions.Comment;

@SuppressWarnings("CanBeFinal")
public final class CraftedCoreConfig implements Config {
public static final CraftedCoreConfig INSTANCE = ConfigLoader.read(CraftedCore.MODID, CraftedCoreConfig.class);
public static final CraftedCoreConfig INSTANCE = ConfigLoader.register(CraftedCore.MODID);
@Comment("Toggle the version checking for every mod that uses CraftedCore")
public boolean enableVersionChecking = true;

@Override
Expand Down
9 changes: 1 addition & 8 deletions common/src/main/java/tocraft/craftedcore/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,11 @@
import tocraft.craftedcore.network.ModernNetworking;

import java.nio.file.Path;
import java.util.List;

@SuppressWarnings("unused")
public interface Config {
/**
* This should be overwritten to improve the performance and avoid errors
*/
@Nullable
default String getName() {
List<String> possibleNames = ConfigLoader.getConfigNames(this);
return !possibleNames.isEmpty() ? possibleNames.get(0) : null;
}
String getName();

@Nullable
default Path getPath() {
Expand Down
65 changes: 53 additions & 12 deletions common/src/main/java/tocraft/craftedcore/config/ConfigLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,31 @@
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import tocraft.craftedcore.CraftedCore;
import tocraft.craftedcore.config.annotions.Comment;
import tocraft.craftedcore.config.annotions.Synchronize;
import tocraft.craftedcore.event.client.ClientPlayerEvents;
import tocraft.craftedcore.network.ModernNetworking;
import tocraft.craftedcore.platform.PlatformData;
import tocraft.craftedcore.util.JsonUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

// heavily based on the work of Draylar - https://github.com/Draylar/omega-config/ and therefore this class is licensed under MIT
public class ConfigLoader {
public static final ResourceLocation CONFIG_SYNC = CraftedCore.id("config_sync");
private static final Map<String, Config> LOADED_CONFIGS = new HashMap<>();
private static final List<Config> CLIENT_CONFIGS = new ArrayList<>();
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final Gson SYNC_ONLY_GSON = new GsonBuilder().addSerializationExclusionStrategy(new SynchronizeStrategy()).setPrettyPrinting().create();
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().setLenient().create();
private static final Gson SYNC_ONLY_GSON = new GsonBuilder().addSerializationExclusionStrategy(new SynchronizeStrategy()).create();

@Environment(EnvType.CLIENT)
public static void registerConfigSyncHandler() {
Expand Down Expand Up @@ -61,12 +65,36 @@ public static void registerConfigSyncHandler() {
});
}

@SafeVarargs
public static <C extends Config> C register(String name, C... typeGetter) {
//noinspection unchecked
return read(name, (Class<C>) typeGetter.getClass().getComponentType());
}

public static <C extends Config> C read(String configName, Class<C> configClass) {
try {
Path configFile = getConfigPath(configName);

if (!Files.exists(configFile)) {
// Write & return a configuration file
// read old config file if exists
Path oldConfigFile = PlatformData.getConfigPath().resolve(configName + ".json");

if (Files.exists(oldConfigFile)) {
C oldConfig = GSON.fromJson(Files.readString(oldConfigFile), configClass);
// config was readable
if (oldConfig != null) {
// write to new config file
writeConfigFile(configFile, oldConfig);
// delete old config file
Files.delete(oldConfigFile);

LOADED_CONFIGS.put(configName, oldConfig);
return oldConfig;
}
}

// if this was reached, the old config couldn't be read
// Write & return a new configuration file
C config = configClass.getDeclaredConstructor().newInstance();
writeConfigFile(configFile, config);

Expand All @@ -78,7 +106,7 @@ public static <C extends Config> C read(String configName, Class<C> configClass)
// some files might be malfunctions
if (newConfig == null) {
newConfig = configClass.getDeclaredConstructor().newInstance();
CraftedCore.LOGGER.error("The Configuration '{}.json' is null. This isn't normal. It will overwritten be with default values.", configName);
CraftedCore.LOGGER.error("The Configuration '{}.json' is null. This isn't normal. It will be overwritten with default values.", configName);
}

// If the configuration existed, it's read now. This overrides it again to ensure every field is represented
Expand All @@ -89,17 +117,32 @@ public static <C extends Config> C read(String configName, Class<C> configClass)
}
} catch (Exception e) {
CraftedCore.LOGGER.error("Failed reading config {}", configName, e);
return null;
}
return null;
}

private static <C extends Config> void writeConfigFile(Path file, C config) {
String json = GSON.toJson(config);
Map<String, String> fieldToComments = new HashMap<>();

// map comments to the fields
for (Field field : config.getClass().getDeclaredFields()) {
for (Annotation annotation : field.getDeclaredAnnotations()) {
if (annotation instanceof Comment comment) {
fieldToComments.put(field.getName(), comment.value());
break;
}
}
}

String jsonWithComment = JsonUtils.addComments(json, fieldToComments);

try {
if (!Files.exists(file)) {
Files.createFile(file);
}

Files.writeString(file, GSON.toJson(config));
Files.writeString(file, jsonWithComment);
} catch (IOException e) {
CraftedCore.LOGGER.error("Failed saving config at {}", file, e);
}
Expand Down Expand Up @@ -191,16 +234,14 @@ public static Config getConfigByName(String configName) {
return LOADED_CONFIGS.get(configName);
}

@ApiStatus.Internal
@NotNull
public static Path getConfigPath(String configName) {
return Paths.get(PlatformData.getConfigPath().toString(), configName + ".json");
return PlatformData.getConfigPath().resolve(configName + ".json5");
}

@ApiStatus.Internal
public static <C extends Config> void writeConfigFile(C config) {
writeConfigFile(getConfigPath(config.getName()), config);
}

public static <C extends Config> List<String> getConfigNames(C config) {
return LOADED_CONFIGS.entrySet().stream().filter(entry -> entry.getValue().equals(config)).map(Map.Entry::getKey).toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package tocraft.craftedcore.config.annotions;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Comment {
String value() default "";
}
33 changes: 33 additions & 0 deletions common/src/main/java/tocraft/craftedcore/util/JsonUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package tocraft.craftedcore.util;

import java.util.*;

public class JsonUtils {
public static String addComments(String json, Map<String, String> keyToComment) {
List<String> lines = new ArrayList<>(json.lines().toList());
Map<Integer, String> insertions = new TreeMap<>();
// write comments into new file
for (int i = 0; i < lines.size(); i++) {
String s = lines.get(i);
String indentation = " ".repeat(s.length() - s.trim().length());

for (Map.Entry<String, String> entry : keyToComment.entrySet()) {
String comment = entry.getValue();
if (s.trim().startsWith(String.format("\"%s\"", entry.getKey()))) {
if (comment.contains("\n")) {
comment = indentation + "// " + String.join(String.format("\n%s// ", indentation), comment.split("\n"));
} else {
comment = String.format("%s// %s", indentation, comment);
}
insertions.put(i + insertions.size(), comment);
break;
}
}
}

StringBuilder sb = new StringBuilder();
insertions.forEach(lines::add);
lines.forEach(s -> sb.append(String.format("%s%n", s)));
return sb.toString();
}
}
5 changes: 2 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
org.gradle.jvmargs=-Xmx4G
# Base Versions
minecraft=1.21
archives_base_name=craftedcore
mod_version=5.4
mod_version=5.5
artifact_type=release
maven_group=dev.tocraft
# Loader Versions
fabric_loader=0.15.11
mixinextras_version=0.4.0
mixinextras_version=0.4.1
# Upload data
curseforge_id=923377
modrinth_id=Dg7PHdkJ
Expand Down

0 comments on commit a77f5b7

Please sign in to comment.