aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/cc/polyfrost/oneconfig/config
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cc/polyfrost/oneconfig/config')
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/OneConfigConfig.java81
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/annotations/ConfigPage.java32
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/annotations/Option.java85
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/core/ConfigCore.java25
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/data/InfoType.java8
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/data/Mod.java26
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/data/ModType.java10
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/data/OptionCategory.java13
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/data/OptionPage.java19
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/data/OptionType.java36
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/data/PageLocation.java6
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/interfaces/BasicOption.java81
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/interfaces/Config.java180
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java51
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapterFactory.java28
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/interfaces/Size.java6
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/profiles/Profiles.java87
17 files changed, 774 insertions, 0 deletions
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/OneConfigConfig.java b/src/main/java/cc/polyfrost/oneconfig/config/OneConfigConfig.java
new file mode 100644
index 0000000..73f5821
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/OneConfigConfig.java
@@ -0,0 +1,81 @@
+package cc.polyfrost.oneconfig.config;
+
+import cc.polyfrost.oneconfig.config.interfaces.Config;
+import com.google.gson.JsonParser;
+import cc.polyfrost.oneconfig.config.data.Mod;
+
+import java.awt.*;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+public class OneConfigConfig extends Config {
+
+ public static String currentProfile = "Default Profile";
+
+ // TODO i dont know how this works so this is just gonna be here for now
+ public static final int TRANSPARENT = new Color(0, 0, 0, 0).getRGB(); // Transparent // button sidebar normal
+
+ public static final int GRAY_900 = new Color(13, 14, 15, 255).getRGB(); // Gray 900
+ public static final int GRAY_900_80 = new Color(13, 14, 15, 204).getRGB(); // Gray 900 80%
+ public static final int GRAY_800 = new Color(21, 22, 23, 255).getRGB(); // Gray 800
+ public static final int GRAY_700 = new Color(34, 35, 38, 255).getRGB(); // Gray 700
+ public static final int GRAY_600 = new Color(42, 44, 48, 255).getRGB(); // Gray 600
+ public static final int GRAY_500 = new Color(49, 51, 56, 255).getRGB(); // Gray 500 // button sidebar hover, button gray normal
+ public static final int GRAY_500_80 = new Color(49, 51, 56, 204).getRGB(); // Gray 500 80% // button sidebar pressed
+
+ public static final int GRAY_400 = new Color(55, 59, 69, 255).getRGB(); // Gray 400
+ public static final int GRAY_300 = new Color(73, 79, 92, 255).getRGB(); // Gray 300 // button gray hover
+ public static final int GRAY_200 = new Color(100, 107, 125, 255).getRGB(); // Gray 200
+ public static final int GRAY_400_80 = new Color(55, 59, 69, 204).getRGB(); // Gray 400 80% // button gray pressed
+ public static final int BLUE_800 = new Color(13, 51, 128, 255).getRGB(); // Blue 800
+ public static final int BLUE_700 = new Color(18, 71, 178, 255).getRGB(); // Blue 700
+ public static final int BLUE_700_80 = new Color(18, 71, 178, 204).getRGB(); // Blue 700 80%
+ public static final int BLUE_600 = new Color(20, 82, 204, 255).getRGB(); // Blue 600 // button blue normal
+ public static final int BLUE_600_80 = new Color(20, 82, 204, 204).getRGB(); // Blue 600 80% // button blue click
+ public static final int BLUE_500 = new Color(25, 103, 255, 255).getRGB(); // Blue 500 // button blue hover
+ public static final int BLUE_400 = new Color(48, 129, 242, 255).getRGB();
+ public static final int BLUE_400_80 = new Color(48, 129, 242, 204).getRGB();
+ public static final int WHITE_50 = new Color(255, 255, 255, 127).getRGB(); // White 60%
+ public static final int WHITE_60 = new Color(255, 255, 255, 153).getRGB(); // White 60%
+ public static final int WHITE_80 = new Color(255, 255, 255, 204).getRGB(); // White 80%
+ public static final int WHITE_90 = new Color(255, 255, 255, 229).getRGB(); // White 90%
+ public static final int WHITE_95 = new Color(255, 255, 255, 242).getRGB(); // White 90%
+ public static final int WHITE = new Color(255, 255, 255, 255).getRGB(); // White 100%
+
+ public static final int ERROR_700 = new Color(180, 24, 24, 255).getRGB(); // Red 700
+
+ public static boolean ROUNDED_CORNERS = true;
+ public static float CORNER_RADIUS_WIN = 20f;
+ public static float CORNER_RADIUS = 12f;
+
+
+ public OneConfigConfig() {
+ super(null, "OneConfig.json");
+ }
+
+ @Override
+ public void init(Mod mod) {
+ if (new File("OneConfig/" + configFile).exists()) load();
+ else save();
+ }
+
+ @Override
+ public void save() {
+ try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get("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(Files.newInputStream(Paths.get("OneConfig/" + configFile)), StandardCharsets.UTF_8))) {
+ deserializePart(new JsonParser().parse(reader).getAsJsonObject(), this.getClass());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/annotations/ConfigPage.java b/src/main/java/cc/polyfrost/oneconfig/config/annotations/ConfigPage.java
new file mode 100644
index 0000000..f9d7c19
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/annotations/ConfigPage.java
@@ -0,0 +1,32 @@
+package cc.polyfrost.oneconfig.config.annotations;
+
+import cc.polyfrost.oneconfig.config.data.PageLocation;
+
+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 ConfigPage {
+ /**
+ * The name of the page that will be displayed to the user
+ */
+ String name();
+
+ /**
+ * If the page button is at the top or bottem of the page
+ */
+ PageLocation location();
+
+ /**
+ * The description of the page that will be displayed to the user
+ */
+ String description() default "";
+
+ /**
+ * The category of the page
+ */
+ String category() default "General";
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/annotations/Option.java b/src/main/java/cc/polyfrost/oneconfig/config/annotations/Option.java
new file mode 100644
index 0000000..d5e9fc7
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/annotations/Option.java
@@ -0,0 +1,85 @@
+package cc.polyfrost.oneconfig.config.annotations;
+
+import cc.polyfrost.oneconfig.config.data.InfoType;
+import cc.polyfrost.oneconfig.config.data.OptionType;
+
+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 Option {
+ /**
+ * The name of the option that will be displayed to the user
+ */
+ String name();
+
+ /**
+ * The type of the option
+ */
+ OptionType type();
+
+ /**
+ * The category of the component
+ */
+ String category() default "General";
+
+ /**
+ * The subcategory of the component (displayed as header)
+ */
+ String subcategory();
+
+ /**
+ * The width of the option (1 = half width, 2 = full width)
+ */
+ int size() default 1;
+
+ /**
+ * A String array of all the possible values for the UniSelector, dropdownList, and ComboBox.
+ * Also used in the DualOption slider, index 0 is the left, index 1 is the right; for example:
+ * {"Option 1", "Option 2"}
+ */
+ String[] options() default {};
+
+ /**
+ * The places you want dividers to be in a dropdown
+ */
+ int[] dividers() default {};
+
+ /**
+ * The placeholder in the text field
+ */
+ String placeholder() default "";
+
+ /**
+ * If the text field is secure or not
+ */
+ boolean secure() default false;
+
+ /**
+ * If the text field is multi line or not
+ */
+ boolean multiLine() default false;
+
+ /**
+ * Minimum value of slider
+ */
+ float min() default 0;
+
+ /**
+ * The maximum value of the slider
+ */
+ float max() default 0;
+
+ /**
+ * Steps of slider (0 for no steps)
+ */
+ int step() default 0;
+
+ /**
+ * Option for info option type
+ */
+ InfoType infoType() default InfoType.INFO;
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/core/ConfigCore.java b/src/main/java/cc/polyfrost/oneconfig/config/core/ConfigCore.java
new file mode 100644
index 0000000..a000f7c
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/core/ConfigCore.java
@@ -0,0 +1,25 @@
+package cc.polyfrost.oneconfig.config.core;
+
+import cc.polyfrost.oneconfig.config.data.Mod;
+import cc.polyfrost.oneconfig.hud.HudCore;
+
+import java.util.ArrayList;
+
+public class ConfigCore {
+ public static ArrayList<Mod> oneConfigMods = new ArrayList<>();
+
+ public static void saveAll() {
+ for (Mod modData : oneConfigMods) {
+ modData.config.save();
+ }
+ }
+
+ public static void reInitAll() {
+ ArrayList<Mod> data = new ArrayList<>(oneConfigMods);
+ oneConfigMods.clear();
+ HudCore.huds.clear();
+ for (Mod modData : data) {
+ modData.config.init(modData);
+ }
+ }
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/data/InfoType.java b/src/main/java/cc/polyfrost/oneconfig/config/data/InfoType.java
new file mode 100644
index 0000000..1c436d6
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/data/InfoType.java
@@ -0,0 +1,8 @@
+package cc.polyfrost.oneconfig.config.data;
+
+public enum InfoType {
+ INFO,
+ WARNING,
+ ERROR,
+ SUCCESS
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/data/Mod.java b/src/main/java/cc/polyfrost/oneconfig/config/data/Mod.java
new file mode 100644
index 0000000..3ddb68b
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/data/Mod.java
@@ -0,0 +1,26 @@
+package cc.polyfrost.oneconfig.config.data;
+
+import cc.polyfrost.oneconfig.config.interfaces.Config;
+
+public class Mod {
+ public final String name;
+ public final ModType modType;
+ public final String creator;
+ public final String version;
+ public Config config;
+ public final OptionPage defaultPage;
+
+ /**
+ * @param name Friendly name of the mod
+ * @param modType Type of the mod (for example ModType.QOL)
+ * @param creator Creator of the mod
+ * @param version Version of the mod
+ */
+ public Mod(String name, ModType modType, String creator, String version) {
+ this.name = name;
+ this.modType = modType;
+ this.creator = creator;
+ this.version = version;
+ this.defaultPage = new OptionPage(name, this);
+ }
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/data/ModType.java b/src/main/java/cc/polyfrost/oneconfig/config/data/ModType.java
new file mode 100644
index 0000000..cbb4568
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/data/ModType.java
@@ -0,0 +1,10 @@
+package cc.polyfrost.oneconfig.config.data;
+
+public enum ModType {
+ PVP,
+ HUD,
+ UTIL_QOL,
+ HYPIXEL,
+ SKYBLOCK,
+ OTHER
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/data/OptionCategory.java b/src/main/java/cc/polyfrost/oneconfig/config/data/OptionCategory.java
new file mode 100644
index 0000000..14111f4
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/data/OptionCategory.java
@@ -0,0 +1,13 @@
+package cc.polyfrost.oneconfig.config.data;
+
+import cc.polyfrost.oneconfig.config.interfaces.BasicOption;
+import cc.polyfrost.oneconfig.gui.elements.config.ConfigPageButton;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+public class OptionCategory {
+ public final LinkedHashMap<String, ArrayList<BasicOption>> subcategories = new LinkedHashMap<>();
+ public final ArrayList<ConfigPageButton> topPages = new ArrayList<>();
+ public final ArrayList<ConfigPageButton> bottomPages = new ArrayList<>();
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/data/OptionPage.java b/src/main/java/cc/polyfrost/oneconfig/config/data/OptionPage.java
new file mode 100644
index 0000000..32a07b9
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/data/OptionPage.java
@@ -0,0 +1,19 @@
+package cc.polyfrost.oneconfig.config.data;
+
+import java.util.LinkedHashMap;
+
+public class OptionPage {
+ public final String name;
+ public final Mod mod;
+ /**
+ * Depth 1 = categories
+ * Depth 2 = subcategories
+ * Depth 3 = list of options
+ */
+ public final LinkedHashMap<String, OptionCategory> categories = new LinkedHashMap<>();
+
+ public OptionPage(String name, Mod mod) {
+ this.name = name;
+ this.mod = mod;
+ }
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/data/OptionType.java b/src/main/java/cc/polyfrost/oneconfig/config/data/OptionType.java
new file mode 100644
index 0000000..99dfb8b
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/data/OptionType.java
@@ -0,0 +1,36 @@
+package cc.polyfrost.oneconfig.config.data;
+
+public enum OptionType {
+ /**
+ * Type: boolean
+ */
+ SWITCH,
+ /**
+ * Type: boolean
+ */
+ CHECKBOX,
+ /**
+ * Type: boolean
+ */
+ DUAL_OPTION,
+ /**
+ * Type: int
+ */
+ UNI_SELECTOR,
+ /**
+ * Type: String
+ * Normal: 1x and 2x, Secure and Mutliline: 2x only
+ */
+ TEXT,
+ /**
+ * Type: int or float
+ */
+ SLIDER,
+ COLOR,
+ /**
+ * Type: int
+ */
+ DROPDOWN,
+ MULTI_DROPDOWN,
+ INFO
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/data/PageLocation.java b/src/main/java/cc/polyfrost/oneconfig/config/data/PageLocation.java
new file mode 100644
index 0000000..c66151d
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/data/PageLocation.java
@@ -0,0 +1,6 @@
+package cc.polyfrost.oneconfig.config.data;
+
+public enum PageLocation {
+ TOP,
+ BOTTOM
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/interfaces/BasicOption.java b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/BasicOption.java
new file mode 100644
index 0000000..2bf2d13
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/BasicOption.java
@@ -0,0 +1,81 @@
+package cc.polyfrost.oneconfig.config.interfaces;
+
+import java.lang.reflect.Field;
+
+@SuppressWarnings({"unused"})
+public abstract class BasicOption {
+ protected final Field field;
+ protected final String name;
+ public final int size;
+
+ /**
+ * Initialize option
+ *
+ * @param field variable attached to option (null for category)
+ * @param name name of option
+ * @param size size of option, 0 for single column, 1 for double.
+ */
+ public BasicOption(Field field, String name, int size) {
+ this.field = field;
+ this.name = name;
+ this.size = size;
+ if (field != null) field.setAccessible(true);
+ }
+
+ /**
+ * @param object Java object to set the variable to
+ */
+ protected void set(Object object) throws IllegalAccessException {
+ if (field == null) return;
+ field.set(null, object);
+ }
+
+ /**
+ * @return value of variable as Java object
+ */
+ protected Object get() throws IllegalAccessException {
+ if (field == null) return null;
+ return field.get(null);
+ }
+
+ /**
+ * @return height of option to align other options accordingly
+ */
+ public abstract int getHeight();
+
+ /**
+ * Function that gets called when drawing option
+ *
+ * @param vg NanoVG context
+ * @param x x position
+ * @param y y position
+ */
+ public abstract void draw(long vg, int x, int y);
+
+ /**
+ * Function that gets called last drawing option,
+ * should be used for things that draw above other options
+ *
+ * @param vg NanoVG context
+ * @param x x position
+ * @param y y position
+ */
+ public void drawLast(long vg, int x, int y) {
+ }
+
+ /**
+ * Function that gets called when a key is typed
+ *
+ * @param key char that has been typed
+ * @param keyCode code of key
+ */
+ public void keyTyped(char key, int keyCode) {
+ }
+
+ /**
+ * @return If the component has an option to render at half size
+ */
+ public boolean hasHalfSize() {
+ return true;
+ }
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/interfaces/Config.java b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/Config.java
new file mode 100644
index 0000000..bad3f14
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/Config.java
@@ -0,0 +1,180 @@
+package cc.polyfrost.oneconfig.config.interfaces;
+
+import cc.polyfrost.oneconfig.gui.elements.config.*;
+import com.google.gson.*;
+import cc.polyfrost.oneconfig.config.annotations.ConfigPage;
+import cc.polyfrost.oneconfig.config.annotations.Option;
+import cc.polyfrost.oneconfig.config.core.ConfigCore;
+import cc.polyfrost.oneconfig.config.data.Mod;
+import cc.polyfrost.oneconfig.config.data.OptionCategory;
+import cc.polyfrost.oneconfig.config.data.OptionPage;
+import cc.polyfrost.oneconfig.config.profiles.Profiles;
+import cc.polyfrost.oneconfig.gui.OneConfigGui;
+import cc.polyfrost.oneconfig.gui.pages.ModConfigPage;
+import net.minecraft.client.Minecraft;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Optional;
+
+public class Config {
+ protected final String configFile;
+ protected final Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).setPrettyPrinting().registerTypeAdapterFactory(OneConfigTypeAdapterFactory.getStaticTypeAdapterFactory()).create();
+ private static Mod mod;
+
+ /**
+ * @param modData information about the mod
+ * @param configFile file where config is stored
+ */
+ public Config(Mod modData, String configFile) {
+ this.configFile = configFile;
+ init(modData);
+ }
+
+ public void init(Mod mod) {
+ if (Profiles.getProfileFile(configFile).exists()) load();
+ else save();
+ mod.config = this;
+ generateOptionList(this.getClass(), mod.defaultPage, mod);
+ ConfigCore.oneConfigMods.add(mod);
+ Config.mod = mod;
+ }
+
+ /**
+ * Save current config to file
+ */
+ public void save() {
+ try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Profiles.getProfileFile(configFile).toPath()), StandardCharsets.UTF_8))) {
+ writer.write(gson.toJson(this.getClass()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Load file and overwrite current values
+ */
+ public void load() {
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(Profiles.getProfileFile(configFile).toPath()), StandardCharsets.UTF_8))) {
+ deserializePart(new JsonParser().parse(reader).getAsJsonObject(), this.getClass());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Generate the option list, for internal use only
+ *
+ * @param clazz target class
+ * @param page page to add options too
+ */
+ protected void generateOptionList(Class<?> clazz, OptionPage page, Mod mod) {
+ for (Field field : clazz.getDeclaredFields()) {
+ if (!field.isAnnotationPresent(Option.class) && !field.isAnnotationPresent(ConfigPage.class)) {
+ processCustomOption(field, page);
+ continue;
+ } else if (field.isAnnotationPresent(ConfigPage.class)) {
+ ConfigPage option = field.getAnnotation(ConfigPage.class);
+ if (!page.categories.containsKey(option.category()))
+ page.categories.put(option.category(), new OptionCategory());
+ OptionPage newPage = new OptionPage(option.name(), mod);
+ try {
+ field.setAccessible(true);
+ Object object = field.get(clazz);
+ generateOptionList(object.getClass(), newPage, mod);
+ switch (option.location()) {
+ case TOP:
+ page.categories.get(option.category()).topPages.add(new ConfigPageButton(field, option.name(), option.description(), newPage));
+ break;
+ case BOTTOM:
+ page.categories.get(option.category()).bottomPages.add(new ConfigPageButton(field, option.name(), option.description(), newPage));
+ break;
+ }
+ } catch (IllegalAccessException e) {
+ continue;
+ }
+ continue;
+ }
+ Option option = field.getAnnotation(Option.class);
+ if (!page.categories.containsKey(option.category()))
+ page.categories.put(option.category(), new OptionCategory());
+ if (!page.categories.get(option.category()).subcategories.containsKey(option.subcategory()))
+ page.categories.get(option.category()).subcategories.put(option.subcategory(), new ArrayList<>());
+ ArrayList<BasicOption> options = page.categories.get(option.category()).subcategories.get(option.subcategory());
+ switch (option.type()) {
+ case SWITCH:
+ options.add(new ConfigSwitch(field, option.name(), option.size()));
+ break;
+ case CHECKBOX:
+ options.add(new ConfigCheckbox(field, option.name(), option.size()));
+ break;
+ case TEXT:
+ options.add(new ConfigTextBox(field, option.name(), option.size(), option.placeholder(), option.secure(), option.multiLine()));
+ break;
+ case DUAL_OPTION:
+ options.add(new ConfigDualOption(field, option.name(), option.size(), option.options()));
+ break;
+ case UNI_SELECTOR:
+ options.add(new ConfigUniSelector(field, option.name(), option.size(), option.options()));
+ break;
+ case DROPDOWN:
+ options.add(new ConfigDropdown(field, option.name(), option.size(), option.options(), option.dividers()));
+ break;
+ case SLIDER:
+ options.add(new ConfigSlider(field, option.name(), option.size(), option.min(), option.max(), option.step()));
+ break;
+ }
+ }
+ }
+
+ /**
+ * Overwrite this method to add your own custom option types
+ *
+ * @param field target field
+ * @param page page to add options too
+ */
+ protected void processCustomOption(Field field, OptionPage page) {
+ }
+
+ /**
+ * Deserialize part of config and load values
+ *
+ * @param json json to deserialize
+ * @param clazz target class
+ */
+ 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()) {
+ 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 ignored) {
+ }
+ }
+ }
+
+ /**
+ * Function to open the gui of this mod
+ */
+ public void openGui() {
+ if (mod == null) return;
+ Minecraft.getMinecraft().displayGuiScreen(new OneConfigGui(new ModConfigPage(mod.defaultPage)));
+ }
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java
new file mode 100644
index 0000000..3368a7f
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapter.java
@@ -0,0 +1,51 @@
+package cc.polyfrost.oneconfig.config.interfaces;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+
+final class OneConfigTypeAdapter<T> extends TypeAdapter<Class<T>> {
+
+ private final Gson gson;
+ private final JsonParser parser = new JsonParser();
+
+ private OneConfigTypeAdapter(final Gson gson) {
+ this.gson = gson;
+ }
+
+ static <T> TypeAdapter<Class<T>> getStaticTypeAdapter(final Gson gson) {
+ return new OneConfigTypeAdapter<>(gson);
+ }
+
+ @Override
+ public void write(final JsonWriter out, final Class<T> value) throws IOException {
+ try {
+ out.beginObject();
+ for (Field field : value.getFields()) {
+ out.name(field.getName());
+ field.setAccessible(true);
+ final TypeAdapter<Object> adapter = (TypeAdapter) gson.getAdapter(field.getType());
+ adapter.write(out, field.get(field.getClass()));
+ }
+ for (Class<?> clazz : value.getClasses()) {
+ out.name(clazz.getSimpleName());
+ final TypeAdapter<JsonElement> adapter = gson.getAdapter(JsonElement.class);
+ adapter.write(out, parser.parse(gson.toJson(clazz)));
+ }
+ out.endObject();
+ } catch (final IllegalAccessException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ @Override
+ public Class<T> read(final JsonReader in) throws IOException {
+ return null;
+ }
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapterFactory.java b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapterFactory.java
new file mode 100644
index 0000000..d310f2c
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/OneConfigTypeAdapterFactory.java
@@ -0,0 +1,28 @@
+package cc.polyfrost.oneconfig.config.interfaces;
+
+import com.google.gson.Gson;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Type;
+
+public class OneConfigTypeAdapterFactory implements TypeAdapterFactory {
+
+ private static final TypeAdapterFactory staticTypeAdapterFactory = new OneConfigTypeAdapterFactory();
+
+ public static TypeAdapterFactory getStaticTypeAdapterFactory() {
+ return staticTypeAdapterFactory;
+ }
+
+ @Override
+ public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
+ final Type type = typeToken.getType();
+ if (type.equals(Class.class)) {
+ @SuppressWarnings("unchecked") final TypeAdapter<T> castStaticTypeAdapter = (TypeAdapter<T>) OneConfigTypeAdapter.getStaticTypeAdapter(gson);
+ return castStaticTypeAdapter;
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/interfaces/Size.java b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/Size.java
new file mode 100644
index 0000000..137e3fd
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/interfaces/Size.java
@@ -0,0 +1,6 @@
+package cc.polyfrost.oneconfig.config.interfaces;
+
+public enum Size {
+ SINGLE_COLUMN, // A single column, 480x32
+ DOUBLE_COLUMN // A double column, 992x32
+}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/profiles/Profiles.java b/src/main/java/cc/polyfrost/oneconfig/config/profiles/Profiles.java
new file mode 100644
index 0000000..4eafd6d
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/profiles/Profiles.java
@@ -0,0 +1,87 @@
+package cc.polyfrost.oneconfig.config.profiles;
+
+import cc.polyfrost.oneconfig.config.OneConfigConfig;
+import cc.polyfrost.oneconfig.OneConfig;
+import cc.polyfrost.oneconfig.config.core.ConfigCore;
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class Profiles {
+ private static final File profileDir = new File("OneConfig/profiles");
+ public static ArrayList<String> profiles;
+
+ public static String getCurrentProfile() {
+ if (!profileDir.exists() && !profileDir.mkdir()) {
+ System.out.println("Could not create profiles folder");
+ return null;
+ }
+ if (profiles == null) {
+ String[] profilesArray = new File("OneConfig/profiles").list((file, s) -> file.isDirectory());
+ if (profilesArray != null) profiles = new ArrayList<>(Arrays.asList(profilesArray));
+ }
+ if (!getProfileDir(OneConfigConfig.currentProfile).exists()) {
+ createProfile(OneConfigConfig.currentProfile);
+ }
+ return OneConfigConfig.currentProfile;
+ }
+
+ public static void createProfile(String name) {
+ File folder = new File(profileDir, name);
+ if (!folder.exists() && !folder.mkdir()) {
+ System.out.println("Could not create profile folder");
+ return;
+ }
+ profiles.add(name);
+ }
+
+ public static File getProfileDir() {
+ return getProfileDir(getCurrentProfile());
+ }
+
+ public static File getProfileDir(String profile) {
+ return new File(new File("OneConfig/profiles"), profile);
+ }
+
+ public static File getProfileFile(String file) {
+ return new File(getProfileDir(), 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 {
+ File newFile = new File(new File("OneConfig/profiles"), newName);
+ FileUtils.moveDirectory(getProfileDir(name), newFile);
+ if (OneConfigConfig.currentProfile.equals(name)) OneConfigConfig.currentProfile = newName;
+ profiles.remove(name);
+ profiles.add(newName);
+ } catch (IOException e) {
+ System.out.println("Failed to rename profile");
+ }
+ }
+
+ public static void deleteProfile(String name) {
+ if (name.equals(getCurrentProfile())) {
+ if (profiles.size() == 1) {
+ System.out.println("Cannot delete only profile!");
+ return;
+ }
+ loadProfile(profiles.stream().filter(entry -> !entry.equals(name)).findFirst().get());
+ }
+ try {
+ FileUtils.deleteDirectory(getProfileDir(name));
+ profiles.remove(name);
+ } catch (IOException e) {
+ System.out.println("Failed to delete profile");
+ }
+ }
+}