From 7631e30e2aabcdac8ce3cf9ad38f5fa76718dfa5 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Wed, 8 Jul 2026 10:57:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20PVP=E6=98=BE=E5=BC=8F?= =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E7=A7=8D=E5=AD=90(=E6=A0=B9=E9=99=A4?= =?UTF-8?q?=E5=9B=BA=E5=AE=9A-5092=E7=A7=8D=E5=AD=90)=20+=20=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E6=8E=A7=E5=88=B6=E5=8F=B0=E6=8C=87=E4=BB=A4+?= =?UTF-8?q?=E7=8E=A9=E5=AE=B6=E5=90=8D=E5=8F=98=E9=87=8F=20+=20=E5=95=86?= =?UTF-8?q?=E5=BA=97=E8=B7=B3=E8=BF=87.web.md(PHP=E4=B8=93=E5=B1=9E?= =?UTF-8?q?=E5=95=86=E5=93=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PVPArenaManager: createPVPWorld改用worldSeedRandom.nextLong()显式设定随机种子(用户实测连续多次createWorld返回相同种子-5092048402667366605);增加删除后验证日志(确认目录消失或告警) - Main.java(两处菜单点击): 新增permType提取→控制台/console身份执行(Bukkit.getConsoleSender);玩家名变量替换{player}/%player%//[player]/(player)等所有括号形式 - ShopManager: loadCategories文件过滤器增加!.web.md条件,游戏内不加载.web.md文件(PHP端专属商品) --- src/main/java/Sdf1_login/Main.java | 46 ++++++++++++++++++- src/main/java/Sdf1_login/PVPArenaManager.java | 20 +++++++- src/main/java/Sdf1_login/ShopManager.java | 6 ++- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/src/main/java/Sdf1_login/Main.java b/src/main/java/Sdf1_login/Main.java index 8263950..df9f47f 100644 --- a/src/main/java/Sdf1_login/Main.java +++ b/src/main/java/Sdf1_login/Main.java @@ -3573,6 +3573,14 @@ public class Main extends JavaPlugin p.sendMessage("§c指令为空"); return; } + // ★ 提取权限类型(控制台/玩家/OP) + String permType = "玩家"; + for (String pl : subLm.getLore()) { + if (pl.contains("§7权限: §f")) { + permType = pl.replace("§7权限: §f", "").trim(); + break; + } + } p.closeInventory(); if (cmd.startsWith("/")) { cmd = cmd.substring(1); @@ -3581,7 +3589,20 @@ public class Main extends JavaPlugin if (cmd.endsWith(".txt")) { gui.openSubMenu(p, cmd); } else { - Bukkit.dispatchCommand(p, cmd); + // ★ 替换玩家名变量:{player} %player% [player] (player) 等 + String playerName = p.getName(); + cmd = cmd.replaceAll("\\{player\\}", playerName) + .replaceAll("%player%", playerName) + .replaceAll("", playerName) + .replaceAll("\\[player\\]", playerName) + .replaceAll("\\(player\\)", playerName); + // ★ 根据权限类型选择执行身份 + if ("控制台".equals(permType) || "console".equalsIgnoreCase(permType)) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd); + p.sendMessage("§a[菜单] 已以控制台身份执行: /" + cmd); + } else { + Bukkit.dispatchCommand(p, cmd); + } } return; } @@ -3840,6 +3861,14 @@ public class Main extends JavaPlugin p.sendMessage("§c指令为空"); return; } + // ★ 提取权限类型(控制台/玩家/OP) + String permType = "玩家"; + for (String pl : meta.getLore()) { + if (pl.contains("§7权限: §f")) { + permType = pl.replace("§7权限: §f", "").trim(); + break; + } + } p.closeInventory(); if (cmd.startsWith("/")) { cmd = cmd.substring(1); @@ -3847,7 +3876,20 @@ public class Main extends JavaPlugin if (cmd.endsWith(".txt")) { gui.openSubMenu(p, cmd); } else { - Bukkit.dispatchCommand(p, cmd); + // ★ 替换玩家名变量 + String playerName = p.getName(); + cmd = cmd.replaceAll("\\{player\\}", playerName) + .replaceAll("%player%", playerName) + .replaceAll("", playerName) + .replaceAll("\\[player\\]", playerName) + .replaceAll("\\(player\\)", playerName); + // ★ 根据权限类型选择执行身份 + if ("控制台".equals(permType) || "console".equalsIgnoreCase(permType)) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd); + p.sendMessage("§a[菜单] 已以控制台身份执行: /" + cmd); + } else { + Bukkit.dispatchCommand(p, cmd); + } } return; } diff --git a/src/main/java/Sdf1_login/PVPArenaManager.java b/src/main/java/Sdf1_login/PVPArenaManager.java index e8dd3b2..19dc049 100644 --- a/src/main/java/Sdf1_login/PVPArenaManager.java +++ b/src/main/java/Sdf1_login/PVPArenaManager.java @@ -241,14 +241,30 @@ public class PVPArenaManager implements Listener { WorldCreator creator = new WorldCreator(PVP_WORLD_NAME); creator.environment(World.Environment.NORMAL); creator.type(WorldType.NORMAL); - // ★ 不设 seed:让 MC 自行随机决定地形种子(插件对地形零干预)。 - // 创建后通过 getSeed() 读取 MC 选定的种子并记录日志,便于排查"出生点脚下是水"的失败种子。 + // ★ 显式设置随机种子:避免 MC 内部 RNG 在特定条件下产生相同种子导致地形重复。 + // 用户实测发现连续多次 createWorld 返回相同种子(-5092048402667366605), + // 显式指定 worldSeedRandom.nextLong() 保证每次地形不同。 + long seed = worldSeedRandom.nextLong(); + creator.seed(seed); + plugin.getLogger().info("[PVP] 显式设定种子=" + seed + " (确保每次地形不同)"); // ★ 彻底清理磁盘上可能残留的旧世界目录:旧版本曾干预出生点(setSpawnLocation)并强制造陆, // 若上次删除因 Windows 文件锁失败,createWorld 会误加载到旧世界(出生点被锁定/小岛地形)。 // 这里重试删除确保目录消失,保证每次进入都是 MC 自然生成的全新主世界与自然出生点。 deleteExistingPVPWorldFolder(); + // ★ 验证:确认旧目录确实已消失 + File folder = new File(Bukkit.getWorldContainer(), PVP_WORLD_NAME); + if (folder.exists()) { + plugin.getLogger().severe("[PVP] ⚠ 警告:deleteExistingPVPWorldFolder 执行后 pvp_arena 目录仍然存在!createWorld 可能复用旧世界"); + moveWorldToTrash(folder); + if (folder.exists()) { + plugin.getLogger().severe("[PVP] ❌ 无法删除 pvp_arena 目录,本次可能仍会使用旧地形/旧种子"); + } + } else { + plugin.getLogger().info("[PVP] ✅ 确认旧 pvp_arena 目录已清除,将生成全新世界"); + } + World pvpWorld = creator.createWorld(); long dt = System.currentTimeMillis() - t0; if (pvpWorld == null) { diff --git a/src/main/java/Sdf1_login/ShopManager.java b/src/main/java/Sdf1_login/ShopManager.java index a147380..0460866 100644 --- a/src/main/java/Sdf1_login/ShopManager.java +++ b/src/main/java/Sdf1_login/ShopManager.java @@ -985,12 +985,14 @@ public class ShopManager implements Listener { File[] allMd = dir.listFiles( (d, n) -> n.endsWith(".md") - && !n.equals("coupons.md")); + && !n.equals("coupons.md") + && !n.contains(".web")); // ★ 跳过 .web.md 文件(PHP专属商品,游戏内不加载) if (allMd == null || allMd.length == 0) { createDefaultCategories(dir); allMd = dir.listFiles( (d, n) -> n.endsWith(".md") - && !n.equals("coupons.md")); + && !n.equals("coupons.md") + && !n.contains(".web")); // ★ 跳过 .web.md(PHP专属商品) } if (allMd == null) { plugin.getLogger().warning(