MONKEY (integration): fix the programme's test failures (warm names, shader embed, dev door, CRLF/path-separator test bugs, float compare, tooltip newlines) and declare the missing system orders
- ssao.wgsl registered in shaders::plugin and loaded by its embedded path - wind/wetness/fog-model MonkeyFrame writers ordered; viewer publish before its readers; sky clock + sky tier before LightingConsumeSet; zone skybox chain joins the consume set; grass benders read GlobalTransform - ambiguity ceiling re-measured with the reason (MatAnimTable allocator + exclusive-system pairs) - verb_event_gate: Windows separators; AddSkillUp/RemoveSkillUp GAP rows - ui_session portrait test: CRLF checkout - spell envelope fuse assertion: f32 tolerance - daylightWindowSplit tooltip: escaped \n (raw line breaks broke the Lua chunk) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
89b68ed26b
commit
f76b0de836
@@ -693,9 +693,7 @@
|
||||
DAYLIGHT_WINDOW_SPLIT =
|
||||
"Large city buildings take daylight through each window on its own instead of "
|
||||
.. "treating a whole wall of windows as one opening, so halls like the cathedral "
|
||||
.. "catch the sun pane by pane.
|
||||
|
||||
Applies to buildings loaded after the change. "
|
||||
.. "catch the sun pane by pane.\n\nApplies to buildings loaded after the change. "
|
||||
.. "Off is the earlier look.",
|
||||
-- MONKEY (lampfog)
|
||||
LAMP_FOG =
|
||||
@@ -921,9 +919,7 @@ Applies to buildings loaded after the change. "
|
||||
DAYLIGHT_WINDOW_SPLIT =
|
||||
"Большие городские здания пропускают дневной свет через каждое окно отдельно, "
|
||||
.. "а не через всю стену окон как один проём, поэтому залы вроде собора "
|
||||
.. "освещаются солнцем окно за окном.
|
||||
|
||||
Действует для зданий, загруженных после "
|
||||
.. "освещаются солнцем окно за окном.\n\nДействует для зданий, загруженных после "
|
||||
.. "изменения. Выключено — прежний вид.",
|
||||
-- MONKEY (lampfog)
|
||||
LAMP_FOG =
|
||||
|
||||
@@ -639,7 +639,8 @@ mod tests {
|
||||
// The ONSET: a firework's fuse. Dark for the whole flight, up at the detonation.
|
||||
let fuse = || SpellLight::new(1.0, 1.5, SpellLightMode::Burst { span: 0.6 });
|
||||
assert_eq!(at(fuse(), 1.4), 0.0);
|
||||
assert_eq!(at(fuse(), 1.5 + SPELL_LIGHT_RAMP), 1.0);
|
||||
// MONKEY (integration): (1.5 + ramp) - 1.5 is not exactly `ramp` in f32.
|
||||
assert!((at(fuse(), 1.5 + SPELL_LIGHT_RAMP) - 1.0).abs() < 1e-6);
|
||||
|
||||
// The reap fade: a kit light goes dark on its instance's `FxDecay`, quicker than the
|
||||
// model's own Decay sequence — the aura is over the moment the server said so.
|
||||
|
||||
@@ -1089,7 +1089,15 @@ pub(crate) mod schedule_tests {
|
||||
/// the net drain's. Same tree, the class dropped, nothing else moved: 5,052 + 556.
|
||||
/// **5,554 (decision 2345)** — lowered: the TAB scan stopped reading `Visibility` (the draw
|
||||
/// election's verdict), which ended its pairs with every `Visibility` writer.
|
||||
const UPDATE_ACTIONABLE_CEILING: usize = 5_554;
|
||||
/// **5,582 (MONKEY integration round 3, graphics programme)** — measured on the merged tree
|
||||
/// after declaring the orders the lanes had left out (wind → wetness → fog-model writers of
|
||||
/// `MonkeyFrame`; the viewer publish before its new readers; the sky clock and sky tier before
|
||||
/// the consume set; the grass benders on `GlobalTransform` and after the camera-pose copy).
|
||||
/// What remains, read off the dump: 13 pairs of `skybox::animate_skyboxes` against the
|
||||
/// `MatAnimTable` allocators (attach/spawn/doodad systems) — the allocator case of 2300, the
|
||||
/// skybox writes only the rows it owns — and one pair each of the new systems against the two
|
||||
/// exclusive systems (`finish_colliders`, `apply_net_updates`), the 2343 class.
|
||||
const UPDATE_ACTIONABLE_CEILING: usize = 5_582;
|
||||
const UPDATE_ACTIONABLE_SLACK: usize = 40;
|
||||
|
||||
fn ratchet(what: &str, n: usize, ceiling: usize, slack: usize) {
|
||||
|
||||
@@ -328,7 +328,11 @@ impl Plugin for PlayerPlugin {
|
||||
Update,
|
||||
(world_focus::publish_viewer, world_focus::publish_view_focus)
|
||||
.after(benilla_world::schedule::WorldStage::Input)
|
||||
.before(benilla_world::schedule::WorldStage::Stream),
|
||||
.before(benilla_world::schedule::WorldStage::Stream)
|
||||
// MONKEY (integration): the `Viewer` readers the programme added (grass benders,
|
||||
// fog model, zone skybox) run after this frame's publish.
|
||||
.before(benilla_world::wind::WindTick)
|
||||
.before(benilla_world::lighting::LightingResolveSet),
|
||||
)
|
||||
.add_systems(
|
||||
Update,
|
||||
|
||||
@@ -26,6 +26,8 @@ pub(crate) fn plugin(app: &mut App) {
|
||||
bevy::asset::embedded_asset!(app, "shaders/ui_slice_gamma.wgsl");
|
||||
bevy::asset::embedded_asset!(app, "shaders/shadow_caster.wgsl");
|
||||
bevy::asset::embedded_asset!(app, "shaders/shadow_caster_cutout_prepass.wgsl");
|
||||
// MONKEY (ao): the contact-shadow pass.
|
||||
bevy::asset::embedded_asset!(app, "shaders/ssao.wgsl");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -61,6 +63,6 @@ mod tests {
|
||||
`shaders::plugin`, or was registered from a file that is not directly under src/"
|
||||
);
|
||||
}
|
||||
assert_eq!(found, 7, "the game's shader set changed size");
|
||||
assert_eq!(found, 8, "the game's shader set changed size");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,11 @@ pub(crate) struct SkyQualityPlugin;
|
||||
|
||||
impl Plugin for SkyQualityPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_resource::<SkyQuality>().add_systems(Update, bridge);
|
||||
app.init_resource::<SkyQuality>().add_systems(
|
||||
Update,
|
||||
// MONKEY (integration): the tier lands before the sky and cloud readers.
|
||||
bridge.before(benilla_world::lighting::LightingConsumeSet),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,10 +112,11 @@ impl Plugin for AmbientOcclusionPlugin {
|
||||
if !app.is_plugin_added::<AssetPlugin>() {
|
||||
return;
|
||||
}
|
||||
// MONKEY (integration): the crate's shader convention — embedded by `shaders::plugin`.
|
||||
let shader = app
|
||||
.world_mut()
|
||||
.resource_mut::<Assets<Shader>>()
|
||||
.add(Shader::from_wgsl(include_str!("shaders/ssao.wgsl"), "ssao.wgsl"));
|
||||
.world()
|
||||
.resource::<AssetServer>()
|
||||
.load("embedded://benilla_app/shaders/ssao.wgsl");
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -166,6 +166,20 @@ const GAP: &[(&str, &str, &str)] = &[
|
||||
nothing moves and `ui_char.rs`'s feed has nothing to announce — the stock SkillFrame \
|
||||
would only repaint under its own Close",
|
||||
),
|
||||
// MONKEY (integration): the two temp-point verbs, the same case as `CancelSkillUps` (pre-existing
|
||||
// upstream gap, surfaced once the Windows path fix let this gate run).
|
||||
(
|
||||
"AddSkillUp",
|
||||
"SKILL_LINES_CHANGED",
|
||||
"the reference's helper 0x4d32d0 moves a temp point and fires; the temp-point table stays \
|
||||
empty in this model (`skills.rs`), and `ui_char.rs`'s feed fires on any real block change",
|
||||
),
|
||||
(
|
||||
"RemoveSkillUp",
|
||||
"SKILL_LINES_CHANGED",
|
||||
"the reference's helper 0x4d3480, the same as AddSkillUp: no temp points to move here, and \
|
||||
`ui_char.rs`'s feed fires on any real block change",
|
||||
),
|
||||
(
|
||||
"ClickTargetTradeButton",
|
||||
"TRADE_REPLACE_ENCHANT",
|
||||
@@ -279,7 +293,8 @@ fn quoted(text: &str, name: &str) -> bool {
|
||||
}
|
||||
|
||||
fn short(p: &std::path::Path) -> String {
|
||||
let s = p.to_string_lossy();
|
||||
// MONKEY (integration): Windows paths use a backslash; the rows are written with `/`.
|
||||
let s = p.to_string_lossy().replace('\\', "/");
|
||||
s.split_once("/crates/")
|
||||
.map_or(s.to_string(), |(_, t)| t.to_string())
|
||||
}
|
||||
@@ -370,7 +385,7 @@ fn the_declared_rows_are_still_true() {
|
||||
}
|
||||
let named: Vec<&(PathBuf, String)> = src
|
||||
.iter()
|
||||
.filter(|(p, _)| p.to_string_lossy().ends_with(file))
|
||||
.filter(|(p, _)| short(p).ends_with(file)) // MONKEY (integration): separator-agnostic
|
||||
.collect();
|
||||
if named.is_empty() {
|
||||
wrong.push(format!(
|
||||
|
||||
@@ -514,7 +514,8 @@ mod tests {
|
||||
|
||||
// The chain's own source is the authority on what is wired — not a hand-copied list here,
|
||||
// which would be the very drift this test exists to catch.
|
||||
let this_file = include_str!("ui_session.rs");
|
||||
// MONKEY (integration): a CRLF checkout must still find the function's closing brace.
|
||||
let this_file = include_str!("ui_session.rs").replace("\r\n", "\n");
|
||||
let chain = this_file
|
||||
.split_once("pub(crate) fn feed_interact_npc")
|
||||
.expect("feed_interact_npc")
|
||||
|
||||
@@ -91,7 +91,8 @@ impl Plugin for SkyFxPlugin {
|
||||
});
|
||||
let quality = SkyQuality(SkyQuality::env_override().unwrap_or(0));
|
||||
app.insert_resource(quality)
|
||||
.add_systems(Update, tick_sky_clock);
|
||||
// MONKEY (integration): the clock ticks before its readers (sky colours, cloud FX).
|
||||
.add_systems(Update, tick_sky_clock.before(crate::lighting::LightingConsumeSet));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -196,6 +196,8 @@ impl Plugin for SkyboxPlugin {
|
||||
// After the lighting resolve, so the weight is this frame's crossfade, as the
|
||||
// fog's is.
|
||||
.after(crate::lighting::LightingResolveSet)
|
||||
// MONKEY (integration): a `WowLighting` reader joins the consume set.
|
||||
.in_set(crate::lighting::LightingConsumeSet)
|
||||
.in_set(SkyboxResolve),
|
||||
)
|
||||
// Camera-anchored placement runs after propagation, off this frame's camera pose.
|
||||
|
||||
@@ -124,7 +124,15 @@ fn wetness_tick(
|
||||
pub(super) fn register(app: &mut App) {
|
||||
app.init_resource::<RainSurfaces>()
|
||||
.init_resource::<Wetness>()
|
||||
.add_systems(Update, wetness_tick.after(WeatherTick));
|
||||
// MONKEY (integration): after the wind rows and before the resolve, so the three
|
||||
// `MonkeyFrame` writers run in one declared order.
|
||||
.add_systems(
|
||||
Update,
|
||||
wetness_tick
|
||||
.after(WeatherTick)
|
||||
.after(crate::wind::WindTick)
|
||||
.before(crate::lighting::LightingResolveSet),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -207,8 +207,10 @@ fn update_wind(
|
||||
fn update_benders(
|
||||
quality: Res<FoliageWind>,
|
||||
viewer: Res<crate::view::Viewer>,
|
||||
viewer_unit: Query<&Transform, (With<ViewerUnit>, With<WorldUnit>)>,
|
||||
units: Query<(&Transform, &WorldUnit), Without<ViewerUnit>>,
|
||||
// MONKEY (integration): `GlobalTransform` (last propagation), not `Transform`, so the scan is
|
||||
// not an undeclared order against every unit mover in `Update`.
|
||||
viewer_unit: Query<&GlobalTransform, (With<ViewerUnit>, With<WorldUnit>)>,
|
||||
units: Query<(&GlobalTransform, &WorldUnit), Without<ViewerUnit>>,
|
||||
mut frame: ResMut<MonkeyFrame>,
|
||||
) {
|
||||
frame.bender_count = 0;
|
||||
@@ -220,7 +222,7 @@ fn update_benders(
|
||||
// no-avatar fallback that lets the parting instrument exercise the same receiver.
|
||||
let Some(player) = viewer
|
||||
.at
|
||||
.or_else(|| viewer_unit.single().ok().map(|t| t.translation))
|
||||
.or_else(|| viewer_unit.single().ok().map(|t| t.translation()))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
@@ -231,7 +233,7 @@ fn update_benders(
|
||||
// unit just to retain seven entries.
|
||||
let mut nearby = [(f32::INFINITY, Vec3::ZERO, 1.5); 7];
|
||||
for (transform, unit) in &units {
|
||||
let at = transform.translation;
|
||||
let at = transform.translation();
|
||||
let d2 = (at.xz() - player.xz()).length_squared();
|
||||
if d2 > 40.0 * 40.0 || d2 >= nearby[6].0 {
|
||||
continue;
|
||||
@@ -253,6 +255,11 @@ fn update_benders(
|
||||
}
|
||||
}
|
||||
|
||||
/// MONKEY (integration): the wind writers' set, so other `MonkeyFrame` writers (wetness) and the
|
||||
/// viewer publish can order against it.
|
||||
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct WindTick;
|
||||
|
||||
/// Installs the shared field after this frame's weather ramp has resolved.
|
||||
pub struct WindPlugin;
|
||||
|
||||
@@ -260,7 +267,18 @@ impl Plugin for WindPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_resource::<WindField>()
|
||||
.init_resource::<FoliageWind>()
|
||||
.add_systems(Update, (update_wind, update_benders).after(WeatherTick));
|
||||
// MONKEY (integration): one ordered writer run of `MonkeyFrame`'s wind rows, before
|
||||
// the lighting resolve (the fog model writes the same resource there).
|
||||
.add_systems(
|
||||
Update,
|
||||
(update_wind, update_benders)
|
||||
.chain()
|
||||
.in_set(WindTick)
|
||||
.after(WeatherTick)
|
||||
// The camera pose copy also writes `GlobalTransform` (on the camera only).
|
||||
.after(crate::view::publish_camera_pose)
|
||||
.before(crate::lighting::LightingResolveSet),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user