mirror of
https://codeberg.org/icewind/vbsp.git
synced 2026-06-03 10:44:07 +02:00
132 lines
3.1 KiB
Rust
132 lines
3.1 KiB
Rust
use crate::*;
|
|
use binrw::io::Cursor;
|
|
use binrw::BinReaderExt;
|
|
use std::borrow::Cow;
|
|
|
|
pub struct BspFile<'a> {
|
|
data: &'a [u8],
|
|
directories: Directories,
|
|
header: Header,
|
|
}
|
|
|
|
impl<'a> BspFile<'a> {
|
|
pub fn new(data: &'a [u8]) -> BspResult<Self> {
|
|
let mut cursor = Cursor::new(data);
|
|
let header: Header = cursor.read_le().map_err(|err| match err {
|
|
binrw::Error::BadMagic { .. } => {
|
|
BspError::UnexpectedHeader(data[..4].try_into().expect(
|
|
"always enough data because otherwise a different binrw error would be hit",
|
|
))
|
|
}
|
|
error => BspError::MalformedData(error),
|
|
})?;
|
|
let directories = cursor.read_le()?;
|
|
|
|
Ok(BspFile {
|
|
data,
|
|
directories,
|
|
header,
|
|
})
|
|
}
|
|
|
|
pub fn header(&self) -> &Header {
|
|
&self.header
|
|
}
|
|
|
|
pub fn lump_reader(&self, lump: LumpType) -> BspResult<LumpReader<Cursor<Cow<[u8]>>>> {
|
|
let entry = self.get_lump_entry(lump);
|
|
let data = self.get_lump(entry)?;
|
|
Ok(LumpReader::new(data, lump, entry.version))
|
|
}
|
|
|
|
pub fn get_lump_entry(&self, lump: LumpType) -> &LumpEntry {
|
|
&self.directories[lump]
|
|
}
|
|
|
|
pub fn get_lump(&self, lump: &LumpEntry) -> BspResult<Cow<[u8]>> {
|
|
let raw_data = self
|
|
.data
|
|
.get(lump.offset as usize..lump.offset as usize + lump.length as usize)
|
|
.ok_or(BspError::LumpOutOfBounds(*lump))?;
|
|
|
|
Ok(match lump.ident {
|
|
0 => Cow::Borrowed(raw_data),
|
|
_ => {
|
|
let data = lzma_decompress_with_header(raw_data, lump.ident as usize)?;
|
|
Cow::Owned(data)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
#[repr(C)]
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
pub enum LumpType {
|
|
Entities,
|
|
Planes,
|
|
TextureData,
|
|
Vertices,
|
|
Visibility,
|
|
Nodes,
|
|
TextureInfo,
|
|
Faces,
|
|
Lighting,
|
|
Occlusion,
|
|
Leaves,
|
|
FaceIds,
|
|
Edges,
|
|
SurfaceEdges,
|
|
Models,
|
|
WorldLights,
|
|
LeafFaces,
|
|
LeafBrushes,
|
|
Brushes,
|
|
BrushSides,
|
|
Areas,
|
|
AreaPortals,
|
|
Unused0,
|
|
Unused1,
|
|
Unused2,
|
|
Unused3,
|
|
DisplacementInfo,
|
|
OriginalFaces,
|
|
PhysDisplacement,
|
|
PhysCollide,
|
|
VertNormals,
|
|
VertNormalIndices,
|
|
DisplacementLightMapAlphas,
|
|
DisplacementVertices,
|
|
DisplacementLightMapSamplePositions,
|
|
GameLump,
|
|
LeafWaterData,
|
|
Primitives,
|
|
PrimVertices,
|
|
PrimIndices,
|
|
PakFile,
|
|
ClipPortalVertices,
|
|
CubeMaps,
|
|
TextureDataStringData,
|
|
TextureDataStringTable,
|
|
Overlays,
|
|
LeafMinimumDistanceToWater,
|
|
FaceMacroTextureInfo,
|
|
DisplacementTris,
|
|
PhysicsCollideSurface,
|
|
WaterOverlays,
|
|
LeafAmbientIndexHdr,
|
|
LeafAmbientIndex,
|
|
LightingHdr,
|
|
WorldLightsHdr,
|
|
LeafAmbientLightingHdr,
|
|
LeafAmbientLighting,
|
|
XZipPakFile,
|
|
FacesHdr,
|
|
MapFlags,
|
|
OverlayFades,
|
|
OverlaySystemLevels,
|
|
PhysLevel,
|
|
DisplacementMultiBlend,
|
|
}
|
|
|
|
static_assertions::const_assert_eq!(LumpType::DisplacementMultiBlend as usize, 63);
|