.
This commit is contained in:
parent
670eba418c
commit
13ced30434
122 changed files with 223 additions and 12 deletions
31
core/velocity/BUILD
Normal file
31
core/velocity/BUILD
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
load("@rules_jvm_external//:defs.bzl", "artifact")
|
||||
load("@rules_java//java:java_library.bzl", "java_library")
|
||||
load("@rules_java//java:java_binary.bzl", "java_binary")
|
||||
|
||||
java_library(
|
||||
name = "api",
|
||||
srcs = glob(["api/main/java/**/*.java"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//core/common",
|
||||
artifact("com.velocitypowered:velocity-api"),
|
||||
artifact("de.kentoj.scrow:kencommandapi-velocity"),
|
||||
],
|
||||
exports = [
|
||||
"//core/common",
|
||||
artifact("de.kentoj.scrow:kencommandapi-velocity"),
|
||||
artifact("org.mongodb:bson"),
|
||||
],
|
||||
)
|
||||
|
||||
java_binary(
|
||||
name = "plugin",
|
||||
srcs = glob(["plugin/main/java/**/*.java"]),
|
||||
create_executable = False,
|
||||
deps = [
|
||||
":api",
|
||||
artifact("com.velocitypowered:velocity-api"),
|
||||
artifact("com.google.inject:guice"),
|
||||
artifact("io.nats:jnats"),
|
||||
],
|
||||
)
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package de.kentoj.scrow.velocity;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import de.kentoj.kencommandapi.CommandAPI;
|
||||
import de.kentoj.scrowlib.instancemanager.InstanceManager;
|
||||
import de.kentoj.scrowlib.messaging.MessageBroker;
|
||||
import de.kentoj.scrowlib.player.NetworkPlayer;
|
||||
import de.kentoj.scrowlib.player.NetworkPlayerFactory;
|
||||
import org.jdbi.v3.core.Jdbi;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ScrowAPI {
|
||||
|
||||
private static Jdbi jdbi;
|
||||
private static CommandAPI<CommandSource> commands;
|
||||
private static CommandAPI<Player> playerCommands;
|
||||
private static MessageBroker messageBroker;
|
||||
private static InstanceManager instanceManager;
|
||||
private static NetworkPlayerFactory playerFactory;
|
||||
|
||||
public static NetworkPlayer getPlayer(Player player) {
|
||||
return getPlayer(player.getUniqueId());
|
||||
}
|
||||
|
||||
public static NetworkPlayer getPlayer(UUID uuid) {
|
||||
return playerFactory.create(uuid);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void initMessageBroker(MessageBroker messageBroker) {
|
||||
ScrowAPI.messageBroker = messageBroker;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void initInstanceManager(InstanceManager instanceManager) {
|
||||
ScrowAPI.instanceManager = instanceManager;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void initJdbi(Jdbi jdbi) {
|
||||
ScrowAPI.jdbi = jdbi;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void initPlayerFactory(NetworkPlayerFactory playerFactory) {
|
||||
ScrowAPI.playerFactory = playerFactory;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void initPlayerCommands(CommandAPI<Player> playerCommands) {
|
||||
ScrowAPI.playerCommands = playerCommands;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void initCommands(CommandAPI<CommandSource> commands) {
|
||||
ScrowAPI.commands = commands;
|
||||
}
|
||||
|
||||
public static Jdbi jdbi() {
|
||||
return jdbi;
|
||||
}
|
||||
|
||||
public static CommandAPI<CommandSource> commands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
public static CommandAPI<Player> playerCommands() {
|
||||
return playerCommands;
|
||||
}
|
||||
|
||||
public static MessageBroker messageBroker() {
|
||||
return messageBroker;
|
||||
}
|
||||
|
||||
public static InstanceManager instanceManager() {
|
||||
return instanceManager;
|
||||
}
|
||||
|
||||
public static NetworkPlayerFactory playerFactory() {
|
||||
return playerFactory;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package de.kentoj.scrow.corevelocity;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import de.kentoj.scrow.corevelocity.misc.OnlineCommand;
|
||||
import de.kentoj.scrow.corevelocity.network.FriendNotifications;
|
||||
import de.kentoj.scrow.corevelocity.network.SendPlayerWatchdog;
|
||||
import de.kentoj.scrow.corevelocity.network.ServerRegisterWatchdog;
|
||||
import de.kentoj.scrow.corevelocity.privmsg.LastTargetCache;
|
||||
import de.kentoj.scrow.corevelocity.privmsg.MsgCommand;
|
||||
import de.kentoj.scrow.corevelocity.privmsg.PrivMsgHandler;
|
||||
import de.kentoj.scrow.corevelocity.privmsg.ReplyCommand;
|
||||
import de.kentoj.scrow.velocity.ScrowAPI;
|
||||
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@Plugin(
|
||||
id = "corevelocity",
|
||||
name = "CoreVelocity",
|
||||
authors = {"gradlehater57"},
|
||||
version = "0"
|
||||
)
|
||||
public final class CoreVelocityPlugin {
|
||||
|
||||
@Inject
|
||||
private ProxyServer server;
|
||||
|
||||
@Subscribe
|
||||
private void onInit(ProxyInitializeEvent __) {
|
||||
ScrowAPISurface.initScrowAPI(server);
|
||||
|
||||
var lastTargetCache = new LastTargetCache();
|
||||
var style = new ScrowMessageStyle("MSG", NamedTextColor.LIGHT_PURPLE);
|
||||
var privmsgHelper = new PrivMsgHandler(style);
|
||||
ScrowAPI.playerCommands().register(new ReplyCommand(server, lastTargetCache, privmsgHelper, style).rootLiteral());
|
||||
ScrowAPI.playerCommands().register(new MsgCommand(server, lastTargetCache, privmsgHelper, style).rootLiteral());
|
||||
ScrowAPI.commands().register(new OnlineCommand(server).rootLiteral());
|
||||
|
||||
var registerWatchdog = new ServerRegisterWatchdog(server);
|
||||
var sendPlayerWatchdog = new SendPlayerWatchdog(server);
|
||||
registerWatchdog.listen();
|
||||
sendPlayerWatchdog.listen();
|
||||
|
||||
server.getEventManager().register(this, new FriendNotifications());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package de.kentoj.scrow.corevelocity;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import de.kentoj.kencommandapi.CommandAPI;
|
||||
import de.kentoj.scrow.velocity.ScrowAPI;
|
||||
import de.kentoj.scrowlib.instancemanager.InstanceManagerImpl;
|
||||
import de.kentoj.scrowlib.messaging.InMemoyMessageBroker;
|
||||
import de.kentoj.scrowlib.messaging.NatsMessageBroker;
|
||||
import de.kentoj.scrowlib.player.NetworkPlayerImpl;
|
||||
import io.nats.client.Nats;
|
||||
import io.nats.client.Options;
|
||||
import org.jdbi.v3.core.Jdbi;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class ScrowAPISurface {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ScrowAPISurface.class);
|
||||
|
||||
public static void initScrowAPI(ProxyServer server) {
|
||||
var natsHost = System.getenv("HOST_NATS");
|
||||
if (natsHost != null) {
|
||||
try {
|
||||
var options = Options.builder()
|
||||
.server(natsHost)
|
||||
.pedantic()
|
||||
.build();
|
||||
ScrowAPI.initMessageBroker(new NatsMessageBroker(Nats.connect(options)));
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
log.error("HOST_NATS not set -> Using in-memory dummy message broker");
|
||||
ScrowAPI.initMessageBroker(new InMemoyMessageBroker());
|
||||
}
|
||||
|
||||
var hostPostgres = System.getenv().get("HOST_POSTGRES");
|
||||
if (hostPostgres != null) {
|
||||
try {
|
||||
Class.forName("org.postgresql.Driver", true, ScrowAPISurface.class.getClassLoader());
|
||||
var props = new Properties();
|
||||
props.setProperty("user", "postgres");
|
||||
ScrowAPI.initJdbi(Jdbi.create(hostPostgres, props));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
log.error("HOST_POSTGRES not set -> Using in-memory database");
|
||||
}
|
||||
|
||||
ScrowAPI.initInstanceManager(new InstanceManagerImpl(ScrowAPI.messageBroker()));
|
||||
ScrowAPI.initCommands(new CommandAPI<>(server, CommandSource.class));
|
||||
ScrowAPI.initPlayerCommands(new CommandAPI<>(server, Player.class));
|
||||
ScrowAPI.initPlayerFactory(playerId -> new NetworkPlayerImpl(ScrowAPI.messageBroker(), playerId));
|
||||
}
|
||||
|
||||
public static void destroyScrowAPI() {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
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 de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||
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;
|
||||
|
||||
public final class OnlineCommand {
|
||||
|
||||
private final RootLiteral<CommandSource> rootLiteral;
|
||||
private final ScrowMessageStyle style = ScrowMessageStyle.GENERIC;
|
||||
private final ProxyServer server;
|
||||
|
||||
public OnlineCommand(ProxyServer server) {
|
||||
this.server = server;
|
||||
rootLiteral = Literal.<CommandSource>builder("online")
|
||||
.withSyncExecutor(this::executeSync)
|
||||
.asRootLiteral(ScrowMessageStyle.GENERIC);
|
||||
}
|
||||
|
||||
private Result<Object, String> executeSync(CommandContext<CommandSource> ctx) {
|
||||
int cnt = server.getPlayerCount();
|
||||
var msg = cnt != 1
|
||||
? "There are currently " + cnt + " players online."
|
||||
: "There is currently 1 player online.";
|
||||
ctx.sender().sendMessage(style.ok(msg));
|
||||
return Results.success(new Object());
|
||||
}
|
||||
|
||||
public RootLiteral<CommandSource> rootLiteral() {
|
||||
return rootLiteral;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package de.kentoj.scrow.corevelocity.network;
|
||||
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
||||
import de.kentoj.scrow.velocity.ScrowAPI;
|
||||
import de.kentoj.scrowlib.messaging.MessageBroker;
|
||||
import org.bson.Document;
|
||||
|
||||
public class FriendNotifications {
|
||||
|
||||
private final MessageBroker messageBroker = ScrowAPI.messageBroker();
|
||||
|
||||
@Subscribe
|
||||
private void onConnect(PostLoginEvent ev) {
|
||||
messageBroker.publish("event.player.connect", new Document("playerId", ev.getPlayer().getUniqueId()));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onDisconnect(DisconnectEvent ev) {
|
||||
messageBroker.publish("event.player.disconnect", new Document("playerId", ev.getPlayer().getUniqueId()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package de.kentoj.scrow.corevelocity.network;
|
||||
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import de.kentoj.scrow.velocity.ScrowAPI;
|
||||
import de.kentoj.scrowlib.messaging.MessageBroker;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class SendPlayerWatchdog {
|
||||
|
||||
private final ExecutorService EXECUTOR = Executors.newVirtualThreadPerTaskExecutor();
|
||||
|
||||
private final MessageBroker messageBroker = ScrowAPI.messageBroker();
|
||||
private final ProxyServer server;
|
||||
|
||||
public SendPlayerWatchdog(ProxyServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void listen() {
|
||||
messageBroker.handle("player.send", doc -> sendPlayer(
|
||||
doc.get("playerId", UUID.class),
|
||||
doc.getString("handle")
|
||||
));
|
||||
}
|
||||
|
||||
private Future<Document> sendPlayer(UUID playerId, String handle) {
|
||||
return EXECUTOR.submit(() -> {
|
||||
var player = server.getPlayer(playerId).orElseThrow();
|
||||
var targetServer = server.getServer(handle).orElseThrow();
|
||||
var res = player.createConnectionRequest(targetServer).connect().get();
|
||||
if (!res.isSuccessful())
|
||||
throw new RuntimeException(res.getStatus().name());
|
||||
return new Document();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package de.kentoj.scrow.corevelocity.network;
|
||||
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import de.kentoj.scrow.velocity.ScrowAPI;
|
||||
import de.kentoj.scrowlib.messaging.MessageBroker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class ServerRegisterWatchdog {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ServerRegisterWatchdog.class);
|
||||
|
||||
private final MessageBroker messageBroker = ScrowAPI.messageBroker();
|
||||
private final ProxyServer server;
|
||||
|
||||
public ServerRegisterWatchdog(ProxyServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void listen() {
|
||||
messageBroker.subscribe("event.instance.up", doc -> {
|
||||
var handle = doc.getString("handle");
|
||||
var port = doc.getInteger("port");
|
||||
server.unregisterServer(new ServerInfo(handle, new InetSocketAddress(port)));
|
||||
log.info("registered server {}", handle);
|
||||
});
|
||||
|
||||
messageBroker.subscribe("event.instance.down", doc -> {
|
||||
var handle = doc.getString("handle");
|
||||
var port = doc.getInteger("port");
|
||||
server.unregisterServer(new ServerInfo(handle, new InetSocketAddress(port)));
|
||||
log.info("unregistered server {}", handle);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package de.kentoj.scrow.corevelocity.privmsg;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LastTargetCache {
|
||||
|
||||
private final Cache<@NotNull UUID, @NotNull UUID> cache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(Duration.ofMinutes(20))
|
||||
.build();
|
||||
|
||||
public @Nullable UUID getLastTarget(UUID uuid) {
|
||||
return cache.getIfPresent(uuid);
|
||||
}
|
||||
|
||||
public void setLastTarget(UUID uuid, UUID target) {
|
||||
cache.put(uuid, target);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
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.ProxyServer;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
|
||||
import de.kentoj.kencommandapi.api.argument.types.StringArgumentType;
|
||||
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.kencommandapi.type.PlayerArgumentType;
|
||||
|
||||
public class MsgCommand {
|
||||
|
||||
private final RootLiteral<Player> rootLiteral;
|
||||
private final CommandArgumentSpec<Player, Player> targetArg;
|
||||
private final CommandArgumentSpec<Player, String> msgArg;
|
||||
|
||||
private final LastTargetCache cache;
|
||||
private final PrivMsgHandler privMsgHandler;
|
||||
|
||||
public MsgCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler helper, MessageStyle style) {
|
||||
this.cache = cache;
|
||||
this.privMsgHandler = helper;
|
||||
|
||||
targetArg = CommandArgumentSpec.builder("target", new PlayerArgumentType<Player>(server)).build();
|
||||
msgArg = CommandArgumentSpec.builder("msg", new StringArgumentType<Player>(true)).build();
|
||||
|
||||
rootLiteral = Literal.<Player>builder("msg", "w", "privmsg")
|
||||
.withArgument(targetArg)
|
||||
.withArgument(msgArg)
|
||||
.withSyncExecutor(this::executeSync)
|
||||
.asRootLiteral(style);
|
||||
}
|
||||
|
||||
private Result<Object, String> executeSync(CommandContext<Player> ctx) {
|
||||
var target = ctx.getArg(targetArg);
|
||||
var msg = ctx.getArg(msgArg);
|
||||
|
||||
var isMessagingSelf = target.getUniqueId().equals(ctx.sender().getUniqueId());
|
||||
if (isMessagingSelf) return Results.failure("You can't message yourself.");
|
||||
|
||||
cache.setLastTarget(ctx.sender().getUniqueId(), target.getUniqueId());
|
||||
privMsgHandler.handle(ctx.sender(), target, msg);
|
||||
return Results.success(new Object());
|
||||
}
|
||||
|
||||
public RootLiteral<Player> rootLiteral() {
|
||||
return rootLiteral;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package de.kentoj.scrow.corevelocity.privmsg;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import static net.kyori.adventure.text.Component.text;
|
||||
|
||||
public class PrivMsgHandler {
|
||||
|
||||
private final ScrowMessageStyle style;
|
||||
|
||||
public PrivMsgHandler(ScrowMessageStyle style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public void handle(Player player, Player target, String msg) {
|
||||
target.sendMessage(style.ok(text(target.getUsername() + " -> You: ").append(Component.text(msg))));
|
||||
player.sendMessage(style.ok(text("You -> " + target.getUsername() + ": ").append(Component.text(msg))));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
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.ProxyServer;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgumentSpec;
|
||||
import de.kentoj.kencommandapi.api.argument.types.StringArgumentType;
|
||||
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.kencommandapi.type.PlayerArgumentType;
|
||||
|
||||
public class ReplyCommand {
|
||||
|
||||
private final RootLiteral<Player> rootLiteral;
|
||||
private final CommandArgumentSpec<Player, String> msgArg;
|
||||
|
||||
private final LastTargetCache cache;
|
||||
private final ProxyServer server;
|
||||
private final PrivMsgHandler privMsgHandler;
|
||||
|
||||
public ReplyCommand(ProxyServer server, LastTargetCache cache, PrivMsgHandler privMsgHandler, MessageStyle style) {
|
||||
this.cache = cache;
|
||||
this.server = server;
|
||||
this.privMsgHandler = privMsgHandler;
|
||||
|
||||
msgArg = CommandArgumentSpec.builder("msg", new StringArgumentType<Player>(true)).build();
|
||||
rootLiteral = Literal.<Player>builder("reply", "r")
|
||||
.withArgument(msgArg)
|
||||
.withSyncExecutor(this::executeSync)
|
||||
.asRootLiteral(style);
|
||||
}
|
||||
|
||||
private Result<Object, String> executeSync(CommandContext<Player> ctx) {
|
||||
var targetId = cache.getLastTarget(ctx.sender().getUniqueId());
|
||||
if (targetId == null)
|
||||
return Results.failure("You didn't messaged anyone recently. Use /msg first");
|
||||
var target = server.getPlayer(targetId).orElse(null);
|
||||
var msg = ctx.getArg(msgArg);
|
||||
|
||||
if (target == null)
|
||||
return Results.failure("The player you last messaged is no longer online.");
|
||||
privMsgHandler.handle(ctx.sender(), target, msg);
|
||||
return Results.success(new Object());
|
||||
}
|
||||
|
||||
public RootLiteral<Player> rootLiteral() {
|
||||
return rootLiteral;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue