Improved automatic command registration

This commit is contained in:
Martin Prokoph
2024-08-28 11:38:35 +02:00
parent 64d26e38b5
commit 8039bf3fec
5 changed files with 67 additions and 88 deletions

View File

@@ -50,7 +50,7 @@ allprojects {
releaseChangelog = { releaseChangelog = {
def changes = new StringBuilder() def changes = new StringBuilder()
changes << "## MidnightLib v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightLib/commits/)" changes << "## MidnightLib v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightLib/commits/)"
def proc = "git log --max-count=1 --pretty=format:%s".execute() def proc = "git log --max-count=10 --pretty=format:%s".execute()
proc.in.eachLine { line -> proc.in.eachLine { line ->
def processedLine = line.toString() def processedLine = line.toString()
if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) { if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) {

View File

@@ -29,7 +29,7 @@ public class MidnightLib {
MidnightConfig.configClass.forEach((modid, config) -> { MidnightConfig.configClass.forEach((modid, config) -> {
for (Field field : config.getFields()) { for (Field field : config.getFields()) {
if (field.isAnnotationPresent(MidnightConfig.Entry.class) && !field.isAnnotationPresent(MidnightConfig.Client.class) && !field.isAnnotationPresent(MidnightConfig.Hidden.class)) if (field.isAnnotationPresent(MidnightConfig.Entry.class) && !field.isAnnotationPresent(MidnightConfig.Client.class) && !field.isAnnotationPresent(MidnightConfig.Hidden.class))
new AutoCommand(field, modid).register(); new AutoCommand(field, modid);
} }
}); });
} }

View File

@@ -1,10 +1,8 @@
package eu.midnightdust.lib.config; package eu.midnightdust.lib.config;
import com.mojang.brigadier.arguments.DoubleArgumentType; import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import eu.midnightdust.lib.util.PlatformFunctions; import eu.midnightdust.lib.util.PlatformFunctions;
import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
@@ -12,106 +10,87 @@ import net.minecraft.text.Text;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects;
@SuppressWarnings("unchecked")
public class AutoCommand { public class AutoCommand {
public static List<LiteralArgumentBuilder<ServerCommandSource>> commands = new ArrayList<>(); public static List<LiteralArgumentBuilder<ServerCommandSource>> commands = new ArrayList<>();
final Field entry; final static String VALUE = "value";
final Field field;
final Class<?> type;
final String modid; final String modid;
final boolean isList;
public AutoCommand(Field entry, String modid) { public AutoCommand(Field field, String modid) {
this.entry = entry; this.field = field;
this.modid = modid; this.modid = modid;
this.type = field.getType();
this.isList = field.getType() == List.class;
LiteralArgumentBuilder<ServerCommandSource> command = CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(
CommandManager.literal(modid).then(CommandManager.literal(field.getName()).executes(this::getValue)));
if (type.isEnum()) {
for (Object enumValue : field.getType().getEnumConstants()) {
command = command.then(CommandManager.literal(enumValue.toString()).executes(ctx -> this.setValue(ctx.getSource(), enumValue, "")));
}
}
else if (isList) {
for (String action : List.of("add", "remove")) {
command = command.then(CommandManager.literal(action).then(
CommandManager.argument(VALUE, getArgType()).executes(ctx -> setValueFromArg(ctx, action))));
}
}
else command = command.then(CommandManager.argument(VALUE, getArgType()).executes(ctx -> setValueFromArg(ctx, "")));
PlatformFunctions.registerCommand(command); commands.add(command);
} }
public void register() { public ArgumentType<?> getArgType() {
LiteralArgumentBuilder<ServerCommandSource> command = CommandManager.literal(modid); MidnightConfig.Entry entry = type.getAnnotation(MidnightConfig.Entry.class);
if (entry.getType() == int.class) if (type.isInstance(Number.class)) {
command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then( if (type == int.class) return IntegerArgumentType.integer((int) entry.min(), (int) entry.max());
CommandManager.argument("value", IntegerArgumentType.integer((int) entry.getAnnotation(MidnightConfig.Entry.class).min(),(int) entry.getAnnotation(MidnightConfig.Entry.class).max())) else if (type == double.class) return DoubleArgumentType.doubleArg(entry.min(), entry.max());
.executes(ctx -> this.setValue(ctx.getSource(), IntegerArgumentType.getInteger(ctx, "value"))) else if (type == float.class) return FloatArgumentType.floatArg((float) entry.min(), (float) entry.max());
));
else if (entry.getType() == double.class)
command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(
CommandManager.argument("value", DoubleArgumentType.doubleArg(entry.getAnnotation(MidnightConfig.Entry.class).min(),entry.getAnnotation(MidnightConfig.Entry.class).max()))
.executes(ctx -> this.setValue(ctx.getSource(), DoubleArgumentType.getDouble(ctx, "value")))
));
else if (entry.getType() == float.class)
command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(
CommandManager.argument("value", FloatArgumentType.floatArg((float) entry.getAnnotation(MidnightConfig.Entry.class).min(), (float) entry.getAnnotation(MidnightConfig.Entry.class).max()))
.executes(ctx -> this.setValue(ctx.getSource(), FloatArgumentType.getFloat(ctx, "value")))
));
else if (entry.getType() == boolean.class) {
for (int i = 0; i < 2; i++) {
command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(
CommandManager.literal(i==0 ? "true":"false")
.executes(ctx -> this.setValue(ctx.getSource(), ctx.getInput().endsWith("true")))
));
}
} }
else if (entry.getType().isEnum()) { else if (type == boolean.class) return BoolArgumentType.bool();
for (int i = 0; i < entry.getType().getEnumConstants().length; ++i) { return StringArgumentType.string();
Object enumValue = Arrays.stream(entry.getType().getEnumConstants()).toList().get(i);
command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(
CommandManager.literal(enumValue.toString())
.executes(ctx -> this.setValue(ctx.getSource(), enumValue))
));
}
}
else if (entry.getType() == List.class) {
for (int i = 0; i < 2; i++) {
int finalI = i;
command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(CommandManager.literal(i==0 ? "add":"remove").then(
CommandManager.argument("value", StringArgumentType.string())
.executes(ctx -> this.setList(ctx.getSource(), StringArgumentType.getString(ctx, "value"), finalI==0))
)));
}
}
else {
command = command.then(CommandManager.literal(this.entry.getName()).executes(ctx -> getValue(ctx.getSource())).then(
CommandManager.argument("value", StringArgumentType.string())
.executes(ctx -> this.setValue(ctx.getSource(), StringArgumentType.getString(ctx, "value")))
));
}
LiteralArgumentBuilder<ServerCommandSource> finalized = CommandManager.literal("midnightconfig").requires(source -> source.hasPermissionLevel(2)).then(command);
PlatformFunctions.registerCommand(finalized); commands.add(finalized);
} }
private int setValue(ServerCommandSource source, Object value) { public int setValueFromArg(CommandContext<ServerCommandSource> context, String action) {
if (type.isInstance(Number.class)) {
if (type == int.class) return setValue(context.getSource(), IntegerArgumentType.getInteger(context, VALUE), action);
else if (type == double.class) return setValue(context.getSource(), DoubleArgumentType.getDouble(context, VALUE), action);
else if (type == float.class) return setValue(context.getSource(), FloatArgumentType.getFloat(context, VALUE), action);
}
else if (type == boolean.class) return setValue(context.getSource(), BoolArgumentType.getBool(context, VALUE), action);
return setValue(context.getSource(), StringArgumentType.getString(context, VALUE), action);
}
private int setValue(ServerCommandSource source, Object value, String action) {
boolean add = Objects.equals(action, "add");
try { try {
if (entry.getType() != List.class) entry.set(null,value); if (!isList) field.set(null, value);
else {
@SuppressWarnings("unchecked") var list = (List<Object>) field.get(null);
if (add) list.add(value);
else if (!list.contains(value)) throw new IllegalArgumentException("List does not contain this string!");
else list.remove(value);
}
MidnightConfig.write(modid); MidnightConfig.write(modid);
} }
catch (Exception e) { catch (Exception e) {
source.sendError(Text.literal("Could not set "+entry.getName()+" to value "+value+": " + e)); if (!isList) source.sendError(Text.literal("Could not set "+field.getName()+" to value "+value+": " + e));
else source.sendError(Text.literal((add ? "Could not add "+value+" to " : "Could not remove "+value+" from ")+field.getName() +": " + e));
return 0; return 0;
} }
if (!isList) source.sendFeedback(() -> Text.literal("Successfully set " + field.getName()+" to "+value), true);
source.sendFeedback(() -> Text.literal("Successfully set " + entry.getName()+" to "+value), true); else source.sendFeedback(() -> Text.literal((add ? "Successfully added " +value+" to " : "Successfully removed " +value+" from ") +field.getName()), true);
return 1; return 1;
} }
private int setList(ServerCommandSource source, String value, boolean add) { private int getValue(CommandContext<ServerCommandSource> context) {
try { context.getSource().sendFeedback(() -> {
List<String> e = (List<String>)entry.get(null); try { return Text.literal("The value of "+field.getName()+" is "+field.get(null));
if (add) e.add(value);
else if (!e.contains(value)) throw new IllegalArgumentException("List does not contain this string!");
else e.remove(value);
MidnightConfig.write(modid);
}
catch (Exception e) {
source.sendError(Text.literal((add ? "Could not add "+value+" to " : "Could not remove "+value+" from ")+entry.getName() +": " + e));
return 0;
}
source.sendFeedback(() -> Text.literal((add ? "Successfully added " +value+" to " : "Successfully removed " +value+" from ") +entry.getName()), true);
return 1;
}
private int getValue(ServerCommandSource source) {
source.sendFeedback(() -> {
try {return Text.literal("The value of "+entry.getName()+" is "+entry.get(null));
} catch (IllegalAccessException e) {throw new RuntimeException(e);} } catch (IllegalAccessException e) {throw new RuntimeException(e);}
}, true); }, true);
return 0; return 0;
} }
} }

View File

@@ -351,7 +351,7 @@ public abstract class MidnightConfig {
} catch (Exception ignored) {} } catch (Exception ignored) {}
info.actionButton = colorButton; info.actionButton = colorButton;
} else if (e.selectionMode() > -1) { } else if (e.selectionMode() > -1) {
ButtonWidget explorerButton = TextIconButtonWidget.builder(Text.of(""), ButtonWidget explorerButton = TextIconButtonWidget.builder(Text.empty(),
button -> new Thread(() -> { button -> new Thread(() -> {
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType()); fileChooser.setFileSelectionMode(e.selectionMode()); fileChooser.setDialogType(e.fileChooserType());

View File

@@ -5,7 +5,7 @@ yarn_mappings=1.21+build.1
enabled_platforms=fabric,neoforge enabled_platforms=fabric,neoforge
archives_base_name=midnightlib archives_base_name=midnightlib
mod_version=1.6.0 mod_version=1.6.1
maven_group=eu.midnightdust maven_group=eu.midnightdust
release_type=release release_type=release
curseforge_id=488090 curseforge_id=488090