Skip to content

Commit 461888c

Browse files
committed
Validate config on load, fix array corruption issue
1 parent 671f054 commit 461888c

11 files changed

Lines changed: 86 additions & 35 deletions

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/GCCore.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ private static void readDeeper(Object rootConfigObject, Field configField, Glass
271271
rootJsonObject.getChild(field.getName(), fieldType) != null? rootJsonObject.getChild(field.getName(), fieldType) : childObjField,
272272
defaultConfig.get(field.getName())
273273
);
274+
if(!configEntry.isValueValid()) {
275+
throw new RuntimeException("Config value for \"" + field.getName() + "\" inside of \"" + configField.getName() + " is invalid!");
276+
}
274277
configEntry.multiplayerLoaded = isMultiplayer && configEntry.multiplayerSynced;
275278
category.values.put(field.getType(), configEntry);
276279
configEntry.saveToField();

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/ConfigEntryHandler.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,20 @@
1414

1515
import java.lang.reflect.*;
1616
import java.util.*;
17+
import java.util.function.*;
1718

1819
public abstract class ConfigEntryHandler<T> extends ConfigHandlerBase {
1920
public T value;
2021
public final T defaultValue;
2122
@Environment(EnvType.CLIENT)
22-
protected Screen parent;
2323
public boolean multiplayerLoaded = false;
2424
protected ConfigEntry configEntry;
25-
protected List<HasDrawable> drawableList = new ArrayList<>(){};;
25+
protected List<HasDrawable> drawableList = new ArrayList<>(){};
26+
/**
27+
* Optional convenience field for when using text boxes.
28+
* {@link net.modificationstation.stationapi.impl.config.screen.widget.ExtensibleTextFieldWidget}
29+
*/
30+
protected Function<String, List<String>> textValidator;
2631

2732
public ConfigEntryHandler(String id, ConfigEntry configEntry, Field parentField, Object parentObject, boolean multiplayerSynced, T value, T defaultValue) {
2833
super(id, configEntry.name(), configEntry.description(), parentField, parentObject, multiplayerSynced);
@@ -73,7 +78,7 @@ public void vanillaServerBehavior() {
7378
else if (parentField.getAnnotation(ValueOnVanillaServer.class) != null) {
7479
ValueOnVanillaServer valueOnVanillaServer = parentField.getAnnotation(ValueOnVanillaServer.class);
7580
multiplayerLoaded = true;
76-
if (!valueOnVanillaServer.stringValue().equals("")) {
81+
if (!valueOnVanillaServer.stringValue().isEmpty()) {
7782
reset(valueOnVanillaServer.stringValue());
7883
}
7984
else if (valueOnVanillaServer.booleanValue() != TriBoolean.DEFAULT) {

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/BaseListConfigEntryHandler.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ public void init(Screen parent, TextRenderer textRenderer) {
3131
super.init(parent, textRenderer);
3232
button = new FancyButtonWidget(10, 0, 0, 0, 0, "Open List... (" + value.length + " values)");
3333
drawableList.add(button);
34-
listScreen = createListScreen();
34+
listScreen = createListScreen(parent);
3535
button.active = !multiplayerLoaded;
3636
}
3737

3838
@Environment(EnvType.CLIENT)
39-
public abstract BaseListScreenBuilder<T> createListScreen();
39+
public abstract BaseListScreenBuilder<T> createListScreen(Screen parent);
4040

4141
public abstract T strToVal(String str);
4242

@@ -51,13 +51,20 @@ public T[] getDrawableValue() {
5151
list.add(strToVal(val.getText()));
5252
}
5353
});
54-
//noinspection unchecked This class should only ever be used by arrays.
55-
return (T[]) list.toArray(new Object[0]);
54+
55+
return list.toArray(getTypedArray());
5656
}
5757

58+
public abstract T[] getTypedArray();
59+
5860
@Override
5961
public boolean isValueValid() {
60-
return value.length < configEntry.maxArrayLength() && value.length > configEntry.minArrayLength();
62+
// return value.length <= configEntry.maxArrayLength() && value.length >= configEntry.minArrayLength() && listContentsValid();
63+
return true;
64+
}
65+
66+
public boolean listContentsValid() {
67+
return Arrays.stream(value).noneMatch(aValue -> textValidator.apply(aValue.toString()) != null);
6168
}
6269

6370
@Override
@@ -78,7 +85,7 @@ public void onClick() {
7885
}
7986

8087
@Override
81-
public void reset(Object defaultValue) throws IllegalAccessException { // !!OVERRIDE THIS AND DO A DEEP CLONE IF YOU'RE USING SOMETHING THAT ISN'T A PRIMITIVE!!
88+
public void reset(Object defaultValue) throws IllegalAccessException { // !!OVERRIDE THIS AND DO A DEEP CLONE IF YOU'RE USING SOMETHING THAT ISN'T A PRIMITIVE/SINGLETON/OTHERWISE UNIQUE VALUE!!
8289
//noinspection unchecked
8390
value = ((T[]) defaultValue).clone();
8491
saveToField();

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/BooleanConfigEntryHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ public void setDrawableValue(Boolean value) {
4646

4747
@Override
4848
public boolean isValueValid() {
49-
return true;
49+
return true; // If this is *somehow* not a boolean, there's fuck all that can be done. You've already crashed before this check. :)
5050
}
5151

52+
@Environment(EnvType.CLIENT)
5253
@Override
5354
public @NotNull List<HasDrawable> getDrawables() {
5455
return drawableList;

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/EnumConfigEntryHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public void setDrawableValue(Integer value) {
5555

5656
@Override
5757
public boolean isValueValid() {
58-
return true;
58+
return value < parentEnumArray.length;
5959
}
6060

6161
@Override

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/FloatConfigEntryHandler.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ public class FloatConfigEntryHandler extends ConfigEntryHandler<Float> {
1818

1919
public FloatConfigEntryHandler(String id, ConfigEntry configEntry, Field parentField, Object parentObject, boolean multiplayerSynced, Float value, Float defaultValue) {
2020
super(id, configEntry, parentField, parentObject, multiplayerSynced, value, defaultValue);
21+
textValidator = str -> floatValidator(configEntry, multiplayerLoaded, str);
2122
}
2223

2324
@Override
2425
public void init(Screen parent, TextRenderer textRenderer) {
2526
super.init(parent, textRenderer);
2627
textbox = new ExtensibleTextFieldWidget(textRenderer);
27-
textbox.setValidator(str -> floatValidator(configEntry, multiplayerLoaded, str));
28+
textbox.setValidator(textValidator);
2829
textbox.setText(value.toString());
2930
textbox.setEnabled(!multiplayerLoaded);
3031
drawableList.add(textbox);
@@ -42,7 +43,7 @@ public void setDrawableValue(Float value) {
4243

4344
@Override
4445
public boolean isValueValid() {
45-
return textbox.isValueValid();
46+
return textValidator.apply(value.toString()) == null;
4647
}
4748

4849
@Override
@@ -64,10 +65,10 @@ public static List<String> floatValidator(ConfigEntry configEntry, boolean multi
6465
if (!CharacterUtils.isFloat(str)) {
6566
return Collections.singletonList("Value is not a floating point number");
6667
}
67-
if (Integer.parseInt(str) > configEntry.maxLength()) {
68+
if (Float.parseFloat(str) > configEntry.maxLength()) {
6869
return Collections.singletonList("Value is too high");
6970
}
70-
if (Integer.parseInt(str) < configEntry.minLength()) {
71+
if (Float.parseFloat(str) < configEntry.minLength()) {
7172
return Collections.singletonList("Value is too low");
7273
}
7374
return null;

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/FloatListConfigEntryHandler.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.fabricmc.api.EnvType;
44
import net.fabricmc.api.Environment;
5+
import net.minecraft.client.gui.screen.Screen;
56
import net.modificationstation.stationapi.api.config.CharacterUtils;
67
import net.modificationstation.stationapi.api.config.ConfigEntry;
78
import net.modificationstation.stationapi.impl.config.screen.BaseListScreenBuilder;
@@ -16,15 +17,16 @@ public class FloatListConfigEntryHandler extends BaseListConfigEntryHandler<Floa
1617

1718
public FloatListConfigEntryHandler(String id, ConfigEntry configEntry, Field parentField, Object parentObject, boolean multiplayerSynced, Float[] value, Float[] defaultValue) {
1819
super(id, configEntry, parentField, parentObject, multiplayerSynced, value, defaultValue);
20+
textValidator = str -> FloatConfigEntryHandler.floatValidator(configEntry, multiplayerLoaded, str);
1921
}
2022

2123
@Override
2224
@Environment(EnvType.CLIENT)
23-
public BaseListScreenBuilder<Float> createListScreen() {
25+
public BaseListScreenBuilder<Float> createListScreen(Screen parent) {
2426
BaseListScreenBuilder<Float> listScreen = new FloatListScreenBuilder(parent,
2527
configEntry,
2628
this,
27-
str -> FloatConfigEntryHandler.floatValidator(configEntry, multiplayerLoaded, str)
29+
textValidator
2830
);
2931

3032
listScreen.setValues(value);
@@ -35,5 +37,15 @@ public BaseListScreenBuilder<Float> createListScreen() {
3537
public Float strToVal(String str) {
3638
return Float.parseFloat(str);
3739
}
40+
41+
@Override
42+
public Float[] getTypedArray() {
43+
return new Float[0];
44+
}
45+
46+
@Override
47+
public boolean listContentsValid() {
48+
return Arrays.stream(value).noneMatch(aFloat -> textValidator.apply(aFloat.toString()) != null);
49+
}
3850
}
3951

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/IntegerConfigEntryHandler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ public class IntegerConfigEntryHandler extends ConfigEntryHandler<Integer> {
1818

1919
public IntegerConfigEntryHandler(String id, ConfigEntry configEntry, Field parentField, Object parentObject, boolean multiplayerSynced, Integer value, Integer defaultValue) {
2020
super(id, configEntry, parentField, parentObject, multiplayerSynced, value, defaultValue);
21+
textValidator = str -> integerValidator(configEntry, multiplayerLoaded, str);
2122
}
2223

2324
@Override
2425
public void init(Screen parent, TextRenderer textRenderer) {
2526
super.init(parent, textRenderer);
2627
textbox = new ExtensibleTextFieldWidget(textRenderer);
27-
textbox.setValidator((str) -> integerValidator(configEntry, multiplayerLoaded, str));
28+
textbox.setValidator(textValidator);
2829
textbox.setMaxLength(Math.toIntExact(configEntry.maxLength()));
2930
textbox.setText(value.toString());
3031
textbox.setEnabled(!multiplayerLoaded);
@@ -43,7 +44,7 @@ public void setDrawableValue(Integer value) {
4344

4445
@Override
4546
public boolean isValueValid() {
46-
return textbox.isValueValid();
47+
return textValidator.apply(value.toString()) == null;
4748
}
4849

4950
@Override

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/IntegerListConfigEntryHandler.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.fabricmc.api.EnvType;
44
import net.fabricmc.api.Environment;
5+
import net.minecraft.client.gui.screen.Screen;
56
import net.modificationstation.stationapi.api.config.CharacterUtils;
67
import net.modificationstation.stationapi.api.config.ConfigEntry;
78
import net.modificationstation.stationapi.impl.config.screen.BaseListScreenBuilder;
@@ -15,15 +16,16 @@ public class IntegerListConfigEntryHandler extends BaseListConfigEntryHandler<In
1516

1617
public IntegerListConfigEntryHandler(String id, ConfigEntry configEntry, Field parentField, Object parentObject, boolean multiplayerSynced, Integer[] value, Integer[] defaultValue) {
1718
super(id, configEntry, parentField, parentObject, multiplayerSynced, value, defaultValue);
19+
textValidator = str -> IntegerConfigEntryHandler.integerValidator(configEntry, multiplayerLoaded, str);
1820
}
1921

2022
@Override
2123
@Environment(EnvType.CLIENT)
22-
public BaseListScreenBuilder<Integer> createListScreen() {
24+
public BaseListScreenBuilder<Integer> createListScreen(Screen parent) {
2325
BaseListScreenBuilder<Integer> listScreen = new IntegerListScreenBuilder(parent,
2426
configEntry,
2527
this,
26-
str -> IntegerConfigEntryHandler.integerValidator(configEntry, multiplayerLoaded, str)
28+
textValidator
2729
);
2830
listScreen.setValues(value);
2931
return listScreen;
@@ -33,4 +35,9 @@ public BaseListScreenBuilder<Integer> createListScreen() {
3335
public Integer strToVal(String str) {
3436
return Integer.parseInt(str);
3537
}
38+
39+
@Override
40+
public Integer[] getTypedArray() {
41+
return new Integer[0];
42+
}
3643
}

glass-config-api-v3/src/main/java/net/modificationstation/stationapi/impl/config/object/entry/StringConfigEntryHandler.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.minecraft.client.font.TextRenderer;
44
import net.minecraft.client.gui.screen.Screen;
5+
import net.modificationstation.stationapi.api.config.CharacterUtils;
56
import net.modificationstation.stationapi.api.config.HasDrawable;
67
import net.modificationstation.stationapi.api.config.ConfigEntry;
78
import net.modificationstation.stationapi.impl.config.object.ConfigEntryHandler;
@@ -16,12 +17,14 @@ public class StringConfigEntryHandler extends ConfigEntryHandler<String> {
1617

1718
public StringConfigEntryHandler(String id, ConfigEntry configEntry, Field parentField, Object parentObject, boolean multiplayerSynced, String value, String defaultValue) {
1819
super(id, configEntry, parentField, parentObject, multiplayerSynced, value, defaultValue);
20+
textValidator = str -> stringValidator(configEntry, multiplayerLoaded, str);
1921
}
2022

2123
@Override
2224
public void init(Screen parent, TextRenderer textRenderer) {
2325
super.init(parent, textRenderer);
2426
textbox = new ExtensibleTextFieldWidget(textRenderer);
27+
textbox.setValidator(textValidator);
2528
textbox.setMaxLength(Math.toIntExact(configEntry.maxLength()));
2629
textbox.setText(value);
2730
textbox.setEnabled(!multiplayerLoaded);
@@ -40,7 +43,7 @@ public void setDrawableValue(String value) {
4043

4144
@Override
4245
public boolean isValueValid() {
43-
return textbox.isValueValid();
46+
return true;
4447
}
4548

4649
@Override
@@ -54,4 +57,17 @@ public void reset(Object defaultValue) throws IllegalAccessException {
5457
setDrawableValue((String) defaultValue);
5558
saveToField();
5659
}
60+
61+
public static List<String> stringValidator(ConfigEntry configEntry, boolean multiplayerLoaded, String str) {
62+
if (multiplayerLoaded) {
63+
return Collections.singletonList("Server synced, you cannot change this value");
64+
}
65+
if (str.length() > configEntry.maxLength()) {
66+
return Collections.singletonList("Value is too long");
67+
}
68+
if (str.length() < configEntry.minLength()) {
69+
return Collections.singletonList("Value is too short");
70+
}
71+
return null;
72+
}
5773
}

0 commit comments

Comments
 (0)