forked from public-mirrors/Uniform
feat: add annotation-driven command system (#12)
parent
ab1b641471
commit
8c62c77bf3
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Uniform, licensed under the GNU General Public License v3.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) Tofaa2
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.william278.uniform.annotations;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import net.william278.uniform.BaseCommand;
|
||||||
|
import net.william278.uniform.element.ArgumentElement;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Argument {
|
||||||
|
|
||||||
|
String name();
|
||||||
|
Class<? extends ArgumentProvider<?>> parser();
|
||||||
|
String[] parserProperties() default {};
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
abstract class ArgumentProvider<S> {
|
||||||
|
|
||||||
|
public abstract ArgumentElement<?, S> provide(@NotNull String name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringArg extends ArgumentProvider<String> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, String> provide(@NotNull String name) {
|
||||||
|
return BaseCommand.string(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WordArg extends ArgumentProvider<String> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, String> provide(@NotNull String name) {
|
||||||
|
return BaseCommand.word(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BooleanArg extends ArgumentProvider<Boolean> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, Boolean> provide(@NotNull String name) {
|
||||||
|
return BaseCommand.bool(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GreedyStringArg extends ArgumentProvider<String> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, String> provide(@NotNull String name) {
|
||||||
|
return BaseCommand.greedyString(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IntegerArg extends ArgumentProvider<Integer> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, Integer> provide(@NotNull String name) {
|
||||||
|
return BaseCommand.intNum(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
class BoundedIntegerArg extends ArgumentProvider<Integer> {
|
||||||
|
private final int min;
|
||||||
|
private final Integer max;
|
||||||
|
|
||||||
|
public BoundedIntegerArg(@NotNull String[] properties) {
|
||||||
|
if (properties.length == 0) {
|
||||||
|
throw new IllegalArgumentException("BoundedIntegerArg requires at least one property (min, max)");
|
||||||
|
}
|
||||||
|
this.min = Integer.parseInt(properties[0]);
|
||||||
|
if (properties.length == 1) {
|
||||||
|
this.max = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.max = Integer.parseInt(properties[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, Integer> provide(@NotNull String name) {
|
||||||
|
if (max == null) {
|
||||||
|
return BaseCommand.intNum(name, min);
|
||||||
|
}
|
||||||
|
return BaseCommand.intNum(name, min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FloatArg extends ArgumentProvider<Float> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, Float> provide(@NotNull String name) {
|
||||||
|
return BaseCommand.floatNum(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
class BoundedFloatArg extends ArgumentProvider<Float> {
|
||||||
|
private final float min;
|
||||||
|
private final Float max;
|
||||||
|
|
||||||
|
public BoundedFloatArg(@NotNull String[] properties) {
|
||||||
|
if (properties.length == 0) {
|
||||||
|
throw new IllegalArgumentException("BoundedFloatArg requires at least one property (min, max)");
|
||||||
|
}
|
||||||
|
this.min = Float.parseFloat(properties[0]);
|
||||||
|
if (properties.length == 1) {
|
||||||
|
this.max = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.max = Float.parseFloat(properties[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, Float> provide(@NotNull String name) {
|
||||||
|
if (max == null) {
|
||||||
|
return BaseCommand.floatNum(name, min);
|
||||||
|
}
|
||||||
|
return BaseCommand.floatNum(name, min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DoubleArg extends ArgumentProvider<Double> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, Double> provide(@NotNull String name) {
|
||||||
|
return BaseCommand.doubleNum(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
class BoundedDoubleArg extends ArgumentProvider<Double> {
|
||||||
|
private final double min;
|
||||||
|
private final Double max;
|
||||||
|
|
||||||
|
public BoundedDoubleArg(@NotNull String[] properties) {
|
||||||
|
if (properties.length == 0) {
|
||||||
|
throw new IllegalArgumentException("BoundedDoubleArg requires at least one property (min, max)");
|
||||||
|
}
|
||||||
|
this.min = Double.parseDouble(properties[0]);
|
||||||
|
if (properties.length == 1) {
|
||||||
|
this.max = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.max = Double.parseDouble(properties[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, Double> provide(@NotNull String name) {
|
||||||
|
if (max == null) {
|
||||||
|
return BaseCommand.doubleNum(name, min);
|
||||||
|
}
|
||||||
|
return BaseCommand.doubleNum(name, min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Uniform, licensed under the GNU General Public License v3.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) Tofaa2
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.william278.uniform.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface CommandDescription {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Uniform, licensed under the GNU General Public License v3.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) Tofaa2
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.william278.uniform.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface CommandNode {
|
||||||
|
|
||||||
|
String value();
|
||||||
|
String[] aliases() default {};
|
||||||
|
String description() default "";
|
||||||
|
PermissionNode permission() default @PermissionNode("");
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Uniform, licensed under the GNU General Public License v3.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) Tofaa2
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.william278.uniform.annotations;
|
||||||
|
|
||||||
|
import net.william278.uniform.Permission;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.ANNOTATION_TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface PermissionNode {
|
||||||
|
|
||||||
|
String value();
|
||||||
|
Permission.Default defaultValue() default Permission.Default.FALSE;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Uniform, licensed under the GNU General Public License v3.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) Tofaa2
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.william278.uniform.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Syntax {
|
||||||
|
PermissionNode permission() default @PermissionNode("");
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Uniform, licensed under the GNU General Public License v3.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) Tofaa2
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.william278.uniform;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.william278.uniform.annotations.*;
|
||||||
|
import net.william278.uniform.element.ArgumentElement;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@CommandNode(
|
||||||
|
value = "annotated",
|
||||||
|
permission = @PermissionNode(value = "uniform.annotated", defaultValue = Permission.Default.TRUE)
|
||||||
|
)
|
||||||
|
public class AnnotatedCommand {
|
||||||
|
|
||||||
|
@CommandDescription // Can use @CommandDescription instead of @CommandNode field for localization support here
|
||||||
|
public final String DESCRIPTION = "An example Uniform annotated command";
|
||||||
|
|
||||||
|
public AnnotatedCommand() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Syntax
|
||||||
|
void defaultExecutor(CommandUser user) {
|
||||||
|
user.getAudience().sendMessage(Component.text("No arguments passed!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@CommandNode("ping")
|
||||||
|
static class Ping {
|
||||||
|
|
||||||
|
public Ping() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Syntax
|
||||||
|
public void pong(CommandUser user) {
|
||||||
|
user.getAudience().sendMessage(Component.text("Pong!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Syntax
|
||||||
|
public void pongMessage(
|
||||||
|
CommandUser user,
|
||||||
|
@Argument(name = "message", parser = Argument.StringArg.class) String message
|
||||||
|
) {
|
||||||
|
user.getAudience().sendMessage(Component.text("Pong! " + message, NamedTextColor.GREEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Syntax
|
||||||
|
public void pongMessageWithColor(
|
||||||
|
CommandUser user,
|
||||||
|
@Argument(name = "message", parser = Argument.StringArg.class) String message,
|
||||||
|
@Argument(name = "color", parser = ColorArg.class) NamedTextColor color
|
||||||
|
) {
|
||||||
|
user.getAudience().sendMessage(Component.text("Colored Pong! " + message, color));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ColorArg extends Argument.ArgumentProvider<NamedTextColor> {
|
||||||
|
@Override
|
||||||
|
public ArgumentElement<?, NamedTextColor> provide(@NotNull String name) {
|
||||||
|
return new ArgumentElement<>(name, (r) -> {
|
||||||
|
final NamedTextColor color = NamedTextColor.NAMES.value(r.readString().toLowerCase(Locale.ENGLISH));
|
||||||
|
if (color == null) {
|
||||||
|
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}, (context, builder) -> {
|
||||||
|
NamedTextColor.NAMES.keys().forEach(color -> builder.suggest(color.toLowerCase(Locale.ENGLISH)));
|
||||||
|
return builder.buildFuture();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue