refactor: redo layout, registration structure

dependabot/gradle/org.projectlombok-lombok-1.18.34
William 5 months ago
parent 712949d4f7
commit 8f4e952337
No known key found for this signature in database

16
.gitignore vendored

@ -1,18 +1,18 @@
.gradle
### Build/run paths ###
build/
run/
target/
### Gradle ###
.gradle
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
.idea/
out/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

8
.idea/.gitignore vendored

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/example-plugin" />
<option value="$PROJECT_DIR$/paper" />
<option value="$PROJECT_DIR$/velocity" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -0,0 +1,18 @@
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/>.

@ -1,2 +1,2 @@
# BrigadierWrapper
A brigadier wrapper for paper and velocity inspired by emortalmcs command system
# Uniform
A cross-platform wrapper for making Brigadier commands, based on BrigadierWrapper by Tofaa2, itself inspired by emortalmcs command system.

@ -1,19 +1,178 @@
import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id 'org.cadixdev.licenser' version '0.6.1' apply false
id 'io.github.goooler.shadow' version '8.1.7'
id 'org.ajoberstar.grgit' version '5.2.2'
id 'maven-publish'
id 'java'
id 'java-library'
}
group = 'me.tofaa'
version = '1.0-SNAPSHOT'
group 'net.william278'
version "$ext.library_version${versionMetadata()}"
description "$ext.library_description"
defaultTasks 'licenseFormat', 'build'
publishing {
repositories {
mavenCentral()
if (System.getenv("RELEASES_MAVEN_USERNAME") != null) {
maven {
name = "william278-releases"
url = "https://repo.william278.net/releases"
credentials {
username = System.getenv("RELEASES_MAVEN_USERNAME")
password = System.getenv("RELEASES_MAVEN_PASSWORD")
}
authentication {
basic(BasicAuthentication)
}
}
}
if (System.getenv("SNAPSHOTS_MAVEN_USERNAME") != null) {
maven {
url = "https://libraries.minecraft.net/"
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)
}
}
}
}
}
allprojects {
apply plugin: 'io.github.goooler.shadow'
apply plugin: 'org.cadixdev.licenser'
apply plugin: 'java'
compileJava.options.encoding = 'UTF-8'
compileJava.options.release.set 17
javadoc.options.encoding = 'UTF-8'
javadoc.options.addStringOption('Xdoclint:none', '-quiet')
repositories {
mavenLocal()
mavenCentral()
maven { url 'https://repo.papermc.io/repository/maven-public/' }
maven { url 'https://libraries.minecraft.net/' }
}
dependencies {
compileOnlyApi("com.mojang:brigadier:1.1.8")
compileOnlyApi("org.jetbrains:annotations:24.0.0")
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.2'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.2'
}
test {
useJUnitPlatform()
}
license {
header = rootProject.file('HEADER')
include '**/*.java'
newLine = true
}
processResources {
filesMatching(['**/*.json', '**/*.yml']) {
filter ReplaceTokens as Class, beginToken: '${', endToken: '}',
tokens: rootProject.ext.properties
}
}
}
subprojects {
version rootProject.version
archivesBaseName = "${rootProject.name}-${project.name.capitalize()}"
jar {
from '../LICENSE'
}
shadowJar {
destinationDirectory.set(file("$rootDir/target"))
archiveClassifier.set('')
}
// Don't include example plugin in publishing
if (['example-plugin'].contains(project.name)) return;
// API publishing
java {
withSourcesJar()
withJavadocJar()
}
sourcesJar {
destinationDirectory.set(file("$rootDir/target"))
}
javadocJar {
destinationDirectory.set(file("$rootDir/target"))
}
shadowJar.dependsOn(sourcesJar, javadocJar)
publishing {
if (['common'].contains(project.name)) {
publications {
mavenJavaCommon(MavenPublication) {
groupId = 'net.william278.uniform'
artifactId = 'uniform-common'
version = "$rootProject.version"
artifact shadowJar
artifact sourcesJar
artifact javadocJar
}
}
}
if (['paper'].contains(project.name)) {
publications {
mavenJavaBukkit(MavenPublication) {
groupId = 'net.william278.uniform'
artifactId = 'uniform-paper'
version = "$rootProject.version"
artifact shadowJar
artifact sourcesJar
artifact javadocJar
}
}
}
if (['velocity'].contains(project.name)) {
publications {
mavenJavaBukkit(MavenPublication) {
groupId = 'net.william278.uniform'
artifactId = 'uniform-velocity'
version = "$rootProject.version"
artifact shadowJar
artifact sourcesJar
artifact javadocJar
}
}
}
}
jar.dependsOn shadowJar
clean.delete "$rootDir/target"
}
logger.lifecycle("Building Uniform ${version} by William278")
@SuppressWarnings('GrMethodMayBeStatic')
def versionMetadata() {
// Get if there is a tag for this commit
def tag = grgit.tag.list().find { it.commit.id == grgit.head().id }
if (tag != null) {
return ''
}
// Otherwise, get the last commit hash and if it's a clean head
if (grgit == null) {
return '-' + System.getenv("GITHUB_RUN_NUMBER") ? 'build.' + System.getenv("GITHUB_RUN_NUMBER") : 'unknown'
}
return '-' + grgit.head().abbreviatedId + (grgit.status().clean ? '' : '-indev')
}

@ -0,0 +1,13 @@
plugins {
id 'java-library'
id 'maven-publish'
}
dependencies {
compileOnlyApi 'com.mojang:brigadier:1.1.8'
compileOnly 'org.jetbrains:annotations:24.1.0'
compileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}

@ -1,11 +1,32 @@
package me.tofaa.brigadierwrapper;
/*
* 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 me.tofaa.brigadierwrapper.element.ArgumentElement;
import me.tofaa.brigadierwrapper.element.CommandElement;
import me.tofaa.brigadierwrapper.element.LiteralElement;
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;
@ -14,6 +35,7 @@ import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
@SuppressWarnings("unused")
public abstract class Command<S> {
private final String name;
@ -122,7 +144,8 @@ public abstract class Command<S> {
return argument(name, BoolArgumentType.bool());
}
protected static <S, T> @NotNull ArgumentElement<S, T> argument(@NotNull String name, @NotNull ArgumentType<T> type, @Nullable SuggestionProvider<S> suggestionProvider) {
protected static <S, T> @NotNull ArgumentElement<S, T> argument(@NotNull String name, @NotNull ArgumentType<T> type,
@Nullable SuggestionProvider<S> suggestionProvider) {
return new ArgumentElement<>(name, type, suggestionProvider);
}

@ -0,0 +1,30 @@
/*
* 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.context.CommandContext;
import org.jetbrains.annotations.NotNull;
public interface CommandExecutor<S> {
void execute(@NotNull CommandContext<S> context);
}

@ -0,0 +1,32 @@
/*
* 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.william278.uniform.element.CommandElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.function.Predicate;
public record CommandSyntax<S>(@Nullable Predicate<S> condition, @NotNull CommandExecutor<S> executor, @NotNull List<CommandElement<S>> elements) {
}

@ -1,6 +1,27 @@
package me.tofaa.brigadierwrapper;
/*
* 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/>.
*/
import me.tofaa.brigadierwrapper.element.CommandElement;
package net.william278.uniform;
import net.william278.uniform.element.CommandElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -8,7 +29,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static me.tofaa.brigadierwrapper.Graph.commandToElement;
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) {

@ -1,4 +1,25 @@
package me.tofaa.brigadierwrapper;
/*
* 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.builder.ArgumentBuilder;

@ -0,0 +1,48 @@
/*
* 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.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.william278.uniform.element.CommandElement;
import net.william278.uniform.element.LiteralElement;
import org.jetbrains.annotations.NotNull;
record Graph<S>(@NotNull Node<S> root) {
static <S> @NotNull Graph<S> create(@NotNull Command<S> command) {
return new Graph<>(Node.command(command));
}
static <S> @NotNull CommandElement<S> commandToElement(@NotNull Command<S> command) {
return new LiteralElement<>(command.getName());
}
@NotNull LiteralCommandNode<S> build() {
CommandNode<S> node = this.root.build();
if (!(node instanceof LiteralCommandNode<S> literalNode)) {
throw new IllegalStateException("Root node is somehow not a literal node. This should be impossible.");
}
return literalNode;
}
}

@ -0,0 +1,49 @@
/*
* 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.builder.ArgumentBuilder;
import com.mojang.brigadier.tree.CommandNode;
import net.william278.uniform.element.CommandElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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) {
return ConversionNode.fromCommand(command).toNode();
}
@NotNull
CommandNode<S> build() {
ArgumentBuilder<S, ?> builder = this.element.toBuilder();
if (this.execution != null) this.execution.addToBuilder(builder);
for (Node<S> child : this.children) {
builder.then(child.build());
}
return builder.build();
}
}

@ -0,0 +1,41 @@
/*
* 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.element;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record ArgumentElement<S, T>(@NotNull String name, @NotNull ArgumentType<T> type,
@Nullable SuggestionProvider<S> suggestionProvider) implements CommandElement<S> {
@Override
public @NotNull ArgumentBuilder<S, ?> toBuilder() {
var builder = RequiredArgumentBuilder.<S, T>argument(this.name, this.type);
if (this.suggestionProvider != null) builder.suggests(this.suggestionProvider);
return builder;
}
}

@ -0,0 +1,30 @@
/*
* 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.element;
import com.mojang.brigadier.builder.ArgumentBuilder;
import org.jetbrains.annotations.NotNull;
public interface CommandElement<S> {
@NotNull ArgumentBuilder<S, ?> toBuilder();
}

@ -0,0 +1,34 @@
/*
* 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.element;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import org.jetbrains.annotations.NotNull;
public record LiteralElement<S>(@NotNull String name) implements CommandElement<S> {
@Override
public @NotNull ArgumentBuilder<S, ?> toBuilder() {
return LiteralArgumentBuilder.literal(this.name);
}
}

@ -1,24 +1,13 @@
plugins {
id 'java'
id 'xyz.jpenilla.run-paper' version '2.2.2'
id 'com.github.johnrengelman.shadow' version '7.0.0'
}
group = 'me.tofaa'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven {
url = "https://repo.papermc.io/repository/maven-public/"
}
id 'xyz.jpenilla.run-paper' version '2.3.0'
}
dependencies {
implementation(project(":paper"))
compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT")
}
compileOnly 'io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT'
}
tasks {
runServer {

@ -1,17 +0,0 @@
package me.tofaa;
import me.tofaa.brigadierwrapper.paper.PaperCommand;
import net.kyori.adventure.text.minimessage.MiniMessage;
public class ExampleCommand extends PaperCommand {
public ExampleCommand() {
super("example", "silly-command");
addSyntax((context) -> {
context.getSource().getBukkitSender().sendMessage("Woah!!!!");
String arg = context.getArgument("message", String.class);
context.getSource().getBukkitSender().sendMessage(MiniMessage.miniMessage().deserialize(arg));
}, stringArg("message"));
}
}

@ -1,14 +0,0 @@
package me.tofaa;
import me.tofaa.brigadierwrapper.paper.PaperBrigadierWrapper;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin {
@Override
public void onEnable() {
PaperBrigadierWrapper.init(this);
PaperBrigadierWrapper.register(new ExampleCommand());
}
}

@ -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;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.william278.uniform.paper.PaperCommand;
public class ExampleCommand extends PaperCommand {
public ExampleCommand() {
super("example", "silly-command");
addSyntax((context) -> {
context.getSource().getBukkitSender().sendMessage("Woah!!!!");
String arg = context.getArgument("message", String.class);
context.getSource().getBukkitSender().sendMessage(MiniMessage.miniMessage().deserialize(arg));
}, stringArg("message"));
}
}

@ -0,0 +1,35 @@
/*
* 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.william278.uniform.paper.PaperUniform;
import org.bukkit.plugin.java.JavaPlugin;
@SuppressWarnings("unused")
public class UniformExample extends JavaPlugin {
@Override
public void onEnable() {
PaperUniform.getInstance(this).register(new ExampleCommand());
}
}

@ -1,4 +1,4 @@
name: ExamplePlugin
name: UniformExample
version: 1.0
api-version: "1.20"
main: me.tofaa.Main
main: net.william278.uniform.UniformExample

@ -0,0 +1,8 @@
javaVersion=17
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.daemon=true
library_version=1.0
library_archive=uniform
library_description=Cross-platform wrapper for making Brigadier commands, based on BrigadierWrapper by Tofaa2, itself inspired by emortalmcs command system.

Binary file not shown.

@ -1,6 +1,7 @@
#Tue May 07 18:37:10 AZT 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

41
gradlew vendored

@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -80,13 +80,11 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@ -133,22 +131,29 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
@ -205,6 +214,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

11
gradlew.bat vendored

@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal

@ -1,20 +1,15 @@
plugins {
id 'java'
id 'java-library'
id 'maven-publish'
}
group = 'me.tofaa'
version = '1.0-SNAPSHOT'
dependencies {
api project(path: ':common')
repositories {
mavenCentral()
maven {
url = "https://repo.papermc.io/repository/maven-public/"
}
}
compileOnlyApi 'io.papermc.paper:paper-mojangapi:1.20.4-R0.1-SNAPSHOT'
dependencies {
api(project(":"))
compileOnlyApi("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT")
compileOnlyApi("io.papermc.paper:paper-mojangapi:1.20.4-R0.1-SNAPSHOT")
compileOnly 'io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT'
compileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}

@ -1,38 +0,0 @@
package me.tofaa.brigadierwrapper.paper;
import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public final class PaperBrigadierWrapper {
private PaperBrigadierWrapper() {}
private static final Set<PaperCommand> COMMANDS = new HashSet<>();
public static void register(PaperCommand... commands) {
Collections.addAll(COMMANDS, commands);
}
public static void init(
@NotNull JavaPlugin plugin
) {
Bukkit.getServer().getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onCmd(CommandRegisteredEvent event) {
for (PaperCommand command : COMMANDS) {
event.getRoot().addChild(command.build());
COMMANDS.remove(command);
}
}
}, plugin);
}
}

@ -1,11 +1,30 @@
package me.tofaa.brigadierwrapper.paper;
/*
* 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 com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.tofaa.brigadierwrapper.Command;
import me.tofaa.brigadierwrapper.element.ArgumentElement;
import net.william278.uniform.Command;
import net.william278.uniform.element.ArgumentElement;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@ -14,6 +33,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.List;
@SuppressWarnings("unused")
public class PaperCommand extends Command<BukkitBrigadierCommandSource> {
public PaperCommand(@NotNull String name, @NotNull String... aliases) {

@ -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.paper;
import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent;
import com.google.common.collect.Sets;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Set;
/**
* A class for registering commands with the Paper server's command manager
*
* @since 1.0
*/
@SuppressWarnings("UnstableApiUsage")
public final class PaperUniform implements Listener {
private static PaperUniform INSTANCE;
private final Set<PaperCommand> commands = Sets.newHashSet();
private PaperUniform(@NotNull JavaPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
@SuppressWarnings({"rawtypes", "unchecked"})
private void onCommandRegistered(@NotNull CommandRegisteredEvent event) {
for (PaperCommand command : commands) {
event.getRoot().addChild(command.build());
commands.remove(command);
}
}
/**
* Get the PaperUniform instance for registering commands
*
* @param plugin The plugin instance
* @return The PaperUniform instance
* @since 1.0
*/
@NotNull
public static PaperUniform getInstance(@NotNull JavaPlugin plugin) {
return INSTANCE != null ? INSTANCE : (INSTANCE = new PaperUniform(plugin));
}
/**
* 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 PaperCommand... commands) {
Collections.addAll(this.commands, commands);
}
}

@ -1,5 +1,14 @@
rootProject.name = 'BrigadierWrapper'
include 'paper'
include 'velocity'
include 'example-plugin'
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = 'Uniform'
include(
'common',
'paper',
'velocity',
'example-plugin'
)

@ -1,9 +0,0 @@
package me.tofaa.brigadierwrapper;
import com.mojang.brigadier.context.CommandContext;
import org.jetbrains.annotations.NotNull;
public interface CommandExecutor<S> {
void execute(@NotNull CommandContext<S> context);
}

@ -1,11 +0,0 @@
package me.tofaa.brigadierwrapper;
import me.tofaa.brigadierwrapper.element.CommandElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.function.Predicate;
public record CommandSyntax<S>(@Nullable Predicate<S> condition, @NotNull CommandExecutor<S> executor, @NotNull List<CommandElement<S>> elements) {
}

@ -1,27 +0,0 @@
package me.tofaa.brigadierwrapper;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import me.tofaa.brigadierwrapper.element.CommandElement;
import me.tofaa.brigadierwrapper.element.LiteralElement;
import org.jetbrains.annotations.NotNull;
record Graph<S>(@NotNull Node<S> root) {
static <S> @NotNull Graph<S> create(@NotNull Command<S> command) {
return new Graph<>(Node.command(command));
}
static <S> @NotNull CommandElement<S> commandToElement(@NotNull Command<S> command) {
return new LiteralElement<>(command.getName());
}
@NotNull LiteralCommandNode<S> build() {
CommandNode<S> node = this.root.build();
if (!(node instanceof LiteralCommandNode<S> literalNode)) {
throw new IllegalStateException("Root node is somehow not a literal node. This should be impossible.");
}
return literalNode;
}
}

@ -1,28 +0,0 @@
package me.tofaa.brigadierwrapper;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.tree.CommandNode;
import me.tofaa.brigadierwrapper.element.CommandElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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) {
return ConversionNode.fromCommand(command).toNode();
}
@NotNull
CommandNode<S> build() {
ArgumentBuilder<S, ?> builder = this.element.toBuilder();
if (this.execution != null) this.execution.addToBuilder(builder);
for (Node<S> child : this.children) {
builder.then(child.build());
}
return builder.build();
}
}

@ -1,20 +0,0 @@
package me.tofaa.brigadierwrapper.element;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record ArgumentElement<S, T>(@NotNull String name, @NotNull ArgumentType<T> type,
@Nullable SuggestionProvider<S> suggestionProvider) implements CommandElement<S> {
@Override
public @NotNull ArgumentBuilder<S, ?> toBuilder() {
var builder = RequiredArgumentBuilder.<S, T>argument(this.name, this.type);
if (this.suggestionProvider != null) builder.suggests(this.suggestionProvider);
return builder;
}
}

@ -1,9 +0,0 @@
package me.tofaa.brigadierwrapper.element;
import com.mojang.brigadier.builder.ArgumentBuilder;
import org.jetbrains.annotations.NotNull;
public interface CommandElement<S> {
@NotNull ArgumentBuilder<S, ?> toBuilder();
}

@ -1,13 +0,0 @@
package me.tofaa.brigadierwrapper.element;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import org.jetbrains.annotations.NotNull;
public record LiteralElement<S>(@NotNull String name) implements CommandElement<S> {
@Override
public @NotNull ArgumentBuilder<S, ?> toBuilder() {
return LiteralArgumentBuilder.literal(this.name);
}
}

@ -1,19 +1,13 @@
plugins {
id 'java'
id 'java-library'
id 'maven-publish'
}
group = 'me.tofaa'
version = '1.0-SNAPSHOT'
dependencies {
api project(path: ':common')
repositories {
mavenCentral()
maven {
url = "https://repo.papermc.io/repository/maven-public/"
}
}
compileOnly 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT'
compileOnly 'org.projectlombok:lombok:1.18.32'
dependencies {
compileOnly("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
api(project(":"))
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}

@ -1,19 +0,0 @@
package me.tofaa.brigadierwrapper.velocity;
import com.velocitypowered.api.command.BrigadierCommand;
import com.velocitypowered.api.proxy.ProxyServer;
public final class VelocityBrigadierWrapper {
private VelocityBrigadierWrapper() {}
public static void registerCommands(
ProxyServer server,
VelocityCommand... commands
) {
for (VelocityCommand command : commands) {
server.getCommandManager().register(new BrigadierCommand(command.build()));
}
}
}

@ -1,4 +1,25 @@
package me.tofaa.brigadierwrapper.velocity;
/*
* 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.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -7,17 +28,19 @@ 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 me.tofaa.brigadierwrapper.Command;
import me.tofaa.brigadierwrapper.element.ArgumentElement;
import net.william278.uniform.Command;
import net.william278.uniform.element.ArgumentElement;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class VelocityCommand extends Command<CommandSource> {
public VelocityCommand(@NotNull String name, @NotNull String... aliases) {
super(name, aliases);
}
protected static ArgumentElement<CommandSource, RegisteredServer> serverArg(ProxyServer server, String name, SuggestionProvider<CommandSource> suggestionProvider) {
protected static ArgumentElement<CommandSource, RegisteredServer> serverArg(ProxyServer server, String name,
SuggestionProvider<CommandSource> suggestionProvider) {
ArgumentType<RegisteredServer> argumentType = reader -> {
String s = reader.readUnquotedString();
RegisteredServer server1 = server.getServer(s).orElse(null);
@ -38,7 +61,8 @@ public class VelocityCommand extends Command<CommandSource> {
});
}
protected static ArgumentElement<CommandSource, CommandSource> sourceArg(ProxyServer server, String name, SuggestionProvider<CommandSource> suggestionProvider) {
protected static ArgumentElement<CommandSource, CommandSource> sourceArg(ProxyServer server, String name,
SuggestionProvider<CommandSource> suggestionProvider) {
ArgumentType<CommandSource> argumentType = reader -> {
String s = reader.readUnquotedString();
CommandSource source = server.getPlayer(s).orElse(null);
@ -58,4 +82,5 @@ public class VelocityCommand extends Command<CommandSource> {
return builder.buildFuture();
});
}
}

@ -0,0 +1,68 @@
/*
* 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.BrigadierCommand;
import com.velocitypowered.api.proxy.ProxyServer;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
/**
* A class for registering commands with the Velocity server's command manager
*
* @since 1.0
*/
@SuppressWarnings("unused")
public final class VelocityUniform {
private static VelocityUniform INSTANCE;
private final ProxyServer server;
private VelocityUniform(@NotNull ProxyServer server) {
this.server = server;
}
/**
* Get the VelocityUniform instance for registering commands
*
* @param server The server instance
* @return The VelocityUniform instance
* @since 1.0
*/
@NotNull
public static VelocityUniform getInstance(@NotNull ProxyServer server) {
return INSTANCE != null ? INSTANCE : (INSTANCE = new VelocityUniform(server));
}
/**
* Register one or more commands with the server's command manager
*
* @param commands The commands to register
* @since 1.0
*/
public void register(@NotNull VelocityCommand... commands) {
Arrays.stream(commands).forEach(cmd -> server.getCommandManager().register(new BrigadierCommand(cmd.build())));
}
}
Loading…
Cancel
Save