From 428bb5d412b66cda37d6f2199e81d0cb81a8bb96 Mon Sep 17 00:00:00 2001
From: DeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>
Date: Sun, 20 Feb 2022 15:50:05 +0100
Subject: profile system

---
 .../java/io/polyfrost/oneconfig/OneConfig.java     |  9 ++-
 .../oneconfig/config/OneConfigConfig.java          | 44 ++++++++++++
 .../oneconfig/config/core/ConfigCore.java          | 14 ++++
 .../oneconfig/config/interfaces/Config.java        | 61 +++++++++-------
 .../config/interfaces/OneConfigTypeAdapter.java    |  2 +-
 .../oneconfig/config/profiles/Profiles.java        | 84 ++++++++++++++++++++++
 .../io/polyfrost/oneconfig/test/TestConfig.java    |  4 +-
 7 files changed, 187 insertions(+), 31 deletions(-)
 create mode 100644 src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java
 create mode 100644 src/main/java/io/polyfrost/oneconfig/config/profiles/Profiles.java

(limited to 'src')

diff --git a/src/main/java/io/polyfrost/oneconfig/OneConfig.java b/src/main/java/io/polyfrost/oneconfig/OneConfig.java
index 9d6ed49..1b90f6b 100644
--- a/src/main/java/io/polyfrost/oneconfig/OneConfig.java
+++ b/src/main/java/io/polyfrost/oneconfig/OneConfig.java
@@ -1,7 +1,9 @@
 package io.polyfrost.oneconfig;
 
 import io.polyfrost.oneconfig.command.OneConfigCommand;
-import io.polyfrost.oneconfig.renderer.Renderer;
+import io.polyfrost.oneconfig.config.OneConfigConfig;
+import io.polyfrost.oneconfig.config.core.ConfigCore;
+import io.polyfrost.oneconfig.config.profiles.Profiles;
 import io.polyfrost.oneconfig.test.TestConfig;
 import io.polyfrost.oneconfig.themes.Themes;
 import net.minecraft.client.Minecraft;
@@ -19,17 +21,20 @@ public class OneConfig {
     public static File jarFile;
     public static File oneConfigDir = new File(mc.mcDataDir, "OneConfig/");
     public static File themesDir = new File(oneConfigDir, "themes/");
-    public static TestConfig config = new TestConfig();
+    public static OneConfigConfig config;
+    public static TestConfig testConfig;
 
     @Mod.EventHandler
     public void onPreFMLInit(FMLPreInitializationEvent event) {
         jarFile = event.getSourceFile();
         oneConfigDir.mkdirs();
         themesDir.mkdirs();
+        config = new OneConfigConfig();
     }
 
     @Mod.EventHandler
     public void onFMLInitialization(FMLInitializationEvent event) {
+        testConfig = new TestConfig();
         ClientCommandHandler.instance.registerCommand(new OneConfigCommand());
         MinecraftForge.EVENT_BUS.register(this);
         Themes.openTheme(new File("OneConfig/themes/one.zip").getAbsoluteFile());
diff --git a/src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java b/src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java
new file mode 100644
index 0000000..de9bf92
--- /dev/null
+++ b/src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java
@@ -0,0 +1,44 @@
+package io.polyfrost.oneconfig.config;
+
+import com.google.gson.JsonParser;
+import io.polyfrost.oneconfig.config.data.ModData;
+import io.polyfrost.oneconfig.config.interfaces.Config;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+
+public class OneConfigConfig extends Config {
+    public OneConfigConfig() {
+        super(null, "OneConfig.json");
+    }
+
+    @Override
+    public void init(ModData modData) {
+        if (new File("OneConfig/" + configFile).exists())
+            load();
+        else
+            save();
+    }
+
+    @Override
+    public void save() {
+        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("OneConfig/" + configFile), StandardCharsets.UTF_8))) {
+            writer.write(gson.toJson(this.getClass()));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void load() {
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("OneConfig/" + configFile), StandardCharsets.UTF_8))) {
+            deserializePart(new JsonParser().parse(reader).getAsJsonObject(), this.getClass());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static HashMap<String, String> profiles = new HashMap<>();
+    public static String currentProfile;
+}
diff --git a/src/main/java/io/polyfrost/oneconfig/config/core/ConfigCore.java b/src/main/java/io/polyfrost/oneconfig/config/core/ConfigCore.java
index ff7ed28..1e0940b 100644
--- a/src/main/java/io/polyfrost/oneconfig/config/core/ConfigCore.java
+++ b/src/main/java/io/polyfrost/oneconfig/config/core/ConfigCore.java
@@ -8,4 +8,18 @@ import java.util.HashMap;
 
 public class ConfigCore {
     public static HashMap<ModData, ArrayList<Option>> settings = new HashMap<>();
+
+    public static void saveAll () {
+        for (ModData modData : settings.keySet()) {
+            modData.config.save();
+        }
+    }
+
+    public static void reInitAll () {
+        ArrayList<ModData> data = new ArrayList<>(settings.keySet());
+        settings.clear();
+        for (ModData modData : data) {
+            modData.config.init(modData);
+        }
+    }
 }
diff --git a/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java b/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java
index f592152..73696a5 100644
--- a/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java
+++ b/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java
@@ -4,6 +4,7 @@ import com.google.gson.*;
 import io.polyfrost.oneconfig.config.annotations.*;
 import io.polyfrost.oneconfig.config.core.ConfigCore;
 import io.polyfrost.oneconfig.config.data.ModData;
+import io.polyfrost.oneconfig.config.profiles.Profiles;
 import io.polyfrost.oneconfig.gui.elements.config.*;
 
 import java.io.*;
@@ -11,20 +12,26 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Map;
+import java.util.Optional;
 
 public class Config {
-    private final File configFile;
-    private final Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).setPrettyPrinting()
+    protected final String configFile;
+    protected final Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).setPrettyPrinting()
             .registerTypeAdapterFactory(OneConfigTypeAdapterFactory.getStaticTypeAdapterFactory()).create();
 
     /**
      * @param modData    information about the mod
      * @param configFile file where config is stored
      */
-    public Config(ModData modData, File configFile) {
+    public Config(ModData modData, String configFile) {
         this.configFile = configFile;
-        if (configFile.exists())
+        init(modData);
+    }
+
+    public void init(ModData modData) {
+        if (Profiles.getProfileFile(configFile).exists())
             load();
         else
             save();
@@ -36,7 +43,7 @@ public class Config {
      * Save current config to file
      */
     public void save() {
-        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(configFile), StandardCharsets.UTF_8))) {
+        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(Profiles.getProfileFile(configFile)), StandardCharsets.UTF_8))) {
             writer.write(gson.toJson(this.getClass()));
         } catch (IOException e) {
             e.printStackTrace();
@@ -47,7 +54,7 @@ public class Config {
      * Load file and overwrite current values
      */
     public void load() {
-        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8))) {
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(Profiles.getProfileFile(configFile)), StandardCharsets.UTF_8))) {
             deserializePart(new JsonParser().parse(reader).getAsJsonObject(), this.getClass());
         } catch (IOException e) {
             e.printStackTrace();
@@ -60,7 +67,7 @@ public class Config {
      * @param clazz target class
      * @return list of options
      */
-    private ArrayList<Option> generateOptionList(Class<?> clazz) {
+    protected ArrayList<Option> generateOptionList(Class<?> clazz) {
         ArrayList<Option> options = new ArrayList<>();
         for (Class<?> innerClass : clazz.getClasses()) {
             if (innerClass.isAnnotationPresent(Category.class)) {
@@ -87,7 +94,11 @@ public class Config {
             } else if (field.isAnnotationPresent(TextField.class)) {
                 TextField textField = field.getAnnotation(TextField.class);
                 options.add(new OConfigText(field, textField.name(), textField.description(), textField.placeholder(), textField.hideText()));
-            } else loadCustomType(field);
+            } else {
+                Option customOption = processCustomOption(field);
+                if (customOption != null)
+                    options.add(customOption);
+            }
         }
         return options;
     }
@@ -96,8 +107,10 @@ public class Config {
      * Overwrite this method to add your own custom option types
      *
      * @param field target field
+     * @return custom option
      */
-    protected void loadCustomType(Field field) {
+    protected Option processCustomOption(Field field) {
+        return null;
     }
 
     /**
@@ -106,28 +119,26 @@ public class Config {
      * @param json  json to deserialize
      * @param clazz target class
      */
-    private void deserializePart(JsonObject json, Class<?> clazz) {
+    protected void deserializePart(JsonObject json, Class<?> clazz) {
         for (Map.Entry<String, JsonElement> element : json.entrySet()) {
             String name = element.getKey();
             JsonElement value = element.getValue();
             if (value.isJsonObject()) {
-                for (Class<?> innerClass : clazz.getClasses()) {
-                    if (innerClass.getSimpleName().equals(name)) {
-                        deserializePart(value.getAsJsonObject(), innerClass);
-                        break;
-                    }
-                }
-            } else {
-                try {
-                    Field field = clazz.getField(name);
-                    TypeAdapter<?> adapter = gson.getAdapter(field.getType());
-                    Object object = adapter.fromJsonTree(value);
-                    field.setAccessible(true);
-                    field.set(null, object);
-                } catch (NoSuchFieldException | IllegalAccessException e) {
-                    e.printStackTrace();
+                Optional<Class<?>> innerClass = Arrays.stream(clazz.getClasses()).filter(aClass -> aClass.getSimpleName().equals(name)).findFirst();
+                if (innerClass.isPresent()) {
+                    deserializePart(value.getAsJsonObject(), innerClass.get());
+                    continue;
                 }
             }
+            try {
+                Field field = clazz.getField(name);
+                TypeAdapter<?> adapter = gson.getAdapter(field.getType());
+                Object object = adapter.fromJsonTree(value);
+                field.setAccessible(true);
+                field.set(null, object);
+            } catch (NoSuchFieldException | IllegalAccessException e) {
+                e.printStackTrace();
+            }
         }
     }
 }
diff --git a/src/main/java/io/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java b/src/main/java/io/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java
index a07e7c8..7754820 100644
--- a/src/main/java/io/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java
+++ b/src/main/java/io/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java
@@ -31,7 +31,7 @@ final class OneConfigTypeAdapter<T> extends TypeAdapter<Class<T>> {
                 out.name(field.getName());
                 field.setAccessible(true);
                 final TypeAdapter<Object> adapter = (TypeAdapter) gson.getAdapter(field.getType());
-                adapter.write(out, field.get(null));
+                adapter.write(out, field.get(field.getClass()));
             }
             for (Class<?> clazz : value.getClasses()) {
                 out.name(clazz.getSimpleName());
diff --git a/src/main/java/io/polyfrost/oneconfig/config/profiles/Profiles.java b/src/main/java/io/polyfrost/oneconfig/config/profiles/Profiles.java
new file mode 100644
index 0000000..0ad7620
--- /dev/null
+++ b/src/main/java/io/polyfrost/oneconfig/config/profiles/Profiles.java
@@ -0,0 +1,84 @@
+package io.polyfrost.oneconfig.config.profiles;
+
+import io.polyfrost.oneconfig.OneConfig;
+import io.polyfrost.oneconfig.config.OneConfigConfig;
+import io.polyfrost.oneconfig.config.core.ConfigCore;
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+public class Profiles {
+    public static Map.Entry<String, String> getCurrentProfile() {
+        if (OneConfigConfig.currentProfile == null) {
+            OneConfigConfig.currentProfile = createProfile("Default Profile").getKey();
+            OneConfig.config.save();
+        }
+        return getProfile(OneConfigConfig.currentProfile);
+    }
+
+    public static Map.Entry<String, String> createProfile(String name) {
+        File profileDir = new File("OneConfig/profiles");
+        if (!profileDir.exists() && !profileDir.mkdir()) {
+            System.out.println("Could not create profiles folder");
+            return null;
+        }
+        File folder = new File(profileDir, name);
+        if (!folder.exists() && !folder.mkdir()) {
+            System.out.println("Could not create profile folder");
+            return null;
+        }
+        OneConfigConfig.profiles.put(name, folder.getAbsolutePath());
+        OneConfig.config.save();
+        return getProfile(name);
+    }
+
+    public static Map.Entry<String, String> getProfile(String name) {
+        return OneConfigConfig.profiles.entrySet().stream().filter(entry -> entry.getKey().equals(name)).findFirst().get();
+    }
+
+    public static File getProfileFile(String file) {
+        return new File(new File(getCurrentProfile().getValue()), file);
+    }
+
+    public static void loadProfile(String profile) {
+        ConfigCore.saveAll();
+        OneConfigConfig.currentProfile = profile;
+        OneConfig.config.save();
+        ConfigCore.reInitAll();
+    }
+
+    public static void renameProfile(String name, String newName) {
+        try {
+            Map.Entry<String, String> profile = getProfile(name);
+            File newFile = new File(new File("OneConfig/profiles"), newName);
+            FileUtils.moveDirectory(new File(profile.getValue()), newFile);
+            if (OneConfigConfig.currentProfile.equals(name))
+                OneConfigConfig.currentProfile = newName;
+            OneConfigConfig.profiles.remove(name);
+            OneConfigConfig.profiles.put(newName, newFile.getAbsolutePath());
+            OneConfig.config.save();
+        } catch (IOException e) {
+            System.out.println("Failed to rename profile");
+        }
+    }
+
+    public static void deleteProfile(String name) {
+        Map.Entry<String, String> profile = getProfile(name);
+        if (profile.equals(getCurrentProfile())) {
+            if (OneConfigConfig.profiles.size() == 1) {
+                System.out.println("Cannot delete only profile!");
+                return;
+            }
+            loadProfile(OneConfigConfig.profiles.entrySet().stream().filter(entry -> !entry.getKey().equals(name)).findFirst().get().getKey());
+        }
+        try {
+            FileUtils.deleteDirectory(new File(profile.getValue()));
+            OneConfigConfig.profiles.remove(name);
+            OneConfig.config.save();
+        } catch (IOException e) {
+            System.out.println("Failed to delete profile");
+        }
+    }
+}
diff --git a/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java b/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java
index 04c912e..387d298 100644
--- a/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java
+++ b/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java
@@ -7,8 +7,6 @@ import io.polyfrost.oneconfig.config.data.ModData;
 import io.polyfrost.oneconfig.config.data.ModType;
 import io.polyfrost.oneconfig.config.interfaces.Config;
 
-import java.io.File;
-
 public class TestConfig extends Config {
 
     @Switch(name = "Cool Switch")
@@ -21,6 +19,6 @@ public class TestConfig extends Config {
     }
 
     public TestConfig() {
-        super(new ModData("hacks", ModType.QOL, "ShadyDev", "1.0"), new File("./config/hacksConfig.json"));
+        super(new ModData("hacks", ModType.QOL, "ShadyDev", "1.0"), "hacksConfig.json");
     }
 }
-- 
cgit