This commit is contained in:
kento2 2026-08-29 03:06:29 +02:00
parent ce56c6e105
commit 35a0784e40
46 changed files with 597 additions and 673 deletions

View file

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="run dev server" type="ShConfigurationType"> <configuration default="false" name="run dev server" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="bazel run //build:dev" /> <option name="SCRIPT_TEXT" value="bazel run //rules:dev" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" /> <option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="" /> <option name="SCRIPT_PATH" value="" />
<option name="SCRIPT_OPTIONS" value="" /> <option name="SCRIPT_OPTIONS" value="" />

View file

@ -2,11 +2,13 @@ bazel_dep(name = "rules_java", version = "9.7.0")
bazel_dep(name = "rules_jvm_external", version = "7.1") bazel_dep(name = "rules_jvm_external", version = "7.1")
bazel_dep(name = "bazel_jar_jar", version = "0.1.15") bazel_dep(name = "bazel_jar_jar", version = "0.1.15")
bazel_dep(name = "rules_shell", version = "0.8.0") bazel_dep(name = "rules_shell", version = "0.8.0")
bazel_dep(name = "contrib_rules_jvm", version = "0.34.0")
bazel_dep(name = "apple_rules_lint", version = "0.4.0")
git_override( git_override(
module_name = "rules_jvm_external", module_name = "rules_jvm_external",
remote = "https://github.com/acecilia/rules_jvm_external.git", remote = "https://github.com/acecilia/rules_jvm_external.git",
branch = "3-snapshot_support", commit = "f799b1bacc6b05776275b180bb245bc4a94e795f",
) )
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
@ -21,34 +23,37 @@ maven.install(
"org.slf4j:slf4j-simple:2.0.18", "org.slf4j:slf4j-simple:2.0.18",
"net.kyori:adventure-api:5.2.0", "net.kyori:adventure-api:5.2.0",
"net.kyori:adventure-text-minimessage:5.2.0", "net.kyori:adventure-text-minimessage:5.2.0",
# use `env REPIN=1 bazel run @maven//:pin` after updating # use `env REPIN=1 bazel run @maven//:pin` after changing velocity-api version
"com.velocitypowered:velocity-api:4.1.0-SNAPSHOT", "com.velocitypowered:velocity-api:4.0.0",
"org.jdbi:jdbi3-core:3.53.0", "org.jdbi:jdbi3-core:3.53.0",
"org.jdbi:jdbi3-postgres:3.53.0", "org.jdbi:jdbi3-postgres:3.53.0",
"org.postgresql:postgresql:42.7.12", "org.postgresql:postgresql:42.7.12",
"org.mongodb:bson:5.8.0", "org.mongodb:bson:5.8.0",
"io.nats:jnats:2.25.2", "io.nats:jnats:2.25.2",
"de.kentoj.scrow:kencommandapi-core:0.42-SNAPSHOT", "site.lab0x13.scrow:commands-common:1.2.0",
"de.kentoj.scrow:kencommandapi-bukkit:0.42-SNAPSHOT", "site.lab0x13.scrow:commands-bukkit:1.2.0",
"de.kentoj.scrow:kencommandapi-velocity:0.42-SNAPSHOT", "site.lab0x13.scrow:commands-velocity:1.2.0",
"io.papermc.paper:paper-api:[26.2.build,)", "io.papermc.paper:paper-api:[26.2.build,)",
"net.luckperms:api:5.5", "net.luckperms:api:5.5",
"com.google.code.gson:gson:2.14.0", "com.google.code.gson:gson:2.14.0",
], ],
fetch_sources = False, # fetch_sources = True,
## fix com.github.bazelbuild.rules_jvm_external.resolver.remote.UriNotFoundException: Unable to download
## com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
#excluded_artifacts = ["com.google.guava:listenablefuture"],
repositories = [ repositories = [
"https://repo1.maven.org/maven2", "https://repo.maven.apache.org/maven2",
"https://git.lab0x13.site/api/packages/scrow/maven", "https://git.lab0x13.site/api/packages/scrow/maven",
"https://repo.papermc.io/repository/maven-public/", "https://repo.papermc.io/repository/maven-public/",
], ],
known_contributing_modules = ["protobuf"], known_contributing_modules = ["protobuf"],
fail_on_missing_checksum = False, # for kencommandapi
resolver = "gradle", resolver = "gradle",
lock_file = "//:maven_install.json", lock_file = "//:maven_install.json",
) )
# luckperms is provided at runtime # luckperms is provided at runtime
maven.amend_artifact(coordinates = "net.luckperms:api", neverlink = "true") maven.amend_artifact(coordinates = "net.luckperms:api", neverlink = "true")
use_repo(maven, "maven") use_repo(maven, "maven")
linter = use_extension("@apple_rules_lint//lint:extensions.bzl", "linter")
linter.configure(name = "java-spotbugs", config = "@contrib_rules_jvm//java:spotbugs-default-config")
use_repo(linter, "apple_linters")

View file

@ -13,12 +13,16 @@ public interface ConfigApi {
this.register(key, null); this.register(key, null);
} }
<V> @Nullable ConfigNode<V> getNode(ConfigKey<V> key); @Nullable ConfigNode<?> getNode(String id);
default <V> @Nullable ConfigNode<?> getNode(ConfigKey<V> key) {
return this.getNode(key.id());
}
default <V> @Nullable V get(ConfigKey<V> key) { default <V> @Nullable V get(ConfigKey<V> key) {
var n = getNode(key); var n = getNode(key);
if (n == null) return null; if (n == null) return null;
return n.value(); return (V) n.value();
} }
Map<String, ConfigNode<?>> allNodes(); Map<String, ConfigNode<?>> allNodes();

View file

@ -27,9 +27,8 @@ public class ConfigApiImpl implements ConfigApi {
identifier first, and then descend into the Sub-Nodes. identifier first, and then descend into the Sub-Nodes.
*/ */
@Override @Override
public @Nullable <V> ConfigNode<V> getNode(ConfigKey<V> key) { public @Nullable ConfigNode<?> getNode(String id) {
ConfigNode<Object> node; ConfigNode<Object> node;
var id = key.id();
var fields = new ArrayDeque<String>(); var fields = new ArrayDeque<String>();
while (true) { while (true) {
node = (ConfigNode<Object>) nodes.get(id); node = (ConfigNode<Object>) nodes.get(id);
@ -52,7 +51,7 @@ public class ConfigApiImpl implements ConfigApi {
if (node == null) if (node == null)
return null; return null;
} }
return (ConfigNode<V>) node; return node;
} }
@Override @Override

View file

@ -3,14 +3,16 @@ package site.lab0x13.scrow.configurator;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import site.lab0x13.scrow.configurator.command.ConfigCommand; import site.lab0x13.scrow.configurator.command.ConfigCommand;
import site.lab0x13.scrow.configurator.node.ConfigNode;
import site.lab0x13.scrow.configurator.type.location.LocationConfigType; import site.lab0x13.scrow.configurator.type.location.LocationConfigType;
public class ConfiguratorPlugin extends JavaPlugin { public class ConfiguratorPlugin extends JavaPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
ConfigRootNode nodeRegistry = new ConfigRootNode(); ConfigApi api = new ConfigApiImpl();
nodeRegistry.register("spawnLocation", new Config<>(LocationConfigType.INSTANCE)); var spawnLocation = new ConfigKey<>("spawnLocation", new LocationConfigType());
ScrowAPI.playerCommands().register(new ConfigCommand(nodeRegistry).rootLiteral()); api.register(spawnLocation);
ScrowAPI.commands().register(new ConfigCommand(api).rootLiteral());
} }
} }

View file

@ -1,8 +1,7 @@
package site.lab0x13.scrow.configurator.action; package site.lab0x13.scrow.configurator.action;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import site.lab0x13.scrow.commands.model.argument.Argument;
import org.bukkit.entity.Player;
import site.lab0x13.scrow.configurator.node.ConfigNode; import site.lab0x13.scrow.configurator.node.ConfigNode;
import java.util.List; import java.util.List;
@ -13,9 +12,9 @@ import java.util.List;
public interface ConfigAction<N extends ConfigNode<?>> { public interface ConfigAction<N extends ConfigNode<?>> {
String name(); String name();
List<CommandArgumentSpec<Player, ?>> arguments(); List<Argument<ScrowBukkitCC, ?>> arguments();
boolean requiresValue(); boolean requiresValue();
void execute(N node, CommandContext<Player> ctx); void execute(N node, ScrowBukkitCC ctx);
} }

View file

@ -3,13 +3,11 @@ package site.lab0x13.scrow.configurator.action;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import org.bukkit.entity.Player; import site.lab0x13.scrow.commands.model.argument.Argument;
import site.lab0x13.scrow.configurator.node.ConfigNode; import site.lab0x13.scrow.configurator.node.ConfigNode;
import site.lab0x13.scrow.configurator.type.ConfigType;
import java.util.List; import java.util.List;
@ -23,7 +21,7 @@ public final class GlobalShowAction implements ConfigAction<ConfigNode<Object>>
} }
@Override @Override
public List<CommandArgumentSpec<Player, ?>> arguments() { public List<Argument<ScrowBukkitCC, ?>> arguments() {
return List.of(); return List.of();
} }
@ -33,7 +31,7 @@ public final class GlobalShowAction implements ConfigAction<ConfigNode<Object>>
} }
@Override @Override
public void execute(ConfigNode<Object> node, CommandContext<Player> ctx) { public void execute(ConfigNode<Object> node, ScrowBukkitCC ctx) {
var jsonElement = node.type().serialize(node.value()); var jsonElement = node.type().serialize(node.value());
var prettyJson = GSON.toJson(jsonElement, JsonElement.class); var prettyJson = GSON.toJson(jsonElement, JsonElement.class);
var component = Component.text(prettyJson + " [click to copy]") var component = Component.text(prettyJson + " [click to copy]")

View file

@ -1,7 +1,7 @@
package site.lab0x13.scrow.configurator.action; package site.lab0x13.scrow.configurator.action;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import site.lab0x13.scrow.commands.model.argument.Argument;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import site.lab0x13.scrow.configurator.node.ConfigNode; import site.lab0x13.scrow.configurator.node.ConfigNode;
@ -22,7 +22,7 @@ public abstract class PickAction<V, N extends ConfigNode<V>> implements ConfigAc
} }
@Override @Override
public List<CommandArgumentSpec<Player, ?>> arguments() { public List<Argument<ScrowBukkitCC, ?>> arguments() {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -32,15 +32,15 @@ public abstract class PickAction<V, N extends ConfigNode<V>> implements ConfigAc
} }
@Override @Override
public void execute(N node, CommandContext<Player> ctx) { public void execute(N node, ScrowBukkitCC ctx) {
pick(ctx.sender()) pick(ctx.player())
.orTimeout(10, TimeUnit.MINUTES) .orTimeout(10, TimeUnit.MINUTES)
.whenComplete((picked, ex) -> { .whenComplete((picked, ex) -> {
if (ex instanceof TimeoutException) { if (ex instanceof TimeoutException) {
ctx.sender().sendMessage(ctx.style().err("Timed out picking value.")); ctx.player().sendMessage(ctx.style().err("Timed out picking value."));
return; return;
} }
ctx.sender().playSound(ctx.sender().getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 0.5f, 0f); ctx.player().playSound(ctx.player().getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 0.5f, 0f);
node.value(picked); node.value(picked);
}); });
} }

View file

@ -1,25 +1,24 @@
package site.lab0x13.scrow.configurator.command; package site.lab0x13.scrow.configurator.command;
import de.kentoj.kencommandapi.api.literal.Literal; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import org.bukkit.entity.Player; import site.lab0x13.scrow.commands.model.literal.Literal;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import site.lab0x13.scrow.configurator.ConfigApi; import site.lab0x13.scrow.configurator.ConfigApi;
import site.lab0x13.scrow.configurator.noderegistry.ConfigNodeWalker;
public final class ConfigCommand { public final class ConfigCommand {
private final RootLiteral<Player> rootLiteral; private final RootLiteral<ScrowBukkitCC> rootLiteral;
public ConfigCommand(ConfigApi configApi) { public ConfigCommand(ConfigApi configApi) {
var style = new ScrowMessageStyle("config", TextColor.color(0x28B088)); var style = new ScrowMessageStyle("config", TextColor.color(0x28B088));
rootLiteral = Literal.<Player>builder("config", "cfg") rootLiteral = Literal.<ScrowBukkitCC>builder("config", "cfg")
.withPermission("command.config") .withPermission("command.config")
.withLiteral(new KeyLiteral(style, configApi).literal()) .withSubLiteral(new KeyLiteral(configApi).literal())
.asRootLiteral(style); .asRootLiteral(style);
} }
public RootLiteral<Player> rootLiteral() { public RootLiteral<ScrowBukkitCC> rootLiteral() {
return rootLiteral; return rootLiteral;
} }
} }

View file

@ -1,48 +0,0 @@
package site.lab0x13.scrow.configurator.command;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;
import de.kentoj.kencommandapi.api.argument.ArgumentType;
import de.kentoj.kencommandapi.api.suggestion.SuggestionProvider;
import org.bukkit.entity.Player;
import site.lab0x13.scrow.configurator.node.ConfigNode;
import site.lab0x13.scrow.configurator.noderegistry.ConfigNodeWalker;
import java.util.Collections;
public class ConfigNodeArgumentType implements ArgumentType<Player, ConfigNode<?>> {
private final ConfigNodeWalker nodeWalker;
public ConfigNodeArgumentType(ConfigRootNode rootNode) {
nodeWalker = new ConfigNodeWalker(rootNode);
}
@Override
public Result<ConfigNode<?>, String> parseInputUnchecked(String input) throws IllegalArgumentException {
assert input != null;
var res = nodeWalker.walk(input);
if (res.error() != null)
Results.failure(res.error());
assert res.node() != null;
return Results.success(res.node());
}
@Override
public SuggestionProvider<Player> getDefaultSuggestionProvider() {
return (_, input) -> {
var res = nodeWalker.walk(input);
switch (res.type()) {
case NO_SUCH_FIELD, INDEX_OUT_OF_RANGE, INDEX_EXPECTED -> {
assert res.node() != null;
return res.node().getFieldNames().stream()
.map(it -> res.parentKey() + "." + it)
.toList();
}
default -> {
return Collections.emptyList();
}
}
};
}
}

View file

@ -1,73 +1,50 @@
package site.lab0x13.scrow.configurator.command; package site.lab0x13.scrow.configurator.command;
import de.kentoj.kencommandapi.api.literal.Literal; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.literal.LiteralBuilder;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable;
import site.lab0x13.scrow.commands.model.literal.Literal;
import site.lab0x13.scrow.configurator.ConfigApi; import site.lab0x13.scrow.configurator.ConfigApi;
import site.lab0x13.scrow.configurator.action.ConfigAction; import site.lab0x13.scrow.configurator.action.ConfigAction;
import site.lab0x13.scrow.configurator.node.ConfigNode; import site.lab0x13.scrow.configurator.node.ConfigNode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
class KeyLiteral { class KeyLiteral {
private final ScrowMessageStyle style; private final Literal<ScrowBukkitCC> literal;
private final Literal<Player> literal; private final ConfigApi api;
KeyLiteral(ScrowMessageStyle style, ConfigApi api) { KeyLiteral(ConfigApi api) {
/* this.api = api;
All registered nodes should be added as literals. SubNoded nodes should be added literal = Literal.<ScrowBukkitCC>dynamic("key")
recursively. .withSubLiteralNames(() -> new ArrayList<>(api.allNodes().keySet()))
When foo is a list node(implements SubNoded): .withSubLiteralProvider(this::keyLiteral)
/cfg key foo <- list node itself is registered, has actions like append, delete, etc. .build();
/cfg key foo.0 <- operate on first element, has actions of foo.0's type
*/
this.style = style;
var builder = Literal.<Player>builder("key");
api.allNodes().forEach((key, node) ->
addNodeLiteral(builder, key, node));
this.literal = builder.build();
} }
private void addNodeLiteral(LiteralBuilder<Player> builder, String key, ConfigNode<?> node) { private @Nullable Literal<ScrowBukkitCC> keyLiteral(String name) {
var nodeLiteralBuilder = Literal.<Player>builder(key); var node = api.getNode(name);
addNodeActionLiteral(nodeLiteralBuilder, (ConfigNode<Object>) node, new ArrayList<>(node.type().actions())); if (node == null)
/* return null;
FUCK ME WE NEED TO ADD LITERALS AT RUNTIME.
I just need /cfg key <node> <actions dependent on node>
except nodes are registered at runtime so we need to register literals at runtime.
or we make it an argument, but then we can't make action's work nicely(only hackishly at best);
or a dy
*/
for (String fieldName : node.type().getSubNodeNames(node.value())) {
var subNode = node.type().getSubNode(node.value(), fieldName);
if (subNode == null) continue;
addNodeActionLiteral();
}
builder.withLiteral(nodeLiteralBuilder.build());
}
private void addNodeActionLiteral(LiteralBuilder<Player> builder, ConfigNode<Object> node, List<ConfigAction<?>> actions) { var literalBuilder = Literal.<ScrowBukkitCC>builder(name);
for (var _action : actions) { for (var action : node.type().actions()) {
var action = (ConfigOptionAction<ConfigNode<Object>>) _action; var actionLiteralBuilder = Literal.<ScrowBukkitCC>builder(action.name());
var actionLiteralBuilder = Literal.<Player>builder(action.name()); action.arguments().forEach(actionLiteralBuilder::withArgument);
for (var argument : action.arguments())
actionLiteralBuilder.withArgument(argument);
actionLiteralBuilder.withSyncExecutor(ctx -> { actionLiteralBuilder.withSyncExecutor(ctx -> {
if (action.requiresValue() && node.value() == null) { if (action.requiresValue() && node.value() == null) {
ctx.sender().sendMessage(style.err("No value set.")); ctx.sender().sendMessage(ctx.style().err("No value set."));
return; return;
} }
action.execute(node, ctx); ((ConfigAction<ConfigNode<?>>) action).execute(node, ctx);
}); });
builder.withLiteral(actionLiteralBuilder.build()); literalBuilder.withSubLiteral(actionLiteralBuilder.build());
} }
return literalBuilder.build();
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }
} }

View file

@ -1,56 +0,0 @@
package site.lab0x13.scrow.configurator.command;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
import de.kentoj.kencommandapi.api.literal.Literal;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import site.lab0x13.scrow.configurator.node.ConfigNode;
import java.util.List;
public class KeyLiteralImpl implements Literal<Player> {
private final ConfigNode<?> node;
public KeyLiteralImpl(String key, ConfigNode<?> node) {
this.key = key;
this.node = node;
}
@Override
public @Nullable Literal<Player> getLiteral(@NotNull String name) {
node.
return null;
}
@Override
public @NotNull List<Literal<Player>> literals() {
gh
}
@Override
public @NotNull String[] names() {
return new String[]{key};
}
@Override
public @Nullable String description() {
return null;
}
@Override
public List<CommandArgumentSpec<Player, ?>> arguments() {
return List.of();
}
@Override
public @Nullable CommandExecutor<Player> executor() {
return null;
}
@Override
public @Nullable String permission() {
return "";
}
}

View file

@ -13,7 +13,7 @@ public class LocationConfigType extends ConfigComplexType<Location> {
public static final LocationConfigType INSTANCE = new LocationConfigType(); public static final LocationConfigType INSTANCE = new LocationConfigType();
private LocationConfigType() { public LocationConfigType() {
addField("world", WorldConfigType.INSTANCE, Location::getWorld); addField("world", WorldConfigType.INSTANCE, Location::getWorld);
addField("x", ConfigPrimitiveType.DOUBLE, Location::getX); addField("x", ConfigPrimitiveType.DOUBLE, Location::getX);
addField("y", ConfigPrimitiveType.DOUBLE, Location::getY); addField("y", ConfigPrimitiveType.DOUBLE, Location::getY);

View file

@ -1,7 +1,7 @@
package site.lab0x13.scrow.configurator.type.location; package site.lab0x13.scrow.configurator.type.location;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import site.lab0x13.scrow.commands.model.argument.Argument;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import site.lab0x13.scrow.configurator.action.ConfigAction; import site.lab0x13.scrow.configurator.action.ConfigAction;
@ -18,7 +18,7 @@ class LocationTeleportAction implements ConfigAction<ConfigNode<Location>> {
} }
@Override @Override
public List<CommandArgumentSpec<Player, ?>> arguments() { public List<Argument<ScrowBukkitCC, ?>> arguments() {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -28,8 +28,9 @@ class LocationTeleportAction implements ConfigAction<ConfigNode<Location>> {
} }
@Override @Override
public void execute(ConfigNode<Location> node, CommandContext<Player> ctx) { public void execute(ConfigNode<Location> node, ScrowBukkitCC ctx) {
ctx.sender().teleport(node.value()); assert node.value() != null;
ctx.sender().sendMessage(ctx.style().ok("You've been teleported.")); ctx.player().teleport(node.value());
ctx.player().sendMessage(ctx.style().ok("You've been teleported."));
} }
} }

View file

@ -1,10 +1,9 @@
package site.lab0x13.scrow.configurator.type.world; package site.lab0x13.scrow.configurator.type.world;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import site.lab0x13.scrow.commands.bukkit.type.WorldArgumentType;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import site.lab0x13.scrow.commands.model.argument.Argument;
import de.kentoj.kencommandapi.type.WorldArgumentType; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player;
import site.lab0x13.scrow.configurator.action.ConfigAction; import site.lab0x13.scrow.configurator.action.ConfigAction;
import site.lab0x13.scrow.configurator.node.ConfigNode; import site.lab0x13.scrow.configurator.node.ConfigNode;
@ -12,8 +11,8 @@ import java.util.List;
class SetWorldAction implements ConfigAction<ConfigNode<World>> { class SetWorldAction implements ConfigAction<ConfigNode<World>> {
private final CommandArgumentSpec<Player, World> arg = private final Argument<ScrowBukkitCC, World> arg =
CommandArgumentSpec.builder("world", new WorldArgumentType<Player>()).build(); Argument.builder("world", new WorldArgumentType<ScrowBukkitCC>()).build();
@Override @Override
public String name() { public String name() {
@ -21,7 +20,7 @@ class SetWorldAction implements ConfigAction<ConfigNode<World>> {
} }
@Override @Override
public List<CommandArgumentSpec<Player, ?>> arguments() { public List<Argument<ScrowBukkitCC, ?>> arguments() {
return List.of(arg); return List.of(arg);
} }
@ -31,7 +30,7 @@ class SetWorldAction implements ConfigAction<ConfigNode<World>> {
} }
@Override @Override
public void execute(ConfigNode<World> node, CommandContext<Player> ctx) { public void execute(ConfigNode<World> node, ScrowBukkitCC ctx) {
World world = ctx.getArg(arg); World world = ctx.getArg(arg);
node.value(world); node.value(world);
ctx.sender().sendMessage(ctx.style().ok("Set world to " + world.getName() + "(" + world.getUID() + ")")); ctx.sender().sendMessage(ctx.style().ok("Set world to " + world.getName() + "(" + world.getUID() + ")"));

View file

@ -9,11 +9,11 @@ java_library(
deps = [ deps = [
"//core/common", "//core/common",
artifact("io.papermc.paper:paper-api"), artifact("io.papermc.paper:paper-api"),
artifact("de.kentoj.scrow:kencommandapi-bukkit"), artifact("site.lab0x13.scrow:commands-bukkit"),
], ],
exports = [ exports = [
"//core/common", "//core/common",
artifact("de.kentoj.scrow:kencommandapi-bukkit"), artifact("site.lab0x13.scrow:commands-bukkit"),
artifact("org.mongodb:bson"), artifact("org.mongodb:bson"),
], ],
neverlink = True, neverlink = True,
@ -27,7 +27,7 @@ java_binary(
resource_strip_prefix = "core/bukkit/plugin/main/resources", resource_strip_prefix = "core/bukkit/plugin/main/resources",
deps = [ deps = [
"//core/common", "//core/common",
artifact("de.kentoj.scrow:kencommandapi-bukkit"), artifact("site.lab0x13.scrow:commands-bukkit"),
artifact("net.luckperms:api"), artifact("net.luckperms:api"),
artifact("io.papermc.paper:paper-api"), artifact("io.papermc.paper:paper-api"),
artifact("io.nats:jnats"), artifact("io.nats:jnats"),

View file

@ -1,6 +1,6 @@
package de.kentoj.scrow.bukkit; package de.kentoj.scrow.bukkit;
import de.kentoj.kencommandapi.CommandAPI; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.scrow.bukkit.minigame.MinigameManager; import de.kentoj.scrow.bukkit.minigame.MinigameManager;
import de.kentoj.scrow.bukkit.region.RegionManager; import de.kentoj.scrow.bukkit.region.RegionManager;
import de.kentoj.scrowlib.economy.EconomyService; import de.kentoj.scrowlib.economy.EconomyService;
@ -12,12 +12,11 @@ import de.kentoj.scrowlib.player.NetworkPlayer;
import de.kentoj.scrowlib.player.NetworkPlayerFactory; import de.kentoj.scrowlib.player.NetworkPlayerFactory;
import de.kentoj.scrowlib.player.PlayerPrefixProvider; import de.kentoj.scrowlib.player.PlayerPrefixProvider;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jdbi.v3.core.Jdbi; import org.jdbi.v3.core.Jdbi;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import site.lab0x13.scrow.commands.bukkit.ScrowCommands;
import java.util.UUID; import java.util.UUID;
@ -38,8 +37,7 @@ public class ScrowAPI {
private static MessageBroker messageBroker; private static MessageBroker messageBroker;
private static InstanceManager instanceManager; private static InstanceManager instanceManager;
private static RegionManager regionManager; private static RegionManager regionManager;
private static CommandAPI<Player> playerCommands; private static ScrowCommands<ScrowBukkitCC> commands;
private static CommandAPI<CommandSender> commands;
private static PlayerPrefixProvider playerPrefixProvider; private static PlayerPrefixProvider playerPrefixProvider;
private static final MinigameManager minigameManager = new MinigameManager(); private static final MinigameManager minigameManager = new MinigameManager();
private static NetworkPlayerFactory playerFactory; private static NetworkPlayerFactory playerFactory;
@ -103,13 +101,8 @@ public class ScrowAPI {
} }
@ApiStatus.Internal @ApiStatus.Internal
public static void setPlayerCommands(CommandAPI<Player> playerCommands) { public static void setCommands(ScrowCommands<ScrowBukkitCC> commandsManager) {
ScrowAPI.playerCommands = playerCommands; ScrowAPI.commands = commandsManager;
}
@ApiStatus.Internal
public static void setCommands(CommandAPI<CommandSender> commands) {
ScrowAPI.commands = commands;
} }
public static @Nullable Jdbi jdbi() { public static @Nullable Jdbi jdbi() {
@ -143,17 +136,15 @@ public class ScrowAPI {
/** /**
* Regions are not a reliable enough to detect fast movements. * Regions are not a reliable enough to detect fast movements.
* The way regions work is that every few ticks, all regions are checked for players. * The way regions work is that every few ticks, all regions are checked for players.
*
* @see org.bukkit.event.player.PlayerMoveEvent * @see org.bukkit.event.player.PlayerMoveEvent
*/ */
public static RegionManager regionManager() { public static RegionManager regionManager() {
return regionManager; return regionManager;
} }
public static CommandAPI<Player> playerCommands() { @ApiStatus.Internal
return playerCommands; public static ScrowCommands<ScrowBukkitCC> commands() {
}
public static CommandAPI<CommandSender> commands() {
return commands; return commands;
} }

View file

@ -0,0 +1,18 @@
package de.kentoj.scrow.bukkit.command;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import org.bukkit.command.CommandSender;
import site.lab0x13.scrow.commands.bukkit.BukkitCommandContext;
public final class ScrowBukkitCC extends BukkitCommandContext<ScrowBukkitCC> {
private final ScrowMessageStyle style;
public ScrowBukkitCC(CommandSender sender, ScrowMessageStyle style) {
super(sender);
this.style = style;
}
public ScrowMessageStyle style() {
return style;
}
}

View file

@ -1,11 +1,11 @@
package de.kentoj.scrow.bukkit.minigame.phaseflow; package de.kentoj.scrow.bukkit.minigame.phaseflow;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import de.kentoj.scrow.bukkit.minigame.Minigame; import de.kentoj.scrow.bukkit.minigame.Minigame;
import de.kentoj.scrow.bukkit.minigame.PlayerManager; import de.kentoj.scrow.bukkit.minigame.PlayerManager;
import de.kentoj.scrow.bukkit.minigame.phase.PhaseFlow; import de.kentoj.scrow.bukkit.minigame.phase.PhaseFlow;
import de.kentoj.scrow.bukkit.minigame.phase.event.PhaseListeners; import de.kentoj.scrow.bukkit.minigame.phase.event.PhaseListeners;
import de.kentoj.scrow.bukkit.minigame.phase.event.PhaseListenersImpl; import de.kentoj.scrow.bukkit.minigame.phase.event.PhaseListenersImpl;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
public class PhaseContext<T extends Minigame> { public class PhaseContext<T extends Minigame> {
private final T game; private final T game;
@ -29,7 +29,7 @@ public class PhaseContext<T extends Minigame> {
return game.playerManager(); return game.playerManager();
} }
public MessageStyle style() { public ScrowMessageStyle style() {
return game.messageStyle(); return game.messageStyle();
} }

View file

@ -21,8 +21,8 @@ public final class CoreImplPlugin extends JavaPlugin {
ScrowAPISurface.initScrowAPI(this, cachedPrefixProvider); ScrowAPISurface.initScrowAPI(this, cachedPrefixProvider);
log.info("Initialized ScrowAPI"); log.info("Initialized ScrowAPI");
ScrowAPI.playerCommands().register(new CoinsCommand().rootLiteral()); ScrowAPI.commands().register(new CoinsCommand().rootLiteral());
ScrowAPI.playerCommands().register(new FriendCommand().rootLiteral()); ScrowAPI.commands().register(new FriendCommand().rootLiteral());
var luckperms = LuckPermsProvider.get(); var luckperms = LuckPermsProvider.get();
new LuckPermsPrefixSetter(luckperms, cachedPrefixProvider).init(this); new LuckPermsPrefixSetter(luckperms, cachedPrefixProvider).init(this);

View file

@ -1,10 +1,11 @@
package de.kentoj.scrow.bukkit; package de.kentoj.scrow.bukkit;
import de.kentoj.kencommandapi.CommandAPI; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.scrow.bukkit.internal.player.NetworkPlayerWatchdog; import de.kentoj.scrow.bukkit.internal.player.NetworkPlayerWatchdog;
import de.kentoj.scrow.bukkit.internal.region.RegionManagerImpl; import de.kentoj.scrow.bukkit.internal.region.RegionManagerImpl;
import de.kentoj.scrow.bukkit.internal.region.RegionPlayerTracker; import de.kentoj.scrow.bukkit.internal.region.RegionPlayerTracker;
import de.kentoj.scrow.bukkit.internal.region.RegionTask; import de.kentoj.scrow.bukkit.internal.region.RegionTask;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.scrowlib.economy.InMemoryEconomyService; import de.kentoj.scrowlib.economy.InMemoryEconomyService;
import de.kentoj.scrowlib.economy.PostgresEconomyService; import de.kentoj.scrowlib.economy.PostgresEconomyService;
import de.kentoj.scrowlib.friends.friendship.InMemoryFriendshipService; import de.kentoj.scrowlib.friends.friendship.InMemoryFriendshipService;
@ -18,12 +19,11 @@ import de.kentoj.scrowlib.player.NetworkPlayerImpl;
import de.kentoj.scrowlib.player.PlayerPrefixProvider; import de.kentoj.scrowlib.player.PlayerPrefixProvider;
import io.nats.client.Nats; import io.nats.client.Nats;
import io.nats.client.Options; import io.nats.client.Options;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jdbi.v3.core.Jdbi; import org.jdbi.v3.core.Jdbi;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import site.lab0x13.scrow.commands.bukkit.ScrowCommands;
import java.io.IOException; import java.io.IOException;
import java.util.Properties; import java.util.Properties;
@ -70,8 +70,7 @@ public class ScrowAPISurface {
ScrowAPI.setPlayerFactory(playerId -> new NetworkPlayerImpl(ScrowAPI.messageBroker(), playerId)); ScrowAPI.setPlayerFactory(playerId -> new NetworkPlayerImpl(ScrowAPI.messageBroker(), playerId));
ScrowAPI.setRegionManager(new RegionManagerImpl()); ScrowAPI.setRegionManager(new RegionManagerImpl());
ScrowAPI.setCommands(new CommandAPI<>(plugin, CommandSender.class)); ScrowAPI.setCommands(new ScrowCommands<>(plugin, (literal, sender) -> new ScrowBukkitCC(sender, (ScrowMessageStyle) literal.style())));
ScrowAPI.setPlayerCommands(new CommandAPI<>(plugin, Player.class));
ScrowAPI.setInstanceManager(new InstanceManagerImpl(ScrowAPI.messageBroker())); ScrowAPI.setInstanceManager(new InstanceManagerImpl(ScrowAPI.messageBroker()));
ScrowAPI.setEconomyService(ScrowAPI.jdbi() != null ? ScrowAPI.setEconomyService(ScrowAPI.jdbi() != null ?
new PostgresEconomyService(ScrowAPI.jdbi()) : new InMemoryEconomyService()); new PostgresEconomyService(ScrowAPI.jdbi()) : new InMemoryEconomyService());

View file

@ -1,31 +1,29 @@
package de.kentoj.scrow.bukkit.command.economy; package de.kentoj.scrow.bukkit.command.economy;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import org.bukkit.entity.Player; import site.lab0x13.scrow.commands.model.literal.Literal;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public final class CoinsCommand { public final class CoinsCommand {
private final RootLiteral<Player> rootLiteral; private final RootLiteral<ScrowBukkitCC> rootLiteral;
public CoinsCommand() { public CoinsCommand() {
rootLiteral = Literal.<Player>builder("coins", "bal", "balance") rootLiteral = Literal.<ScrowBukkitCC>builder("coins", "bal", "balance")
.withPermission("command.coins.get.self") .withPermission("command.coins.get.self")
.withExecutor(this::execute) .withExecutor(this::execute)
.withLiteral(new CoinsSetLiteral().literal()) .withSubLiteral(new CoinsSetLiteral().literal())
.withLiteral(new CoinsGetLiteral().literal()) .withSubLiteral(new CoinsGetLiteral().literal())
.asRootLiteral(ScrowMessageStyle.GENERIC); .asRootLiteral(ScrowMessageStyle.GENERIC);
} }
public CompletableFuture<?> execute(CommandContext<Player> ctx) { public CompletableFuture<?> execute(ScrowBukkitCC ctx) {
var player = ctx.sender(); var player = ctx.player();
return Tasks.supplyAsync(() -> return Tasks.supplyAsync(() ->
ScrowAPI.economyService().getCoins(player.getUniqueId())) ScrowAPI.economyService().getCoins(player.getUniqueId()))
.thenSync(amount -> .thenSync(amount ->
@ -33,7 +31,7 @@ public final class CoinsCommand {
.toFuture(); .toFuture();
} }
public RootLiteral<Player> rootLiteral() { public RootLiteral<ScrowBukkitCC> rootLiteral() {
return rootLiteral; return rootLiteral;
} }
} }

View file

@ -1,34 +1,32 @@
package de.kentoj.scrow.bukkit.command.economy; package de.kentoj.scrow.bukkit.command.economy;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import de.kentoj.kencommandapi.type.OfflinePlayerArgumentType;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import site.lab0x13.scrow.commands.bukkit.type.OfflinePlayerArgumentType;
import site.lab0x13.scrow.commands.model.argument.Argument;
import site.lab0x13.scrow.commands.model.literal.Literal;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public final class CoinsGetLiteral { public final class CoinsGetLiteral {
private final Literal<Player> literal; private final Literal<ScrowBukkitCC> literal;
private final CommandArgumentSpec<Player, OfflinePlayer> playerArg; private final Argument<ScrowBukkitCC, OfflinePlayer> playerArg;
public CoinsGetLiteral() { public CoinsGetLiteral() {
playerArg = CommandArgumentSpec.builder("player", new OfflinePlayerArgumentType<Player>()) playerArg = Argument.builder("player", new OfflinePlayerArgumentType<ScrowBukkitCC>())
.withDefaultValue(CommandContext::sender) .withDefaultValue(ScrowBukkitCC::player)
.build(); .build();
literal = Literal.<Player>builder("get") literal = Literal.<ScrowBukkitCC>builder("get")
.withPermission("command.coins.get.others") .withPermission("command.coins.get.others")
.withArgument(playerArg) .withArgument(playerArg)
.withExecutor(this::execute) .withExecutor(this::execute)
.build(); .build();
} }
private CompletableFuture<?> execute(CommandContext<Player> ctx) { private CompletableFuture<?> execute(ScrowBukkitCC ctx) {
var player = ctx.getArg(playerArg); var player = ctx.getArg(playerArg);
return Tasks.supplyAsync(() -> return Tasks.supplyAsync(() ->
ScrowAPI.economyService().getCoins(player.getUniqueId())) ScrowAPI.economyService().getCoins(player.getUniqueId()))
@ -37,7 +35,7 @@ public final class CoinsGetLiteral {
.toFuture(); .toFuture();
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }
} }

View file

@ -1,11 +1,10 @@
package de.kentoj.scrow.bukkit.command.economy; package de.kentoj.scrow.bukkit.command.economy;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.argument.types.IntegerArgumentType; import site.lab0x13.scrow.commands.model.argument.Argument;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import site.lab0x13.scrow.commands.model.argument.types.IntegerArgumentType;
import de.kentoj.kencommandapi.api.literal.Literal; import site.lab0x13.scrow.commands.model.literal.Literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle; import site.lab0x13.scrow.commands.bukkit.type.OfflinePlayerArgumentType;
import de.kentoj.kencommandapi.type.OfflinePlayerArgumentType;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
@ -15,17 +14,17 @@ import java.util.concurrent.CompletableFuture;
public final class CoinsSetLiteral { public final class CoinsSetLiteral {
private final Literal<Player> literal; private final Literal<ScrowBukkitCC> literal;
private final CommandArgumentSpec<Player, OfflinePlayer> playerArg; private final Argument<ScrowBukkitCC, OfflinePlayer> playerArg;
private final CommandArgumentSpec<Player, Integer> amountArg; private final Argument<ScrowBukkitCC, Integer> amountArg;
CoinsSetLiteral() { CoinsSetLiteral() {
playerArg = CommandArgumentSpec.builder("player", new OfflinePlayerArgumentType<Player>()) playerArg = Argument.builder("player", new OfflinePlayerArgumentType<ScrowBukkitCC>())
.withDefaultValue(CommandContext::sender) .withDefaultValue(ScrowBukkitCC::player)
.build(); .build();
amountArg = CommandArgumentSpec.builder("amount", new IntegerArgumentType<Player>()) amountArg = Argument.builder("amount", new IntegerArgumentType<ScrowBukkitCC>())
.build(); .build();
literal = Literal.<Player>builder("set") literal = Literal.<ScrowBukkitCC>builder("set")
.withPermission("command.coins.set") .withPermission("command.coins.set")
.withArgument(playerArg) .withArgument(playerArg)
.withArgument(amountArg) .withArgument(amountArg)
@ -33,7 +32,7 @@ public final class CoinsSetLiteral {
.build(); .build();
} }
private CompletableFuture<?> execute(CommandContext<Player> ctx) { private CompletableFuture<?> execute(ScrowBukkitCC ctx) {
var player = ctx.getArg(playerArg); var player = ctx.getArg(playerArg);
var amount = ctx.getArg(amountArg); var amount = ctx.getArg(amountArg);
return Tasks.runAsync(() -> return Tasks.runAsync(() ->
@ -43,7 +42,7 @@ public final class CoinsSetLiteral {
.toFuture(); .toFuture();
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }
} }

View file

@ -2,15 +2,13 @@ package de.kentoj.scrow.bukkit.command.friends;
import com.leakyabstractions.result.api.Result; import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results; import com.leakyabstractions.result.core.Results;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import site.lab0x13.scrow.commands.model.argument.Argument;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.literal.Literal; import site.lab0x13.scrow.commands.model.literal.Literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle; import site.lab0x13.scrow.commands.bukkit.type.OfflinePlayerArgumentType;
import de.kentoj.kencommandapi.type.OfflinePlayerArgumentType;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.scheduler.Task; import de.kentoj.scrow.bukkit.scheduler.Task;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.scrowlib.friends.FriendRequestService; import de.kentoj.scrowlib.friends.FriendRequestService;
import de.kentoj.scrowlib.friends.FriendshipService; import de.kentoj.scrowlib.friends.FriendshipService;
import de.kentoj.scrowlib.friends.friendship.FriendshipImpl; import de.kentoj.scrowlib.friends.friendship.FriendshipImpl;
@ -18,6 +16,7 @@ import de.kentoj.scrowlib.friends.request.FriendRequestImpl;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import site.lab0x13.scrow.commands.model.literal.MessageStyle;
import java.time.Instant; import java.time.Instant;
import java.util.Objects; import java.util.Objects;
@ -26,22 +25,22 @@ import java.util.concurrent.CompletableFuture;
public final class FriendAddLiteral { public final class FriendAddLiteral {
private final Literal<Player> literal; private final Literal<ScrowBukkitCC> literal;
private final CommandArgumentSpec<Player, OfflinePlayer> playerArg; private final Argument<ScrowBukkitCC, OfflinePlayer> playerArg;
private final FriendRequestService requestService = ScrowAPI.friendRequestService(); private final FriendRequestService requestService = ScrowAPI.friendRequestService();
private final FriendshipService friendsService = ScrowAPI.friendshipService(); private final FriendshipService friendsService = ScrowAPI.friendshipService();
FriendAddLiteral() { FriendAddLiteral() {
playerArg = CommandArgumentSpec.builder("player", new OfflinePlayerArgumentType<Player>()) playerArg = Argument.builder("player", new OfflinePlayerArgumentType<ScrowBukkitCC>())
.build(); .build();
literal = Literal.<Player>builder("add") literal = Literal.<ScrowBukkitCC>builder("add")
.withArgument(playerArg) .withArgument(playerArg)
.withExecutor(this::execute) .withExecutor(this::execute)
.build(); .build();
} }
private CompletableFuture<?> execute(CommandContext<Player> ctx) { private CompletableFuture<?> execute(ScrowBukkitCC ctx) {
var self = ctx.sender(); var self = ctx.player();
var other = ctx.getArg(playerArg); var other = ctx.getArg(playerArg);
return Tasks.supplyAsync(() -> findAction(self, other) return Tasks.supplyAsync(() -> findAction(self, other)
.mapSuccess(action -> { .mapSuccess(action -> {
@ -53,6 +52,10 @@ public final class FriendAddLiteral {
} }
private void sendRequest(MessageStyle style, Player self, OfflinePlayer other) { private void sendRequest(MessageStyle style, Player self, OfflinePlayer other) {
if (other.equals(self)) {
self.sendMessage(style.ok("You can't send yourself a friend request."));
return;
}
Tasks.runAsync(() -> Tasks.runAsync(() ->
requestService.saveFriendRequest(new FriendRequestImpl(self.getUniqueId(), other.getUniqueId()))) requestService.saveFriendRequest(new FriendRequestImpl(self.getUniqueId(), other.getUniqueId())))
.runSync(() -> { .runSync(() -> {
@ -110,7 +113,7 @@ public final class FriendAddLiteral {
.mapSync(Objects::nonNull); .mapSync(Objects::nonNull);
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }

View file

@ -1,25 +1,25 @@
package de.kentoj.scrow.bukkit.command.friends; package de.kentoj.scrow.bukkit.command.friends;
import de.kentoj.kencommandapi.api.literal.Literal; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player; import site.lab0x13.scrow.commands.model.literal.Literal;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
public final class FriendCommand { public final class FriendCommand {
private final RootLiteral<Player> rootLiteral; private final RootLiteral<ScrowBukkitCC> rootLiteral;
public FriendCommand() { public FriendCommand() {
rootLiteral = Literal.<Player>builder("f", "friend") rootLiteral = Literal.<ScrowBukkitCC>builder("f", "friend")
.withLiteral(new FriendListLiteral().literal()) .withSubLiteral(new FriendListLiteral().literal())
.withLiteral(new FriendAddLiteral().literal()) .withSubLiteral(new FriendAddLiteral().literal())
.withLiteral(new FriendRemoveLiteral().literal()) .withSubLiteral(new FriendRemoveLiteral().literal())
.withLiteral(new FriendRequestDeclineLiteral().literal()) .withSubLiteral(new FriendRequestDeclineLiteral().literal())
.withLiteral(new FriendRequestsLiteral().literal()) .withSubLiteral(new FriendRequestsLiteral().literal())
.asRootLiteral(new ScrowMessageStyle("Friends", NamedTextColor.AQUA)); .asRootLiteral(new ScrowMessageStyle("Friends", NamedTextColor.AQUA));
} }
@ -38,7 +38,7 @@ public final class FriendCommand {
.color(NamedTextColor.RED)); .color(NamedTextColor.RED));
} }
public RootLiteral<Player> rootLiteral() { public RootLiteral<ScrowBukkitCC> rootLiteral() {
return rootLiteral; return rootLiteral;
} }
} }

View file

@ -1,8 +1,7 @@
package de.kentoj.scrow.bukkit.command.friends; package de.kentoj.scrow.bukkit.command.friends;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.literal.Literal; import site.lab0x13.scrow.commands.model.literal.Literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
@ -11,7 +10,6 @@ import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -20,16 +18,16 @@ import static java.util.Objects.requireNonNull;
import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.text;
public final class FriendListLiteral { public final class FriendListLiteral {
private final Literal<Player> literal; private final Literal<ScrowBukkitCC> literal;
FriendListLiteral() { FriendListLiteral() {
literal = Literal.<Player>builder("list") literal = Literal.<ScrowBukkitCC>builder("list")
.withExecutor(this::displayFriendList) .withExecutor(this::displayFriendList)
.build(); .build();
} }
private CompletableFuture<?> displayFriendList(CommandContext<Player> ctx) { private CompletableFuture<?> displayFriendList(ScrowBukkitCC ctx) {
var sender = ctx.sender(); var sender = ctx.player();
return Tasks.supplyAsync(() -> return Tasks.supplyAsync(() ->
ScrowAPI.friendshipService().getFriendships(sender.getUniqueId())) ScrowAPI.friendshipService().getFriendships(sender.getUniqueId()))
.thenSync(friendships -> { .thenSync(friendships -> {
@ -67,7 +65,7 @@ public final class FriendListLiteral {
return message; return message;
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }
} }

View file

@ -1,36 +1,33 @@
package de.kentoj.scrow.bukkit.command.friends; package de.kentoj.scrow.bukkit.command.friends;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.type.OfflinePlayerArgumentType;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import site.lab0x13.scrow.commands.bukkit.type.OfflinePlayerArgumentType;
import site.lab0x13.scrow.commands.model.argument.Argument;
import site.lab0x13.scrow.commands.model.literal.Literal;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public final class FriendRemoveLiteral { public final class FriendRemoveLiteral {
private final Literal<Player> literal; private final Literal<ScrowBukkitCC> literal;
private final CommandArgumentSpec<Player, OfflinePlayer> playerArg; private final Argument<ScrowBukkitCC, OfflinePlayer> playerArg;
FriendRemoveLiteral() { FriendRemoveLiteral() {
playerArg = CommandArgumentSpec.<Player, OfflinePlayer>builder("player", new OfflinePlayerArgumentType<>()) playerArg = Argument.<ScrowBukkitCC, OfflinePlayer>builder("player", new OfflinePlayerArgumentType<>())
.build(); .build();
literal = Literal.<Player>builder("remove") literal = Literal.<ScrowBukkitCC>builder("remove")
.withArgument(playerArg) .withArgument(playerArg)
.withExecutor(this::removeFriend) .withExecutor(this::removeFriend)
.build(); .build();
} }
private CompletableFuture<?> removeFriend(CommandContext<Player> ctx) { private CompletableFuture<?> removeFriend(ScrowBukkitCC ctx) {
var friend = ctx.getArg(playerArg); var friend = ctx.getArg(playerArg);
return Tasks.supplyAsync(() -> return Tasks.supplyAsync(() ->
ScrowAPI.friendshipService().deleteFriendship(friend.getUniqueId(), ctx.sender().getUniqueId())) ScrowAPI.friendshipService().deleteFriendship(friend.getUniqueId(), ctx.player().getUniqueId()))
.thenSync(deleted -> { .thenSync(deleted -> {
if (!deleted) { if (!deleted) {
ctx.sender().sendMessage(ctx.style().err("You are not friends with " + friend.getName() + ".")); ctx.sender().sendMessage(ctx.style().err("You are not friends with " + friend.getName() + "."));
@ -40,7 +37,7 @@ public final class FriendRemoveLiteral {
}).toFuture(); }).toFuture();
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }
} }

View file

@ -1,50 +1,46 @@
package de.kentoj.scrow.bukkit.command.friends; package de.kentoj.scrow.bukkit.command.friends;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
import de.kentoj.kencommandapi.api.invocation.CommandContext;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.type.OfflinePlayerArgumentType;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.scrowlib.friends.FriendRequestService; import de.kentoj.scrowlib.friends.FriendRequestService;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import site.lab0x13.scrow.commands.bukkit.type.OfflinePlayerArgumentType;
import site.lab0x13.scrow.commands.model.argument.Argument;
import site.lab0x13.scrow.commands.model.literal.Literal;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public final class FriendRequestDeclineLiteral { public final class FriendRequestDeclineLiteral {
private final Literal<Player> literal; private final Literal<ScrowBukkitCC> literal;
private final CommandArgumentSpec<Player, OfflinePlayer> playerArg; private final Argument<ScrowBukkitCC, OfflinePlayer> playerArg;
private final FriendRequestService requestService = ScrowAPI.friendRequestService(); private final FriendRequestService requestService = ScrowAPI.friendRequestService();
FriendRequestDeclineLiteral() { FriendRequestDeclineLiteral() {
playerArg = CommandArgumentSpec.builder("player", new OfflinePlayerArgumentType<Player>()) playerArg = Argument.builder("player", new OfflinePlayerArgumentType<ScrowBukkitCC>())
.build(); .build();
literal = Literal.<Player>builder("reject", "decline") literal = Literal.<ScrowBukkitCC>builder("reject", "decline")
.withArgument(playerArg) .withArgument(playerArg)
.withExecutor(this::declineFriendRequest) .withExecutor(this::declineFriendRequest)
.build(); .build();
} }
private CompletableFuture<?> declineFriendRequest(CommandContext<Player> ctx) { private CompletableFuture<?> declineFriendRequest(ScrowBukkitCC ctx) {
var other = ctx.getArg(playerArg); var other = ctx.getArg(playerArg);
return Tasks.supplyAsync(() -> return Tasks.supplyAsync(() ->
requestService.deleteFriendRequest(other.getUniqueId(), ctx.sender().getUniqueId())) requestService.deleteFriendRequest(other.getUniqueId(), ctx.player().getUniqueId()))
.thenSync(deleted -> { .thenSync(deleted -> {
if (!deleted) { if (!deleted) {
ctx.sender().sendMessage(ctx.style().err("There's no incoming friend request from " + other.getName() + ".")); ctx.player().sendMessage(ctx.style().err("There's no incoming friend request from " + other.getName() + "."));
return; return;
} }
ctx.sender().sendMessage(ctx.style().ok("Friend request declined.")); ctx.player().sendMessage(ctx.style().ok("Friend request declined."));
ScrowAPI.getPlayer(other).sendMessage(ctx.style().ok(ctx.sender().getName() + " has declined your friend request.")); ScrowAPI.getPlayer(other).sendMessage(ctx.style().ok(ctx.player().getName() + " has declined your friend request."));
}).toFuture(); }).toFuture();
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }
} }

View file

@ -1,8 +1,7 @@
package de.kentoj.scrow.bukkit.command.friends; package de.kentoj.scrow.bukkit.command.friends;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC;
import de.kentoj.kencommandapi.api.literal.Literal; import site.lab0x13.scrow.commands.model.literal.Literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import de.kentoj.scrow.bukkit.ScrowAPI; import de.kentoj.scrow.bukkit.ScrowAPI;
import de.kentoj.scrow.bukkit.scheduler.Tasks; import de.kentoj.scrow.bukkit.scheduler.Tasks;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
@ -11,7 +10,6 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -20,26 +18,26 @@ import static net.kyori.adventure.text.Component.text;
public final class FriendRequestsLiteral { public final class FriendRequestsLiteral {
private final Literal<Player> literal; private final Literal<ScrowBukkitCC> literal;
FriendRequestsLiteral() { FriendRequestsLiteral() {
literal = Literal.<Player>builder("requests") literal = Literal.<ScrowBukkitCC>builder("requests")
.withExecutor(this::displayFriendRequests) .withExecutor(this::displayFriendRequests)
.build(); .build();
} }
private CompletableFuture<?> displayFriendRequests(CommandContext<Player> ctx) { private CompletableFuture<?> displayFriendRequests(ScrowBukkitCC ctx) {
return Tasks.supplyAsync(() -> return Tasks.supplyAsync(() ->
ScrowAPI.friendRequestService().getFriendRequestsTo(ctx.sender().getUniqueId())) ScrowAPI.friendRequestService().getFriendRequestsTo(ctx.player().getUniqueId()))
.thenSync(list -> { .thenSync(list -> {
if (list.isEmpty()) { if (list.isEmpty()) {
ctx.sender().sendMessage(ctx.style().err("You have no friend requests.")); ctx.player().sendMessage(ctx.style().err("You have no friend requests."));
return; return;
} }
var requesters = list.stream() var requesters = list.stream()
.sorted(this::compareByAge) .sorted(this::compareByAge)
.map(fr -> Bukkit.getOfflinePlayer(fr.from()).getName()); .map(fr -> Bukkit.getOfflinePlayer(fr.from()).getName());
ctx.sender().sendMessage(formatList(ctx.style(), requesters.toList())); ctx.player().sendMessage(formatList(ctx.style(), requesters.toList()));
}).toFuture(); }).toFuture();
} }
@ -59,7 +57,7 @@ public final class FriendRequestsLiteral {
return message; return message;
} }
public Literal<Player> literal() { public Literal<ScrowBukkitCC> literal() {
return literal; return literal;
} }
} }

View file

@ -7,7 +7,7 @@ shared_deps = [
artifact("org.jetbrains:annotations"), artifact("org.jetbrains:annotations"),
artifact("com.google.guava:guava"), artifact("com.google.guava:guava"),
artifact("org.slf4j.slf4j:api"), artifact("org.slf4j.slf4j:api"),
artifact("de.kentoj.scrow:kencommandapi-core"), artifact("site.lab0x13.scrow:commands-common"),
artifact("net.kyori:adventure-api"), artifact("net.kyori:adventure-api"),
artifact("net.kyori:adventure-text-minimessage"), artifact("net.kyori:adventure-text-minimessage"),
artifact("org.jdbi:jdbi3-core"), artifact("org.jdbi:jdbi3-core"),

View file

@ -1,10 +1,10 @@
package de.kentoj.scrowlib.convention; package de.kentoj.scrowlib.convention;
import de.kentoj.kencommandapi.api.platform.MessageStyle;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import site.lab0x13.scrow.commands.model.literal.MessageStyle;
public record ScrowMessageStyle( public record ScrowMessageStyle(
Component prefix, Component prefix,

View file

@ -9,12 +9,14 @@ java_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//core/common", "//core/common",
artifact("site.lab0x13.scrow:commands-common"),
artifact("com.velocitypowered:velocity-api"), artifact("com.velocitypowered:velocity-api"),
artifact("de.kentoj.scrow:kencommandapi-velocity"), artifact("site.lab0x13.scrow:commands-velocity"),
], ],
exports = [ exports = [
"//core/common", "//core/common",
artifact("de.kentoj.scrow:kencommandapi-velocity"), artifact("site.lab0x13.scrow:commands-common"),
artifact("site.lab0x13.scrow:commands-velocity"),
artifact("org.mongodb:bson"), artifact("org.mongodb:bson"),
], ],
neverlink = True, neverlink = True,
@ -25,11 +27,13 @@ java_binary(
srcs = glob(["plugin/main/java/**/*.java", "api/main/java/**/*.java"]), srcs = glob(["plugin/main/java/**/*.java", "api/main/java/**/*.java"]),
create_executable = False, create_executable = False,
deps = [ deps = [
":api",
"//core/common", "//core/common",
artifact("site.lab0x13.scrow:commands-common"),
artifact("com.velocitypowered:velocity-api"), artifact("com.velocitypowered:velocity-api"),
artifact("com.google.inject:guice"), artifact("com.google.inject:guice"),
artifact("io.nats:jnats"), artifact("io.nats:jnats"),
artifact("de.kentoj.scrow:kencommandapi-velocity"), artifact("site.lab0x13.scrow:commands-velocity"),
artifact("org.mongodb:bson"), artifact("org.mongodb:bson"),
artifact("org.postgresql:postgresql"), artifact("org.postgresql:postgresql"),
artifact("com.google.code.gson:gson"), artifact("com.google.code.gson:gson"),

View file

@ -1,22 +1,21 @@
package de.kentoj.scrow.velocity; package de.kentoj.scrow.velocity;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import de.kentoj.kencommandapi.CommandAPI; import de.kentoj.scrow.velocity.commands.ScrowVelocityCC;
import de.kentoj.scrowlib.instancemanager.InstanceManager; import de.kentoj.scrowlib.instancemanager.InstanceManager;
import de.kentoj.scrowlib.messaging.MessageBroker; import de.kentoj.scrowlib.messaging.MessageBroker;
import de.kentoj.scrowlib.player.NetworkPlayer; import de.kentoj.scrowlib.player.NetworkPlayer;
import de.kentoj.scrowlib.player.NetworkPlayerFactory; import de.kentoj.scrowlib.player.NetworkPlayerFactory;
import org.jdbi.v3.core.Jdbi; import org.jdbi.v3.core.Jdbi;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import site.lab0x13.scrow.commands.velocity.ScrowCommands;
import java.util.UUID; import java.util.UUID;
public class ScrowAPI { public class ScrowAPI {
private static Jdbi jdbi; private static Jdbi jdbi;
private static CommandAPI<CommandSource> commands; private static ScrowCommands<ScrowVelocityCC> commands;
private static CommandAPI<Player> playerCommands;
private static MessageBroker messageBroker; private static MessageBroker messageBroker;
private static InstanceManager instanceManager; private static InstanceManager instanceManager;
private static NetworkPlayerFactory playerFactory; private static NetworkPlayerFactory playerFactory;
@ -30,32 +29,27 @@ public class ScrowAPI {
} }
@ApiStatus.Internal @ApiStatus.Internal
public static void initMessageBroker(MessageBroker messageBroker) { public static void setMessageBroker(MessageBroker messageBroker) {
ScrowAPI.messageBroker = messageBroker; ScrowAPI.messageBroker = messageBroker;
} }
@ApiStatus.Internal @ApiStatus.Internal
public static void initInstanceManager(InstanceManager instanceManager) { public static void setInstanceManager(InstanceManager instanceManager) {
ScrowAPI.instanceManager = instanceManager; ScrowAPI.instanceManager = instanceManager;
} }
@ApiStatus.Internal @ApiStatus.Internal
public static void initJdbi(Jdbi jdbi) { public static void setJdbi(Jdbi jdbi) {
ScrowAPI.jdbi = jdbi; ScrowAPI.jdbi = jdbi;
} }
@ApiStatus.Internal @ApiStatus.Internal
public static void initPlayerFactory(NetworkPlayerFactory playerFactory) { public static void setPlayerFactory(NetworkPlayerFactory playerFactory) {
ScrowAPI.playerFactory = playerFactory; ScrowAPI.playerFactory = playerFactory;
} }
@ApiStatus.Internal @ApiStatus.Internal
public static void initPlayerCommands(CommandAPI<Player> playerCommands) { public static void setCommands(ScrowCommands<ScrowVelocityCC> commands) {
ScrowAPI.playerCommands = playerCommands;
}
@ApiStatus.Internal
public static void initCommands(CommandAPI<CommandSource> commands) {
ScrowAPI.commands = commands; ScrowAPI.commands = commands;
} }
@ -63,14 +57,10 @@ public class ScrowAPI {
return jdbi; return jdbi;
} }
public static CommandAPI<CommandSource> commands() { public static ScrowCommands<ScrowVelocityCC> commands() {
return commands; return commands;
} }
public static CommandAPI<Player> playerCommands() {
return playerCommands;
}
public static MessageBroker messageBroker() { public static MessageBroker messageBroker() {
return messageBroker; return messageBroker;
} }

View file

@ -0,0 +1,19 @@
package de.kentoj.scrow.velocity.commands;
import com.velocitypowered.api.command.CommandSource;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import site.lab0x13.scrow.commands.velocity.VelocityCommandContext;
public class ScrowVelocityCC extends VelocityCommandContext<ScrowVelocityCC> {
private final ScrowMessageStyle style;
public ScrowVelocityCC(CommandSource sender, ScrowMessageStyle style) {
super(sender);
this.style = style;
}
public ScrowMessageStyle style() {
return style;
}
}

View file

@ -3,6 +3,7 @@ package de.kentoj.scrow.corevelocity;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.scrow.corevelocity.misc.OnlineCommand; import de.kentoj.scrow.corevelocity.misc.OnlineCommand;
@ -12,14 +13,12 @@ import de.kentoj.scrow.corevelocity.privmsg.MsgCommand;
import de.kentoj.scrow.corevelocity.privmsg.PrivMsgHandler; import de.kentoj.scrow.corevelocity.privmsg.PrivMsgHandler;
import de.kentoj.scrow.corevelocity.privmsg.ReplyCommand; import de.kentoj.scrow.corevelocity.privmsg.ReplyCommand;
import de.kentoj.scrow.corevelocity.serverregistration.ConsulV1ServerInstanceScanner; import de.kentoj.scrow.corevelocity.serverregistration.ConsulV1ServerInstanceScanner;
import de.kentoj.scrow.corevelocity.serverregistration.RegistrationTask; import de.kentoj.scrow.corevelocity.serverregistration.PlayerTryJoinLobbyListener;
import de.kentoj.scrow.corevelocity.serverregistration.ServerInstanceScanner;
import de.kentoj.scrow.velocity.ScrowAPI; import de.kentoj.scrow.velocity.ScrowAPI;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.scrowlib.utils.EnvUtils; import de.kentoj.scrowlib.utils.EnvUtils;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import site.lab0x13.scrow.commands.model.literal.MessageStyle;
import java.time.Duration;
@Plugin( @Plugin(
id = "corevelocity", id = "corevelocity",
@ -31,6 +30,7 @@ public final class CoreVelocityPlugin {
@Inject @Inject
private ProxyServer server; private ProxyServer server;
private ConsulV1ServerInstanceScanner instanceScanner;
@Subscribe @Subscribe
private void onInit(ProxyInitializeEvent __) { private void onInit(ProxyInitializeEvent __) {
@ -39,15 +39,21 @@ public final class CoreVelocityPlugin {
var lastTargetCache = new LastTargetCache(); var lastTargetCache = new LastTargetCache();
var style = new ScrowMessageStyle("MSG", NamedTextColor.LIGHT_PURPLE); var style = new ScrowMessageStyle("MSG", NamedTextColor.LIGHT_PURPLE);
var privmsgHelper = new PrivMsgHandler(style); var privmsgHelper = new PrivMsgHandler(style);
ScrowAPI.playerCommands().register(new ReplyCommand(server, lastTargetCache, privmsgHelper, style).rootLiteral()); ScrowAPI.commands().register(new ReplyCommand(server, lastTargetCache, privmsgHelper, style).rootLiteral());
ScrowAPI.playerCommands().register(new MsgCommand(server, lastTargetCache, privmsgHelper, style).rootLiteral()); ScrowAPI.commands().register(new MsgCommand(server, lastTargetCache, privmsgHelper, style).rootLiteral());
ScrowAPI.commands().register(new OnlineCommand(server).rootLiteral()); ScrowAPI.commands().register(new OnlineCommand(server).rootLiteral());
var sendPlayerWatchdog = new SendPlayerWatchdog(server); var sendPlayerWatchdog = new SendPlayerWatchdog(server);
sendPlayerWatchdog.listen(); sendPlayerWatchdog.listen();
ServerInstanceScanner instanceScanner = new ConsulV1ServerInstanceScanner(EnvUtils.envOrThrow("HOST_CONSUL")); instanceScanner = new ConsulV1ServerInstanceScanner(server, EnvUtils.envOrThrow("HOST_CONSUL"));
server.getScheduler().buildTask(this, new RegistrationTask(server, instanceScanner)) server.getEventManager().register(this, new PlayerTryJoinLobbyListener(server));
.repeat(Duration.ofSeconds(3)) server.getScheduler()
.buildTask(this, () -> instanceScanner.start())
.schedule(); .schedule();
} }
@Subscribe
private void onShutdown(ProxyShutdownEvent __) {
instanceScanner.close();
}
} }

View file

@ -1,10 +1,9 @@
package de.kentoj.scrow.corevelocity; package de.kentoj.scrow.corevelocity;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.CommandAPI;
import de.kentoj.scrow.velocity.ScrowAPI; import de.kentoj.scrow.velocity.ScrowAPI;
import de.kentoj.scrow.velocity.commands.ScrowVelocityCC;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.scrowlib.instancemanager.InstanceManagerImpl; import de.kentoj.scrowlib.instancemanager.InstanceManagerImpl;
import de.kentoj.scrowlib.messaging.InMemoyMessageBroker; import de.kentoj.scrowlib.messaging.InMemoyMessageBroker;
import de.kentoj.scrowlib.messaging.NatsMessageBroker; import de.kentoj.scrowlib.messaging.NatsMessageBroker;
@ -14,6 +13,7 @@ import io.nats.client.Options;
import org.jdbi.v3.core.Jdbi; import org.jdbi.v3.core.Jdbi;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import site.lab0x13.scrow.commands.velocity.ScrowCommands;
import java.io.IOException; import java.io.IOException;
import java.util.Properties; import java.util.Properties;
@ -30,13 +30,13 @@ public class ScrowAPISurface {
.server(natsHost) .server(natsHost)
.pedantic() .pedantic()
.build(); .build();
ScrowAPI.initMessageBroker(new NatsMessageBroker(Nats.connect(options))); ScrowAPI.setMessageBroker(new NatsMessageBroker(Nats.connect(options)));
} catch (IOException | InterruptedException e) { } catch (IOException | InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} else { } else {
log.error("HOST_NATS not set -> Using in-memory dummy message broker"); log.error("HOST_NATS not set -> Using in-memory dummy message broker");
ScrowAPI.initMessageBroker(new InMemoyMessageBroker()); ScrowAPI.setMessageBroker(new InMemoyMessageBroker());
} }
var hostPostgres = System.getenv().get("HOST_POSTGRES"); var hostPostgres = System.getenv().get("HOST_POSTGRES");
@ -45,7 +45,7 @@ public class ScrowAPISurface {
Class.forName("org.postgresql.Driver", true, ScrowAPISurface.class.getClassLoader()); Class.forName("org.postgresql.Driver", true, ScrowAPISurface.class.getClassLoader());
var props = new Properties(); var props = new Properties();
props.setProperty("user", "postgres"); props.setProperty("user", "postgres");
ScrowAPI.initJdbi(Jdbi.create(hostPostgres, props)); ScrowAPI.setJdbi(Jdbi.create(hostPostgres, props));
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -53,10 +53,9 @@ public class ScrowAPISurface {
log.error("HOST_POSTGRES not set -> Using in-memory database"); log.error("HOST_POSTGRES not set -> Using in-memory database");
} }
ScrowAPI.initInstanceManager(new InstanceManagerImpl(ScrowAPI.messageBroker())); ScrowAPI.setInstanceManager(new InstanceManagerImpl(ScrowAPI.messageBroker()));
ScrowAPI.initCommands(new CommandAPI<>(server, CommandSource.class)); ScrowAPI.setCommands(new ScrowCommands<>(server, (literal, sender) -> new ScrowVelocityCC(sender, (ScrowMessageStyle) literal.style())));
ScrowAPI.initPlayerCommands(new CommandAPI<>(server, Player.class)); ScrowAPI.setPlayerFactory(playerId -> new NetworkPlayerImpl(ScrowAPI.messageBroker(), playerId));
ScrowAPI.initPlayerFactory(playerId -> new NetworkPlayerImpl(ScrowAPI.messageBroker(), playerId));
} }
public static void destroyScrowAPI() { public static void destroyScrowAPI() {

View file

@ -1,38 +1,33 @@
package de.kentoj.scrow.corevelocity.misc; package de.kentoj.scrow.corevelocity.misc;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import de.kentoj.scrow.velocity.commands.ScrowVelocityCC;
import de.kentoj.kencommandapi.api.invocation.SyncCommandExecutor;
import de.kentoj.kencommandapi.api.literal.Literal;
import de.kentoj.kencommandapi.api.literal.RootLiteral;
import de.kentoj.scrowlib.convention.ScrowMessageStyle; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import site.lab0x13.scrow.commands.model.literal.Literal;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
public final class OnlineCommand { public final class OnlineCommand {
private final RootLiteral<CommandSource> rootLiteral; private final RootLiteral<ScrowVelocityCC> rootLiteral;
private final ScrowMessageStyle style = ScrowMessageStyle.GENERIC; private final ScrowMessageStyle style = ScrowMessageStyle.GENERIC;
private final ProxyServer server; private final ProxyServer server;
public OnlineCommand(ProxyServer server) { public OnlineCommand(ProxyServer server) {
this.server = server; this.server = server;
rootLiteral = Literal.<CommandSource>builder("online") rootLiteral = Literal.<ScrowVelocityCC>builder("online")
.withSyncExecutor(this::executeSync) .withSyncExecutor(this::executeSync)
.asRootLiteral(ScrowMessageStyle.GENERIC); .asRootLiteral(ScrowMessageStyle.GENERIC);
} }
private Result<Object, String> executeSync(CommandContext<CommandSource> ctx) { private void executeSync(ScrowVelocityCC ctx) {
int cnt = server.getPlayerCount(); int cnt = server.getPlayerCount();
var msg = cnt != 1 var msg = cnt != 1
? "There are currently " + cnt + " players online." ? "There are currently " + cnt + " players online."
: "There is currently 1 player online."; : "There is currently 1 player online.";
ctx.sender().sendMessage(style.ok(msg)); ctx.sender().sendMessage(style.ok(msg));
return Results.success(new Object());
} }
public RootLiteral<CommandSource> rootLiteral() { public RootLiteral<ScrowVelocityCC> rootLiteral() {
return rootLiteral; return rootLiteral;
} }
} }

View file

@ -1,54 +1,53 @@
package de.kentoj.scrow.corevelocity.privmsg; package de.kentoj.scrow.corevelocity.privmsg;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import de.kentoj.scrow.velocity.commands.ScrowVelocityCC;
import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import site.lab0x13.scrow.commands.model.argument.Argument;
import de.kentoj.kencommandapi.api.literal.Literal; import site.lab0x13.scrow.commands.model.argument.types.StringArgumentType;
import de.kentoj.kencommandapi.api.literal.RootLiteral; import site.lab0x13.scrow.commands.model.literal.Literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle; import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import de.kentoj.kencommandapi.type.PlayerArgumentType; import site.lab0x13.scrow.commands.velocity.type.PlayerArgumentType;
public class MsgCommand { public class MsgCommand {
private final RootLiteral<Player> rootLiteral; private final RootLiteral<ScrowVelocityCC> rootLiteral;
private final CommandArgumentSpec<Player, Player> targetArg; private final Argument<ScrowVelocityCC, Player> targetArg;
private final CommandArgumentSpec<Player, String> msgArg; private final Argument<ScrowVelocityCC, String> msgArg;
private final LastTargetCache cache; private final LastTargetCache cache;
private final PrivMsgHandler privMsgHandler; private final PrivMsgHandler privMsgHandler;
public MsgCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler helper, MessageStyle style) { public MsgCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler helper, ScrowMessageStyle style) {
this.cache = cache; this.cache = cache;
this.privMsgHandler = helper; this.privMsgHandler = helper;
targetArg = CommandArgumentSpec.builder("target", new PlayerArgumentType<Player>(server)).build(); targetArg = Argument.builder("target", new PlayerArgumentType<ScrowVelocityCC>(server)).build();
msgArg = CommandArgumentSpec.builder("msg", new StringArgumentType<Player>(true)).build(); msgArg = Argument.builder("msg", new StringArgumentType<ScrowVelocityCC>(true)).build();
rootLiteral = Literal.<Player>builder("msg", "w", "privmsg") rootLiteral = Literal.<ScrowVelocityCC>builder("msg", "w", "privmsg")
.withArgument(targetArg) .withArgument(targetArg)
.withArgument(msgArg) .withArgument(msgArg)
.withSyncExecutor(this::executeSync) .withSyncExecutor(this::executeSync)
.asRootLiteral(style); .asRootLiteral(style);
} }
private Result<Object, String> executeSync(CommandContext<Player> ctx) { private void executeSync(ScrowVelocityCC ctx) {
var target = ctx.getArg(targetArg); var target = ctx.getarg(targetArg);
var msg = ctx.getArg(msgArg); var msg = ctx.getArg(msgArg);
var isMessagingSelf = target.getUniqueId().equals(ctx.sender().getUniqueId()); var isMessagingSelf = target.getUniqueId().equals(ctx.player().getUniqueId());
if (isMessagingSelf) return Results.failure("You can't message yourself."); if (isMessagingSelf) {
ctx.player().sendMessage(ctx.style().err("You can't message yourself."));
cache.setLastTarget(ctx.sender().getUniqueId(), target.getUniqueId()); return;
privMsgHandler.handle(ctx.sender(), target, msg);
return Results.success(new Object());
} }
public RootLiteral<Player> rootLiteral() { cache.setLastTarget(ctx.player().getUniqueId(), target.getUniqueId());
privMsgHandler.handle(ctx.player(), target, msg);
}
public RootLiteral<ScrowVelocityCC> rootLiteral() {
return rootLiteral; return rootLiteral;
} }
} }

View file

@ -1,53 +1,51 @@
package de.kentoj.scrow.corevelocity.privmsg; package de.kentoj.scrow.corevelocity.privmsg;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results; import com.leakyabstractions.result.core.Results;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec; import de.kentoj.scrow.velocity.commands.ScrowVelocityCC;
import de.kentoj.kencommandapi.api.argument.types.StringArgumentType; import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import de.kentoj.kencommandapi.api.invocation.CommandContext; import site.lab0x13.scrow.commands.model.argument.Argument;
import de.kentoj.kencommandapi.api.literal.Literal; import site.lab0x13.scrow.commands.model.argument.types.StringArgumentType;
import de.kentoj.kencommandapi.api.literal.RootLiteral; import site.lab0x13.scrow.commands.model.literal.Literal;
import de.kentoj.kencommandapi.api.platform.MessageStyle; import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import de.kentoj.kencommandapi.type.PlayerArgumentType;
public class ReplyCommand { public class ReplyCommand {
private final RootLiteral<Player> rootLiteral; private final RootLiteral<ScrowVelocityCC> rootLiteral;
private final CommandArgumentSpec<Player, String> msgArg; private final Argument<ScrowVelocityCC, String> msgArg;
private final LastTargetCache cache; private final LastTargetCache cache;
private final ProxyServer server; private final ProxyServer server;
private final PrivMsgHandler privMsgHandler; private final PrivMsgHandler privMsgHandler;
public ReplyCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler privMsgHandler, MessageStyle style) { public ReplyCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler privMsgHandler, ScrowMessageStyle style) {
this.cache = cache; this.cache = cache;
this.server = server; this.server = server;
this.privMsgHandler = privMsgHandler; this.privMsgHandler = privMsgHandler;
msgArg = CommandArgumentSpec.builder("msg", new StringArgumentType<Player>(true)).build(); msgArg = Argument.builder("msg", new StringArgumentType<ScrowVelocityCC>(true)).build();
rootLiteral = Literal.<Player>builder("reply", "r") rootLiteral = Literal.<ScrowVelocityCC>builder("reply", "r")
.withArgument(msgArg) .withArgument(msgArg)
.withSyncExecutor(this::executeSync) .withSyncExecutor(this::executeSync)
.asRootLiteral(style); .asRootLiteral(style);
} }
private Result<Object, String> executeSync(CommandContext<Player> ctx) { private void executeSync(ScrowVelocityCC ctx) {
var targetId = cache.getLastTarget(ctx.sender().getUniqueId()); var targetId = cache.getLastTarget(ctx.player().getUniqueId());
if (targetId == null) if (targetId == null) {
return Results.failure("You didn't messaged anyone recently. Use /msg first"); ctx.player().sendMessage(ctx.style().err("You didn't messaged anyone recently. Use /msg first"));
return;
}
var target = server.getPlayer(targetId).orElse(null); var target = server.getPlayer(targetId).orElse(null);
var msg = ctx.getArg(msgArg); var msg = ctx.getArg(msgArg);
if (target == null) {
if (target == null) ctx.player().sendMessage(ctx.style().err("The player you last messaged is no longer online."));
return Results.failure("The player you last messaged is no longer online."); return;
}
privMsgHandler.handle(ctx.sender(), target, msg); privMsgHandler.handle(ctx.sender(), target, msg);
return Results.success(new Object());
} }
public RootLiteral<Player> rootLiteral() { public RootLiteral<ScrowVelocityCC> rootLiteral() {
return rootLiteral; return rootLiteral;
} }
} }

View file

@ -1,50 +1,105 @@
package de.kentoj.scrow.corevelocity.serverregistration; package de.kentoj.scrow.corevelocity.serverregistration;
import com.google.common.hash.Hashing; import com.google.common.hash.Hashing;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo; import com.velocitypowered.api.proxy.server.ServerInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient; import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.List;
import java.util.stream.Stream; import java.util.stream.StreamSupport;
public class ConsulV1ServerInstanceScanner implements ServerInstanceScanner, Closeable { public class ConsulV1ServerInstanceScanner implements Closeable {
private static final Logger log = LoggerFactory.getLogger("server registration");
private final ProxyServer server;
private final String consulUrl; private final String consulUrl;
private final HttpClient client; private final HttpClient client;
public ConsulV1ServerInstanceScanner(String consulUrl) { // see https://developer.hashicorp.com/consul/api-docs/features/blocking
private long lastIndex = -1;
public ConsulV1ServerInstanceScanner(ProxyServer server, String consulUrl) {
this.server = server;
this.consulUrl = consulUrl; this.consulUrl = consulUrl;
this.client = HttpClient.newHttpClient(); this.client = HttpClient.newHttpClient();
} }
@Override public void start() {
// FIXME query cluster-wide while (!Thread.currentThread().isInterrupted()) {
public Stream<ServerInfo> queryMinecraftServers() throws IOException, InterruptedException { try {
var url = consulUrl + "/v1/agent/services/?filter=" + URLEncoder.encode("\"minecraft\" in Tags", StandardCharsets.UTF_8); log.info("Querying servers...");
var knownServers = server.getAllServers().stream()
.map(RegisteredServer::getServerInfo)
.toList();
var currentServers = queryMinecraftServers();
registerNewServers(knownServers, currentServers);
unregisterDeadServers(knownServers, currentServers);
} catch (IOException e) {
throw new RuntimeException("failed querying Minecraft servers", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
private void unregisterDeadServers(List<ServerInfo> knownServers, List<ServerInfo> currentServers) {
var currentServerIds = currentServers.stream().map(ServerInfo::getName).toList();
knownServers.stream()
.filter(s -> !currentServerIds.contains(s.getName()))
.forEach(s -> {
server.unregisterServer(s);
log.info("Unregistered server {}", s.getName());
});
}
private void registerNewServers(List<ServerInfo> knownServers, List<ServerInfo> currentServers) {
var knownServerIds = knownServers.stream()
.map(ServerInfo::getName)
.toList();
currentServers.forEach(s -> {
if (knownServerIds.contains(s.getName()))
return;
server.registerServer(s);
log.info("registered server {}", s.getName());
});
}
private List<ServerInfo> queryMinecraftServers() throws IOException, InterruptedException {
var url = consulUrl + "/v1/health/service/minecraft?passing=true";
if (lastIndex >= 0)
url += "&index=" + lastIndex;
var request = HttpRequest.newBuilder(URI.create(url)) var request = HttpRequest.newBuilder(URI.create(url))
.GET() .GET()
.build(); .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString()); var response = client.send(request, HttpResponse.BodyHandlers.ofString());
var jsonResponse = JsonParser.parseString(response.body()).getAsJsonObject(); var jsonResponse = JsonParser.parseString(response.body()).getAsJsonArray();
return jsonResponse.entrySet().stream() lastIndex = response.headers().firstValueAsLong("X-Consul-Index").orElseThrow();
.map(Map.Entry::getValue)
.map(JsonElement::getAsJsonObject) return StreamSupport.stream(jsonResponse.spliterator(), false)
.map(j -> j.getAsJsonObject().get("Service").getAsJsonObject())
.map(service -> { .map(service -> {
var name = toServerName(service.get("Service").getAsString(), service.get("ID").getAsString()); var gamemodeName = service.get("Meta").getAsJsonObject().get("mode").getAsString();
var host = InetSocketAddress.createUnresolved(service.get("Address").getAsString(), var address = InetSocketAddress.createUnresolved(
service.get("Port").getAsInt()); service.get("Address").getAsString(), service.get("Port").getAsInt());
return new ServerInfo(name, host); var id = toServerName(gamemodeName, service.get("ID").getAsString());
}); return new ServerInfo(id, address);
})
.toList();
} }
private String toServerName(String serviceName, String id) { private String toServerName(String serviceName, String id) {
@ -54,7 +109,7 @@ public class ConsulV1ServerInstanceScanner implements ServerInstanceScanner, Clo
} }
@Override @Override
public void close() throws IOException { public void close() {
client.close(); client.close();
} }
} }

View file

@ -0,0 +1,22 @@
package de.kentoj.scrow.corevelocity.serverregistration;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.player.PlayerChooseInitialServerEvent;
import com.velocitypowered.api.proxy.ProxyServer;
public class PlayerTryJoinLobbyListener {
private final ProxyServer server;
public PlayerTryJoinLobbyListener(ProxyServer server) {
this.server = server;
}
@Subscribe
private void onChooseInitialServer(PlayerChooseInitialServerEvent ev) {
var lobby = server.getAllServers().stream()
.filter(n -> n.getServerInfo().getName().startsWith("lobby-"))
.findAny();
lobby.ifPresent(ev::setInitialServer);
}
}

View file

@ -1,29 +0,0 @@
package de.kentoj.scrow.corevelocity.serverregistration;
import com.velocitypowered.api.proxy.ProxyServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class RegistrationTask implements Runnable {
private static final Logger log = LoggerFactory.getLogger(RegistrationTask.class);
private final ProxyServer server;
private final ServerInstanceScanner watcher;
public RegistrationTask(ProxyServer server, ServerInstanceScanner watcher) {
this.server = server;
this.watcher = watcher;
}
@Override
public void run() {
try {
watcher.queryMinecraftServers().forEach(server::registerServer);
} catch (IOException | InterruptedException e) {
throw new RuntimeException("Failed querying available servers", e);
}
}
}

View file

@ -1,11 +0,0 @@
package de.kentoj.scrow.corevelocity.serverregistration;
import com.velocitypowered.api.proxy.server.ServerInfo;
import java.io.IOException;
import java.util.stream.Stream;
public interface ServerInstanceScanner {
Stream<ServerInfo> queryMinecraftServers() throws IOException, InterruptedException;
}

View file

@ -8,10 +8,7 @@
"com.google.j2objc:j2objc-annotations": 2003271689, "com.google.j2objc:j2objc-annotations": 2003271689,
"com.leakyabstractions:result": 1655671314, "com.leakyabstractions:result": 1655671314,
"com.leakyabstractions:result-api": -741055074, "com.leakyabstractions:result-api": -741055074,
"com.velocitypowered:velocity-api": 598211634, "com.velocitypowered:velocity-api": -596354110,
"de.kentoj.scrow:kencommandapi-bukkit": -2022880473,
"de.kentoj.scrow:kencommandapi-core": 112982056,
"de.kentoj.scrow:kencommandapi-velocity": 10985446,
"io.nats:jnats": 1953137185, "io.nats:jnats": 1953137185,
"io.papermc.paper:paper-api": -1677464331, "io.papermc.paper:paper-api": -1677464331,
"net.kyori:adventure-api": 1030187247, "net.kyori:adventure-api": 1030187247,
@ -24,87 +21,90 @@
"org.postgresql:postgresql": 524160786, "org.postgresql:postgresql": 524160786,
"org.slf4j:slf4j-api": -2005163028, "org.slf4j:slf4j-api": -2005163028,
"org.slf4j:slf4j-simple": 1999565066, "org.slf4j:slf4j-simple": 1999565066,
"repositories": 1054740373 "repositories": 1947988996,
"site.lab0x13.scrow:commands-bukkit": -62834474,
"site.lab0x13.scrow:commands-common": -2092194647,
"site.lab0x13.scrow:commands-velocity": 576878071
}, },
"__RESOLVED_ARTIFACTS_HASH": { "__RESOLVED_ARTIFACTS_HASH": {
"aopalliance:aopalliance": 1403132272, "aopalliance:aopalliance": 1434507571,
"com.github.ben-manes.caffeine:caffeine": 436159489, "com.github.ben-manes.caffeine:caffeine": 1421648842,
"com.google.code.findbugs:jsr305": 870839855, "com.google.code.findbugs:jsr305": 1862677076,
"com.google.code.gson:gson": -641501239, "com.google.code.gson:gson": 1379142432,
"com.google.errorprone:error_prone_annotations": 577932745, "com.google.errorprone:error_prone_annotations": 1910407674,
"com.google.guava:failureaccess": 1715931538, "com.google.guava:failureaccess": 1052373329,
"com.google.guava:guava": -24633313, "com.google.guava:guava": 809448928,
"com.google.guava:listenablefuture": 1079558157, "com.google.guava:listenablefuture": -777871306,
"com.google.inject:guice": 894286452, "com.google.inject:guice": -239057743,
"com.google.j2objc:j2objc-annotations": -1008747351, "com.google.j2objc:j2objc-annotations": 1851322138,
"com.leakyabstractions:result": -226801672, "com.leakyabstractions:result": -1858809852,
"com.leakyabstractions:result-api": -651535813, "com.leakyabstractions:result-api": -382801976,
"com.moandjiezana.toml:toml4j": 2067114335, "com.moandjiezana.toml:toml4j": 508480266,
"com.mojang:brigadier": 913620533, "com.mojang:brigadier": 913620533,
"com.velocitypowered:velocity-api": 965888822, "com.velocitypowered:velocity-api": -1579746067,
"com.velocitypowered:velocity-brigadier": -1261075963, "com.velocitypowered:velocity-brigadier": -1261075963,
"commons-codec:commons-codec": -1411194476, "commons-codec:commons-codec": 577559951,
"de.kentoj.scrow:kencommandapi-bukkit": -1110763167, "io.leangen.geantyref:geantyref": 277437211,
"de.kentoj.scrow:kencommandapi-core": 772231973, "io.nats:jnats": 76423921,
"de.kentoj.scrow:kencommandapi-velocity": 39000638, "io.papermc.paper:paper-api": -202770527,
"io.leangen.geantyref:geantyref": 669182600, "it.unimi.dsi:fastutil": 1795699813,
"io.nats:jnats": 549130756, "jakarta.inject:jakarta.inject-api": -689154986,
"io.papermc.paper:paper-api": -97577052, "javax.inject:javax.inject": 132675352,
"it.unimi.dsi:fastutil": 1739877374, "net.kyori:adventure-api": 951482800,
"jakarta.inject:jakarta.inject-api": 188991469,
"javax.inject:javax.inject": 698155243,
"net.kyori:adventure-api": 1766228173,
"net.kyori:adventure-bom": 1472851752, "net.kyori:adventure-bom": 1472851752,
"net.kyori:adventure-key": -1110227447, "net.kyori:adventure-key": 1723611760,
"net.kyori:adventure-text-logger-slf4j": -1327104502, "net.kyori:adventure-text-logger-slf4j": 1685198185,
"net.kyori:adventure-text-minimessage": 397844782, "net.kyori:adventure-text-minimessage": -1417678707,
"net.kyori:adventure-text-serializer-ansi": -1565160095, "net.kyori:adventure-text-serializer-ansi": -632322135,
"net.kyori:adventure-text-serializer-commons": -1221427884, "net.kyori:adventure-text-serializer-commons": 1111905531,
"net.kyori:adventure-text-serializer-gson": 115363333, "net.kyori:adventure-text-serializer-gson": -496856431,
"net.kyori:adventure-text-serializer-json": 799049496, "net.kyori:adventure-text-serializer-json": -2093423733,
"net.kyori:adventure-text-serializer-legacy": -1920918334, "net.kyori:adventure-text-serializer-legacy": -1926708191,
"net.kyori:adventure-text-serializer-plain": -791487701, "net.kyori:adventure-text-serializer-plain": 921342090,
"net.kyori:ansi": 997964596, "net.kyori:ansi": 967735279,
"net.kyori:option": -134523688, "net.kyori:option": 1219025611,
"net.luckperms:api": 476490203, "net.luckperms:api": -446182360,
"net.md-5:bungeecord-chat": 2047504207, "net.md-5:bungeecord-chat": -1895309617,
"org.apache.commons:commons-lang3": -1070155819, "org.apache.commons:commons-lang3": -1165348498,
"org.apache.httpcomponents:httpclient": -1780430011, "org.apache.httpcomponents:httpclient": 2047177206,
"org.apache.httpcomponents:httpcore": 67453319, "org.apache.httpcomponents:httpcore": -1947336196,
"org.apache.logging.log4j:log4j-api": -79106511, "org.apache.logging.log4j:log4j-api": 802684562,
"org.apache.maven.resolver:maven-resolver-api": -274344430, "org.apache.maven.resolver:maven-resolver-api": 1715320017,
"org.apache.maven.resolver:maven-resolver-connector-basic": -1819010895, "org.apache.maven.resolver:maven-resolver-connector-basic": 100049798,
"org.apache.maven.resolver:maven-resolver-impl": 988241953, "org.apache.maven.resolver:maven-resolver-impl": 421281398,
"org.apache.maven.resolver:maven-resolver-named-locks": -663305356, "org.apache.maven.resolver:maven-resolver-named-locks": -1957834767,
"org.apache.maven.resolver:maven-resolver-spi": 2054051643, "org.apache.maven.resolver:maven-resolver-spi": -1888553111,
"org.apache.maven.resolver:maven-resolver-transport-http": -1829861066, "org.apache.maven.resolver:maven-resolver-transport-http": -115815877,
"org.apache.maven.resolver:maven-resolver-util": 1240367164, "org.apache.maven.resolver:maven-resolver-util": -776482680,
"org.apache.maven:maven-artifact": -1775316664, "org.apache.maven:maven-artifact": 1332968914,
"org.apache.maven:maven-builder-support": -2045756754, "org.apache.maven:maven-builder-support": -162686027,
"org.apache.maven:maven-model": -1477170202, "org.apache.maven:maven-model": -1118138882,
"org.apache.maven:maven-model-builder": -312842796, "org.apache.maven:maven-model-builder": -918833418,
"org.apache.maven:maven-repository-metadata": -1092475520, "org.apache.maven:maven-repository-metadata": 506128932,
"org.apache.maven:maven-resolver-provider": -241093259, "org.apache.maven:maven-resolver-provider": -1075865842,
"org.bouncycastle:bcprov-lts8on": -8124988, "org.bouncycastle:bcprov-lts8on": -1005412513,
"org.checkerframework:checker-qual": -1521111878, "org.checkerframework:checker-qual": -684653783,
"org.codehaus.plexus:plexus-interpolation": -455118382, "org.codehaus.plexus:plexus-interpolation": 729223441,
"org.codehaus.plexus:plexus-utils": 37123609, "org.codehaus.plexus:plexus-utils": 1392395178,
"org.eclipse.sisu:org.eclipse.sisu.inject": 1305442139, "org.eclipse.sisu:org.eclipse.sisu.inject": -872173912,
"org.jdbi:jdbi3-core": -576523574, "org.jdbi:jdbi3-core": -488012747,
"org.jdbi:jdbi3-postgres": 419487850, "org.jdbi:jdbi3-postgres": -850946846,
"org.jetbrains:annotations": -1687668980, "org.jetbrains:annotations": 915498150,
"org.joml:joml": -564433831, "org.joml:joml": 387749226,
"org.jspecify:jspecify": 117231129, "org.jspecify:jspecify": -659362902,
"org.mongodb:bson": 1783866955, "org.mongodb:bson": 1197817272,
"org.postgresql:postgresql": -1607497519, "org.postgresql:postgresql": -790235150,
"org.slf4j:jcl-over-slf4j": 498129285, "org.slf4j:jcl-over-slf4j": 33502784,
"org.slf4j:slf4j-api": 500377983, "org.slf4j:slf4j-api": -1239545596,
"org.slf4j:slf4j-simple": -1055624668, "org.slf4j:slf4j-simple": 1518912321,
"org.spongepowered:configurate-core": -1474651178, "org.spongepowered:configurate-core": 784735666,
"org.spongepowered:configurate-gson": 284154998, "org.spongepowered:configurate-gson": -58090930,
"org.spongepowered:configurate-hocon": 1862397725, "org.spongepowered:configurate-hocon": -1372729557,
"org.spongepowered:configurate-yaml": -859469457, "org.spongepowered:configurate-yaml": -1304688999,
"org.yaml:snakeyaml": 1308413731 "org.yaml:snakeyaml": -1320689696,
"site.lab0x13.scrow:commands-bukkit": 1630649671,
"site.lab0x13.scrow:commands-common": 716919454,
"site.lab0x13.scrow:commands-velocity": -238206298
}, },
"artifacts": { "artifacts": {
"aopalliance:aopalliance": { "aopalliance:aopalliance": {
@ -193,9 +193,9 @@
}, },
"com.velocitypowered:velocity-api": { "com.velocitypowered:velocity-api": {
"shasums": { "shasums": {
"jar": "f5835a4a6191f909005b695ccc07b915e8dadeff4ab69c82a7cac1c9e4c8e6ce" "jar": "faf296a44b39573002590a2c7172c6adea2eb0f65760b452f78a75c9eb308d37"
}, },
"version": "4.1.0-20260803.131214-10" "version": "4.0.0"
}, },
"com.velocitypowered:velocity-brigadier": { "com.velocitypowered:velocity-brigadier": {
"shasums": { "shasums": {
@ -209,24 +209,6 @@
}, },
"version": "1.16.0" "version": "1.16.0"
}, },
"de.kentoj.scrow:kencommandapi-bukkit": {
"shasums": {
"jar": null
},
"version": "0.42-SNAPSHOT"
},
"de.kentoj.scrow:kencommandapi-core": {
"shasums": {
"jar": null
},
"version": "0.42-SNAPSHOT"
},
"de.kentoj.scrow:kencommandapi-velocity": {
"shasums": {
"jar": null
},
"version": "0.42-SNAPSHOT"
},
"io.leangen.geantyref:geantyref": { "io.leangen.geantyref:geantyref": {
"shasums": { "shasums": {
"jar": "386b535c079be7d65ddbe0ad9c00955155b7862225aa92b4c6553ab2b1ea95f9" "jar": "386b535c079be7d65ddbe0ad9c00955155b7862225aa92b4c6553ab2b1ea95f9"
@ -241,9 +223,9 @@
}, },
"io.papermc.paper:paper-api": { "io.papermc.paper:paper-api": {
"shasums": { "shasums": {
"jar": "b35f0f979731d960a6f9db1c0925eeb9f4511b1b1d8c60c2609dca8cfd2d1163" "jar": "167237534a28a64b22f2bca1af0809e1b0ee689e9d4b8653bdd17c4a4c7c4b17"
}, },
"version": "26.2.build.111-stable" "version": "26.2-rc-2.build.9-alpha"
}, },
"it.unimi.dsi:fastutil": { "it.unimi.dsi:fastutil": {
"shasums": { "shasums": {
@ -499,9 +481,9 @@
}, },
"org.jetbrains:annotations": { "org.jetbrains:annotations": {
"shasums": { "shasums": {
"jar": "ebc7aec252ed0c7d2d04c039d7f00e69f7b86b1f493c741d67b3ef31b986b054" "jar": "2037be378980d3ba9333e97955f3b2cde392aa124d04ca73ce2eee6657199297"
}, },
"version": "26.1.0" "version": "26.0.2-1"
}, },
"org.joml:joml": { "org.joml:joml": {
"shasums": { "shasums": {
@ -574,6 +556,24 @@
"jar": "e6682acf1ace77508ef13649cbf4f8d09d2cf5457bdb61d25ffb6ac0233d78dd" "jar": "e6682acf1ace77508ef13649cbf4f8d09d2cf5457bdb61d25ffb6ac0233d78dd"
}, },
"version": "2.5" "version": "2.5"
},
"site.lab0x13.scrow:commands-bukkit": {
"shasums": {
"jar": "88d8f281f3e00a94111268bce29d0e3df62376d2cbd72563ea2312874a2ac087"
},
"version": "1.2.0"
},
"site.lab0x13.scrow:commands-common": {
"shasums": {
"jar": "19c1c025e77ed9c9e44a20540041caab7c402568af94c7f8aec768586d4b41b3"
},
"version": "1.2.0"
},
"site.lab0x13.scrow:commands-velocity": {
"shasums": {
"jar": "02a0a1eff84f1757f5c42f58fda6851c807d95801af8623ffab9e5e482392489"
},
"version": "1.2.0"
} }
}, },
"conflict_resolution": { "conflict_resolution": {
@ -581,14 +581,13 @@
"com.google.guava:guava:31.0.1-jre": "com.google.guava:guava:33.6.0-jre", "com.google.guava:guava:31.0.1-jre": "com.google.guava:guava:33.6.0-jre",
"com.google.j2objc:j2objc-annotations:2.8": "com.google.j2objc:j2objc-annotations:3.1", "com.google.j2objc:j2objc-annotations:2.8": "com.google.j2objc:j2objc-annotations:3.1",
"io.leangen.geantyref:geantyref:1.3.16": "io.leangen.geantyref:geantyref:2.0.1", "io.leangen.geantyref:geantyref:1.3.16": "io.leangen.geantyref:geantyref:2.0.1",
"io.papermc.paper:paper-api:[26.2.build,)": "io.papermc.paper:paper-api:26.2.build.111-stable", "io.papermc.paper:paper-api:[26.2.build,)": "io.papermc.paper:paper-api:26.2-rc-2.build.9-alpha",
"net.kyori:adventure-key": "net.kyori:adventure-key:5.2.0", "net.kyori:adventure-bom:4.26.1": "net.kyori:adventure-bom:5.2.0",
"net.kyori:adventure-text-logger-slf4j": "net.kyori:adventure-text-logger-slf4j:5.2.0", "net.kyori:adventure-text-logger-slf4j": "net.kyori:adventure-text-logger-slf4j:5.2.0",
"net.kyori:adventure-text-serializer-ansi": "net.kyori:adventure-text-serializer-ansi:5.2.0", "net.kyori:adventure-text-serializer-ansi": "net.kyori:adventure-text-serializer-ansi:5.2.0",
"net.kyori:adventure-text-serializer-gson": "net.kyori:adventure-text-serializer-gson:5.2.0", "net.kyori:adventure-text-serializer-gson": "net.kyori:adventure-text-serializer-gson:5.2.0",
"net.kyori:adventure-text-serializer-legacy": "net.kyori:adventure-text-serializer-legacy:5.2.0", "net.kyori:adventure-text-serializer-legacy": "net.kyori:adventure-text-serializer-legacy:5.2.0",
"net.kyori:adventure-text-serializer-plain": "net.kyori:adventure-text-serializer-plain:5.2.0", "net.kyori:adventure-text-serializer-plain": "net.kyori:adventure-text-serializer-plain:5.2.0",
"org.jetbrains:annotations:26.0.2-1": "org.jetbrains:annotations:26.1.0",
"org.yaml:snakeyaml:2.2": "org.yaml:snakeyaml:2.5" "org.yaml:snakeyaml:2.2": "org.yaml:snakeyaml:2.5"
}, },
"dependencies": { "dependencies": {
@ -639,24 +638,6 @@
"org.spongepowered:configurate-yaml", "org.spongepowered:configurate-yaml",
"org.yaml:snakeyaml" "org.yaml:snakeyaml"
], ],
"de.kentoj.scrow:kencommandapi-bukkit": [
"de.kentoj.scrow:kencommandapi-core",
"io.papermc.paper:paper-api",
"org.jetbrains:annotations"
],
"de.kentoj.scrow:kencommandapi-core": [
"com.google.guava:guava",
"com.leakyabstractions:result",
"com.leakyabstractions:result-api",
"net.kyori:adventure-api",
"org.jetbrains:annotations",
"org.slf4j:slf4j-api"
],
"de.kentoj.scrow:kencommandapi-velocity": [
"com.velocitypowered:velocity-api",
"de.kentoj.scrow:kencommandapi-core",
"org.jetbrains:annotations"
],
"io.nats:jnats": [ "io.nats:jnats": [
"org.bouncycastle:bcprov-lts8on", "org.bouncycastle:bcprov-lts8on",
"org.jspecify:jspecify" "org.jspecify:jspecify"
@ -668,7 +649,6 @@
"it.unimi.dsi:fastutil", "it.unimi.dsi:fastutil",
"net.kyori:adventure-api", "net.kyori:adventure-api",
"net.kyori:adventure-bom", "net.kyori:adventure-bom",
"net.kyori:adventure-key",
"net.kyori:adventure-text-logger-slf4j", "net.kyori:adventure-text-logger-slf4j",
"net.kyori:adventure-text-minimessage", "net.kyori:adventure-text-minimessage",
"net.kyori:adventure-text-serializer-gson", "net.kyori:adventure-text-serializer-gson",
@ -823,6 +803,31 @@
], ],
"org.spongepowered:configurate-yaml": [ "org.spongepowered:configurate-yaml": [
"org.spongepowered:configurate-core" "org.spongepowered:configurate-core"
],
"site.lab0x13.scrow:commands-bukkit": [
"com.google.guava:guava",
"com.leakyabstractions:result",
"com.leakyabstractions:result-api",
"io.papermc.paper:paper-api",
"net.kyori:adventure-api",
"org.jetbrains:annotations",
"site.lab0x13.scrow:commands-common"
],
"site.lab0x13.scrow:commands-common": [
"com.google.guava:guava",
"com.leakyabstractions:result",
"com.leakyabstractions:result-api",
"net.kyori:adventure-api",
"org.jetbrains:annotations"
],
"site.lab0x13.scrow:commands-velocity": [
"com.google.guava:guava",
"com.leakyabstractions:result",
"com.leakyabstractions:result-api",
"com.velocitypowered:velocity-api",
"net.kyori:adventure-api",
"org.jetbrains:annotations",
"site.lab0x13.scrow:commands-common"
] ]
}, },
"packages": { "packages": {
@ -955,26 +960,6 @@
"org.apache.commons.codec.language.bm", "org.apache.commons.codec.language.bm",
"org.apache.commons.codec.net" "org.apache.commons.codec.net"
], ],
"de.kentoj.scrow:kencommandapi-bukkit": [
"de.kentoj.kencommandapi",
"de.kentoj.kencommandapi.suggestionprovider",
"de.kentoj.kencommandapi.type"
],
"de.kentoj.scrow:kencommandapi-core": [
"de.kentoj.kencommandapi.api",
"de.kentoj.kencommandapi.api.argument",
"de.kentoj.kencommandapi.api.argument.types",
"de.kentoj.kencommandapi.api.invocation",
"de.kentoj.kencommandapi.api.literal",
"de.kentoj.kencommandapi.api.platform",
"de.kentoj.kencommandapi.api.suggestion",
"de.kentoj.kencommandapi.internal"
],
"de.kentoj.scrow:kencommandapi-velocity": [
"de.kentoj.kencommandapi",
"de.kentoj.kencommandapi.suggestionprovider",
"de.kentoj.kencommandapi.type"
],
"io.leangen.geantyref:geantyref": [ "io.leangen.geantyref:geantyref": [
"io.leangen.geantyref" "io.leangen.geantyref"
], ],
@ -1908,10 +1893,28 @@
"org.yaml.snakeyaml.serializer", "org.yaml.snakeyaml.serializer",
"org.yaml.snakeyaml.tokens", "org.yaml.snakeyaml.tokens",
"org.yaml.snakeyaml.util" "org.yaml.snakeyaml.util"
],
"site.lab0x13.scrow:commands-bukkit": [
"site.lab0x13.scrow.commands.bukkit",
"site.lab0x13.scrow.commands.bukkit.suggestionprovider",
"site.lab0x13.scrow.commands.bukkit.type"
],
"site.lab0x13.scrow:commands-common": [
"site.lab0x13.scrow.commands",
"site.lab0x13.scrow.commands.model",
"site.lab0x13.scrow.commands.model.argument",
"site.lab0x13.scrow.commands.model.argument.types",
"site.lab0x13.scrow.commands.model.literal",
"site.lab0x13.scrow.commands.parser"
],
"site.lab0x13.scrow:commands-velocity": [
"site.lab0x13.scrow.commands.velocity",
"site.lab0x13.scrow.commands.velocity.suggestionprovider",
"site.lab0x13.scrow.commands.velocity.type"
] ]
}, },
"repositories": { "repositories": {
"https://repo1.maven.org/maven2/": [ "https://repo.maven.apache.org/maven2/": [
"aopalliance:aopalliance", "aopalliance:aopalliance",
"com.github.ben-manes.caffeine:caffeine", "com.github.ben-manes.caffeine:caffeine",
"com.google.code.findbugs:jsr305", "com.google.code.findbugs:jsr305",
@ -1983,9 +1986,9 @@
"org.yaml:snakeyaml" "org.yaml:snakeyaml"
], ],
"https://git.lab0x13.site/api/packages/scrow/maven/": [ "https://git.lab0x13.site/api/packages/scrow/maven/": [
"de.kentoj.scrow:kencommandapi-bukkit", "site.lab0x13.scrow:commands-bukkit",
"de.kentoj.scrow:kencommandapi-core", "site.lab0x13.scrow:commands-common",
"de.kentoj.scrow:kencommandapi-velocity" "site.lab0x13.scrow:commands-velocity"
], ],
"https://repo.papermc.io/repository/maven-public/": [ "https://repo.papermc.io/repository/maven-public/": [
"aopalliance:aopalliance", "aopalliance:aopalliance",

View file

@ -23,7 +23,7 @@ fetch_file(
fetch_file( fetch_file(
name = "luckperms", name = "luckperms",
filename = "LuckPerms.jar", filename = "LuckPerms.jar",
url = "https://download.luckperms.net/1652/bukkit/loader/LuckPerms-Bukkit-5.5.65.jar", url = "https://download.luckperms.net/1668/bukkit/loader/LuckPerms-Bukkit-5.5.81.jar",
) )
fetch_file( fetch_file(
name = "viaversion", name = "viaversion",