physics versioning plan
This commit is contained in:
parent
91a1b3d65e
commit
eaecbc5b73
@ -28,12 +28,16 @@ pub enum Error{
|
|||||||
/* block types
|
/* block types
|
||||||
|
|
||||||
BLOCK_BOT_HEADER:
|
BLOCK_BOT_HEADER:
|
||||||
// Tegments are laid out in chronological order,
|
// Segments are laid out in chronological order,
|
||||||
// but block_id is not necessarily in ascending order.
|
// but block_id is not necessarily in ascending order.
|
||||||
//
|
//
|
||||||
// This is to place the final segment close to the start of the file,
|
// This is to place the final segment close to the start of the file,
|
||||||
// which allows the duration of the bot to be conveniently calculated
|
// which allows the duration of the bot to be conveniently calculated
|
||||||
// from the first and last instruction timestamps.
|
// from the first and last instruction timestamps.
|
||||||
|
//
|
||||||
|
// Use exact physics version for replay playback
|
||||||
|
// Use highest compatible physics version for verification
|
||||||
|
u32 physics_version
|
||||||
u32 num_segments
|
u32 num_segments
|
||||||
for _ in 0..num_segments{
|
for _ in 0..num_segments{
|
||||||
i64 time
|
i64 time
|
||||||
@ -61,6 +65,7 @@ struct SegmentHeader{
|
|||||||
#[binrw]
|
#[binrw]
|
||||||
#[brw(little)]
|
#[brw(little)]
|
||||||
struct Header{
|
struct Header{
|
||||||
|
physics_version:u32,
|
||||||
num_segments:u32,
|
num_segments:u32,
|
||||||
#[br(count=num_segments)]
|
#[br(count=num_segments)]
|
||||||
segments:Vec<SegmentHeader>,
|
segments:Vec<SegmentHeader>,
|
||||||
@ -151,7 +156,7 @@ impl<R:BinReaderExt> StreamableBot<R>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MAX_BLOCK_SIZE:usize=64*1024;//64 kB
|
const MAX_BLOCK_SIZE:usize=64*1024;//64 kB
|
||||||
pub fn write_bot<W:BinWriterExt>(mut writer:W,instructions:impl IntoIterator<Item=TimedPhysicsInstruction>)->Result<(),Error>{
|
pub fn write_bot<W:BinWriterExt>(mut writer:W,physics_version:u32,instructions:impl IntoIterator<Item=TimedPhysicsInstruction>)->Result<(),Error>{
|
||||||
// decide which instructions to put in which segment
|
// decide which instructions to put in which segment
|
||||||
// write segment 1 to block 1
|
// write segment 1 to block 1
|
||||||
// write segment N to block 2
|
// write segment N to block 2
|
||||||
@ -251,6 +256,7 @@ pub fn write_bot<W:BinWriterExt>(mut writer:W,instructions:impl IntoIterator<Ite
|
|||||||
};
|
};
|
||||||
|
|
||||||
let header=Header{
|
let header=Header{
|
||||||
|
physics_version,
|
||||||
num_segments:num_segments as u32,
|
num_segments:num_segments as u32,
|
||||||
segments,
|
segments,
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,45 @@ use strafesnet_common::integer::{self,vec3,mat3,Planar64,Planar64Vec3,Planar64Ma
|
|||||||
pub use strafesnet_common::physics::{Time,TimeInner};
|
pub use strafesnet_common::physics::{Time,TimeInner};
|
||||||
use gameplay::ModeState;
|
use gameplay::ModeState;
|
||||||
|
|
||||||
|
// Physics bug fixes can easily desync all bots.
|
||||||
|
//
|
||||||
|
// When replaying a bot, use the exact physics version which it was recorded with.
|
||||||
|
//
|
||||||
|
// When validating a new bot, use the latest compatible physics version
|
||||||
|
// from the compatiblity matrix, since it may include bugfixes
|
||||||
|
// for things like clipping through walls with surgical precision
|
||||||
|
// i.e. without breaking bots which don't exploit the bug.
|
||||||
|
//
|
||||||
|
// Compatible physics versions should be determined empirically via leaderboard resimulation.
|
||||||
|
// Compatible physics versions should result in an identical leaderboard state,
|
||||||
|
// or the only bots which fail are ones exploiting a surgically patched bug.
|
||||||
|
#[derive(Clone,Copy,Hash,Debug,id::Id,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
|
pub struct PhysicsVersion(u32);
|
||||||
|
pub const VERSION:PhysicsVersion=PhysicsVersion(0);
|
||||||
|
const LATEST_COMPATIBLE_VERSION:[u32;1+VERSION.0 as usize]=const{
|
||||||
|
let compat=[0];
|
||||||
|
|
||||||
|
let mut input_version=0;
|
||||||
|
while input_version<compat.len(){
|
||||||
|
// compatible version must be greater that or equal to the input version
|
||||||
|
assert!(input_version as u32<=compat[input_version]);
|
||||||
|
// compatible version must be a version that exists
|
||||||
|
assert!(compat[input_version]<=VERSION.0);
|
||||||
|
input_version+=1;
|
||||||
|
}
|
||||||
|
compat
|
||||||
|
};
|
||||||
|
pub enum PhysicsVersionError{
|
||||||
|
UnknownPhysicsVersion,
|
||||||
|
}
|
||||||
|
pub const fn get_latest_compatible_version(PhysicsVersion(version):PhysicsVersion)->Result<PhysicsVersion,PhysicsVersionError>{
|
||||||
|
if (version as usize)<LATEST_COMPATIBLE_VERSION.len(){
|
||||||
|
Ok(PhysicsVersion(LATEST_COMPATIBLE_VERSION[version as usize]))
|
||||||
|
}else{
|
||||||
|
Err(PhysicsVersionError::UnknownPhysicsVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type Body=crate::body::Body<TimeInner>;
|
pub type Body=crate::body::Body<TimeInner>;
|
||||||
type MouseState=strafesnet_common::mouse::MouseState<TimeInner>;
|
type MouseState=strafesnet_common::mouse::MouseState<TimeInner>;
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ impl InstructionConsumer<Instruction<'_>> for Session{
|
|||||||
std::thread::spawn(move ||{
|
std::thread::spawn(move ||{
|
||||||
std::fs::create_dir_all("replays").unwrap();
|
std::fs::create_dir_all("replays").unwrap();
|
||||||
let file=std::fs::File::create(file_name).unwrap();
|
let file=std::fs::File::create(file_name).unwrap();
|
||||||
strafesnet_snf::bot::write_bot(std::io::BufWriter::new(file),replay.recording.instructions).unwrap();
|
strafesnet_snf::bot::write_bot(std::io::BufWriter::new(file),crate::physics::VERSION.get(),replay.recording.instructions).unwrap();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user