This commit is contained in:
Quaternions 2024-12-30 04:36:15 -08:00
parent b0a1e4b126
commit 39196119ff

332
src/v1.rs
View File

@ -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)
}
}