diff --git a/Readme.md b/Readme.md index fb4edb825..e4d5e3791 100644 --- a/Readme.md +++ b/Readme.md @@ -17,5 +17,8 @@ It should be automatically included when pulling the full mod. XZ for Java (data compression)\ https://tukaani.org/xz/java.html -Toml for Java (config handeling)\ +Toml for Java (config handling)\ https://github.com/TheElectronWill/night-config + +Json for Java (config handling)\ +https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/core/config/ConfigBase.java b/src/main/java/com/seibel/lod/core/config/ConfigBase.java index fc3da99bd..6a587c838 100644 --- a/src/main/java/com/seibel/lod/core/config/ConfigBase.java +++ b/src/main/java/com/seibel/lod/core/config/ConfigBase.java @@ -9,7 +9,6 @@ import com.seibel.lod.core.config.types.ConfigEntry; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -43,13 +42,15 @@ public class ConfigBase { acceptableInputs.add(Long.class); // acceptableInputs.add(Float.class); acceptableInputs.add(String.class); - acceptableInputs.add(HashMap.class); // TODO[CONFIG]: This is handled separately to check the first input is String and the second input is valid + acceptableInputs.add(Map.class); // TODO[CONFIG]: This is handled separately to check the first input is String and the second input is valid } /** Disables the minimum and maximum of a variable */ public static boolean disableMinMax = false; // Very fun to use public static final List> entries = new ArrayList<>(); + public static final int configVersion = 1; + public static void init(Class config) { addAcceptableInputs(); // Add all of the acceptable stuff to the acceptableInputs list initNestedClass(config, ""); // Init root category diff --git a/src/main/java/com/seibel/lod/core/config/file/ConfigFileHandling.java b/src/main/java/com/seibel/lod/core/config/file/ConfigFileHandling.java index 670fdd5cb..208e142fe 100644 --- a/src/main/java/com/seibel/lod/core/config/file/ConfigFileHandling.java +++ b/src/main/java/com/seibel/lod/core/config/file/ConfigFileHandling.java @@ -90,12 +90,12 @@ public class ConfigFileHandling { // Save an entry @SuppressWarnings("unchecked") public static void saveEntry(ConfigEntry entry, CommentedFileConfig workConfig) { - if (!entry.getAppearance().showInFile) - return; - if (!entry.get().getClass().isAssignableFrom(HashMap.class)) { - workConfig.set(entry.getNameWCategory(), entry.get()); + if (!entry.getAppearance().showInFile) return; + + if (ConfigTypeConverters.convertObjects.containsKey(entry.getType())) { + workConfig.set(entry.getNameWCategory(), ConfigTypeConverters.convertToString(entry.getType(), entry.getTrueValue())); } else { - workConfig.set(entry.getNameWCategory(), getStringFromHashMap((HashMap) entry.get())); + workConfig.set(entry.getNameWCategory(), entry.getTrueValue()); } } @@ -108,28 +108,21 @@ public class ConfigFileHandling { } // Loads an entry - @SuppressWarnings("unchecked") // Suppress due to its always safe. (I think. See reasons below.) + @SuppressWarnings("unchecked") // Suppress due to its always safe public static void loadEntry(ConfigEntry entry, CommentedFileConfig workConfig) { - if (!entry.getAppearance().showInFile) - return; + if (!entry.getAppearance().showInFile) return; + if (workConfig.contains(entry.getNameWCategory())) { try { - if (entry.get().getClass().isEnum()) { - // Safe cast due to above checking that is indeed a Enum - // And the second cast back to is safe due to the template - entry.setWTSave((T) ( - workConfig.getEnum(entry.getNameWCategory(), (Class) entry.get().getClass()) - )); - } else if (entry.getType().isAssignableFrom(HashMap.class)) { - entry.setWTSave((T) getHashMapFromString(workConfig.get(entry.getNameWCategory()))); + if (entry.getType().isEnum()) { + entry.setWTSave((T) ( workConfig.getEnum(entry.getNameWCategory(), (Class) entry.getType()) )); + } else if (ConfigTypeConverters.convertObjects.containsKey(entry.getType())) { + entry.setWTSave((T) ConfigTypeConverters.convertFromString(entry.getType(), workConfig.get(entry.getNameWCategory()))); } else { entry.setWTSave((T) workConfig.get(entry.getNameWCategory())); - if (entry.isValid() == 0) - return; - else if (entry.isValid() == -1) - entry.setWTSave(entry.getMin()); - else if (entry.isValid() == 1) - entry.setWTSave(entry.getMax()); + if (entry.isValid() == 0) return; + else if (entry.isValid() == -1) entry.setWTSave(entry.getMin()); + else if (entry.isValid() == 1) entry.setWTSave(entry.getMax()); } } catch (Exception e) { e.printStackTrace(); @@ -176,29 +169,53 @@ public class ConfigFileHandling { } } - // Stuff for converting HashMap's and String's (uses json) - public static String getStringFromHashMap(HashMap item) { - JSONObject jsonObject = new JSONObject(); - for (int i=0; i< item.size(); i++) { - jsonObject.put(item.keySet().toArray()[i], item.get(item.keySet().toArray()[i])); + // ========== API (server) STUFF ========== // + @SuppressWarnings("unchecked") + /** ALWAYS CLEAR WHEN NOT ON SERVER!!!! */ + public static void clearApiValues() { + for (AbstractConfigType entry : ConfigBase.entries) { + if (ConfigEntry.class.isAssignableFrom(entry.getClass()) && ((ConfigEntry) entry).useApiOverwrite) { + ((ConfigEntry) entry).setApiValue(null); + } + } + } + @SuppressWarnings("unchecked") + public static String exportApiValues() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("configVersion", ConfigBase.configVersion); + for (AbstractConfigType entry : ConfigBase.entries) { + if (ConfigEntry.class.isAssignableFrom(entry.getClass()) && ((ConfigEntry) entry).useApiOverwrite) { + if (ConfigTypeConverters.convertObjects.containsKey(entry.getType())) { + jsonObject.put(entry.getNameWCategory(), ConfigTypeConverters.convertToString(entry.getType(), ((ConfigEntry) entry).getTrueValue())); + } else { + jsonObject.put(entry.getNameWCategory(), ((ConfigEntry) entry).getTrueValue()); + } + } } - return jsonObject.toJSONString(); } - public static HashMap getHashMapFromString(String s) { - HashMap map = new HashMap<>(); - + @SuppressWarnings("unchecked") // Suppress due to its always safe + public static void importApiValues(String values) { JSONObject jsonObject = null; try { - jsonObject = (JSONObject) new JSONParser().parse(s); + jsonObject = (JSONObject) new JSONParser().parse(values); } catch (ParseException p) { p.printStackTrace(); } - for (int i = 0; i < jsonObject.keySet().toArray().length; i++) { - map.put((String) jsonObject.keySet().toArray()[i], (T) jsonObject.get(jsonObject.keySet().toArray()[i])); + // Importing code + for (AbstractConfigType entry : ConfigBase.entries) { + if (ConfigEntry.class.isAssignableFrom(entry.getClass()) && ((ConfigEntry) entry).useApiOverwrite) { + Object jsonItem = jsonObject.get(entry.getNameWCategory()); + if (entry.getType().isEnum()) { + ((ConfigEntry) entry).setApiValue(Enum.valueOf((Class) entry.getType(), jsonItem.toString())); + } else if (ConfigTypeConverters.convertObjects.containsKey(entry.getType())) { + ((ConfigEntry) entry).setApiValue(ConfigTypeConverters.convertFromString(entry.getType(), jsonItem.toString())); + } else { + ((ConfigEntry) entry).setApiValue(jsonItem); + } + } } - return map; } } diff --git a/src/main/java/com/seibel/lod/core/config/file/ConfigTypeConverters.java b/src/main/java/com/seibel/lod/core/config/file/ConfigTypeConverters.java new file mode 100644 index 000000000..0fc325609 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/config/file/ConfigTypeConverters.java @@ -0,0 +1,74 @@ +package com.seibel.lod.core.config.file; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.util.HashMap; +import java.util.Map; + +public class ConfigTypeConverters { + // Once you've made a converter add it to here where the first value is the type you want to convert and the 2nd value is the converter + public static final Map convertObjects = new HashMap() {{ + put(Map.class, new MapConverter()); + }}; + + public static String convertToString(Class clazz, Object value) { + try { + return convertObjects.get(clazz).convertToString(value); + } catch (Exception e) { + System.out.println("Type [" + clazz.toString() + "] isnt a convertable value in the config file handler"); + return null; + } + } + public static Object convertFromString(Class clazz, String value) { + try { + return convertObjects.get(clazz).convertFromString(value); + } catch (Exception e) { + System.out.println("Type [" + clazz.toString() + "] isnt a convertable value in the config file handler"); + return null; + } + } + + + /** + * The converter should extend this + */ + public static abstract class ConverterBase { + public abstract String convertToString(Object value); + public abstract Object convertFromString(String value); + } + + + @SuppressWarnings("unchecked") + public static class MapConverter extends ConverterBase { + @Override + public String convertToString(Object item) { + Map mapObject = (Map) item; + JSONObject jsonObject = new JSONObject(); + + for (int i = 0; i < mapObject.size(); i++) { + jsonObject.put(mapObject.keySet().toArray()[i], mapObject.get(mapObject.keySet().toArray()[i])); + } + + return jsonObject.toJSONString(); + } + + @Override + public Map convertFromString(String s) { + Map map = new HashMap<>(); + + JSONObject jsonObject = null; + try { + jsonObject = (JSONObject) new JSONParser().parse(s); + } catch (ParseException p) { + p.printStackTrace(); + } + + for (int i = 0; i < jsonObject.keySet().toArray().length; i++) { + map.put((String) jsonObject.keySet().toArray()[i], jsonObject.get(jsonObject.keySet().toArray()[i])); + } + return map; + } + } +} diff --git a/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java b/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java index 68f2f14e3..1a6d5375a 100644 --- a/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java +++ b/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java @@ -16,7 +16,7 @@ public class ConfigEntry extends AbstractConfigType> { private T min; private T max; // Stuff for server overwrites - private final boolean useApiOverwrite; + public final boolean useApiOverwrite; private T apiValue; /** Creates the entry */ @@ -35,6 +35,9 @@ public class ConfigEntry extends AbstractConfigType> { return this.defaultValue; } + public void setApiValue(T newApiValue) { + this.apiValue = newApiValue; + } @Override public void set(T newValue) { this.value = newValue; @@ -46,6 +49,9 @@ public class ConfigEntry extends AbstractConfigType> { return apiValue; return value; } + public T getTrueValue() { + return value; + } public MinDefaultMax getMinValueMax() { return new MinDefaultMax(min, value, max);