Maraiah/maraiah/map/minf.rs

137 lines
3.4 KiB
Rust

//! `Info` type.
use crate::{err::*, text::*};
use bitflags::bitflags;
/// Reads a `Minf` chunk.
pub fn read(b: &[u8]) -> ResultS<Info>
{
read_data! {
endian: BIG, buf: b, size: 88, start: 0, data {
let texture_id = u16[0];
let physics_id = u16[2];
let skypict_id = u16[4];
let miss_flags = u16[6] flag MissionFlags;
let envi_flags = u16[8] flag EnvironmentFlags;
let level_name = mac_roman_cstr[18; 66] no_try;
let entr_flags = u32[84] flag EntryFlags;
}
}
Ok(Info{texture_id, physics_id, skypict_id, miss_flags, envi_flags,
entr_flags, level_name})
}
/// Writes a `Minf` chunk.
pub fn write(v: &Info) -> Vec<u8>
{
let mut o = Vec::with_capacity(4);
o.extend(&v.texture_id.to_be_bytes());
o.extend(&v.physics_id.to_be_bytes());
o.extend(&v.skypict_id.to_be_bytes());
o.extend(&v.miss_flags.bits().to_be_bytes());
o.extend(&v.envi_flags.bits().to_be_bytes());
o.extend(&pad_zero(to_mac_roman(&v.level_name), 66));
o.extend(&v.entr_flags.bits().to_be_bytes());
o
}
/// Reads an old `Minf` chunk.
pub fn read_old(b: &[u8]) -> ResultS<Info>
{
let minf = read(b)?;
let mut entr_flags = if minf.entr_flags.is_empty() {
EntryFlags::SOLO
} else {
minf.entr_flags
};
if entr_flags.intersects(EntryFlags::SOLO | EntryFlags::CARNAGE) {
entr_flags.insert(EntryFlags::CO_OP)
}
Ok(Info{entr_flags, ..minf})
}
impl Default for Info
{
fn default() -> Self
{
Self{texture_id: 0,
physics_id: 1,
skypict_id: 0,
miss_flags: MissionFlags::empty(),
envi_flags: EnvironmentFlags::empty(),
entr_flags: EntryFlags::SOLO,
level_name: "Map".to_string()}
}
}
/// Static map information.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Info
{
pub texture_id: u16,
pub physics_id: u16,
pub skypict_id: u16,
pub miss_flags: MissionFlags,
pub envi_flags: EnvironmentFlags,
pub entr_flags: EntryFlags,
pub level_name: String,
}
bitflags! {
/// Static environment flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EnvironmentFlags: u16
{
const VACUUM = 1;
const MAGNETIC = 1 << 1;
const REBELLION = 1 << 2;
const LOW_GRAV = 1 << 3;
const M1_GLUE = 1 << 4;
const LAVA_FLOOR = 1 << 5;
const REBELLION2 = 1 << 6;
const MUSIC = 1 << 7;
const TERM_PAUSE = 1 << 8;
const M1_MONSTER = 1 << 9;
const M1_WEPS = 1 << 10;
}
}
bitflags! {
/// Static entry point flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EntryFlags: u32
{
const SOLO = 1;
const CO_OP = 1 << 1;
const CARNAGE = 1 << 2;
const KTMWTB = 1 << 3;
const KOTH = 1 << 4;
const DEFENSE = 1 << 5;
const RUGBY = 1 << 6;
const CTF = 1 << 7;
}
}
bitflags! {
/// Static mission flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MissionFlags: u16
{
const EXTERMINATION = 1;
const EXPLORATION = 1 << 1;
const RETRIEVAL = 1 << 2;
const REPAIR = 1 << 3;
const RESCUE = 1 << 4;
const M1_EXPLORATION = 1 << 5;
const M1_RESCUE = 1 << 6;
const M1_REPAIR = 1 << 7;
}
}
// EOF