aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeConfigSpecMixin.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeConfigSpecMixin.java')
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeConfigSpecMixin.java160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeConfigSpecMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeConfigSpecMixin.java
new file mode 100644
index 0000000..288af26
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeConfigSpecMixin.java
@@ -0,0 +1,160 @@
+package com.anthonyhilyard.iceberg.mixin;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import com.anthonyhilyard.iceberg.util.DynamicSubconfig;
+import com.electronwill.nightconfig.core.CommentedConfig;
+import com.electronwill.nightconfig.core.UnmodifiableConfig;
+import com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction;
+import com.electronwill.nightconfig.core.ConfigSpec.CorrectionListener;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Overwrite;
+import org.spongepowered.asm.mixin.Shadow;
+
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.common.ForgeConfigSpec.ValueSpec;
+
+
+@Mixin(value = ForgeConfigSpec.class, remap = false)
+public class ForgeConfigSpecMixin
+{
+ @Shadow(remap = false)
+ private Map<List<String>, String> levelComments;
+
+ @Shadow(remap = false)
+ private boolean stringsMatchIgnoringNewlines(@Nullable Object obj1, @Nullable Object obj2) { return false; }
+
+ /**
+ * @author iceberg
+ * @reason Overwrite the correct method to fix subconfigs not being handled properly.
+ */
+ @Overwrite(remap = false)
+ private int correct(UnmodifiableConfig spec, CommentedConfig config, LinkedList<String> parentPath, List<String> parentPathUnmodifiable, CorrectionListener listener, CorrectionListener commentListener, boolean dryRun)
+ {
+ int count = 0;
+
+ Map<String, Object> specMap = spec.valueMap();
+ Map<String, Object> configMap = config.valueMap();
+
+ for (Map.Entry<String, Object> specEntry : specMap.entrySet())
+ {
+ final String key = specEntry.getKey();
+ Object specValue = specEntry.getValue();
+ final Object configValue = configMap.get(key);
+ final CorrectionAction action = configValue == null ? CorrectionAction.ADD : CorrectionAction.REPLACE;
+
+ parentPath.addLast(key);
+
+ String subConfigComment = null;
+
+ // If this value is a config, use that as the spec value to support subconfigs.
+ if (specValue instanceof ValueSpec valueSpec && valueSpec.getDefault() instanceof UnmodifiableConfig)
+ {
+ subConfigComment = valueSpec.getComment();
+ specValue = valueSpec.getDefault();
+ }
+
+ if (specValue instanceof UnmodifiableConfig)
+ {
+ if (configValue instanceof CommentedConfig)
+ {
+ count += correct((UnmodifiableConfig)specValue, (CommentedConfig)configValue, parentPath, parentPathUnmodifiable, listener, commentListener, dryRun);
+ if (count > 0 && dryRun)
+ {
+ return count;
+ }
+ }
+ else if (dryRun)
+ {
+ return 1;
+ }
+ else
+ {
+ CommentedConfig newValue = config.createSubConfig();
+ configMap.put(key, newValue);
+ listener.onCorrect(action, parentPathUnmodifiable, configValue, newValue);
+ count++;
+ count += correct((UnmodifiableConfig)specValue, newValue, parentPath, parentPathUnmodifiable, listener, commentListener, dryRun);
+ }
+
+ String newComment = subConfigComment == null ? levelComments.get(parentPath) : subConfigComment;
+ String oldComment = config.getComment(key);
+ if (!stringsMatchIgnoringNewlines(oldComment, newComment))
+ {
+ if (commentListener != null)
+ {
+ commentListener.onCorrect(action, parentPathUnmodifiable, oldComment, newComment);
+ }
+
+ if (dryRun)
+ {
+ return 1;
+ }
+
+ config.setComment(key, newComment);
+ }
+ }
+ else
+ {
+ ValueSpec valueSpec = (ValueSpec)specValue;
+ if (!valueSpec.test(configValue))
+ {
+ if (dryRun)
+ {
+ return 1;
+ }
+
+ Object newValue = valueSpec.correct(configValue);
+ configMap.put(key, newValue);
+ listener.onCorrect(action, parentPathUnmodifiable, configValue, newValue);
+ count++;
+ }
+ String oldComment = config.getComment(key);
+ if (!stringsMatchIgnoringNewlines(oldComment, valueSpec.getComment()))
+ {
+ if (commentListener != null)
+ {
+ commentListener.onCorrect(action, parentPathUnmodifiable, oldComment, valueSpec.getComment());
+ }
+
+ if (dryRun)
+ {
+ return 1;
+ }
+
+ config.setComment(key, valueSpec.getComment());
+ }
+ }
+
+ parentPath.removeLast();
+ }
+
+ // Second step: removes the unspecified values
+ for (Iterator<Map.Entry<String, Object>> ittr = configMap.entrySet().iterator(); ittr.hasNext();)
+ {
+ Map.Entry<String, Object> entry = ittr.next();
+
+ // If the spec is a dynamic subconfig, don't bother checking the spec since that's the point.
+ if (!(spec instanceof DynamicSubconfig) && !specMap.containsKey(entry.getKey()))
+ {
+ if (dryRun)
+ {
+ return 1;
+ }
+
+ ittr.remove();
+ parentPath.addLast(entry.getKey());
+ listener.onCorrect(CorrectionAction.REMOVE, parentPathUnmodifiable, entry.getValue(), null);
+ parentPath.removeLast();
+ count++;
+ }
+ }
+ return count;
+ }
+}