diff --git a/code/__DEFINES/rust.dm b/code/__DEFINES/rust.dm index 6ac60f4de08..a78d48c341f 100644 --- a/code/__DEFINES/rust.dm +++ b/code/__DEFINES/rust.dm @@ -57,6 +57,8 @@ /proc/byondapi_stack_trace(err) CRASH(err) +// MARK: MILLA + /proc/milla_init_z(z) return RUSTLIB_CALL(milla_initialize, z) @@ -116,6 +118,11 @@ /proc/create_environment(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature) return RUSTLIB_CALL(milla_create_environment, oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature) +/proc/set_zlevel_freeze(z, bool_frozen) + return RUSTLIB_CALL(milla_set_zlevel_frozen, z, bool_frozen) + +// MARK: MapManip + /proc/mapmanip_read_dmm(mapname) return RUSTLIB_CALL(mapmanip_read_dmm_file, mapname) diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm index 08437daa609..5858f9b1621 100644 --- a/code/datums/helper_datums/map_template.dm +++ b/code/datums/helper_datums/map_template.dm @@ -51,6 +51,9 @@ // if given a multi-z template // it might need to be adapted for that when that time comes GLOB.space_manager.add_dirt(placement.z) + var/datum/milla_safe/freeze_z_level/milla_freeze = new() + milla_freeze.invoke_async(T.z) + UNTIL(milla_freeze.done) try var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, shouldCropMap = TRUE) if(!bounds) diff --git a/code/modules/awaymissions/zlevel_helpers.dm b/code/modules/awaymissions/zlevel_helpers.dm index 749abdf47a5..ca3cc60c150 100644 --- a/code/modules/awaymissions/zlevel_helpers.dm +++ b/code/modules/awaymissions/zlevel_helpers.dm @@ -13,6 +13,8 @@ * turf in the world */ if(SSair && SSair.initialized) SSair.setup_turfs(bot_left, top_right) + log_debug("Unfreezing atmos.") + set_zlevel_freeze(bot_left.z, FALSE) log_debug("\tTook [stop_watch(subtimer)]s") subtimer = start_watch() @@ -39,3 +41,12 @@ for(var/otherthing in T) qdel(otherthing) T.ChangeTurf(T.baseturf) + +/datum/milla_safe/freeze_z_level + var/done = FALSE + +// Ensures that atmos is frozen before loading +/datum/milla_safe/freeze_z_level/on_run(z) + log_debug("Freezing atmos.") + set_zlevel_freeze(z, TRUE) + done = TRUE diff --git a/rust/src/milla/api.rs b/rust/src/milla/api.rs index 8239cfc1d95..a92b648732e 100644 --- a/rust/src/milla/api.rs +++ b/rust/src/milla/api.rs @@ -703,6 +703,27 @@ fn milla_get_tick_time() -> eyre::Result { )) } +/// BYOND API for freezing a specific z-level. +#[byondapi::bind] +fn milla_set_zlevel_frozen( + byond_z: ByondValue, + byond_frozen: ByondValue, +) -> eyre::Result { + let z = f32::try_from(byond_z)? as i32 - 1; + let frozen = bool::try_from(byond_frozen)?; + let buffers = BUFFERS.get().ok_or(eyre!("BUFFERS not initialized."))?; + let active = buffers.get_active().read().unwrap(); + let maybe_z_level = active.0[z as usize].try_write(); + if maybe_z_level.is_err() { + return Err(eyre!( + "Tried to freeze or unfreeze during asynchronous, read-only atmos. Use a /datum/milla_safe/..." + )); + } + let mut z_level = maybe_z_level.unwrap(); + z_level.frozen = frozen; + Ok(ByondValue::null()) +} + // Yay, tests! #[cfg(test)] mod tests { diff --git a/rust/src/milla/constants.rs b/rust/src/milla/constants.rs index 550ec73fcc1..75ba648af5d 100644 --- a/rust/src/milla/constants.rs +++ b/rust/src/milla/constants.rs @@ -1,5 +1,5 @@ /// How many Z levels we allow before being suspicious that the wrong number was sent. -pub(crate) const MAX_Z_LEVELS: i32 = 10; +pub(crate) const MAX_Z_LEVELS: i32 = 15; /// How big is the map? Assumed square. pub(crate) const MAP_SIZE: usize = 255; diff --git a/rust/src/milla/model.rs b/rust/src/milla/model.rs index 4b7ac10036e..838bb090cce 100644 --- a/rust/src/milla/model.rs +++ b/rust/src/milla/model.rs @@ -401,6 +401,7 @@ impl From<&InterestingTile> for Vec { pub(crate) struct ZLevel { tiles: Box<[Tile; MAP_SIZE * MAP_SIZE]>, pub(crate) active_pressure_chunks: HashSet<(u8, u8)>, + pub(crate) frozen: bool, } impl ZLevel { @@ -412,6 +413,7 @@ impl ZLevel { ZLevel { tiles: unbuilt.into_boxed_slice().try_into().unwrap(), active_pressure_chunks: HashSet::new(), + frozen: false, } } @@ -455,6 +457,7 @@ impl ZLevel { self.tiles[i].copy_from(&other.tiles[i]); } self.active_pressure_chunks = other.active_pressure_chunks.clone(); + self.frozen = other.frozen; } } diff --git a/rust/src/milla/tick.rs b/rust/src/milla/tick.rs index ee197e5788f..ca0f126beae 100644 --- a/rust/src/milla/tick.rs +++ b/rust/src/milla/tick.rs @@ -95,12 +95,14 @@ pub(crate) fn tick_z_level( // Initialize the new frame as a copy of the old one. next.copy_from(&prev); - simulate::find_walls(&mut next); - simulate::update_wind(&prev, &mut next); - simulate::flow_air(&prev, &mut next)?; - simulate::post_process(&prev, &mut next, &environments, new_interesting_tiles, z)?; + if !prev.frozen { + simulate::find_walls(&mut next); + simulate::update_wind(&prev, &mut next); + simulate::flow_air(&prev, &mut next)?; + simulate::post_process(&prev, &mut next, &environments, new_interesting_tiles, z)?; - next.active_pressure_chunks.clear(); + next.active_pressure_chunks.clear(); + } Ok(()) } diff --git a/rustlibs.dll b/rustlibs.dll index 9ff2cf0ca90..7d375e48185 100644 Binary files a/rustlibs.dll and b/rustlibs.dll differ diff --git a/rustlibs_prod.dll b/rustlibs_prod.dll index fde6bd0f899..9cecefa4bec 100644 Binary files a/rustlibs_prod.dll and b/rustlibs_prod.dll differ diff --git a/tools/ci/librustlibs_ci.so b/tools/ci/librustlibs_ci.so index 96e744b5efb..96da50944ae 100644 Binary files a/tools/ci/librustlibs_ci.so and b/tools/ci/librustlibs_ci.so differ