mirror of
https://codeberg.org/icewind/vbsp.git
synced 2026-06-03 18:54:05 +02:00
valve bsp wip
This commit is contained in:
parent
dbba7565d8
commit
08a1c53535
6 changed files with 568 additions and 712 deletions
149
src/bspfile.rs
Normal file
149
src/bspfile.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
use crate::*;
|
||||
use binread::io::Cursor;
|
||||
use binread::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> {
|
||||
const EXPECTED_HEADER: Header = Header {
|
||||
v: b'V',
|
||||
b: b'B',
|
||||
s: b'S',
|
||||
p: b'P',
|
||||
};
|
||||
// TODO: Use this to decide on the version to parse it as
|
||||
const EXPECTED_VERSION: u32 = 0x14;
|
||||
|
||||
let mut cursor = Cursor::new(data);
|
||||
let header: Header = cursor.read_le()?;
|
||||
let version: u32 = cursor.read_le()?;
|
||||
|
||||
if header != EXPECTED_HEADER || version != EXPECTED_VERSION {
|
||||
return Err(BspError::UnexpectedHeader(header));
|
||||
}
|
||||
|
||||
let directories = cursor.read_le()?;
|
||||
|
||||
let map_version: u32 = cursor.read_le()?;
|
||||
dbg!(map_version);
|
||||
|
||||
Ok(BspFile {
|
||||
data,
|
||||
directories,
|
||||
header,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn directories(&self) -> &Directories {
|
||||
&self.directories
|
||||
}
|
||||
|
||||
pub fn header(&self) -> &Header {
|
||||
&self.header
|
||||
}
|
||||
|
||||
pub fn lump_reader(&self, lump: LumpType) -> BspResult<LumpReader<Cursor<Cow<[u8]>>>> {
|
||||
let data = self.get_lump(lump)?;
|
||||
Ok(LumpReader::new(data))
|
||||
}
|
||||
|
||||
fn get_lump(&self, lump: LumpType) -> BspResult<Cow<[u8]>> {
|
||||
let lump = &self.directories[lump];
|
||||
let raw_data = self
|
||||
.data
|
||||
.get(lump.offset as usize..lump.offset as usize + lump.length as usize)
|
||||
.ok_or_else(|| BspError::LumpOutOfBounds(lump.clone()))?;
|
||||
|
||||
Ok(match lump.ident {
|
||||
0 => Cow::Borrowed(raw_data),
|
||||
_ => {
|
||||
let mut data: Vec<u8> = Vec::with_capacity(lump.ident as usize);
|
||||
let mut cursor = Cursor::new(raw_data);
|
||||
lzma_rs::lzma_decompress(&mut cursor, &mut data)
|
||||
.map_err(BspError::LumpDecompressError)?;
|
||||
if data.len() != lump.ident as usize {
|
||||
return Err(BspError::UnexpectedUncompressedLumpSize {
|
||||
got: data.len() as u32,
|
||||
expected: lump.ident,
|
||||
});
|
||||
}
|
||||
|
||||
Cow::Owned(data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[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,
|
||||
DisplayInfo,
|
||||
OriginalFaces,
|
||||
PhysDisplay,
|
||||
PhysCollide,
|
||||
VertNormals,
|
||||
VertNormalIndices,
|
||||
DisplayLightMapAlphas,
|
||||
DisplayVertices,
|
||||
DisplayLightMapSamplePositions,
|
||||
GameLump,
|
||||
LeafWaterData,
|
||||
Primitives,
|
||||
PrimVertices,
|
||||
PrimIndices,
|
||||
PakFile,
|
||||
ClipPortalVertices,
|
||||
CubeMaps,
|
||||
TextureDataStringData,
|
||||
TextureDataStringTable,
|
||||
Overlays,
|
||||
LeafMinimumDistanceToWater,
|
||||
FaceMacroTextureInfo,
|
||||
DisplayTris,
|
||||
PhysicsCollideSurface,
|
||||
WaterOverlays,
|
||||
LeafAmbientIndexHdr,
|
||||
LeafAmbientIndex,
|
||||
LightingHdr,
|
||||
WorldLightsHdr,
|
||||
LeafAmbientLightingHdr,
|
||||
LeafAmbientLighting,
|
||||
XZipPakFile,
|
||||
FacesHdr,
|
||||
MapFlags,
|
||||
OverlayFades,
|
||||
OverlaySystemLevels,
|
||||
PhysLevel,
|
||||
DisplayMultiBlend,
|
||||
}
|
||||
1021
src/lib.rs
1021
src/lib.rs
File diff suppressed because it is too large
Load diff
83
src/reader.rs
Normal file
83
src/reader.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
use crate::*;
|
||||
use binread::BinReaderExt;
|
||||
use bv::BitVec;
|
||||
use std::borrow::Cow;
|
||||
use std::mem::size_of;
|
||||
|
||||
pub struct LumpReader<R> {
|
||||
inner: R,
|
||||
length: usize,
|
||||
}
|
||||
|
||||
impl<'a> LumpReader<Cursor<Cow<'a, [u8]>>> {
|
||||
pub fn new(data: Cow<'a, [u8]>) -> Self {
|
||||
let length = data.len();
|
||||
let reader = Cursor::new(data);
|
||||
LumpReader {
|
||||
inner: reader,
|
||||
length,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BinReaderExt + Read> LumpReader<R> {
|
||||
pub fn read_entities(&mut self) -> BspResult<Entities> {
|
||||
let mut entities = String::with_capacity(self.length);
|
||||
self.inner.read_to_string(&mut entities)?;
|
||||
Ok(Entities { entities })
|
||||
}
|
||||
|
||||
pub fn read_vec<F, T>(&mut self, mut f: F) -> BspResult<Vec<T>>
|
||||
where
|
||||
F: FnMut(&mut LumpReader<R>) -> BspResult<T>,
|
||||
{
|
||||
let num_entries = self.length / size_of::<T>();
|
||||
let mut entries = Vec::with_capacity(num_entries);
|
||||
|
||||
for _ in 0..num_entries {
|
||||
entries.push(f(self)?);
|
||||
}
|
||||
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
pub fn read<T: BinRead>(&mut self) -> BspResult<T> {
|
||||
Ok(self.inner.read_le()?)
|
||||
}
|
||||
|
||||
pub fn read_visdata(&mut self) -> BspResult<VisData> {
|
||||
if (self.length as usize) < std::mem::size_of::<u32>() * 2 {
|
||||
return Ok(VisData::default());
|
||||
}
|
||||
|
||||
let n_vecs = self.inner.read_le()?;
|
||||
let sz_vecs = self.inner.read_le()?;
|
||||
let vecs_size = n_vecs as u64 * sz_vecs as u64;
|
||||
let mut vecs = Vec::with_capacity(
|
||||
vecs_size
|
||||
.try_into()
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?,
|
||||
);
|
||||
self.inner
|
||||
.by_ref()
|
||||
.take(vecs_size as u64)
|
||||
.read_to_end(&mut vecs)?;
|
||||
|
||||
if (vecs.len() as u64) < vecs_size {
|
||||
return Err(BspError::UnexpectedEOF);
|
||||
}
|
||||
|
||||
if (vecs.len() as u64) > vecs_size {
|
||||
return Err(BspError::UnexpectedExtraData);
|
||||
}
|
||||
|
||||
let vecs = BitVec::from_bits(vecs);
|
||||
|
||||
let vis_data = VisData {
|
||||
n_vecs,
|
||||
sz_vecs,
|
||||
vecs,
|
||||
};
|
||||
Ok(vis_data)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue