148 lines
7.7 KiB
Java
148 lines
7.7 KiB
Java
package io.gitlab.jfronny.libjf.config.impl;
|
|
|
|
import com.mojang.brigadier.Command;
|
|
import com.mojang.brigadier.arguments.*;
|
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
|
import io.gitlab.jfronny.commons.throwable.ThrowingRunnable;
|
|
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
|
|
import io.gitlab.jfronny.libjf.LibJf;
|
|
import io.gitlab.jfronny.libjf.config.api.*;
|
|
import io.gitlab.jfronny.libjf.config.api.type.Type;
|
|
import net.fabricmc.api.ModInitializer;
|
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
|
import net.minecraft.server.command.ServerCommandSource;
|
|
import net.minecraft.text.*;
|
|
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Function;
|
|
|
|
import static net.minecraft.server.command.CommandManager.argument;
|
|
import static net.minecraft.server.command.CommandManager.literal;
|
|
|
|
public class JfConfigCommand implements ModInitializer {
|
|
@Override
|
|
public void onInitialize() {
|
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
|
LiteralArgumentBuilder<ServerCommandSource> c_libjf = literal(LibJf.MOD_ID);
|
|
LiteralArgumentBuilder<ServerCommandSource> c_config = literal("config")
|
|
.requires((serverCommandSource) -> serverCommandSource.hasPermissionLevel(4))
|
|
.executes(context -> {
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] Loaded configs for:"), false);
|
|
ConfigHolder.getInstance().getRegistered().forEach((s, config) -> {
|
|
context.getSource().sendFeedback(Text.literal("- " + s), false);
|
|
});
|
|
return Command.SINGLE_SUCCESS;
|
|
});
|
|
LiteralArgumentBuilder<ServerCommandSource> c_reload = literal("reload").executes(context -> {
|
|
ConfigHolder.getInstance().getRegistered().forEach((mod, config) -> config.load());
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] Reloaded configs"), true);
|
|
return Command.SINGLE_SUCCESS;
|
|
});
|
|
LiteralArgumentBuilder<ServerCommandSource> c_reset = literal("reset").executes(context -> {
|
|
context.getSource().sendError(Text.literal("[libjf-config-v1] Please specify a config to reset"));
|
|
return Command.SINGLE_SUCCESS;
|
|
});
|
|
ConfigHolder.getInstance().getRegistered().forEach((id, config) -> {
|
|
c_reload.then(literal(id).executes(context -> {
|
|
config.load();
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] Reloaded config for " + id), true);
|
|
return Command.SINGLE_SUCCESS;
|
|
}));
|
|
registerEntries(config, id, c_config, c_reset, cns -> {
|
|
LiteralArgumentBuilder<ServerCommandSource> c_instance = literal(id);
|
|
cns.accept(c_instance);
|
|
return c_instance;
|
|
});
|
|
});
|
|
dispatcher.register(c_libjf.then(c_config.then(c_reload).then(c_reset)));
|
|
});
|
|
}
|
|
|
|
private void registerEntries(ConfigCategory config, String subpath, LiteralArgumentBuilder<ServerCommandSource> c_config, LiteralArgumentBuilder<ServerCommandSource> c_reset, Function<Consumer<LiteralArgumentBuilder<ServerCommandSource>>, LiteralArgumentBuilder<ServerCommandSource>> pathGen) {
|
|
c_config.then(pathGen.apply(cns -> {
|
|
cns.executes(context -> {
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] " + subpath + " is a category"), false);
|
|
return Command.SINGLE_SUCCESS;
|
|
});
|
|
for (EntryInfo<?> entry : config.getEntries()) {
|
|
registerEntry(config, subpath, cns, entry);
|
|
}
|
|
}));
|
|
c_reset.then(pathGen.apply(cns -> {
|
|
cns.executes(context -> {
|
|
config.reset();
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] Reset config for " + subpath), true);
|
|
return Command.SINGLE_SUCCESS;
|
|
});
|
|
config.getPresets().forEach((id2, preset) -> {
|
|
cns.then(literal(id2).executes(context -> {
|
|
preset.run();
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] Loaded preset " + id2 + " for " + subpath), true);
|
|
return Command.SINGLE_SUCCESS;
|
|
}));
|
|
});
|
|
}));
|
|
config.getCategories().forEach((id2, cfg) -> {
|
|
registerEntries(cfg, cfg.getCategoryPath(), c_config, c_reset, cns -> {
|
|
return pathGen.apply(cns1 -> {
|
|
LiteralArgumentBuilder<ServerCommandSource> c_instance2 = literal(id2);
|
|
cns.accept(c_instance2);
|
|
cns1.then(c_instance2);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
private final DynamicCommandExceptionType eType = new DynamicCommandExceptionType(o -> {
|
|
if (o instanceof Throwable throwable) {
|
|
return Text.literal("Could not execute command: " + throwable.getMessage());
|
|
} else return Text.literal("Could not execute command");
|
|
});
|
|
|
|
private <T> void registerEntry(ConfigCategory config, String subpath, LiteralArgumentBuilder<ServerCommandSource> cns, EntryInfo<T> entry) {
|
|
LiteralArgumentBuilder<ServerCommandSource> c_entry = literal(entry.getName()).executes(context -> {
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] The value of " + subpath + "." + entry.getName() + " is " + tryRun(entry::getValue)), false);
|
|
return Command.SINGLE_SUCCESS;
|
|
});
|
|
ArgumentType<?> type = getType(entry);
|
|
if (type != null) {
|
|
c_entry.then(argument("value", type).executes(context -> {
|
|
@SuppressWarnings("unchecked") T value = context.getArgument("value", (Class<T>) entry.getValueType().asClass());
|
|
tryRun(() -> entry.setValue(value));
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] Set " + subpath + "." + entry.getName() + " to " + value), true);
|
|
return Command.SINGLE_SUCCESS;
|
|
}));
|
|
}
|
|
else if (entry.getValueType().isEnum()) {
|
|
for (T enumConstant : ((Type.TEnum<T>)entry.getValueType()).options()) {
|
|
c_entry.then(literal(enumConstant.toString()).executes(context -> {
|
|
tryRun(() -> entry.setValue(enumConstant));
|
|
context.getSource().sendFeedback(Text.literal("[libjf-config-v1] Set " + subpath + "." + entry.getName() + " to " + enumConstant), true);
|
|
return Command.SINGLE_SUCCESS;
|
|
}));
|
|
}
|
|
}
|
|
cns.then(c_entry);
|
|
}
|
|
|
|
private <T> ArgumentType<?> getType(EntryInfo<T> info) {
|
|
Type<T> type = info.getValueType();
|
|
if (type.isInt()) return IntegerArgumentType.integer((int) info.getMinValue(), (int) info.getMaxValue());
|
|
else if (type.isFloat()) return FloatArgumentType.floatArg((float) info.getMinValue(), (float) info.getMaxValue());
|
|
else if (type.isDouble()) return DoubleArgumentType.doubleArg(info.getMinValue(), info.getMaxValue());
|
|
else if (type.isString()) return StringArgumentType.greedyString();
|
|
else if (type.isBool()) return BoolArgumentType.bool();
|
|
else return null;
|
|
}
|
|
|
|
private <T> T tryRun(ThrowingSupplier<T, ?> supplier) throws CommandSyntaxException {
|
|
return supplier.orThrow(eType::create).get();
|
|
}
|
|
|
|
private void tryRun(ThrowingRunnable<?> supplier) throws CommandSyntaxException {
|
|
supplier.orThrow(eType::create).run();
|
|
}
|
|
}
|