diff --git a/src/main/java/emu/grasscutter/command/commands/BanCommand.java b/src/main/java/emu/grasscutter/command/commands/BanCommand.java new file mode 100644 index 000000000..e353f398e --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/BanCommand.java @@ -0,0 +1,87 @@ +package emu.grasscutter.command.commands; + +import java.util.List; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; + +import static emu.grasscutter.utils.Language.translate; + +@Command( + label = "ban", + usage = "ban [time] [reason]", + description = "commands.ban.description", + targetRequirement = Command.TargetRequirement.NONE +) +public final class BanCommand implements CommandHandler { + + private boolean banAccount(int uid, int time, String reason) { + Player player = Grasscutter.getGameServer().getPlayerByUid(uid, true); + + if (player == null) { + return false; + } + + Account account = player.getAccount(); + if (account == null) { + account = DatabaseHelper.getAccountByPlayerId(uid); + } + + account.setBanReason(reason); + account.setBanEndTime(time); + account.setBanStartTime((int) System.currentTimeMillis() / 1000); + account.setBanned(true); + account.save(); + + Player banUser = Grasscutter.getGameServer().getPlayerByUid(uid); + + if (banUser != null) { + banUser.getSession().close(); + } + return true; + } + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (args.size() < 1) { + CommandHandler.sendMessage(sender, translate(sender, "commands.ban.command_usage")); + return; + } + + int uid = 0; + int time = 2051190000; + String reason = "Reason not specified."; + + if (args.size() >= 1) { + try { + uid = Integer.parseInt(args.get(0)); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(sender, translate(sender, "commands.ban.invalid_player_id")); + return; + } + } + + if (args.size() >= 2) { + try { + time = Integer.parseInt(args.get(1)); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(sender, translate(sender, "commands.ban.invalid_time")); + return; + } + } + + if (args.size() >= 3) { + reason = args.get(2); + } + + if (banAccount(uid, time, reason)) { + CommandHandler.sendMessage(sender, translate(sender, "commands.ban.success")); + } else { + CommandHandler.sendMessage(sender, translate(sender, "commands.ban.failure")); + } + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/command/commands/UnBanCommand.java b/src/main/java/emu/grasscutter/command/commands/UnBanCommand.java new file mode 100644 index 000000000..40a14c5ae --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/UnBanCommand.java @@ -0,0 +1,66 @@ +package emu.grasscutter.command.commands; + +import java.util.List; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; + +import static emu.grasscutter.utils.Language.translate; + +@Command( + label = "unban", + usage = "unban ", + description = "commands.unban.description", + targetRequirement = Command.TargetRequirement.NONE +) +public final class UnBanCommand implements CommandHandler { + + private boolean unBanAccount(int uid) { + Player player = Grasscutter.getGameServer().getPlayerByUid(uid, true); + + if (player == null) { + return false; + } + + Account account = player.getAccount(); + + if (account == null) { + account = DatabaseHelper.getAccountByPlayerId(uid); + } + + account.setBanReason(null); + account.setBanEndTime(0); + account.setBanStartTime(0); + account.setBanned(false); + account.save(); + + return true; + } + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (args.size() < 1) { + CommandHandler.sendMessage(sender, translate(sender, "commands.unban.command_usage")); + return; + } + + int uid = 0; + + try { + uid = Integer.parseInt(args.get(0)); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(sender, translate(sender, "commands.unban.invalid_player_id")); + return; + } + + if (unBanAccount(uid)) { + CommandHandler.sendMessage(sender, translate(sender, "commands.unban.success")); + } else { + CommandHandler.sendMessage(sender, translate(sender, "commands.unban.failure")); + } + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/Account.java b/src/main/java/emu/grasscutter/game/Account.java index 3697dade5..840c10b79 100644 --- a/src/main/java/emu/grasscutter/game/Account.java +++ b/src/main/java/emu/grasscutter/game/Account.java @@ -28,6 +28,11 @@ public class Account { private String sessionKey; // Session token for dispatch server private List permissions; private Locale locale; + + private String banReason; + private int banEndTime; + private int banStartTime; + private boolean isBanned; @Deprecated public Account() { @@ -105,6 +110,46 @@ public class Account { this.locale = locale; } + public String getBanReason() { + return banReason; + } + + public void setBanReason(String banReason) { + this.banReason = banReason; + } + + public int getBanEndTime() { + return banEndTime; + } + + public void setBanEndTime(int banEndTime) { + this.banEndTime = banEndTime; + } + + public int getBanStartTime() { + return banStartTime; + } + + public void setBanStartTime(int banStartTime) { + this.banStartTime = banStartTime; + } + + public boolean isBanned() { + if (banEndTime > 0 && banEndTime < System.currentTimeMillis() / 1000) { + this.isBanned = false; + this.banEndTime = 0; + this.banStartTime = 0; + this.banReason = null; + save(); + } + + return isBanned; + } + + public void setBanned(boolean isBanned) { + this.isBanned = isBanned; + } + /** * The collection of a player's permissions. */ diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java index f48c40873..14f25a98c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java @@ -1,5 +1,7 @@ package emu.grasscutter.server.packet.send; +import java.util.Base64; + import com.google.protobuf.ByteString; import emu.grasscutter.net.packet.BasePacket; @@ -14,8 +16,25 @@ public class PacketGetPlayerTokenRsp extends BasePacket { super(PacketOpcodes.GetPlayerTokenRsp, true); this.setUseDispatchKey(true); - - GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() + + if (session.getPlayer().getAccount().isBanned()) { + byte[] bin = Base64.getDecoder().decode("5LiN54ixIEdDIOWNgeW5tOS6hu+8jOWNgeW5tOmHjOeUqOi/h+eahOavj+S4gOS4qiBQUyDpg73lg48gR0PjgII="); + + GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() + .setUid(session.getPlayer().getUid()) + .setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) + .setRetcode(21) + .setExtraBinData(ByteString.copyFrom(bin)) + .setMsg("FORBID_CHEATING_PLUGINS") + .setBlackUidEndTime(session.getPlayer().getAccount().getBanEndTime()) + .setRegPlatform(3) + .setCountryCode("US") + .setClientIpStr(session.getAddress().getAddress().getHostAddress()) + .build(); + + this.setData(p.toByteArray()); + } else { + GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() .setUid(session.getPlayer().getUid()) .setToken(session.getAccount().getToken()) .setAccountType(1) @@ -29,7 +48,8 @@ public class PacketGetPlayerTokenRsp extends BasePacket { .setRegPlatform(3) .setClientIpStr(session.getAddress().getAddress().getHostAddress()) .build(); - - this.setData(p.toByteArray()); + + this.setData(p.toByteArray()); + } } } diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index d349f0b3f..ef3dd1628 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -391,6 +391,21 @@ "success": "Changed climate type to %s with weather type %s.", "invalid_id": "Invalid ID.", "description": "Changes the weather" + }, + "ban": { + "description": "Ban a player", + "success": "Successful.", + "failure": "Failed, player not found.", + "invalid_time": "Unable to parse timestamp.", + "invalid_player_id": "Unable to parse player ID.", + "command_usage": "Usage: ban [timestamp] [reason]" + }, + "unban": { + "description": "Unban a player", + "success": "Successful.", + "failure": "Failed, player not found.", + "invalid_player_id": "Unable to parse player ID.", + "command_usage": "Usage: unban " } }, "gacha": { diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index e14bb367d..849c13cb2 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -391,6 +391,21 @@ "success": "已更改气候类型为 %s,天气类型为 %s。", "invalid_id": "无效的ID。", "description": "更改天气" + }, + "ban": { + "description": "封禁玩家", + "success": "封禁玩家成功。", + "failure": "封禁玩家失败,因为无法获取到其账户。", + "invalid_time": "无法解析时间戳。", + "invalid_player_id": "无法解析玩家 ID。", + "command_usage": "用法:ban <玩家ID> [时间] [原因]" + }, + "unban": { + "description": "取消玩家的封禁", + "success": "取消玩家的封禁成功。", + "failure": "取消玩家的封禁失败,因为无法获取到其账户。", + "invalid_player_id": "无法解析玩家 ID。", + "command_usage": "用法:unban <玩家ID>" } }, "gacha": {