优化PVP世界创建:关闭结构生成+简化安全出生点,消除主线程长时卡服

- createPVPWorld: 加 c.generateStructures(false),去除村庄/神庙/矿洞等结构生成(出生点搜索时单区块十几秒卡死的主因);hill/water/cave/tree 自然地形特征不受影响

- forceSafeSpawn: 删除半径8广域扫描(289列同步区块生成),改为仅检查Minecraft已生成的(0,0)出生列,不安全才原地搭3x3小平台(O(1)零额外生成)

- 预生成半径 4->2(25区块),进一步缩短主线程占用
This commit is contained in:
2026-07-09 00:37:12 +08:00
parent 7a14457713
commit dfd8fee381
+28 -25
View File
@@ -284,6 +284,10 @@ public class PVPArenaManager implements Listener {
// ★ 真实自然地形:丘陵/水域/洞穴/树木由 Minecraft 生成(非人造) // ★ 真实自然地形:丘陵/水域/洞穴/树木由 Minecraft 生成(非人造)
c.type(WorldType.NORMAL); c.type(WorldType.NORMAL);
c.seed(seed); c.seed(seed);
// ★ 关键性能:关闭村庄/神庙/矿洞等结构生成。结构生成是每次 createWorld 出生点搜索时
// 单个区块被拖到十几秒卡死的主因。hill/water/cave/tree 等自然地形特征不受影响,
// 仍保持"真实自然地形",只是不再生成人造结构。
c.generateStructures(false);
// 注意:Paper 26.x 已移除 WorldCreator.keepSpawnInMemory(boolean),改由 reapplyWorldRules 的 setKeepSpawnInMemory(false) 控制 // 注意:Paper 26.x 已移除 WorldCreator.keepSpawnInMemory(boolean),改由 reapplyWorldRules 的 setKeepSpawnInMemory(false) 控制
plugin.getLogger().info("[PVP] 生成PVP竞技场世界 " + pvpWorldName + " 种子=" + seed + " (NORMAL真实自然地形, 主线程同步createWorld)"); plugin.getLogger().info("[PVP] 生成PVP竞技场世界 " + pvpWorldName + " 种子=" + seed + " (NORMAL真实自然地形, 主线程同步createWorld)");
@@ -296,8 +300,8 @@ public class PVPArenaManager implements Listener {
// ★ 固化安全出生点:中心半径找实体非流体方块;找不到兜底在 (0,24,0) 搭平台(不再"水→删除重建"导致多次 createWorld) // ★ 固化安全出生点:中心半径找实体非流体方块;找不到兜底在 (0,24,0) 搭平台(不再"水→删除重建"导致多次 createWorld)
forceSafeSpawn(pvpWorld); forceSafeSpawn(pvpWorld);
// 同步分批预生成周边区块(每 tick 一行,不冻服) // 同步分批预生成出生点周边区块(半径2=5×5=25个,每 tick 一行,均摊不冻服)
preGenerateSpawnChunksAsync(pvpWorld, 4); preGenerateSpawnChunksAsync(pvpWorld, 2);
reapplyWorldRules(pvpWorld); reapplyWorldRules(pvpWorld);
plugin.getLogger().info("[PVP] PVP竞技场世界就绪 种子=" + seed + " 耗时=" + dt + "ms(NORMAL真实自然地形, 出生点已固化)"); plugin.getLogger().info("[PVP] PVP竞技场世界就绪 种子=" + seed + " 耗时=" + dt + "ms(NORMAL真实自然地形, 出生点已固化)");
@@ -305,34 +309,33 @@ public class PVPArenaManager implements Listener {
} }
/** /**
* 固化PVP世界出生点:在中心半径内寻找第一个"实体且非流体"的方块作为出生点。 * 固化PVP世界出生点:仅检查 Minecraft 出生点搜索已确定的出生列(位于已生成的 (0,0) 区块内,
* 找不到则强制在中心 (0,24,0) 搭建安全平台。 * 不会触发任何额外区块生成),安全则保留天然地形并抬高 1 格;仅当该列不安全时才在出生点
* 目的:彻底规避原 NORMAL 世界"出生点为水→删除重建换种子"导致的 13s 主线程卡服。 * 原地搭 3×3 小平台。★ 绝不再做半径 8 的广域扫描(旧实现会触发 289 列同步区块生成,是卡服主因之一)。
*/ */
private void forceSafeSpawn(World world) { private void forceSafeSpawn(World world) {
int maxR = 8; Location spawn = world.getSpawnLocation();
for (int rad = 0; rad <= maxR; rad++) { int x = spawn.getBlockX();
for (int dx = -rad; dx <= rad; dx++) { int z = spawn.getBlockZ();
for (int dz = -rad; dz <= rad; dz++) { int top = getTopSolidY(world, x, z);
if (rad > 0 && Math.abs(dx) != rad && Math.abs(dz) != rad) continue; // 仅遍历当前环 Material m = world.getBlockAt(x, top, z).getType();
int top = getTopSolidY(world, dx, dz); if (m.isSolid() && !isFluid(m)) {
Material m = world.getBlockAt(dx, top, dz).getType(); // 出生列已安全,保留天然地形,仅把出生点设在方块顶部上方 1 格
if (m.isSolid() && !isFluid(m)) { world.setSpawnLocation(x, top + 1, z);
world.setSpawnLocation(dx, top + 1, dz); return;
return; }
} // 兜底:仅在出生点原地搭 3×3 安全平台(只动这一处,O(1),零额外区块生成)
int sy = Math.max(top + 1, 64);
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
for (int y = sy - 3; y <= sy; y++) {
Block b = world.getBlockAt(x + dx, y, z + dz);
b.setType(y == sy ? Material.GRASS_BLOCK : Material.STONE);
} }
} }
} }
// 兜底:中心安全平台 for (int y = sy + 1; y <= sy + 4; y++) world.getBlockAt(x, y, z).setType(Material.AIR);
int sy = 24; world.setSpawnLocation(x, sy + 1, z);
for (int y = 0; y <= sy; y++) {
Block b = world.getBlockAt(0, y, 0);
b.setType(y == sy ? Material.GRASS_BLOCK : (y == 0 ? Material.BEDROCK : Material.STONE));
}
for (int y = sy + 1; y <= sy + 4; y++) world.getBlockAt(0, y, 0).setType(Material.AIR);
world.setSpawnLocation(0, sy + 1, 0);
plugin.getLogger().warning("[PVP] 未找到天然安全出生点,已生成中心兜底平台");
} }
/** 是否为实体(固体)方块:玩家可站立的地面。水/空气/岩浆等非固体返回 false */ /** 是否为实体(固体)方块:玩家可站立的地面。水/空气/岩浆等非固体返回 false */