diff --git a/README.md b/README.md
index 31180ee..cca89b0 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
Versions are available on maven in the format `net.william278.uniform:ARTIFACT:VERSION`. See below for a table of supported platforms.
-Note that Uniform versions omit the `v` prefix. Fabric versions are suffixed with the target Minecraft version (e.g. `1.1.9+1.21`) and also require Fabric API installed on the server.
+Note that Uniform versions omit the `v` prefix. Fabric versions are suffixed with the target Minecraft version (e.g. `1.1.10+1.21`) and also require Fabric API installed on the server. Sponge versions are suffixed with the target Sponge API version (e.g. `1.1.10+11`).
@@ -29,7 +29,7 @@ Note that Uniform versions omit the `v` prefix. Fabric versions are suffixed wit
Platform
Artifact
-
Platform ver.
+
Minecraft ver.
Java ver.
Uniform ver.
@@ -46,45 +46,50 @@ Note that Uniform versions omit the `v` prefix. Fabric versions are suffixed wit
Supported Platforms
-
Bukkit/Spigot
+
Bukkit / Spigot
uniform-bukkit
-
≥mc 1.17.1
+
≥1.17.1
≥17
-
+
Paper
uniform-paper
-
≥mc 1.17.1
-
Velocity
+
Velocity (3.3.0)
uniform-velocity
-
≥3.3.0
+
≥1.8.9
-
Fabric
+
Sponge (api 11)
+
uniform-sponge
+
=1.20.6
+
≥21
+
+
+
Fabric (1.20.1)
uniform-fabric
-
=mc 1.20.1
-
≥21
+
=1.20.1
-
=mc 1.21
+
Fabric (1.21)
+
=1.21
Formerly Supported Platforms
-
Fabric
+
Fabric (1.20.6)
uniform-fabric
-
=mc 1.20.6
+
=1.20.6
≥21
v1.1.8
-Example: To target Uniform on Bukkit, the artifact is `net.william278.uniform:uniform-bukkit:1.1.9` (check that this version is up-to-date – make sure you target the latest available!).
+Example: To target Uniform on Bukkit, the artifact is `net.william278.uniform:uniform-bukkit:1.1.10` (check that this version is up-to-date – make sure you target the latest available!).
## 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).
@@ -99,7 +104,7 @@ repositories {
}
```
-Then, add the dependency itself. Replace `VERSION` with the latest release version. (e.g., `1.0`) and `PLATFORM` with the platform you are targeting (e.g., `paper`). If you want to target pre-release "snapshot" versions (not recommended), you should use the `/snapshots` repository instead.
+Then, add the dependency itself. Replace `VERSION` with the latest release version. (e.g., `1.1.10`) and `PLATFORM` with the platform you are targeting (e.g., `paper`). If you want to target pre-release "snapshot" versions (not recommended), you should use the `/snapshots` repository instead.
```groovy
dependencies {
diff --git a/build.gradle b/build.gradle
index 3bf961d..e2b6981 100644
--- a/build.gradle
+++ b/build.gradle
@@ -209,6 +209,19 @@ subprojects {
}
}
+ if (['sponge-11'].contains(project.name)) {
+ publications {
+ mavenSponge11(MavenPublication) {
+ groupId = 'net.william278.uniform'
+ artifactId = 'uniform-sponge'
+ version = "${rootProject.version}+11"
+ artifact shadowJar
+ artifact sourcesJar
+ artifact javadocJar
+ }
+ }
+ }
+
}
jar.dependsOn shadowJar
diff --git a/settings.gradle b/settings.gradle
index 0aef91d..6196c78 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -12,6 +12,7 @@ include(
// Server Plugins
'paper',
'bukkit',
+ 'sponge-11',
// Proxy Plugins
'velocity',
diff --git a/sponge-11/build.gradle b/sponge-11/build.gradle
new file mode 100644
index 0000000..45aa20a
--- /dev/null
+++ b/sponge-11/build.gradle
@@ -0,0 +1,13 @@
+plugins {
+ id 'java-library'
+ id 'maven-publish'
+}
+
+dependencies {
+ implementation project(path: ':common')
+
+ compileOnly 'org.spongepowered:spongeapi:11.0.0'
+ compileOnly 'org.projectlombok:lombok:1.18.32'
+
+ annotationProcessor 'org.projectlombok:lombok:1.18.32'
+}
diff --git a/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeCommand.java b/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeCommand.java
new file mode 100644
index 0000000..54ff176
--- /dev/null
+++ b/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeCommand.java
@@ -0,0 +1,146 @@
+/*
+ * This file is part of Uniform, licensed under the GNU General Public License v3.0.
+ *
+ * Copyright (c) Tofaa2
+ * Copyright (c) William278
+ * 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 .
+ */
+
+package net.william278.uniform.sponge;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.william278.uniform.BaseCommand;
+import net.william278.uniform.Command;
+import net.william278.uniform.Permission;
+import net.william278.uniform.Uniform;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.spongepowered.api.Game;
+import org.spongepowered.api.command.Command.Raw;
+import org.spongepowered.api.command.CommandCause;
+import org.spongepowered.api.command.CommandCompletion;
+import org.spongepowered.api.command.CommandResult;
+import org.spongepowered.api.command.exception.CommandException;
+import org.spongepowered.api.command.parameter.ArgumentReader;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@SuppressWarnings("unused")
+public class SpongeCommand extends BaseCommand {
+
+ private @Nullable Permission permission;
+
+ public SpongeCommand(@NotNull Command command) {
+ super(command);
+ this.permission = command.getPermission().orElse(null);
+ }
+
+ public SpongeCommand(@NotNull String name, @NotNull String description, @NotNull List aliases) {
+ super(name, description, aliases);
+ }
+
+ public SpongeCommand(@NotNull String name, @NotNull List aliases) {
+ super(name, aliases);
+ }
+
+ @NotNull
+ Impl getImpl() {
+ return new Impl(this);
+ }
+
+ static final class Impl implements Raw {
+
+ private static final int COMMAND_SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS;
+ private final CommandDispatcher dispatcher = new CommandDispatcher<>();
+ private final SpongeCommand command;
+ private final @Nullable Permission permission;
+
+ public Impl(@NotNull SpongeCommand command) {
+ this.dispatcher.register(command.createBuilder());
+ this.command = command;
+ this.permission = command.permission;
+ }
+
+ @Override
+ public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) throws CommandException {
+ try {
+ return dispatcher.execute(arguments.immutable().remaining(), cause) == COMMAND_SUCCESS
+ ? CommandResult.success()
+ : CommandResult.error(Component.translatable("command.failed", NamedTextColor.RED));
+ } catch (CommandSyntaxException e) {
+ throw new CommandException(Component
+ .translatable("command.context.parse_error", NamedTextColor.RED).arguments(
+ Component.text(e.getRawMessage().getString()),
+ Component.text(e.getCursor()),
+ Component.text(e.getContext())
+ ), e, true);
+ }
+ }
+
+ @Override
+ public List complete(CommandCause cause, ArgumentReader.Mutable arguments) throws CommandException {
+ return dispatcher.getCompletionSuggestions(
+ dispatcher.parse(arguments.remaining(), cause),
+ arguments.cursor()
+ )
+ .thenApply(suggestions -> suggestions.getList().stream().map(s -> CommandCompletion.of(
+ s.getText(), Component.text(s.getTooltip().getString())
+ )).toList())
+ .join();
+ }
+
+ @Override
+ public boolean canExecute(CommandCause cause) {
+ if (permission == null) {
+ return true;
+ }
+ return new SpongeCommandUser(cause).checkPermission(permission);
+ }
+
+ @Override
+ public Optional shortDescription(CommandCause cause) {
+ return Optional.of(Component.text(command.getDescription()));
+ }
+
+ @Override
+ public Optional extendedDescription(CommandCause cause) {
+ return Optional.of(Component.text(command.getDescription()));
+ }
+
+ @Override
+ public Component usage(CommandCause cause) {
+ return Component.text(dispatcher.getSmartUsage(dispatcher.getRoot(), cause)
+ .values().stream().map("/%s"::formatted).collect(Collectors.joining("\n")));
+ }
+
+ }
+
+ @Override
+ public void addSubCommand(@NotNull Command command) {
+ addSubCommand(new SpongeCommand(command));
+ }
+
+ @Override
+ public Uniform getUniform() {
+ return SpongeUniform.INSTANCE;
+ }
+
+}
diff --git a/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeCommandUser.java b/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeCommandUser.java
new file mode 100644
index 0000000..fff98c0
--- /dev/null
+++ b/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeCommandUser.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of Uniform, licensed under the GNU General Public License v3.0.
+ *
+ * Copyright (c) Tofaa2
+ * Copyright (c) William278
+ * 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 .
+ */
+
+package net.william278.uniform.sponge;
+
+import net.kyori.adventure.audience.Audience;
+import net.william278.uniform.CommandUser;
+import net.william278.uniform.Permission;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.spongepowered.api.command.CommandCause;
+import org.spongepowered.api.entity.living.player.Player;
+import org.spongepowered.api.util.Tristate;
+
+import java.util.UUID;
+
+public record SpongeCommandUser(@NotNull CommandCause executor) implements CommandUser {
+
+ @Override
+ @NotNull
+ public Audience getAudience() {
+ return executor.audience();
+ }
+
+ @Override
+ @Nullable
+ public String getName() {
+ return executor instanceof Player player ? player.name() : null;
+ }
+
+ @Override
+ @Nullable
+ public UUID getUuid() {
+ return executor instanceof Player player ? player.uniqueId() : null;
+ }
+
+ @Override
+ public boolean checkPermission(@NotNull Permission permission) {
+ final Tristate state = executor.permissionValue(permission.toString());
+ if (state == Tristate.UNDEFINED && permission.defaultValue() == Permission.Default.IF_OP) {
+ return executor.hasPermission(permission.toString());
+ }
+ return state == Tristate.TRUE;
+ }
+
+}
diff --git a/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeUniform.java b/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeUniform.java
new file mode 100644
index 0000000..aec6318
--- /dev/null
+++ b/sponge-11/src/main/java/net/william278/uniform/sponge/SpongeUniform.java
@@ -0,0 +1,106 @@
+/*
+ * This file is part of Uniform, licensed under the GNU General Public License v3.0.
+ *
+ * Copyright (c) Tofaa2
+ * Copyright (c) William278
+ * 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 .
+ */
+
+package net.william278.uniform.sponge;
+
+import lombok.Getter;
+import lombok.Setter;
+import net.william278.uniform.BaseCommand;
+import net.william278.uniform.Command;
+import net.william278.uniform.CommandUser;
+import net.william278.uniform.Uniform;
+import org.jetbrains.annotations.NotNull;
+import org.spongepowered.api.Game;
+import org.spongepowered.api.command.Command.Raw;
+import org.spongepowered.api.command.CommandCause;
+import org.spongepowered.api.event.Listener;
+import org.spongepowered.api.event.lifecycle.RegisterCommandEvent;
+import org.spongepowered.plugin.PluginContainer;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Function;
+
+@SuppressWarnings("unused")
+public final class SpongeUniform implements Uniform {
+
+ static SpongeUniform INSTANCE;
+
+ private final Set commands = new HashSet<>();
+ private final PluginContainer plugin;
+
+ @Getter
+ @Setter
+ Function