Keep Cave Age spawns below the roof
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-22 16:27:56 -04:00
1 parent 31ba6f9c15
commit 251d0a2de8
3 files changed
+27 -7

No files matched your search

+5
View File
@@ -276,6 +276,11 @@ dimension skylight while retaining local block light. The latter is the closest
server-safe modern equivalent to Legacy's removed per-dimension light-table server-safe modern equivalent to Legacy's removed per-dimension light-table
scaling hook. scaling hook.
Version 0.2.18.1 prevents Cave Ages from choosing a spawn on their upper roof.
Their grounded arrival search now begins with the floor below player Y=64 and
works downward. If it finds no suitable footing, the existing floor-Y=63
platform fallback places the player at Y=64.
Version 0.2.14.0 restores the legacy Linking and Descriptive Book artwork for Version 0.2.14.0 restores the legacy Linking and Descriptive Book artwork for
inventory items and gives each book its matching open-book texture when placed inventory items and gives each book its matching open-book texture when placed
on a Book Stand. Return Linking Books created inside another Age also retain and on a Book Stand. Return Linking Books created inside another Age also retain and
+1 -1
View File
@@ -35,7 +35,7 @@ mod_name=Rivencraft
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=LGPL-3.0-or-later mod_license=LGPL-3.0-or-later
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md. # The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
mod_version=0.2.18.0 mod_version=0.2.18.1
immersive_portals_version=6.0.7 immersive_portals_version=6.0.7
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources. # This should match the base package used for the mod sources.
@@ -37,6 +37,7 @@ public final class AgeDimensionService {
private static final int PLATFORM_RADIUS = 2; private static final int PLATFORM_RADIUS = 2;
private static final int SURFACE_SEARCH_RADIUS = 16; private static final int SURFACE_SEARCH_RADIUS = 16;
private static final int FALLBACK_PLATFORM_Y = 63; private static final int FALLBACK_PLATFORM_Y = 63;
private static final int CAVE_SPAWN_SEARCH_Y = 64;
private AgeDimensionService() { private AgeDimensionService() {
} }
@@ -64,7 +65,7 @@ public final class AgeDimensionService {
BlockPos spawn = definition.spawn(); BlockPos spawn = definition.spawn();
if (spawn == null) { if (spawn == null) {
spawn = createSafeSpawn(level); spawn = createSafeSpawn(level, definition);
definition = AgeRegistrySavedData.get(level).setSpawn(definition.id(), spawn); definition = AgeRegistrySavedData.get(level).setSpawn(definition.id(), spawn);
} }
return Optional.of(new LinkTarget( return Optional.of(new LinkTarget(
@@ -105,10 +106,19 @@ public final class AgeDimensionService {
return ResourceKey.create(net.minecraft.core.registries.Registries.DIMENSION, definition.dimensionId()); return ResourceKey.create(net.minecraft.core.registries.Registries.DIMENSION, definition.dimensionId());
} }
private static BlockPos createSafeSpawn(ServerLevel level) { private static BlockPos createSafeSpawn(ServerLevel level, AgeDefinition age) {
BlockPos floorCenter = isNetherStyle(level) BlockPos floorCenter;
? netherSpawnFloor(level) if (age.generationProfile().equals(AgeGenerationProfiles.CAVE)) {
: highestFootedSurface(level).orElseGet(() -> fallbackSpawnFloor(level)); // Cave Ages are enclosed. Searching from the world ceiling would
// select or expose their roof, so begin with the floor beneath a
// player standing at Y=64 and search downward from there.
floorCenter = highestFootedSurface(level, CAVE_SPAWN_SEARCH_Y - 1)
.orElseGet(() -> fallbackSpawnFloor(level));
} else if (isNetherStyle(level)) {
floorCenter = netherSpawnFloor(level);
} else {
floorCenter = highestFootedSurface(level).orElseGet(() -> fallbackSpawnFloor(level));
}
for (int x = -PLATFORM_RADIUS; x <= PLATFORM_RADIUS; x++) { for (int x = -PLATFORM_RADIUS; x <= PLATFORM_RADIUS; x++) {
for (int z = -PLATFORM_RADIUS; z <= PLATFORM_RADIUS; z++) { for (int z = -PLATFORM_RADIUS; z <= PLATFORM_RADIUS; z++) {
@@ -138,8 +148,13 @@ public final class AgeDimensionService {
/** Selects the highest nearby terrain column that can naturally support a player. */ /** Selects the highest nearby terrain column that can naturally support a player. */
private static Optional<BlockPos> highestFootedSurface(ServerLevel level) { private static Optional<BlockPos> highestFootedSurface(ServerLevel level) {
return highestFootedSurface(level, level.getMaxBuildHeight() - 5);
}
private static Optional<BlockPos> highestFootedSurface(ServerLevel level, int requestedMaximumFloorY) {
BlockPos best = null; BlockPos best = null;
int maximumFloorY = level.getMaxBuildHeight() - 5; int maximumFloorY = Math.clamp(requestedMaximumFloorY,
level.getMinBuildHeight(), level.getMaxBuildHeight() - 5);
for (int x = -SURFACE_SEARCH_RADIUS; x <= SURFACE_SEARCH_RADIUS; x++) { for (int x = -SURFACE_SEARCH_RADIUS; x <= SURFACE_SEARCH_RADIUS; x++) {
for (int z = -SURFACE_SEARCH_RADIUS; z <= SURFACE_SEARCH_RADIUS; z++) { for (int z = -SURFACE_SEARCH_RADIUS; z <= SURFACE_SEARCH_RADIUS; z++) {