Procházet zdrojové kódy

[WIP] Config manager restructure

Lortseam před 4 roky
rodič
revize
bd31f3046d

+ 0 - 24
src/main/java/me/lortseam/completeconfig/ConfigManager.java

@@ -64,36 +64,12 @@ public class ConfigManager {
         return JsonNull.INSTANCE;
     }
 
-    //TODO: Create own class for validations like these
-    private void addListenerToEntry(Entry<?> entry, Method method, ConfigEntryContainer container) {
-        //TODO: Add void return type check
-        //TODO: Allow listeners without parameters if forceUpdate equals true or listener is defined in different class
-        if (method.getParameterCount() != 1 || method.getParameterTypes()[0] != entry.getType()) {
-            throw new IllegalArgumentException("Listener method " + method + " has wrong parameter type(s)");
-        }
-        if (!method.isAccessible()) {
-            method.setAccessible(true);
-        }
-        entry.addListener(method, container);
-    }
-
-    //TODO: Löschen
-    private Map<String, Entry> findEntries(LinkedHashMap<String, Collection> collections, Class<? extends ConfigEntryContainer> parentClass) {
-        Map<String, Entry> entries = new HashMap<>();
-        for (Collection collection : collections.values()) {
-            entries.putAll(collection.getEntries().entrySet().stream().filter(entry -> entry.getValue().getParentObject().getClass() == parentClass).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
-            entries.putAll(findEntries(collection.getCollections(), parentClass));
-        }
-        return entries;
-    }
-
     public void register(ConfigCategory... categories) {
         for (ConfigCategory category : categories) {
             config.registerTopLevelCategory(category);
         }
     }
 
-
     private String buildTranslationKey(String... ids) {
         return joinIDs("config", modID, joinIDs(ids));
     }

+ 6 - 3
src/main/java/me/lortseam/completeconfig/collection/Collection.java

@@ -1,6 +1,7 @@
 package me.lortseam.completeconfig.collection;
 
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
 import me.lortseam.completeconfig.api.ConfigCategory;
 import me.lortseam.completeconfig.api.ConfigEntryContainer;
 import me.lortseam.completeconfig.exception.IllegalAnnotationTargetException;
@@ -9,14 +10,16 @@ import java.lang.reflect.Modifier;
 import java.util.*;
 import java.util.stream.Collectors;
 
+@RequiredArgsConstructor
 public class Collection {
 
     @Getter
-    private final EntryMap entries = new EntryMap();
+    private final EntryMap entries;
     @Getter
-    private final CollectionMap collections = new CollectionMap();
+    private final CollectionMap collections;
 
-    public Collection(ConfigEntryContainer container) {
+    Collection(ConfigEntryContainer container) {
+        this(new EntryMap(), new CollectionMap());
         fill(container);
     }
 

+ 30 - 25
src/main/java/me/lortseam/completeconfig/collection/EntryMap.java

@@ -5,6 +5,7 @@ import me.lortseam.completeconfig.ConfigMap;
 import me.lortseam.completeconfig.api.ConfigEntry;
 import me.lortseam.completeconfig.api.ConfigEntryContainer;
 import me.lortseam.completeconfig.api.ConfigEntryListener;
+import me.lortseam.completeconfig.entry.Bounds;
 import me.lortseam.completeconfig.entry.Entry;
 import me.lortseam.completeconfig.exception.IllegalAnnotationParameterException;
 import me.lortseam.completeconfig.exception.IllegalAnnotationTargetException;
@@ -20,7 +21,7 @@ public class EntryMap extends ConfigMap<Entry> {
     void fill(ConfigEntryContainer container) {
         LinkedHashMap<String, Entry> containerEntries = new LinkedHashMap<>();
         for (Class<? extends ConfigEntryContainer> clazz : container.getClasses()) {
-            List<Listener> listeners = new ArrayList<>();
+            /*List<Listener> listeners = new ArrayList<>();
             Iterator<Listener> iter = pendingListeners.iterator();
             while (iter.hasNext()) {
                 Listener listener = iter.next();
@@ -28,7 +29,7 @@ public class EntryMap extends ConfigMap<Entry> {
                     listeners.add(listener);
                     iter.remove();
                 }
-            }
+            }*/
             Arrays.stream(clazz.getDeclaredMethods()).filter(method -> !Modifier.isStatic(method.getModifiers()) && method.isAnnotationPresent(ConfigEntryListener.class)).forEach(method -> {
                 ConfigEntryListener listener = method.getDeclaredAnnotation(ConfigEntryListener.class);
                 String fieldName = listener.value();
@@ -40,6 +41,18 @@ public class EntryMap extends ConfigMap<Entry> {
                 }
                 Class<? extends ConfigEntryContainer> fieldClass = listener.container();
                 if (fieldClass == ConfigEntryContainer.class) {
+                    fieldClass = container.getClass();
+                }
+                //TODO: Check for void return type
+                //TODO: Check for valid parameter type
+                if (method.getParameterCount() != 1) {
+                    throw new IllegalArgumentException("Listener method " + method + " has wrong number of parameters");
+                }
+                if (!method.isAccessible()) {
+                    method.setAccessible(true);
+                }
+                Entry.of(fieldName, fieldClass).addListener(method, container);
+                /*if (fieldClass == ConfigEntryContainer.class) {
                     listeners.add(new Listener(method, container, fieldName));
                 } else {
                     Map<String, Entry> fieldClassEntries = findEntries(config, fieldClass);
@@ -52,7 +65,7 @@ public class EntryMap extends ConfigMap<Entry> {
                         }
                         addListenerToEntry(entry, method, container);
                     }
-                }
+                }*/
             });
             LinkedHashMap<String, Entry> clazzEntries = new LinkedHashMap<>();
             Arrays.stream(clazz.getDeclaredFields()).filter(field -> {
@@ -70,12 +83,12 @@ public class EntryMap extends ConfigMap<Entry> {
                 if (!field.isAccessible()) {
                     field.setAccessible(true);
                 }
-                Entry.Builder builder = new Entry.Builder(field, container);
+                Entry<?> entry = Entry.of(field, container);
                 if (field.isAnnotationPresent(ConfigEntry.class)) {
                     ConfigEntry entryAnnotation = field.getDeclaredAnnotation(ConfigEntry.class);
                     String customTranslationKey = entryAnnotation.customTranslationKey();
                     if (!StringUtils.isBlank(customTranslationKey)) {
-                        builder.setCustomTranslationKey(customTranslationKey);
+                        entry.setCustomTranslationKey(customTranslationKey);
                     }
                     String[] customTooltipKeys = entryAnnotation.customTooltipKeys();
                     if (customTooltipKeys.length > 0) {
@@ -84,53 +97,45 @@ public class EntryMap extends ConfigMap<Entry> {
                                 throw new IllegalAnnotationParameterException("Tooltip key(s) of entry field " + field + " must not be blank");
                             }
                         }
-                        builder.setCustomTooltipKeys(customTooltipKeys);
+                        entry.setCustomTooltipKeys(customTooltipKeys);
                     }
-                    builder.setForceUpdate(entryAnnotation.forceUpdate());
+                    entry.setForceUpdate(entryAnnotation.forceUpdate());
                 }
                 if (field.isAnnotationPresent(ConfigEntry.Bounded.Integer.class)) {
                     if (field.getType() != int.class && field.getType() != Integer.class) {
                         throw new IllegalAnnotationTargetException("Cannot apply Integer bound to non Integer field " + field);
                     }
                     ConfigEntry.Bounded.Integer bounds = field.getDeclaredAnnotation(ConfigEntry.Bounded.Integer.class);
-                    builder.setBounds(bounds.min(), bounds.max());
+                    entry.getExtras().setBounds(bounds.min(), bounds.max());
                 } else if (field.isAnnotationPresent(ConfigEntry.Bounded.Long.class)) {
                     if (field.getType() != long.class && field.getType() != Long.class) {
                         throw new IllegalAnnotationTargetException("Cannot apply Long bound to non Long field " + field);
                     }
                     ConfigEntry.Bounded.Long bounds = field.getDeclaredAnnotation(ConfigEntry.Bounded.Long.class);
-                    builder.setBounds(bounds.min(), bounds.max());
+                    entry.getExtras().setBounds(bounds.min(), bounds.max());
                 } else if (field.isAnnotationPresent(ConfigEntry.Bounded.Float.class)) {
                     if (field.getType() != float.class && field.getType() != Float.class) {
                         throw new IllegalAnnotationTargetException("Cannot apply Float bound to non Float field " + field);
                     }
                     ConfigEntry.Bounded.Float bounds = field.getDeclaredAnnotation(ConfigEntry.Bounded.Float.class);
-                    builder.setBounds(bounds.min(), bounds.max());
+                    entry.getExtras().setBounds(bounds.min(), bounds.max());
                 } else if (field.isAnnotationPresent(ConfigEntry.Bounded.Double.class)) {
                     if (field.getType() != double.class && field.getType() != Double.class) {
                         throw new IllegalAnnotationTargetException("Cannot apply Double bound to non Double field " + field);
                     }
                     ConfigEntry.Bounded.Double bounds = field.getDeclaredAnnotation(ConfigEntry.Bounded.Double.class);
-                    builder.setBounds(bounds.min(), bounds.max());
+                    entry.getExtras().setBounds(bounds.min(), bounds.max());
                 }
-                Entry<?> entry = builder.build();
-                if (guiRegistry.getProvider(entry) == null) {
+                //TODO
+                /*if (guiRegistry.getProvider(entry) == null) {
                     throw new UnsupportedOperationException("Could not find gui provider for field type " + entry.getType());
-                }
-                String fieldName = field.getName();
-                listeners.removeIf(listener -> {
-                    if (!listener.getFieldName().equals(fieldName)) {
-                        return false;
-                    }
-                    addListenerToEntry(entry, listener.getMethod(), listener.getParentObject());
-                    return true;
-                });
-                clazzEntries.put(fieldName, entry);
+                }*/
+                clazzEntries.put(field.getName(), entry);
             });
-            if (!listeners.isEmpty()) {
+            /*if (!listeners.isEmpty()) {
                 Listener listener = listeners.iterator().next();
                 throw new IllegalAnnotationParameterException("Could not find field " + listener.getFieldName() + " in " + clazz + " requested by listener method " + listener.getMethod());
-            }
+            }*/
             //TODO: Quite hacky solution to sort the entries (superclasses first)
             clazzEntries.putAll(containerEntries);
             containerEntries = clazzEntries;

+ 25 - 9
src/main/java/me/lortseam/completeconfig/entry/Entry.java

@@ -1,10 +1,7 @@
 package me.lortseam.completeconfig.entry;
 
 import com.google.common.collect.MoreCollectors;
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.*;
 import me.lortseam.completeconfig.api.ConfigEntryContainer;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -19,18 +16,33 @@ import java.util.*;
 public class Entry<T> {
 
     private static final Logger LOGGER = LogManager.getLogger();
-    private static final Set<Entry> entries = new HashSet<>();
+    private static final Set<Entry> ENTRIES = new HashSet<>();
 
     public static Entry<?> of(String fieldName, Class<? extends ConfigEntryContainer> parentClass) {
         try {
             Field field = parentClass.getField(fieldName);
-            return entries.stream().filter(entry -> entry.parentObject.getClass() == parentClass && entry.field == field).collect(MoreCollectors.toOptional()).orElse(new Entry<>(field, parentClass));
+            return of(field);
         } catch (NoSuchFieldException e) {
             //TODO
             throw new RuntimeException(e);
         }
     }
 
+    private static <T> Entry<T> of(Field field) {
+        return ENTRIES.stream().filter(entry -> entry.field == field).collect(MoreCollectors.toOptional()).orElseGet(() -> {
+            Entry<T> entry = new Entry<>(field, (Class<T>) field.getType());
+            ENTRIES.add(entry);
+            return entry;
+        });
+    }
+
+    public static <T> Entry<T> of(Field field, ConfigEntryContainer parentObject) {
+        Entry<T> entry = of(field);
+        entry.parentObject = parentObject;
+        entry.defaultValue = entry.getValue();
+        return entry;
+    }
+
     @Getter
     private final Field field;
     @Getter
@@ -40,12 +52,15 @@ public class Entry<T> {
     @Getter
     private T defaultValue;
     @Getter
+    @Setter
     private String customTranslationKey;
     @Getter
+    @Setter
     private String[] customTooltipKeys;
     @Getter
-    private Extras<T> extras;
+    private Extras<T> extras = new Extras<>(this);
     private final List<Listener> listeners = new ArrayList<>();
+    @Setter
     private boolean forceUpdate;
 
     /*private Entry(Field field, Class<T> type, ConfigEntryContainer parentObject, String customTranslationKey, String[] customTooltipKeys, Extras<T> extras, boolean forceUpdate) {
@@ -86,10 +101,10 @@ public class Entry<T> {
         if (extras.getBounds() != null) {
             if (new BigDecimal(value.toString()).compareTo(new BigDecimal(extras.getBounds().getMin().toString())) < 0) {
                 LOGGER.warn("[CompleteConfig] Tried to set value of field " + field + " to a value less than minimum bound, setting to minimum now!");
-                value = extras.getBounds().getMin();
+                value = (T) extras.getBounds().getMin();
             } else if (new BigDecimal(value.toString()).compareTo(new BigDecimal(extras.getBounds().getMax().toString())) > 0) {
                 LOGGER.warn("[CompleteConfig] Tried to set value of field " + field + " to a value greater than maximum bound, setting to maximum now!");
-                value = extras.getBounds().getMax();
+                value = (T) extras.getBounds().getMax();
             }
         }
         if (value.equals(get())) {
@@ -119,6 +134,7 @@ public class Entry<T> {
     }
 
     public void addListener(Method method, ConfigEntryContainer parentObject) {
+
         listeners.add(new Listener(method, parentObject));
     }
 

+ 8 - 1
src/main/java/me/lortseam/completeconfig/entry/Extras.java

@@ -3,11 +3,18 @@ package me.lortseam.completeconfig.entry;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 
 @RequiredArgsConstructor(access = AccessLevel.PACKAGE)
 public class Extras<T> {
 
+    private final Entry<T> entry;
     @Getter
-    private final Bounds<T> bounds;
+    private Bounds<T> bounds;
+
+    public <N extends Number> void setBounds(N min, N max) {
+        //TODO: Check for correct min/max type
+        bounds = new Bounds<>((T) min, (T) max);
+    }
 
 }

+ 3 - 1
src/main/java/me/lortseam/completeconfig/serialization/CollectionDeserializer.java

@@ -3,6 +3,8 @@ package me.lortseam.completeconfig.serialization;
 import com.google.gson.*;
 import com.google.gson.reflect.TypeToken;
 import me.lortseam.completeconfig.collection.Collection;
+import me.lortseam.completeconfig.collection.CollectionMap;
+import me.lortseam.completeconfig.collection.EntryMap;
 import me.lortseam.completeconfig.entry.Entry;
 
 import java.lang.reflect.Type;
@@ -24,7 +26,7 @@ public class CollectionDeserializer implements JsonDeserializer<Collection> {
                 entries.add(entry.getKey(), entry.getValue());
             }
         }
-        return new Collection(context.deserialize(collections, new TypeToken<LinkedHashMap<String, Collection>>() {}.getType()), context.deserialize(entries, new TypeToken<LinkedHashMap<String, Entry>>() {}.getType()));
+        return new Collection(context.deserialize(collections, new TypeToken<CollectionMap>() {}.getType()), context.deserialize(entries, new TypeToken<EntryMap>() {}.getType()));
     }
 
 }

+ 1 - 1
src/main/resources/fabric.mod.json

@@ -20,7 +20,7 @@
 
   "depends": {
     "minecraft": "1.16.x",
-    "fabricloader": ">=0.7.4",
+    "fabricloader": ">=0.9.0",
     "cloth-config2": "*"
   }
 }