use binrw::{BinReaderExt, binrw}; #[derive(Debug)] pub enum Error{ InvalidHeader, InvalidSegment(binrw::Error), InvalidSegmentId(SegmentId), File(crate::file::Error), } /* block types BLOCK_BOT_HEADER: u128 map_resource_uuid //which map is this bot running //don't include style info in bot header because it's in the simulation state //blocks are laid out in chronological order, but indices may jump around. u64 num_segments for _ in 0..num_segments{ i64 time //simulation_state timestamp u64 block_id } BLOCK_BOT_SEGMENT: //format version indicates what version of these structures to use SimulationState simulation_state //SimulationState is just under ClientState which includes Play/Pause events that the simulation doesn't know about. //to read, greedily decode instructions until eof loop{ //delta encode as much as possible (time,mousepos) //strafe ticks are implied //physics can be implied in an input-only bot file TimedInstruction instruction } */ //error hiding mock code mod simulation{ #[super::binrw] #[brw(little)] pub struct State{} #[super::binrw] #[brw(little)] pub struct Instruction{} } // mod instruction{ // #[super::binrw] // #[brw(little)] // pub struct TimedInstruction{ // time:u64, // instruction:Instruction // } // } // mod timeline{ // #[super::binrw] // #[brw(little)] // pub struct Timeline{ // #[bw(try_calc(u32::try_from(instructions.len())))] // instruction_count:u32, // #[br(count=instruction_count)] // instructions:Vec> // } // } //serious code #[binrw] #[brw(little)] #[derive(Clone,Copy,Debug,id::Id)] pub struct SegmentId(u32); #[binrw] #[brw(little)] pub struct Segment{ state:simulation::State, //#[bw(try_calc(u32::try_from(instructions.len())))] //instruction_count:u32, //#[br(count=instruction_count)] //instructions:Vec> //please remember that strafe ticks are implicit! 33% smaller bot files } pub struct StreamableBot{ file:crate::file::File, //timeline:timeline::Timeline, segment_id_to_block_id:Vec, } impl StreamableBot{ pub(crate) fn new(file:crate::file::File)->Result{ Err(Error::InvalidHeader) } pub fn load_segment(&mut self,segment_id:SegmentId)->Result{ let block_id=*self.segment_id_to_block_id.get(segment_id.get() as usize).ok_or(Error::InvalidSegmentId(segment_id))?; let mut block=self.file.block_reader(block_id).map_err(Error::File)?; let segment=block.read_le().map_err(Error::InvalidSegment)?; Ok(segment) } }