Rewritten

Command:
- handle
- report
Added new
Command:
- notice
This commit is contained in:
2025-11-08 11:18:08 +08:00
parent 53fb52e294
commit 6f489eb660
8 changed files with 643 additions and 39 deletions

View File

@@ -8,6 +8,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.xgqy.survival.command.CommandTabExecutor;
import org.xgqy.survival.command.DqshopCommandExecutor; import org.xgqy.survival.command.DqshopCommandExecutor;
import org.xgqy.survival.command.FriendCommandExecutor; import org.xgqy.survival.command.FriendCommandExecutor;
import org.xgqy.survival.command.HandleCommandExecutor; import org.xgqy.survival.command.HandleCommandExecutor;
@@ -17,6 +18,7 @@ import org.xgqy.survival.command.InventoryCommandExecutor;
import org.xgqy.survival.command.KillCommandExecutor; import org.xgqy.survival.command.KillCommandExecutor;
import org.xgqy.survival.command.LandCommandExecutor; import org.xgqy.survival.command.LandCommandExecutor;
import org.xgqy.survival.command.LoginCommandExecutor; import org.xgqy.survival.command.LoginCommandExecutor;
import org.xgqy.survival.command.NoticeCommandExecutor;
import org.xgqy.survival.command.PartyCommandExecutor; import org.xgqy.survival.command.PartyCommandExecutor;
import org.xgqy.survival.command.PcCommandExecutor; import org.xgqy.survival.command.PcCommandExecutor;
import org.xgqy.survival.command.PointCommandExecutor; import org.xgqy.survival.command.PointCommandExecutor;
@@ -41,6 +43,7 @@ import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -274,9 +277,26 @@ public final class Survival extends JavaPlugin {
getCommand("selfkill").setExecutor(new KillCommandExecutor(this)); getCommand("selfkill").setExecutor(new KillCommandExecutor(this));
getCommand("land").setExecutor(new LandCommandExecutor(this)); getCommand("land").setExecutor(new LandCommandExecutor(this));
getCommand("qd").setExecutor(new LandCommandExecutor(this)); getCommand("qd").setExecutor(new LandCommandExecutor(this));
getLogger().info("Survival插件已启用信用分持久化功能加载完成"); getCommand("notice").setExecutor(new NoticeCommandExecutor(this));
CommandTabExecutor tabExecutor = new CommandTabExecutor();
registerTabCompleter(tabExecutor);
} }
private void registerTabCompleter(CommandTabExecutor completer) {
// 所有需要补全的命令列表
List<String> commands = Arrays.asList(
"handle", "tpacc", "friend", "party", "settag", "teleport",
"point", "land", "pvp", "help", "tag", "hub", "selfkill",
"qd", "reg", "login", "msg", "inventory", "notice"
);
for (String cmd : commands) {
if (getCommand(cmd) != null) {
getCommand(cmd).setTabCompleter(completer);
} else {
getLogger().warning("命令 " + cmd + " 未在 plugin.yml 中配置,无法注册补全器!");
}
}
}
@Override @Override
public void onDisable() { public void onDisable() {
// 保存玩家标签数据 // 保存玩家标签数据

View File

@@ -0,0 +1,314 @@
package org.xgqy.survival.command;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 统一命令补全器:整合所有命令的自动补全逻辑
*/
public class CommandTabExecutor implements TabCompleter {
// 支持的颜色列表(用于 settag 命令)
private static final Map<String, String> COLOR_MAP = new HashMap<>();
static {
// 初始化颜色映射(与 SetTagCommandExecutor 对应)
COLOR_MAP.put("black", "");
COLOR_MAP.put("dark_blue", "");
COLOR_MAP.put("dark_green", "");
COLOR_MAP.put("dark_aqua", "");
COLOR_MAP.put("dark_red", "");
COLOR_MAP.put("dark_purple", "");
COLOR_MAP.put("gold", "");
COLOR_MAP.put("gray", "");
COLOR_MAP.put("dark_gray", "");
COLOR_MAP.put("blue", "");
COLOR_MAP.put("green", "");
COLOR_MAP.put("aqua", "");
COLOR_MAP.put("red", "");
COLOR_MAP.put("light_purple", "");
COLOR_MAP.put("yellow", "");
COLOR_MAP.put("white", "");
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
List<String> completions = new ArrayList<>();
String cmdName = command.getName().toLowerCase();
// 根据命令名称分发补全逻辑
switch (cmdName) {
case "handle":
completions = handleTabComplete(args);
break;
case "tpacc":
completions = tpAccTabComplete(args);
break;
case "friend":
completions = friendTabComplete(sender, args);
break;
case "party":
completions = partyTabComplete(sender, args);
break;
case "settag":
completions = setTagTabComplete(sender, args);
break;
case "teleport":
completions = teleportTabComplete(sender, args);
break;
case "point":
case "land":
completions = pointLandTabComplete(sender, args);
break;
case "pvp":
case "help":
case "tag":
case "hub":
case "selfkill":
case "qd":
case "reg":
case "login":
case "msg":
case "inventory":
case "notice":
completions = simpleCommandTabComplete(sender, cmdName, args);
break;
default:
// 未知命令返回空
completions.clear();
break;
}
return completions;
}
// ------------------------------ 各命令补全逻辑 ------------------------------
/**
* /handle 命令补全(处理举报)
*/
private List<String> handleTabComplete(String[] args) {
List<String> completions = new ArrayList<>();
// 一级参数no/point/12h/1d/3d/7d/14d/1mo/3mo/1y/ban
if (args.length == 1) {
List<String> options = Arrays.asList(
"no", "point", "12h", "1d", "3d", "7d", "14d",
"1mo", "3mo", "1y", "ban"
);
completions = filterMatches(options, args[0]);
}
// 二级参数ban 后补全天数提示
else if (args.length == 2 && "ban".equalsIgnoreCase(args[0])) {
completions.add("<天数>");
}
return completions;
}
/**
* /tpacc 命令补全(传送申请处理)
*/
private List<String> tpAccTabComplete(String[] args) {
List<String> completions = new ArrayList<>();
// 一级参数accept/deny/tome/detome
if (args.length == 1) {
List<String> options = Arrays.asList("accept", "deny", "tome", "detome");
completions = filterMatches(options, args[0]);
}
return completions;
}
/**
* /friend 命令补全(好友操作)
*/
private List<String> friendTabComplete(CommandSender sender, String[] args) {
List<String> completions = new ArrayList<>();
if (!(sender instanceof Player)) return completions;
// 一级参数add/allow/deny/remove/list
if (args.length == 1) {
List<String> options = Arrays.asList("add", "allow", "deny", "remove", "list");
completions = filterMatches(options, args[0]);
}
// 二级参数:操作后补全在线玩家名
else if (args.length == 2 && Arrays.asList("add", "allow", "deny", "remove").contains(args[0].toLowerCase())) {
completions = getOnlinePlayers(args[1]);
}
return completions;
}
/**
* /party 命令补全(队伍操作)
*/
private List<String> partyTabComplete(CommandSender sender, String[] args) {
List<String> completions = new ArrayList<>();
if (!(sender instanceof Player)) return completions;
// 一级参数create/quit/join/list/kick/ban/disband/help
if (args.length == 1) {
List<String> options = Arrays.asList(
"create", "quit", "join", "list", "kick", "ban", "disband", "help"
);
completions = filterMatches(options, args[0]);
}
// 二级参数join/kick/ban 后补全在线玩家名
else if (args.length == 2 && Arrays.asList("join", "kick", "ban").contains(args[0].toLowerCase())) {
completions = getOnlinePlayers(args[1]);
}
return completions;
}
/**
* /settag 命令补全(设置标签)
*/
private List<String> setTagTabComplete(CommandSender sender, String[] args) {
List<String> completions = new ArrayList<>();
// 权限校验:无权限则不显示补全
if (!sender.hasPermission("permission.settag")) return completions;
// 一级参数:在线玩家名
if (args.length == 1) {
completions = getOnlinePlayers(args[1]);
}
// 二级参数add/remove/check
else if (args.length == 2) {
List<String> options = Arrays.asList("add", "remove", "check");
completions = filterMatches(options, args[1]);
}
// 三级参数add/check/remove 后补全标签内容
else if (args.length == 3) {
String op = args[1].toLowerCase();
if (Arrays.asList("add", "check", "remove").contains(op)) {
completions.add("<标签内容>");
}
}
// 四级参数add/check 后补全颜色
else if (args.length == 4) {
String op = args[1].toLowerCase();
if (Arrays.asList("add", "check").contains(op)) {
completions = filterMatches(new ArrayList<>(COLOR_MAP.keySet()), args[3]);
}
}
// 五级参数add 后补全天数
else if (args.length == 5 && "add".equalsIgnoreCase(args[1])) {
completions.add("<天数(999=永久)>");
}
return completions;
}
/**
* /teleport 命令补全(传送)
*/
private List<String> teleportTabComplete(CommandSender sender, String[] args) {
List<String> completions = new ArrayList<>();
if (!(sender instanceof Player)) return completions;
// 一级参数:在线玩家名
if (args.length == 1) {
completions = getOnlinePlayers(args[0]);
}
// 二级参数me
else if (args.length == 2) {
if ("me".startsWith(args[1].toLowerCase())) {
completions.add("me");
}
}
return completions;
}
/**
* /point /land 命令补全(信用分/领地操作)
*/
private List<String> pointLandTabComplete(CommandSender sender, String[] args) {
List<String> completions = new ArrayList<>();
if (!(sender instanceof Player)) return completions;
// 一级参数:在线玩家名
if (args.length == 1) {
completions = getOnlinePlayers(args[0]);
}
// 二级参数set/add/remove
else if (args.length == 2) {
List<String> options = Arrays.asList("set", "add", "remove");
completions = filterMatches(options, args[1]);
}
// 三级参数:数值提示
else if (args.length == 3) {
completions.add("<数值>");
}
return completions;
}
/**
* 简单命令补全pvp/help/tag/hub/selfkill/qd/reg/login/msg/inventory/notice
*/
private List<String> simpleCommandTabComplete(CommandSender sender, String cmdName, String[] args) {
List<String> completions = new ArrayList<>();
if (!(sender instanceof Player)) return completions;
switch (cmdName) {
// /reg <密码> <确认密码>
case "reg":
if (args.length == 1) completions.add("<密码>");
else if (args.length == 2) completions.add("<确认密码>");
break;
// /login <密码>
case "login":
if (args.length == 1) completions.add("<密码>");
break;
// /msg <玩家名> <消息>
case "msg":
if (args.length == 1) completions = getOnlinePlayers(args[0]);
else if (args.length == 2) completions.add("<消息内容>");
break;
// /inventory <玩家名>
case "inventory":
if (args.length == 1) completions = getOnlinePlayers(args[0]);
break;
// /notice <玩家名>
case "notice":
if (args.length == 1) completions = getOnlinePlayers(args[0]);
break;
// 无参数命令pvp/help/tag/hub/selfkill/qd
default:
completions.clear();
break;
}
return completions;
}
// ------------------------------ 通用工具方法 ------------------------------
/**
* 获取在线玩家名列表(支持前缀匹配)
*/
private static List<String> getOnlinePlayers(String partialName) {
List<String> playerNames = new ArrayList<>();
for (Player player : Bukkit.getOnlinePlayers()) {
playerNames.add(player.getName());
}
return filterMatches(playerNames, partialName);
}
/**
* 从候选列表中过滤出匹配输入前缀的选项(不区分大小写)
*/
private static List<String> filterMatches(List<String> candidates, String partial) {
String lowerPartial = partial.toLowerCase();
return candidates.stream()
.filter(candidate -> candidate.toLowerCase().startsWith(lowerPartial))
.collect(Collectors.toList());
}
}

View File

@@ -11,10 +11,11 @@ import org.jetbrains.annotations.NotNull;
import org.xgqy.survival.Survival; import org.xgqy.survival.Survival;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
public class HandleCommandExecutor implements CommandExecutor { public class HandleCommandExecutor implements CommandExecutor {
private Survival plugin; private final Survival plugin;
public HandleCommandExecutor(Survival plugin) { public HandleCommandExecutor(Survival plugin) {
this.plugin = plugin; this.plugin = plugin;
@@ -22,37 +23,254 @@ public class HandleCommandExecutor implements CommandExecutor {
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (sender instanceof Player) { // 1. 校验执行者必须是在线管理员OP
if (args.length != 1) { if (!(sender instanceof Player admin)) {
sender.sendMessage(ChatColor.RED + "无效语法 :\n/handle <player> - 处理玩家\n/handle list - 待处理列表"); sender.sendMessage(ChatColor.RED + "只有游戏内管理员可执行此处理命令");
return true; return true;
} }
if (args[0].equals("list")) { if (!admin.isOp()) {
sender.sendMessage(ChatColor.YELLOW + "---------------------------------------\n" + ChatColor.GREEN + plugin.banlist.get(sender) + ChatColor.YELLOW + " 原因: ", ChatColor.RED + plugin.banreason.get(plugin.banlist.get(sender)) + ChatColor.YELLOW + "\n---------------------------------------\n"); admin.sendMessage(ChatColor.RED + "权限不足!仅管理员可处理举报");
return true;
}
if (!Bukkit.getPlayer(args[0]).isOnline() && !args[0].equals("list") && Bukkit.getPlayer(args[0]) != plugin.banlist.get((Player) sender)) {
sender.sendMessage(ChatColor.RED + "玩家不在线");
return true; return true;
} }
BanList banlis = Bukkit.getBanList(BanList.Type.NAME); // 2. 校验管理员是否有待处理的举报
long dur = 24 * 60 * 60 * 1000L; Player target = plugin.banlist.get(admin);
Date expdat = new Date(System.currentTimeMillis() + dur); String reportReason = plugin.banreason.get(target);
plugin.banreason.put(plugin.banlist.get(sender), null); if (target == null || !target.isOnline()) {
plugin.banlist.put((Player) sender, null); admin.sendMessage(ChatColor.RED + "无待处理的举报玩家,或该玩家已离线");
sender.sendMessage(ChatColor.YELLOW + "处理完成\n"); return true;
for (Player repo : plugin.reportlist.get(Bukkit.getPlayer(args[0]))) {
repo.sendMessage(ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | " +
ChatColor.GREEN + "\n 您举报的玩家 " + ChatColor.RED + ChatColor.BOLD +
args[0] + ChatColor.GREEN + " 已经被封禁\n" + ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | \n" + ChatColor.GREEN + " 感谢您为维护游戏平衡做贡献!");
} }
plugin.reportlist.put(Bukkit.getPlayer(args[0]), null);
banlis.addBan(args[0], ChatColor.AQUA + "\n\n星阁钱语\n" + ChatColor.RED + "您的账号 " + args[0] + " 已被封禁\n原因: 管理员处理作弊行为", expdat, null); // 3. 校验参数合法性
Bukkit.getPlayer(args[0]).kickPlayer(ChatColor.AQUA + "星阁钱语\n" + ChatColor.RED + "你被封禁了" + ChatColor.BOLD + ChatColor.YELLOW + " 1 " + ChatColor.RED + "\n被封禁的账号: " + ChatColor.RED + ChatColor.BOLD + args[0] + ChatColor.RED + "\n封禁原因:" + "管理员处理"); if (args.length == 0) {
sendUsage(admin);
return true;
}
// 4. 分支处理不同命令参数(新增带单位的固定封禁)
switch (args[0]) {
case "no":
handleReject(admin, target);
break;
case "point":
handleDeductPoint(admin, target, reportReason);
break;
case "12h":
case "1d":
case "3d":
case "7d":
case "14d":
case "1mo":
case "3mo":
case "1y":
handleFixedBan(admin, target, reportReason, args[0]);
break;
case "ban":
handleCustomBan(admin, target, reportReason, args);
break;
default:
admin.sendMessage(ChatColor.RED + "无效参数!");
sendUsage(admin);
break;
}
return true;
}
/**
* 修正:同步新的命令用法提示(新增带单位的固定封禁参数)
*/
private void sendUsage(Player admin) {
admin.sendMessage(ChatColor.LIGHT_PURPLE + "举报处理命令用法:");
admin.sendMessage(ChatColor.WHITE + "/handle no - 驳回举报");
admin.sendMessage(ChatColor.WHITE + "/handle point - 扣除玩家信用分");
admin.sendMessage(ChatColor.WHITE + "/handle 12h/1d/3d/7d/14d - 封禁12小时/1天/3天/7天/14天");
admin.sendMessage(ChatColor.WHITE + "/handle 1mo/3mo/1y - 封禁1个月/3个月/1年");
admin.sendMessage(ChatColor.WHITE + "/handle ban <天数> - 自定义封禁天数(按天计算)");
}
// 原有方法:驳回举报(无修改)
private void handleReject(Player admin, Player target) {
plugin.banlist.remove(admin);
plugin.banreason.remove(target);
admin.sendMessage(ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | " +
ChatColor.GREEN + "已驳回玩家 " + ChatColor.RED + target.getName() + " 的举报");
notifyReporters(target, ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+
ChatColor.GREEN+"您举报的玩家 "+ChatColor.YELLOW+ChatColor.BOLD+target.getName()+ChatColor.GREEN+" 经查实无违规行为,已驳回请求\n"+
ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+ChatColor.YELLOW+"感谢您为维护游戏环境做出贡献,但请不要滥用举报。");
}
// 原有方法:扣除信用分(无修改)
private void handleDeductPoint(Player admin, Player target, String reason) {
plugin.banlist.remove(admin);
plugin.banreason.remove(target);
target.getScoreboard().getObjective("handled").getScore(target).setScore(target.getScoreboard().getObjective(("handled")).getScore(target).getScore()+5);
admin.sendMessage(ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | " +
ChatColor.GREEN + "已扣除玩家 " + ChatColor.RED + target.getName() +
ChatColor.GREEN + " 的信用分,举报原因:" + ChatColor.YELLOW + reason);
notifyReporters(target, ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+
ChatColor.GREEN+"您举报的玩家 "+ChatColor.YELLOW+ChatColor.BOLD+target.getName()+ChatColor.GREEN+" 已经被处理\n"+
ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+ChatColor.YELLOW+"感谢您为维护游戏平衡做出贡献。");
}
/**
* 修正处理带单位的固定封禁12h/1d/1mo等
*/
private void handleFixedBan(Player admin, Player target, String reason, String timeStr) {
// 调用重载的banPlayer方法支持带单位参数
boolean banSuccess = banPlayer(target, reason, timeStr);
if (banSuccess) {
// 清理待处理数据
plugin.banlist.remove(admin);
plugin.banreason.remove(target);
// 修正通知消息显示真实单位如12小时、1个月
String timeDisplay = getTimeDisplay(timeStr);
admin.sendMessage(ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | " +
ChatColor.GREEN + "已成功封禁玩家 " + ChatColor.RED + target.getName() +
ChatColor.GREEN + " " + timeDisplay + ",举报原因:" + ChatColor.YELLOW + reason);
} else { } else {
admin.sendMessage(ChatColor.RED + "封禁失败!无效的封禁时长格式");
}
}
// 原有方法:自定义天数封禁(无修改,仍按天计算)
private void handleCustomBan(Player admin, Player target, String reason, String[] args) {
if (args.length != 2) {
admin.sendMessage(ChatColor.RED + "自定义封禁用法错误!正确格式:/handle ban <天数>");
return;
}
int days;
try {
days = Integer.parseInt(args[1]);
if (days <= 0) {
admin.sendMessage(ChatColor.RED + "封禁天数必须为正整数");
return;
}
} catch (NumberFormatException e) {
admin.sendMessage(ChatColor.RED + "请输入有效的数字作为封禁天数");
return;
}
// 调用原有的banPlayer方法按天数计算
banPlayer(target, reason, days);
plugin.banlist.remove(admin);
plugin.banreason.remove(target);
admin.sendMessage(ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | " +
ChatColor.GREEN + "已自定义封禁玩家 " + ChatColor.RED + target.getName() +
ChatColor.GREEN + " " + days + " 天,举报原因:" + ChatColor.YELLOW + reason);
}
/**
* 新增重载banPlayer方法支持带单位的时间字符串
* @param timeStr 带单位的封禁时长12h/1d/3d/7d/14d/1mo/3mo/1y
* @return 封禁是否成功
*/
private boolean banPlayer(Player player, String reason, String timeStr) {
// 1. 解析时间字符串为毫秒数
long banMillis = parseTimeToMillis(timeStr);
if (banMillis <= 0) {
return false;
}
// 2. 计算封禁到期时间
Date expireDate = new Date(System.currentTimeMillis() + banMillis);
// 3. 构建封禁消息(显示真实单位)
String timeDisplay = getTimeDisplay(timeStr);
String banReason = ChatColor.AQUA + "CloudNest" + ChatColor.DARK_AQUA + "NetWork\n" +
ChatColor.RED + "您的账号 " + player.getName() + " 已被封禁\n" +
ChatColor.RED + "原因: " + reason + "\n" +
ChatColor.RED + "封禁时长: " + timeDisplay;
String kickMessage = ChatColor.AQUA + "CloudNest" + ChatColor.DARK_AQUA + "NetWork\n" +
ChatColor.RED + "你被封禁了" + ChatColor.BOLD + ChatColor.YELLOW + " " + timeDisplay + " " +
ChatColor.RED + "\n被封禁的账号: " + ChatColor.RED + ChatColor.BOLD + player.getName() +
ChatColor.RED + "\n封禁原因: " + reason;
// 4. 执行封禁操作
Bukkit.getBanList(BanList.Type.NAME).addBan(player.getName(), banReason, expireDate, null);
player.kickPlayer(kickMessage);
// 5. 通知举报者
notifyReporters(player, ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+
ChatColor.GREEN+"您举报的玩家 "+ChatColor.YELLOW+ChatColor.BOLD+player.getName()+ChatColor.GREEN+" 已经被处理\n"+
ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+ChatColor.YELLOW+"感谢您为维护游戏平衡做出贡献。");
// 6. 清理举报缓存
plugin.reportlist.remove(player);
return true; return true;
} }
return true;
/**
* 原有:按天数封禁(保留,用于自定义封禁)
*/
private void banPlayer(Player player, String reason, int days) {
long banDuration = (long) days * 24 * 60 * 60 * 1000L;
Date expireDate = new Date(System.currentTimeMillis() + banDuration);
String banReason = ChatColor.AQUA + "CloudNest" + ChatColor.DARK_AQUA + "NetWork\n" +
ChatColor.RED + "您的账号 " + player.getName() + " 已被封禁\n" +
ChatColor.RED + "原因: " + reason + "\n" +
ChatColor.RED + "封禁时长: " + days + "";
String kickMessage = ChatColor.AQUA + "CloudNest" + ChatColor.DARK_AQUA + "NetWork\n" +
ChatColor.RED + "你被封禁了" + ChatColor.BOLD + ChatColor.YELLOW + " " + days + " " +
ChatColor.RED + "\n被封禁的账号: " + ChatColor.RED + ChatColor.BOLD + player.getName() +
ChatColor.RED + "\n封禁原因: " + reason;
Bukkit.getBanList(BanList.Type.NAME).addBan(player.getName(), banReason, expireDate, null);
player.kickPlayer(kickMessage);
notifyReporters(player, ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+
ChatColor.GREEN+"您举报的玩家 "+ChatColor.YELLOW+ChatColor.BOLD+player.getName()+ChatColor.GREEN+" 已经被处理\n"+
ChatColor.LIGHT_PURPLE+"举报系统 "+ChatColor.WHITE+"| "+ChatColor.YELLOW+"感谢您为维护游戏平衡做出贡献。");
plugin.reportlist.remove(player);
}
/**
* 工具方法:将带单位的时间字符串转换为毫秒数
* 对应关系12h=12小时1d=1天1mo=30天1y=365天
*/
private long parseTimeToMillis(String timeStr) {
return switch (timeStr.toLowerCase()) {
case "12h" -> 12L * 60 * 60 * 1000; // 12小时 = 12*3600*1000ms
case "1d" -> 1L * 24 * 60 * 60 * 1000; // 1天
case "3d" -> 3L * 24 * 60 * 60 * 1000; // 3天
case "7d" -> 7L * 24 * 60 * 60 * 1000; // 7天
case "14d" -> 14L * 24 * 60 * 60 * 1000; // 14天
case "1mo" -> 30L * 24 * 60 * 60 * 1000; // 1个月按30天算
case "3mo" -> 90L * 24 * 60 * 60 * 1000; // 3个月90天
case "1y" -> 365L * 24 * 60 * 60 * 1000; // 1年365天
default -> -1; // 无效格式
};
}
/**
* 工具方法将时间字符串转换为友好显示文本如12h→12小时1mo→1个月
*/
private String getTimeDisplay(String timeStr) {
return switch (timeStr.toLowerCase()) {
case "12h" -> "12小时";
case "1d" -> "1天";
case "3d" -> "3天";
case "7d" -> "7天";
case "14d" -> "14天";
case "1mo" -> "1个月";
case "3mo" -> "3个月";
case "1y" -> "1年";
default -> timeStr; // 异常情况直接显示原字符串
};
}
// 原有方法:通知举报者(无修改)
private void notifyReporters(Player target, String message) {
var reporters = plugin.reportlist.getOrDefault(target, new HashSet<>());
for (Player reporter : reporters) {
if (reporter != null && reporter.isOnline()) {
reporter.sendMessage(message);
}
}
} }
} }

View File

@@ -0,0 +1,36 @@
package org.xgqy.survival.command;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.xgqy.survival.Survival;
public class NoticeCommandExecutor implements CommandExecutor {
private Survival plugin;
public NoticeCommandExecutor(Survival plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
Player player = Bukkit.getPlayer(args[0]);
if(!player.isOnline()){
sender.sendMessage(ChatColor.RED+"玩家不在线");
return true;
}
if(!player.isOp()){
sender.sendMessage(ChatColor.RED+"你无权使用该命令");
return true;
}
player.sendMessage(ChatColor.RED+"警告"+ChatColor.WHITE+" | "+ChatColor.GRAY+"检测到您有疑似作弊行为,请立即停止。");
player.sendTitle(ChatColor.AQUA+"星阁钱语",ChatColor.RED+"您的行为已上报,正在自动检查。",20,160,20);
//player.playSound(player, Sound.BLOCK_NOTE_BLOCK_XYLOPHONE,1.0f,1.0f);
return true;
}
}

View File

@@ -19,7 +19,6 @@ public class PointCommandExecutor implements CommandExecutor {
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (sender instanceof Player) {
if(args.length != 4){ if(args.length != 4){
sender.sendMessage(ChatColor.RED+"参数不足或参数过多!\n/point <player> <add|remove|set> <number> <reason>"); sender.sendMessage(ChatColor.RED+"参数不足或参数过多!\n/point <player> <add|remove|set> <number> <reason>");
return true; return true;
@@ -40,15 +39,11 @@ public class PointCommandExecutor implements CommandExecutor {
}else if(args[1].equals("remove")){ }else if(args[1].equals("remove")){
plugin.ppoint.put(player,plugin.ppoint.get(player)-Integer.parseInt(args[2])); plugin.ppoint.put(player,plugin.ppoint.get(player)-Integer.parseInt(args[2]));
plugin.breason.put(player,args[3]); plugin.breason.put(player,args[3]);
player.getScoreboard().getObjective("handled").getScore(player).setScore(Integer.parseInt(args[2])); player.getScoreboard().getObjective("handled").getScore(player).setScore(player.getScoreboard().getObjective(("handled")).getScore(player).getScore()+Integer.parseInt(args[2]));
}else{ }else{
sender.sendMessage(ChatColor.RED+"参数错误!\n/point <player> <add|remove|set> <number> <reason>"); sender.sendMessage(ChatColor.RED+"参数错误!\n/point <player> <add|remove|set> <number> <reason>");
return true; return true;
} }
return true; return true;
} else {
sender.sendMessage(ChatColor.RED + "无法对非玩家类使用");
return true;
}
} }
} }

View File

@@ -1,5 +1,8 @@
package org.xgqy.survival.command; package org.xgqy.survival.command;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.BanList; import org.bukkit.BanList;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
@@ -317,7 +320,18 @@ public class ReportCommandExecutor implements CommandExecutor, Listener {
ChatColor.GREEN + "举报原因: " + ChatColor.YELLOW + reason + "\n" + ChatColor.GREEN + "举报原因: " + ChatColor.YELLOW + reason + "\n" +
ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | " + ChatColor.LIGHT_PURPLE + "举报系统" + ChatColor.WHITE + " | " +
ChatColor.YELLOW + "请尽快处理该举报"); ChatColor.YELLOW + "请尽快处理该举报");
BaseComponent[] message = new ComponentBuilder(ChatColor.YELLOW+"工具栏: ")
.append(new ComponentBuilder(ChatColor.GREEN + "[传送到玩家] ").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/tp "+target.getName())).create())
.append(new ComponentBuilder(ChatColor.GREEN + "[提醒该玩家] \n").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/notice "+target.getName())).create())
.append(ChatColor.YELLOW+"处理栏: ")
.append(new ComponentBuilder(ChatColor.RED + "[驳回]").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/handle no")).create())
.append(new ComponentBuilder(ChatColor.RED + "[扣除信用分]").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/handle point")).create())
.append(new ComponentBuilder(ChatColor.RED + "[封禁1天]").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/handle 1")).create())
.append(new ComponentBuilder(ChatColor.RED + "[封禁3天]").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/handle 3")).create())
.append(new ComponentBuilder(ChatColor.RED + "[封禁7天]").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/handle 7")).create())
.append(new ComponentBuilder(ChatColor.RED + "[自定义封禁]").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/handle ban")).create())
.create();
admin.spigot().sendMessage(message);
// 添加到待处理列表 // 添加到待处理列表
plugin.banlist.put(admin, target); plugin.banlist.put(admin, target);
plugin.banreason.put(target, reason); plugin.banreason.put(target, reason);

View File

@@ -47,7 +47,11 @@ public class LoginEvent implements Listener {
initialLocations.put(player, initialLoc); // 记录初始位置 initialLocations.put(player, initialLoc); // 记录初始位置
// 初始化未登录隔离状态:隐身+高处传送+致盲 // 初始化未登录隔离状态:隐身+高处传送+致盲
setupUnloggedState(player); setupUnloggedState(player);
if(!plugin.getAccountManager().isRegistered(player.getUniqueId())){
if(!plugin.getPlayerTags().getTags(player).contains("小萌新")){
plugin.getPlayerTags().addTag(player,"小萌新",30);
}
}
// 登录提示定时器(每秒发送一次,登录后停止) // 登录提示定时器(每秒发送一次,登录后停止)
new BukkitRunnable() { new BukkitRunnable() {
@Override @Override

View File

@@ -83,6 +83,9 @@ commands:
selfkill: selfkill:
description: self kill description: self kill
usage: /<command> usage: /<command>
notice:
description: notice a player
usage: /<command> <player>
permissions: permissions:
permission.settag: permission.settag:
description: Allows setting player tags description: Allows setting player tags