Compare commits

..

1 Commits

Author SHA1 Message Date
InkerBot ad25f16f4d use java8 to build 3 months ago

@ -9,7 +9,7 @@ plugins {
id 'java' id 'java'
} }
group 'net.william278' group 'org.inksnow.husk'
version "$ext.library_version${versionMetadata()}" version "$ext.library_version${versionMetadata()}"
description "$ext.library_description" description "$ext.library_description"
defaultTasks 'licenseFormat', 'build' defaultTasks 'licenseFormat', 'build'
@ -21,30 +21,12 @@ ext {
publishing { publishing {
repositories { repositories {
if (System.getenv("RELEASES_MAVEN_USERNAME") != null) { maven {
maven { name = 'husk-release'
name = "william278-releases" url = findProperty("repository.huskrelease.url")
url = "https://repo.william278.net/releases" credentials {
credentials { username = findProperty("repository.huskrelease.username")
username = System.getenv("RELEASES_MAVEN_USERNAME") password = findProperty("repository.huskrelease.password")
password = System.getenv("RELEASES_MAVEN_PASSWORD")
}
authentication {
basic(BasicAuthentication)
}
}
}
if (System.getenv("SNAPSHOTS_MAVEN_USERNAME") != null) {
maven {
name = "william278-snapshots"
url = "https://repo.william278.net/snapshots"
credentials {
username = System.getenv("SNAPSHOTS_MAVEN_USERNAME")
password = System.getenv("SNAPSHOTS_MAVEN_PASSWORD")
}
authentication {
basic(BasicAuthentication)
}
} }
} }
} }
@ -56,7 +38,7 @@ allprojects {
apply plugin: 'java' apply plugin: 'java'
compileJava.options.encoding = 'UTF-8' compileJava.options.encoding = 'UTF-8'
compileJava.options.release.set 17 compileJava.options.release.set 8
javadoc.options.encoding = 'UTF-8' javadoc.options.encoding = 'UTF-8'
javadoc.options.addStringOption('Xdoclint:none', '-quiet') javadoc.options.addStringOption('Xdoclint:none', '-quiet')
@ -134,7 +116,7 @@ subprojects {
if (['common'].contains(project.name)) { if (['common'].contains(project.name)) {
publications { publications {
mavenJavaCommon(MavenPublication) { mavenJavaCommon(MavenPublication) {
groupId = 'net.william278.uniform' groupId = 'org.inksnow.husk.uniform'
artifactId = 'uniform-common' artifactId = 'uniform-common'
version = "$rootProject.version" version = "$rootProject.version"
artifact shadowJar artifact shadowJar
@ -147,7 +129,7 @@ subprojects {
if (['paper'].contains(project.name)) { if (['paper'].contains(project.name)) {
publications { publications {
mavenJavaPaper(MavenPublication) { mavenJavaPaper(MavenPublication) {
groupId = 'net.william278.uniform' groupId = 'org.inksnow.husk.uniform'
artifactId = 'uniform-paper' artifactId = 'uniform-paper'
version = "$rootProject.version" version = "$rootProject.version"
artifact shadowJar artifact shadowJar
@ -160,7 +142,7 @@ subprojects {
if (['bukkit'].contains(project.name)) { if (['bukkit'].contains(project.name)) {
publications { publications {
mavenJavaBukkit(MavenPublication) { mavenJavaBukkit(MavenPublication) {
groupId = 'net.william278.uniform' groupId = 'org.inksnow.husk.uniform'
artifactId = 'uniform-bukkit' artifactId = 'uniform-bukkit'
version = "$rootProject.version" version = "$rootProject.version"
artifact shadowJar artifact shadowJar
@ -173,7 +155,7 @@ subprojects {
if (['velocity'].contains(project.name)) { if (['velocity'].contains(project.name)) {
publications { publications {
mavenJavaVelocity(MavenPublication) { mavenJavaVelocity(MavenPublication) {
groupId = 'net.william278.uniform' groupId = 'org.inksnow.husk.uniform'
artifactId = 'uniform-velocity' artifactId = 'uniform-velocity'
version = "$rootProject.version" version = "$rootProject.version"
artifact shadowJar artifact shadowJar
@ -186,7 +168,7 @@ subprojects {
if (['fabric-1.20.1'].contains(project.name)) { if (['fabric-1.20.1'].contains(project.name)) {
publications { publications {
mavenJavaFabric1_20_1(MavenPublication) { mavenJavaFabric1_20_1(MavenPublication) {
groupId = 'net.william278.uniform' groupId = 'org.inksnow.husk.uniform'
artifactId = 'uniform-fabric' artifactId = 'uniform-fabric'
version = "${rootProject.version}+1.20.1" version = "${rootProject.version}+1.20.1"
artifact remapJar artifact remapJar
@ -199,7 +181,7 @@ subprojects {
if (['fabric-1.21'].contains(project.name)) { if (['fabric-1.21'].contains(project.name)) {
publications { publications {
mavenJavaFabric1_21(MavenPublication) { mavenJavaFabric1_21(MavenPublication) {
groupId = 'net.william278.uniform' groupId = 'org.inksnow.husk.uniform'
artifactId = 'uniform-fabric' artifactId = 'uniform-fabric'
version = "${rootProject.version}+1.21" version = "${rootProject.version}+1.21"
artifact remapJar artifact remapJar
@ -212,7 +194,7 @@ subprojects {
if (['sponge-11'].contains(project.name)) { if (['sponge-11'].contains(project.name)) {
publications { publications {
mavenSponge11(MavenPublication) { mavenSponge11(MavenPublication) {
groupId = 'net.william278.uniform' groupId = 'org.inksnow.husk.uniform'
artifactId = 'uniform-sponge' artifactId = 'uniform-sponge'
version = "${rootProject.version}+11" version = "${rootProject.version}+11"
artifact shadowJar artifact shadowJar

@ -6,7 +6,7 @@ plugins {
dependencies { dependencies {
api project(path: ':common') api project(path: ':common')
implementation 'net.kyori:adventure-platform-bukkit:4.3.4' implementation 'net.kyori:adventure-platform-bukkit:4.3.3'
implementation 'space.arim.morepaperlib:morepaperlib:0.4.4' implementation 'space.arim.morepaperlib:morepaperlib:0.4.4'
compileOnlyApi 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT' compileOnlyApi 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'

@ -32,6 +32,7 @@ import net.william278.uniform.BaseCommand;
import net.william278.uniform.Command; import net.william278.uniform.Command;
import net.william278.uniform.Permission; import net.william278.uniform.Permission;
import net.william278.uniform.Uniform; import net.william278.uniform.Uniform;
import net.william278.uniform.util.StringUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandException; import org.bukkit.command.CommandException;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -82,14 +83,17 @@ public class BukkitCommand extends BaseCommand<CommandSender> {
this.setAliases(command.getAliases()); this.setAliases(command.getAliases());
this.setUsage(getUsageText()); this.setUsage(getUsageText());
if (permission != null) { if (permission != null) {
this.setPermission(permission.node()); this.setPermission(permission.getNode());
} }
} }
@NotNull @NotNull
private String getUsageText() { private String getUsageText() {
return dispatcher.getSmartUsage(dispatcher.getRoot(), Bukkit.getConsoleSender()).values().stream() return dispatcher.getSmartUsage(dispatcher.getRoot(), Bukkit.getConsoleSender())
.map("/%s"::formatted).collect(Collectors.joining("\n")); .values()
.stream()
.map("/"::concat)
.collect(Collectors.joining("\n"));
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -121,13 +125,15 @@ public class BukkitCommand extends BaseCommand<CommandSender> {
dispatcher.parse(passed, sender), dispatcher.parse(passed, sender),
passed.length() // Spigot API limitation - we can only TAB complete the full text length :( passed.length() // Spigot API limitation - we can only TAB complete the full text length :(
) )
.thenApply(suggestions -> suggestions.getList().stream().map(Suggestion::getText).toList()) .thenApply(suggestions -> suggestions.getList().stream()
.map(Suggestion::getText)
.collect(Collectors.toList()))
.join(); .join();
} }
@Override @Override
public boolean testPermissionSilent(@NotNull CommandSender target) { public boolean testPermissionSilent(@NotNull CommandSender target) {
if (permission == null || permission.node().isBlank()) { if (permission == null || StringUtil.isBlank(permission.getNode())) {
return true; return true;
} }
return new BukkitCommandUser(target).checkPermission(permission); return new BukkitCommandUser(target).checkPermission(permission);
@ -140,7 +146,10 @@ public class BukkitCommand extends BaseCommand<CommandSender> {
@NotNull @NotNull
private String getInput(@NotNull String[] args) { private String getInput(@NotNull String[] args) {
return args.length == 0 ? getName() : "%s %s".formatted(getName(), String.join(" ", args)); if (args.length == 0) {
return getName();
}
return getName() + " " + String.join(" ", args);
} }
} }

@ -21,6 +21,7 @@
package net.william278.uniform.bukkit; package net.william278.uniform.bukkit;
import lombok.Value;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.william278.uniform.CommandUser; import net.william278.uniform.CommandUser;
import net.william278.uniform.Permission; import net.william278.uniform.Permission;
@ -32,7 +33,10 @@ import org.jetbrains.annotations.Nullable;
import java.util.UUID; import java.util.UUID;
public record BukkitCommandUser(@NotNull CommandSender sender) implements CommandUser { @Value
public class BukkitCommandUser implements CommandUser {
@NotNull CommandSender sender;
@Override @Override
@NotNull @NotNull
@ -48,15 +52,15 @@ public record BukkitCommandUser(@NotNull CommandSender sender) implements Comman
@Override @Override
@Nullable @Nullable
public UUID getUuid() { public UUID getUuid() {
return sender instanceof Player player ? player.getUniqueId() : null; return sender instanceof Player ? ((Player) sender).getUniqueId() : null;
} }
@Override @Override
public boolean checkPermission(@NotNull Permission permission) { public boolean checkPermission(@NotNull Permission permission) {
if (sender.isPermissionSet(permission.node())) { if (sender.isPermissionSet(permission.getNode())) {
return sender.hasPermission(permission.node()); return sender.hasPermission(permission.getNode());
} }
return permission.defaultValue().check( return permission.getDefaultValue().check(
sender.isOp() || sender instanceof ConsoleCommandSender sender.isOp() || sender instanceof ConsoleCommandSender
); );
} }

@ -37,6 +37,7 @@ import space.arim.morepaperlib.commands.CommandRegistration;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
/** /**
* A class for registering commands with the Bukkit server's CommandMap * A class for registering commands with the Bukkit server's CommandMap
@ -91,7 +92,8 @@ public final class BukkitUniform implements Uniform {
registrar.getServerCommandMap().registerAll( registrar.getServerCommandMap().registerAll(
PLUGIN.getName().toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9_]", ""), PLUGIN.getName().toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9_]", ""),
Arrays.stream(commands).map(c -> (BukkitCommand) c) Arrays.stream(commands).map(c -> (BukkitCommand) c)
.map(c -> (org.bukkit.command.Command) c.getImpl(this)).toList() .map(c -> (org.bukkit.command.Command) c.getImpl(this))
.collect(Collectors.toList())
); );
} }

@ -6,6 +6,7 @@ plugins {
dependencies { dependencies {
compileOnlyApi 'com.mojang:brigadier:1.1.8' compileOnlyApi 'com.mojang:brigadier:1.1.8'
compileOnlyApi 'net.kyori:adventure-api:4.17.0' compileOnlyApi 'net.kyori:adventure-api:4.17.0'
compileOnlyApi 'com.google.guava:guava:21.0'
compileOnly 'org.jetbrains:annotations:24.1.0' compileOnly 'org.jetbrains:annotations:24.1.0'
compileOnly 'org.projectlombok:lombok:1.18.32' compileOnly 'org.projectlombok:lombok:1.18.32'

@ -21,6 +21,7 @@
package net.william278.uniform; package net.william278.uniform;
import com.google.common.collect.ImmutableList;
import com.mojang.brigadier.arguments.*; import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.SuggestionProvider;
@ -114,7 +115,7 @@ public abstract class BaseCommand<S> {
@SafeVarargs @SafeVarargs
public final void addConditionalSyntax(@Nullable Predicate<S> condition, @NotNull CommandExecutor<S> executor, public final void addConditionalSyntax(@Nullable Predicate<S> condition, @NotNull CommandExecutor<S> executor,
@NotNull CommandElement<S>... elements) { @NotNull CommandElement<S>... elements) {
var syntax = new CommandSyntax<>(condition, executor, List.of(elements)); CommandSyntax<S> syntax = new CommandSyntax<>(condition, executor, ImmutableList.copyOf(elements));
this.syntaxes.add(syntax); this.syntaxes.add(syntax);
} }

@ -21,10 +21,13 @@
package net.william278.uniform; package net.william278.uniform;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.Value;
import net.william278.uniform.annotations.Argument; import net.william278.uniform.annotations.Argument;
import net.william278.uniform.annotations.CommandDescription; import net.william278.uniform.annotations.CommandDescription;
import net.william278.uniform.annotations.CommandNode; import net.william278.uniform.annotations.CommandNode;
@ -39,6 +42,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Parameter; import java.lang.reflect.Parameter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -51,7 +55,7 @@ import static net.william278.uniform.CommandExecutor.methodToExecutor;
public abstract class Command implements CommandProvider { public abstract class Command implements CommandProvider {
private final String name; private final String name;
private List<String> aliases = List.of(); private List<String> aliases = Collections.emptyList();
private String description = ""; private String description = "";
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
private @Nullable Permission permission = null; private @Nullable Permission permission = null;
@ -70,7 +74,7 @@ public abstract class Command implements CommandProvider {
throw new IllegalArgumentException("@CommandNode annotation is required on annotated command/sub-commands"); throw new IllegalArgumentException("@CommandNode annotation is required on annotated command/sub-commands");
} }
this.name = node.value(); this.name = node.value();
this.aliases = List.of(node.aliases()); this.aliases = ImmutableList.copyOf(node.aliases());
this.description = node.description(); this.description = node.description();
this.scope = node.scope(); this.scope = node.scope();
Permission.annotated(node.permission()).ifPresent(this::setPermission); Permission.annotated(node.permission()).ifPresent(this::setPermission);
@ -87,11 +91,16 @@ public abstract class Command implements CommandProvider {
} }
public boolean contains(@NotNull CommandUser user) { public boolean contains(@NotNull CommandUser user) {
return switch (this) { switch (this) {
case IN_GAME -> !user.isConsole(); case IN_GAME:
case CONSOLE -> user.isConsole(); return !user.isConsole();
case ALL -> true; case CONSOLE:
}; return user.isConsole();
case ALL:
return true;
default:
throw new IllegalArgumentException("Unknown execution scope: " + this);
}
} }
} }
@ -194,8 +203,15 @@ public abstract class Command implements CommandProvider {
} }
} }
public record SubCommand(@NotNull String name, @NotNull List<String> aliases, @Nullable Permission permission, @Value
@NotNull ExecutionScope scope, @NotNull CommandProvider provider) { @RequiredArgsConstructor
public static class SubCommand {
@NotNull String name;
@NotNull List<String> aliases;
@Nullable Permission permission;
@NotNull ExecutionScope scope;
@NotNull CommandProvider provider;
public SubCommand(@NotNull String name, @NotNull List<String> aliases, @Nullable Permission permission, public SubCommand(@NotNull String name, @NotNull List<String> aliases, @Nullable Permission permission,
@NotNull CommandProvider provider) { @NotNull CommandProvider provider) {
this(name, aliases, permission, ExecutionScope.ALL, provider); this(name, aliases, permission, ExecutionScope.ALL, provider);
@ -206,11 +222,11 @@ public abstract class Command implements CommandProvider {
} }
public SubCommand(@NotNull String name, @Nullable Permission permission, @NotNull CommandProvider provider) { public SubCommand(@NotNull String name, @Nullable Permission permission, @NotNull CommandProvider provider) {
this(name, List.of(), permission, ExecutionScope.ALL, provider); this(name, Collections.emptyList(), permission, ExecutionScope.ALL, provider);
} }
public SubCommand(@NotNull String name, @NotNull CommandProvider provider) { public SubCommand(@NotNull String name, @NotNull CommandProvider provider) {
this(name, List.of(), null, ExecutionScope.ALL, provider); this(name, Collections.emptyList(), null, ExecutionScope.ALL, provider);
} }

@ -39,7 +39,7 @@ public interface CommandExecutor<S> {
@NotNull BaseCommand<?> cmd) { @NotNull BaseCommand<?> cmd) {
return (context) -> { return (context) -> {
try { try {
method.invoke(instance, injectParams(method, context, cmd)); method.invoke(instance, private$injectParams(method, context, cmd));
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("Failed to invoke command executor from annotated method", e); throw new IllegalStateException("Failed to invoke command executor from annotated method", e);
} }
@ -47,8 +47,8 @@ public interface CommandExecutor<S> {
} }
@Nullable @Nullable
private static Object @NotNull [] injectParams(@NotNull Method method, @NotNull CommandContext<?> context, static Object @NotNull [] private$injectParams(@NotNull Method method, @NotNull CommandContext<?> context,
@NotNull BaseCommand<?> cmd) { @NotNull BaseCommand<?> cmd) {
final Object[] params = new Object[method.getParameterCount()]; final Object[] params = new Object[method.getParameterCount()];
for (int i = 0; i < method.getParameterCount(); i++) { for (int i = 0; i < method.getParameterCount(); i++) {
final Parameter param = method.getParameters()[i]; final Parameter param = method.getParameters()[i];

@ -21,6 +21,7 @@
package net.william278.uniform; package net.william278.uniform;
import lombok.Value;
import net.william278.uniform.element.CommandElement; import net.william278.uniform.element.CommandElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -28,7 +29,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
public record CommandSyntax<S>(@Nullable Predicate<S> condition, @NotNull CommandExecutor<S> executor, @Value
@NotNull List<CommandElement<S>> elements) { public class CommandSyntax<S> {
@Nullable Predicate<S> condition;
@NotNull CommandExecutor<S> executor;
@NotNull List<CommandElement<S>> elements;
} }

@ -21,6 +21,9 @@
package net.william278.uniform; package net.william278.uniform;
import com.google.common.collect.ImmutableList;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import net.william278.uniform.element.CommandElement; import net.william278.uniform.element.CommandElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -31,8 +34,13 @@ import java.util.Map;
import static net.william278.uniform.Graph.commandToElement; import static net.william278.uniform.Graph.commandToElement;
record ConversionNode<S>(@NotNull CommandElement<S> element, @Nullable Execution<S> execution, @Value
@NotNull Map<CommandElement<S>, ConversionNode<S>> nextMap) { @RequiredArgsConstructor
public class ConversionNode<S> {
@NotNull CommandElement<S> element;
@Nullable Execution<S> execution;
@NotNull Map<CommandElement<S>, ConversionNode<S>> nextMap;
static <S> @NotNull ConversionNode<S> fromCommand(@NotNull BaseCommand<S> command) { static <S> @NotNull ConversionNode<S> fromCommand(@NotNull BaseCommand<S> command) {
ConversionNode<S> root = new ConversionNode<>(commandToElement(command), Execution.fromCommand(command)); ConversionNode<S> root = new ConversionNode<>(commandToElement(command), Execution.fromCommand(command));
@ -40,8 +48,8 @@ record ConversionNode<S>(@NotNull CommandElement<S> element, @Nullable Execution
for (CommandSyntax<S> syntax : command.getSyntaxes()) { for (CommandSyntax<S> syntax : command.getSyntaxes()) {
ConversionNode<S> syntaxNode = root; ConversionNode<S> syntaxNode = root;
for (CommandElement<S> element : syntax.elements()) { for (CommandElement<S> element : syntax.getElements()) {
boolean last = element == syntax.elements().get(syntax.elements().size() - 1); boolean last = element == syntax.getElements().get(syntax.getElements().size() - 1);
syntaxNode = syntaxNode.nextMap.computeIfAbsent(element, e -> { syntaxNode = syntaxNode.nextMap.computeIfAbsent(element, e -> {
Execution<S> execution = last ? Execution.fromSyntax(syntax) : null; Execution<S> execution = last ? Execution.fromSyntax(syntax) : null;
return new ConversionNode<>(e, execution); return new ConversionNode<>(e, execution);
@ -69,7 +77,7 @@ record ConversionNode<S>(@NotNull CommandElement<S> element, @Nullable Execution
nodes[i++] = entry.toNode(); nodes[i++] = entry.toNode();
} }
return new Node<>(this.element, this.execution, List.of(nodes)); return new Node<>(this.element, this.execution, ImmutableList.copyOf(nodes));
} }
} }

@ -22,6 +22,7 @@
package net.william278.uniform; package net.william278.uniform;
import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.ArgumentBuilder;
import lombok.Value;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -29,11 +30,16 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.function.Predicate; import java.util.function.Predicate;
record Execution<S>(@NotNull Predicate<S> predicate, @Nullable CommandExecutor<S> defaultExecutor, @Value
@Nullable CommandExecutor<S> executor, @Nullable Predicate<S> condition) implements Predicate<S> { public class Execution<S> implements Predicate<S> {
private static final Executor CACHED_EXECUTOR = Executors.newCachedThreadPool(); private static final Executor CACHED_EXECUTOR = Executors.newCachedThreadPool();
@NotNull Predicate<S> predicate;
@Nullable CommandExecutor<S> defaultExecutor;
@Nullable CommandExecutor<S> executor;
@Nullable Predicate<S> condition;
@NotNull @NotNull
static <S> Execution<S> fromCommand(@NotNull BaseCommand<S> command) { static <S> Execution<S> fromCommand(@NotNull BaseCommand<S> command) {
CommandExecutor<S> defaultExecutor = command.getDefaultExecutor(); CommandExecutor<S> defaultExecutor = command.getDefaultExecutor();
@ -42,9 +48,9 @@ record Execution<S>(@NotNull Predicate<S> predicate, @Nullable CommandExecutor<S
CommandExecutor<S> executor = defaultExecutor; CommandExecutor<S> executor = defaultExecutor;
Predicate<S> condition = defaultCondition; Predicate<S> condition = defaultCondition;
for (CommandSyntax<S> syntax : command.getSyntaxes()) { for (CommandSyntax<S> syntax : command.getSyntaxes()) {
if (!syntax.elements().isEmpty()) continue; if (!syntax.getElements().isEmpty()) continue;
executor = syntax.executor(); executor = syntax.getExecutor();
condition = syntax.condition(); condition = syntax.getCondition();
break; break;
} }
@ -53,8 +59,8 @@ record Execution<S>(@NotNull Predicate<S> predicate, @Nullable CommandExecutor<S
@NotNull @NotNull
static <S> Execution<S> fromSyntax(@NotNull CommandSyntax<S> syntax) { static <S> Execution<S> fromSyntax(@NotNull CommandSyntax<S> syntax) {
CommandExecutor<S> executor = syntax.executor(); CommandExecutor<S> executor = syntax.getExecutor();
Predicate<S> condition = syntax.condition(); Predicate<S> condition = syntax.getCondition();
return new Execution<>(source -> condition == null || condition.test(source), null, executor, condition); return new Execution<>(source -> condition == null || condition.test(source), null, executor, condition);
} }

@ -24,11 +24,14 @@ package net.william278.uniform;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode;
import lombok.Value;
import net.william278.uniform.element.CommandElement; import net.william278.uniform.element.CommandElement;
import net.william278.uniform.element.LiteralElement; import net.william278.uniform.element.LiteralElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
record Graph<S>(@NotNull Node<S> root) { @Value
public class Graph<S> {
@NotNull Node<S> root;
static <S> @NotNull Graph<S> create(@NotNull BaseCommand<S> command) { static <S> @NotNull Graph<S> create(@NotNull BaseCommand<S> command) {
return new Graph<>(Node.command(command)); return new Graph<>(Node.command(command));
@ -41,10 +44,10 @@ record Graph<S>(@NotNull Node<S> root) {
@NotNull @NotNull
LiteralCommandNode<S> build() { LiteralCommandNode<S> build() {
CommandNode<S> node = this.root.build(); CommandNode<S> node = this.root.build();
if (!(node instanceof LiteralCommandNode<S> literalNode)) { if (!(node instanceof LiteralCommandNode)) {
throw new IllegalStateException("Root node is somehow not a literal node. This should be impossible."); throw new IllegalStateException("Root node is somehow not a literal node. This should be impossible.");
} }
return literalNode; return (LiteralCommandNode<S>) node;
} }
@NotNull @NotNull
@ -52,7 +55,7 @@ record Graph<S>(@NotNull Node<S> root) {
final LiteralArgumentBuilder<S> builder = LiteralArgumentBuilder.literal(name); final LiteralArgumentBuilder<S> builder = LiteralArgumentBuilder.literal(name);
final CommandNode<S> command = this.root.build(); final CommandNode<S> command = this.root.build();
builder.executes(command.getCommand()); builder.executes(command.getCommand());
this.root.children().forEach(child -> builder.then(child.build())); this.root.getChildren().forEach(child -> builder.then(child.build()));
return builder; return builder;
} }

@ -23,13 +23,18 @@ package net.william278.uniform;
import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.CommandNode;
import lombok.Value;
import net.william278.uniform.element.CommandElement; import net.william278.uniform.element.CommandElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
record Node<S>(@NotNull CommandElement<S> element, @Nullable Execution<S> execution, @NotNull List<Node<S>> children) { @Value
public class Node<S> {
@NotNull CommandElement<S> element;
@Nullable Execution<S> execution;
@NotNull List<Node<S>> children;
static <S> @NotNull Node<S> command(@NotNull BaseCommand<S> command) { static <S> @NotNull Node<S> command(@NotNull BaseCommand<S> command) {
return ConversionNode.fromCommand(command).toNode(); return ConversionNode.fromCommand(command).toNode();

@ -21,14 +21,22 @@
package net.william278.uniform; package net.william278.uniform;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import net.william278.uniform.annotations.PermissionNode; import net.william278.uniform.annotations.PermissionNode;
import net.william278.uniform.util.StringUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public record Permission(@NotNull String node, @NotNull Default defaultValue) { @Value
@RequiredArgsConstructor
public class Permission {
@NotNull String node;
@NotNull Default defaultValue;
Permission(@NotNull String node) { Permission(@NotNull String node) {
this(node, Default.FALSE); this(node, Default.FALSE);
@ -51,7 +59,7 @@ public record Permission(@NotNull String node, @NotNull Default defaultValue) {
@NotNull @NotNull
static Optional<Permission> annotated(@NotNull PermissionNode annotation) { static Optional<Permission> annotated(@NotNull PermissionNode annotation) {
if (annotation.value().isBlank()) { if (StringUtil.isBlank(annotation.value())) {
return Optional.empty(); return Optional.empty();
} }
return Optional.of(new Permission(annotation.value(), annotation.defaultValue())); return Optional.of(new Permission(annotation.value(), annotation.defaultValue()));
@ -63,11 +71,12 @@ public record Permission(@NotNull String node, @NotNull Default defaultValue) {
FALSE; FALSE;
public boolean check(boolean op) { public boolean check(boolean op) {
return switch (this) { switch (this) {
case IF_OP -> op; case IF_OP: return op;
case TRUE -> true; case TRUE: return true;
case FALSE -> false; case FALSE: return false;
}; default: throw new IllegalStateException("Unexpected value: " + this);
}
} }
} }

@ -32,7 +32,7 @@ public interface Uniform {
default void register(@NotNull Object... annotated) { default void register(@NotNull Object... annotated) {
register(Arrays.stream(annotated) register(Arrays.stream(annotated)
.map(c -> c instanceof Command cmd ? cmd : new Command.AnnotatedCommand(c)) .map(c -> c instanceof Command ? (Command) c : new Command.AnnotatedCommand(c))
.toArray(Command[]::new)); .toArray(Command[]::new));
} }

@ -50,7 +50,7 @@ public final class ArgumentElement<S, T> implements CommandElement<S> {
@Override @Override
@NotNull @NotNull
public ArgumentBuilder<S, ?> toBuilder() { public ArgumentBuilder<S, ?> toBuilder() {
var builder = RequiredArgumentBuilder.<S, T>argument(this.name, this.type); RequiredArgumentBuilder<S, T> builder = RequiredArgumentBuilder.<S, T>argument(this.name, this.type);
if (this.suggestionProvider != null) builder.suggests(this.suggestionProvider); if (this.suggestionProvider != null) builder.suggests(this.suggestionProvider);
return builder; return builder;
} }

@ -23,9 +23,12 @@ package net.william278.uniform.element;
import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import lombok.Value;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public record LiteralElement<S>(@NotNull String name) implements CommandElement<S> { @Value
public class LiteralElement<S> implements CommandElement<S> {
@NotNull String name;
@Override @Override
@NotNull @NotNull

@ -0,0 +1,40 @@
/*
* 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.util;
import lombok.experimental.UtilityClass;
@UtilityClass
public class StringUtil {
public static boolean isBlank(String $this) {
final int strLen = $this.length();
if (strLen == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace($this.charAt(i))) {
return false;
}
}
return true;
}
}

@ -21,6 +21,7 @@
package net.william278.uniform; package net.william278.uniform;
import com.google.common.collect.ImmutableList;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.william278.uniform.element.ArgumentElement; import net.william278.uniform.element.ArgumentElement;
@ -38,7 +39,7 @@ public class ExtendedCommand extends Command {
public ExtendedCommand() { public ExtendedCommand() {
super("example"); super("example");
setDescription("An example command for Uniform"); setDescription("An example command for Uniform");
setAliases(List.of("helloworld")); setAliases(ImmutableList.of("helloworld"));
setPermission(Permission.defaultIfOp("uniform.example")); setPermission(Permission.defaultIfOp("uniform.example"));
} }
@ -56,9 +57,21 @@ public class ExtendedCommand extends Command {
final CommandUser user = sub.getUser(ctx.getSource()); final CommandUser user = sub.getUser(ctx.getSource());
final IceCreamFlavor flavor = ctx.getArgument("flavor", IceCreamFlavor.class); final IceCreamFlavor flavor = ctx.getArgument("flavor", IceCreamFlavor.class);
switch (flavor) { switch (flavor) {
case VANILLA -> user.getAudience().sendMessage(Component.text("Vanilla ice cream is fine!")); case VANILLA: {
case CHOCOLATE -> user.getAudience().sendMessage(Component.text("Chocolate ice cream is kino!")); user.getAudience().sendMessage(Component.text("Vanilla ice cream is fine!"));
case STRAWBERRY -> user.getAudience().sendMessage(Component.text("Strawberry ice cream is ok...")); break;
}
case CHOCOLATE: {
user.getAudience().sendMessage(Component.text("Chocolate ice cream is kino!"));
break;
}
case STRAWBERRY: {
user.getAudience().sendMessage(Component.text("Strawberry ice cream is ok..."));
break;
}
default: {
// do nothing
}
} }
}, exampleCustomArg())); }, exampleCustomArg()));
} }

@ -27,6 +27,7 @@ import com.mojang.brigadier.suggestion.Suggestion;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.william278.uniform.*; import net.william278.uniform.*;
import net.william278.uniform.util.StringUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandException; import org.bukkit.command.CommandException;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -87,14 +88,14 @@ public class LegacyPaperCommand extends BaseCommand<CommandSender> {
this.setAliases(command.getAliases()); this.setAliases(command.getAliases());
this.setUsage(getUsageText()); this.setUsage(getUsageText());
if (permission != null) { if (permission != null) {
this.setPermission(permission.node()); this.setPermission(permission.getNode());
} }
} }
@NotNull @NotNull
private String getUsageText() { private String getUsageText() {
return dispatcher.getSmartUsage(dispatcher.getRoot(), Bukkit.getConsoleSender()).values().stream() return dispatcher.getSmartUsage(dispatcher.getRoot(), Bukkit.getConsoleSender()).values().stream()
.map("/%s"::formatted).collect(Collectors.joining("\n")); .map("/"::concat).collect(Collectors.joining("\n"));
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -126,13 +127,16 @@ public class LegacyPaperCommand extends BaseCommand<CommandSender> {
dispatcher.parse(passed, sender), dispatcher.parse(passed, sender),
passed.length() // Spigot API limitation - we can only TAB complete the full text length :( passed.length() // Spigot API limitation - we can only TAB complete the full text length :(
) )
.thenApply(suggestions -> suggestions.getList().stream().map(Suggestion::getText).toList()) .thenApply(suggestions -> suggestions.getList()
.stream()
.map(Suggestion::getText)
.collect(Collectors.toList()))
.join(); .join();
} }
@Override @Override
public boolean testPermissionSilent(@NotNull CommandSender target) { public boolean testPermissionSilent(@NotNull CommandSender target) {
if (permission == null || permission.node().isBlank()) { if (permission == null || StringUtil.isBlank(permission.getNode())) {
return true; return true;
} }
return new LegacyPaperCommandUser(target).checkPermission(permission); return new LegacyPaperCommandUser(target).checkPermission(permission);
@ -140,7 +144,10 @@ public class LegacyPaperCommand extends BaseCommand<CommandSender> {
@NotNull @NotNull
private String getInput(@NotNull String[] args) { private String getInput(@NotNull String[] args) {
return args.length == 0 ? getName() : "%s %s".formatted(getName(), String.join(" ", args)); if (args.length == 0) {
return getName();
}
return getName() + " " + String.join(" ", args);
} }
} }

@ -21,6 +21,7 @@
package net.william278.uniform.paper; package net.william278.uniform.paper;
import lombok.Value;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.william278.uniform.CommandUser; import net.william278.uniform.CommandUser;
import net.william278.uniform.Permission; import net.william278.uniform.Permission;
@ -32,7 +33,10 @@ import org.jetbrains.annotations.Nullable;
import java.util.UUID; import java.util.UUID;
public record LegacyPaperCommandUser(@NotNull CommandSender sender) implements CommandUser { @Value
public class LegacyPaperCommandUser implements CommandUser {
@NotNull CommandSender sender;
@Override @Override
@NotNull @NotNull
@ -48,15 +52,15 @@ public record LegacyPaperCommandUser(@NotNull CommandSender sender) implements C
@Override @Override
@Nullable @Nullable
public UUID getUuid() { public UUID getUuid() {
return sender instanceof Player player ? player.getUniqueId() : null; return sender instanceof Player ? ((Player) sender).getUniqueId() : null;
} }
@Override @Override
public boolean checkPermission(@NotNull Permission permission) { public boolean checkPermission(@NotNull Permission permission) {
if (sender.isPermissionSet(permission.node())) { if (sender.isPermissionSet(permission.getNode())) {
return sender.hasPermission(permission.node()); return sender.hasPermission(permission.getNode());
} }
return permission.defaultValue().check( return permission.getDefaultValue().check(
sender.isOp() || sender instanceof ConsoleCommandSender sender.isOp() || sender instanceof ConsoleCommandSender
); );
} }

@ -21,6 +21,7 @@
package net.william278.uniform.paper; package net.william278.uniform.paper;
import com.google.common.collect.ImmutableList;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
@ -38,6 +39,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
@SuppressWarnings({"unused", "UnstableApiUsage"}) @SuppressWarnings({"unused", "UnstableApiUsage"})
public class PaperCommand extends BaseCommand<CommandSourceStack> { public class PaperCommand extends BaseCommand<CommandSourceStack> {
@ -92,11 +94,11 @@ public class PaperCommand extends BaseCommand<CommandSourceStack> {
if (playerName.equals("@a")) { if (playerName.equals("@a")) {
return Bukkit.getOnlinePlayers(); return Bukkit.getOnlinePlayers();
} }
var player = Bukkit.getPlayer(playerName); Player player = Bukkit.getPlayer(playerName);
if (player == null) { if (player == null) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader); throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader);
} }
return List.of(player); return ImmutableList.of(player);
}, (context, builder) -> { }, (context, builder) -> {
builder.suggest("@a"); builder.suggest("@a");
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
@ -112,9 +114,9 @@ public class PaperCommand extends BaseCommand<CommandSourceStack> {
public List<CommandSyntax<CommandSourceStack>> getSyntaxes() { public List<CommandSyntax<CommandSourceStack>> getSyntaxes() {
return super.getSyntaxes().stream().map( return super.getSyntaxes().stream().map(
syntax -> new CommandSyntax<>( syntax -> new CommandSyntax<>(
syntax.condition(), syntax.getCondition(),
syntax.executor(), syntax.getExecutor(),
syntax.elements().stream() syntax.getElements().stream()
.filter(e -> e instanceof ArgumentElement) .filter(e -> e instanceof ArgumentElement)
.map(e -> (ArgumentElement<?, ?>) e) .map(e -> (ArgumentElement<?, ?>) e)
.map(e -> e.custom() ? new ArgumentElement<>( .map(e -> e.custom() ? new ArgumentElement<>(
@ -123,9 +125,9 @@ public class PaperCommand extends BaseCommand<CommandSourceStack> {
e.suggestionProvider() e.suggestionProvider()
) : e) ) : e)
.map(e -> (CommandElement<CommandSourceStack>) e) .map(e -> (CommandElement<CommandSourceStack>) e)
.toList() .collect(Collectors.toList())
) )
).toList(); ).collect(Collectors.toList());
} }
@Override @Override

@ -22,6 +22,7 @@
package net.william278.uniform.paper; package net.william278.uniform.paper;
import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.CommandSourceStack;
import lombok.Value;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.william278.uniform.CommandUser; import net.william278.uniform.CommandUser;
import net.william278.uniform.Permission; import net.william278.uniform.Permission;
@ -32,8 +33,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.UUID; import java.util.UUID;
@SuppressWarnings("UnstableApiUsage") @SuppressWarnings("UnstableApiUsage")
public record PaperCommandUser(@NotNull CommandSourceStack source) implements CommandUser { @Value
public class PaperCommandUser implements CommandUser {
@NotNull CommandSourceStack source;
@Override @Override
@NotNull @NotNull
@ -55,10 +57,10 @@ public record PaperCommandUser(@NotNull CommandSourceStack source) implements Co
@Override @Override
public boolean checkPermission(@NotNull Permission permission) { public boolean checkPermission(@NotNull Permission permission) {
if (source.getSender().isPermissionSet(permission.node())) { if (source.getSender().isPermissionSet(permission.getNode())) {
return source.getSender().hasPermission(permission.node()); return source.getSender().hasPermission(permission.getNode());
} }
return permission.defaultValue().check( return permission.getDefaultValue().check(
source.getSender().isOp() || source.getSender() instanceof ConsoleCommandSender source.getSender().isOp() || source.getSender() instanceof ConsoleCommandSender
); );
} }

@ -35,6 +35,7 @@ import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
@ -108,7 +109,8 @@ public final class PaperUniform implements Uniform {
// Register with the legacy API // Register with the legacy API
plugin.getServer().getCommandMap().registerAll( plugin.getServer().getCommandMap().registerAll(
plugin.getName().toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9_]", ""), plugin.getName().toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9_]", ""),
s.map(c -> (LegacyPaperCommand) c).map(c -> (org.bukkit.command.Command) c.getImpl(this)).toList() s.map(c -> (LegacyPaperCommand) c).map(c -> (org.bukkit.command.Command) c.getImpl(this))
.collect(Collectors.toList())
); );
} }

@ -12,14 +12,14 @@ include(
// Server Plugins // Server Plugins
'paper', 'paper',
'bukkit', 'bukkit',
'sponge-11', // 'sponge-11',
// Proxy Plugins // Proxy Plugins
'velocity', 'velocity',
// Fabric Server-Side Mods // Fabric Server-Side Mods
'fabric-1.20.1', // 'fabric-1.20.1',
'fabric-1.21', // 'fabric-1.21',
// Example plugin // Example plugin
'example-plugin' 'example-plugin'

@ -24,6 +24,7 @@ package net.william278.uniform.velocity;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.permission.Tristate; import com.velocitypowered.api.permission.Tristate;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import lombok.Value;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.william278.uniform.CommandUser; import net.william278.uniform.CommandUser;
import net.william278.uniform.Permission; import net.william278.uniform.Permission;
@ -32,7 +33,10 @@ import org.jetbrains.annotations.Nullable;
import java.util.UUID; import java.util.UUID;
public record VelocityCommandUser(CommandSource source) implements CommandUser { @Value
public class VelocityCommandUser implements CommandUser {
CommandSource source;
@Override @Override
@NotNull @NotNull
@ -54,10 +58,10 @@ public record VelocityCommandUser(CommandSource source) implements CommandUser {
@Override @Override
public boolean checkPermission(@NotNull Permission permission) { public boolean checkPermission(@NotNull Permission permission) {
if (source.getPermissionValue(permission.node()) != Tristate.UNDEFINED) { if (source.getPermissionValue(permission.getNode()) != Tristate.UNDEFINED) {
return source.getPermissionValue(permission.node()) == Tristate.TRUE; return source.getPermissionValue(permission.getNode()) == Tristate.TRUE;
} }
return permission.defaultValue().check(source.hasPermission(permission.node())); return permission.getDefaultValue().check(source.hasPermission(permission.getNode()));
} }
} }

Loading…
Cancel
Save