initial commit
Some checks failed
Build and Deploy artifact / build (push) Failing after 11s

This commit is contained in:
kento2 2026-08-25 15:37:39 +02:00
commit 7c322707ba
51 changed files with 1488 additions and 0 deletions

23
bukkit/BUILD.bazel Normal file
View file

@ -0,0 +1,23 @@
load("@rules_jvm_external//:defs.bzl", "artifact", "java_export")
load("//:defs.bzl", "GROUP", "VERSION")
java_export(
name = "bukkit",
maven_coordinates = GROUP + ":commands-bukkit:" + VERSION,
srcs = glob(["site/lab0x13/scrow/commands/**/*.java"]),
visibility = ["//visibility:public"],
deps = [
"//common:common-lib",
artifact("org.jetbrains:annotations"),
artifact("com.google.guava:guava"),
artifact("net.kyori:adventure-api"),
artifact("com.leakyabstractions:result-api"),
artifact("com.leakyabstractions:result"),
artifact("io.papermc.paper:paper-api"),
],
exports = [
"//common:common-lib",
artifact("com.leakyabstractions:result-api"),
artifact("com.leakyabstractions:result"),
]
)

View file

@ -0,0 +1,24 @@
package site.lab0x13.scrow.commands.bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import site.lab0x13.scrow.commands.model.AbstractCommandContext;
import site.lab0x13.scrow.commands.model.CommandContext;
public class BukkitCommandContext<C extends CommandContext<C>> extends AbstractCommandContext<C> {
private final CommandSender sender;
public BukkitCommandContext(CommandSender sender) {
this.sender = sender;
}
public CommandSender sender() {
return sender;
}
public Player player() {
return (Player) sender();
}
}

View file

@ -0,0 +1,16 @@
package site.lab0x13.scrow.commands.bukkit;
import net.kyori.adventure.text.Component;
import site.lab0x13.scrow.commands.PlatformAdapter;
class BukkitPlatform<C extends BukkitCommandContext<C>> implements PlatformAdapter<C> {
@Override
public boolean checkPermission(C ctx, String permission) {
return ctx.sender().hasPermission(permission);
}
@Override
public void sendMessage(C ctx, Component message) {
ctx.sender().sendMessage(message);
}
}

View file

@ -0,0 +1,36 @@
package site.lab0x13.scrow.commands.bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import site.lab0x13.scrow.commands.CommandHandler;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import java.util.stream.Stream;
public class BukkitScrowCommand<C extends BukkitCommandContext<C>> extends Command {
private final RootLiteral<C> rootLiteral;
private final CommandContextFactory<C> commandContextFactory;
private final CommandHandler<C> commandHandler;
protected BukkitScrowCommand(CommandHandler<C> commandHandler, CommandContextFactory<C> commandContextFactory, RootLiteral<C> rootLiteral) {
super(rootLiteral.names().getFirst());
this.commandHandler = commandHandler;
this.commandContextFactory = commandContextFactory;
this.rootLiteral = rootLiteral;
this.setAliases(rootLiteral.names());
this.setPermission(rootLiteral.permission());
}
@Override
public boolean execute(@NotNull CommandSender commandSender, @NotNull String commandLabel, String @NotNull [] args) {
commandHandler.invoke(
rootLiteral,
commandContextFactory.createContext(commandSender),
Stream.of(args).filter(str -> !str.isEmpty())
);
return true;
}
}

View file

@ -0,0 +1,9 @@
package site.lab0x13.scrow.commands.bukkit;
import org.bukkit.command.CommandSender;
@FunctionalInterface
public interface CommandContextFactory<C extends BukkitCommandContext<C>> {
C createContext(CommandSender sender);
}

View file

@ -0,0 +1,50 @@
package site.lab0x13.scrow.commands.bukkit;
import org.bukkit.Bukkit;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.Nullable;
import site.lab0x13.scrow.commands.CommandHandler;
import site.lab0x13.scrow.commands.IScrowCommands;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class ScrowCommands<C extends BukkitCommandContext<C>> implements IScrowCommands<C> {
private final CommandContextFactory<C> commandContextFactory;
private final List<RootLiteral<C>> rootLiterals = new ArrayList<>();
private final SimpleCommandMap commandMap;
private final CommandHandler<C> commandHandler;
public ScrowCommands(Plugin plugin, CommandContextFactory<C> commandContextFactory) {
try {
Field field = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap");
field.setAccessible(true);
commandMap = (SimpleCommandMap) field.get(Bukkit.getPluginManager());
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalStateException("failed getting command map", e);
}
this.commandContextFactory = commandContextFactory;
this.commandHandler = new CommandHandler<C>(new BukkitPlatform<>());
Bukkit.getPluginManager().registerEvents(new TabCompleteListener<>(this, commandHandler, commandContextFactory), plugin);
}
@Override
public void register(RootLiteral<C> rootLiteral) {
rootLiterals.add(rootLiteral);
commandMap.register(rootLiteral.names().getFirst(),
new BukkitScrowCommand<>(commandHandler, commandContextFactory, rootLiteral));
}
@Override
public @Nullable RootLiteral<C> getRootLiteral(String name) {
return rootLiterals.stream()
.filter(literal -> literal.names().contains(name))
.findAny()
.orElse(null);
}
}

View file

@ -0,0 +1,46 @@
package site.lab0x13.scrow.commands.bukkit;
import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import site.lab0x13.scrow.commands.CommandHandler;
import java.util.Arrays;
public class TabCompleteListener<C extends BukkitCommandContext<C>> implements Listener {
private final ScrowCommands<C> commandAPI;
private final CommandHandler<C> commandHandler;
private final CommandContextFactory<C> commandContextFactory;
public TabCompleteListener(ScrowCommands<C> commandAPI, CommandHandler<C> commandHandler, CommandContextFactory<C> commandContextFactory) {
this.commandAPI = commandAPI;
this.commandHandler = commandHandler;
this.commandContextFactory = commandContextFactory;
}
@EventHandler(ignoreCancelled = true)
public void onAsyncTabComplete(AsyncTabCompleteEvent ev) {
if (!ev.isCommand()) return;
var args = ev.getBuffer().substring(1).split(" ");
if (args.length == 0) return;
var label = args[0];
{
// commands can be called with a '<plugin name>:' prefix. strip it.
int l = label.indexOf(':');
if (l >= 0)
label = label.substring(l + 1);
}
var literal = commandAPI.getRootLiteral(label);
if (literal == null) return;
ev.setHandled(true);
ev.setCompletions(commandHandler.suggest(
literal,
commandContextFactory.createContext(ev.getSender()),
Arrays.copyOfRange(args, 1, args.length),
ev.getBuffer().endsWith(" ")
));
}
}