feat: added Many setting for collections
still very raw and not super helpful but kind of usable?
This commit is contained in:
parent
add2ea7945
commit
bfc6d4fef6
1 changed files with 152 additions and 42 deletions
|
@ -1,23 +1,28 @@
|
||||||
package ftbsc.bscv.tools;
|
package ftbsc.bscv.tools;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.mojang.brigadier.arguments.*;
|
import com.mojang.brigadier.arguments.*;
|
||||||
|
|
||||||
import ftbsc.bscv.api.IModule;
|
import ftbsc.bscv.api.IModule;
|
||||||
import net.minecraft.command.Commands;
|
import net.minecraft.command.Commands;
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
import net.minecraftforge.server.command.EnumArgument;
|
import net.minecraftforge.server.command.EnumArgument;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static ftbsc.bscv.Boscovicino.log;
|
import static ftbsc.bscv.Boscovicino.log;
|
||||||
|
|
||||||
public abstract class Setting<T> {
|
public abstract class Setting<T, I> {
|
||||||
|
|
||||||
protected Optional<String> name;
|
protected Optional<String> name;
|
||||||
protected Optional<String> comment;
|
protected Optional<String> comment;
|
||||||
protected Optional<T> fallback;
|
protected Optional<T> fallback;
|
||||||
protected Optional<Consumer<T>> callback;
|
protected Optional<Consumer<I>> callback;
|
||||||
|
|
||||||
|
|
||||||
Setting() {
|
Setting() {
|
||||||
this.name = Optional.empty();
|
this.name = Optional.empty();
|
||||||
|
@ -26,68 +31,75 @@ public abstract class Setting<T> {
|
||||||
this.callback = Optional.empty();
|
this.callback = Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Setting<T> name(String name) {
|
public Setting<T, I> name(String name) {
|
||||||
this.name = Optional.of(name);
|
this.name = Optional.of(name);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Setting<T> comment(String comment) {
|
public Setting<T, I> comment(String comment) {
|
||||||
this.comment = Optional.of(comment);
|
this.comment = Optional.of(comment);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Setting<T> fallback(T fallback) {
|
public Setting<T, I> fallback(T fallback) {
|
||||||
this.fallback = Optional.of(fallback);
|
this.fallback = Optional.of(fallback);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Setting<T> callback(Consumer<T> callback) {
|
public Setting<T, I> callback(Consumer<I> callback) {
|
||||||
this.callback = Optional.of(callback);
|
this.callback = Optional.of(callback);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract ForgeConfigSpec.ConfigValue<T> value(ForgeConfigSpec.Builder builder);
|
abstract ForgeConfigSpec.ConfigValue<T> value(ForgeConfigSpec.Builder builder);
|
||||||
|
|
||||||
abstract ArgumentType<T> argument();
|
abstract ArgumentType<I> argument();
|
||||||
|
|
||||||
abstract Class<T> clazz();
|
public abstract ForgeConfigSpec.ConfigValue<T> build(IModule module);
|
||||||
|
|
||||||
public ForgeConfigSpec.ConfigValue<T> build(IModule module) {
|
|
||||||
ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder());
|
|
||||||
|
|
||||||
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(
|
private static abstract class ValueSetting<T> extends Setting<T, T> {
|
||||||
Commands.literal(module.getName().toLowerCase())
|
|
||||||
.then(
|
abstract Class<T> clazz();
|
||||||
Commands.literal(optName)
|
|
||||||
|
public ForgeConfigSpec.ConfigValue<T> build(IModule module) {
|
||||||
|
ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder());
|
||||||
|
|
||||||
|
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(
|
.then(
|
||||||
Commands.argument(optName, arg)
|
Commands.literal(optName)
|
||||||
.executes( ctx -> {
|
.then(
|
||||||
T value = ctx.getArgument(optName, clazz);
|
Commands.argument(optName, arg)
|
||||||
if (cb != null) {
|
.executes( ctx -> {
|
||||||
cb.accept(value);
|
T value = ctx.getArgument(optName, clazz);
|
||||||
}
|
if (cb != null) {
|
||||||
conf.set(value);
|
cb.accept(value);
|
||||||
conf.save();
|
}
|
||||||
log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString()));
|
conf.set(value);
|
||||||
return 1;
|
conf.save();
|
||||||
}))
|
log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString()));
|
||||||
.executes(ctx -> {
|
return 1;
|
||||||
log(String.format("> %s: %s <", optName, conf.get().toString()));
|
}))
|
||||||
return 1;
|
.executes(ctx -> {
|
||||||
})
|
log(String.format("> %s: %s <", optName, conf.get().toString()));
|
||||||
)
|
return 1;
|
||||||
);
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return conf;
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Bool extends Setting<Boolean> {
|
public static class Bool extends ValueSetting<Boolean> {
|
||||||
public static Bool builder() { return new Bool(); }
|
public static Bool builder() { return new Bool(); }
|
||||||
|
|
||||||
public Class<Boolean> clazz() { return Boolean.class; }
|
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> min;
|
||||||
protected Optional<Double> max;
|
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> min;
|
||||||
protected Optional<Integer> max;
|
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(); }
|
public static Str builder() { return new Str(); }
|
||||||
|
|
||||||
protected boolean greedy = false;
|
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;
|
private final Class<T> enumClazz;
|
||||||
|
|
||||||
public static<T extends Enum<T>> Switch<T> builder(Class<T> type) { return new Switch<T>(type); }
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue