Compare commits
14 Commits
file-forma
...
movestate
| Author | SHA1 | Date | |
|---|---|---|---|
| 54c0ef47c1 | |||
| df2524cd2d | |||
| d832004e03 | |||
| f929a61ac4 | |||
| aefaa8454c | |||
| 83e108c8e1 | |||
| fde62febcf | |||
| c5ecf6b34a | |||
| 2d2f0099ab | |||
| edd15d0a09 | |||
| 526666651a | |||
| 9005de6e8e | |||
| 6114835471 | |||
| cea51457a6 |
@@ -11,7 +11,6 @@ mod model_graphics;
|
||||
mod zeroes;
|
||||
mod worker;
|
||||
mod physics;
|
||||
mod sniffer;
|
||||
mod settings;
|
||||
mod framework;
|
||||
mod primitives;
|
||||
|
||||
@@ -18,7 +18,9 @@ pub enum PhysicsInstruction {
|
||||
Input(PhysicsInputInstruction),
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub enum PhysicsInputInstruction{
|
||||
pub enum PhysicsInputInstruction {
|
||||
ReplaceMouse(MouseState,MouseState),
|
||||
SetNextMouse(MouseState),
|
||||
SetMoveRight(bool),
|
||||
SetMoveUp(bool),
|
||||
SetMoveBack(bool),
|
||||
@@ -27,51 +29,26 @@ pub enum PhysicsInputInstruction{
|
||||
SetMoveForward(bool),
|
||||
SetJump(bool),
|
||||
SetZoom(bool),
|
||||
ReplaceMouse(MouseState,MouseState),
|
||||
SetNextMouse(MouseState),
|
||||
Reset,
|
||||
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,
|
||||
MoveMouse(glam::IVec2),
|
||||
MoveRight(bool),
|
||||
MoveUp(bool),
|
||||
MoveBack(bool),
|
||||
MoveLeft(bool),
|
||||
MoveDown(bool),
|
||||
MoveForward(bool),
|
||||
Jump(bool),
|
||||
Zoom(bool),
|
||||
Reset,
|
||||
Idle,
|
||||
//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
|
||||
//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)]
|
||||
pub struct Body {
|
||||
position: Planar64Vec3,//I64 where 2^32 = 1 u
|
||||
@@ -80,6 +57,38 @@ pub struct Body {
|
||||
time:Time,//nanoseconds x xxxxD!
|
||||
}
|
||||
|
||||
pub enum MoveRestriction {
|
||||
Air,
|
||||
Water,
|
||||
Ground,
|
||||
Ladder,//multiple ladders how
|
||||
}
|
||||
|
||||
/*
|
||||
enum InputInstruction {
|
||||
}
|
||||
struct InputState {
|
||||
}
|
||||
impl InputState {
|
||||
pub fn get_control(&self,control:u32) -> bool {
|
||||
self.controls&control!=0
|
||||
}
|
||||
}
|
||||
impl crate::instruction::InstructionEmitter<InputInstruction> for InputState{
|
||||
fn next_instruction(&self, time_limit:crate::body::Time) -> Option<TimedInstruction<InputInstruction>> {
|
||||
//this is polled by PhysicsState for actions like Jump
|
||||
//no, it has to be the other way around. physics is run up until the jump instruction, and then the jump instruction is pushed.
|
||||
self.queue.get(0)
|
||||
}
|
||||
}
|
||||
impl crate::instruction::InstructionConsumer<InputInstruction> for InputState{
|
||||
fn process_instruction(&mut self,ins:TimedInstruction<InputInstruction>){
|
||||
//add to queue
|
||||
self.queue.push(ins);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//hey dumbass just use a delta
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct MouseState {
|
||||
@@ -1308,7 +1317,6 @@ impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState
|
||||
//JUST POLLING!!! NO MUTATION
|
||||
let mut collector = crate::instruction::InstructionCollector::new(time_limit);
|
||||
//check for collision stop instructions with curent contacts
|
||||
//TODO: make this into a touching.next_instruction(&mut collector) member function
|
||||
for (_,collision_data) in &self.touching.contacts {
|
||||
collector.collect(self.predict_collision_end(self.time,time_limit,collision_data));
|
||||
}
|
||||
@@ -1360,6 +1368,7 @@ fn run_teleport_behaviour(teleport_behaviour:&Option<crate::model::TeleportBehav
|
||||
}
|
||||
},
|
||||
Some(crate::model::TeleportBehaviour::Wormhole(wormhole))=>{
|
||||
//telefart
|
||||
let origin_model=model;
|
||||
let destination_model=models.get_wormhole_model(wormhole.destination_model_id)?;
|
||||
//ignore the transform for now
|
||||
|
||||
134
src/sniffer.rs
134
src/sniffer.rs
@@ -1,134 +0,0 @@
|
||||
//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:
|
||||
StyleInfoOverrides style_info_overrides
|
||||
//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
|
||||
}
|
||||
//block 0 is the current block, not part of the map data
|
||||
u64 num_spacial_blocks
|
||||
for block_id in 1..num_spacial_blocks{
|
||||
u64 node_id
|
||||
u64 block_id
|
||||
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.
|
||||
|
||||
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
|
||||
}
|
||||
@@ -6,7 +6,7 @@ pub fn zeroes2(a0:Planar64,a1:Planar64,a2:Planar64) -> Vec<Planar64>{
|
||||
if a2==Planar64::ZERO{
|
||||
return zeroes1(a0, a1);
|
||||
}
|
||||
let radicand=a1.get() as i128*a1.get() as i128-a2.get() as i128*a0.get() as i128*4;
|
||||
let mut radicand=a1.get() as i128*a1.get() as i128-a2.get() as i128*a0.get() as i128*4;
|
||||
if 0<radicand {
|
||||
//start with f64 sqrt
|
||||
let planar_radicand=Planar64::raw(unsafe{(radicand as f64).sqrt().to_int_unchecked()});
|
||||
|
||||
Reference in New Issue
Block a user