feat(mods): adjust computed world fog color

Co-Authored-By: Codex <[email protected]>
This commit is contained in:
[email protected]andCodex committed 2026-11-01 15:10:03 +01:00
1 parent 885e287a2e
commit e0d42f6719
4 files changed
+93

No files matched your search

@@ -1331,6 +1331,17 @@ impl Game<'_> {
pub(super) fn native_zoom(&self, zoom: &mut Option<NativeZoom>) {
let _ = zoom;
}
/// Computed world fog RGB, after ordinary effects and before upload. Title panoramas skip it.
/// Only finite RGB components in 0..=1 are accepted; alpha and distances stay unchanged.
pub(super) fn native_compute_fog_color(
&self,
partial: f32,
camera: [f64; 3],
fog_type: horizon_client::fog::FogType,
rgb: &mut [f32; 3],
) {
let _ = (partial, camera, fog_type, rgb);
}
/// The camera shake native mods ask for in this frame, `partial` ticks
/// past the last tick (0 to 1): add your pitch, yaw and roll in degrees
/// and your offset in blocks, along the camera's right, up and back, to
@@ -140,8 +140,27 @@ impl Game<'_> {
if !self.settings.horizon.fog {
horizon_client::fog::clear_distance_fog(&mut fog, &input);
}
if self.title.is_none() {
fog.color =
self.native_fog_color_now(self.clock.fraction() as f32, at, fog_type, fog.color);
}
fog
}
fn native_fog_color_now(
&self,
partial: f32,
camera: [f64; 3],
fog_type: FogType,
color: [f32; 4],
) -> [f32; 4] {
let mut rgb = [color[0], color[1], color[2]];
self.native_compute_fog_color(partial, camera, fog_type, &mut rgb);
if rgb.iter().all(|v| v.is_finite() && (0.0..=1.0).contains(v)) {
[rgb[0], rgb[1], rgb[2], color[3]]
} else {
color
}
}
/// `FogRenderer.computeFogColor`'s night vision brightenFactor:
/// `GameRenderer.nightVisionScale`, but not while Darkness is on.
fn fog_night_vision(&self) -> f32 {
+51
View File
@@ -0,0 +1,51 @@
"""Run the actual fog color dispatch with a fake mod, without a GPU/window."""
from pathlib import Path
import shutil
import subprocess
import tempfile
import unittest
from test_world_input_capture import method
ROOT = Path(__file__).resolve().parents[1]
class ComputeFogColorHookTests(unittest.TestCase):
@unittest.skipUnless(shutil.which("rustc"), "requires Rust")
def test_rgb_override_fallback_and_alpha(self):
source = (ROOT / "crates/horizon-client/src/game/render_tick.rs").read_text(encoding="utf-8")
actual = method(source, "native_fog_color_now")
frame = method(source.replace("pub(super) fn", "fn"), "frame_fog")
self.assertIn("if self.title.is_none() { fog.color = self.native_fog_color_now", " ".join(frame.split()))
fixture = r"""
#[derive(Clone, Copy, Debug, PartialEq)]
enum FogType { Atmospheric, Water, Lava, PowderSnow }
struct Game { replacement: Option<[f32; 3]> }
impl Game {
fn native_compute_fog_color(&self, partial: f32, camera: [f64; 3],
_kind: FogType, rgb: &mut [f32; 3]) {
assert_eq!((partial, camera, *rgb), (0.25, [1.0, 2.0, 3.0], [0.2, 0.4, 0.6]));
if let Some(value) = self.replacement { *rgb = value; }
}
METHOD
}
#[test]
fn all_environments_valid_invalid_and_unchanged() {
let original = [0.2, 0.4, 0.6, 0.75];
for kind in [FogType::Atmospheric, FogType::Water, FogType::Lava, FogType::PowderSnow] {
for (replacement, expected) in [(None, original),
(Some([0.0, 1.0, 0.5]), [0.0, 1.0, 0.5, 0.75]),
(Some([f32::NAN, 0.0, 0.0]), original),
(Some([0.0, f32::INFINITY, 0.0]), original),
(Some([0.0, 0.0, -0.1]), original),
(Some([1.1, 0.0, 0.0]), original)] {
assert_eq!(Game { replacement }.native_fog_color_now(0.25, [1.0, 2.0, 3.0], kind, original), expected);
}
}
}
""".replace("METHOD", actual)
with tempfile.TemporaryDirectory() as folder:
src, exe = Path(folder) / "fog.rs", Path(folder) / "fog.exe"
src.write_text(fixture, encoding="utf-8")
subprocess.run(["rustc", "--edition=2024", "--test", str(src), "-o", str(exe)], check=True)
subprocess.run([str(exe)], check=True)
@@ -0,0 +1,12 @@
{
"hooks": [
{
"name": "compute_fog_color",
"target": "horizon_client::game::native_hooks::Game<'_>::native_compute_fog_color",
"neoforge": "ViewportEvent.ComputeFogColor",
"side": "client"
}
],
"rust_summary": "a computed fog color hook (`native_compute_fog_color`).",
"doc_summary": "`native_compute_fog_color(partial, camera, fog_type, rgb)` adjusts the final world fog RGB after normal biome, weather and effect calculation and before GPU upload. Camera is its world position; fog_type distinguishes atmosphere, water, lava and powder snow. Only finite components in 0..=1 are accepted; invalid requests retain the original RGB. Alpha and all distance fields are unchanged. Title panoramas skip this hook. Bundles need \"hooks\": @API:compute_fog_color@."
}