diff options
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/ftbsc/bscv/tools/Setting.java | 196 |
1 files changed, 153 insertions, 43 deletions
diff --git a/src/main/java/ftbsc/bscv/tools/Setting.java b/src/main/java/ftbsc/bscv/tools/Setting.java index 99f5480..427e22e 100644 --- a/src/main/java/ftbsc/bscv/tools/Setting.java +++ b/src/main/java/ftbsc/bscv/tools/Setting.java @@ -1,23 +1,28 @@ package ftbsc.bscv.tools; +import com.google.common.collect.Lists; import com.mojang.brigadier.arguments.*; + import ftbsc.bscv.api.IModule; import net.minecraft.command.Commands; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.server.command.EnumArgument; +import java.io.Serializable; +import java.util.List; import java.util.Optional; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; import static ftbsc.bscv.Boscovicino.log; -public abstract class Setting<T> { +public abstract class Setting<T, I> { protected Optional<String> name; protected Optional<String> comment; protected Optional<T> fallback; - protected Optional<Consumer<T>> callback; - + protected Optional<Consumer<I>> callback; Setting() { this.name = Optional.empty(); @@ -26,68 +31,75 @@ public abstract class Setting<T> { this.callback = Optional.empty(); } - public Setting<T> name(String name) { + public Setting<T, I> name(String name) { this.name = Optional.of(name); return this; } - public Setting<T> comment(String comment) { + public Setting<T, I> comment(String comment) { this.comment = Optional.of(comment); return this; } - public Setting<T> fallback(T fallback) { + public Setting<T, I> fallback(T fallback) { this.fallback = Optional.of(fallback); return this; } - public Setting<T> callback(Consumer<T> callback) { + public Setting<T, I> callback(Consumer<I> callback) { this.callback = Optional.of(callback); return this; } abstract ForgeConfigSpec.ConfigValue<T> value(ForgeConfigSpec.Builder builder); - abstract ArgumentType<T> argument(); + abstract ArgumentType<I> argument(); + + public abstract ForgeConfigSpec.ConfigValue<T> build(IModule module); + - abstract Class<T> clazz(); - public ForgeConfigSpec.ConfigValue<T> build(IModule module) { - ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder()); + private static abstract class ValueSetting<T> extends Setting<T, T> { + + abstract Class<T> clazz(); - String optName = this.name.get(); - Class<T> clazz = this.clazz(); - ArgumentType<T> arg = this.argument(); - Consumer<T> cb = this.callback.isPresent() ? this.callback.get() : null; + public ForgeConfigSpec.ConfigValue<T> build(IModule module) { + ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder()); - module.getDispatcher().register( - Commands.literal(module.getName().toLowerCase()) - .then( - Commands.literal(optName) + String optName = this.name.get(); + Class<T> clazz = this.clazz(); + ArgumentType<T> arg = this.argument(); + Consumer<T> cb = this.callback.isPresent() ? this.callback.get() : null; + + module.getDispatcher().register( + Commands.literal(module.getName().toLowerCase()) .then( - Commands.argument(optName, arg) - .executes( ctx -> { - T value = ctx.getArgument(optName, clazz); - if (cb != null) { - cb.accept(value); - } - conf.set(value); - conf.save(); - log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString())); - return 1; - })) - .executes(ctx -> { - log(String.format("> %s: %s <", optName, conf.get().toString())); - return 1; - }) - ) - ); - - return conf; + Commands.literal(optName) + .then( + Commands.argument(optName, arg) + .executes( ctx -> { + T value = ctx.getArgument(optName, clazz); + if (cb != null) { + cb.accept(value); + } + conf.set(value); + conf.save(); + log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString())); + return 1; + })) + .executes(ctx -> { + log(String.format("> %s: %s <", optName, conf.get().toString())); + return 1; + }) + ) + ); + + return conf; + } } - public static class Bool extends Setting<Boolean> { + public static class Bool extends ValueSetting<Boolean> { public static Bool builder() { return new Bool(); } public Class<Boolean> clazz() { return Boolean.class; } @@ -101,7 +113,7 @@ public abstract class Setting<T> { } - public static class Decimal extends Setting<Double> { + public static class Decimal extends ValueSetting<Double> { protected Optional<Double> min; protected Optional<Double> max; @@ -133,7 +145,7 @@ public abstract class Setting<T> { } - public static class Number extends Setting<Integer> { + public static class Number extends ValueSetting<Integer> { protected Optional<Integer> min; protected Optional<Integer> max; @@ -165,7 +177,7 @@ public abstract class Setting<T> { } - public static class Str extends Setting<String> { + public static class Str extends ValueSetting<String> { public static Str builder() { return new Str(); } protected boolean greedy = false; @@ -190,7 +202,7 @@ public abstract class Setting<T> { } - public static class Switch<T extends Enum<T>> extends Setting<T> { + public static class Switch<T extends Enum<T>> extends ValueSetting<T> { private final Class<T> enumClazz; public static<T extends Enum<T>> Switch<T> builder(Class<T> type) { return new Switch<T>(type); } @@ -214,4 +226,102 @@ public abstract class Setting<T> { } } + public static class Many<T, S extends Serializable> extends Setting<List<? extends S>, T> { + private Predicate<Object> validator; + private Function<T, S> writer; + private final ArgumentType<T> argument_type; + private final Class<T> clazz; + + // TODO can we infer clazz from the argument type without needing the second argument??? + public Many(ArgumentType<T> argument, Class<T> clazz) { + super(); + this.validator = x -> true; + this.writer = x -> (S) x; // TODO this works ootb if it's just the same type but crashes at runtime for everything else + this.argument_type = argument; + this.clazz = clazz; + } + + public static<T, S extends Serializable> Many<T, S> builder(ArgumentType<T> argument, Class<T> clazz) { return new Many<T, S>(argument, clazz); } + + public Many<T, S> validator(Predicate<Object> validator) { + this.validator = validator; + return this; + } + + public Many<T, S> writer(Function<T, S> writer) { + this.writer = writer; + return this; + } + + public ArgumentType<T> argument() { + return this.argument_type; + } + + public ForgeConfigSpec.ConfigValue<List<? extends S>> value(ForgeConfigSpec.Builder builder) { + return builder + .comment(this.comment.get()) + .defineList( + this.name.get(), + this.fallback.get(), + this.validator + ); + } + + public ForgeConfigSpec.ConfigValue<List<? extends S>> build(IModule module) { + ForgeConfigSpec.ConfigValue<List<? extends S>> conf = this.value(module.getConfigBuilder()); + + String optName = this.name.get(); + ArgumentType<T> arg = this.argument(); + Consumer<T> cb = this.callback.isPresent() ? this.callback.get() : null; + + module.getDispatcher().register( + Commands.literal(module.getName().toLowerCase()) + .then( + Commands.literal(optName) + .then( + Commands.literal("add") + .then( + Commands.argument(optName, arg) + .executes( ctx -> { + T value = ctx.getArgument(optName, this.clazz); + if (cb != null) { + cb.accept(value); + } + List<S> botch = Lists.newArrayList(conf.get()); + botch.add(this.writer.apply(value)); + conf.set(botch); + conf.save(); + log(String.format("> %s -++> %s <", String.join(".", conf.getPath()), conf.get().toString())); + return 1; + }) + ) + ) + .then( + Commands.literal("remove") + .then( + Commands.argument(optName, arg) + .executes( ctx -> { + T value = ctx.getArgument(optName, clazz); + if (cb != null) { + cb.accept(value); + } + List<S> botch = Lists.newArrayList(conf.get()); + boolean removed = botch.remove(this.writer.apply(value)); + conf.set(botch); + conf.save(); + log(String.format("> %s -%s> %s <", String.join(".", conf.getPath()), removed ? "//" : "--", conf.get().toString())); + return 1; + }) + ) + ) + .executes(ctx -> { + log(String.format("> %s: %s <", optName, conf.get().toString())); + return 1; + }) + ) + ); + + return conf; + } + } } |