mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-14 20:22:05 +00:00
changes: - rscadd: "BAPI - mapmanip submap performance improvements." - rscadd: "BAPI - mapmanip script." perf improv in the form of changing the map container from hashmap to a flat grid hashmap was only bad for big maps with lots of submaps - did not affect horizon with its one small submap the script:  --------- Co-authored-by: DreamySkrell <> Co-authored-by: AuroraBuildBot <action@github.com>
154 lines
4.8 KiB
Rust
154 lines
4.8 KiB
Rust
pub mod core;
|
|
pub mod tools;
|
|
|
|
pub use core::GridMap;
|
|
use eyre::Context;
|
|
use eyre::ContextCompat;
|
|
use rand::prelude::IteratorRandom;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[cfg(test)]
|
|
mod test;
|
|
|
|
///
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(tag = "type")]
|
|
pub enum MapManipulation {
|
|
SubmapExtractInsert {
|
|
submap_size_x: i64,
|
|
submap_size_y: i64,
|
|
submaps_dmm: String,
|
|
marker_extract: String,
|
|
marker_insert: String,
|
|
submaps_can_repeat: bool,
|
|
},
|
|
}
|
|
|
|
pub fn mapmanip_config_parse(config_path: &std::path::Path) -> eyre::Result<Vec<MapManipulation>> {
|
|
// read
|
|
let config = std::fs::read_to_string(config_path)
|
|
.wrap_err(format!("mapmanip config read err: {config_path:?}"))?;
|
|
|
|
// strip comments
|
|
// as the jsonc format is "json with comments"
|
|
// but serde_json lib can only handle actual json
|
|
let re = regex::Regex::new(r"\/\/.*")?;
|
|
let config = re.replace_all(&config, "");
|
|
|
|
// parse
|
|
let config = serde_json::from_str::<Vec<MapManipulation>>(&config)
|
|
.wrap_err(format!("mapmanip config json parse err: {config_path:?}"))?;
|
|
|
|
Ok(config)
|
|
}
|
|
|
|
pub fn mapmanip(
|
|
map_dir_path: &std::path::Path,
|
|
map: dmmtools::dmm::Map,
|
|
config: &Vec<MapManipulation>,
|
|
) -> eyre::Result<dmmtools::dmm::Map> {
|
|
// convert to gridmap
|
|
let mut map = core::to_grid_map(&map);
|
|
|
|
// go through all the manipulations in `.jsonc` config for this `.dmm`
|
|
for (n, manipulation) in config.iter().enumerate() {
|
|
// readable index for errors
|
|
let n = n + 1;
|
|
let config_len = config.len();
|
|
|
|
match manipulation {
|
|
MapManipulation::SubmapExtractInsert {
|
|
submap_size_x,
|
|
submap_size_y,
|
|
submaps_dmm,
|
|
marker_extract,
|
|
marker_insert,
|
|
submaps_can_repeat,
|
|
} => mapmanip_submap_extract_insert(
|
|
map_dir_path,
|
|
&mut map,
|
|
*submap_size_x,
|
|
*submap_size_y,
|
|
submaps_dmm,
|
|
marker_extract,
|
|
marker_insert,
|
|
*submaps_can_repeat,
|
|
)
|
|
.wrap_err(format!(
|
|
"submap extract insert fail;
|
|
submaps path: {submaps_dmm:?};
|
|
markers: {marker_extract}, {marker_insert};"
|
|
)),
|
|
}
|
|
.wrap_err(format!("mapmanip fail; manip n is: {n}/{config_len}"))?;
|
|
}
|
|
|
|
Ok(core::to_dict_map(&map).wrap_err("failed on `to_dict_map`")?)
|
|
}
|
|
|
|
fn mapmanip_submap_extract_insert(
|
|
map_dir_path: &std::path::Path,
|
|
map: &mut GridMap,
|
|
submap_size_x: i64,
|
|
submap_size_y: i64,
|
|
submaps_dmm: &String,
|
|
marker_extract: &String,
|
|
marker_insert: &String,
|
|
submaps_can_repeat: bool,
|
|
) -> eyre::Result<()> {
|
|
let submap_size = dmmtools::dmm::Coord2::new(
|
|
submap_size_x.try_into().wrap_err("invalid submap_size_x")?,
|
|
submap_size_y.try_into().wrap_err("invalid submap_size_y")?,
|
|
);
|
|
|
|
// get the submaps map
|
|
let submaps_dmm: std::path::PathBuf = submaps_dmm.try_into().wrap_err("invalid path")?;
|
|
let submaps_dmm = map_dir_path.join(submaps_dmm);
|
|
let submaps_map = GridMap::from_file(&submaps_dmm)
|
|
.wrap_err(format!("can't read and parse submap dmm: {submaps_dmm:?}"))?;
|
|
|
|
// find all the submap extract markers
|
|
let mut marker_extract_coords = vec![];
|
|
for (coord, tile) in submaps_map.grid.iter() {
|
|
if tile.prefabs.iter().any(|p| p.path == *marker_extract) {
|
|
marker_extract_coords.push(coord);
|
|
}
|
|
}
|
|
|
|
// find all the insert markers
|
|
let mut marker_insert_coords = vec![];
|
|
for (coord, tile) in map.grid.iter() {
|
|
if tile.prefabs.iter().any(|p| p.path == *marker_insert) {
|
|
marker_insert_coords.push(coord);
|
|
}
|
|
}
|
|
|
|
// do all the extracts-inserts
|
|
for insert_coord in marker_insert_coords {
|
|
// pick a submap
|
|
let (extract_coord_index, extract_coord) = marker_extract_coords
|
|
.iter()
|
|
.cloned()
|
|
.enumerate()
|
|
.choose(&mut rand::thread_rng())
|
|
.wrap_err(format!(
|
|
"can't pick a submap to extract; no more extract markers in the submaps dmm; marker type: {marker_extract}"
|
|
))?;
|
|
|
|
// if submaps should not be repeating, remove this one from the list
|
|
if !submaps_can_repeat {
|
|
marker_extract_coords.remove(extract_coord_index);
|
|
}
|
|
|
|
// extract that submap from the submap dmm
|
|
let extracted = tools::extract_submap(&submaps_map, extract_coord, submap_size)
|
|
.wrap_err(format!("submap extraction failed; from {extract_coord}"))?;
|
|
|
|
// and insert the submap into the manipulated map
|
|
tools::insert_submap(&extracted, insert_coord, map)
|
|
.wrap_err(format!("submap insertion failed; at {insert_coord}"))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|