修复PVP世界生成小平台问题:先强制生成出生点区块再寻找安全点,避免误判虚空铺设漂浮平台(#735)

This commit is contained in:
2026-07-06 19:27:03 +08:00
parent 24e5248cec
commit 035dd418fc
+36 -6
View File
@@ -166,13 +166,17 @@ public class PVPArenaManager implements Listener {
pvpWorld.setGameRule(GameRule.DO_WEATHER_CYCLE, false); pvpWorld.setGameRule(GameRule.DO_WEATHER_CYCLE, false);
pvpWorld.setTime(6000); // 中午 pvpWorld.setTime(6000); // 中午
// 设置出生点(在正常地形中找安全位置或用默认) // ★ 关键修复:先强制同步生成出生点周边区块,否则新世界区块尚未加载,
// getBlockAt 全为空气 → findSafeSpawn 返回 null → 误铺漂浮小平台
preGenerateSpawnChunks(pvpWorld);
// 设置出生点(在正常地形中找安全位置)
Location spawnLoc = findSafeSpawn(pvpWorld); Location spawnLoc = findSafeSpawn(pvpWorld);
if (spawnLoc != null) { if (spawnLoc != null) {
pvpWorld.setSpawnLocation(spawnLoc.getBlockX(), spawnLoc.getBlockY(), spawnLoc.getBlockZ()); pvpWorld.setSpawnLocation(spawnLoc.getBlockX(), spawnLoc.getBlockY(), spawnLoc.getBlockZ());
} else { } else {
pvpWorld.setSpawnLocation(0, 100, 0); pvpWorld.setSpawnLocation(0, 100, 0);
// 如果默认高度没有地面,铺设平台保底 // 极端兜底:仍未找到地面才铺平台(正常情况不会触发)
buildFallbackPlatform(pvpWorld); buildFallbackPlatform(pvpWorld);
} }
@@ -184,21 +188,47 @@ public class PVPArenaManager implements Listener {
} }
/** /**
* 在世界中寻找安全的出生点(优先找地面位置) * 强制同步生成出生点周边区块(3x3),确保地形已存在后再寻找安全出生点
* 必须在主线程调用(命令处理阶段)
*/
private void preGenerateSpawnChunks(World world) {
int cx = world.getSpawnLocation().getBlockX() >> 4;
int cz = world.getSpawnLocation().getBlockZ() >> 4;
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
try {
world.loadChunk(cx + dx, cz + dz, true);
} catch (Exception e) {
plugin.getLogger().warning("[PVP] 生成区块失败: " + (cx + dx) + "," + (cz + dz));
}
}
}
}
/**
* 在世界中寻找安全的出生点(优先找最高的非空气且非流体方块作为地面)
*/ */
private Location findSafeSpawn(World world) { private Location findSafeSpawn(World world) {
int spawnX = world.getSpawnLocation().getBlockX(); int spawnX = world.getSpawnLocation().getBlockX();
int spawnZ = world.getSpawnLocation().getBlockZ(); int spawnZ = world.getSpawnLocation().getBlockZ();
// 在出生点附近搜索最高的固体方块 // 从顶部向下扫描整列,找到最高的固体地面(跳过空气与流体)
for (int y = 255; y >= 60; y--) { for (int y = 255; y >= 1; y--) {
Block block = world.getBlockAt(spawnX, y, spawnZ); Block block = world.getBlockAt(spawnX, y, spawnZ);
if (!block.getType().isAir()) { Material type = block.getType();
if (!type.isAir() && !isFluid(type)) {
return new Location(world, spawnX + 0.5, y + 1, spawnZ + 0.5); return new Location(world, spawnX + 0.5, y + 1, spawnZ + 0.5);
} }
} }
return null; // 未找到安全地面 return null; // 未找到安全地面
} }
/**
* 判断方块是否为流体(水/熔岩),流体上不适合作为安全出生地面
*/
private boolean isFluid(Material type) {
return type == Material.WATER || type == Material.LAVA;
}
/** /**
* 保底平台:如果出生点下方全是空气则铺一个平台 * 保底平台:如果出生点下方全是空气则铺一个平台
*/ */