From 6c0e1713b5a90cdff63f1c3f57db7c225dfb3597 Mon Sep 17 00:00:00 2001 From: ypsdf1 Date: Fri, 1 May 2026 01:01:55 +0800 Subject: [PATCH] =?UTF-8?q?v1.4=20=E6=96=B0=E5=A2=9E=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=AF=BC=E5=85=A5cdk=E5=92=8C=E8=AE=B0=E5=90=8D=EF=BC=8C?= =?UTF-8?q?=E5=85=81=E8=AE=B8=E7=A4=BC=E5=8C=85=E7=A0=81=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E9=A2=86=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/sdf1/Main.java | 523 +++++++++++++++++++------------ src/main/resources/plugin.yml | 4 + 2 files changed, 327 insertions(+), 200 deletions(-) diff --git a/src/main/java/com/sdf1/Main.java b/src/main/java/com/sdf1/Main.java index 623d64f..d465707 100644 --- a/src/main/java/com/sdf1/Main.java +++ b/src/main/java/com/sdf1/Main.java @@ -49,11 +49,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { private boolean cdksWarned = false; private String cfgLinkMode = ""; private String cfgUpdateChannel = ""; + private String cfgNameBoard = ""; + private String cfgAdminTeam = ""; + private String cfgAdminTag = ""; + private final Map scoreMap = new HashMap(); private Plugin cyPlugin = null; private java.lang.reflect.Method cyGiveSlots = null; private Economy economy = null; - private static final long LISTEN_TIMEOUT_MS = 15000L; private final Map listening = new ConcurrentHashMap(); private final Map chatCd = new ConcurrentHashMap(); private int failCount = 0; @@ -68,7 +71,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { private static final Map ALIASES = new HashMap(); static { String[][] pairs = { - {"计分板","计分板"},{"口令板","计分板"},{"口令库","计分板"},{"查重板","计分板"},{"scoreboard","计分板"},{"cdk板","计分板"},{"cdk","计分板"}, + {"计分板","计分板"},{"口令板","计分板"},{"口令库","计分板"},{"scoreboard","计分板"}, + {"记名板","记名板"},{"记名","记名板"},{"nameboard","记名板"},{"查重板","记名板"},{"查重","记名板"},{"dedup","记名板"}, {"联控插件","联控插件"},{"联控","联控插件"},{"cy插件","联控插件"},{"cy","联控插件"},{"cy_beibao","联控插件"}, {"分值","分值"},{"分数","分值"},{"score","分值"},{"points","分值"}, {"动作","动作"},{"action","动作"},{"操作","动作"}, @@ -77,11 +81,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { {"天数","天数"},{"天","天数"},{"days","天数"}, {"金额","金额"},{"金","金额"},{"钱","金额"},{"money","金额"}, {"版本号","版本号"},{"版本","版本号"},{"version","版本号"},{"ver","版本号"}, - {"更新通道","更新通道"},{"联控模式","联控模式"} + {"更新通道","更新通道"},{"联控模式","联控模式"}, + {"管理团队","管理团队"},{"admin团队","管理团队"},{"team","管理团队"}, + {"管理标签","管理标签"},{"admin标签","管理标签"},{"tag","管理标签"} }; for (String[] p : pairs) ALIASES.put(p[0].toLowerCase(), p[1]); } + private static final Map CN_NUMS = new HashMap(); static { CN_NUMS.put("零", 0); CN_NUMS.put("一", 1); CN_NUMS.put("二", 2); CN_NUMS.put("三", 3); @@ -92,14 +99,10 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { CN_NUMS.put("伍", 5); CN_NUMS.put("陆", 6); CN_NUMS.put("柒", 7); CN_NUMS.put("捌", 8); CN_NUMS.put("玖", 9); CN_NUMS.put("拾", 10); CN_NUMS.put("佰", 100); CN_NUMS.put("仟", 1000); } - private static class ActionEntry { - String type; - double money, moneyMin, moneyMax; + String type; double money, moneyMin, moneyMax; int slots, days, slotsMin, slotsMax, daysMin, daysMax; - int decimalPlaces = -1; - String rawText = ""; - + int decimalPlaces = -1; String rawText = ""; ActionEntry(String t) { type = t; } } private static class ScoreAction { @@ -115,17 +118,17 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { setupEconomy(); setupCyReflection(); getCommand("sdf1").setExecutor(this); + getCommand("import").setExecutor(this); // ← 新增 getServer().getPluginManager().registerEvents(this, this); checkUpdate(null); log("[SDF1] ===== 启动完成 ====="); } + @Override public void onDisable() { log("[SDF1] 卸载"); listening.clear(); } private void log(String msg) { getLogger().info(msg); } // PLACEHOLDER_PART2 - // ===== 共享算法:主控/被控互相发现 ===== - private static final String[] DISCOVER_NAMES = {"Sdf1", "sdf1", "SDF1", "SDF1Plugin"}; private static final String[] CY_DISCOVER_NAMES = {"CY_beibao", "CY", "cy_beibao", "Cy", "cy"}; private Plugin discoveredCy = null; private java.lang.reflect.Method discoveredCyActivate = null; @@ -145,40 +148,27 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { discoveredCy = p; try { discoveredCyActivate = p.getClass().getMethod("onSdf1Activation", String.class, int.class, int.class); } catch (Exception ignored) {} try { discoveredCyPing = p.getClass().getMethod("onSdf1Ping"); } catch (Exception ignored) {} - log("[共享] 发现被控: " + p.getName()); + if (discoveredCyActivate != null) { log("[共享] 发现被控: " + p.getName()); } + else { discoveredCy = null; log("[共享] " + p.getName() + " 缺少共享方法,跳过"); } return; } } - log("[共享] 未发现被控插件"); - } - private boolean isCyConnected() { - return discoveredCy != null && discoveredCy.isEnabled() && discoveredCyActivate != null; + log("[共享] 未发现被控"); } + private boolean isCyConnected() { return discoveredCy != null && discoveredCy.isEnabled() && discoveredCyActivate != null; } private String cyPing() { if (!isCyConnected()) { discoverCyPlugin(); if (!isCyConnected()) return "未连接"; } - if (discoveredCyPing != null) { - try { Object result = discoveredCyPing.invoke(discoveredCy); return result != null ? result.toString() : "OK"; } - catch (Exception e) { return "ping失败"; } - } - return "OK(无ping方法)"; + if (discoveredCyPing != null) { try { Object r = discoveredCyPing.invoke(discoveredCy); return r != null ? r.toString() : "OK"; } catch (Exception e) { return "ping失败"; } } + return "OK(无ping)"; } - - // ===== 配置文件 ===== private void extractDefaultConfig() { - File folder = getDataFolder(); - File f = new File(folder, "设置.txt"); + File folder = getDataFolder(); File f = new File(folder, "设置.txt"); log("[SDF1] 目标: " + f.getAbsolutePath() + " exists=" + f.exists()); if (f.exists() && f.length() > 0) { log("[SDF1] 已存在,跳过"); return; } - try { - InputStream in = getResource("设置.txt"); - if (in != null) { - if (!folder.exists()) folder.mkdirs(); - FileOutputStream fos = new FileOutputStream(f); - byte[] buf = new byte[1024]; int len; - while ((len = in.read(buf)) > 0) fos.write(buf, 0, len); - fos.close(); in.close(); - log("[SDF1] jar提取完成 " + f.length() + "字节"); return; - } + try { InputStream in = getResource("设置.txt"); + if (in != null) { if (!folder.exists()) folder.mkdirs(); FileOutputStream fos = new FileOutputStream(f); + byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) fos.write(buf, 0, len); fos.close(); in.close(); + log("[SDF1] jar提取完成 " + f.length() + "字节"); return; } } catch (Exception e) { log("[SDF1] jar提取异常: " + e.getMessage()); } writeFallbackConfig(f); } @@ -187,21 +177,33 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { File parent = f.getParentFile(); if (parent != null && !parent.exists()) parent.mkdirs(); PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8)); - pw.println("# SDF1 主控配置"); pw.println("版本号: 1"); pw.println("更新通道: GH"); - pw.println("计分板: "); pw.println("联控插件: "); pw.println("联控模式: 开"); - pw.println(); pw.println("1:"); pw.println(" - 给那个玩家100块"); - pw.println(); pw.println("2:"); pw.println(" - 给那个玩家抽个盲盒"); pw.println(" - 然后口令删了"); + pw.println("# SDF1 主控配置"); + pw.println("版本号: 1"); + pw.println("更新通道: GH"); + pw.println("管理团队: admin"); + pw.println("管理标签: admin"); + pw.println(); + pw.println("计分板: "); + pw.println("联控插件: "); + pw.println("联控模式: 开"); + pw.println("记名板: "); + pw.println(); + pw.println("1:"); + pw.println(" - 给那个玩家100块"); + pw.println(); + pw.println("2:"); + pw.println(" - 给那个玩家抽个盲盒"); + pw.println(" - 然后口令删了"); pw.flush(); pw.close(); - log("[SDF1] 生成默认配置 " + f.length() + "字节"); } catch (Exception e) { log("[SDF1] 写入失败: " + e.getMessage()); } } + private void loadConfig(boolean verbose) { scoreMap.clear(); configLoaded = false; cdksWarned = false; - cfgCdkObj = ""; cfgCyName = ""; cfgVer = 0; cfgLinkMode = ""; cfgUpdateChannel = ""; + cfgCdkObj = ""; cfgCyName = ""; cfgVer = 0; cfgLinkMode = ""; cfgUpdateChannel = ""; cfgNameBoard = ""; File f = new File(getDataFolder(), "设置.txt"); if (!f.exists() || f.length() == 0) extractDefaultConfig(); - try { - List rawLines = new ArrayList(); + try { List rawLines = new ArrayList(); BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8)); String line; while ((line = r.readLine()) != null) rawLines.add(line); r.close(); if (verbose) { log("===== 配置原文 ====="); for (int i = 0; i < rawLines.size(); i++) log(String.format("L%02d: %s", i + 1, rawLines.get(i))); } @@ -209,21 +211,12 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { List cleanLines = stripAllComments(rawLines, diag); if (verbose) { log("===== 逐行解析 ====="); for (String d : diag) log(d); } deepParse(cleanLines, diag); - if (verbose) { - log("===== 最终配置 ====="); - log("版本号: " + cfgVer); log("计分板: " + (cfgCdkObj.isEmpty() ? "(未设置)" : cfgCdkObj)); - log("联控插件: " + (cfgCyName.isEmpty() ? "(未设置)" : cfgCyName)); - log("联控模式: " + (cfgLinkMode.isEmpty() ? "(未设置)" : cfgLinkMode)); - log("规则数: " + scoreMap.size()); - for (Map.Entry entry : scoreMap.entrySet()) { - ScoreAction sa = entry.getValue(); + if (verbose) { log("===== 最终配置 ====="); log("版本号: " + cfgVer); log("计分板: " + (cfgCdkObj.isEmpty() ? "(未设置)" : cfgCdkObj)); + log("联控插件: " + (cfgCyName.isEmpty() ? "(未设置)" : cfgCyName)); log("联控模式: " + (cfgLinkMode.isEmpty() ? "(未设置)" : cfgLinkMode)); + log("记名板: " + (cfgNameBoard.isEmpty() ? "(未设置)" : cfgNameBoard)); log("规则数: " + scoreMap.size()); + for (Map.Entry entry : scoreMap.entrySet()) { ScoreAction sa = entry.getValue(); log(" 分值" + entry.getKey() + " -> " + sa.actions.size() + "个动作" + (sa.oneTime ? " (一次性)" : "")); - for (int i = 0; i < sa.actions.size(); i++) { - ActionEntry ae = sa.actions.get(i); - log(" 动作" + (i + 1) + ": [" + ae.type + "] " + ae.rawText); - } - } - } + for (int i = 0; i < sa.actions.size(); i++) { ActionEntry ae = sa.actions.get(i); log(" 动作" + (i + 1) + ": [" + ae.type + "] " + ae.rawText); } } } } catch (Exception e) { log("[SDF1] 读取失败: " + e.getMessage()); } } @@ -247,13 +240,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { String actionText = bare.substring(1).trim(); actionText = actionText.replaceAll("^\"(.*)\"$", "$1").replaceAll("^'(.*)'$", "$1"); diag.add(" -> [动作] \"" + actionText + "\""); - if (cur != null) { - parseNaturalAction(cur, actionText, diag); - log("[解析] cur=" + cur.get("分值")); - } else { - diag.add(" -> [警告] 动作不在规则块内"); - } - + if (cur != null) { parseNaturalAction(cur, actionText, diag); log("[解析] cur=" + cur.get("分值")); } + else { diag.add(" -> [警告] 动作不在规则块内"); } continue; } String[] kv = extractKV(line); @@ -265,6 +253,9 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { if (!resolved.equals(key)) diag.add(" -> 同义词: \"" + key + "\" -> \"" + resolved + "\""); key = resolved; if (isKnownGlobal(key)) { globals.put(key, value); diag.add(" -> [全局] " + key + " = \"" + value + "\""); } + else if (key.equals("分值")) { + } + else if (key.equals("分值")) { cur = new HashMap(); cur.put(key, value); blocks.add(cur); diag.add(" -> [新规则] 分值 = " + value); } else if (isKnownBlock(key)) { if (cur == null) { cur = new HashMap(); blocks.add(cur); } cur.put(key, value); diag.add(" -> [块内] " + key + " = \"" + value + "\""); } else { diag.add(" -> [跳过] 未知: \"" + key + "\""); } @@ -272,18 +263,21 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { String verStr = safeStr(globals.get("版本号")); if (!verStr.isEmpty()) { try { cfgVer = (int) Double.parseDouble(verStr); } catch (Exception e) { cfgVer = 0; } } cfgCdkObj = safeStr(globals.get("计分板")); cfgCyName = safeStr(globals.get("联控插件")); - cfgLinkMode = safeStr(globals.get("联控模式")); cfgUpdateChannel = safeStr(globals.get("更新通道")); + cfgLinkMode = safeStr(globals.get("联控模式")); + cfgUpdateChannel = safeStr(globals.get("更新通道")); + cfgNameBoard = safeStr(globals.get("记名板")); + cfgAdminTeam = safeStr(globals.get("管理团队")); + cfgAdminTag = safeStr(globals.get("管理标签")); + for (Map block : blocks) { log("[解析] 块内容: " + block); - int scoreKey = safeInt(block.get("分值")); if (scoreKey <= 0) continue; ScoreAction sa = new ScoreAction(); sa.oneTime = "true".equals(block.get("_一次性")); if ("true".equals(block.get("_经济盲盒"))) { ActionEntry e = new ActionEntry("经济盲盒"); - e.moneyMin = safeDouble(block.get("_经济盲盒_min")); - e.moneyMax = safeDouble(block.get("_经济盲盒_max")); + e.moneyMin = safeDouble(block.get("_经济盲盒_min")); e.moneyMax = safeDouble(block.get("_经济盲盒_max")); if (e.moneyMin <= 0) e.moneyMin = 100; if (e.moneyMax <= 0) e.moneyMax = e.moneyMin; e.decimalPlaces = safeInt(block.getOrDefault("_小数位", "-1")); e.rawText = "经济盲盒 " + fmtMoney(e.moneyMin) + "~" + fmtMoney(e.moneyMax) + (e.decimalPlaces >= 0 ? " (" + e.decimalPlaces + "位小数)" : ""); @@ -301,31 +295,21 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { if (block.containsKey("_扣钱")) { ActionEntry e = new ActionEntry("扣钱"); e.money = safeDouble(block.get("_扣钱")); e.rawText = "扣钱 $" + fmtMoney(e.money); sa.actions.add(e); } if (block.containsKey("_联控")) { ActionEntry e = new ActionEntry("联控"); e.slots = safeInt(block.get("_格子数")); e.days = safeInt(block.get("_天数")); e.rawText = "联控 +" + e.slots + "格 " + e.days + "天"; sa.actions.add(e); } } - if (block.containsKey("_小数位")) { - int dp = safeInt(block.get("_小数位")); - for (ActionEntry ae : sa.actions) ae.decimalPlaces = dp; - } - if ("true".equals(block.get("_删除口令"))) { - ActionEntry de = new ActionEntry("删除口令"); - de.rawText = "删除口令"; - sa.actions.add(de); - log("[解析] 添加删除口令动作"); - } - - + if (block.containsKey("_小数位")) { int dp = safeInt(block.get("_小数位")); for (ActionEntry ae : sa.actions) ae.decimalPlaces = dp; } + if ("true".equals(block.get("_删除口令"))) { ActionEntry de = new ActionEntry("删除口令"); de.rawText = "删除口令"; sa.actions.add(de); log("[解析] 添加删除口令动作"); } + if ("true".equals(block.get("_记名"))) { sa.oneTime = true; log("[解析] 标记为一次性(记名)"); } if (sa.actions.isEmpty()) { diag.add("[警告] 分值" + scoreKey + " 无有效动作"); continue; } scoreMap.put(scoreKey, sa); } configLoaded = !cfgCdkObj.isEmpty(); } + private void parseNaturalAction(Map block, String text, List diag) { text = text.replaceAll("^['\"](.*)['\"]$", "$1").trim(); - if (text.contains("删") || text.contains("删除")) { - block.put("_一次性", "true"); - block.put("_删除口令", "true"); - diag.add(" -> 识别: 删除口令"); + if (text.contains("删") || text.contains("删除") || text.contains("销毁") || text.contains("作废") || text.contains("清除") || text.contains("清空") || text.contains("抹除") || text.contains("删掉") || text.contains("移除")) { + block.put("_一次性", "true"); block.put("_删除口令", "true"); diag.add(" -> 识别: 删除口令"); } - + if (text.contains("记名") || text.contains("永久一次性")) { block.put("_记名", "true"); diag.add(" -> 识别: 记名"); } Matcher decMatch = Pattern.compile("(\\d+)\\s*位\\s*小数").matcher(text); if (decMatch.find()) { block.put("_小数位", decMatch.group(1)); diag.add(" -> 识别: 小数位=" + decMatch.group(1)); } if (text.contains("盲盒") || text.contains("抽")) { @@ -336,10 +320,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { block.put("_联控盲盒", "true"); diag.add(" -> 识别: 联控盲盒(默认)"); return; } boolean hasSlotKeyword = text.contains("背包") || text.contains("空间") || text.contains("格") || text.contains("激活"); - if (hasSlotKeyword) { - int[] sd = extractSlotDay(text); - if (sd != null) { block.put("_联控", "true"); block.put("_格子数", String.valueOf(sd[1])); block.put("_天数", String.valueOf(sd[0])); diag.add(" -> 识别: 联控 " + sd[0] + "天" + sd[1] + "格"); } - } + if (hasSlotKeyword) { int[] sd = extractSlotDay(text); if (sd != null) { block.put("_联控", "true"); block.put("_格子数", String.valueOf(sd[1])); block.put("_天数", String.valueOf(sd[0])); diag.add(" -> 识别: 联控 " + sd[0] + "天" + sd[1] + "格"); } } boolean isTake = text.contains("扣") || text.contains("减") || text.contains("扣除"); if (isTake) { double amt = extractMoneyExcludingSlots(text); if (amt > 0) { block.put("_扣钱", String.valueOf(amt)); diag.add(" -> 识别: 扣钱 " + amt); } } boolean isGive = !isTake && (text.contains("给") || text.contains("奖") || text.contains("发") || text.contains("加")); @@ -348,6 +329,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { // PLACEHOLDER_PART4 // ===== 工具方法 ===== + + private String safeStr(String s) { return s == null ? "" : s.trim(); } private int safeInt(String s) { if (s == null || s.trim().isEmpty()) return 0; @@ -365,6 +348,10 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } private double safeDouble(String s) { try { return Double.parseDouble(s == null ? "0" : s.trim()); } catch (Exception e) { return safeInt(s); } } private String fmtMoney(double v) { return v == (long) v ? String.valueOf((long) v) : String.format("%.2f", v); } + private String fmtAmount(double v, int dp) { + if (dp >= 0) return String.format("%." + dp + "f", v); + return v == (long) v ? String.valueOf((long) v) : String.format("%.2f", v); + } private int findUnquoted(String s, char target) { boolean inSq = false; boolean inDq = false; for (int i = 0; i < s.length(); i++) { @@ -405,8 +392,11 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { return key; } private boolean isKnownGlobal(String key) { - return key.equals("计分板") || key.equals("联控插件") || key.equals("版本号") || key.equals("更新通道") || key.equals("联控模式"); + return key.equals("计分板") || key.equals("记名板") || key.equals("联控插件") + || key.equals("版本号") || key.equals("更新通道") || key.equals("联控模式") + || key.equals("管理团队") || key.equals("管理标签"); } + private boolean isKnownBlock(String key) { return key.equals("分值") || key.equals("动作") || key.equals("类型") || key.equals("格子数") || key.equals("天数") || key.equals("金额"); } @@ -419,14 +409,6 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { if (unitStr.equals("百万")) return num * 1000000; return num; } - private double extractMoneyAmount(String text) { - double[] range = extractMoneyRange(text); - if (range != null) return (range[0] + range[1]) / 2; - Matcher m = Pattern.compile("([\\d.]+)\\s*(元|块|千|万|十万|百万)?").matcher(text); - double max = 0; - while (m.find()) { double a = parseMoneyWithUnit(m.group(1), m.group(2)); if (a > max) max = a; } - return max; - } private double[] extractMoneyRange(String text) { Matcher m = Pattern.compile("([\\d.]+)\\s*(元|块|千|万|十万|百万)?\\s*[~\\-到至]+\\s*([\\d.]+)\\s*(元|块|千|万|十万|百万)?").matcher(text); if (m.find()) { @@ -449,7 +431,6 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } return max; } - private int[] extractSlotDay(String text) { Matcher m1 = Pattern.compile("(\\d+)\\s*格.*?(\\d+)\\s*天").matcher(text); if (m1.find()) return new int[]{Integer.parseInt(m1.group(2)), Integer.parseInt(m1.group(1))}; @@ -485,15 +466,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { for (int i = 0; i < rawLines.size(); i++) { String raw = rawLines.get(i); String trimmed = raw.trim(); String ln = String.format("L%02d", i + 1); if (trimmed.isEmpty()) { diag.add(ln + ": (空行)"); result.add(""); continue; } - if (inBlock) { int endIdx = trimmed.indexOf("*/"); if (endIdx >= 0) { inBlock = false; String after = trimmed.substring(endIdx + 2).trim(); result.add(after.isEmpty() ? "" : after); } else result.add(""); diag.add(ln + ": " + raw); diag.add(" -> [踢除块注释中]"); totalComments++; continue; } - if (inHtml) { int endIdx = trimmed.indexOf("-->"); if (endIdx >= 0) { inHtml = false; String after = trimmed.substring(endIdx + 3).trim(); result.add(after.isEmpty() ? "" : after); } else result.add(""); diag.add(ln + ": " + raw); diag.add(" -> [踢除HTML注释中]"); totalComments++; continue; } - if (trimmed.contains("/*")) { int bs = trimmed.indexOf("/*"); int be = trimmed.indexOf("*/", bs + 2); if (be >= 0) { String b = trimmed.substring(0, bs).trim(); String a = trimmed.substring(be + 2).trim(); String c = (b + " " + a).trim(); result.add(c); } else { inBlock = true; String b = trimmed.substring(0, bs).trim(); result.add(b.isEmpty() ? "" : b); } diag.add(ln + ": " + raw); diag.add(" -> [踢除块注释]"); totalComments++; continue; } - if (trimmed.contains("", hs + 4); if (he >= 0) { String b = trimmed.substring(0, hs).trim(); String a = trimmed.substring(he + 3).trim(); String c = (b + " " + a).trim(); result.add(c); } else { inHtml = true; String b = trimmed.substring(0, hs).trim(); result.add(b.isEmpty() ? "" : b); } diag.add(ln + ": " + raw); diag.add(" -> [踢除HTML注释]"); totalComments++; continue; } - if (trimmed.startsWith("#") || trimmed.startsWith("//")) { diag.add(ln + ": " + raw); diag.add(" -> [踢除整行注释]"); result.add(""); totalComments++; continue; } + if (inBlock) { int endIdx = trimmed.indexOf("*/"); if (endIdx >= 0) { inBlock = false; String after = trimmed.substring(endIdx + 2).trim(); result.add(after.isEmpty() ? "" : after); } else result.add(""); diag.add(ln + ": [踢除块注释中]"); totalComments++; continue; } + if (inHtml) { int endIdx = trimmed.indexOf("-->"); if (endIdx >= 0) { inHtml = false; String after = trimmed.substring(endIdx + 3).trim(); result.add(after.isEmpty() ? "" : after); } else result.add(""); diag.add(ln + ": [踢除HTML注释中]"); totalComments++; continue; } + if (trimmed.contains("/*")) { int bs = trimmed.indexOf("/*"); int be = trimmed.indexOf("*/", bs + 2); if (be >= 0) { String b = trimmed.substring(0, bs).trim(); String a = trimmed.substring(be + 2).trim(); result.add((b + " " + a).trim()); } else { inBlock = true; String b = trimmed.substring(0, bs).trim(); result.add(b.isEmpty() ? "" : b); } diag.add(ln + ": [踢除块注释]"); totalComments++; continue; } + if (trimmed.contains("", hs + 4); if (he >= 0) { String b = trimmed.substring(0, hs).trim(); String a = trimmed.substring(he + 3).trim(); result.add((b + " " + a).trim()); } else { inHtml = true; String b = trimmed.substring(0, hs).trim(); result.add(b.isEmpty() ? "" : b); } diag.add(ln + ": [踢除HTML注释]"); totalComments++; continue; } + if (trimmed.startsWith("#") || trimmed.startsWith("//")) { diag.add(ln + ": [踢除整行注释]"); result.add(""); totalComments++; continue; } int hashIdx = findUnquoted(trimmed, '#'); if (hashIdx >= 0) { trimmed = trimmed.substring(0, hashIdx).trim(); totalInline++; } int slashIdx = findUnquoted(trimmed, '/'); if (slashIdx >= 0 && slashIdx + 1 < trimmed.length() && trimmed.charAt(slashIdx + 1) == '/') { trimmed = trimmed.substring(0, slashIdx).trim(); totalInline++; } - diag.add(ln + ": " + raw); diag.add(" -> [保留] \"" + trimmed + "\""); - result.add(trimmed); + diag.add(ln + ": [保留] \"" + trimmed + "\""); result.add(trimmed); } diag.add("总行: " + rawLines.size() + " | 注释: " + totalComments + " | 有效行: " + result.size()); return result; @@ -520,8 +500,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } private int lookupScore(String code) { if (!configLoaded || cfgCdkObj.isEmpty()) return -1; - try { - Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + try { Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); Objective obj = board.getObjective(cfgCdkObj); if (obj == null) { if (!cdksWarned) { log("[计分板] 找不到: " + cfgCdkObj); cdksWarned = true; } return -1; } cdksWarned = false; Score s = obj.getScore(code); @@ -531,28 +510,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { private void consumeCode(String code, boolean oneTime) { if (!oneTime) return; log("[删除] 口令: \"" + code + "\" 目标: " + cfgCdkObj); - try { - Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + try { Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); Objective obj = board.getObjective(cfgCdkObj); - if (obj != null) { - Score sc = obj.getScore(code); - if (sc.isScoreSet()) { - // 反射尝试 resetScore - boolean removed = false; - try { - java.lang.reflect.Method m = obj.getClass().getMethod("resetScore", String.class); - m.invoke(obj, code); removed = true; - } catch (Throwable ignored) {} - if (!removed) { - try { - java.lang.reflect.Method m = board.getClass().getMethod("resetScore", String.class); - m.invoke(board, code); removed = true; - } catch (Throwable ignored) {} - } + if (obj != null) { Score sc = obj.getScore(code); + if (sc.isScoreSet()) { boolean removed = false; + try { java.lang.reflect.Method m = obj.getClass().getMethod("resetScore", String.class); m.invoke(obj, code); removed = true; } catch (Throwable ignored) {} + if (!removed) { try { java.lang.reflect.Method m = board.getClass().getMethod("resetScore", String.class); m.invoke(board, code); removed = true; } catch (Throwable ignored) {} } if (!removed) { sc.setScore(Integer.MIN_VALUE); removed = true; } - log("[删除] API结果: " + removed); - } - } + log("[删除] API结果: " + removed); } } } catch (Exception e) { log("[删除] API异常: " + e.getMessage()); } fallbackDelete(code); } @@ -560,16 +525,26 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { Bukkit.getScheduler().runTask(this, new Runnable() { public void run() { String safeCode = code.replace("\"", "\\\""); String cmd = "scoreboard players reset " + safeCode + " " + cfgCdkObj; - log("[删除] 兜底执行: " + cmd); - try { - boolean ok = Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd); - log("[删除] 兜底结果: " + ok); - } catch (Exception e) { log("[删除] 兜底失败: " + e.getMessage()); } + log("[删除] 兜底: " + cmd); + try { Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd); } catch (Exception e) { log("[删除] 兜底失败: " + e.getMessage()); } } }); } - - + /** 管理员判定:OP / 权限 / 团队 / 标签 */ + private boolean checkAdminSilent(CommandSender s) { + if (s.isOp()) return true; + if (s.hasPermission("sdf1.admin")) return true; + if (!(s instanceof Player)) return false; + Player p = (Player) s; + if (!cfgAdminTag.isEmpty() && p.getScoreboardTags().contains(cfgAdminTag)) return true; + if (!cfgAdminTeam.isEmpty()) { + try { + org.bukkit.scoreboard.Team team = p.getScoreboard().getTeam(cfgAdminTeam); + if (team != null && team.hasEntry(p.getName())) return true; + } catch (Exception ignored) {} + } + return false; + } private void startListening(Player p) { listening.put(p.getUniqueId(), System.currentTimeMillis()); @@ -594,6 +569,15 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { ScoreAction sa = scoreMap.get(scoreVal); if (sa == null) { p.sendMessage("§c[SDF1] 规则未配置"); log("[拦截] " + p.getName() + " 分值=" + scoreVal + " 无规则"); return; } log("[拦截] " + p.getName() + " 分值=" + scoreVal + " 动作数=" + sa.actions.size() + (sa.oneTime ? " 一次性" : "")); + // 记名查重 + if (cfgNameBoard != null && !cfgNameBoard.isEmpty() && sa.oneTime) { + String nameKey = msg + "_" + p.getName(); + try { Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + Objective nameObj = board.getObjective(cfgNameBoard); + if (nameObj != null) { Score ns = nameObj.getScore(nameKey); + if (ns.isScoreSet() && ns.getScore() > 0) { p.sendMessage("§c[SDF1] 你已领取过此口令"); log("[记名] " + p.getName() + " 重复: " + nameKey); return; } } + } catch (Exception ignored) {} + } boolean oneTime = sa.oneTime; p.sendMessage("§a[SDF1] 执行: " + sa.actions.size() + "个动作"); for (ActionEntry ae : sa.actions) { @@ -604,33 +588,46 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { else if ("联控盲盒".equals(ae.type)) execSlotBox(p, ae, oneTime, msg); else if ("联控".equals(ae.type)) execCy(p, ae, oneTime, msg); else if ("删除口令".equals(ae.type)) execDelete(p, ae, oneTime, msg); - - } + // 记名写入 + if (cfgNameBoard != null && !cfgNameBoard.isEmpty() && sa.oneTime) { + final String nameKey = msg + "_" + p.getName(); + final String boardName = cfgNameBoard; + final Player fp = p; + Bukkit.getScheduler().runTask(this, new Runnable() { public void run() { + try { Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + Objective obj = board.getObjective(boardName); + if (obj == null) { + log("[记名] 记名板不存在: " + boardName + ",跳过写入"); + fp.sendMessage("§c[SDF1] 记名板不存在,记名失败"); + return; + } + obj.getScore(nameKey).setScore(1); + log("[记名] 写入: " + nameKey); + fp.sendMessage("§a[SDF1] 记名成功"); + } catch (Exception e) { + log("[记名] 写入失败: " + e.getMessage()); + } + } }); + } + } // ===== 执行动作 ===== - private String fmtAmount(double v, int dp) { - if (dp >= 0) return String.format("%." + dp + "f", v); - return v == (long) v ? String.valueOf((long) v) : String.format("%.2f", v); - } private void execGiveMoney(Player p, ActionEntry a, boolean oneTime, String code) { if (economy == null) { p.sendMessage("§c[SDF1] 经济不可用"); return; } double before = economy.getBalance(p); economy.depositPlayer(p, a.money); double after = economy.getBalance(p); consumeCode(code, oneTime); p.sendMessage("§a[SDF1] 获得 §e$" + fmtAmount(a.money, a.decimalPlaces)); p.sendMessage("§7余额: §a$" + fmtMoney(before) + " §7-> §a$" + fmtMoney(after)); - log("[发钱] " + p.getName() + " +$" + fmtAmount(a.money, a.decimalPlaces)); } - private void execTakeMoney(Player p, ActionEntry a, boolean oneTime, String code) { + private void execTakeMoney(Player p, ActionEntry a, boolean oneTime, String code) { if (economy == null) { p.sendMessage("§c[SDF1] 经济不可用"); return; } double amount = Math.abs(a.money); if (!economy.has(p, amount)) { p.sendMessage("§c[SDF1] 余额不足! 需要: $" + fmtAmount(amount, a.decimalPlaces)); return; } double before = economy.getBalance(p); economy.withdrawPlayer(p, amount); double after = economy.getBalance(p); consumeCode(code, oneTime); p.sendMessage("§c[SDF1] 扣除 §e$" + fmtAmount(amount, a.decimalPlaces)); p.sendMessage("§7余额: §a$" + fmtMoney(before) + " §7-> §a$" + fmtMoney(after)); - log("[扣款] " + p.getName() + " -$" + fmtAmount(amount, a.decimalPlaces)); } - private void execMoneyBox(final Player p, final ActionEntry a, final boolean oneTime, final String code) { if (economy == null) { p.sendMessage("§c[SDF1] 经济不可用"); return; } p.sendMessage("§6§l[SDF1] §e§l盲盒开启中..."); @@ -643,9 +640,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { amount = Math.round(amount * 100.0) / 100.0; double before = economy.getBalance(p); economy.depositPlayer(p, amount); double after = economy.getBalance(p); consumeCode(code, oneTime); - p.sendMessage("§6§l[SDF1] §e§l恭喜!获得 $§c§l" + fmtMoney(amount) + " §e§l!"); + p.sendMessage("§6§l[SDF1] §e§l恭喜!获得 $§c§l" + fmtAmount(amount, a.decimalPlaces) + " §e§l!"); p.sendMessage("§7余额: §a$" + fmtMoney(before) + " §7-> §a$" + fmtMoney(after)); - log("[经济盲盒] " + p.getName() + " +$" + fmtMoney(amount)); } }, 20L); } }, 20L); } }, 20L); @@ -659,10 +655,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { Bukkit.getScheduler().runTaskLater(Main.this, new Runnable() { public void run() { int rd = a.daysMin + rng.nextInt(Math.max(1, a.daysMax - a.daysMin + 1)); int rs = a.slotsMin + rng.nextInt(Math.max(1, a.slotsMax - a.slotsMin + 1)); - if (tryCyActivate(p, rs, rd)) { - consumeCode(code, oneTime); - p.sendMessage("§6§l[SDF1] §e§l恭喜!获得 §c§l" + rd + "天会员 + " + rs + "格空间 §e§l!"); - } else { p.sendMessage("§c[SDF1] 联控连接失败,盲盒作废"); } + if (tryCyActivate(p, rs, rd)) { consumeCode(code, oneTime); p.sendMessage("§6§l[SDF1] §e§l恭喜!获得 §c§l" + rd + "天会员 + " + rs + "格空间 §e§l!"); } + else { p.sendMessage("§c[SDF1] 联控连接失败,盲盒作废"); } } }, 20L); } }, 20L); } }, 20L); @@ -673,51 +667,201 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { private boolean tryCyActivate(Player p, int slots, int days) { if (!isCyConnected()) { discoverCyPlugin(); if (!isCyConnected()) { p.sendMessage("§c[SDF1] 联控未连接,跳过"); return false; } } try { discoveredCyActivate.invoke(discoveredCy, p.getName(), slots, days); return true; } - catch (Exception e) { p.sendMessage("§c[SDF1] 联控失败,跳过"); log("[联控] 失败: " + e.getMessage()); return false; } + catch (Exception e) { p.sendMessage("§c[SDF1] 联控失败"); log("[联控] 失败: " + e.getMessage()); return false; } } private void execDelete(Player p, ActionEntry a, boolean oneTime, String code) { log("[删除] " + p.getName() + " 口令: \"" + code + "\""); consumeCode(code, true); } - - // ===== 插件事件 ===== @EventHandler public void onPluginEnable(PluginEnableEvent event) { String name = event.getPlugin().getName(); - for (String n : CY_DISCOVER_NAMES) { - if (name.equalsIgnoreCase(n)) { log("[联控] 检测到 " + name); discoverCyPlugin(); setupCyReflection(); return; } - } + for (String n : CY_DISCOVER_NAMES) { if (name.equalsIgnoreCase(n)) { log("[联控] 检测到 " + name); discoverCyPlugin(); setupCyReflection(); return; } } } @EventHandler public void onPluginDisableEvent(PluginDisableEvent event) { String name = event.getPlugin().getName(); - if (cyPlugin != null && name.equals(cyPlugin.getName())) { log("[联控] " + name + " 卸载"); cyPlugin = null; cyGiveSlots = null; } + if (cyPlugin != null && name.equals(cyPlugin.getName())) { cyPlugin = null; cyGiveSlots = null; } if (discoveredCy != null && name.equals(discoveredCy.getName())) { discoveredCy = null; discoveredCyActivate = null; discoveredCyPing = null; } } // ===== 指令 ===== + // ===== SECTION: 命令处理 ===== + @Override public boolean onCommand(CommandSender s, Command c, String l, String[] a) { - if (a.length == 0) { - if (s instanceof Player) { Player p = (Player) s; if (!configLoaded) { p.sendMessage("§c未加载"); return true; } if (cfgCdkObj.isEmpty()) { p.sendMessage("§c未配置"); return true; } startListening(p); } - else { s.sendMessage("[SDF1] v" + cfgVer + " rules=" + scoreMap.size() + " 联控:" + (isCyConnected() ? "是" : "否") + " Vault:" + (economy != null ? "是" : "否")); } + + // /import <文件名> — 独立命令入口 + if (c.getName().equalsIgnoreCase("import")) { + if (!checkAdminSilent(s)) { showHelp(s); return true; } + if (a.length < 1) { s.sendMessage("§c用法: /import <文件名.txt>"); return true; } + execImport(s, a[0]); return true; } - String cmd = a[0].toLowerCase(); - if (cmd.equals("reload")) { - if (!s.isOp()) { s.sendMessage("§c仅OP"); return true; } - scoreMap.clear(); configLoaded = false; cdksWarned = false; listening.clear(); failCount = 0; circuitBroken = false; - loadConfig(true); setupCyReflection(); discoverCyPlugin(); setupEconomy(); + + // /sdf1 系列 + if (a.length == 0) { + if (s instanceof Player) { + Player p = (Player) s; + if (!configLoaded) { p.sendMessage("§c未加载"); return true; } + if (cfgCdkObj.isEmpty()) { p.sendMessage("§c未配置"); return true; } + startListening(p); + } else { + showHelp(s); + } + return true; + } + + String sub = a[0].toLowerCase(); + + // shop/listen/status — 所有人可用 + if (sub.equals("listen")) { + if (!(s instanceof Player)) { s.sendMessage("§c仅玩家"); return true; } + startListening((Player) s); + return true; + } + if (sub.equals("status")) { + s.sendMessage("[SDF1] v" + cfgVer + + " 计分板:" + cfgCdkObj + + " 记名板:" + (cfgNameBoard.isEmpty() ? "(未设置)" : cfgNameBoard) + + " 规则:" + scoreMap.size() + + " 联控:" + cyPing() + + " Vault:" + (economy != null ? economy.getName() : "无")); + return true; + } + + // 以下命令需要管理员身份,无权限静默返回帮助 + if (!checkAdminSilent(s)) { showHelp(s); return true; } + + if (sub.equals("reload")) { + scoreMap.clear(); + configLoaded = false; + cdksWarned = false; + listening.clear(); + failCount = 0; + circuitBroken = false; + loadConfig(true); + setupCyReflection(); + discoverCyPlugin(); + setupEconomy(); s.sendMessage("[SDF1] 重载 v" + cfgVer + " 规则:" + scoreMap.size()); - } else if (cmd.equals("update")) { if (!s.isOp()) { s.sendMessage("§c仅OP"); return true; } checkUpdate(s); } - else if (cmd.equals("listen")) { if (!(s instanceof Player)) { s.sendMessage("§c仅玩家"); return true; } startListening((Player) s); } - else if (cmd.equals("status")) { s.sendMessage("[SDF1] v" + cfgVer + " 计分板:" + cfgCdkObj + " 规则:" + scoreMap.size() + " 联控:" + cyPing() + " Vault:" + (economy != null ? economy.getName() : "无")); } - else s.sendMessage("[SDF1] /sdf1 [listen|reload|update|status]"); + return true; + } + if (sub.equals("update")) { checkUpdate(s); return true; } + if (sub.equals("get")) { execGet(s); return true; } + if (sub.equals("import")) { + if (a.length < 2) { s.sendMessage("§c用法: /sdf1 import <文件名.txt>"); return true; } + execImport(s, a[1]); + return true; + } + + showHelp(s); return true; } + /** 根据权限显示对应帮助 */ + private void showHelp(CommandSender s) { + if (checkAdminSilent(s)) { + s.sendMessage("§e/sdf1 - 打开口令监听"); + s.sendMessage("§e/sdf1 status - 查看状态"); + s.sendMessage("§e/sdf1 listen - 开启监听"); + s.sendMessage("§e/sdf1 reload - 重载配置"); + s.sendMessage("§e/sdf1 get - 查看口令库存"); + s.sendMessage("§e/sdf1 import <文件> - 导入口令"); + s.sendMessage("§e/import <文件> - 导入口令(独立命令)"); + s.sendMessage("§e/sdf1 update - 检查更新"); + } else { + s.sendMessage("§e/sdf1 - 打开口令监听"); + s.sendMessage("§e/sdf1 status - 查看状态"); + s.sendMessage("§e/sdf1 listen - 开启监听"); + } + } + + + private void execImport(CommandSender s, String fileName) { + if (cfgCdkObj.isEmpty()) { s.sendMessage("§c计分板未配置"); return; } + File f = new File(getDataFolder(), fileName); + if (!f.exists()) { s.sendMessage("§c文件不存在: " + fileName); return; } + try { + BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8)); + String line; + int count = 0, skip = 0; + int currentScore = 1; + + Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + Objective obj = board.getObjective(cfgCdkObj); + if (obj == null) { s.sendMessage("§c计分板目标不存在: " + cfgCdkObj); r.close(); return; } + + while ((line = r.readLine()) != null) { + line = line.trim(); + if (line.isEmpty() || line.startsWith("#") || line.startsWith("//")) continue; + + // 分隔符 → 重置为1分 + if (line.equals("--") || line.equals("---")) { currentScore = 1; continue; } + + // 块头: "2分:" / "5分:" / "10分" + Matcher blockHead = Pattern.compile("^(\\d+)\\s*分\\s*[::]?\\s*$").matcher(line); + if (blockHead.matches()) { + currentScore = Math.max(1, Integer.parseInt(blockHead.group(1))); + continue; + } + + // 行内分数: "cdk1|cdk2 2分" + int scoreForLine = currentScore; + String codeLine = line; + Matcher inlineScore = Pattern.compile("^(.+?)\\s+(\\d+)\\s*分\\s*$").matcher(line); + if (inlineScore.matches()) { + codeLine = inlineScore.group(1).trim(); + scoreForLine = Math.max(1, Integer.parseInt(inlineScore.group(2))); + } + + // 按分隔符拆分口令 + String[] parts = codeLine.split("[|,,、;;]+"); + for (String part : parts) { + part = part.replaceAll("^[((【{\\[「『\"]+", "").replaceAll("[))】}\\]」』\"]+$", "").trim(); + part = part.replaceAll("^[-*•·>►▶]+\\s*", "").trim(); + if (part.isEmpty()) continue; + try { + int oldScore = obj.getScore(part).isScoreSet() ? obj.getScore(part).getScore() : 0; + if (oldScore > 0) { skip++; continue; } + obj.getScore(part).setScore(scoreForLine); + count++; + } catch (Exception e) { skip++; } + } + } + r.close(); + s.sendMessage("§a[SDF1] 导入完成: 新增 " + count + " 条,跳过 " + skip + " 条"); + log("[导入] " + s.getName() + " " + fileName + " 新增=" + count + " 跳过=" + skip); + } catch (Exception e) { s.sendMessage("§c读取失败: " + e.getMessage()); } + } + + private void execGet(CommandSender s) { + if (cfgCdkObj.isEmpty()) { s.sendMessage("§c计分板未配置"); return; } + try { Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + Objective obj = board.getObjective(cfgCdkObj); + if (obj == null) { s.sendMessage("§c计分板目标不存在: " + cfgCdkObj); return; } + + int total = 0; + // 遍历计分板全部条目,统计有分值的数量(全版本兼容) + for (String entry : board.getEntries()) { + try { + Score sc = obj.getScore(entry); + if (sc.isScoreSet()) total++; + } catch (Exception ignored) {} + } + + s.sendMessage("§a[SDF1] 口令库: " + cfgCdkObj); + s.sendMessage("§a[SDF1] 存货量: " + total + " 条"); + s.sendMessage("§a[SDF1] 规则数: " + scoreMap.size()); + if (!cfgNameBoard.isEmpty()) s.sendMessage("§a[SDF1] 记名板: " + cfgNameBoard); + } catch (Exception e) { s.sendMessage("§c查询失败: " + e.getMessage()); } + } + + + + // ===== 更新检查 ===== private void checkUpdate(final CommandSender manual) { new Thread(new Runnable() { public void run() { @@ -732,40 +876,19 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } }).start(); } private String[] fetchRelease(String apiUrl, String ch) { - try { - TrustManager[] trustAll = new TrustManager[]{ new X509TrustManager() { - public X509Certificate[] getAcceptedIssuers() { return null; } - public void checkClientTrusted(X509Certificate[] c, String a) {} - public void checkServerTrusted(X509Certificate[] c, String a) {} - }}; - SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, trustAll, new java.security.SecureRandom()); + try { TrustManager[] trustAll = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] c, String a) {} public void checkServerTrusted(X509Certificate[] c, String a) {} } }; + SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAll, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() { - public boolean verify(String h, javax.net.ssl.SSLSession s) { return true; } - }); + HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() { public boolean verify(String h, javax.net.ssl.SSLSession s) { return true; } }); HttpURLConnection c = (HttpURLConnection) new URL(apiUrl).openConnection(); - c.setRequestMethod("GET"); - c.setRequestProperty("User-Agent", "SDF1-Plugin/1.0"); - c.setRequestProperty("Accept", "application/json"); - c.setConnectTimeout(15000); - c.setReadTimeout(15000); - c.setInstanceFollowRedirects(true); - if (c.getResponseCode() != 200) { - log("[更新] " + ch + " HTTP " + c.getResponseCode()); - return null; - } + c.setRequestMethod("GET"); c.setRequestProperty("User-Agent", "SDF1-Plugin/1.0"); c.setRequestProperty("Accept", "application/json"); + c.setConnectTimeout(15000); c.setReadTimeout(15000); c.setInstanceFollowRedirects(true); + if (c.getResponseCode() != 200) { log("[更新] " + ch + " HTTP " + c.getResponseCode()); return null; } String json = new String(c.getInputStream().readAllBytes(), StandardCharsets.UTF_8); - String rv = jParse(json, "tag_name"); - String rn = jParse(json, "body"); - if (rv == null || rv.isEmpty()) return null; - return new String[]{rv, rn != null ? rn : ""}; - } catch (Exception e) { - log("[更新] " + ch + " " + e.getMessage()); - return null; - } + String rv = jParse(json, "tag_name"); String rn = jParse(json, "body"); + if (rv == null || rv.isEmpty()) return null; return new String[]{rv, rn != null ? rn : ""}; + } catch (Exception e) { log("[更新] " + ch + " " + e.getMessage()); return null; } } - private void applyUpdate(String rv, String notes, String dlLink, CommandSender manual, String ch) { remoteVer = rv; if (!rv.equals(String.valueOf(cfgVer))) { String msg = "[SDF1] 新版本! v" + cfgVer + " -> v" + rv; log(msg); log("下载: " + dlLink); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index cf8a3a7..8b657a3 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -10,6 +10,10 @@ commands: usage: /sdf1 permission: cy.use permission-message: §c你没有权限使用此命令 + import: + description: 导入口令 + permission: import.op + permission-message: 无权限 permissions: sdf1.use: description: 使用 /sdf1 基础命令