diff options
Diffstat (limited to 'src/main/java/com/anthonyhilyard/iceberg/util/ConfigMenusForgeHelper.java')
-rw-r--r-- | src/main/java/com/anthonyhilyard/iceberg/util/ConfigMenusForgeHelper.java | 531 |
1 files changed, 265 insertions, 266 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/ConfigMenusForgeHelper.java b/src/main/java/com/anthonyhilyard/iceberg/util/ConfigMenusForgeHelper.java index ad4f8d5..6907a3d 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/util/ConfigMenusForgeHelper.java +++ b/src/main/java/com/anthonyhilyard/iceberg/util/ConfigMenusForgeHelper.java @@ -1,266 +1,265 @@ -package com.anthonyhilyard.iceberg.util; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Field; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; -import java.util.stream.Stream; - -import com.anthonyhilyard.iceberg.Loader; -import com.electronwill.nightconfig.core.CommentedConfig; -import com.electronwill.nightconfig.core.Config; -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import com.google.common.collect.Maps; -import com.google.common.base.Objects; -import com.google.common.collect.Iterators; - -import org.apache.commons.lang3.exception.ExceptionUtils; - -import fuzs.configmenusforge.client.gui.data.EntryData; -import fuzs.configmenusforge.client.gui.data.IEntryData; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TextComponent; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.fml.unsafe.UnsafeHacks; - -public class ConfigMenusForgeHelper -{ - private final static Map<Class<?>, List<MethodHandle>> configSpecMethodHandles = Maps.newHashMap(); - private final static Map<Class<?>, Boolean> cachedConfigSpecClasses = Maps.newHashMap(); - private final static MethodType getValuesMethodType = MethodType.methodType(UnmodifiableConfig.class); - private final static MethodType isLoadedMethodType = MethodType.methodType(boolean.class); - private final static MethodType saveMethodType = MethodType.methodType(void.class); - - private static Object callMethod(UnmodifiableConfig spec, int methodIndex) - { - Class<?> specClass = spec.getClass(); - if (!cachedConfigSpecClasses.containsKey(specClass)) - { - cacheClass(specClass); - } - - if (configSpecMethodHandles.containsKey(specClass)) - { - try - { - return configSpecMethodHandles.get(specClass).get(methodIndex).invoke(spec); - } - catch (Throwable e) - { - Loader.LOGGER.warn(ExceptionUtils.getStackTrace(e)); - } - } - return null; - } - - public static UnmodifiableConfig getValues(UnmodifiableConfig spec) - { - return (UnmodifiableConfig) callMethod(spec, 0); - } - - public static boolean isLoaded(UnmodifiableConfig spec) - { - return (Boolean) callMethod(spec, 1); - } - - public static void save(UnmodifiableConfig spec) - { - callMethod(spec, 2); - } - - public static Boolean cachedValidity(Class<?> specClass) - { - return cachedConfigSpecClasses.getOrDefault(specClass, null); - } - - public static void cacheClass(Class<?> specClass) - { - MethodHandle getValuesMethod = null; - MethodHandle isLoadedMethod = null; - MethodHandle saveMethod = null; - try - { - getValuesMethod = MethodHandles.lookup().findVirtual(specClass, "getValues", getValuesMethodType); - isLoadedMethod = MethodHandles.lookup().findVirtual(specClass, "isLoaded", isLoadedMethodType); - saveMethod = MethodHandles.lookup().findVirtual(specClass, "save", saveMethodType); - } - catch (Throwable e) - { - Loader.LOGGER.warn(ExceptionUtils.getStackTrace(e)); - } - - // If we found valid getValues, isLoaded and save methods, add them to the cache. - if (getValuesMethod != null && isLoadedMethod != null && saveMethod != null) - { - cachedConfigSpecClasses.put(specClass, true); - configSpecMethodHandles.put(specClass, List.of(getValuesMethod, isLoadedMethod, saveMethod)); - } - else - { - cachedConfigSpecClasses.put(specClass, false); - } - } - - /** - * Changed spec from a ForgeConfigSpec to an UnmodifiableConfig. - */ - public static void makeValueToDataMap(UnmodifiableConfig spec, UnmodifiableConfig values, CommentedConfig comments, Map<Object, IEntryData> allData, String basePath) - { - for (String path : values.valueMap().keySet()) - { - String currentPath = basePath.isEmpty() ? path : basePath + "." + path; - Object value = values.valueMap().get(path); - if (value instanceof UnmodifiableConfig category) - { - final EntryData.CategoryEntryData data = new EntryData.CategoryEntryData(path, category, comments.getComment(path)); - allData.put(category, data); - makeValueToDataMap(spec, category, (CommentedConfig) comments.valueMap().get(path), allData, currentPath); - } - else if (value instanceof ForgeConfigSpec.ConfigValue<?> configValue && configValue.get() instanceof UnmodifiableConfig category) - { - final EntryData.CategoryEntryData data = new DynamicCategoryEntryData(path, category, comments.getComment(path)); - allData.put(category, data); - makeValueToDataMap(spec, category, (CommentedConfig) comments.valueMap().get(path), allData, currentPath); - } - else if (value instanceof ForgeConfigSpec.ConfigValue<?> configValue) - { - final EntryData.ConfigEntryData<?> data = new EntryData.ConfigEntryData<>(path, configValue, spec.getRaw(configValue.getPath())); - allData.put(configValue, data); - } - // Allow non-configvalue values if the parent is a dynamic subconfig. - else if (!(value instanceof ForgeConfigSpec.ConfigValue<?>) && allData.containsKey(values) && allData.get(values) instanceof DynamicCategoryEntryData) - { - final EntryData.ConfigEntryData<?> data = new DynamicConfigEntryData<>(List.of(currentPath.split("\\.")), value, spec.getRaw(currentPath), spec); - allData.put(value, data); - } - } - } - - public static class DynamicCategoryEntryData extends EntryData.CategoryEntryData - { - public DynamicCategoryEntryData(String path, UnmodifiableConfig config, String comment) { - super(path, config, comment); - } - } - - public static class DynamicConfigEntryData<T> extends EntryData.ConfigEntryData<T> - { - private final ForgeConfigSpec.ValueSpec valueSpec; - private T currentValue; - private T configValue; - private final List<String> fullPath; - private final UnmodifiableConfig spec; - - private final static ForgeConfigSpec.ConfigValue<?> dummyConfigValue; - - private Component title; - - static - { - dummyConfigValue = UnsafeHacks.newInstance(ForgeConfigSpec.ConfigValue.class); - try - { - Field specField = ForgeConfigSpec.ConfigValue.class.getDeclaredField("spec"); - UnsafeHacks.setField(specField, dummyConfigValue, UnsafeHacks.newInstance(ForgeConfigSpec.class)); - Field defaultSupplierField = ForgeConfigSpec.ConfigValue.class.getDeclaredField("defaultSupplier"); - UnsafeHacks.setField(defaultSupplierField, dummyConfigValue, (Supplier<?>)(() -> null)); - } - catch (Exception e) { } - } - - @SuppressWarnings("unchecked") - public DynamicConfigEntryData(List<String> fullPath, T configValue, ForgeConfigSpec.ValueSpec valueSpec, UnmodifiableConfig spec) - { - super(fullPath.get(fullPath.size() - 1), (ForgeConfigSpec.ConfigValue<T>) dummyConfigValue, valueSpec); - this.configValue = configValue; - this.currentValue = configValue; - this.valueSpec = valueSpec; - this.fullPath = fullPath; - this.spec = spec; - - // We will override the normal title functionality since we want it to be unformatted. - this.title = new TextComponent(getPath()); - } - - @Override - public Component getTitle() - { - return this.title; - } - - @Override - public boolean mayResetValue() - { - return !listSafeEquals(currentValue, getDefaultValue()); - } - - @Override - public boolean mayDiscardChanges() - { - return listSafeEquals(configValue, currentValue); - } - - private static <T> boolean listSafeEquals(T o1, T o2) - { - // Attempts to solve an issue where types of lists won't match when one is read from file - // (due to enum being converted to string, long to int) - if (o1 instanceof List<?> list1 && o2 instanceof List<?> list2) - { - final Stream<String> stream1 = list1.stream().map(o -> o instanceof Enum<?> e ? e.name() : o.toString()); - final Stream<String> stream2 = list2.stream().map(o -> o instanceof Enum<?> e ? e.name() : o.toString()); - return Iterators.elementsEqual(stream1.iterator(), stream2.iterator()); - } - return Objects.equal(o1, o2); - } - - @Override - public void resetCurrentValue() - { - currentValue = getDefaultValue(); - } - - @Override - public void discardCurrentValue() - { - currentValue = configValue; - } - - @Override - public void saveConfigValue() - { - try - { - Field childConfigField = spec.getClass().getDeclaredField("childConfig"); - Config childConfig = UnsafeHacks.getField(childConfigField, spec); - childConfig.set(fullPath, currentValue); - } - catch (Exception e) { } - configValue = currentValue; - } - - @SuppressWarnings("unchecked") - public T getDefaultValue() - { - return (T) valueSpec.getDefault(); - } - - public T getCurrentValue() - { - return currentValue; - } - - public void setCurrentValue(T newValue) - { - currentValue = newValue; - } - - @Override - public List<String> getFullPath() - { - return fullPath; - } - } -}
\ No newline at end of file +// package com.anthonyhilyard.iceberg.util; + +// import java.lang.invoke.MethodHandle; +// import java.lang.invoke.MethodHandles; +// import java.lang.invoke.MethodType; +// import java.lang.reflect.Field; +// import java.util.List; +// import java.util.Map; +// import java.util.function.Supplier; +// import java.util.stream.Stream; + +// import com.anthonyhilyard.iceberg.Loader; +// import com.electronwill.nightconfig.core.CommentedConfig; +// import com.electronwill.nightconfig.core.Config; +// import com.electronwill.nightconfig.core.UnmodifiableConfig; +// import com.google.common.collect.Maps; +// import com.google.common.base.Objects; +// import com.google.common.collect.Iterators; + +// import org.apache.commons.lang3.exception.ExceptionUtils; + +// import fuzs.configmenusforge.client.gui.data.EntryData; +// import fuzs.configmenusforge.client.gui.data.IEntryData; +// import net.minecraft.network.chat.Component; +// import net.minecraftforge.common.ForgeConfigSpec; +// import net.minecraftforge.fml.unsafe.UnsafeHacks; + +// public class ConfigMenusForgeHelper +// { +// private final static Map<Class<?>, List<MethodHandle>> configSpecMethodHandles = Maps.newHashMap(); +// private final static Map<Class<?>, Boolean> cachedConfigSpecClasses = Maps.newHashMap(); +// private final static MethodType getValuesMethodType = MethodType.methodType(UnmodifiableConfig.class); +// private final static MethodType isLoadedMethodType = MethodType.methodType(boolean.class); +// private final static MethodType saveMethodType = MethodType.methodType(void.class); + +// private static Object callMethod(UnmodifiableConfig spec, int methodIndex) +// { +// Class<?> specClass = spec.getClass(); +// if (!cachedConfigSpecClasses.containsKey(specClass)) +// { +// cacheClass(specClass); +// } + +// if (configSpecMethodHandles.containsKey(specClass)) +// { +// try +// { +// return configSpecMethodHandles.get(specClass).get(methodIndex).invoke(spec); +// } +// catch (Throwable e) +// { +// Loader.LOGGER.warn(ExceptionUtils.getStackTrace(e)); +// } +// } +// return null; +// } + +// public static UnmodifiableConfig getValues(UnmodifiableConfig spec) +// { +// return (UnmodifiableConfig) callMethod(spec, 0); +// } + +// public static boolean isLoaded(UnmodifiableConfig spec) +// { +// return (Boolean) callMethod(spec, 1); +// } + +// public static void save(UnmodifiableConfig spec) +// { +// callMethod(spec, 2); +// } + +// public static Boolean cachedValidity(Class<?> specClass) +// { +// return cachedConfigSpecClasses.getOrDefault(specClass, null); +// } + +// public static void cacheClass(Class<?> specClass) +// { +// MethodHandle getValuesMethod = null; +// MethodHandle isLoadedMethod = null; +// MethodHandle saveMethod = null; +// try +// { +// getValuesMethod = MethodHandles.lookup().findVirtual(specClass, "getValues", getValuesMethodType); +// isLoadedMethod = MethodHandles.lookup().findVirtual(specClass, "isLoaded", isLoadedMethodType); +// saveMethod = MethodHandles.lookup().findVirtual(specClass, "save", saveMethodType); +// } +// catch (Throwable e) +// { +// Loader.LOGGER.warn(ExceptionUtils.getStackTrace(e)); +// } + +// // If we found valid getValues, isLoaded and save methods, add them to the cache. +// if (getValuesMethod != null && isLoadedMethod != null && saveMethod != null) +// { +// cachedConfigSpecClasses.put(specClass, true); +// configSpecMethodHandles.put(specClass, List.of(getValuesMethod, isLoadedMethod, saveMethod)); +// } +// else +// { +// cachedConfigSpecClasses.put(specClass, false); +// } +// } + +// /** +// * Changed spec from a ForgeConfigSpec to an UnmodifiableConfig. +// */ +// public static void makeValueToDataMap(UnmodifiableConfig spec, UnmodifiableConfig values, CommentedConfig comments, Map<Object, IEntryData> allData, String basePath) +// { +// for (String path : values.valueMap().keySet()) +// { +// String currentPath = basePath.isEmpty() ? path : basePath + "." + path; +// Object value = values.valueMap().get(path); +// if (value instanceof UnmodifiableConfig category) +// { +// final EntryData.CategoryEntryData data = new EntryData.CategoryEntryData(path, category, comments.getComment(path)); +// allData.put(category, data); +// makeValueToDataMap(spec, category, (CommentedConfig) comments.valueMap().get(path), allData, currentPath); +// } +// else if (value instanceof ForgeConfigSpec.ConfigValue<?> configValue && configValue.get() instanceof UnmodifiableConfig category) +// { +// final EntryData.CategoryEntryData data = new DynamicCategoryEntryData(path, category, comments.getComment(path)); +// allData.put(category, data); +// makeValueToDataMap(spec, category, (CommentedConfig) comments.valueMap().get(path), allData, currentPath); +// } +// else if (value instanceof ForgeConfigSpec.ConfigValue<?> configValue) +// { +// final EntryData.ConfigEntryData<?> data = new EntryData.ConfigEntryData<>(path, configValue, spec.getRaw(configValue.getPath())); +// allData.put(configValue, data); +// } +// // Allow non-configvalue values if the parent is a dynamic subconfig. +// else if (!(value instanceof ForgeConfigSpec.ConfigValue<?>) && allData.containsKey(values) && allData.get(values) instanceof DynamicCategoryEntryData) +// { +// final EntryData.ConfigEntryData<?> data = new DynamicConfigEntryData<>(List.of(currentPath.split("\\.")), value, spec.getRaw(currentPath), spec); +// allData.put(value, data); +// } +// } +// } + +// public static class DynamicCategoryEntryData extends EntryData.CategoryEntryData +// { +// public DynamicCategoryEntryData(String path, UnmodifiableConfig config, String comment) { +// super(path, config, comment); +// } +// } + +// public static class DynamicConfigEntryData<T> extends EntryData.ConfigEntryData<T> +// { +// private final ForgeConfigSpec.ValueSpec valueSpec; +// private T currentValue; +// private T configValue; +// private final List<String> fullPath; +// private final UnmodifiableConfig spec; + +// private final static ForgeConfigSpec.ConfigValue<?> dummyConfigValue; + +// private Component title; + +// static +// { +// dummyConfigValue = UnsafeHacks.newInstance(ForgeConfigSpec.ConfigValue.class); +// try +// { +// Field specField = ForgeConfigSpec.ConfigValue.class.getDeclaredField("spec"); +// UnsafeHacks.setField(specField, dummyConfigValue, UnsafeHacks.newInstance(ForgeConfigSpec.class)); +// Field defaultSupplierField = ForgeConfigSpec.ConfigValue.class.getDeclaredField("defaultSupplier"); +// UnsafeHacks.setField(defaultSupplierField, dummyConfigValue, (Supplier<?>)(() -> null)); +// } +// catch (Exception e) { } +// } + +// @SuppressWarnings("unchecked") +// public DynamicConfigEntryData(List<String> fullPath, T configValue, ForgeConfigSpec.ValueSpec valueSpec, UnmodifiableConfig spec) +// { +// super(fullPath.get(fullPath.size() - 1), (ForgeConfigSpec.ConfigValue<T>) dummyConfigValue, valueSpec); +// this.configValue = configValue; +// this.currentValue = configValue; +// this.valueSpec = valueSpec; +// this.fullPath = fullPath; +// this.spec = spec; + +// // We will override the normal title functionality since we want it to be unformatted. +// this.title = Component.literal(getPath()); +// } + +// @Override +// public Component getTitle() +// { +// return this.title; +// } + +// @Override +// public boolean mayResetValue() +// { +// return !listSafeEquals(currentValue, getDefaultValue()); +// } + +// @Override +// public boolean mayDiscardChanges() +// { +// return listSafeEquals(configValue, currentValue); +// } + +// private static <T> boolean listSafeEquals(T o1, T o2) +// { +// // Attempts to solve an issue where types of lists won't match when one is read from file +// // (due to enum being converted to string, long to int) +// if (o1 instanceof List<?> list1 && o2 instanceof List<?> list2) +// { +// final Stream<String> stream1 = list1.stream().map(o -> o instanceof Enum<?> e ? e.name() : o.toString()); +// final Stream<String> stream2 = list2.stream().map(o -> o instanceof Enum<?> e ? e.name() : o.toString()); +// return Iterators.elementsEqual(stream1.iterator(), stream2.iterator()); +// } +// return Objects.equal(o1, o2); +// } + +// @Override +// public void resetCurrentValue() +// { +// currentValue = getDefaultValue(); +// } + +// @Override +// public void discardCurrentValue() +// { +// currentValue = configValue; +// } + +// @Override +// public void saveConfigValue() +// { +// try +// { +// Field childConfigField = spec.getClass().getDeclaredField("childConfig"); +// Config childConfig = UnsafeHacks.getField(childConfigField, spec); +// childConfig.set(fullPath, currentValue); +// } +// catch (Exception e) { } +// configValue = currentValue; +// } + +// @SuppressWarnings("unchecked") +// public T getDefaultValue() +// { +// return (T) valueSpec.getDefault(); +// } + +// public T getCurrentValue() +// { +// return currentValue; +// } + +// public void setCurrentValue(T newValue) +// { +// currentValue = newValue; +// } + +// @Override +// public List<String> getFullPath() +// { +// return fullPath; +// } +// } +// }
\ No newline at end of file |