From 98ecc797fde1eff48557969677f39a87c7729834 Mon Sep 17 00:00:00 2001 From: Dustin Norberg Date: Tue, 22 Sep 2026 16:50:15 -0400 Subject: [PATCH] Prevent Zero Length skybox bouncing --- docs/PORTING.md | 5 +++ gradle.properties | 2 +- .../net/dnorberg/rivencraft/Rivencraft.java | 2 -- .../rivencraft/book/AgeCelestialService.java | 31 ------------------- .../rivencraft/book/AgeDimensionService.java | 11 +++---- .../rivencraft/gametest/LinkingGameTests.java | 4 +-- 6 files changed, 13 insertions(+), 42 deletions(-) delete mode 100644 src/main/java/net/dnorberg/rivencraft/book/AgeCelestialService.java diff --git a/docs/PORTING.md b/docs/PORTING.md index ce347b2..b002445 100644 --- a/docs/PORTING.md +++ b/docs/PORTING.md @@ -304,6 +304,11 @@ random outcome using its effective one-in-seven grammar weight. Zero Length freezes an Age at its generated phase without changing the global daylight cycle, while nonzero Ages retain their independently scaled clocks. +Version 0.2.20.2 gives Zero Length Ages a stationary per-dimension clock rate +instead of advancing and correcting their time once per tick. This keeps the +integer day time fixed while preventing the client skybox from visually +bouncing between adjacent celestial positions. + 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 on a Book Stand. Return Linking Books created inside another Age also retain and diff --git a/gradle.properties b/gradle.properties index f605d64..c87434a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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.20.1 +mod_version=0.2.20.2 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. # This should match the base package used for the mod sources. diff --git a/src/main/java/net/dnorberg/rivencraft/Rivencraft.java b/src/main/java/net/dnorberg/rivencraft/Rivencraft.java index 2d61c36..8854ddb 100644 --- a/src/main/java/net/dnorberg/rivencraft/Rivencraft.java +++ b/src/main/java/net/dnorberg/rivencraft/Rivencraft.java @@ -13,7 +13,6 @@ import net.dnorberg.rivencraft.config.RivencraftConfig; import net.dnorberg.rivencraft.config.RivencraftClientConfig; import net.dnorberg.rivencraft.book.AgeDimensionService; import net.dnorberg.rivencraft.book.AgeWeatherService; -import net.dnorberg.rivencraft.book.AgeCelestialService; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; @@ -39,7 +38,6 @@ public final class Rivencraft { ModCreativeTabs.register(modEventBus); NeoForge.EVENT_BUS.addListener(BookStandConversionHandler::onRightClickBlock); NeoForge.EVENT_BUS.addListener(AgeWeatherService::onLevelTickPost); - NeoForge.EVENT_BUS.addListener(AgeCelestialService::onLevelTickPost); LOGGER.info("Initializing Rivencraft"); } } diff --git a/src/main/java/net/dnorberg/rivencraft/book/AgeCelestialService.java b/src/main/java/net/dnorberg/rivencraft/book/AgeCelestialService.java deleted file mode 100644 index b4caec6..0000000 --- a/src/main/java/net/dnorberg/rivencraft/book/AgeCelestialService.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.dnorberg.rivencraft.book; - -import java.util.Map; -import java.util.WeakHashMap; -import net.minecraft.server.level.ServerLevel; -import net.neoforged.neoforge.event.tick.LevelTickEvent; - -/** Holds Zero Length Age clocks without changing the server-wide daylight gamerule. */ -public final class AgeCelestialService { - private static final Map FROZEN_TIMES = new WeakHashMap<>(); - - private AgeCelestialService() { - } - - public static void freezeAt(ServerLevel level, long dayTime) { - FROZEN_TIMES.put(level, dayTime); - } - - public static void unfreeze(ServerLevel level) { - FROZEN_TIMES.remove(level); - } - - public static void onLevelTickPost(LevelTickEvent.Post event) { - if (event.getLevel() instanceof ServerLevel level) { - Long frozenTime = FROZEN_TIMES.get(level); - if (frozenTime != null && level.getDayTime() != frozenTime) { - level.setDayTime(frozenTime); - } - } - } -} diff --git a/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java b/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java index dbcbff4..07fb9f5 100644 --- a/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java +++ b/src/main/java/net/dnorberg/rivencraft/book/AgeDimensionService.java @@ -104,10 +104,12 @@ public final class AgeDimensionService { private static void applyCelestialClock(ServerLevel level, AgeDefinition age) { if (age.traits().hasStoppedCelestialCycle()) { - level.setDayTimePerTick(-1.0F); - AgeCelestialService.freezeAt(level, level.getDayTime()); + // NeoForge rejects an exact zero rate. The smallest positive float + // never advances the integer clock during a practical world + // lifetime and avoids a one-tick-forward/one-tick-back correction + // that makes the client sky visibly bounce. + level.setDayTimePerTick(Float.MIN_VALUE); } else { - AgeCelestialService.unfreeze(level); level.setDayTimePerTick((float)(1.0D / age.traits().celestialPeriod())); } } @@ -115,9 +117,6 @@ public final class AgeDimensionService { private static void applyInitialCelestialPhase(ServerLevel level, AgeDefinition age) { long phaseTime = (long)(age.traits().celestialPhase() * Level.TICKS_PER_DAY); level.setDayTime(phaseTime); - if (age.traits().hasStoppedCelestialCycle()) { - AgeCelestialService.freezeAt(level, phaseTime); - } } private static void synchronizeImmersivePortals(MinecraftServer server) { diff --git a/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java b/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java index d1244b7..0e8210d 100644 --- a/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java +++ b/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java @@ -188,8 +188,8 @@ public final class LinkingGameTests { helper.assertTrue(Math.abs(level.dimensionType().ambientLight() - expectedAmbientLight) < 0.0001F, "The runtime dimension must apply the persisted lighting trait"); if (definition.traits().hasStoppedCelestialCycle()) { - helper.assertTrue(level.getDayTimePerTick() < 0.0F, - "A Zero Length Age must leave vanilla clock advancement under the freeze controller"); + helper.assertValueEqual(level.getDayTimePerTick(), Float.MIN_VALUE, + "A Zero Length Age must use the stationary nonzero clock rate"); } else { float expectedDaySpeed = (float)(1.0D / definition.traits().celestialPeriod()); helper.assertTrue(Math.abs(level.getDayTimePerTick() - expectedDaySpeed) < 0.0001F,