feat: code
This commit is contained in:
@@ -5,17 +5,22 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import io.papermc.paper.command.brigadier.Commands;
|
||||
import io.papermc.paper.dialog.Dialog;
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import online.mineroo.common.BindRequest;
|
||||
import online.mineroo.common.BindRequest.PlayerBindStatusEnum;
|
||||
import online.mineroo.common.MessageManager;
|
||||
import online.mineroo.paper.MinerooCore;
|
||||
import online.mineroo.paper.ProxyNetworkService;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class BindCommand {
|
||||
|
||||
private MinerooCore plugin;
|
||||
|
||||
public BindCommand(MinerooCore plugin) {
|
||||
@@ -23,28 +28,61 @@ public class BindCommand {
|
||||
}
|
||||
|
||||
public LiteralCommandNode<CommandSourceStack> build() {
|
||||
LiteralArgumentBuilder<CommandSourceStack> bind = Commands.literal("bind")
|
||||
.executes(context -> {
|
||||
CommandSourceStack sender = context.getSource();
|
||||
if (!sender.getSender().hasPermission("mineroo.admin.bind.server")) {
|
||||
return bindPlayer(context);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
LiteralArgumentBuilder<CommandSourceStack> bind = Commands.literal("bind").executes(context -> {
|
||||
CommandSourceStack sender = context.getSource();
|
||||
if (!sender.getSender().hasPermission("mineroo.admin.bind.server")) {
|
||||
return bindPlayer(context);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
bind.then(
|
||||
Commands.literal("server")
|
||||
.requires(sender -> sender.getSender().hasPermission("mineroo.admin.bind.server"))
|
||||
.executes(this::bindServer));
|
||||
bind.then(Commands.literal("server")
|
||||
.requires(sender -> sender.getSender().hasPermission("mineroo.admin.bind.server"))
|
||||
.executes(this::bindServer));
|
||||
|
||||
bind.then(
|
||||
Commands.literal("player").requires(sender -> sender.getSender().hasPermission("mineroo.admin.bind.server"))
|
||||
.executes(this::bindPlayer));
|
||||
bind.then(Commands.literal("player")
|
||||
.requires(sender -> sender.getSender().hasPermission("mineroo.admin.bind.server"))
|
||||
.executes(this::bindPlayer));
|
||||
|
||||
return bind.build();
|
||||
}
|
||||
|
||||
private int bindPlayer(CommandContext<CommandSourceStack> context) {
|
||||
Logger logger = this.plugin.getSLF4JLogger();
|
||||
MessageManager messageManager = this.plugin.getMessageManager();
|
||||
|
||||
if (context.getSource().getExecutor() instanceof Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
||||
if (uuid == null) {
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
try {
|
||||
this.plugin.getBindRequest().checkPlayerBindStatus(uuid, null).thenAccept(response -> {
|
||||
PlayerBindStatusEnum status = response.getStatus();
|
||||
|
||||
plugin.getSLF4JLogger().debug(status.toString());
|
||||
|
||||
if (status == PlayerBindStatusEnum.BOUND) {
|
||||
player.sendMessage(messageManager.get("info.bind.player.already-bound"));
|
||||
} else if (status == PlayerBindStatusEnum.NOT_BOUND) {
|
||||
Dialog dialog = RegistryAccess.registryAccess()
|
||||
.getRegistry(RegistryKey.DIALOG)
|
||||
.get(Key.key("mineroo:bind_user"));
|
||||
if (dialog == null) {
|
||||
logger.error("load user bind dialog failed.");
|
||||
player.sendMessage(messageManager.get("info.bind.player.dialog-undefined"));
|
||||
}
|
||||
|
||||
// TODO: Need a timeout check
|
||||
player.showDialog(dialog);
|
||||
}
|
||||
});
|
||||
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -58,13 +96,16 @@ public class BindCommand {
|
||||
|
||||
private void sendMotdTokenToVelocity(String motdToken) {
|
||||
// Send via any online player (Plugin Messaging must be attached to a player)
|
||||
org.bukkit.entity.Player player = org.bukkit.Bukkit.getOnlinePlayers().stream().findFirst().orElse(null);
|
||||
org.bukkit.entity.Player player =
|
||||
org.bukkit.Bukkit.getOnlinePlayers().stream().findFirst().orElse(null);
|
||||
if (player == null)
|
||||
return;
|
||||
com.google.common.io.ByteArrayDataOutput out = com.google.common.io.ByteStreams.newDataOutput();
|
||||
out.writeUTF(online.mineroo.common.ProtocolConstants.BIND_MOTD_TOKEN);
|
||||
out.writeUTF(motdToken);
|
||||
player.sendPluginMessage(plugin, online.mineroo.common.ProtocolConstants.PROTOCOL_CHANNEL, out.toByteArray());
|
||||
player.sendPluginMessage(
|
||||
plugin, online.mineroo.common.ProtocolConstants.PROTOCOL_CHANNEL, out.toByteArray()
|
||||
);
|
||||
}
|
||||
|
||||
private int bindServer(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
|
||||
@@ -73,9 +114,9 @@ public class BindCommand {
|
||||
Logger logger = plugin.getSLF4JLogger();
|
||||
BindRequest bindRequest = plugin.getBindRequest();
|
||||
try {
|
||||
|
||||
String address = plugin.getConfigObject().getServer().getServerBind().getAddress();
|
||||
String port = String.valueOf(plugin.getConfigObject().getServer().getServerBind().getPort());
|
||||
String port =
|
||||
String.valueOf(plugin.getConfigObject().getServer().getServerBind().getPort());
|
||||
if (plugin.getNetworkService() instanceof ProxyNetworkService) {
|
||||
address = "$hostname";
|
||||
port = "$port";
|
||||
@@ -84,8 +125,9 @@ public class BindCommand {
|
||||
// 1. Check binding status
|
||||
if (bindRequest.checkBindStatus(address, port).join()) {
|
||||
plugin.getMessageManager().get("command.bind.server.already-bound");
|
||||
context.getSource().getSender()
|
||||
.sendMessage(plugin.getMessageManager().get("command.bind.server.already-bound"));
|
||||
context.getSource().getSender().sendMessage(
|
||||
plugin.getMessageManager().get("command.bind.server.already-bound")
|
||||
);
|
||||
return;
|
||||
}
|
||||
// 2. Initiate MOTD verification
|
||||
@@ -94,7 +136,9 @@ public class BindCommand {
|
||||
String motdToken = bindRequest.getMotdToken();
|
||||
// Send MOTD token to Velocity
|
||||
applyMotdToken(motdToken);
|
||||
context.getSource().getSender().sendMessage(plugin.getMessageManager().get("command.bind.server.wait"));
|
||||
context.getSource().getSender().sendMessage(
|
||||
plugin.getMessageManager().get("command.bind.server.wait")
|
||||
);
|
||||
try {
|
||||
Thread.sleep(2 * 60 * 1000 + 5000); // 2m 5s
|
||||
} catch (InterruptedException e) {
|
||||
@@ -105,16 +149,23 @@ public class BindCommand {
|
||||
boolean success = false;
|
||||
int maxRetries = 3;
|
||||
for (int i = 1; i <= maxRetries; i++) {
|
||||
if (bindRequest.finalizeServerBinding(
|
||||
plugin.getConfigObject().getServer().getServerName(),
|
||||
plugin.getConfigObject().getServer().getDescription()).join()) {
|
||||
if (bindRequest
|
||||
.finalizeServerBinding(
|
||||
plugin.getConfigObject().getServer().getServerName(),
|
||||
plugin.getConfigObject().getServer().getDescription()
|
||||
)
|
||||
.join()) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
if (i < maxRetries) {
|
||||
context.getSource().getSender().sendMessage(
|
||||
plugin.getMessageManager().get("command.bind.server.retry", "current", String.valueOf(i), "max",
|
||||
String.valueOf(maxRetries)));
|
||||
context.getSource().getSender().sendMessage(plugin.getMessageManager().get(
|
||||
"command.bind.server.retry",
|
||||
"current",
|
||||
String.valueOf(i),
|
||||
"max",
|
||||
String.valueOf(maxRetries)
|
||||
));
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
@@ -123,18 +174,24 @@ public class BindCommand {
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
context.getSource().getSender().sendMessage(plugin.getMessageManager().get("command.bind.server.success"));
|
||||
context.getSource().getSender().sendMessage(
|
||||
plugin.getMessageManager().get("command.bind.server.success")
|
||||
);
|
||||
} else {
|
||||
context.getSource().getSender().sendMessage(plugin.getMessageManager().get("command.bind.server.failed"));
|
||||
context.getSource().getSender().sendMessage(
|
||||
plugin.getMessageManager().get("command.bind.server.failed")
|
||||
);
|
||||
}
|
||||
} else {
|
||||
context.getSource().getSender()
|
||||
.sendMessage(plugin.getMessageManager().get("command.bind.server.inital.failed"));
|
||||
context.getSource().getSender().sendMessage(
|
||||
plugin.getMessageManager().get("command.bind.server.inital.failed")
|
||||
);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error("Bind process error", ex);
|
||||
context.getSource().getSender().sendMessage(
|
||||
plugin.getMessageManager().get("command.bind.server.failed"));
|
||||
plugin.getMessageManager().get("command.bind.server.failed")
|
||||
);
|
||||
} finally {
|
||||
// After binding is complete, you can send a message to clear the MOTD token
|
||||
applyMotdToken(""); // Clear MOTD
|
||||
|
||||
@@ -3,6 +3,7 @@ package online.mineroo.paper.listeners;
|
||||
|
||||
import com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent;
|
||||
import io.papermc.paper.connection.PlayerConfigurationConnection;
|
||||
import io.papermc.paper.connection.PlayerGameConnection;
|
||||
import io.papermc.paper.dialog.Dialog;
|
||||
import io.papermc.paper.dialog.DialogResponseView;
|
||||
import io.papermc.paper.event.connection.configuration.AsyncPlayerConnectionConfigureEvent;
|
||||
@@ -14,6 +15,7 @@ import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -24,10 +26,10 @@ import online.mineroo.common.BindRequest.PlayerBindResponse;
|
||||
import online.mineroo.common.BindRequest.PlayerBindStatusEnum;
|
||||
import online.mineroo.paper.Config;
|
||||
import online.mineroo.paper.MinerooCore;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@NullMarked
|
||||
public class PlayerBindListener implements Listener {
|
||||
@@ -98,7 +100,7 @@ public class PlayerBindListener implements Listener {
|
||||
} else if (bindResponse.getStatus() == PlayerBindEnum.PENDING) {
|
||||
audience.closeDialog();
|
||||
String msg = "Binding request submitted!\nPlease go to Mineroo.Online to confirm the "
|
||||
+ "binding. After confirmation, please re-enter the server.";
|
||||
+ "binding. After confirmation, please re-enter the server.";
|
||||
connection.disconnect(Component.text(msg, NamedTextColor.GREEN));
|
||||
} else {
|
||||
audience.closeDialog();
|
||||
@@ -134,17 +136,40 @@ public class PlayerBindListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
void onHandleDialog(PlayerCustomClickEvent event) {
|
||||
Logger logger = plugin.getSLF4JLogger();
|
||||
|
||||
// Handle custom click only for configuration connection.
|
||||
if (!(event.getCommonConnection()
|
||||
instanceof PlayerConfigurationConnection configurationConnection)) {
|
||||
return;
|
||||
// Main handlr only use for PlayerConfigureationConnection,
|
||||
// Inside Block use for handle command bind request.
|
||||
if (event.getCommonConnection() instanceof PlayerGameConnection playerConn) {
|
||||
// handle command bind
|
||||
Player player = playerConn.getPlayer();
|
||||
UUID playerUuid = player.getUniqueId();
|
||||
this.PlayerBindProcess(event, playerUuid, response -> {
|
||||
if (response.getStatus() == PlayerBindEnum.PENDING) {
|
||||
player.sendMessage(this.plugin.getMessageManager().get("info.bind.player.pending"));
|
||||
} else if (response.getStatus() == PlayerBindEnum.BOUND) {
|
||||
player.sendMessage(this.plugin.getMessageManager().get("info.bind.player.success"));
|
||||
} else {
|
||||
String statusText =
|
||||
(response.getStatus() != null) ? response.getStatus().toString() : "UNKNOWN_STATUS";
|
||||
String messageText =
|
||||
(response.getMessage() != null) ? response.getMessage() : "Bind Failed";
|
||||
String fullMessage = "[ " + statusText + " ]: " + messageText;
|
||||
player.sendMessage(Component.text(fullMessage, NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
} else if (event.getCommonConnection()
|
||||
instanceof PlayerConfigurationConnection configurationConnection) {
|
||||
// handle required configuration event bind
|
||||
UUID playerUuid = configurationConnection.getProfile().getId();
|
||||
this.PlayerBindProcess(event, playerUuid, response -> {
|
||||
setConnectionJoinResult(playerUuid, response);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
UUID uniqueId = configurationConnection.getProfile().getId();
|
||||
|
||||
if (uniqueId == null) {
|
||||
private void PlayerBindProcess(
|
||||
PlayerCustomClickEvent event, UUID playerUuid, Consumer<PlayerBindResponse> callback
|
||||
) {
|
||||
if (playerUuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -157,32 +182,29 @@ public class PlayerBindListener implements Listener {
|
||||
}
|
||||
|
||||
String userEmail = view.getText("user_email");
|
||||
String playerName = "Unknown";
|
||||
|
||||
if (event.getCommonConnection() instanceof PlayerConfigurationConnection conn) {
|
||||
BindRequest bindRequest = plugin.getBindRequest();
|
||||
String playerName = conn.getProfile().getName();
|
||||
|
||||
bindRequest.PlayerBindRequest(userEmail, uniqueId, conn.getProfile().getName())
|
||||
.thenAccept(response -> { setConnectionJoinResult(uniqueId, response); })
|
||||
.exceptionally(ex -> {
|
||||
logger.error("Error occurred during bind request for " + playerName, ex);
|
||||
setConnectionJoinResult(
|
||||
uniqueId,
|
||||
BindRequest.createPlayerBindErrorResponse(
|
||||
"Network request failed, please contact the server administrator."
|
||||
)
|
||||
);
|
||||
return null;
|
||||
});
|
||||
;
|
||||
playerName = conn.getProfile().getName();
|
||||
} else if (event.getCommonConnection() instanceof PlayerGameConnection conn) {
|
||||
playerName = conn.getPlayer().getName();
|
||||
}
|
||||
|
||||
} else if (key.equals(Key.key("mineroo:bind_user/cancel"))) {
|
||||
// If it is the same as the agree one, set the result to true.
|
||||
BindRequest bindRequest = plugin.getBindRequest();
|
||||
|
||||
setConnectionJoinResult(
|
||||
uniqueId, BindRequest.createPlayerBindErrorResponse("Canceled the bind requirement")
|
||||
);
|
||||
bindRequest.PlayerBindRequest(userEmail, playerUuid, playerName)
|
||||
.thenAccept(response -> { callback.accept(response); })
|
||||
.exceptionally(ex -> {
|
||||
callback.accept(BindRequest.createPlayerBindErrorResponse(
|
||||
"Network request failed: " + ex.getMessage()
|
||||
));
|
||||
return null;
|
||||
});
|
||||
|
||||
} else if (key.equals(Key.key("mineroo:bind_user/cancel"))) {
|
||||
callback.accept(BindRequest.createPlayerBindErrorResponse(
|
||||
this.plugin.getMessageManager().getString("info.bind.player.canceled")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,13 @@ command.bind.server.success=<green>绑定成功!<green>
|
||||
command.bind.server.failed=<red>绑定失败。</red>
|
||||
command.bind.server.retry=<yellow>验证未通过,10 秒后重试 (<current>/<max>) ...</yellow>
|
||||
|
||||
## Player Bind [Both for screen and command]
|
||||
info.bind.player.already-bound=<yellow>当前用户已绑定</yellow>
|
||||
info.bind.player.dialog-undefined=<red>Dialog 加载失败,请联系管理员</red>
|
||||
info.bind.player.pending = "<green>绑定申请已发送,请登录 Mineroo 网站进行后续操作。</green>"
|
||||
info.bind.player.success = "<green>绑定成功!</green>"
|
||||
info.bind.player.canceled = "绑定请求已取消。"
|
||||
|
||||
# Reload Command
|
||||
command.reload.success=<green>配置文件重载成功!耗时 <time>ms</green>
|
||||
command.reload.failed=<red>配置文件重载失败,请查看控制台日志。</red>
|
||||
|
||||
Reference in New Issue
Block a user