feat: make x-plat command registering possible

dependabot/gradle/org.projectlombok-lombok-1.18.34
William 5 months ago
parent e5c8975339
commit 785b33e845
No known key found for this signature in database

@ -18,10 +18,10 @@ jobs:
steps:
- name: 'Checkout for CI 🛎️'
uses: actions/checkout@v4
- name: 'Set up JDK 17 📦'
- name: 'Set up JDK 21 📦'
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
- name: 'Build with Gradle 🏗️'
uses: gradle/gradle-build-action@v3

@ -15,10 +15,10 @@ jobs:
steps:
- name: 'Checkout for CI 🛎️'
uses: actions/checkout@v4
- name: 'Set up JDK 17 📦'
- name: 'Set up JDK 21 📦'
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
- name: 'Build with Gradle 🏗️'
uses: gradle/gradle-build-action@v3

@ -17,20 +17,71 @@
Uniform _currently_ targets the following platforms, (in addition to `uniform-common` which you can compile against in multi-platform plugins):
| Platform | Artifact | Version | Java |
|----------------|--------------------|------------|:-----:|
| Paper | `uniform-paper` | \>`1.20.4` | >`17` |
| Velocity | `uniform-velocity` | \>`3.3.0` | >`17` |
| Platform | Artifact | Minecraft | Java |
|---------------|-------------------------|:----------:|:-----:|
| Paper | `uniform-paper` | \>`1.20.4` | >`17` |
| Velocity | `uniform-velocity` | \>`3.3.0` | >`17` |
| Fabric 1.20.1 | `uniform-fabric-1.20.1` | =`1.20.1` | >`17` |
| Fabric 1.20.6 | `uniform-fabric-1.20.6` | =`1.20.6` | >`21` |
Uniform _plans_ to support the following platforms:
| Platform | Version | Java |
|----------------|------------|:-----:|
| Fabric | =`1.20.6` | >`21` |
| Spigot† | \>`1.17.1` | >`17` |
† Brigadier commands are wrapped into non-brigadier Bukkit plugin commands for legacy Spigot support.
## Using
### Platform-specific commands
Extend the platform-specific `PlatformCommand` class and implement the `execute` method.
```java
public class ExampleCommand extends PaperCommand {
public ExampleCommand() {
super("example", "platform-specific");
addSyntax((context) -> {
context.getSource().getBukkitSender().sendMessage("Woah!!!!");
String arg = context.getArgument("message", String.class);
context.getSource().getBukkitSender().sendMessage(MiniMessage.miniMessage().deserialize(arg));
}, stringArg("message"));
}
}
```
### Cross-platform commands
Target `uniform-common` and implement the `Command` class.
```java
public class ExampleCrossPlatCommand implements Command {
@Override
@NotNull
public String getNamespace() {
return "example";
}
@Override
@NotNull
public List<String> getAliases() {
return List.of("cross-plat");
}
@Override
public <S> void provide(@NotNull BaseCommand<S> command) {
command.setCondition(source -> true);
command.setDefaultExecutor((ctx) -> {
// Use command.getUser(ctx.getSource()) to get the user
final Audience user = command.getUser(ctx.getSource()).getAudience();
user.sendMessage(Component.text("Hello, world!"));
});
}
}
```
## Setup
Uniform is available [on Maven](https://repo.william278.net/#/releases/net/william278/uniform/). You can browse the Javadocs [here](https://repo.william278.net/javadoc/releases/net/william278/uniform/latest).

@ -59,6 +59,7 @@ allprojects {
mavenCentral()
maven { url 'https://repo.papermc.io/repository/maven-public/' }
maven { url 'https://libraries.minecraft.net/' }
maven { url 'https://maven.fabricmc.net/' }
}
dependencies {

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

@ -0,0 +1,157 @@
/*
* 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.arguments.*;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.tree.LiteralCommandNode;
import lombok.AccessLevel;
import lombok.Getter;
import net.william278.uniform.element.ArgumentElement;
import net.william278.uniform.element.CommandElement;
import net.william278.uniform.element.LiteralElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
@SuppressWarnings("unused")
public abstract class BaseCommand<S> {
@Getter
private final String name;
@Getter
private final String[] aliases;
public BaseCommand(@NotNull Command command) {
this.name = command.getNamespace();
this.aliases = command.getAliases().toArray(new String[0]);
command.provide(this);
}
public BaseCommand(@NotNull String name, @NotNull String... aliases) {
this.name = name;
this.aliases = aliases;
}
@Nullable
@Getter(AccessLevel.PACKAGE)
private Predicate<S> condition;
@Nullable
@Getter(AccessLevel.PACKAGE)
private CommandExecutor<S> defaultExecutor;
@Getter(AccessLevel.PACKAGE)
private final List<CommandSyntax<S>> syntaxes = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private final List<BaseCommand<S>> subCommands = new ArrayList<>();
@NotNull
protected abstract CommandUser getUser(@NotNull S user);
protected final void setCondition(@NotNull Predicate<S> condition) {
this.condition = condition;
}
protected final void setDefaultExecutor(@NotNull CommandExecutor<S> executor) {
this.defaultExecutor = executor;
}
@SafeVarargs
protected final void addConditionalSyntax(@Nullable Predicate<S> condition, @NotNull CommandExecutor<S> executor,
@NotNull CommandElement<S>... elements) {
var syntax = new CommandSyntax<>(condition, executor, List.of(elements));
this.syntaxes.add(syntax);
}
@SafeVarargs
protected final void addSyntax(@NotNull CommandExecutor<S> executor, @NotNull CommandElement<S>... elements) {
this.addConditionalSyntax(null, executor, elements);
}
protected final void addSubCommand(@NotNull BaseCommand<S> command) {
this.subCommands.add(command);
}
@NotNull
public final LiteralCommandNode<S> build() {
return Graph.create(this).build();
}
@NotNull
protected static <S> LiteralElement<S> literalArg(@NotNull String name) {
return new LiteralElement<>(name);
}
@NotNull
protected static <S> ArgumentElement<S, String> stringArg(@NotNull String name) {
return argument(name, StringArgumentType.string());
}
@NotNull
protected static <S> ArgumentElement<S, Integer> integerArg(@NotNull String name) {
return argument(name, IntegerArgumentType.integer());
}
@NotNull
protected static <S> ArgumentElement<S, Integer> integerArg(@NotNull String name, int min) {
return argument(name, IntegerArgumentType.integer(min));
}
@NotNull
protected static <S> ArgumentElement<S, Integer> integerArg(@NotNull String name, int min, int max) {
return argument(name, IntegerArgumentType.integer(min, max));
}
@NotNull
protected static <S> ArgumentElement<S, Float> floatArg(@NotNull String name) {
return argument(name, FloatArgumentType.floatArg());
}
@NotNull
protected static <S> ArgumentElement<S, Float> floatArg(@NotNull String name, float min) {
return argument(name, FloatArgumentType.floatArg(min));
}
@NotNull
protected static <S> ArgumentElement<S, Float> floatArg(@NotNull String name, float min, float max) {
return argument(name, FloatArgumentType.floatArg(min, max));
}
@NotNull
protected static <S> ArgumentElement<S, Boolean> booleanArg(@NotNull String name) {
return argument(name, BoolArgumentType.bool());
}
@NotNull
protected static <S, T> ArgumentElement<S, T> argument(@NotNull String name, @NotNull ArgumentType<T> type,
@Nullable SuggestionProvider<S> suggestionProvider) {
return new ArgumentElement<>(name, type, suggestionProvider);
}
@NotNull
protected static <S, T> ArgumentElement<S, T> argument(@NotNull String name, @NotNull ArgumentType<T> type) {
return argument(name, type, null);
}
}

@ -21,129 +21,18 @@
package net.william278.uniform;
import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.tree.LiteralCommandNode;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.william278.uniform.element.ArgumentElement;
import net.william278.uniform.element.CommandElement;
import net.william278.uniform.element.LiteralElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
@SuppressWarnings("unused")
@RequiredArgsConstructor
public abstract class Command<S> {
@Getter
private final String name;
@Getter
private final String[] aliases;
@Nullable
@Getter(AccessLevel.PACKAGE)
private Predicate<S> condition;
@Nullable
@Getter(AccessLevel.PACKAGE)
private CommandExecutor<S> defaultExecutor;
@Getter(AccessLevel.PACKAGE)
private final List<CommandSyntax<S>> syntaxes = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private final List<Command<S>> subCommands = new ArrayList<>();
public Command(@NotNull String name) {
this(name, new String[0]);
}
protected final void setCondition(@NotNull Predicate<S> condition) {
this.condition = condition;
}
protected final void setDefaultExecutor(@NotNull CommandExecutor<S> executor) {
this.defaultExecutor = executor;
}
@SafeVarargs
protected final void addConditionalSyntax(@Nullable Predicate<S> condition, @NotNull CommandExecutor<S> executor,
@NotNull CommandElement<S>... elements) {
var syntax = new CommandSyntax<>(condition, executor, List.of(elements));
this.syntaxes.add(syntax);
}
@SafeVarargs
protected final void addSyntax(@NotNull CommandExecutor<S> executor, @NotNull CommandElement<S>... elements) {
this.addConditionalSyntax(null, executor, elements);
}
protected final void addSubCommand(@NotNull Command<S> command) {
this.subCommands.add(command);
}
@NotNull
public final LiteralCommandNode<S> build() {
return Graph.create(this).build();
}
@NotNull
protected static <S> LiteralElement<S> literalArg(@NotNull String name) {
return new LiteralElement<>(name);
}
@NotNull
protected static <S> ArgumentElement<S, String> stringArg(@NotNull String name) {
return argument(name, StringArgumentType.string());
}
public interface Command {
@NotNull
protected static <S> ArgumentElement<S, Integer> integerArg(@NotNull String name) {
return argument(name, IntegerArgumentType.integer());
}
String getNamespace();
@NotNull
protected static <S> ArgumentElement<S, Integer> integerArg(@NotNull String name, int min) {
return argument(name, IntegerArgumentType.integer(min));
}
List<String> getAliases();
@NotNull
protected static <S> ArgumentElement<S, Integer> integerArg(@NotNull String name, int min, int max) {
return argument(name, IntegerArgumentType.integer(min, max));
}
@NotNull
protected static <S> ArgumentElement<S, Float> floatArg(@NotNull String name) {
return argument(name, FloatArgumentType.floatArg());
}
@NotNull
protected static <S> ArgumentElement<S, Float> floatArg(@NotNull String name, float min) {
return argument(name, FloatArgumentType.floatArg(min));
}
@NotNull
protected static <S> ArgumentElement<S, Float> floatArg(@NotNull String name, float min, float max) {
return argument(name, FloatArgumentType.floatArg(min, max));
}
@NotNull
protected static <S> ArgumentElement<S, Boolean> booleanArg(@NotNull String name) {
return argument(name, BoolArgumentType.bool());
}
@NotNull
protected static <S, T> ArgumentElement<S, T> argument(@NotNull String name, @NotNull ArgumentType<T> type,
@Nullable SuggestionProvider<S> suggestionProvider) {
return new ArgumentElement<>(name, type, suggestionProvider);
}
@NotNull
protected static <S, T> ArgumentElement<S, T> argument(@NotNull String name, @NotNull ArgumentType<T> type) {
return argument(name, type, null);
}
<S> void provide(@NotNull BaseCommand<S> command);
}
}

@ -0,0 +1,36 @@
/*
* 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 net.kyori.adventure.audience.Audience;
import java.util.UUID;
public interface CommandUser {
Audience getAudience();
String getName();
UUID getUniqueId();
}

@ -34,7 +34,7 @@ import static net.william278.uniform.Graph.commandToElement;
record ConversionNode<S>(@NotNull CommandElement<S> element, @Nullable Execution<S> execution,
@NotNull Map<CommandElement<S>, ConversionNode<S>> nextMap) {
static <S> @NotNull ConversionNode<S> fromCommand(@NotNull Command<S> command) {
static <S> @NotNull ConversionNode<S> fromCommand(@NotNull BaseCommand<S> command) {
ConversionNode<S> root = new ConversionNode<>(commandToElement(command), Execution.fromCommand(command));
for (CommandSyntax<S> syntax : command.getSyntaxes()) {
@ -49,7 +49,7 @@ record ConversionNode<S>(@NotNull CommandElement<S> element, @Nullable Execution
}
}
for (Command<S> subCommand : command.getSubCommands()) {
for (BaseCommand<S> subCommand : command.getSubCommands()) {
root.nextMap.put(commandToElement(subCommand), fromCommand(subCommand));
}

@ -35,7 +35,7 @@ record Execution<S>(@NotNull Predicate<S> predicate, @Nullable CommandExecutor<S
private static final Executor CACHED_EXECUTOR = Executors.newCachedThreadPool();
@NotNull
static <S> Execution<S> fromCommand(@NotNull Command<S> command) {
static <S> Execution<S> fromCommand(@NotNull BaseCommand<S> command) {
CommandExecutor<S> defaultExecutor = command.getDefaultExecutor();
Predicate<S> defaultCondition = command.getCondition();

@ -29,11 +29,11 @@ import org.jetbrains.annotations.NotNull;
record Graph<S>(@NotNull Node<S> root) {
static <S> @NotNull Graph<S> create(@NotNull Command<S> command) {
static <S> @NotNull Graph<S> create(@NotNull BaseCommand<S> command) {
return new Graph<>(Node.command(command));
}
static <S> @NotNull CommandElement<S> commandToElement(@NotNull Command<S> command) {
static <S> @NotNull CommandElement<S> commandToElement(@NotNull BaseCommand<S> command) {
return new LiteralElement<>(command.getName());
}

@ -31,7 +31,7 @@ import java.util.List;
record Node<S>(@NotNull CommandElement<S> element, @Nullable Execution<S> execution, @NotNull List<Node<S>> children) {
static <S> @NotNull Node<S> command(@NotNull Command<S> command) {
static <S> @NotNull Node<S> command(@NotNull BaseCommand<S> command) {
return ConversionNode.fromCommand(command).toNode();
}

@ -39,4 +39,5 @@ public record ArgumentElement<S, T>(@NotNull String name, @NotNull ArgumentType<
if (this.suggestionProvider != null) builder.suggests(this.suggestionProvider);
return builder;
}
}

@ -32,4 +32,5 @@ public record LiteralElement<S>(@NotNull String name) implements CommandElement<
public ArgumentBuilder<S, ?> toBuilder() {
return LiteralArgumentBuilder.literal(this.name);
}
}

@ -0,0 +1,53 @@
/*
* 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 net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ExampleCrossPlatCommand implements Command {
@Override
@NotNull
public String getNamespace() {
return "example";
}
@Override
@NotNull
public List<String> getAliases() {
return List.of("cross-plat");
}
@Override
public <S> void provide(@NotNull BaseCommand<S> command) {
command.setCondition(source -> true);
command.setDefaultExecutor((ctx) -> {
final Audience user = command.getUser(ctx.getSource()).getAudience();
user.sendMessage(Component.text("Hello, world!"));
});
}
}

@ -29,7 +29,9 @@ public class UniformExample extends JavaPlugin {
@Override
public void onEnable() {
PaperUniform.getInstance(this).register(new ExampleCommand());
PaperUniform uniform = PaperUniform.getInstance(this);
uniform.register(new ExampleCommand());
uniform.register(new ExampleCrossPlatCommand());
}
}

@ -0,0 +1,21 @@
plugins {
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'java-library'
id 'maven-publish'
}
dependencies {
api project(path: ':common')
minecraft 'com.mojang:minecraft:1.20.1'
mappings 'net.fabricmc:yarn:1.20.1+build.10:v2'
modCompileOnly 'net.fabricmc:fabric-loader:0.15.11'
modCompileOnly 'net.fabricmc.fabric-api:fabric-api:0.92.2+1.20.1'
modImplementation include('net.kyori:adventure-platform-fabric:5.9.0')
compileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}

@ -0,0 +1,81 @@
/*
* 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.fabric;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.Identifier;
import net.minecraft.util.InvalidIdentifierException;
import net.william278.uniform.BaseCommand;
import net.william278.uniform.Command;
import net.william278.uniform.CommandUser;
import net.william278.uniform.element.ArgumentElement;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class FabricCommand extends BaseCommand<ServerCommandSource> {
public FabricCommand(@NotNull Command command) {
super(command);
}
public FabricCommand(@NotNull String name, @NotNull String... aliases) {
super(name, aliases);
}
protected static ArgumentElement<ServerCommandSource, Item> itemArg(String name) {
return registryArg(name, Registries.ITEM);
}
protected static ArgumentElement<ServerCommandSource, Block> blockArg(String name) {
return registryArg(name, Registries.BLOCK);
}
protected static <T> ArgumentElement<ServerCommandSource, T> registryArg(String name, Registry<T> registry) {
return new ArgumentElement<>(name, reader -> {
String itemId = reader.readString();
final Identifier id;
try {
id = Identifier.tryParse(itemId);
} catch (InvalidIdentifierException e) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader);
}
if (registry.getOrEmpty(id).isEmpty()) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader);
}
return registry.get(id);
}, (context, builder) -> {
registry.getIds().forEach(id -> builder.suggest(id.toString()));
return builder.buildFuture();
});
}
@Override
@NotNull
protected CommandUser getUser(@NotNull ServerCommandSource user) {
return new FabricCommandUser(user);
}
}

@ -0,0 +1,51 @@
/*
* 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.fabric;
import net.kyori.adventure.audience.Audience;
import net.minecraft.server.command.ServerCommandSource;
import net.william278.uniform.CommandUser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public record FabricCommandUser(@NotNull ServerCommandSource source) implements CommandUser {
@Override
public Audience getAudience() {
return source.getPlayer();
}
@Override
@Nullable
public String getName() {
return source.getName();
}
@Override
@Nullable
public UUID getUniqueId() {
return source.getPlayer() != null ? source.getPlayer().getUuid() : null;
}
}

@ -0,0 +1,82 @@
/*
* 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.fabric;
import com.google.common.collect.Sets;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.william278.uniform.Command;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
/**
* A class for registering commands with the Fabric (1.20.1) server
*
* @since 1.0
*/
public final class FabricUniform {
private static FabricUniform INSTANCE;
private final Set<FabricCommand> commands = Sets.newHashSet();
private FabricUniform() {
CommandRegistrationCallback.EVENT.register((dispatcher, registry, environment) ->
commands.forEach(command -> dispatcher.register(command.build().createBuilder()))
);
}
/**
* Get the FabricUniform instance for registering commands
*
* @return The FabricUniform instance
* @since 1.0
*/
@NotNull
public static FabricUniform getInstance() {
return INSTANCE != null ? INSTANCE : (INSTANCE = new FabricUniform());
}
/**
* Register a command to be added to the server's command manager
*
* @param commands The commands to register
* @since 1.0
*/
public void register(@NotNull FabricCommand... commands) {
Collections.addAll(this.commands, commands);
}
/**
* Register a command to be added to the server's command manager
*
* @param commands The commands to register
* @since 1.0
*/
public void register(@NotNull Command... commands) {
register(Arrays.stream(commands).map(FabricCommand::new).toArray(FabricCommand[]::new));
}
}

@ -0,0 +1,21 @@
plugins {
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'java-library'
id 'maven-publish'
}
dependencies {
api project(path: ':common')
minecraft 'com.mojang:minecraft:1.20.6'
mappings 'net.fabricmc:yarn:1.20.6+build.3:v2'
modCompileOnly 'net.fabricmc:fabric-loader:0.15.11'
modCompileOnly 'net.fabricmc.fabric-api:fabric-api:0.100.0+1.20.6'
modImplementation include('net.kyori:adventure-platform-fabric:5.13.0')
compileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}

@ -0,0 +1,82 @@
/*
* 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.fabric;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.Identifier;
import net.minecraft.util.InvalidIdentifierException;
import net.william278.uniform.BaseCommand;
import net.william278.uniform.Command;
import net.william278.uniform.CommandUser;
import net.william278.uniform.element.ArgumentElement;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class FabricCommand extends BaseCommand<ServerCommandSource> {
public FabricCommand(@NotNull String name, @NotNull String... aliases) {
super(name, aliases);
}
public FabricCommand(@NotNull Command command) {
super(command);
}
protected static ArgumentElement<ServerCommandSource, Item> itemArg(String name) {
return registryArg(name, Registries.ITEM);
}
protected static ArgumentElement<ServerCommandSource, Block> blockArg(String name) {
return registryArg(name, Registries.BLOCK);
}
protected static <T> ArgumentElement<ServerCommandSource, T> registryArg(String name, Registry<T> registry) {
return new ArgumentElement<>(name, reader -> {
String itemId = reader.readString();
final Identifier id;
try {
id = Identifier.tryParse(itemId);
} catch (InvalidIdentifierException e) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader);
}
if (registry.getOrEmpty(id).isEmpty()) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader);
}
return registry.get(id);
}, (context, builder) -> {
registry.getIds().forEach(id -> builder.suggest(id.toString()));
return builder.buildFuture();
});
}
@Override
@NotNull
protected CommandUser getUser(@NotNull ServerCommandSource user) {
return new FabricCommandUser(user);
}
}

@ -0,0 +1,51 @@
/*
* 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.fabric;
import net.kyori.adventure.audience.Audience;
import net.minecraft.server.command.ServerCommandSource;
import net.william278.uniform.CommandUser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public record FabricCommandUser(@NotNull ServerCommandSource source) implements CommandUser {
@Override
public Audience getAudience() {
return source.getPlayer();
}
@Override
@Nullable
public String getName() {
return source.getName();
}
@Override
@Nullable
public UUID getUniqueId() {
return source.getPlayer() != null ? source.getPlayer().getUuid() : null;
}
}

@ -0,0 +1,82 @@
/*
* 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.fabric;
import com.google.common.collect.Sets;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.william278.uniform.Command;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
/**
* A class for registering commands with the Fabric (1.20.6) server
*
* @since 1.0
*/
public final class FabricUniform {
private static FabricUniform INSTANCE;
private final Set<FabricCommand> commands = Sets.newHashSet();
private FabricUniform() {
CommandRegistrationCallback.EVENT.register((dispatcher, registry, environment) ->
commands.forEach(command -> dispatcher.register(command.build().createBuilder()))
);
}
/**
* Get the FabricUniform instance for registering commands
*
* @return The FabricUniform instance
* @since 1.0
*/
@NotNull
public static FabricUniform getInstance() {
return INSTANCE != null ? INSTANCE : (INSTANCE = new FabricUniform());
}
/**
* Register a command to be added to the server's command manager
*
* @param commands The commands to register
* @since 1.0
*/
public void register(@NotNull FabricCommand... commands) {
Collections.addAll(this.commands, commands);
}
/**
* Register a command to be added to the server's command manager
*
* @param commands The commands to register
* @since 1.0
*/
public void register(@NotNull Command... commands) {
register(Arrays.stream(commands).map(FabricCommand::new).toArray(FabricCommand[]::new));
}
}

@ -23,7 +23,9 @@ package net.william278.uniform.paper;
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.william278.uniform.BaseCommand;
import net.william278.uniform.Command;
import net.william278.uniform.CommandUser;
import net.william278.uniform.element.ArgumentElement;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -34,7 +36,11 @@ import java.util.Collection;
import java.util.List;
@SuppressWarnings("unused")
public class PaperCommand extends Command<BukkitBrigadierCommandSource> {
public class PaperCommand extends BaseCommand<BukkitBrigadierCommandSource> {
public PaperCommand(@NotNull Command command) {
super(command);
}
public PaperCommand(@NotNull String name, @NotNull String... aliases) {
super(name, aliases);
@ -76,4 +82,10 @@ public class PaperCommand extends Command<BukkitBrigadierCommandSource> {
});
}
@Override
@NotNull
protected CommandUser getUser(@NotNull BukkitBrigadierCommandSource user) {
return new PaperCommandUser(user);
}
}

@ -0,0 +1,51 @@
/*
* 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.paper;
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
import net.kyori.adventure.audience.Audience;
import net.william278.uniform.CommandUser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public record PaperCommandUser(@NotNull BukkitBrigadierCommandSource source) implements CommandUser {
@Override
public Audience getAudience() {
return source.getBukkitSender();
}
@Override
@Nullable
public String getName() {
return source.getBukkitEntity() != null ? source.getBukkitSender().getName() : null;
}
@Override
@Nullable
public UUID getUniqueId() {
return source.getBukkitEntity() != null ? source.getBukkitEntity().getUniqueId() : null;
}
}

@ -23,11 +23,13 @@ package net.william278.uniform.paper;
import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent;
import com.google.common.collect.Sets;
import net.william278.uniform.Command;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
@ -78,4 +80,14 @@ public final class PaperUniform implements Listener {
Collections.addAll(this.commands, commands);
}
/**
* Register command(s) to be added to the server's command manager
*
* @param commands The commands to register
* @since 1.0
*/
public void register(@NotNull Command... commands) {
register(Arrays.stream(commands).map(PaperCommand::new).toArray(PaperCommand[]::new));
}
}

@ -1,14 +1,24 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url 'https://maven.fabricmc.net/' }
}
}
rootProject.name = 'Uniform'
include(
'common',
// Server Plugins
'paper',
// Proxy Plugins
'velocity',
// Fabric Server-Side Mods
'fabric-1.20.1',
'fabric-1.20.6',
// Example plugin
'example-plugin'
)

@ -28,12 +28,18 @@ import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.william278.uniform.BaseCommand;
import net.william278.uniform.Command;
import net.william278.uniform.CommandUser;
import net.william278.uniform.element.ArgumentElement;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class VelocityCommand extends Command<CommandSource> {
public class VelocityCommand extends BaseCommand<CommandSource> {
public VelocityCommand(@NotNull Command command) {
super(command);
}
public VelocityCommand(@NotNull String name, @NotNull String... aliases) {
super(name, aliases);
@ -83,4 +89,9 @@ public class VelocityCommand extends Command<CommandSource> {
});
}
@Override
@NotNull
protected CommandUser getUser(@NotNull CommandSource user) {
return new VelocityCommandUser(user);
}
}

@ -0,0 +1,51 @@
/*
* 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.velocity;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.audience.Audience;
import net.william278.uniform.CommandUser;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public record VelocityCommandUser(CommandSource source) implements CommandUser {
@Override
public Audience getAudience() {
return source;
}
@Override
@Nullable
public String getName() {
return source instanceof Player ? ((Player) source).getUsername() : null;
}
@Override
@Nullable
public UUID getUniqueId() {
return source instanceof Player ? ((Player) source).getUniqueId() : null;
}
}

@ -23,6 +23,7 @@ package net.william278.uniform.velocity;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.proxy.ProxyServer;
import net.william278.uniform.Command;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@ -56,7 +57,7 @@ public final class VelocityUniform {
}
/**
* Register one or more commands with the server's command manager
* Register a command with the server's command manager
*
* @param commands The commands to register
* @since 1.0
@ -65,4 +66,14 @@ public final class VelocityUniform {
Arrays.stream(commands).forEach(cmd -> server.getCommandManager().register(new BrigadierCommand(cmd.build())));
}
/**
* Register a command with the server's command manager
*
* @param commands The commands to register
* @since 1.0
*/
public void register(@NotNull Command... commands) {
register(Arrays.stream(commands).map(VelocityCommand::new).toArray(VelocityCommand[]::new));
}
}

Loading…
Cancel
Save