Scan Age spawn columns from world top
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-21 14:55:35 -04:00
1 parent 58964052c9
commit b8215f1336
4 files changed
+32 -12

No files matched your search

+3 -2
View File
@@ -37,8 +37,9 @@ Open a page-free Descriptive Book, name its Age, and press Create. Rivencraft
assigns the book a permanent Age UUID, creates a dedicated vanilla-like runtime
dimension, and prepares a five-by-five cobblestone arrival platform at the
highest suitable nearby terrain. Solid blocks and tree leaves are valid
footing. If no suitable surface is available, the
platform is generated at Y=63. Reopen the book and click its preview to travel.
footing. Candidate columns are scanned from the top down so cave floors are not
selected, and fluid-covered columns are excluded. If no suitable surface is
available, the platform is generated at Y=63. Reopen the book and click its preview to travel.
Copies of the written book continue to resolve to the same persistent Age
across server restarts.
+4
View File
@@ -202,6 +202,10 @@ no suitable natural footing exists.
Version 0.2.10.2 allows leaf blocks to count as proper natural footing when
selecting the highest arrival surface.
Version 0.2.10.3 scans each candidate column downward from the dimension's top
before choosing footing, preventing cave floors from being selected as the Age
arrival surface. Columns covered by fluid remain ineligible.
The preview code is separated behind a renderer interface and uses an isolated
Ponder level populated from server-authoritative destination snapshots.
+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.
mod_license=LGPL-3.0-or-later
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
mod_version=0.2.10.2
mod_version=0.2.10.3
# 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.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
@@ -121,18 +121,12 @@ public final class AgeDimensionService {
for (int x = -SURFACE_SEARCH_RADIUS; x <= SURFACE_SEARCH_RADIUS; x++) {
for (int z = -SURFACE_SEARCH_RADIUS; z <= SURFACE_SEARCH_RADIUS; z++) {
int floorY = level.getHeight(Heightmap.Types.WORLD_SURFACE, x, z) - 1;
if (floorY < level.getMinBuildHeight() || floorY > maximumFloorY) {
Optional<BlockPos> columnFooting = highestFootingInColumn(level, x, z, maximumFloorY);
if (columnFooting.isEmpty()) {
continue;
}
BlockPos candidate = new BlockPos(x, floorY, z);
var state = level.getBlockState(candidate);
if (!level.getFluidState(candidate).isEmpty()
|| (!state.is(BlockTags.LEAVES)
&& !state.isFaceSturdy(level, candidate, net.minecraft.core.Direction.UP))) {
continue;
}
BlockPos candidate = columnFooting.get();
if (best == null || candidate.getY() > best.getY()
|| (candidate.getY() == best.getY()
@@ -145,6 +139,27 @@ public final class AgeDimensionService {
return Optional.ofNullable(best);
}
/** Scans downward from the top so cave floors cannot be mistaken for surface footing. */
private static Optional<BlockPos> highestFootingInColumn(ServerLevel level, int x, int z, int maximumFloorY) {
BlockPos.MutableBlockPos candidate = new BlockPos.MutableBlockPos(x, maximumFloorY, z);
for (int y = maximumFloorY; y >= level.getMinBuildHeight(); y--) {
candidate.setY(y);
if (!level.getFluidState(candidate).isEmpty()) {
return Optional.empty();
}
var state = level.getBlockState(candidate);
if (state.isAir()) {
continue;
}
if (state.is(BlockTags.LEAVES)
|| state.isFaceSturdy(level, candidate, net.minecraft.core.Direction.UP)) {
return Optional.of(candidate.immutable());
}
}
return Optional.empty();
}
private static BlockPos fallbackSpawnFloor(ServerLevel level) {
int floorY = Math.clamp(FALLBACK_PLATFORM_Y,
level.getMinBuildHeight(), level.getMaxBuildHeight() - 5);