Merge main into the branch

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Ludovic MarieandClaude Opus 5.5 committed 2026-10-29 12:28:51 +01:00
commit dc8f01ea19
3 files changed
+72 -8

No files matched your search

+25 -5
View File
@@ -203,6 +203,13 @@ pub struct FogInputs<'a> {
/// `BossHealthOverlay.shouldCreateWorldFog`: a boss bar with
/// `createWorldFog` is shown (the Ender Dragon's).
pub boss_world_fog: bool,
/// The camera entity is a spectator (`LavaFogEnvironment`).
pub spectator: bool,
/// The camera entity has Fire Resistance (`LavaFogEnvironment`).
pub fire_resistance: bool,
/// `GameRenderer.nightVisionScale` while Night Vision is on without
/// Darkness, else 0 (`FogRenderer.computeFogColor`'s brightenFactor).
pub night_vision: f32,
}
/// `FogRenderer.setupFog` + `computeFogColor`.
@@ -272,7 +279,11 @@ pub fn setup_fog(tables: &FogTables, state: &FogState, input: &FogInputs) -> Fog
color[1] += (color[1] * 0.6 - color[1]) * t;
color[2] += (color[2] * 0.6 - color[2]) * t;
}
let brighten = if eye_in_water { water_vision } else { 0.0 };
let brighten = if eye_in_water {
water_vision
} else {
input.night_vision
};
if color.iter().all(|&c| c != 0.0) {
let scale = 1.0 / color[0].max(color[1]).max(color[2]);
color = color.map(|c| c + (c * scale - c) * brighten);
@@ -288,10 +299,16 @@ pub fn setup_fog(tables: &FogTables, state: &FogState, input: &FogInputs) -> Fog
};
match input.fog_type {
FogType::Lava => {
fog.environmental_start = 0.25;
fog.environmental_end = 1.0;
fog.sky_end = 1.0;
fog.cloud_end = 1.0;
// LavaFogEnvironment.setupFog.
(fog.environmental_start, fog.environmental_end) = if input.spectator {
(-8.0, rd * 0.5)
} else if input.fire_resistance {
(0.0, 5.0)
} else {
(0.25, 1.0)
};
fog.sky_end = fog.environmental_end;
fog.cloud_end = fog.environmental_end;
}
FogType::PowderSnow => {
fog.environmental_start = 0.0;
@@ -405,6 +422,9 @@ mod tests {
darkness: None,
darken_world: 0.0,
boss_world_fog: false,
spectator: false,
fire_resistance: false,
night_vision: 0.0,
}
}
#[test]
@@ -118,9 +118,28 @@ impl Game<'_> {
.boss_overlay
.darken_amount(self.clock.fraction() as f32),
boss_world_fog: self.boss_overlay.should_create_world_fog(),
spectator: self.spectator(),
fire_resistance: self.potions.effects.get("fire_resistance").is_some(),
night_vision: self.fog_night_vision(),
},
)
}
/// `FogRenderer.computeFogColor`'s night vision brightenFactor:
/// `GameRenderer.nightVisionScale`, but not while Darkness is on.
fn fog_night_vision(&self) -> f32 {
let partial = self.clock.fraction() as f32;
match self.potions.effects.get("night_vision") {
Some(e) if self.potions.effects.get("darkness").is_none() => {
// MobEffectInstance.endsWithin(200); -1 is infinite.
if e.duration < 0 || e.duration > 200 {
1.0
} else {
0.7 + ((e.duration as f32 - partial) * std::f32::consts::PI * 0.2).sin() * 0.3
}
}
_ => 0.0,
}
}
/// `ClientLevelData.isFlat`: on the server thread, the world-wide flag.
fn level_flat(&self) -> bool {
match self.remote.as_ref() {
+28 -3
View File
@@ -208,7 +208,10 @@ fn is_potion_item(item: &str) -> bool {
/// The name line of `stack`, as the item's translation or, for potions and
/// smithing templates, its name component gives it.
pub fn name_line(stack: &ItemStack, translate: &dyn Fn(&str) -> Option<String>) -> String {
let path = stack.item.trim_start_matches("minecraft:");
let (namespace, path) = stack
.item
.split_once(':')
.unwrap_or(("minecraft", &stack.item));
if let Some(name) = stack.custom_name() {
return name.to_owned();
}
@@ -231,9 +234,12 @@ pub fn name_line(stack: &ItemStack, translate: &dyn Fn(&str) -> Option<String>)
} else {
None
};
// `Item.getDescriptionId`: `Util.makeDescriptionId("item", id)`, or the
// block's for a block item, in the item's own namespace.
let id = format!("{namespace}.{}", path.replace('/', "."));
key.and_then(|k| translate(&k))
.or_else(|| translate(&format!("item.minecraft.{path}")))
.or_else(|| translate(&format!("block.minecraft.{path}")))
.or_else(|| translate(&format!("item.{id}")))
.or_else(|| translate(&format!("block.{id}")))
.unwrap_or_else(|| path.replace('_', " "))
}
@@ -862,6 +868,25 @@ mod tests {
assert_eq!(rarity(&plain, "common"), "common");
}
#[test]
fn name_line_translates_items_of_any_namespace() {
let translate = |key: &str| match key {
"item.example.ruby" => Some("Ruby".to_owned()),
"block.example.ruby_block" => Some("Block of Ruby".to_owned()),
"item.example.tools.chisel" => Some("Chisel".to_owned()),
"item.minecraft.diamond" => Some("Diamond".to_owned()),
_ => None,
};
let name = |id: &str| name_line(&ItemStack::new(id, 1), &translate);
// `Util.makeDescriptionId`: the item's own namespace, `/` as `.`.
assert_eq!(name("example:ruby"), "Ruby");
assert_eq!(name("example:ruby_block"), "Block of Ruby");
assert_eq!(name("example:tools/chisel"), "Chisel");
assert_eq!(name("minecraft:diamond"), "Diamond");
// No translation: the path, as the creative names fall back to.
assert_eq!(name("example:raw_ruby"), "raw ruby");
}
#[test]
fn container_lines_list_five_stacks_then_how_many_more() {
let mut chest = ItemStack::new("minecraft:chest", 1);