Rewritten
Command: - handle - report Added new Command: - notice
This commit is contained in:
@@ -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() {
|
||||||
// 保存玩家标签数据
|
// 保存玩家标签数据
|
||||||
|
|||||||
314
src/main/java/org/xgqy/survival/command/CommandTabExecutor.java
Normal file
314
src/main/java/org/xgqy/survival/command/CommandTabExecutor.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user