Skip to content

Commit

Permalink
BAPI - mapmanip multiz support (Aurorastation#19687)
Browse files Browse the repository at this point in the history
changes:
  - rscadd: "BAPI - mapmanip multiz support."

needed for the current map freeze

before, multiz dmm maps were not handled at all, always assuming there's
one zlevel (reading and writing)
now with this PR, multiz dmm maps will be handled correctly, both
submaps and the maps they are inserted into

---------

Co-authored-by: DreamySkrell <>
Co-authored-by: AuroraBuildBot <[email protected]>
  • Loading branch information
DreamySkrell and actions-user authored Jul 24, 2024
1 parent 13d6557 commit 60c5a2a
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 116 deletions.
Binary file modified bapi.dll
Binary file not shown.
7 changes: 7 additions & 0 deletions html/changelogs/DreamySkrell-bapi-multiz.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

author: DreamySkrell

delete-after: True

changes:
- rscadd: "BAPI - mapmanip multiz support."
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,57 @@
"type": "SubmapExtractInsert",
"submap_size_x": 7,
"submap_size_y": 5,
"submap_size_z": 1,
"submaps_dmm": "hegemony_waypoint_submaps.dmm",
"marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/hegemony_waypoint/chapel",
"marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/hegemony_waypoint/chapel",
"submaps_can_repeat": false
},

{
"type": "SubmapExtractInsert",
"submap_size_x": 11,
"submap_size_y": 5,
"submap_size_z": 1,
"submaps_dmm": "hegemony_waypoint_submaps.dmm",
"marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/hegemony_waypoint/kitchen",
"marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/hegemony_waypoint/kitchen",
"submaps_can_repeat": false
},

{
"type": "SubmapExtractInsert",
"submap_size_x": 7,
"submap_size_y": 5,
"submap_size_z": 1,
"submaps_dmm": "hegemony_waypoint_submaps.dmm",
"marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/hegemony_waypoint/dorms",
"marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/hegemony_waypoint/dorms",
"submaps_can_repeat": false
},

{
"type": "SubmapExtractInsert",
"submap_size_x": 5,
"submap_size_y": 6,
"submap_size_z": 1,
"submaps_dmm": "hegemony_waypoint_submaps.dmm",
"marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/hegemony_waypoint/eva",
"marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/hegemony_waypoint/eva",
"submaps_can_repeat": false
},

{
"type": "SubmapExtractInsert",
"submap_size_x": 5,
"submap_size_y": 6,
"submap_size_z": 1,
"submaps_dmm": "hegemony_waypoint_submaps.dmm",
"marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/hegemony_waypoint/atmos",
"marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/hegemony_waypoint/atmos",
"submaps_can_repeat": false
},

{
"type": "SubmapExtractInsert",
"submap_size_x": 5,
"submap_size_y": 7,
"submap_size_z": 1,
"submaps_dmm": "hegemony_waypoint_submaps.dmm",
"marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/hegemony_waypoint/hydro",
"marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/hegemony_waypoint/hydro",
Expand Down
1 change: 1 addition & 0 deletions maps/sccv_horizon/sccv_horizon-1_deck_1.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"type": "SubmapExtractInsert",
"submap_size_x": 3,
"submap_size_y": 5,
"submap_size_z": 1,
"submaps_dmm": "submaps/ops_warehouse_small_storage.dmm", // separate folder for horizon submaps for easier organization
"marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/sccv_horizon/ops_warehouse_small_storage",
"marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/sccv_horizon/ops_warehouse_small_storage",
Expand Down
7 changes: 0 additions & 7 deletions rust/bapi/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions rust/bapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ eyre = "0.6.12"
diff = "0.1"
# general utility lib for iterator operations
itertools = "0.10.5"
# simple flat grid, basically just wrapper over Vec<Vec<T>>
grid = "0.14.0"
# fast hashmap
fxhash = "0.2.1"
# generating random numbers
Expand Down
59 changes: 38 additions & 21 deletions rust/bapi/src/mapmanip/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod map_to_string;
pub use map_to_string::map_to_string;

use dmmtools::dmm;
use dmmtools::dmm::Coord2;
use dmmtools::dmm::Coord3;

///
#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -54,50 +54,67 @@ impl Tile {
}
}

/// Thin abstraction over `grid::Grid`, to provide a hashmap-like interface,
/// and to translate between dmm coords (start at 1) and grid coords (start at 0).
/// Thin abstraction over a flat vec, to provide a simple hashmap-like interface,
/// and to translate between 3D dmm coords (start at 1), and 1D flat vec coords (start at 0).
/// The translation is so that it looks better in logs/errors/etc,
/// where shown coords would correspond to coords seen in game or in strongdmm.
#[derive(Clone, Debug)]
pub struct TileGrid {
pub grid: grid::Grid<crate::mapmanip::core::Tile>,
pub size: Coord3,
pub grid: Vec<crate::mapmanip::core::Tile>,
}

impl TileGrid {
pub fn new(size_x: i32, size_y: i32) -> TileGrid {
pub fn new(size_x: i32, size_y: i32, size_z: i32) -> TileGrid {
Self {
grid: grid::Grid::new(size_x as usize, size_y as usize),
size: Coord3::new(size_x, size_y, size_z),
grid: vec![Tile::default(); (size_x * size_y * size_y) as usize],
}
}

pub fn len(&self) -> usize {
self.grid.size().0 * self.grid.size().1
self.grid.len()
}

pub fn iter(&self) -> impl Iterator<Item = (Coord2, &Tile)> {
self.grid
.indexed_iter()
.map(|((x, y), t)| (Coord2::new((x + 1) as i32, (y + 1) as i32), t))
fn coord_to_index(&self, coord: &Coord3) -> usize {
let coord = Coord3::new(coord.x - 1, coord.y - 1, coord.z - 1);
((coord.x) + (coord.y * self.size.x) + (coord.z * self.size.x * self.size.y)) as usize
}

pub fn get_mut(&mut self, coord: &Coord2) -> Option<&mut Tile> {
self.grid
.get_mut((coord.x - 1) as usize, (coord.y - 1) as usize)
fn index_to_coord(&self, index: usize) -> Coord3 {
let index = index as i32;
Coord3::new(
(index % self.size.x) + 1,
((index / self.size.x) % self.size.y) + 1,
(index / (self.size.x * self.size.y)) + 1,
)
}

pub fn get(&self, coord: &Coord2) -> Option<&Tile> {
self.grid
.get((coord.x - 1) as usize, (coord.y - 1) as usize)
pub fn get_mut(&mut self, coord: &Coord3) -> Option<&mut Tile> {
let index = self.coord_to_index(coord);
self.grid.get_mut(index)
}

pub fn get(&self, coord: &Coord3) -> Option<&Tile> {
self.grid.get(self.coord_to_index(coord))
}

pub fn insert(&mut self, coord: &Coord2, tile: Tile) {
pub fn insert(&mut self, coord: &Coord3, tile: Tile) {
*self.get_mut(coord).unwrap() = tile;
}

pub fn keys(&self) -> impl Iterator<Item = Coord2> + '_ {
pub fn iter(&self) -> impl Iterator<Item = (Coord3, &Tile)> {
self.grid
.indexed_iter()
.map(|((x, y), _t)| Coord2::new((x + 1) as i32, (y + 1) as i32))
.iter()
.enumerate()
.map(|(i, t)| (self.index_to_coord(i), t))
}

pub fn keys(&self) -> impl Iterator<Item = Coord3> + '_ {
self.grid
.iter()
.enumerate()
.map(|(i, _t)| self.index_to_coord(i))
}

pub fn values(&self) -> impl Iterator<Item = &Tile> {
Expand Down
18 changes: 10 additions & 8 deletions rust/bapi/src/mapmanip/core/to_dict_map.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::mapmanip::GridMap;
use dmmtools::dmm::{self, Coord2};
use dmmtools::dmm::{self, Coord3};
use eyre::ContextCompat;
use fxhash::FxHashMap;
use std::collections::BTreeSet;
Expand Down Expand Up @@ -52,13 +52,15 @@ pub fn to_dict_map(grid_map: &GridMap) -> eyre::Result<dmm::Map> {

for x in 1..(grid_map.size.x + 1) {
for y in 1..(grid_map.size.y + 1) {
let coord = Coord2::new(x, y);
if let Some(tile) = grid_map.grid.get(&coord) {
let key = dictionary_reverse.get(&tile.prefabs).unwrap().clone();
dict_map.dictionary.insert(key, tile.prefabs.clone());
dict_map.grid[coord3_to_index(coord.z(1), grid_map.size)] = key;
} else {
panic!();
for z in 1..(grid_map.size.z + 1) {
let coord = Coord3::new(x, y, z);
if let Some(tile) = grid_map.grid.get(&coord) {
let key = dictionary_reverse.get(&tile.prefabs).unwrap().clone();
dict_map.dictionary.insert(key, tile.prefabs.clone());
dict_map.grid[coord3_to_index(coord, grid_map.size)] = key;
} else {
eyre::bail!("to_dict_map fail; grid map has no coord: {coord:?}");
}
}
}
}
Expand Down
21 changes: 12 additions & 9 deletions rust/bapi/src/mapmanip/core/to_grid_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@ pub fn to_grid_map(dict_map: &dmm::Map) -> GridMap {
grid: crate::mapmanip::core::TileGrid::new(
dict_map.dim_xyz().0 as i32,
dict_map.dim_xyz().1 as i32,
dict_map.dim_xyz().2 as i32,
),
};

for x in 1..grid_map.size.x + 1 {
for y in 1..grid_map.size.y + 1 {
let coord = dmm::Coord2::new(x, y);
let key = dict_map.index(coord.z(1));
let prefabs = dict_map.dictionary[key].clone();
let tile = Tile {
key_suggestion: *key,
prefabs,
};
let coord = dmm::Coord2::new(coord.x, coord.y);
grid_map.grid.insert(&coord, tile);
for z in 1..grid_map.size.z + 1 {
let coord = dmm::Coord3::new(x, y, z);
let key = dict_map.index(coord);
let prefabs = dict_map.dictionary[key].clone();
let tile = Tile {
key_suggestion: *key,
prefabs,
};
let coord = dmm::Coord3::new(coord.x, coord.y, coord.z);
grid_map.grid.insert(&coord, tile);
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion rust/bapi/src/mapmanip/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum MapManipulation {
SubmapExtractInsert {
submap_size_x: i64,
submap_size_y: i64,
submap_size_z: i64,
submaps_dmm: String,
marker_extract: String,
marker_insert: String,
Expand Down Expand Up @@ -60,6 +61,7 @@ pub fn mapmanip(
MapManipulation::SubmapExtractInsert {
submap_size_x,
submap_size_y,
submap_size_z,
submaps_dmm,
marker_extract,
marker_insert,
Expand All @@ -69,6 +71,7 @@ pub fn mapmanip(
&mut map,
*submap_size_x,
*submap_size_y,
*submap_size_z,
submaps_dmm,
marker_extract,
marker_insert,
Expand All @@ -91,14 +94,16 @@ fn mapmanip_submap_extract_insert(
map: &mut GridMap,
submap_size_x: i64,
submap_size_y: i64,
submap_size_z: i64,
submaps_dmm: &String,
marker_extract: &String,
marker_insert: &String,
submaps_can_repeat: bool,
) -> eyre::Result<()> {
let submap_size = dmmtools::dmm::Coord2::new(
let submap_size = dmmtools::dmm::Coord3::new(
submap_size_x.try_into().wrap_err("invalid submap_size_x")?,
submap_size_y.try_into().wrap_err("invalid submap_size_y")?,
submap_size_z.try_into().wrap_err("invalid submap_size_z")?,
);

// get the submaps map
Expand Down
9 changes: 5 additions & 4 deletions rust/bapi/src/mapmanip/test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use dmmtools::dmm::{self, Coord2};
use dmmtools::dmm::{self, Coord3};
use itertools::Itertools;

fn print_diff(left: &str, right: &str) {
Expand Down Expand Up @@ -57,8 +57,8 @@ fn extract() {
let grid_map_src = crate::mapmanip::core::to_grid_map(&dict_map_src);
let grid_map_xtr = crate::mapmanip::tools::extract_submap(
&grid_map_src,
Coord2::new(4, 7),
Coord2::new(10, 5),
Coord3::new(4, 7, 1),
Coord3::new(10, 5, 1),
)
.unwrap();
let grid_map_xtr_expected = crate::mapmanip::core::to_grid_map(&dict_map_xtr_expected);
Expand Down Expand Up @@ -88,7 +88,7 @@ fn insert() {
crate::mapmanip::core::GridMap::from_file(&path_dst_expected).unwrap();
let grid_map_xtr = crate::mapmanip::core::GridMap::from_file(&path_xtr).unwrap();
let mut grid_map_dst = crate::mapmanip::core::GridMap::from_file(&path_dst).unwrap();
crate::mapmanip::tools::insert_submap(&grid_map_xtr, Coord2::new(6, 4), &mut grid_map_dst)
crate::mapmanip::tools::insert_submap(&grid_map_xtr, Coord3::new(6, 4, 1), &mut grid_map_dst)
.unwrap();

assert_eq!(
Expand Down Expand Up @@ -133,6 +133,7 @@ fn mapmanip_configs_parse() {
let foo = vec![crate::mapmanip::MapManipulation::SubmapExtractInsert {
submap_size_x: 1,
submap_size_y: 2,
submap_size_z: 3,
submaps_dmm: "a".to_owned(),
marker_extract: "b".to_owned(),
marker_insert: "c".to_owned(),
Expand Down
31 changes: 17 additions & 14 deletions rust/bapi/src/mapmanip/tools/extract_submap.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
use crate::mapmanip::core::GridMap;
use dmmtools::dmm;
use dmmtools::dmm::Coord2;
use dmmtools::dmm::Coord3;
use eyre::ContextCompat;

/// Returns part of map of `xtr_size` and at `xtr_coord` from `src_map`.
pub fn extract_submap(
src_map: &GridMap,
xtr_coord: dmm::Coord2,
xtr_size: dmm::Coord2,
xtr_coord: dmm::Coord3,
xtr_size: dmm::Coord3,
) -> eyre::Result<GridMap> {
let mut dst_map = GridMap {
size: xtr_size.z(1),
grid: crate::mapmanip::core::TileGrid::new(xtr_size.x, xtr_size.y),
size: xtr_size,
grid: crate::mapmanip::core::TileGrid::new(xtr_size.x, xtr_size.y, xtr_size.z),
};

for x in 1..(xtr_size.x + 1) {
for y in 1..(xtr_size.y + 1) {
let src_x = xtr_coord.x + x - 1;
let src_y = xtr_coord.y + y - 1;
for z in 1..(xtr_size.z + 1) {
let src_x = xtr_coord.x + x - 1;
let src_y = xtr_coord.y + y - 1;
let src_z = xtr_coord.z + z - 1;

let tile = src_map
.grid
.get(&Coord2::new(src_x, src_y))
.wrap_err(format!(
"cannot extract submap; coords out of bounds; x: {src_x}; y: {src_y};"
))?;
let tile = src_map
.grid
.get(&Coord3::new(src_x, src_y, src_z))
.wrap_err(format!(
"cannot extract submap; coords out of bounds; x: {src_x}; y: {src_y}; z: {src_z}"
))?;

dst_map.grid.insert(&Coord2::new(x, y), tile.clone());
dst_map.grid.insert(&Coord3::new(x, y, z), tile.clone());
}
}
}

Expand Down
Loading

0 comments on commit 60c5a2a

Please sign in to comment.