From 9f3e1ba82fd40f3dd58deeaf66b7210c19e5f6b7 Mon Sep 17 00:00:00 2001 From: ChrisM-Pek Date: Thu, 27 Aug 2026 07:06:45 +0200 Subject: [PATCH 1/2] fix(ouch): relier la TNT meteo a Ambiance La detonation ne parlait qu'au ciel vanilla, donc Ambiance remettait la pluie. La TNT demande maintenant un ciel clair une heure via l'API Ambiance, avec un fondu du niveau de pluie vers les clients. Co-authored-by: Cursor --- ambiance/build.gradle | 2 + .../AmbianceEnvironmentController.java | 43 +++++++++++++++++-- build.gradle | 1 + ouch/build.gradle | 8 +++- .../ouch/entity/WeatherTntEntity.java | 8 +++- ouch/src/main/resources/fabric.mod.json | 1 + 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/ambiance/build.gradle b/ambiance/build.gradle index 5c4a53b..74f2cd8 100644 --- a/ambiance/build.gradle +++ b/ambiance/build.gradle @@ -265,6 +265,8 @@ tasks.register("verifyAmbiance") { 'class AmbianceEnvironmentController', 'enum AmbianceDailyWeather', 'enum AmbianceCloudCover', 'enum AmbianceLunarNight', 'id("environment_sync")', 'setRainLevel(weather.rainIntensity())', + 'ClientboundGameEventPacket.RAIN_LEVEL_CHANGE', + 'WEATHER_FADE_EPSILON', 'Math.multiplyExact(worldDay, MINECRAFT_DAY_TICKS)', 'class AmbianceEffects', 'class AmbianceBiomeTints', 'AmbianceShaderCompatibility.isShaderPackActive()', 'case LIGHT_RAIN -> 0.72F', diff --git a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/environment/AmbianceEnvironmentController.java b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/environment/AmbianceEnvironmentController.java index 50ceff3..be8b886 100644 --- a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/environment/AmbianceEnvironmentController.java +++ b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/environment/AmbianceEnvironmentController.java @@ -10,8 +10,10 @@ import java.util.IdentityHashMap; import java.util.Map; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.minecraft.network.protocol.game.ClientboundGameEventPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.players.PlayerList; import net.minecraft.util.RandomSource; import net.minecraft.world.level.saveddata.WeatherData; @@ -22,6 +24,8 @@ import net.minecraft.world.level.saveddata.WeatherData; */ public final class AmbianceEnvironmentController { private static final int UPDATE_INTERVAL_TICKS = 20; + /** Vanilla fades rain and thunder by 0.01 per tick; stay above that so we do not snap. */ + private static final float WEATHER_FADE_EPSILON = 0.012F; private static final Map TIMED_WEATHER = new IdentityHashMap<>(); private static final Map LUNAR_OVERRIDES = new IdentityHashMap<>(); private static final Map LAST_BROADCAST_WEATHER = new IdentityHashMap<>(); @@ -44,6 +48,8 @@ public final class AmbianceEnvironmentController { ServerTickEvents.END_SERVER_TICK.register(server -> { if (server.getTickCount() % UPDATE_INTERVAL_TICKS == 0) { refresh(server); + } else { + applyWeather(server, effectiveWeather(server, AmbianceData.get(server))); } }); } @@ -210,6 +216,9 @@ public final class AmbianceEnvironmentController { } private static void applyWeather(MinecraftServer server, AmbianceDailyWeather weather) { + float targetRain = weather.rainIntensity(); + float targetThunder = weather.thunder() ? 1.0F : 0.0F; + PlayerList players = server.getPlayerList(); for (ServerLevel level : server.getAllLevels()) { if (!level.canHaveWeather()) { continue; @@ -217,11 +226,37 @@ public final class AmbianceEnvironmentController { WeatherData data = level.getWeatherData(); data.setClearWeatherTime(weather.raining() ? 0 : 2400); data.setRainTime(weather.raining() ? 2400 : 0); - data.setRaining(weather.raining()); data.setThunderTime(weather.thunder() ? 2400 : 0); - data.setThundering(weather.thunder()); - level.setRainLevel(weather.rainIntensity()); - level.setThunderLevel(weather.thunder() ? 1.0F : 0.0F); + float currentRain = level.getRainLevel(1.0F); + float currentThunder = level.getThunderLevel(1.0F); + if (currentRain > targetRain + WEATHER_FADE_EPSILON) { + data.setRaining(false); + } else if (currentRain < targetRain - WEATHER_FADE_EPSILON) { + data.setRaining(true); + } else { + data.setRaining(weather.raining()); + if (currentRain != targetRain) { + level.setRainLevel(weather.rainIntensity()); + players.broadcastAll( + new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, targetRain), + level.dimension() + ); + } + } + if (currentThunder > targetThunder + WEATHER_FADE_EPSILON) { + data.setThundering(false); + } else if (currentThunder < targetThunder - WEATHER_FADE_EPSILON) { + data.setThundering(true); + } else { + data.setThundering(weather.thunder()); + if (currentThunder != targetThunder) { + level.setThunderLevel(targetThunder); + players.broadcastAll( + new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, targetThunder), + level.dimension() + ); + } + } } } diff --git a/build.gradle b/build.gradle index edd2bb8..ec8189d 100644 --- a/build.gradle +++ b/build.gradle @@ -3592,6 +3592,7 @@ project(":anotherworld") { project(":ouch") { dependencies { implementation project(":anotherworld") + implementation project(":ambiance") implementation project(":sanctuary") } } diff --git a/ouch/build.gradle b/ouch/build.gradle index 5e073e6..669e494 100644 --- a/ouch/build.gradle +++ b/ouch/build.gradle @@ -23,6 +23,8 @@ tasks.register("verifyOuch") { def itemRegistry = file("src/main/java/fr/koka99cab/sanctuary26/ouch/registry/OuchItems.java").text def creativeTab = file("src/main/java/fr/koka99cab/sanctuary26/ouch/registry/OuchCreativeTab.java").text def weatherRegistry = file("src/main/java/fr/koka99cab/sanctuary26/ouch/registry/OuchWeatherTnt.java").text + def weatherEntity = file("src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java").text + def manifest = new JsonSlurper().parse(file("src/main/resources/fabric.mod.json")) if (!itemRegistry.contains("MIGRATED_WEAPONS = List.of(CREEPERLOCK, MITRAILLETTE, EXPULSEUR, ASPIRATEUR)") || !itemRegistry.contains("WEAPONS = List.of(CREEPERLOCK, MITRAILLETTE, EXPULSEUR, ASPIRATEUR, MINING_RIFLE, BETA_BOW)") || !creativeTab.contains('OuchMod.id("arsenal")') @@ -35,11 +37,15 @@ tasks.register("verifyOuch") { || !weatherRegistry.contains('OuchMod.id("weather_tnt")') || !weatherRegistry.contains('Identifier.fromNamespaceAndPath("redstoner", "weather_tnt")') || !weatherRegistry.contains('Identifier.fromNamespaceAndPath("weather_tnt", "weather_tnt")') + || !weatherEntity.contains("AmbianceEnvironmentController.setWeatherForDuration") + || !weatherEntity.contains("AmbianceDailyWeather.CLEAR") + || weatherEntity.contains("setWeatherParameters") + || manifest.depends?.ambiance != "*" || !file("src/main/resources/assets/ouch/blockstates/weather_tnt.json").isFile() || !file("src/main/resources/assets/ouch/items/weather_tnt.json").isFile() || !file("src/main/resources/data/ouch/loot_table/blocks/weather_tnt.json").isFile() || !file("src/main/resources/data/ouch/recipe/weather_tnt.json").isFile()) { - throw new GradleException("Ouch must own Weather TNT and preserve both historical aliases") + throw new GradleException("Ouch must own Weather TNT, clear Ambiance rain for one hour, and preserve both historical aliases") } if (!itemRegistry.contains('register("mining_rifle", properties -> new MiningRifleItem(properties.durability(640).enchantable(14)))')) { diff --git a/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java b/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java index bd2aba6..b3900f9 100644 --- a/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java +++ b/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java @@ -1,5 +1,7 @@ package fr.koka99cab.sanctuary26.ouch.entity; +import fr.koka99cab.sanctuary26.ambiance.environment.AmbianceDailyWeather; +import fr.koka99cab.sanctuary26.ambiance.environment.AmbianceEnvironmentController; import fr.koka99cab.sanctuary26.ouch.registry.OuchWeatherTnt; import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.core.particles.ParticleTypes; @@ -82,7 +84,11 @@ public class WeatherTntEntity extends PrimedTnt { private void detonate(ServerLevel level) { MinecraftServer server = level.getServer(); if (server != null) { - server.setWeatherParameters(CLEAR_WEATHER_TICKS, 0, false, false); + AmbianceEnvironmentController.setWeatherForDuration( + server, + AmbianceDailyWeather.CLEAR, + CLEAR_WEATHER_TICKS + ); } level.setSkyFlashTime(2); diff --git a/ouch/src/main/resources/fabric.mod.json b/ouch/src/main/resources/fabric.mod.json index 82b5730..7e07d36 100644 --- a/ouch/src/main/resources/fabric.mod.json +++ b/ouch/src/main/resources/fabric.mod.json @@ -24,6 +24,7 @@ "java": ">=25", "fabric-api": ">=0.154.2+26.2", "anotherworld": ">=0.0.0-alpha.46", + "ambiance": "*", "sanctuary": ">=0.0.0-alpha.110" }, "custom": { -- 2.54.0 From 79ac34dd1cf721fdff55d8ca1789fafbb079bcf6 Mon Sep 17 00:00:00 2001 From: ChrisM-Pek Date: Thu, 27 Aug 2026 07:12:53 +0200 Subject: [PATCH 2/2] fix(ouch): garder le ciel clair 12 heures apres la TNT meteo Co-authored-by: Cursor --- ouch/build.gradle | 3 ++- .../fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ouch/build.gradle b/ouch/build.gradle index 669e494..805c8b2 100644 --- a/ouch/build.gradle +++ b/ouch/build.gradle @@ -39,13 +39,14 @@ tasks.register("verifyOuch") { || !weatherRegistry.contains('Identifier.fromNamespaceAndPath("weather_tnt", "weather_tnt")') || !weatherEntity.contains("AmbianceEnvironmentController.setWeatherForDuration") || !weatherEntity.contains("AmbianceDailyWeather.CLEAR") + || !weatherEntity.contains("CLEAR_WEATHER_TICKS = 864_000") || weatherEntity.contains("setWeatherParameters") || manifest.depends?.ambiance != "*" || !file("src/main/resources/assets/ouch/blockstates/weather_tnt.json").isFile() || !file("src/main/resources/assets/ouch/items/weather_tnt.json").isFile() || !file("src/main/resources/data/ouch/loot_table/blocks/weather_tnt.json").isFile() || !file("src/main/resources/data/ouch/recipe/weather_tnt.json").isFile()) { - throw new GradleException("Ouch must own Weather TNT, clear Ambiance rain for one hour, and preserve both historical aliases") + throw new GradleException("Ouch must own Weather TNT, clear Ambiance rain for twelve hours, and preserve both historical aliases") } if (!itemRegistry.contains('register("mining_rifle", properties -> new MiningRifleItem(properties.durability(640).enchantable(14)))')) { diff --git a/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java b/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java index b3900f9..0e13267 100644 --- a/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java +++ b/ouch/src/main/java/fr/koka99cab/sanctuary26/ouch/entity/WeatherTntEntity.java @@ -18,7 +18,7 @@ import net.minecraft.world.phys.Vec3; public class WeatherTntEntity extends PrimedTnt { public static final int DEFAULT_FUSE_TICKS = 60; - private static final int CLEAR_WEATHER_TICKS = 72_000; + private static final int CLEAR_WEATHER_TICKS = 864_000; private static final double LAUNCH_SPEED = 0.56D; private static final DustParticleOptions BLUE_DUST = new DustParticleOptions(0x44A6FF, 1.35F); -- 2.54.0