diff --git a/README.md b/README.md index 675a7ef..f47a9c8 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,11 @@ The details are a string representing a language key that can be used in your la The second constructor has an `onChange` parameter, which is a Consumer that is run every time this config is changed, which can be used to send data to clients on servers or trigger other events. -You can get the value from a `ConfigItem` with the `get` method. +You can get the value from a `ConfigItem` with the `getValue` method. + +#### Array Config Items + +`ArrayConfigItem`s are exactly the same as normal config items, but have a couple useful methods to get values based on their index. You cannot nest `ArrayConfigItem`s inside other `ArrayConfigItem`s ### Config Item Groups `ConfigItemGroup`s are a way to store multiple `ConfigItem`s into one group. `ConfigItemGroup`s can be nested in each other for sub groups. There is one constructor: @@ -117,21 +121,23 @@ public class TestConfig extends Config { public static class ConfigGroupLevel1 extends ConfigItemGroup { public static final ConfigItem testEnum = new ConfigItem<>("test_enum", EnumTest.A, "test_enum"); - public static final ConfigItem testItem = new ConfigItem("test_boolean", true, "test_boolean"); + public static final ConfigItem testItem = new ConfigItem<>("test_boolean", true, "test_boolean"); + + public static final ArrayConfigItem testArray = new ArrayConfigItem<>("test_array", new Integer[]{1, 2, 3}, "test_array"); public ConfigGroupLevel1() { - super(of(new NestedGroup(), testItem, testEnum), "group"); + super(of(new NestedGroup(), testItem, testEnum, testArray), "group"); } public static class NestedGroup extends ConfigItemGroup { - public static final ConfigItem nestedItem = new ConfigItem("test_int", 0, "test_integer"); + public static final ConfigItem nestedItem = new ConfigItem<>("test_int", 0, "test_integer"); public NestedGroup() { super(of(nestedItem, new TripleNested()), "nested"); } public static class TripleNested extends ConfigItemGroup { - public static final ConfigItem testString = new ConfigItem("test_string", "Default", "test_string"); + public static final ConfigItem testString = new ConfigItem<>("test_string", "Default", "test_string"); public TripleNested() { super(of(testString), "triple"); @@ -152,7 +158,12 @@ This then creates a config file called `oroarmor_config_testmod.json` in the `/c } }, "test_boolean": true, - "test_enum": "A" + "test_enum": "A", + "test_array": [ + 1, + 2, + 3 + ] } } ``` diff --git a/common/src/main/java/com/oroarmor/config/ArrayConfigItem.java b/common/src/main/java/com/oroarmor/config/ArrayConfigItem.java new file mode 100644 index 0000000..ec2f175 --- /dev/null +++ b/common/src/main/java/com/oroarmor/config/ArrayConfigItem.java @@ -0,0 +1,144 @@ +/* + * MIT License + * + * Copyright (c) 2021 OroArmor (Eli Orona) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.oroarmor.config; + +import java.util.Arrays; +import java.util.function.Consumer; + +import com.google.gson.JsonElement; +import org.jetbrains.annotations.Nullable; + +/** + * {@link ArrayConfigItem} stores an array of the supported types
+ * The current supported types are booleans, integers, doubles, strings, and + * {@link ConfigItemGroup} + * + * @param + * @author Eli Orona + */ +public class ArrayConfigItem extends ConfigItem { + + /** + * Creates a new config with the name, defaultValue, and details + * + * @param name The name for the config item + * @param defaultValue The default value in case of a corrupted/missing config + * @param details A translatable string for readability in multiple + * languages + */ + public ArrayConfigItem(String name, T[] defaultValue, String details) { + this(name, defaultValue, details, null); + } + + /** + * Creates a new config with the name, defaultValue, details, and an onChange + * consumer + * + * @param name The name for the config item + * @param defaultValue The default value in case of a corrupted/missing config + * @param details A translatable string for readability in multiple + * languages + * @param onChange A {@link Consumer} that is run every time the config item + * is modified + */ + public ArrayConfigItem(String name, T[] defaultValue, String details, @Nullable Consumer> onChange) { + super(name, defaultValue, details, onChange); + if(defaultValue[0] instanceof ArrayConfigItem) { + throw new UnsupportedOperationException("ArrayConfigItems cannot be nested"); + } + this.value = Arrays.copyOf(defaultValue, defaultValue.length); + } + + /** + * Reads and sets the {@link ConfigItem} from a JSON Element. Will throw an + * error if the type does not match the type of the {@link ConfigItem} + * + * @param element The JSON Element + */ + @SuppressWarnings("unchecked") + public void fromJson(JsonElement element) { + for(int i = 0; i < element.getAsJsonArray().size(); i++) { + T newValue; + JsonElement arrayElement = element.getAsJsonArray().get(i); + switch (this.type) { + case BOOLEAN: + newValue = (T) (Object) arrayElement.getAsBoolean(); + break; + + case INTEGER: + newValue = (T) (Object) arrayElement.getAsInt(); + break; + + case DOUBLE: + newValue = (T) (Object) arrayElement.getAsDouble(); + break; + + case STRING: + newValue = (T) arrayElement.getAsString(); + break; + + case ENUM: + newValue = (T) Arrays.stream(((T) defaultValue[i]).getClass().getEnumConstants()).filter(val -> val.toString().equals(arrayElement.getAsString())).findFirst().get(); + break; + + case GROUP: + ((ConfigItemGroup) defaultValue[i]).fromJson(arrayElement.getAsJsonObject()); + + default: + return; + } + value[i] = newValue; + } + if (value != null) { + setValue(value); + } + } + + /** + * @param position The position in the array for the value + * @return The default value of the {@link ConfigItem} + */ + public T getDefaultValue(int position) { + return this.defaultValue[position]; + } + + /** + * @param position The position in the array for the value + * @return The current value of the {@link ConfigItem} + */ + public T getValue(int position) { + return this.value[position]; + } + + /** + * Sets the value in {@code position} the {@link ArrayConfigItem} + * + * @param value The value to set + * @param position The position in the array for the value + */ + public void setValue(T value, int position) { + this.value[position] = value; + } +} diff --git a/common/src/main/java/com/oroarmor/config/ConfigItem.java b/common/src/main/java/com/oroarmor/config/ConfigItem.java index 138a19c..27d9b53 100644 --- a/common/src/main/java/com/oroarmor/config/ConfigItem.java +++ b/common/src/main/java/com/oroarmor/config/ConfigItem.java @@ -210,8 +210,11 @@ public static Type getTypeFrom(Object value) { return ENUM; } + if (value != null && value.getClass().isArray()) { + return getTypeFrom(((Object[]) value)[0]); + } + return null; } - } } diff --git a/common/src/main/java/com/oroarmor/config/ConfigItemGroup.java b/common/src/main/java/com/oroarmor/config/ConfigItemGroup.java index 8685283..d938969 100644 --- a/common/src/main/java/com/oroarmor/config/ConfigItemGroup.java +++ b/common/src/main/java/com/oroarmor/config/ConfigItemGroup.java @@ -29,6 +29,7 @@ import java.util.Map.Entry; import java.util.StringJoiner; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -111,6 +112,40 @@ private void parseConfig(ConfigItem c, JsonObject object) { } } + /** + * Turns an array config into a json property + * + * @param c The array config item + * @param object the json object + */ + private void parseArrayConfig(ArrayConfigItem c, JsonObject object) { + JsonArray array = new JsonArray(); + + for (int i = 0; i < c.getValue().length; i++) { + switch (c.getType()) { + case BOOLEAN: + array.add((Boolean) c.getValue(i)); + break; + case DOUBLE: + case INTEGER: + array.add((Number) c.getValue(i)); + break; + case STRING: + array.add((String) c.getValue(i)); + break; + case ENUM: + array.add(c.getValue(i).toString()); + break; + case GROUP: + array.add(((ConfigItemGroup) c.getValue(i)).toJson()); + default: + break; + } + } + + object.add(c.getName(), array); + } + /** * Converts the config items into json * @@ -120,7 +155,10 @@ public JsonObject toJson() { JsonObject object = new JsonObject(); for (ConfigItem c : configs) { - parseConfig(c, object); + if (!(c instanceof ArrayConfigItem)) + parseConfig(c, object); + else + parseArrayConfig((ArrayConfigItem) c, object); } return object; diff --git a/common/src/main/java/com/oroarmor/config/command/ConfigCommand.java b/common/src/main/java/com/oroarmor/config/command/ConfigCommand.java index 04d5bbf..fe61958 100644 --- a/common/src/main/java/com/oroarmor/config/command/ConfigCommand.java +++ b/common/src/main/java/com/oroarmor/config/command/ConfigCommand.java @@ -24,14 +24,18 @@ package com.oroarmor.config.command; +import java.util.Arrays; + import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.DoubleArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.oroarmor.config.ArrayConfigItem; import com.oroarmor.config.Config; import com.oroarmor.config.ConfigItem; import com.oroarmor.config.ConfigItem.Type; @@ -86,6 +90,35 @@ protected MutableText createItemText(ConfigItem item, ConfigItemGroup group) return configListText; } + protected MutableText createArrayItemText(ArrayConfigItem item, ConfigItemGroup group) { + MutableText configListText = new LiteralText(""); + boolean atDefault = Arrays.equals(item.getDefaultValue(), item.getValue()); + configListText.append(new LiteralText("[" + I18n.translate(item.getDetails()) + "]")); + configListText.append(" : "); + + StringBuilder array = new StringBuilder(); + for (int i = 0; i < item.getValue().length; i++) { + if (i != 0) { + array.append(", "); + } + array.append(item.getValue(i)); + } + + StringBuilder defaultArray = new StringBuilder(); + for (int i = 0; i < item.getDefaultValue().length; i++) { + if (i != 0) { + defaultArray.append(", "); + } + defaultArray.append(item.getDefaultValue(i)); + } + + configListText.append(new LiteralText("[" + array.toString() + "]") + .formatted(atDefault ? Formatting.GREEN : Formatting.DARK_GREEN) + .styled(s -> s.withHoverEvent(new HoverEvent(Action.SHOW_TEXT, new LiteralText((atDefault ? "At Default " : "") + "Value: " + (atDefault ? defaultArray.toString() + ". Click to change value." : array.toString() + ". Click to reset value.")))) + .withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + config.getID() + " " + group.getName() + " " + item.getName() + " " + (atDefault ? "value" : item.getDefaultValue()))))); + return configListText; + } + private int listConfigGroup(CommandContext c, ConfigItemGroup group) { MutableText configList = new LiteralText(""); @@ -135,7 +168,7 @@ protected void parseConfigItemText(MutableText configList, ConfigItemGroup group } configList.append(padding + "/\n"); } else { - configList.append(createItemText(item, group)); + configList.append(item instanceof ArrayConfigItem ? createArrayItemText((ArrayConfigItem) item, group) : createItemText(item, group)); configList.append("\n"); } } @@ -169,28 +202,57 @@ protected void parseConfigItemGroupCommand(LiteralArgumentBuilder configItemCommand = literal(item.getName()).executes((c) -> listItem(c, item, group)); - switch (item.getType()) { - case BOOLEAN: - configItemCommand.then(argument("boolean", BoolArgumentType.bool()).executes(c -> setItemBoolean(c, (ConfigItem) item, group))); - break; - case DOUBLE: - configItemCommand.then(argument("double", DoubleArgumentType.doubleArg()).executes(c -> setItemDouble(c, (ConfigItem) item, group))); - break; - case INTEGER: - configItemCommand.then(argument("int", IntegerArgumentType.integer()).executes(c -> setItemInteger(c, (ConfigItem) item, group))); - break; - case STRING: - configItemCommand.then(argument("string", StringArgumentType.string()).executes(c -> setItemString(c, (ConfigItem) item, group))); - break; - case ENUM: - Enum[] enums = ((Enum) item.getValue()).getClass().getEnumConstants(); - for (Enum _enum : enums) { - configItemCommand.then(literal(_enum.toString()).executes(c -> setItemEnum(c, _enum, (ConfigItem>) item, group))); - } - break; - - default: - break; + if (item instanceof ArrayConfigItem) { + RequiredArgumentBuilder arrayIndex = argument("index", IntegerArgumentType.integer(0, ((ArrayConfigItem) item).getValue().length)); + + switch (item.getType()) { + case BOOLEAN: + arrayIndex.then(argument("boolean", BoolArgumentType.bool()).executes(c -> setArrayItemBoolean(c, (ArrayConfigItem) item, group))); + break; + case DOUBLE: + arrayIndex.then(argument("double", DoubleArgumentType.doubleArg()).executes(c -> setArrayItemDouble(c, (ArrayConfigItem) item, group))); + break; + case INTEGER: + arrayIndex.then(argument("int", IntegerArgumentType.integer()).executes(c -> setArrayItemInteger(c, (ArrayConfigItem) item, group))); + break; + case STRING: + arrayIndex.then(argument("string", StringArgumentType.string()).executes(c -> setArrayItemString(c, (ArrayConfigItem) item, group))); + break; + case ENUM: + Enum[] enums = ((Enum) item.getValue()).getClass().getEnumConstants(); + for (Enum _enum : enums) { + arrayIndex.then(literal(_enum.toString()).executes(c -> setArrayItemEnum(c, _enum, (ArrayConfigItem>) item, group))); + } + break; + + default: + break; + } + configItemCommand.then(arrayIndex); + } else { + switch (item.getType()) { + case BOOLEAN: + configItemCommand.then(argument("boolean", BoolArgumentType.bool()).executes(c -> setItemBoolean(c, (ConfigItem) item, group))); + break; + case DOUBLE: + configItemCommand.then(argument("double", DoubleArgumentType.doubleArg()).executes(c -> setItemDouble(c, (ConfigItem) item, group))); + break; + case INTEGER: + configItemCommand.then(argument("int", IntegerArgumentType.integer()).executes(c -> setItemInteger(c, (ConfigItem) item, group))); + break; + case STRING: + configItemCommand.then(argument("string", StringArgumentType.string()).executes(c -> setItemString(c, (ConfigItem) item, group))); + break; + case ENUM: + Enum[] enums = ((Enum) item.getValue()).getClass().getEnumConstants(); + for (Enum _enum : enums) { + configItemCommand.then(literal(_enum.toString()).executes(c -> setItemEnum(c, _enum, (ConfigItem>) item, group))); + } + break; + + default: + break; + } } configGroupCommand.then(configItemCommand); } @@ -227,4 +289,39 @@ protected int setAndSaveConfig(CommandContext c, Config config.saveConfigToFile(); return 1; } + + protected int setArrayItemBoolean(CommandContext c, ArrayConfigItem item, ConfigItemGroup group) { + int index = IntegerArgumentType.getInteger(c, "index"); + boolean result = BoolArgumentType.getBool(c, "boolean"); + return setArrayAndSaveConfig(c, item, result, index); + } + + protected int setArrayItemDouble(CommandContext c, ArrayConfigItem item, ConfigItemGroup group) { + int index = IntegerArgumentType.getInteger(c, "index"); + double result = DoubleArgumentType.getDouble(c, "double"); + return setArrayAndSaveConfig(c, item, result, index); + } + + protected int setArrayItemInteger(CommandContext c, ArrayConfigItem item, ConfigItemGroup group) { + int index = IntegerArgumentType.getInteger(c, "index"); + int result = IntegerArgumentType.getInteger(c, "int"); + return setArrayAndSaveConfig(c, item, result, index); + } + + private int setArrayItemString(CommandContext c, ArrayConfigItem item, ConfigItemGroup group) { + int index = IntegerArgumentType.getInteger(c, "index"); + String result = StringArgumentType.getString(c, "string"); + return setArrayAndSaveConfig(c, item, result, index); + } + + private int setArrayItemEnum(CommandContext c, Enum _enum, ArrayConfigItem> item, ConfigItemGroup group) { + int index = IntegerArgumentType.getInteger(c, "index"); + return setArrayAndSaveConfig(c, item, _enum, index); + } + + protected int setArrayAndSaveConfig(CommandContext c, ArrayConfigItem item, T result, int index) { + item.setValue(result, index); + config.saveConfigToFile(); + return 1; + } } diff --git a/common/src/main/java/com/oroarmor/config/screen/ConfigScreen.java b/common/src/main/java/com/oroarmor/config/screen/ConfigScreen.java index 7e8d0cc..d9cddf2 100644 --- a/common/src/main/java/com/oroarmor/config/screen/ConfigScreen.java +++ b/common/src/main/java/com/oroarmor/config/screen/ConfigScreen.java @@ -24,9 +24,11 @@ package com.oroarmor.config.screen; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import com.oroarmor.config.ArrayConfigItem; import com.oroarmor.config.Config; import com.oroarmor.config.ConfigItem; import com.oroarmor.config.ConfigItemGroup; @@ -110,6 +112,68 @@ private AbstractConfigListEntry createStringConfigItem(ConfigItem ci, return entryBuilder.startStrField(new TranslatableText(ci.getDetails()), ci.getValue()).setSaveConsumer(ci::setValue).setDefaultValue(ci::getDefaultValue).build(); } + private void setupBooleanArrayConfigItem(ArrayConfigItem ci, ConfigCategory category, ConfigEntryBuilder entryBuilder) { + category.addEntry(createBooleanArrayConfigItem(ci, entryBuilder)); + } + + private void setupDoubleArrayConfigItem(ArrayConfigItem ci, ConfigCategory category, ConfigEntryBuilder entryBuilder) { + category.addEntry(createDoubleArrayConfigItem(ci, entryBuilder)); + } + + private void setupIntegerArrayConfigItem(ArrayConfigItem ci, ConfigCategory category, ConfigEntryBuilder entryBuilder) { + category.addEntry(createIntegerArrayConfigItem(ci, entryBuilder)); + } + + private void setupStringArrayConfigItem(ArrayConfigItem ci, ConfigCategory category, ConfigEntryBuilder entryBuilder) { + category.addEntry(createStringArrayConfigItem(ci, entryBuilder)); + } + + protected void setupEnumArrayConfigItem(ArrayConfigItem> ci, ConfigCategory category, ConfigEntryBuilder entryBuilder) { + category.addEntry(createEnumArrayConfigItem(ci, entryBuilder)); + } + + private AbstractConfigListEntry createBooleanArrayConfigItem(ArrayConfigItem ci, ConfigEntryBuilder entryBuilder) { + List configs = new ArrayList<>(); + for (int i = 0; i < ci.getValue().length; i++) { + int finalI = i; + AbstractConfigListEntry entry = entryBuilder.startBooleanToggle(new TranslatableText(ci.getDetails()).append(": " + i), ci.getValue(i)).setSaveConsumer(val -> ci.setValue(val, finalI)).setDefaultValue(() -> ci.getDefaultValue(finalI)).build(); + configs.add(entry); + } + + return entryBuilder.startSubCategory(new TranslatableText(ci.getDetails()), configs).build(); + } + + private AbstractConfigListEntry createDoubleArrayConfigItem(ArrayConfigItem ci, ConfigEntryBuilder entryBuilder) { + List configs = new ArrayList<>(); + for (int i = 0; i < ci.getValue().length; i++) { + int finalI = i; + AbstractConfigListEntry entry = entryBuilder.startDoubleField(new TranslatableText(ci.getDetails()).append(": " + i), ci.getValue(i)).setSaveConsumer(val -> ci.setValue(val, finalI)).setDefaultValue(() -> ci.getDefaultValue(finalI)).build(); + configs.add(entry); + } + + return entryBuilder.startSubCategory(new TranslatableText(ci.getDetails()), configs).build(); + } + + private AbstractConfigListEntry createIntegerArrayConfigItem(ArrayConfigItem ci, ConfigEntryBuilder entryBuilder) { + List configs = new ArrayList<>(); + for (int i = 0; i < ci.getValue().length; i++) { + int finalI = i; + AbstractConfigListEntry entry = entryBuilder.startIntField(new TranslatableText(ci.getDetails()).append(": " + i), ci.getValue(i)).setSaveConsumer(val -> ci.setValue(val, finalI)).setDefaultValue(() -> ci.getDefaultValue(finalI)).build(); + configs.add(entry); + } + return entryBuilder.startSubCategory(new TranslatableText(ci.getDetails()), configs).build(); + } + + private AbstractConfigListEntry createStringArrayConfigItem(ArrayConfigItem ci, ConfigEntryBuilder entryBuilder) { + List configs = new ArrayList<>(); + for (int i = 0; i < ci.getValue().length; i++) { + int finalI = i; + AbstractConfigListEntry entry = entryBuilder.startStrField(new TranslatableText(ci.getDetails()).append(": " + i), ci.getValue(i)).setSaveConsumer(val -> ci.setValue(val, finalI)).setDefaultValue(() -> ci.getDefaultValue(finalI)).build(); + configs.add(entry); + } + return entryBuilder.startSubCategory(new TranslatableText(ci.getDetails()), configs).build(); + } + @SuppressWarnings("unchecked") private > AbstractConfigListEntry createEnumConfigItem(ConfigItem> ci, ConfigEntryBuilder entryBuilder) { return entryBuilder.startEnumSelector(new TranslatableText(ci.getDetails()), (Class) ((Enum) ci.getValue()).getClass().getEnumConstants()[0].getClass(), (T) ci.getValue()) @@ -117,55 +181,123 @@ private > AbstractConfigListEntry createEnumConfigItem(Conf .setDefaultValue(() -> (T) ci.getValue()).build(); } + private > AbstractConfigListEntry createEnumArrayConfigItem(ArrayConfigItem> ci, ConfigEntryBuilder entryBuilder) { + List configs = new ArrayList<>(); + for (int i = 0; i < ci.getValue().length; i++) { + int finalI = i; + AbstractConfigListEntry entry = entryBuilder.startEnumSelector(new TranslatableText(ci.getDetails()).append(": " + i), (Class) ((Enum) ci.getValue(i)).getClass().getEnumConstants()[0].getClass(), (T) ci.getValue(i)).setSaveConsumer(val -> ci.setValue(val, finalI)).setDefaultValue(() -> (T) ci.getDefaultValue(finalI)).build(); + configs.add(entry); + } + + return entryBuilder.startSubCategory(new TranslatableText(ci.getDetails()), configs).build(); + } + @SuppressWarnings({"unchecked", "rawtypes"}) protected void setupConfigItem(ConfigItem ci, ConfigCategory category, ConfigEntryBuilder entryBuilder) { - switch (ci.getType()) { - case BOOLEAN: - setupBooleanConfigItem((ConfigItem) ci, category, entryBuilder); - break; - case DOUBLE: - setupDoubleConfigItem((ConfigItem) ci, category, entryBuilder); - break; - case GROUP: - List entryList = ((ConfigItemGroup) ci).getConfigs().stream().map(configItem -> createConfigItem(configItem, entryBuilder, category.getCategoryKey().getString() + "." + ci.getName())).collect(Collectors.toList()); - SubCategoryBuilder groupCategory = entryBuilder.startSubCategory(new TranslatableText(category.getCategoryKey().getString() + "." + ci.getName()), entryList); - category.addEntry(groupCategory.build()); - break; - case INTEGER: - setupIntegerConfigItem((ConfigItem) ci, category, entryBuilder); - break; - case STRING: - setupStringConfigItem((ConfigItem) ci, category, entryBuilder); - break; - case ENUM: - setupEnumConfigItem((ConfigItem>) ci, category, entryBuilder); - default: - break; + if (!(ci instanceof ArrayConfigItem)) { + switch (ci.getType()) { + case BOOLEAN: + setupBooleanConfigItem((ConfigItem) ci, category, entryBuilder); + break; + case DOUBLE: + setupDoubleConfigItem((ConfigItem) ci, category, entryBuilder); + break; + case GROUP: + List entryList = ((ConfigItemGroup) ci).getConfigs().stream().map(configItem -> createConfigItem(configItem, entryBuilder, category.getCategoryKey().getString() + "." + ci.getName())).collect(Collectors.toList()); + SubCategoryBuilder groupCategory = entryBuilder.startSubCategory(new TranslatableText(category.getCategoryKey().getString() + "." + ci.getName()), entryList); + category.addEntry(groupCategory.build()); + break; + case INTEGER: + setupIntegerConfigItem((ConfigItem) ci, category, entryBuilder); + break; + case STRING: + setupStringConfigItem((ConfigItem) ci, category, entryBuilder); + break; + case ENUM: + setupEnumConfigItem((ConfigItem>) ci, category, entryBuilder); + default: + break; + } + } else { + switch (ci.getType()) { + case BOOLEAN: + setupBooleanArrayConfigItem((ArrayConfigItem) ci, category, entryBuilder); + break; + case DOUBLE: + setupDoubleArrayConfigItem((ArrayConfigItem) ci, category, entryBuilder); + break; + case GROUP: + List subList = new ArrayList<>(); + for (int i = 0; i < ((ArrayConfigItem) ci).getValue().length; i++) { + int finalI = i; + List entryList = (((ArrayConfigItem) ci).getValue(i)).getConfigs().stream().map(configItem -> createConfigItem(configItem, entryBuilder, category.getCategoryKey().getString() + "." + ((ArrayConfigItem) ci).getValue(finalI).getName())).collect(Collectors.toList()); + SubCategoryBuilder groupCategory = entryBuilder.startSubCategory(new TranslatableText(category.getCategoryKey().getString() + "." + ((ArrayConfigItem) ci).getValue(finalI).getName()), entryList); + subList.add(groupCategory.build()); + } + + category.addEntry(entryBuilder.startSubCategory(new TranslatableText(category.getCategoryKey().getString() + "." + (ci).getName()), subList).build()); + break; + case INTEGER: + setupIntegerArrayConfigItem((ArrayConfigItem) ci, category, entryBuilder); + break; + case STRING: + setupStringArrayConfigItem((ArrayConfigItem) ci, category, entryBuilder); + break; + case ENUM: + setupEnumArrayConfigItem((ArrayConfigItem>) ci, category, entryBuilder); + default: + break; + } } } @SuppressWarnings({"unchecked", "rawtypes"}) private AbstractConfigListEntry createConfigItem(ConfigItem ci, ConfigEntryBuilder entryBuilder, String superGroupName) { - switch (ci.getType()) { - case BOOLEAN: - return createBooleanConfigItem((ConfigItem) ci, entryBuilder); - case DOUBLE: - return createDoubleConfigItem((ConfigItem) ci, entryBuilder); - case INTEGER: - return createIntegerConfigItem((ConfigItem) ci, entryBuilder); - case STRING: - return createStringConfigItem((ConfigItem) ci, entryBuilder); - - case ENUM: - return createEnumConfigItem((ConfigItem>) ci, entryBuilder); - case GROUP: - List subItems = ((ConfigItemGroup) ci).getConfigs().stream().map(configItem -> createConfigItem(configItem, entryBuilder, superGroupName + "." + ci.getName())).collect(Collectors.toList()); - SubCategoryBuilder groupCategory = entryBuilder.startSubCategory(new TranslatableText(superGroupName + "." + ci.getName()), subItems); - return groupCategory.build(); - default: - return null; + if (!(ci instanceof ArrayConfigItem)) { + switch (ci.getType()) { + case BOOLEAN: + return createBooleanConfigItem((ConfigItem) ci, entryBuilder); + case DOUBLE: + return createDoubleConfigItem((ConfigItem) ci, entryBuilder); + case INTEGER: + return createIntegerConfigItem((ConfigItem) ci, entryBuilder); + case STRING: + return createStringConfigItem((ConfigItem) ci, entryBuilder); + case ENUM: + return createEnumConfigItem((ConfigItem>) ci, entryBuilder); + case GROUP: + List subItems = ((ConfigItemGroup) ci).getConfigs().stream().map(configItem -> createConfigItem(configItem, entryBuilder, superGroupName + "." + ci.getName())).collect(Collectors.toList()); + SubCategoryBuilder groupCategory = entryBuilder.startSubCategory(new TranslatableText(superGroupName + "." + ci.getName()), subItems); + return groupCategory.build(); + default: + return null; + } + } else { + switch (ci.getType()) { + case BOOLEAN: + return createBooleanArrayConfigItem((ArrayConfigItem) ci, entryBuilder); + case DOUBLE: + return createDoubleArrayConfigItem((ArrayConfigItem) ci, entryBuilder); + case INTEGER: + return createIntegerArrayConfigItem((ArrayConfigItem) ci, entryBuilder); + case STRING: + return createStringArrayConfigItem((ArrayConfigItem) ci, entryBuilder); + case ENUM: + return createEnumArrayConfigItem((ArrayConfigItem>) ci, entryBuilder); + case GROUP: + List subList = new ArrayList<>(); + for (int i = 0; i < ((ArrayConfigItem) ci).getValue().length; i++) { + int finalI = i; + List entryList = (((ArrayConfigItem) ci).getValue(i)).getConfigs().stream().map(configItem -> createConfigItem(configItem, entryBuilder, superGroupName + "." + ((ArrayConfigItem) ci).getValue(finalI).getName())).collect(Collectors.toList()); + SubCategoryBuilder groupCategory = entryBuilder.startSubCategory(new TranslatableText(superGroupName + "." + ((ArrayConfigItem) ci).getValue(finalI).getName()), entryList); + subList.add(groupCategory.build()); + } + + return entryBuilder.startSubCategory(new TranslatableText(superGroupName + "." + (ci).getName()), subList).build(); + default: + return null; + } } } - } diff --git a/fabric-testmod/src/main/java/com/oroarmor/config/testmod/OroConfigTestMod.java b/fabric-testmod/src/main/java/com/oroarmor/config/testmod/OroConfigTestMod.java index f479329..e153079 100644 --- a/fabric-testmod/src/main/java/com/oroarmor/config/testmod/OroConfigTestMod.java +++ b/fabric-testmod/src/main/java/com/oroarmor/config/testmod/OroConfigTestMod.java @@ -38,5 +38,7 @@ public void onInitialize() { CONFIG.readConfigFromFile(); ServerLifecycleEvents.SERVER_STOPPED.register(instance -> CONFIG.saveConfigToFile()); CommandRegistrationCallback.EVENT.register(new ConfigCommand(CONFIG)::register); + + CONFIG.saveConfigToFile(); } } diff --git a/fabric-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java b/fabric-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java index 11a5902..29340e3 100644 --- a/fabric-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java +++ b/fabric-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java @@ -27,6 +27,7 @@ import java.io.File; import java.util.List; +import com.oroarmor.config.ArrayConfigItem; import com.oroarmor.config.Config; import com.oroarmor.config.ConfigItem; import com.oroarmor.config.ConfigItemGroup; @@ -47,8 +48,10 @@ public static class ConfigGroupLevel1 extends ConfigItemGroup { public static final ConfigItem testEnum = new ConfigItem<>("test_enum", EnumTest.A, "test_enum"); public static final ConfigItem testItem = new ConfigItem<>("test_boolean", true, "test_boolean"); + public static final ArrayConfigItem testArray = new ArrayConfigItem<>("test_array", new Integer[]{1, 2, 3}, "test_array"); + public ConfigGroupLevel1() { - super(of(new NestedGroup(), testItem, testEnum), "group"); + super(of(new NestedGroup(), testItem, testEnum, testArray), "group"); } public static class NestedGroup extends ConfigItemGroup { diff --git a/fabric-testmod/src/main/resources/fabric.mod.json b/fabric-testmod/src/main/resources/fabric.mod.json index f2d9a9d..27a9b68 100644 --- a/fabric-testmod/src/main/resources/fabric.mod.json +++ b/fabric-testmod/src/main/resources/fabric.mod.json @@ -7,7 +7,7 @@ "authors": [ "OroArmor" ], - "license": "CC0-1.0", + "license": "MIT", "icon": "oro-config_icon.jpg", "environment": "*", "entrypoints": { diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 47e00cb..52ae996 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -9,7 +9,7 @@ ], "contact": { }, - "license": "CC0-1.0", + "license": "MIT", "icon": "oro-config_icon.jpg", "environment": "*", "depends": { diff --git a/forge-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java b/forge-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java index ed25812..3e1f8f3 100644 --- a/forge-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java +++ b/forge-testmod/src/main/java/com/oroarmor/config/testmod/TestConfig.java @@ -27,6 +27,7 @@ import java.io.File; import java.util.List; +import com.oroarmor.config.ArrayConfigItem; import com.oroarmor.config.Config; import com.oroarmor.config.ConfigItem; import com.oroarmor.config.ConfigItemGroup; @@ -47,8 +48,10 @@ public static class ConfigGroupLevel1 extends ConfigItemGroup { public static final ConfigItem testEnum = new ConfigItem<>("test_enum", EnumTest.A, "test_enum"); public static final ConfigItem testItem = new ConfigItem<>("test_boolean", true, "test_boolean"); + public static final ArrayConfigItem testArray = new ArrayConfigItem<>("test_array", new Integer[]{1, 2, 3}, "test_array"); + public ConfigGroupLevel1() { - super(of(new NestedGroup(), testItem, testEnum), "group"); + super(of(new NestedGroup(), testItem, testEnum, testArray), "group"); } public static class NestedGroup extends ConfigItemGroup { @@ -67,4 +70,4 @@ public TripleNested() { } } } -} +} \ No newline at end of file diff --git a/forge-testmod/src/main/resources/META-INF/mods.toml b/forge-testmod/src/main/resources/META-INF/mods.toml index 2261590..2efa58e 100644 --- a/forge-testmod/src/main/resources/META-INF/mods.toml +++ b/forge-testmod/src/main/resources/META-INF/mods.toml @@ -1,7 +1,7 @@ modLoader = "javafml" loaderVersion = "[35,)" #issueTrackerURL = "" -license = "CCO 1.0" +license = "MIT" [[mods]] modId = "oroconfig-testmod" diff --git a/gradle.properties b/gradle.properties index eb6bd6b..fda7a2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx2048M minecraft_version=1.16.5 archives_base_name=oro-config -mod_version=2.0.0 +mod_version=2.1.0 maven_group=com.oroarmor architectury_version=1.7.117 fabric_loader_version=0.11.1 diff --git a/settings.gradle b/settings.gradle index d0eac29..58a1e9d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,7 +11,7 @@ include("common") include("fabric") include("forge") -include("fabric-testmod") -include("forge-testmod") +//include("fabric-testmod") +//include("forge-testmod") rootProject.name = "oro-config"