2024-01-19 03:28:01 +00:00
|
|
|
use binrw::{BinReaderExt, binrw};
|
|
|
|
|
2024-01-16 03:09:34 +00:00
|
|
|
pub enum Error{
|
2024-01-19 00:39:58 +00:00
|
|
|
InvalidHeader,
|
2024-01-19 03:28:01 +00:00
|
|
|
InvalidSegment(binrw::Error),
|
|
|
|
InvalidSegmentId(u64),
|
|
|
|
File(crate::file::Error),
|
2024-01-16 03:09:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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<SimulationInstruction> instruction
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2024-01-19 03:28:01 +00:00
|
|
|
//error hiding mock code
|
2024-01-17 04:07:11 +00:00
|
|
|
mod simulation{
|
2024-01-19 03:28:01 +00:00
|
|
|
#[super::binrw]
|
|
|
|
#[brw(little)]
|
2024-01-17 04:07:11 +00:00
|
|
|
pub struct State{}
|
2024-01-19 03:28:01 +00:00
|
|
|
#[super::binrw]
|
|
|
|
#[brw(little)]
|
2024-01-17 04:07:11 +00:00
|
|
|
pub struct Instruction{}
|
|
|
|
}
|
|
|
|
mod instruction{
|
2024-01-19 03:28:01 +00:00
|
|
|
#[super::binrw]
|
|
|
|
#[brw(little)]
|
|
|
|
pub struct TimedInstruction<Instruction:binrw::BinRead+binrw::BinWrite>{
|
|
|
|
time:u64,
|
|
|
|
instruction:Instruction
|
|
|
|
}
|
2024-01-17 04:07:11 +00:00
|
|
|
}
|
|
|
|
mod timeline{
|
2024-01-19 03:28:01 +00:00
|
|
|
#[super::binrw]
|
|
|
|
#[brw(little)]
|
|
|
|
pub struct Timeline<Instruction:binrw::BinRead+binrw::BinWrite>{
|
|
|
|
#[bw(try_calc(u32::try_from(instructions.len())))]
|
|
|
|
instruction_count:u32,
|
|
|
|
#[br(count=instruction_count)]
|
|
|
|
instructions:Vec<super::instruction::TimedInstruction<Instruction>>
|
|
|
|
}
|
2024-01-17 04:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//serious code
|
|
|
|
|
2024-01-19 03:28:01 +00:00
|
|
|
#[binrw]
|
|
|
|
#[brw(little)]
|
2024-01-18 23:33:22 +00:00
|
|
|
struct SegmentId(u64);
|
|
|
|
|
2024-01-19 03:28:01 +00:00
|
|
|
#[binrw]
|
|
|
|
#[brw(little)]
|
2024-01-18 23:33:22 +00:00
|
|
|
pub struct Segment{
|
|
|
|
state:simulation::State,
|
2024-01-19 03:28:01 +00:00
|
|
|
#[bw(try_calc(u32::try_from(instructions.len())))]
|
|
|
|
instruction_count:u32,
|
|
|
|
#[br(count=instruction_count)]
|
2024-01-18 23:33:22 +00:00
|
|
|
instructions:Vec<instruction::TimedInstruction<simulation::Instruction>>
|
|
|
|
}
|
|
|
|
|
2024-01-19 03:28:01 +00:00
|
|
|
pub struct StreamableBot<R:BinReaderExt>{
|
|
|
|
file:crate::file::File<R>,
|
2024-01-18 23:33:22 +00:00
|
|
|
timeline:timeline::Timeline<SegmentId>,
|
2024-01-19 03:28:01 +00:00
|
|
|
segment_id_to_block_id:Vec<crate::file::BlockId>,
|
2024-01-18 23:33:22 +00:00
|
|
|
}
|
2024-01-19 03:28:01 +00:00
|
|
|
impl<R:BinReaderExt> StreamableBot<R>{
|
|
|
|
pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{
|
2024-01-19 00:39:58 +00:00
|
|
|
Err(Error::InvalidHeader)
|
|
|
|
}
|
2024-01-19 03:28:01 +00:00
|
|
|
pub fn load_segment(&mut self,segment_id:SegmentId)->Result<Segment,Error>{
|
|
|
|
let block_id=*self.segment_id_to_block_id.get(segment_id.0 as usize).ok_or(Error::InvalidSegmentId(segment_id.0))?;
|
|
|
|
let mut block=self.file.take_block(block_id).map_err(|e|Error::File(e))?;
|
|
|
|
let segment=block.read_le().map_err(|e|Error::InvalidSegment(e))?;
|
|
|
|
Ok(segment)
|
2024-01-18 23:33:22 +00:00
|
|
|
}
|
2024-01-16 03:09:34 +00:00
|
|
|
}
|