Even more abstraction to config stuff

This commit is contained in:
coolGi2007
2022-04-24 15:49:49 +10:00
parent 1f80084377
commit 3fb4d631ac
9 changed files with 199 additions and 118 deletions
+12 -21
View File
@@ -1,12 +1,13 @@
package com.seibel.lod.core;
import com.seibel.lod.core.config.*;
import com.seibel.lod.core.config.types.ConfigCategory;
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.core.enums.config.*;
import com.seibel.lod.core.enums.rendering.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import java.util.HashMap;
import java.util.Map;
/**
* This handles any configuration the user has access to.
@@ -30,19 +31,15 @@ public class Config
// |-> Buffers
// |-> Debugging
@ConfigAnnotations.Category
public static Client client;
public static ConfigCategory<Client> client = new ConfigCategory.Builder<Client>().set(new Client()).build();
public static class Client
{
@ConfigAnnotations.Category
public static Graphics graphics;
public static ConfigCategory<Graphics> graphics = new ConfigCategory.Builder<Graphics>().set(new Graphics()).build();
@ConfigAnnotations.Category
public static WorldGenerator worldGenerator;
public static ConfigCategory<WorldGenerator> worldGenerator = new ConfigCategory.Builder<WorldGenerator>().set(new WorldGenerator()).build();
@ConfigAnnotations.Category
public static Advanced advanced;
public static ConfigCategory<Advanced> advanced = new ConfigCategory.Builder<Advanced>().set(new Advanced()).build();
public static ConfigEntry<Boolean> optionsButton = new ConfigEntry.Builder<Boolean>()
@@ -57,14 +54,11 @@ public class Config
public static class Graphics
{
@ConfigAnnotations.Category
public static Quality quality;
public static ConfigCategory<Quality> quality = new ConfigCategory.Builder<Quality>().set(new Quality()).build();
@ConfigAnnotations.Category
public static FogQuality fogQuality;
public static ConfigCategory<FogQuality> fogQuality = new ConfigCategory.Builder<FogQuality>().set(new FogQuality()).build();
@ConfigAnnotations.Category
public static AdvancedGraphics advancedGraphics;
public static ConfigCategory<AdvancedGraphics> advancedGraphics = new ConfigCategory.Builder<AdvancedGraphics>().set(new AdvancedGraphics()).build();
public static class Quality
@@ -182,14 +176,11 @@ public class Config
public static class Advanced
{
@ConfigAnnotations.Category
public static Threading threading;
public static ConfigCategory<Threading> threading = new ConfigCategory.Builder<Threading>().set(new Threading()).build();
@ConfigAnnotations.Category
public static Debugging debugging;
public static ConfigCategory<Debugging> debugging = new ConfigCategory.Builder<Debugging>().set(new Debugging()).build();
@ConfigAnnotations.Category
public static Buffers buffers;
public static ConfigCategory<Buffers> buffers = new ConfigCategory.Builder<Buffers>().set(new Buffers()).build();
public static class Threading
@@ -14,32 +14,29 @@ import java.lang.annotation.Target;
*/
public class ConfigAnnotations {
/** For making categories */
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Category
{
/** Use com.seibel.lod.core.config.types.ConfigCategory instead of this */
public @interface Category {}
}
/**
* Makes text (looks like normal entry but doesn't save and has no button)
*
* Accepts string and the text is the value
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Comment
{
}
public @interface Comment {}
/**
* Adds a comment to the file,
* This should only be used in special cases where comments from an entry cant reach
*
* Accepts string and the text is the value
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FileComment
{
}
public @interface FileComment {}
}
@@ -2,8 +2,11 @@ package com.seibel.lod.core.config;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.config.file.ConfigFileHandling;
import com.seibel.lod.core.config.gui.AbstractScreen;
import com.seibel.lod.core.config.types.AbstractConfigType;
import com.seibel.lod.core.config.types.ConfigCategory;
import com.seibel.lod.core.config.types.ConfigEntry;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
@@ -20,12 +23,14 @@ public class ConfigBase {
What the config works with
Enum
Integer
Boolean
Double
Float
Byte
Map<String, ?>
Integer
Double
Long
// Float (to be tested)
String
Map<String, ?> // The ? should be another value from above
*/
public static final List<Class<?>> acceptableInputs = new ArrayList<>();
private static void addAcceptableInputs() {
@@ -33,14 +38,14 @@ public class ConfigBase {
acceptableInputs.add(Byte.class);
acceptableInputs.add(Short.class);
acceptableInputs.add(Integer.class);
acceptableInputs.add(Double.class);
acceptableInputs.add(Long.class);
acceptableInputs.add(Float.class);
// acceptableInputs.add(Float.class);
acceptableInputs.add(String.class);
acceptableInputs.add(HashMap.class);
}
public static final List<ConfigEntry<?>> entries = new ArrayList<ConfigEntry<?>>();
public static final List<String> categories = new ArrayList<>();
public static final List<AbstractConfigType<?>> entries = new ArrayList<>();
public static void init(Class<?> config) {
addAcceptableInputs(); // Add all of the acceptable stuff to the acceptableInputs list
@@ -55,25 +60,27 @@ public class ConfigBase {
// Put all the entries in entries
for (Field field : config.getFields()) {
if (ConfigEntry.class.isAssignableFrom(field.getType())) { // If item is type ConfigEntry
if (AbstractConfigType.class.isAssignableFrom(field.getType())) {
try {
if (isAcceptableType(((ConfigEntry<?>) field.get(field.getType())).get().getClass())) {
entries.add((ConfigEntry<?>) field.get(field.getType())); // Add to entries
entries.get(entries.size() - 1).category = category;
entries.get(entries.size() - 1).name = field.getName();
} else {
ClientApi.LOGGER.error("Invalid variable type at [" + (category.isEmpty() ? "" : category + ".") + field.getName() + "].");
ClientApi.LOGGER.error("Type [" + ((ConfigEntry<?>) field.get(field.getType())).get().getClass() + "] is not one of these types [" + acceptableInputs.toString() + "]");
}
entries.add((AbstractConfigType<?>) field.get(field.getType()));
} catch (IllegalAccessException exception) {
exception.printStackTrace();
}
}
if (field.isAnnotationPresent(ConfigAnnotations.Category.class)) { // If it's a category then init the stuff inside it and put it in the category list
String NCategory = (category.isEmpty() ? "" : category + ".") + field.getName();
categories.add(NCategory);
initNestedClass(field.getType(), NCategory);
AbstractConfigType<?> entry = entries.get(entries.size() - 1);
entry.category = category;
entry.name = field.getName();
if (ConfigEntry.class.isAssignableFrom(field.getType())) { // If item is type ConfigEntry
if (!isAcceptableType(((ConfigEntry<?>) entry).get().getClass())) {
ClientApi.LOGGER.error("Invalid variable type at [" + (category.isEmpty() ? "" : category + ".") + field.getName() + "].");
ClientApi.LOGGER.error("Type [" + ((ConfigEntry<?>) entry).get().getClass() + "] is not one of these types [" + acceptableInputs.toString() + "]");
}
}
if (ConfigCategory.class.isAssignableFrom(field.getType())) { // If it's a category then init the stuff inside it and put it in the category list
initNestedClass((entry.getType()), ((ConfigCategory) entry).getDestination());
}
}
}
}
@@ -0,0 +1,14 @@
package com.seibel.lod.core.config;
public enum ConfigEntryAppearance {
ALL(true, true),
ONLY_SHOW(true, false),
ONLY_IN_FILE(true, false);
public final boolean showInGui;
public final boolean showInFile; // If this is false then it wouldn't save the option
ConfigEntryAppearance(boolean showInGui, boolean showInFile) { // If both are false then the config won't touch the option
this.showInGui = showInGui;
this.showInFile = showInFile;
}
}
@@ -3,7 +3,8 @@ package com.seibel.lod.core.config.file;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.config.ConfigBase;
import com.seibel.lod.core.config.ConfigEntry;
import com.seibel.lod.core.config.types.AbstractConfigType;
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import org.json.simple.JSONObject;
@@ -34,9 +35,11 @@ public class ConfigFileHandling {
}
loadConfig(config);
for (ConfigEntry<?> entry : ConfigBase.entries) {
createComment(entry, config);
saveEntry(entry, config);
for (AbstractConfigType<?> entry : ConfigBase.entries) {
if (ConfigEntry.class.isAssignableFrom(entry.getClass())) {
createComment((ConfigEntry<?>) entry, config);
saveEntry((ConfigEntry<?>) entry, config);
}
}
config.close();
@@ -57,9 +60,11 @@ public class ConfigFileHandling {
}
// Load all the entries
for (ConfigEntry<?> entry : ConfigBase.entries) {
createComment(entry, config);
loadEntry(entry, config);
for (AbstractConfigType<?> entry : ConfigBase.entries) {
if (ConfigEntry.class.isAssignableFrom(entry.getClass())) {
createComment((ConfigEntry<?>) entry, config);
loadEntry((ConfigEntry<?>) entry, config);
}
}
config.close();
@@ -74,6 +79,8 @@ 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());
} else {
@@ -91,6 +98,8 @@ public class ConfigFileHandling {
// Loads an entry
@SuppressWarnings("unchecked") // Suppress due to its always safe. (I think. See reasons below.)
public static <T> void loadEntry(ConfigEntry<T> entry, CommentedFileConfig workConfig) {
if (!entry.getAppearance().showInFile)
return;
if (workConfig.contains(entry.getNameWCategory())) {
if (entry.get().getClass().isEnum()) {
// Safe cast due to above checking that <T> is indeed a Enum
@@ -0,0 +1,72 @@
package com.seibel.lod.core.config.types;
import com.seibel.lod.core.config.ConfigEntryAppearance;
/**
* The class where all config options should extend
*
* @author coolGi2007
*/
public abstract class AbstractConfigType<T> {
public String category = ""; // This should only be set once in the init
public String name; // This should only be set once in the init
protected T value;
protected ConfigEntryAppearance appearance;
public AbstractConfigType(ConfigEntryAppearance appearance, T value) {
this.appearance = appearance;
this.value = value;
}
/** Gets the value */
public T get() {
return this.value;
}
/** Sets the value */
public void set(T newValue) {
this.value = newValue;
}
public ConfigEntryAppearance getAppearance() {
return appearance;
}
public void setAppearance(ConfigEntryAppearance newAppearance) {
this.appearance = newAppearance;
}
/** Should not be needed for anything other than the gui/file handling */
public String getCategory() {
return this.category;
}
/** Should not be needed for anything other than the gui/file handling */
public String getName() {
return this.name;
}
/** Should not be needed for anything other than the gui/file handling */
public String getNameWCategory() {
return (this.category.isEmpty() ? "" : this.category + ".") + this.name;
}
// Gets the class of T
public Class<?> getType() {
return value.getClass();
}
protected static abstract class Builder<T> {
protected ConfigEntryAppearance tmpAppearance = ConfigEntryAppearance.ALL;
protected T tmpValue;
public this setAppearance(ConfigEntryAppearance newAppearance) {
this.tmpAppearance = newAppearance;
return this;
}
public this set(T newValue) {
this.tmpValue = newValue;
return this;
}
}
}
@@ -0,0 +1,33 @@
package com.seibel.lod.core.config.types;
import com.seibel.lod.core.config.ConfigEntryAppearance;
public class ConfigCategory<T> extends AbstractConfigType<T> {
private final String destination; // Where the category goes to
public ConfigCategory(ConfigEntryAppearance appearance, T value, String destination) {
super(appearance, value);
if (destination == null) {
this.destination = getNameWCategory();
} else {
this.destination = destination;
}
}
public String getDestination() {
return this.destination;
}
public static class Builder<T> extends AbstractConfigType.Builder<T> {
private String tmpDestination = null;
public Builder<T> setDestination(String newDestination) {
this.tmpDestination = newDestination;
return this;
}
public ConfigCategory<T> build() {
return new ConfigCategory(tmpAppearance, tmpValue, tmpDestination);
}
}
}
@@ -1,5 +1,6 @@
package com.seibel.lod.core.config;
package com.seibel.lod.core.config.types;
import com.seibel.lod.core.config.ConfigEntryAppearance;
import com.seibel.lod.core.config.file.ConfigFileHandling;
/**
@@ -7,25 +8,20 @@ import com.seibel.lod.core.config.file.ConfigFileHandling;
*
* @author coolGi2007
*/
public class ConfigEntry<T> {
public String category = ""; // This should only be set once in the init
public String name; // This should only be set once in the init
public class ConfigEntry<T> extends AbstractConfigType<T> {
private T value;
private T defaultValue;
private String comment;
private T min;
private T max;
private boolean show; // Show the option
/** Creates the entry */
private ConfigEntry(T value, String comment, T min, T max, boolean show) {
this.value = value;
private ConfigEntry(ConfigEntryAppearance appearance, T value, String comment, T min, T max) {
super(appearance, value);
this.defaultValue = value;
this.comment = comment;
this.min = min;
this.max = max;
this.show = show;
}
@@ -34,18 +30,15 @@ public class ConfigEntry<T> {
return this.defaultValue;
}
/** Gets the value */
public T get() {
return this.value;
}
/** Sets the value */
public void set(T new_value) {
this.value = new_value;
@Override
public void set(T newValue) {
this.value = newValue;
save();
}
/** Sets the value without saving */
public void setWTSave(T new_value) {
this.value = new_value;
public void setWTSave(T newValue) {
this.value = newValue;
}
/** Gets the min value */
@@ -64,14 +57,6 @@ public class ConfigEntry<T> {
public void setMax(T newMax) {
this.max = newMax;
}
/** Checks weather it should be shown */
public boolean getShow() {
return this.show;
}
/** Says to show the option */
public void setShow(boolean newShow) {
this.show = newShow;
}
/** Gets the comment */
public String getComment() {
@@ -83,20 +68,6 @@ public class ConfigEntry<T> {
}
/** Should not be needed for anything other than the gui/file handling */
public String getCategory() {
return this.category;
}
/** Should not be needed for anything other than the gui/file handling */
public String getName() {
return this.name;
}
/** Should not be needed for anything other than the gui/file handling */
public String getNameWCategory() {
return (this.category.isEmpty() ? "" : this.category + ".") + this.name;
}
/**
* Checks if the option is valid
*
@@ -142,18 +113,10 @@ public class ConfigEntry<T> {
}
}
// Use this so it dost do file handling stuff
public static class Builder<T> {
private T tmpValue;
public static class Builder<T> extends AbstractConfigType.Builder<T> {
private String tmpComment;
private T tmpMin;
private T tmpMax;
private boolean tmpShow = true;
public Builder<T> set(T newValue) {
this.tmpValue = newValue;
return this;
}
public Builder<T> comment(String newComment) {
this.tmpComment = newComment;
@@ -166,14 +129,9 @@ public class ConfigEntry<T> {
return this;
}
public Builder<T> showOption(boolean newShow) {
this.tmpShow = newShow;
return this;
}
public ConfigEntry<T> build() {
return new ConfigEntry<T>(tmpValue, tmpComment, tmpMin, tmpMax, tmpShow);
return new ConfigEntry<T>(tmpAppearance, tmpValue, tmpComment, tmpMin, tmpMax);
}
}
}
@@ -49,12 +49,12 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override
public boolean getOptionsButton()
{
return Config.client.optionsButton.get();
return Config.Client.optionsButton.get();
}
@Override
public void setOptionsButton(boolean newOptionsButton)
{
Config.client.optionsButton.set(newOptionsButton);
Config.Client.optionsButton.set(newOptionsButton);
}