use crate::api::dungeon_mode::*;
use crate::api::enums::TerrainType;
use crate::ffi;
use core::slice;
impl DungeonTile {
pub fn init(&mut self) {
unsafe { ffi::InitializeTile(self as *mut _) };
}
pub fn get_terrain(&self) -> Option<TerrainType> {
unsafe { ffi::GetTileTerrain(force_mut_ptr!(self)) }
.try_into()
.ok()
}
pub fn set_terrain_obstacle_checked(&mut self, secondary_terrain: bool, room_index: u8) {
unsafe {
ffi::SetTerrainObstacleChecked(
self as *mut _,
secondary_terrain as ffi::bool_,
room_index,
)
}
}
pub fn set_secondary_terrain_on_wall(&mut self) {
unsafe { ffi::SetSecondaryTerrainOnWall(self as *mut _) }
}
pub fn bind_trap(&mut self, trap: &mut DungeonEntity, is_visible: bool) {
unsafe { ffi::BindTrapToTile(self, trap, is_visible as ffi::bool_) }
}
}
pub trait DungeonTileGridRead<const W: usize, const H: usize> {
fn get(&self, x: usize, y: usize) -> Option<&DungeonTile>;
fn iter(&self) -> DungeonTileGridIter<W>;
}
pub trait DungeonTileGridWrite<const W: usize, const H: usize>: DungeonTileGridRead<W, H> {
fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut DungeonTile>;
fn insert(&mut self, x: usize, y: usize, tile: DungeonTile);
fn iter_mut(&mut self) -> DungeonTileGridIterMut<W>;
}
pub struct DungeonTileGridRef<'a, const W: usize, const H: usize>(
pub(crate) &'a [[*mut ffi::tile; W]; H],
);
pub struct DungeonTileGridMut<'a, const W: usize, const H: usize>(
pub(crate) &'a mut [[*mut ffi::tile; W]; H],
);
impl<'a, const W: usize, const H: usize> DungeonTileGridRead<W, H>
for DungeonTileGridRef<'a, W, H>
{
fn get(&self, x: usize, y: usize) -> Option<&DungeonTile> {
unsafe { self.0[y][x].as_ref() }
}
fn iter(&self) -> DungeonTileGridIter<W> {
DungeonTileGridIter {
tiles_iter: self.0.iter(),
cur_row: None,
cur_row_iter: None,
}
}
}
impl<'a, const W: usize, const H: usize> DungeonTileGridRead<W, H>
for DungeonTileGridMut<'a, W, H>
{
fn get(&self, x: usize, y: usize) -> Option<&DungeonTile> {
unsafe { self.0[y][x].as_ref() }
}
fn iter(&self) -> DungeonTileGridIter<W> {
DungeonTileGridIter {
tiles_iter: self.0.iter(),
cur_row: None,
cur_row_iter: None,
}
}
}
impl<'a, const W: usize, const H: usize> DungeonTileGridWrite<W, H>
for DungeonTileGridMut<'a, W, H>
{
fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut DungeonTile> {
unsafe { self.0[y][x].as_mut().map(|tile| &mut *tile) }
}
fn insert(&mut self, x: usize, y: usize, tile: DungeonTile) {
let mut otile = unsafe { &mut *self.0[y][x] };
otile._bitfield_align_1 = tile._bitfield_align_1;
otile._bitfield_1 = tile._bitfield_1;
otile.spawn_or_visibility_flags = tile.spawn_or_visibility_flags;
otile.texture_id = tile.texture_id;
otile.field_0x6 = tile.field_0x6;
otile.room = tile.room;
otile.walkable_neighbor_flags = tile.walkable_neighbor_flags;
otile.monster = tile.monster;
otile.object = tile.object;
}
fn iter_mut(&mut self) -> DungeonTileGridIterMut<W> {
DungeonTileGridIterMut {
tiles_iter: self.0.iter(),
cur_row: None,
cur_row_iter: None,
}
}
}
pub struct DungeonTileGridIter<'a, const W: usize> {
tiles_iter: slice::Iter<'a, [*mut ffi::tile; W]>,
cur_row: Option<&'a [*mut ffi::tile; W]>,
cur_row_iter: Option<slice::Iter<'a, *mut ffi::tile>>,
}
impl<'a, const W: usize> Iterator for DungeonTileGridIter<'a, W> {
type Item = &'a DungeonTile;
fn next(&mut self) -> Option<Self::Item> {
if self.cur_row.is_none() {
self.cur_row = self.tiles_iter.next();
self.cur_row_iter = Some(self.cur_row?.iter());
}
let tile = self.cur_row_iter.as_mut().unwrap().next();
match tile {
Some(tile) => Some(unsafe { &**tile }),
None => {
self.cur_row = None;
self.next()
}
}
}
}
pub struct DungeonTileGridIterMut<'a, const W: usize> {
tiles_iter: slice::Iter<'a, [*mut ffi::tile; W]>,
cur_row: Option<&'a [*mut ffi::tile; W]>,
cur_row_iter: Option<slice::Iter<'a, *mut ffi::tile>>,
}
impl<'a, const W: usize> Iterator for DungeonTileGridIterMut<'a, W> {
type Item = &'a mut DungeonTile;
fn next(&mut self) -> Option<Self::Item> {
if self.cur_row.is_none() {
self.cur_row = self.tiles_iter.next();
self.cur_row_iter = Some(self.cur_row?.iter());
}
let tile = self.cur_row_iter.as_mut().unwrap().next();
match tile {
Some(tile) => Some(unsafe { &mut **tile }),
None => {
self.cur_row = None;
self.next()
}
}
}
}