diff --git a/.idea/misc.xml b/.idea/misc.xml index fdc35ea..0c04b52 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 04ec7ee..b920fdd 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ jar - 21 + 25 UTF-8 @@ -37,10 +37,10 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.14.0 - 21 - 21 + 25 + 25 diff --git a/src/main/java/Sdf1_game/Main.java b/src/main/java/Sdf1_game/Main.java index ed3de4d..7a872b3 100644 --- a/src/main/java/Sdf1_game/Main.java +++ b/src/main/java/Sdf1_game/Main.java @@ -897,8 +897,6 @@ public class Main extends JavaPlugin } return r; } - - return r; } diff --git a/src/main/java/Sdf1_game/TreasureInventory.java b/src/main/java/Sdf1_game/TreasureInventory.java index b7c778f..7a298b8 100644 --- a/src/main/java/Sdf1_game/TreasureInventory.java +++ b/src/main/java/Sdf1_game/TreasureInventory.java @@ -588,11 +588,15 @@ public class TreasureInventory { player.getInventory() .addItem(give); - // 限时物品记录领取限制 - if (r.getDurationSec() > 0) { + // ★ 限时/限次物品记录领取限制(有时限 或 有攻击次数 都要记录) + if (r.getDurationSec() > 0 + || r.getAttackUsesLimit() > 0) { tm.claim(player.getName(), r.getDisplayName(), config.name); + tm.addClaim(player.getName(), + r.getDisplayName(), + config.name); } msg.append("§a✓ ") diff --git a/src/main/java/Sdf1_game/TreasureListener.java b/src/main/java/Sdf1_game/TreasureListener.java index 30bf75f..f565da7 100644 --- a/src/main/java/Sdf1_game/TreasureListener.java +++ b/src/main/java/Sdf1_game/TreasureListener.java @@ -476,9 +476,10 @@ public class TreasureListener implements Listener { // ========== 4. 确认是容器 ========== InventoryType topType = e.getView() .getTopInventory().getType(); - // 只放行玩家背包和创造模式背包,其他所有容器都拦截 + // 只放行玩家背包、创造模式背包和玩家合成背包,其他所有容器都拦截 if (topType == InventoryType.PLAYER - || topType == InventoryType.CREATIVE) { + || topType == InventoryType.CREATIVE + || topType == InventoryType.CRAFTING) { return; } diff --git a/src/main/java/Sdf1_game/TreasureManager.java b/src/main/java/Sdf1_game/TreasureManager.java index 2838d26..60701bf 100644 --- a/src/main/java/Sdf1_game/TreasureManager.java +++ b/src/main/java/Sdf1_game/TreasureManager.java @@ -210,6 +210,7 @@ public class TreasureManager { /** 加载领取记录 */ private void loadClaims() { claimedSet.clear(); + claimDb.clear(); if (!claimFile.exists()) return; try { BufferedReader br = new BufferedReader( @@ -219,9 +220,14 @@ public class TreasureManager { String line; while ((line = br.readLine()) != null) { line = line.trim(); - if (!line.isEmpty() - && !line.startsWith("#")) { + if (line.isEmpty() || line.startsWith("#")) + continue; + if (line.contains("|")) { + // claimedSet 格式: 玩家|物品|区域 claimedSet.add(line); + } else if (line.contains(".")) { + // claimDb 格式: 玩家.物品.区域 + claimDb.put(line, true); } } br.close(); @@ -231,9 +237,8 @@ public class TreasureManager { } } public void reload() { - // ★ 先清内存 - claimDb.clear(); - saveClaims(); // 写空文件 + // ★ 先销毁领取记录文件并清空所有内存 + forceCleanClaims(); // 清除玩家背包里的自定义物品 for (org.bukkit.entity.Player p : @@ -546,11 +551,12 @@ public class TreasureManager { } // ★ 检查2: 无领取记录→视为过期 - if (!shouldRemove - && !isClaimed(playerName, - rName, region)) { - shouldRemove = true; - reason = "无领取记录(过期/重载)"; + // 宝箱物品(区域名含"宝箱")不需要领取限制 + if (!shouldRemove && !isTreasureItem(playerName, region)) { + if (!isClaimed(playerName, rName, region)) { + shouldRemove = true; + reason = "无领取记录(过期/重载)"; + } } // 检查3: 已过期 @@ -620,9 +626,21 @@ public class TreasureManager { public boolean isClaimed(String player, String itemName, String regionName) { - String key = player + "." - + itemName + "." + regionName; - return claimDb.containsKey(key); + // ★ 检查claimDb(限时物品) + String key = player + "." + itemName + "." + regionName; + if (claimDb.containsKey(key)) return true; + + // ★ 检查claimedSet(寻宝物品/宝箱物品) + String key2 = player + "|" + itemName + "|" + regionName; + return claimedSet.contains(key2); + } + + /** 检查是否是宝箱物品(不检查领取限制) */ + public boolean isTreasureItem(String playerName, + String regionName) { + // 宝箱物品区域名包含"宝箱"或" Treasure"关键词 + return regionName != null && + (regionName.contains("宝箱") || regionName.contains("Treasure")); } @@ -900,7 +918,7 @@ public class TreasureManager { } public void forceCleanClaims() { - // ★ 暴力方案:直接删文件再重建 + // ★ 暴力方案:直接删文件再重建,清空所有内存 if (claimFile.exists()) { boolean deleted = claimFile.delete(); plugin.getLogger().info( @@ -918,6 +936,7 @@ public class TreasureManager { + e.getMessage()); } claimedSet.clear(); + claimDb.clear(); } /** @@ -1571,9 +1590,14 @@ public class TreasureManager { try { FileWriter fw = new FileWriter( claimFile); + // 保存 claimDb(限时物品,用 . 分隔) for (String key : claimDb.keySet()) { fw.write(key + "\n"); } + // 保存 claimedSet(寻宝物品,用 | 分隔) + for (String key : claimedSet) { + fw.write(key + "\n"); + } fw.close(); } catch (IOException e) { plugin.getLogger().warning( diff --git a/src/main/java/Sdf1_game/UpdateChecker.java b/src/main/java/Sdf1_game/UpdateChecker.java index 8da3c7a..c6ff6c1 100644 --- a/src/main/java/Sdf1_game/UpdateChecker.java +++ b/src/main/java/Sdf1_game/UpdateChecker.java @@ -55,6 +55,10 @@ public class UpdateChecker { private static final String GITEE_API = "https://gitee.com/api/v5/repos/" + GITEE_OWNER + "/" + GITEE_REPO + "/releases/latest"; + // 第三路备选:宝塔静态HTML + private static final String FALLBACK_HTML = + "https://caoyuan.ypshidifu.cn/update_check.html"; + // 仓库页面链接 private static final String GITHUB_LINK = "https://github.com/" + GITHUB_OWNER + "/" + GITHUB_REPO + "/releases"; @@ -202,37 +206,47 @@ public class UpdateChecker { } else if (ge != null && ge.isSuccess()) { chosen = ge; } else { - // 双通道均失败 - failCount++; - StringBuilder sb = new StringBuilder(); - if (gh != null && gh.error != null) { - sb.append("§7GitHub: §c").append(gh.error); + // ★ 双通道均失败,尝试第三路备选(宝塔静态HTML) + plugin.getLogger().info("[Sdf1_game] GitHub/Gitee 均失败,尝试第三路备选 BaoTa..."); + CheckResult fbResult = tryFallbackChannel(); + if (fbResult != null && fbResult.isSuccess()) { + chosen = fbResult; + plugin.getLogger().info("[Sdf1_game] 第三路备选 BaoTa 检查成功: " + fbResult.version); + } else { + failCount++; + StringBuilder sb = new StringBuilder(); + if (gh != null && gh.error != null) { + sb.append("§7GitHub: §c").append(gh.error); + } + if (ge != null && ge.error != null) { + if (sb.length() > 0) sb.append("\n"); + sb.append("§7Gitee: §c").append(ge.error); + } + if (fbResult != null && fbResult.error != null) { + if (sb.length() > 0) sb.append("\n"); + sb.append("§7BaoTa: §c").append(fbResult.error); + } + if (failCount >= TRIP_THRESHOLD) { + circuitTripped = true; + plugin.getLogger().warning( + "[Sdf1_game] 更新检测已熔断,连续失败" + failCount + "次"); + scheduleRetry(); + } + if (sender != null) { + final String msg = sb.toString(); + final boolean tripped = circuitTripped; + final int fc = failCount; + Bukkit.getScheduler().runTask(plugin, () -> { + sender.sendMessage("§c§l[更新] 检测失败"); + sender.sendMessage(msg); + sender.sendMessage("§e失败次数: " + fc + "/" + TRIP_THRESHOLD); + if (tripped) { + sender.sendMessage("§c已熔断,2分钟后自动重试,或重启服务器重置"); + } + }); + } + return; } - if (ge != null && ge.error != null) { - if (sb.length() > 0) sb.append("\n"); - sb.append("§7Gitee: §c").append(ge.error); - } - if (failCount >= TRIP_THRESHOLD) { - circuitTripped = true; - plugin.getLogger().warning( - "[Sdf1_game] 更新检测已熔断,连续失败" + failCount + "次"); - // 熔断后安排2分钟后重试 - scheduleRetry(); - } - if (sender != null) { - final String msg = sb.toString(); - final boolean tripped = circuitTripped; - final int fc = failCount; - Bukkit.getScheduler().runTask(plugin, () -> { - sender.sendMessage("§c§l[更新] 检测失败"); - sender.sendMessage(msg); - sender.sendMessage("§e失败次数: " + fc + "/" + TRIP_THRESHOLD); - if (tripped) { - sender.sendMessage("§c已熔断,2分钟后自动重试,或重启服务器重置"); - } - }); - } - return; } // 至少一个通道成功 @@ -314,6 +328,83 @@ public class UpdateChecker { // ========== HTTP 请求 ========== + /** + * 第三路备选:从宝塔静态HTML解析版本信息 + * HTML中用 块 + String html = sb.toString(); + + // ★ 去除 Cloudflare 注入的 CDN-CGI 链接(...) + html = html.replaceAll("]*>[^<]*", ""); + + // 解析 块 + int start = html.indexOf(""); + if (start < 0 || end < 0 || end <= start) { + plugin.getLogger().warning("[Sdf1_game] BaoTa: 无法解析更新数据块"); + return new CheckResult(null, "BaoTa", FALLBACK_HTML, + "BaoTa: 无法解析更新数据块"); + } + String block = html.substring(start, end); + + // 逐行查找匹配当前插件名的记录 + String[] lines = block.split("\n"); + for (String l : lines) { + l = l.trim(); + // 跳过空行、注释标记行、HTML注入标签 + if (l.isEmpty() || l.startsWith("