aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/cc/polyfrost/oneconfig/config/interfaces
diff options
context:
space:
mode:
authorDeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>2022-05-03 18:25:32 +0200
committerDeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>2022-05-03 18:25:32 +0200
commita0ff501947a84b268e099524a06b56a6b900dad2 (patch)
treedb27ca1b28dbc7e57b8c99f54c80732d3042e856 /src/main/java/cc/polyfrost/oneconfig/config/interfaces
parentb798930b21b89b81be05a31281f768667a6dd7f3 (diff)
downloadOneConfig-a0ff501947a84b268e099524a06b56a6b900dad2.tar.gz
OneConfig-a0ff501947a84b268e099524a06b56a6b900dad2.tar.bz2
OneConfig-a0ff501947a84b268e099524a06b56a6b900dad2.zip
move to cc.polyfrost
Diffstat (limited to 'src/main/java/cc/polyfrost/oneconfig/config/interfaces')
-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
5 files changed, 346 insertions, 0 deletions
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
+}