From b65f9379e3c4e16ec3ed91fd3b7c0e1310006819 Mon Sep 17 00:00:00 2001 From: Dustin Norberg Date: Tue, 22 Sep 2026 16:32:25 -0400 Subject: [PATCH] Apply persisted Age weather traits --- docs/PORTING.md | 8 +++ gradle.properties | 2 +- .../net/dnorberg/rivencraft/Rivencraft.java | 2 + .../rivencraft/book/AgeDefinition.java | 2 +- .../rivencraft/book/AgeWeatherService.java | 71 +++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/dnorberg/rivencraft/book/AgeWeatherService.java diff --git a/docs/PORTING.md b/docs/PORTING.md index a1b06ad..9aa4439 100644 --- a/docs/PORTING.md +++ b/docs/PORTING.md @@ -281,6 +281,14 @@ 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.19.0 applies persisted weather traits to loaded Ages. Normal uses +Minecraft's normal weather cycle. Fast and Slow use Legacy's original duration +and cooldown ranges at half and double normal speed for Minecraft's combined +rain/thunder weather timer. Off keeps an Age clear; +Always, Cloudy, Rain, and Snow maintain non-thundering precipitation; Storm +maintains rain and thunder. Minecraft still chooses rain versus snow from biome +temperature, so dedicated Snow/Rain biome overrides remain future work. + 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 344eaa2..d8c1dbc 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.18.1 +mod_version=0.2.19.0 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 e259173..8854ddb 100644 --- a/src/main/java/net/dnorberg/rivencraft/Rivencraft.java +++ b/src/main/java/net/dnorberg/rivencraft/Rivencraft.java @@ -12,6 +12,7 @@ import net.dnorberg.rivencraft.network.ModNetworking; 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.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; @@ -36,6 +37,7 @@ public final class Rivencraft { ModSounds.register(modEventBus); ModCreativeTabs.register(modEventBus); NeoForge.EVENT_BUS.addListener(BookStandConversionHandler::onRightClickBlock); + NeoForge.EVENT_BUS.addListener(AgeWeatherService::onLevelTickPost); LOGGER.info("Initializing Rivencraft"); } } diff --git a/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java b/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java index b95f3b8..e2f3631 100644 --- a/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java +++ b/src/main/java/net/dnorberg/rivencraft/book/AgeDefinition.java @@ -21,7 +21,7 @@ public record AgeDefinition( public static final ResourceLocation RANDOM_VANILLA_PROFILE = ResourceLocation.fromNamespaceAndPath( Rivencraft.MOD_ID, "random_vanilla" ); - public static final int CURRENT_GENERATION_VERSION = 4; + public static final int CURRENT_GENERATION_VERSION = 5; public AgeDefinition { Objects.requireNonNull(id, "id"); diff --git a/src/main/java/net/dnorberg/rivencraft/book/AgeWeatherService.java b/src/main/java/net/dnorberg/rivencraft/book/AgeWeatherService.java new file mode 100644 index 0000000..83fdce3 --- /dev/null +++ b/src/main/java/net/dnorberg/rivencraft/book/AgeWeatherService.java @@ -0,0 +1,71 @@ +package net.dnorberg.rivencraft.book; + +import java.util.Map; +import java.util.WeakHashMap; +import net.dnorberg.rivencraft.Rivencraft; +import net.minecraft.server.level.ServerLevel; +import net.neoforged.neoforge.event.tick.LevelTickEvent; + +/** Applies persisted Legacy-inspired weather behavior to loaded Ages. */ +public final class AgeWeatherService { + private static final int FIXED_WEATHER_DURATION = 6000; + private static final Map STATES = new WeakHashMap<>(); + + private AgeWeatherService() { + } + + public static void onLevelTickPost(LevelTickEvent.Post event) { + if (!(event.getLevel() instanceof ServerLevel level) + || !level.dimension().location().getNamespace().equals(Rivencraft.MOD_ID)) { + return; + } + AgeDefinition age = AgeRegistrySavedData.get(level) + .findByDimension(level.dimension().location()) + .orElse(null); + if (age == null) { + return; + } + + AgeTraits.Weather weather = age.traits().weather(); + if (weather == AgeTraits.Weather.NORMAL) { + STATES.remove(level); + return; + } + + if (weather == AgeTraits.Weather.FAST || weather == AgeTraits.Weather.SLOW) { + applyVariableWeather(level, weather); + } else { + STATES.remove(level); + applyFixedWeather(level, weather); + } + } + + private static void applyVariableWeather( + ServerLevel level, + AgeTraits.Weather weather + ) { + WeatherState current = new WeatherState(level.isRaining(), level.isThundering()); + WeatherState previous = STATES.put(level, current); + if (current.equals(previous)) { + return; + } + + int scale = weather == AgeTraits.Weather.FAST ? 1 : 4; + int rainBase = 6000 * scale; + int rainRange = (current.raining() ? 6000 : 84000) * scale; + int duration = rainBase + level.getRandom().nextInt(rainRange); + level.setWeatherParameters(0, duration, current.raining(), current.thundering()); + } + + private static void applyFixedWeather(ServerLevel level, AgeTraits.Weather weather) { + boolean raining = weather != AgeTraits.Weather.OFF; + boolean thundering = weather == AgeTraits.Weather.STORM; + if (level.isRaining() != raining || level.isThundering() != thundering + || level.getGameTime() % 200L == 0L) { + level.setWeatherParameters(0, FIXED_WEATHER_DURATION, raining, thundering); + } + } + + private record WeatherState(boolean raining, boolean thundering) { + } +}