Compare commits
11 Commits
master
...
file-forma
Author | SHA1 | Date | |
---|---|---|---|
ba83ffe60b | |||
07d6d995ed | |||
7bff8bca28 | |||
c301477a2e | |||
a3cd48b6db | |||
925dec1666 | |||
2c379d22a2 | |||
97ca5bca3b | |||
b92ccc2602 | |||
112d517ed4 | |||
041fed841f |
@ -7,6 +7,7 @@ mod worker;
|
|||||||
mod zeroes;
|
mod zeroes;
|
||||||
mod integer;
|
mod integer;
|
||||||
mod physics;
|
mod physics;
|
||||||
|
mod sniffer;
|
||||||
mod graphics;
|
mod graphics;
|
||||||
mod settings;
|
mod settings;
|
||||||
mod primitives;
|
mod primitives;
|
||||||
|
@ -18,9 +18,7 @@ pub enum PhysicsInstruction {
|
|||||||
Input(PhysicsInputInstruction),
|
Input(PhysicsInputInstruction),
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PhysicsInputInstruction {
|
pub enum PhysicsInputInstruction{
|
||||||
ReplaceMouse(MouseState,MouseState),
|
|
||||||
SetNextMouse(MouseState),
|
|
||||||
SetMoveRight(bool),
|
SetMoveRight(bool),
|
||||||
SetMoveUp(bool),
|
SetMoveUp(bool),
|
||||||
SetMoveBack(bool),
|
SetMoveBack(bool),
|
||||||
@ -29,12 +27,51 @@ pub enum PhysicsInputInstruction {
|
|||||||
SetMoveForward(bool),
|
SetMoveForward(bool),
|
||||||
SetJump(bool),
|
SetJump(bool),
|
||||||
SetZoom(bool),
|
SetZoom(bool),
|
||||||
|
ReplaceMouse(MouseState,MouseState),
|
||||||
|
SetNextMouse(MouseState),
|
||||||
Reset,
|
Reset,
|
||||||
Idle,
|
Idle,
|
||||||
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum InputInstruction {
|
||||||
|
MoveRight(bool)=0,
|
||||||
|
MoveUp(bool)=1,
|
||||||
|
MoveBack(bool)=2,
|
||||||
|
MoveLeft(bool)=3,
|
||||||
|
MoveDown(bool)=4,
|
||||||
|
MoveForward(bool)=5,
|
||||||
|
Jump(bool)=6,
|
||||||
|
Zoom(bool)=7,
|
||||||
|
MoveMouse(glam::IVec2)=64,
|
||||||
|
Reset=100,
|
||||||
|
Idle=127,
|
||||||
//Idle: there were no input events, but the simulation is safe to advance to this timestep
|
//Idle: there were no input events, but the simulation is safe to advance to this timestep
|
||||||
//for interpolation / networking / playback reasons, most playback heads will always want
|
//for interpolation / networking / playback reasons, most playback heads will always want
|
||||||
//to be 1 instruction ahead to generate the next state for interpolation.
|
//to be 1 instruction ahead to generate the next state for interpolation.
|
||||||
}
|
}
|
||||||
|
impl InputInstruction{
|
||||||
|
pub fn id(&self)->u32{
|
||||||
|
let parity=match self{
|
||||||
|
crate::physics::InputInstruction::MoveRight(s)
|
||||||
|
|crate::physics::InputInstruction::MoveUp(s)
|
||||||
|
|crate::physics::InputInstruction::MoveBack(s)
|
||||||
|
|crate::physics::InputInstruction::MoveLeft(s)
|
||||||
|
|crate::physics::InputInstruction::MoveDown(s)
|
||||||
|
|crate::physics::InputInstruction::MoveForward(s)
|
||||||
|
|crate::physics::InputInstruction::Jump(s)
|
||||||
|
|crate::physics::InputInstruction::Zoom(s)=>(*s as u32)<<31,
|
||||||
|
crate::physics::InputInstruction::MoveMouse(_)
|
||||||
|
|crate::physics::InputInstruction::Reset
|
||||||
|
|crate::physics::InputInstruction::Idle=>0u32,
|
||||||
|
};
|
||||||
|
self.discriminant()|parity
|
||||||
|
}
|
||||||
|
pub fn discriminant(&self)->u32{
|
||||||
|
//from documentation for std::mem::discriminant(&self)
|
||||||
|
unsafe{*<*const _>::from(self).cast::<u32>()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone,Hash,Default)]
|
#[derive(Clone,Hash,Default)]
|
||||||
pub struct Body{
|
pub struct Body{
|
||||||
@ -1887,4 +1924,4 @@ fn already_inside_hit_nothing(){
|
|||||||
Planar64Vec3::int(0,1,0),
|
Planar64Vec3::int(0,1,0),
|
||||||
Time::ZERO
|
Time::ZERO
|
||||||
),None);
|
),None);
|
||||||
}
|
}
|
||||||
|
134
src/sniffer.rs
Normal file
134
src/sniffer.rs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//file format "sniff"
|
||||||
|
|
||||||
|
/* spec
|
||||||
|
|
||||||
|
//begin global header
|
||||||
|
|
||||||
|
//global metadata (32 bytes)
|
||||||
|
b"SNFB"
|
||||||
|
u32 format_version
|
||||||
|
u64 priming_bytes
|
||||||
|
//how many bytes of the file must be read to guarantee all of the expected
|
||||||
|
//format-specific metadata is available to facilitate streaming the remaining contents
|
||||||
|
//used by the database to guarantee that it serves at least the bare minimum
|
||||||
|
u128 resource_uuid
|
||||||
|
//identifies the file from anywhere for any other file
|
||||||
|
|
||||||
|
//global block layout (variable size)
|
||||||
|
u64 num_blocks
|
||||||
|
for block_id in 0..num_blocks{
|
||||||
|
u64 first_byte
|
||||||
|
}
|
||||||
|
|
||||||
|
//end global header
|
||||||
|
|
||||||
|
//begin blocks
|
||||||
|
|
||||||
|
//each block is compressed with zstd or gz or something
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* block types
|
||||||
|
BLOCK_MAP_HEADER:
|
||||||
|
DefaultStyleInfo style_info
|
||||||
|
//bvh goes here
|
||||||
|
u64 num_nodes
|
||||||
|
//node 0 parent node is implied to be None
|
||||||
|
for node_id in 1..num_nodes{
|
||||||
|
u64 parent_node
|
||||||
|
}
|
||||||
|
u64 num_spacial_blocks
|
||||||
|
for spacial_block_id in 0..num_spacial_blocks{
|
||||||
|
u64 node_id
|
||||||
|
u64 block_id //data block
|
||||||
|
Aabb block_extents
|
||||||
|
}
|
||||||
|
//ideally spacial blocks are sorted from distance to start zone
|
||||||
|
//texture blocks are inserted before the first spacial block they are used in
|
||||||
|
|
||||||
|
BLOCK_MAP_RESOURCE:
|
||||||
|
//an individual one of the following:
|
||||||
|
- model (IndexedModel)
|
||||||
|
- shader (compiled SPIR-V)
|
||||||
|
- image (JpegXL)
|
||||||
|
- sound (Opus)
|
||||||
|
- video (AV1)
|
||||||
|
- animation (Trey thing)
|
||||||
|
|
||||||
|
BLOCK_MAP_OBJECT:
|
||||||
|
//an individual one of the following:
|
||||||
|
- model instance
|
||||||
|
- located resource
|
||||||
|
//for a list of resources, parse the object.
|
||||||
|
//alternatively, BLOCK_MAP_REGION lists a group of objects to be decoded all at once
|
||||||
|
|
||||||
|
BLOCK_BOT_HEADER:
|
||||||
|
u128 map_resource_uuid //which map is this bot running
|
||||||
|
u128 time_resource_uuid //resource database time
|
||||||
|
//don't include style info in bot header because it's in the physics state
|
||||||
|
//blocks are laid out in chronological order, but indices may jump around.
|
||||||
|
u64 num_segments
|
||||||
|
for _ in 0..num_segments{
|
||||||
|
i64 time //physics_state timestamp
|
||||||
|
u64 block_id
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCK_BOT_SEGMENT:
|
||||||
|
//format version indicates what version of these structures to use
|
||||||
|
PhysicsState physics_state
|
||||||
|
//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<PhysicsInstruction> instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCK_DEMO_HEADER:
|
||||||
|
//timeline of loading maps, player equipment, bots
|
||||||
|
*/
|
||||||
|
struct InputInstructionCodecState{
|
||||||
|
mouse_pos:glam::IVec2,
|
||||||
|
time:crate::integer::Time,
|
||||||
|
}
|
||||||
|
//8B - 12B
|
||||||
|
impl InputInstructionCodecState{
|
||||||
|
pub fn encode(&mut self,ins:&crate::instruction::TimedInstruction<crate::physics::InputInstruction>)->([u8;12],usize){
|
||||||
|
let dt=ins.time-self.time;
|
||||||
|
self.time=ins.time;
|
||||||
|
let mut data=[0u8;12];
|
||||||
|
[data[0],data[1],data[2],data[3]]=(dt.nanos() as u32).to_le_bytes();//4B
|
||||||
|
//instruction id packed with game control parity bit. This could be 1 byte but it ruins the alignment
|
||||||
|
[data[4],data[5],data[6],data[7]]=ins.instruction.id().to_le_bytes();//4B
|
||||||
|
match &ins.instruction{
|
||||||
|
&crate::physics::InputInstruction::MoveMouse(m)=>{//4B
|
||||||
|
let dm=m-self.mouse_pos;
|
||||||
|
[data[8],data[9]]=(dm.x as i16).to_le_bytes();
|
||||||
|
[data[10],data[11]]=(dm.y as i16).to_le_bytes();
|
||||||
|
self.mouse_pos=m;
|
||||||
|
(data,12)
|
||||||
|
},
|
||||||
|
//0B
|
||||||
|
crate::physics::InputInstruction::MoveRight(_)
|
||||||
|
|crate::physics::InputInstruction::MoveUp(_)
|
||||||
|
|crate::physics::InputInstruction::MoveBack(_)
|
||||||
|
|crate::physics::InputInstruction::MoveLeft(_)
|
||||||
|
|crate::physics::InputInstruction::MoveDown(_)
|
||||||
|
|crate::physics::InputInstruction::MoveForward(_)
|
||||||
|
|crate::physics::InputInstruction::Jump(_)
|
||||||
|
|crate::physics::InputInstruction::Zoom(_)
|
||||||
|
|crate::physics::InputInstruction::Reset
|
||||||
|
|crate::physics::InputInstruction::Idle=>(data,8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//everything must be 4 byte aligned, it's all going to be compressed so don't think too had about saving less than 4 bytes
|
||||||
|
//TODO: Omit (mouse only?) instructions that don't surround an actual physics instruction
|
||||||
|
fn write_input_instruction<W:std::io::Write>(state:&mut InputInstructionCodecState,w:&mut W,ins:&crate::instruction::TimedInstruction<crate::physics::InputInstruction>)->Result<usize,std::io::Error>{
|
||||||
|
//TODO: insert idle instruction if gap is over u32 nanoseconds
|
||||||
|
//TODO: don't write idle instructions
|
||||||
|
//OR: end the data block! the full state at the start of the next block will contain an absolute timestamp
|
||||||
|
let (data,size)=state.encode(ins);
|
||||||
|
w.write(&data[0..size])//8B-12B
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user