Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
c807fd98e6
|
|||
|
d108697552
|
|||
|
0cd02fbb75
|
|||
|
3674bb38b3
|
|||
|
3323b0109a
|
|||
|
8c776f29b0
|
|||
|
87ba477f63
|
|||
|
508a0db66f
|
|||
|
e88d62c3ea
|
|||
|
1b6b02ef5a
|
|||
|
dc87100e91
|
|||
|
224a873d89
|
|||
|
3cf39032cc
|
|||
|
0c896f3ee1
|
|||
|
17edf88e05
|
|||
|
42e91e3627
|
|||
| f9c5ef7b44 | |||
|
b9aaf9d30f
|
|||
|
8b365a0579
|
|||
|
71685468b6
|
|||
|
9ace707bbb
|
|||
|
7cb66719b0
|
|||
|
27aa3fb5d1
|
|||
|
a6c10eab21
|
|||
|
4ef063a474
|
|||
|
03b5b8c239
|
|||
|
488ce55990
|
|||
|
fe98210d10
|
|||
|
2eb282dfe2
|
|||
| c8ec986a2b | |||
|
a6ce331682
|
|||
|
6a6849ec79
|
|||
| 8b52f0765f | |||
| 8030308310 | |||
| 67bb41fa5e | |||
| 7659e941b9 | |||
| fd9ddd9ca8 | |||
| 7f86d0edaf | |||
|
6021177364
|
|||
|
eb26ba0593
|
|||
|
d4e94ab0da
|
|||
|
cdbb5e6b01
|
|||
|
240a8798cd
|
|||
|
7e0cb86a32
|
|||
|
9fdaf34df3
|
|||
|
cc67966743
|
|||
|
9af3f4e6cf
|
|||
|
95b8fb2d95
|
|||
|
503710aa95
|
|||
|
fd59928644
|
|||
|
873ea5e9da
|
|||
|
f3768af543
|
|||
|
91d1ba68d4
|
|||
| 3a13ae1642 | |||
| f21b5f8c40 |
38
Cargo.lock
generated
38
Cargo.lock
generated
@@ -10,9 +10,9 @@ checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
|
||||
|
||||
[[package]]
|
||||
name = "binrw"
|
||||
version = "0.14.1"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d4bca59c20d6f40c2cc0802afbe1e788b89096f61bdf7aeea6bf00f10c2909b"
|
||||
checksum = "81419ff39e6ed10a92a7f125290859776ced35d9a08a665ae40b23e7ca702f30"
|
||||
dependencies = [
|
||||
"array-init",
|
||||
"binrw_derive",
|
||||
@@ -21,9 +21,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "binrw_derive"
|
||||
version = "0.14.1"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8ba42866ce5bced2645bfa15e97eef2c62d2bdb530510538de8dd3d04efff3c"
|
||||
checksum = "376404e55ec40d0d6f8b4b7df3f87b87954bd987f0cf9a7207ea3b6ea5c9add4"
|
||||
dependencies = [
|
||||
"either",
|
||||
"owo-colors",
|
||||
@@ -34,15 +34,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.22.0"
|
||||
version = "1.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
|
||||
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
@@ -61,31 +61,31 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.5.0"
|
||||
version = "4.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.94"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strafesnet_roblox_bot_file"
|
||||
version = "0.3.1"
|
||||
version = "0.9.4"
|
||||
dependencies = [
|
||||
"binrw",
|
||||
"bitflags",
|
||||
@@ -94,9 +94,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
version = "2.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -105,6 +105,6 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[package]
|
||||
name = "strafesnet_roblox_bot_file"
|
||||
version = "0.3.1"
|
||||
edition = "2021"
|
||||
version = "0.9.4"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
binrw = "0.14.1"
|
||||
binrw = "0.15.0"
|
||||
bitflags = "2.6.0"
|
||||
itertools = { version = "0.14.0", optional = true }
|
||||
|
||||
|
||||
14
README.md
14
README.md
@@ -3,7 +3,7 @@ Roblox Bhop/Surf Bot File Format
|
||||
|
||||
## Example
|
||||
|
||||
Read the whole file with the itertools feature enabled:
|
||||
Read the whole file and print each position:
|
||||
```rust
|
||||
use strafesnet_roblox_bot_file::v0::read_all_to_block;
|
||||
|
||||
@@ -11,6 +11,10 @@ let file=std::fs::read("bot_file")?;
|
||||
let mut input=std::io::Cursor::new(file);
|
||||
|
||||
let block=read_all_to_block(&mut input)?;
|
||||
|
||||
for output_event in &block.output_events{
|
||||
println!("{:?}",output_event.event.position);
|
||||
}
|
||||
```
|
||||
Or decode individual blocks using block location info:
|
||||
```rust
|
||||
@@ -19,21 +23,25 @@ use strafesnet_roblox_bot_file::v0::{Block,BlockTimelines,FileHeader};
|
||||
let file=std::fs::read("bot_file")?;
|
||||
let mut input=std::io::Cursor::new(file);
|
||||
|
||||
// FileHeader is the first 16 bytes of the file.
|
||||
let header=FileHeader::from_reader(&mut input)?;
|
||||
// BlockTimelines is an index of the blocks within the file.
|
||||
let timelines=BlockTimelines::from_reader(&header,&mut input)?;
|
||||
|
||||
// offline blocks include the following event types:
|
||||
// World, Gravity, Run, Camera, Setting
|
||||
for timed in timelines.offline_blocks(){
|
||||
let block_info=timelines.block_info(timed.event)?;
|
||||
let block=Block::from_reader(block_info.take_seek(&mut input)?)?;
|
||||
let block_reader=block_info.take_seek(&mut input)?;
|
||||
let block=Block::from_reader(block_reader)?;
|
||||
}
|
||||
|
||||
// realtime blocks include the following event types:
|
||||
// Input, Output, Sound
|
||||
for timed in timelines.realtime_blocks(){
|
||||
let block_info=timelines.block_info(timed.event)?;
|
||||
let block=Block::from_reader(block_info.take_seek(&mut input)?)?;
|
||||
let block_reader=block_info.take_seek(&mut input)?;
|
||||
let block=Block::from_reader(block_reader)?;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
pub use binrw::Error as BinrwError;
|
||||
|
||||
pub mod v0;
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
65
src/tests.rs
65
src/tests.rs
@@ -1,42 +1,41 @@
|
||||
use crate::v0::{Block,BlockTimelines,FileHeader,Timed};
|
||||
use crate::v0;
|
||||
use crate::v0::{Block,BlockTimelines,FileHeader};
|
||||
|
||||
#[test]
|
||||
fn _1(){
|
||||
fn deserialize_manual()->Result<(),binrw::Error>{
|
||||
let file=std::fs::read("files/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d").unwrap();
|
||||
let mut input=std::io::Cursor::new(file);
|
||||
let header=FileHeader::from_reader(&mut input).unwrap();
|
||||
let timelines=BlockTimelines::from_reader(&header,&mut input).unwrap();
|
||||
println!("header={:?}",header);
|
||||
for &Timed{time,event:block_id} in timelines.offline_blocks(){
|
||||
println!("offline time={} block_id={:?}",time,block_id);
|
||||
let take_seek=timelines.block_info(block_id).unwrap().take_seek(&mut input).unwrap();
|
||||
let _block=Block::from_reader(take_seek).unwrap();
|
||||
// offline blocks include the following event types:
|
||||
// World, Gravity, Run, Camera, Setting
|
||||
let header=FileHeader::from_reader(&mut input)?;
|
||||
let timelines=BlockTimelines::from_reader(&header,&mut input)?;
|
||||
for block in timelines.offline_blocks(){
|
||||
let block_info=timelines.block_info(block.event).unwrap();
|
||||
let block_reader=block_info.take_seek(&mut input)?;
|
||||
let _block=Block::from_reader(block_reader)?;
|
||||
}
|
||||
for &Timed{time,event:block_id} in timelines.realtime_blocks(){
|
||||
println!("realtime time={} block_id={:?}",time,block_id);
|
||||
let take_seek=timelines.block_info(block_id).unwrap().take_seek(&mut input).unwrap();
|
||||
let _block=Block::from_reader(take_seek).unwrap();
|
||||
// realtime blocks include the following event types:
|
||||
// Input, Output, Sound
|
||||
for block in timelines.realtime_blocks(){
|
||||
let block_info=timelines.block_info(block.event).unwrap();
|
||||
let block_reader=block_info.take_seek(&mut input)?;
|
||||
let _block=Block::from_reader(block_reader)?;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="itertools")]
|
||||
use crate::v0::{read_all_to_block,Error};
|
||||
#[test]
|
||||
#[cfg(feature="itertools")]
|
||||
fn _2()->Result<(),Error>{
|
||||
let file=std::fs::read("files/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d").unwrap();
|
||||
|
||||
let t0=std::time::Instant::now();
|
||||
|
||||
let _block=read_all_to_block(std::io::Cursor::new(file))?;
|
||||
|
||||
println!("{:?}",t0.elapsed());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: file serialization test
|
||||
#[test]
|
||||
fn deserialize_all()->Result<(),v0::Error>{
|
||||
let file=std::fs::read("files/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d").unwrap();
|
||||
let _block=v0::read_all_to_block(std::io::Cursor::new(file))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature="itertools")]
|
||||
fn serialize_round_trip()->Result<(),binrw::Error>{
|
||||
let file=std::fs::read("files/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d").unwrap();
|
||||
let block=v0::read_all_to_block(std::io::Cursor::new(file.as_slice())).unwrap();
|
||||
|
||||
let mut data=Vec::with_capacity(file.len());
|
||||
v0::serialize(&block,&mut std::io::Cursor::new(&mut data))?;
|
||||
|
||||
// TODO: It encodes, but is it equal? Test something! PartialEq?
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user