lib
This commit is contained in:
parent
b0a1e4b126
commit
39196119ff
332
src/v1.rs
332
src/v1.rs
@ -1 +1,333 @@
|
||||
use binrw::{binrw,BinReaderExt,io::TakeSeekExt};
|
||||
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub enum Bool{
|
||||
#[brw(magic=0u32)]
|
||||
False,
|
||||
#[brw(magic=1u32)]
|
||||
True,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct Vector2{
|
||||
pub x:f32,
|
||||
pub y:f32,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct Vector3{
|
||||
pub x:f32,
|
||||
pub y:f32,
|
||||
pub z:f32,
|
||||
}
|
||||
|
||||
// input
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct InputEvent{
|
||||
pub game_controls:u32,
|
||||
pub mouse_pos:Vector2,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedInputEvent{
|
||||
pub time:f64,
|
||||
pub event:InputEvent,
|
||||
}
|
||||
|
||||
// output
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct OutputEvent{
|
||||
pub tick_info:u32,
|
||||
pub angles:Vector3,
|
||||
pub position:Vector3,
|
||||
pub velocity:Vector3,
|
||||
pub acceleration:Vector3,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedOutputEvent{
|
||||
pub time:f64,
|
||||
pub event:OutputEvent,
|
||||
}
|
||||
|
||||
// sound
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct SoundEvent{
|
||||
pub sound_type:u32,
|
||||
pub material:u32,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedSoundEvent{
|
||||
pub time:f64,
|
||||
pub event:SoundEvent,
|
||||
}
|
||||
|
||||
// world
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct WorldEventReset{
|
||||
pub position:Vector3,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct WorldEventButton{
|
||||
pub button_id:u32,
|
||||
#[brw(magic=b"quatdata")]
|
||||
__:(),
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct WorldEventSetTime{
|
||||
pub time:f64,
|
||||
#[brw(magic=b"data")]
|
||||
__:(),
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct WorldEventSetPaused{
|
||||
pub paused:Bool,
|
||||
#[brw(magic=b"quatdata")]
|
||||
__:(),
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub enum WorldEvent{
|
||||
#[brw(magic=0u32)]
|
||||
Reset(WorldEventReset),
|
||||
#[brw(magic=1u32)]
|
||||
Button(WorldEventButton),
|
||||
#[brw(magic=2u32)]
|
||||
SetTime(WorldEventSetTime),
|
||||
#[brw(magic=3u32)]
|
||||
SetPaused(WorldEventSetPaused),
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedWorldEvent{
|
||||
pub time:f64,
|
||||
pub event:WorldEvent,
|
||||
}
|
||||
|
||||
// gravity
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct GravityEvent{
|
||||
pub gravity:Vector3,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedGravityEvent{
|
||||
pub time:f64,
|
||||
pub event:GravityEvent,
|
||||
}
|
||||
|
||||
// run
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub enum RunEventType{
|
||||
#[brw(magic=0u32)]
|
||||
Prepare,
|
||||
#[brw(magic=1u32)]
|
||||
Start,
|
||||
#[brw(magic=2u32)]
|
||||
Finish,
|
||||
#[brw(magic=3u32)]
|
||||
Clear,
|
||||
#[brw(magic=4u32)]
|
||||
Flag,
|
||||
#[brw(magic=5u32)]
|
||||
LoadState,
|
||||
#[brw(magic=6u32)]
|
||||
SaveState,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct RunEvent{
|
||||
run_event_type:RunEventType,
|
||||
mode_id:i32,
|
||||
flag_reason_id:u32,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedRunEvent{
|
||||
pub time:f64,
|
||||
pub event:RunEvent,
|
||||
}
|
||||
|
||||
// camera
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct CameraEvent{
|
||||
pub camera_event_id:u32,
|
||||
pub value:Vector3,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedCameraEvent{
|
||||
pub time:f64,
|
||||
pub event:CameraEvent,
|
||||
}
|
||||
|
||||
// setting
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct SettingEvent{
|
||||
pub setting_id:u32,
|
||||
pub value:f64,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedSettingEvent{
|
||||
pub time:f64,
|
||||
pub event:SettingEvent,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Block{
|
||||
pub input_events:Vec<TimedInputEvent>,
|
||||
pub output_events:Vec<TimedOutputEvent>,
|
||||
pub sound_events:Vec<TimedSoundEvent>,
|
||||
pub world_events:Vec<TimedWorldEvent>,
|
||||
pub gravity_events:Vec<TimedGravityEvent>,
|
||||
pub run_events:Vec<TimedRunEvent>,
|
||||
pub camera_events:Vec<TimedCameraEvent>,
|
||||
pub setting_events:Vec<TimedSettingEvent>,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
enum EventType{
|
||||
#[brw(magic=1u32)]
|
||||
Input,
|
||||
#[brw(magic=2u32)]
|
||||
Output,
|
||||
#[brw(magic=3u32)]
|
||||
Sound,
|
||||
#[brw(magic=4u32)]
|
||||
World,
|
||||
#[brw(magic=5u32)]
|
||||
Gravity,
|
||||
#[brw(magic=6u32)]
|
||||
Run,
|
||||
#[brw(magic=7u32)]
|
||||
Camera,
|
||||
#[brw(magic=8u32)]
|
||||
Setting,
|
||||
}
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
struct EventChunkHeader{
|
||||
event_type:EventType,
|
||||
num_events:u32,
|
||||
}
|
||||
|
||||
// first time I've managed to write BinRead generics without this stupid T::Args<'a>:Required thing blocking me
|
||||
fn read_data_into_events<'a,R:BinReaderExt,T>(data:&mut R,events:&mut Vec<T>,num_events:usize)->binrw::BinResult<()>
|
||||
where
|
||||
T:binrw::BinRead,
|
||||
T::Args<'a>:binrw::__private::Required,
|
||||
{
|
||||
// there is only supposed to be at most one of each type of event chunk per block, so no need to amortize.
|
||||
events.reserve_exact(num_events);
|
||||
for _ in 0..num_events{
|
||||
events.push(data.read_le()?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Block{
|
||||
fn read<R:BinReaderExt>(mut data:R)->binrw::BinResult<Block>{
|
||||
let mut block=Block::default();
|
||||
// well... this looks error prone
|
||||
while let Ok(event_chunk_header)=data.read_le::<EventChunkHeader>(){
|
||||
match event_chunk_header.event_type{
|
||||
EventType::Input=>read_data_into_events(&mut data,&mut block.input_events,event_chunk_header.num_events as usize)?,
|
||||
EventType::Output=>read_data_into_events(&mut data,&mut block.output_events,event_chunk_header.num_events as usize)?,
|
||||
EventType::Sound=>read_data_into_events(&mut data,&mut block.sound_events,event_chunk_header.num_events as usize)?,
|
||||
EventType::World=>read_data_into_events(&mut data,&mut block.world_events,event_chunk_header.num_events as usize)?,
|
||||
EventType::Gravity=>read_data_into_events(&mut data,&mut block.gravity_events,event_chunk_header.num_events as usize)?,
|
||||
EventType::Run=>read_data_into_events(&mut data,&mut block.run_events,event_chunk_header.num_events as usize)?,
|
||||
EventType::Camera=>read_data_into_events(&mut data,&mut block.camera_events,event_chunk_header.num_events as usize)?,
|
||||
EventType::Setting=>read_data_into_events(&mut data,&mut block.setting_events,event_chunk_header.num_events as usize)?,
|
||||
}
|
||||
}
|
||||
Ok(block)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
InvalidBlockId(BlockId),
|
||||
Seek(std::io::Error),
|
||||
InvalidData(binrw::Error),
|
||||
}
|
||||
impl std::fmt::Display for Error{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"{self:?}")
|
||||
}
|
||||
}
|
||||
impl std::error::Error for Error{}
|
||||
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
#[derive(Debug)]
|
||||
pub struct BlockId(u32);
|
||||
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct TimedBlockId{
|
||||
pub time:f64,
|
||||
pub block_id:BlockId,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
pub struct FileHeader{
|
||||
#[brw(magic=b"qbot")]
|
||||
pub file_version:u32,
|
||||
pub num_offline_events:u32,
|
||||
pub num_realtime_events:u32,
|
||||
#[br(count=num_offline_events+num_realtime_events+1)]
|
||||
pub block_positions:Vec<u32>,
|
||||
#[br(count=num_offline_events)]
|
||||
pub offline_blocks_timeline:Vec<TimedBlockId>,
|
||||
#[br(count=num_realtime_events)]
|
||||
pub realtime_blocks_timeline:Vec<TimedBlockId>,
|
||||
}
|
||||
|
||||
pub struct File<R:BinReaderExt>{
|
||||
header:FileHeader,
|
||||
//reference to the data
|
||||
data:R,
|
||||
}
|
||||
|
||||
impl<R:BinReaderExt> File<R>{
|
||||
pub fn new(mut input:R)->Result<File<R>,binrw::Error>{
|
||||
Ok(File{
|
||||
header:input.read_le()?,
|
||||
data:input,
|
||||
})
|
||||
}
|
||||
fn data_mut(&mut self)->&mut R{
|
||||
&mut self.data
|
||||
}
|
||||
fn block_reader(&mut self,block_id:BlockId)->Result<binrw::io::TakeSeek<&mut R>,Error>{
|
||||
if self.header.block_positions.len() as u32<=block_id.0{
|
||||
return Err(Error::InvalidBlockId(block_id))
|
||||
}
|
||||
let block_start=self.header.block_positions[block_id.0 as usize] as u64;
|
||||
let block_end=self.header.block_positions[block_id.0 as usize+1] as u64;
|
||||
self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(Error::Seek)?;
|
||||
Ok(self.data_mut().take_seek(block_end-block_start))
|
||||
}
|
||||
pub fn read_block(&mut self,block_id:BlockId)->Result<Block,Error>{
|
||||
let data=self.block_reader(block_id)?;
|
||||
let block=Block::read(data).map_err(Error::InvalidData)?;
|
||||
Ok(block)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user