fix(chunkloader): support trapdoor ceilings and creeper-specific spawning on simulated platforms

This commit is contained in:
Marcos Paulo
2026-08-20 20:20:59 -03:00
parent f35e4a5bff
commit 2a63a04e4f
2 changed files with 34 additions and 4 deletions
@@ -465,7 +465,7 @@ final class ChunkLoaders {
int baseZ = loader.chunkZ() << 4;
ThreadLocalRandom rnd = ThreadLocalRandom.current();
for (int i = 0; i < 2; i++) {
for (int i = 0; i < 4; i++) {
int rx = baseX + rnd.nextInt(16);
int rz = baseZ + rnd.nextInt(16);
int topY = Math.max(w.getMinHeight() + 2, Math.min(w.getMaxHeight() - 2, loader.y() + rnd.nextInt(-24, 25)));
@@ -474,15 +474,30 @@ final class ChunkLoaders {
Block space = w.getBlockAt(rx, topY, rz);
Block spaceAbove = w.getBlockAt(rx, topY + 1, rz);
if (!ground.getType().isSolid() || !space.getType().isAir() || !spaceAbove.getType().isAir()) {
if (!ground.getType().isSolid() || ground.isLiquid() || ground.getType() == Material.LAVA || ground.getType() == Material.WATER) {
continue;
}
if (ground.isLiquid() || ground.getType() == Material.LAVA || ground.getType() == Material.WATER) {
if (!space.getType().isAir()) {
continue;
}
boolean isAirAbove = spaceAbove.getType().isAir();
boolean isTrapdoorAbove = isTrapdoor(spaceAbove.getType());
if (!isAirAbove && !isTrapdoorAbove) {
continue;
}
int light = space.getLightLevel();
EntityType toSpawn = pickEntityType(w, space, light);
EntityType toSpawn;
if (isTrapdoorAbove) {
if (light > 0) {
continue;
}
toSpawn = EntityType.CREEPER;
} else {
toSpawn = pickEntityType(w, space, light);
}
if (toSpawn == null) {
continue;
}
@@ -497,6 +512,11 @@ final class ChunkLoaders {
}
}
static boolean isTrapdoor(Material mat) {
if (mat == null) return false;
return mat.name().endsWith("_TRAPDOOR");
}
static EntityType pickEntityType(World w, Block space, int light) {
boolean isSlime = false;
try {
@@ -212,6 +212,16 @@ class ChunkLoaderTest {
assertTrue(loader.timeLeft().contains("h"));
}
@Test
void recognizesTrapdoorsCorrectly() {
assertTrue(ChunkLoaders.isTrapdoor(org.bukkit.Material.OAK_TRAPDOOR));
assertTrue(ChunkLoaders.isTrapdoor(org.bukkit.Material.IRON_TRAPDOOR));
assertTrue(ChunkLoaders.isTrapdoor(org.bukkit.Material.SPRUCE_TRAPDOOR));
assertFalse(ChunkLoaders.isTrapdoor(org.bukkit.Material.AIR));
assertFalse(ChunkLoaders.isTrapdoor(org.bukkit.Material.STONE));
assertFalse(ChunkLoaders.isTrapdoor(null));
}
@Test
void simulationSafelyNoopsWithNullPlugin() {
loaders.startSimulation();