Sfoglia il codice sorgente

Add global registry

Lortseam 4 anni fa
parent
commit
f9f8223251

+ 15 - 18
lib/src/main/java/me/lortseam/completeconfig/data/Config.java

@@ -1,5 +1,7 @@
 package me.lortseam.completeconfig.data;
 
+import lombok.AccessLevel;
+import lombok.Getter;
 import lombok.NonNull;
 import lombok.extern.log4j.Log4j2;
 import me.lortseam.completeconfig.api.ConfigContainer;
@@ -8,26 +10,23 @@ import me.lortseam.completeconfig.io.ConfigSource;
 import net.fabricmc.loader.api.FabricLoader;
 import net.fabricmc.loader.api.metadata.ModMetadata;
 
-import java.util.*;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Objects;
 
 @Log4j2(topic = "CompleteConfig")
 public final class Config extends BaseCollection {
 
-    private static final Map<String, Config> mainConfigs = new HashMap<>();
-    private static final Set<Config> saveOnExitConfigs = new HashSet<>();
-
     static {
         Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-            for (Config config : saveOnExitConfigs) {
-                config.save();
+            for (Config config : Registry.getConfigs()) {
+                if (config.saveOnExit) {
+                    config.save();
+                }
             }
         }));
     }
 
-    public static Map<String, Config> getMainConfigs() {
-        return Collections.unmodifiableMap(mainConfigs);
-    }
-
     /**
      * Creates a new config builder for the specified mod.
      *
@@ -40,11 +39,14 @@ public final class Config extends BaseCollection {
         return new Builder(modId);
     }
 
+    @Getter(AccessLevel.PACKAGE)
     private final ConfigSource source;
+    private final boolean saveOnExit;
 
-    private Config(ConfigSource source, ConfigContainer[] children) {
+    private Config(ConfigSource source, ConfigContainer[] children, boolean saveOnExit) {
         super(TranslationKey.from(source));
         this.source = source;
+        this.saveOnExit = saveOnExit;
         resolve(children);
     }
 
@@ -139,18 +141,13 @@ public final class Config extends BaseCollection {
         public Config build() {
             Config config = null;
             if (!children.isEmpty()) {
-                config = new Config(new ConfigSource(modId, branch), children.toArray(new ConfigContainer[0]));
+                config = new Config(new ConfigSource(modId, branch), children.toArray(new ConfigContainer[0]), saveOnExit);
             }
             if (config == null || config.isEmpty()) {
                 logger.warn("Empty config: " + modId + " " + Arrays.toString(branch));
                 return null;
             }
-            if (main || branch.length == 0 && !mainConfigs.containsKey(modId)) {
-                mainConfigs.put(modId, config);
-            }
-            if (saveOnExit) {
-                saveOnExitConfigs.add(config);
-            }
+            Registry.register(config, main || branch.length == 0 && !Registry.getMainConfig(modId).isPresent());
             config.load();
             return config;
         }

+ 7 - 42
lib/src/main/java/me/lortseam/completeconfig/data/Entry.java

@@ -1,6 +1,5 @@
 package me.lortseam.completeconfig.data;
 
-import com.google.common.collect.Lists;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.NonNull;
@@ -19,7 +18,6 @@ import me.lortseam.completeconfig.exception.IllegalAnnotationParameterException;
 import me.lortseam.completeconfig.extensions.CompleteConfigExtension;
 import me.lortseam.completeconfig.util.ReflectionUtils;
 import net.minecraft.text.Text;
-import net.minecraft.text.TextColor;
 import org.apache.commons.lang3.StringUtils;
 import org.spongepowered.configurate.CommentedConfigurationNode;
 import org.spongepowered.configurate.serialize.SerializationException;
@@ -29,8 +27,9 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.function.UnaryOperator;
 
 @Log4j2(topic = "CompleteConfig")
@@ -38,51 +37,17 @@ import java.util.function.UnaryOperator;
 public class Entry<T> implements DataPart, Identifiable {
 
     private static final Transformer DEFAULT_TRANSFORMER = Entry::new;
-    private static final List<Transformation> transformations = Lists.newArrayList(
-            Transformation.builder().byType(boolean.class, Boolean.class).byAnnotation(ConfigEntry.Boolean.class, true).transforms(BooleanEntry::new),
-            Transformation.builder().byType(int.class, Integer.class).byAnnotation(ConfigEntry.BoundedInteger.class).transforms(origin -> {
-                ConfigEntry.BoundedInteger bounds = origin.getAnnotation(ConfigEntry.BoundedInteger.class);
-                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
-            }),
-            Transformation.builder().byType(int.class, Integer.class).byAnnotation(Arrays.asList(ConfigEntry.BoundedInteger.class, ConfigEntry.Slider.class)).transforms(origin -> {
-                ConfigEntry.BoundedInteger bounds = origin.getAnnotation(ConfigEntry.BoundedInteger.class);
-                return new SliderEntry<>(origin, bounds.min(), bounds.max());
-            }),
-            Transformation.builder().byType(long.class, Long.class).byAnnotation(ConfigEntry.BoundedLong.class).transforms(origin -> {
-                ConfigEntry.BoundedLong bounds = origin.getAnnotation(ConfigEntry.BoundedLong.class);
-                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
-            }),
-            Transformation.builder().byType(long.class, Long.class).byAnnotation(Arrays.asList(ConfigEntry.BoundedLong.class, ConfigEntry.Slider.class)).transforms(origin -> {
-                ConfigEntry.BoundedLong bounds = origin.getAnnotation(ConfigEntry.BoundedLong.class);
-                return new SliderEntry<>(origin, bounds.min(), bounds.max());
-            }),
-            Transformation.builder().byType(float.class, Float.class).byAnnotation(ConfigEntry.BoundedFloat.class).transforms(origin -> {
-                ConfigEntry.BoundedFloat bounds = origin.getAnnotation(ConfigEntry.BoundedFloat.class);
-                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
-            }),
-            Transformation.builder().byType(double.class, Double.class).byAnnotation(ConfigEntry.BoundedDouble.class).transforms(origin -> {
-                ConfigEntry.BoundedDouble bounds = origin.getAnnotation(ConfigEntry.BoundedDouble.class);
-                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
-            }),
-            Transformation.builder().byType(type -> Enum.class.isAssignableFrom(ReflectionUtils.getTypeClass(type))).transforms(EnumEntry::new),
-            Transformation.builder().byType(type -> Enum.class.isAssignableFrom(ReflectionUtils.getTypeClass(type))).byAnnotation(ConfigEntry.Dropdown.class).transforms(DropdownEntry::new),
-            Transformation.builder().byAnnotation(ConfigEntry.Color.class).transforms(ColorEntry::new),
-            Transformation.builder().byType(TextColor.class).transforms(origin -> new ColorEntry<>(origin, false))
-    );
-    private static final Set<Entry> entries = new HashSet<>();
 
     static {
-        for (Collection<Transformation> transformations : CompleteConfig.collectExtensions(CompleteConfigExtension.class, CompleteConfigExtension::getTransformations)) {
-            Entry.transformations.addAll(transformations);
+        for (Transformation[] transformations : CompleteConfig.collectExtensions(CompleteConfigExtension.class, CompleteConfigExtension::getTransformations)) {
+            Registry.register(transformations);
         }
     }
 
     static Entry<?> of(Field field, ConfigContainer parentObject, TranslationKey parentTranslation) {
         EntryOrigin origin = new EntryOrigin(field, parentObject, parentTranslation);
-        Entry<?> entry = transformations.stream().filter(transformation -> transformation.test(origin)).findFirst().map(Transformation::getTransformer).orElse(DEFAULT_TRANSFORMER).transform(origin);
-        if (!entries.add(entry)) {
-            throw new UnsupportedOperationException(entry + " was already resolved");
-        }
+        Entry<?> entry = Registry.getTransformations().stream().filter(transformation -> transformation.test(origin)).findFirst().map(Transformation::getTransformer).orElse(DEFAULT_TRANSFORMER).transform(origin);
+        Registry.register(entry);
         return entry;
     }
 

+ 128 - 0
lib/src/main/java/me/lortseam/completeconfig/data/Registry.java

@@ -0,0 +1,128 @@
+package me.lortseam.completeconfig.data;
+
+import com.google.common.collect.Lists;
+import lombok.NonNull;
+import lombok.experimental.UtilityClass;
+import me.lortseam.completeconfig.api.ConfigEntry;
+import me.lortseam.completeconfig.data.entry.Transformation;
+import me.lortseam.completeconfig.gui.ConfigScreenBuilder;
+import me.lortseam.completeconfig.io.ConfigSource;
+import me.lortseam.completeconfig.util.ReflectionUtils;
+import net.minecraft.text.TextColor;
+
+import java.util.Collection;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@UtilityClass
+public final class Registry {
+
+    private static final Map<String, ModConfigSet> configs = new HashMap<>();
+    private static final Set<Entry> entries = new HashSet<>();
+    private static final List<Transformation> transformations = Lists.newArrayList(
+            Transformation.builder().byType(boolean.class, Boolean.class).byAnnotation(ConfigEntry.Boolean.class, true).transforms(BooleanEntry::new),
+            Transformation.builder().byType(int.class, Integer.class).byAnnotation(ConfigEntry.BoundedInteger.class).transforms(origin -> {
+                ConfigEntry.BoundedInteger bounds = origin.getAnnotation(ConfigEntry.BoundedInteger.class);
+                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
+            }),
+            Transformation.builder().byType(int.class, Integer.class).byAnnotation(Arrays.asList(ConfigEntry.BoundedInteger.class, ConfigEntry.Slider.class)).transforms(origin -> {
+                ConfigEntry.BoundedInteger bounds = origin.getAnnotation(ConfigEntry.BoundedInteger.class);
+                return new SliderEntry<>(origin, bounds.min(), bounds.max());
+            }),
+            Transformation.builder().byType(long.class, Long.class).byAnnotation(ConfigEntry.BoundedLong.class).transforms(origin -> {
+                ConfigEntry.BoundedLong bounds = origin.getAnnotation(ConfigEntry.BoundedLong.class);
+                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
+            }),
+            Transformation.builder().byType(long.class, Long.class).byAnnotation(Arrays.asList(ConfigEntry.BoundedLong.class, ConfigEntry.Slider.class)).transforms(origin -> {
+                ConfigEntry.BoundedLong bounds = origin.getAnnotation(ConfigEntry.BoundedLong.class);
+                return new SliderEntry<>(origin, bounds.min(), bounds.max());
+            }),
+            Transformation.builder().byType(float.class, Float.class).byAnnotation(ConfigEntry.BoundedFloat.class).transforms(origin -> {
+                ConfigEntry.BoundedFloat bounds = origin.getAnnotation(ConfigEntry.BoundedFloat.class);
+                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
+            }),
+            Transformation.builder().byType(double.class, Double.class).byAnnotation(ConfigEntry.BoundedDouble.class).transforms(origin -> {
+                ConfigEntry.BoundedDouble bounds = origin.getAnnotation(ConfigEntry.BoundedDouble.class);
+                return new BoundedEntry<>(origin, bounds.min(), bounds.max());
+            }),
+            Transformation.builder().byType(type -> Enum.class.isAssignableFrom(ReflectionUtils.getTypeClass(type))).transforms(EnumEntry::new),
+            Transformation.builder().byType(type -> Enum.class.isAssignableFrom(ReflectionUtils.getTypeClass(type))).byAnnotation(ConfigEntry.Dropdown.class).transforms(DropdownEntry::new),
+            Transformation.builder().byAnnotation(ConfigEntry.Color.class).transforms(ColorEntry::new),
+            Transformation.builder().byType(TextColor.class).transforms(origin -> new ColorEntry<>(origin, false))
+    );
+
+    static void register(Config config, boolean main) {
+        getConfigs(config.getMod().getId()).add(config, main);
+    }
+
+    static void register(Entry<?> entry) {
+        if (!entries.add(entry)) {
+            throw new UnsupportedOperationException(entry + " was already resolved");
+        }
+    }
+
+    static void register(Transformation... transformations) {
+        Registry.transformations.addAll(Arrays.asList(transformations));
+    }
+
+    /**
+     * Sets the main screen builder for a mod. The main screen builder will be used to build the config screen if no
+     * custom builder was specified.
+     *
+     * @param modId the mod's ID
+     * @param screenBuilder the screen builder
+     */
+    public static void register(@NonNull String modId, @NonNull ConfigScreenBuilder screenBuilder) {
+        getConfigs(modId).screenBuilder = screenBuilder;
+    }
+
+    public boolean hasSource(ConfigSource source) {
+        return getConfigs().stream().map(Config::getSource).collect(Collectors.toSet()).contains(source);
+    }
+
+    private static ModConfigSet getConfigs(String modId) {
+        return configs.computeIfAbsent(modId, key -> new ModConfigSet());
+    }
+
+    static Set<Config> getConfigs() {
+        return configs.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
+    }
+
+    public static Optional<Config> getMainConfig(String modId) {
+        return Optional.ofNullable(configs.get(modId)).map(modConfigs -> modConfigs.main);
+    }
+
+    public static Map<String, Config> getMainConfigs() {
+        return configs.keySet().stream().map(Registry::getMainConfig).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toMap(config -> {
+            return config.getMod().getId();
+        }, Function.identity()));
+    }
+
+    static List<Transformation> getTransformations() {
+        return Collections.unmodifiableList(transformations);
+    }
+
+    public static Optional<ConfigScreenBuilder> getScreenBuilder(String modId, ConfigScreenBuilder fallback) {
+        ConfigScreenBuilder screenBuilder = getConfigs(modId).screenBuilder;
+        if (screenBuilder != null) {
+            return Optional.of(screenBuilder);
+        }
+        return Optional.ofNullable(fallback);
+    }
+
+    private static class ModConfigSet extends HashSet<Config> {
+
+        private Config main;
+        private ConfigScreenBuilder screenBuilder;
+
+        private void add(Config config, boolean main) {
+            add(config);
+            if (main) {
+                this.main = config;
+            }
+        }
+
+    }
+
+}

+ 1 - 3
lib/src/main/java/me/lortseam/completeconfig/extensions/CompleteConfigExtension.java

@@ -3,15 +3,13 @@ package me.lortseam.completeconfig.extensions;
 import me.lortseam.completeconfig.data.entry.Transformation;
 import org.spongepowered.configurate.serialize.TypeSerializerCollection;
 
-import java.util.Collection;
-
 public interface CompleteConfigExtension extends Extension {
 
     default TypeSerializerCollection getTypeSerializers() {
         return null;
     }
 
-    default Collection<Transformation> getTransformations() {
+    default Transformation[] getTransformations() {
         return null;
     }
 

+ 1 - 3
lib/src/main/java/me/lortseam/completeconfig/extensions/GuiExtension.java

@@ -2,11 +2,9 @@ package me.lortseam.completeconfig.extensions;
 
 import me.lortseam.completeconfig.gui.cloth.GuiProvider;
 
-import java.util.Collection;
-
 public interface GuiExtension extends Extension {
 
-    default Collection<GuiProvider> getProviders() {
+    default GuiProvider[] getProviders() {
         return null;
     }
 

+ 3 - 5
lib/src/main/java/me/lortseam/completeconfig/extensions/clothbasicmath/ClothBasicMathExtension.java

@@ -1,6 +1,5 @@
 package me.lortseam.completeconfig.extensions.clothbasicmath;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
@@ -11,7 +10,6 @@ import me.lortseam.completeconfig.extensions.Extension;
 import me.shedaniel.math.Color;
 import org.spongepowered.configurate.serialize.TypeSerializerCollection;
 
-import java.util.Collection;
 import java.util.Set;
 
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
@@ -25,10 +23,10 @@ public final class ClothBasicMathExtension implements CompleteConfigExtension {
     }
 
     @Override
-    public Collection<Transformation> getTransformations() {
-        return ImmutableList.of(
+    public Transformation[] getTransformations() {
+        return new Transformation[] {
                 Transformation.builder().byType(Color.class).transforms(origin -> new ColorEntry<>(origin, true))
-        );
+        };
     }
 
     @Override

+ 5 - 6
lib/src/main/java/me/lortseam/completeconfig/extensions/clothbasicmath/ClothBasicMathGuiExtension.java

@@ -6,20 +6,19 @@ import me.lortseam.completeconfig.gui.cloth.GuiProvider;
 import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
 import me.shedaniel.math.Color;
 
-import java.util.Collection;
-import java.util.Collections;
-
 final class ClothBasicMathGuiExtension implements GuiExtension {
 
     @Override
-    public Collection<GuiProvider> getProviders() {
-        return Collections.singletonList(GuiProvider.create(ColorEntry.class, (ColorEntry<Color> entry) -> ConfigEntryBuilder.create()
+    public GuiProvider[] getProviders() {
+        return new GuiProvider[] {
+                GuiProvider.create(ColorEntry.class, (ColorEntry<Color> entry) -> ConfigEntryBuilder.create()
                         .startColorField(entry.getText(), entry.getValue())
                         .setAlphaMode(entry.isAlphaMode())
                         .setDefaultValue(entry.getDefaultValue().getColor())
                         .setTooltip(entry.getTooltip())
                         .setSaveConsumer2(entry::setValue),
-                Color.class));
+                        Color.class)
+        };
     }
 
 }

+ 1 - 25
lib/src/main/java/me/lortseam/completeconfig/gui/ConfigScreenBuilder.java

@@ -1,6 +1,5 @@
 package me.lortseam.completeconfig.gui;
 
-import lombok.NonNull;
 import me.lortseam.completeconfig.data.Config;
 import me.lortseam.completeconfig.gui.cloth.ClothConfigScreenBuilder;
 import net.fabricmc.api.EnvType;
@@ -8,32 +7,9 @@ import net.fabricmc.api.Environment;
 import net.fabricmc.loader.api.FabricLoader;
 import net.minecraft.client.gui.screen.Screen;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-
 public abstract class ConfigScreenBuilder {
 
-    private static final ConfigScreenBuilder fallback = FabricLoader.getInstance().isModLoaded("cloth-config2") ? new ClothConfigScreenBuilder() : null;
-    private static final Map<String, ConfigScreenBuilder> mainBuilders = new HashMap<>();
-
-    /**
-     * Sets the main screen builder for a mod. The main screen builder will be used to build the config screen if no
-     * custom builder was specified.
-     *
-     * @param modId the mod's ID
-     * @param screenBuilder the screen builder
-     */
-    public static void setMain(@NonNull String modId, @NonNull ConfigScreenBuilder screenBuilder) {
-        mainBuilders.put(modId, screenBuilder);
-    }
-
-    public static Optional<ConfigScreenBuilder> getMain(@NonNull String modId) {
-        if (mainBuilders.containsKey(modId)) {
-            return Optional.of(mainBuilders.get(modId));
-        }
-        return Optional.ofNullable(fallback);
-    }
+    public static final ConfigScreenBuilder FALLBACK = FabricLoader.getInstance().isModLoaded("cloth-config2") ? new ClothConfigScreenBuilder() : null;
 
     /**
      * Builds a screen based on a config.

+ 3 - 2
lib/src/main/java/me/lortseam/completeconfig/gui/ModMenuIntegration.java

@@ -3,6 +3,7 @@ package me.lortseam.completeconfig.gui;
 import com.terraformersmc.modmenu.api.ConfigScreenFactory;
 import com.terraformersmc.modmenu.api.ModMenuApi;
 import me.lortseam.completeconfig.data.Config;
+import me.lortseam.completeconfig.data.Registry;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -13,8 +14,8 @@ public final class ModMenuIntegration implements ModMenuApi {
     @Override
     public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
         Map<String, ConfigScreenFactory<?>> factories = new HashMap<>();
-        for (Map.Entry<String, Config> entry : Config.getMainConfigs().entrySet()) {
-            Optional<ConfigScreenBuilder> builder = ConfigScreenBuilder.getMain(entry.getKey());
+        for (Map.Entry<String, Config> entry : Registry.getMainConfigs().entrySet()) {
+            Optional<ConfigScreenBuilder> builder = Registry.getScreenBuilder(entry.getKey(), ConfigScreenBuilder.FALLBACK);
             if (!builder.isPresent()) continue;
             factories.put(entry.getKey(), parentScreen -> builder.get().build(parentScreen, entry.getValue()));
         }

+ 2 - 3
lib/src/main/java/me/lortseam/completeconfig/gui/cloth/GuiProviderRegistry.java

@@ -12,7 +12,6 @@ import net.fabricmc.api.EnvType;
 import net.fabricmc.api.Environment;
 import net.minecraft.text.TextColor;
 
-import java.util.Collection;
 import java.util.*;
 import java.util.stream.Stream;
 
@@ -198,8 +197,8 @@ public final class GuiProviderRegistry {
     );
 
     static {
-        for (Collection<GuiProvider> providers : CompleteConfig.collectExtensions(GuiExtension.class, GuiExtension::getProviders)) {
-            globalProviders.addAll(providers);
+        for (GuiProvider[] providers : CompleteConfig.collectExtensions(GuiExtension.class, GuiExtension::getProviders)) {
+            globalProviders.addAll(Arrays.asList(providers));
         }
     }
 

+ 2 - 4
lib/src/main/java/me/lortseam/completeconfig/io/ConfigSource.java

@@ -5,6 +5,7 @@ import lombok.Getter;
 import lombok.extern.log4j.Log4j2;
 import me.lortseam.completeconfig.CompleteConfig;
 import me.lortseam.completeconfig.data.Config;
+import me.lortseam.completeconfig.data.Registry;
 import me.lortseam.completeconfig.extensions.CompleteConfigExtension;
 import net.fabricmc.loader.api.FabricLoader;
 import org.apache.commons.lang3.ArrayUtils;
@@ -14,15 +15,12 @@ import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
 import org.spongepowered.configurate.serialize.TypeSerializerCollection;
 
 import java.nio.file.Path;
-import java.util.HashSet;
-import java.util.Set;
 
 @Log4j2(topic = "CompleteConfig")
 @EqualsAndHashCode(onlyExplicitlyIncluded = true)
 public final class ConfigSource {
 
     private static final TypeSerializerCollection GLOBAL_TYPE_SERIALIZERS;
-    private static final Set<ConfigSource> sources = new HashSet<>();
 
     static {
         TypeSerializerCollection.Builder builder = TypeSerializerCollection.builder();
@@ -45,7 +43,7 @@ public final class ConfigSource {
     public ConfigSource(String modId, String[] branch) {
         this.modId = modId;
         this.branch = branch;
-        if (!sources.add(this)) {
+        if (Registry.hasSource(this)) {
             throw new IllegalArgumentException("A config of " + this + " already exists");
         }
         Path path = FabricLoader.getInstance().getConfigDir();