pub struct Key(pub u32);Expand description
Represents keys that can be pressed during osu!standard gameplay. Includes mouse buttons (M1, M2), keyboard keys (K1, K2), and smoke.
Tuple Fields§
§0: u32Implementations§
Source§impl Key
impl Key
pub const M1: Self
pub const M2: Self
pub const K1: Self
pub const K2: Self
pub const SMOKE: Self
Sourcepub fn value(&self) -> u32
pub fn value(&self) -> u32
Examples found in repository?
examples/example_1.rs (line 81)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5 let osr_path = Path::new("assets/test.osr");
6
7 // Check if the file exists
8 if !osr_path.exists() {
9 eprintln!("Error: File 'assets/test.osr' not found!");
10 eprintln!("Please place a valid .osr file at 'assets/test.osr' to run this example.");
11 return Ok(());
12 }
13
14 println!("Reading replay from: {}", osr_path.display());
15
16 // Parse the replay file
17 match Replay::from_path(osr_path) {
18 Ok(replay) => {
19 println!("\n=== Replay Information ===");
20 println!("Username: {}", replay.username);
21 println!("Game Mode: {:?}", replay.mode);
22 println!("Game Version: {}", replay.game_version);
23 println!("Beatmap Hash: {}", replay.beatmap_hash);
24 println!("Score: {}", replay.score);
25 println!("Max Combo: {}", replay.max_combo);
26 println!("Perfect: {}", replay.perfect);
27 println!("Mods: {:?} (value: {})", replay.mods, replay.mods.value());
28 println!("Timestamp: {}", replay.timestamp);
29 println!("Replay ID: {}", replay.replay_id);
30
31 // Hit counts
32 println!("\n=== Hit Counts ===");
33 println!("300s: {}", replay.count_300);
34 println!("100s: {}", replay.count_100);
35 println!("50s: {}", replay.count_50);
36 println!("Gekis: {}", replay.count_geki);
37 println!("Katus: {}", replay.count_katu);
38 println!("Misses: {}", replay.count_miss);
39
40 // RNG seed
41 if let Some(seed) = replay.rng_seed {
42 println!("\n=== RNG Seed ===");
43 println!("Seed: {}", seed);
44 }
45
46 // Life bar information
47 if let Some(ref life_bar) = replay.life_bar_graph {
48 println!("\n=== Life Bar ===");
49 println!("Life bar states: {}", life_bar.len());
50 if !life_bar.is_empty() {
51 println!(
52 "First state: time={}ms, life={}",
53 life_bar[0].time, life_bar[0].life
54 );
55 println!(
56 "Last state: time={}ms, life={}",
57 life_bar[life_bar.len() - 1].time,
58 life_bar[life_bar.len() - 1].life
59 );
60 }
61 } else {
62 println!("\n=== Life Bar ===");
63 println!("No life bar data available");
64 }
65
66 // Replay data information
67 println!("\n=== Replay Data ===");
68 println!("Total events: {}", replay.replay_data.len());
69
70 if !replay.replay_data.is_empty() {
71 println!("\nFirst 5 events:");
72 for (i, event) in replay.replay_data.iter().take(5).enumerate() {
73 match event {
74 ReplayEvent::Osu(e) => {
75 println!(
76 " {}: Osu - time_delta={}ms, x={}, y={}, keys={}",
77 i + 1,
78 e.time_delta,
79 e.x,
80 e.y,
81 e.keys.value()
82 );
83 }
84 ReplayEvent::Taiko(e) => {
85 println!(
86 " {}: Taiko - time_delta={}ms, x={}, keys={}",
87 i + 1,
88 e.time_delta,
89 e.x,
90 e.keys.value()
91 );
92 }
93 ReplayEvent::Catch(e) => {
94 println!(
95 " {}: Catch - time_delta={}ms, x={}, dashing={}",
96 i + 1,
97 e.time_delta,
98 e.x,
99 e.dashing
100 );
101 }
102 ReplayEvent::Mania(e) => {
103 println!(
104 " {}: Mania - time_delta={}ms, keys={}",
105 i + 1,
106 e.time_delta,
107 e.keys.value()
108 );
109 }
110 }
111 }
112
113 if replay.replay_data.len() > 5 {
114 println!(" ... and {} more events", replay.replay_data.len() - 5);
115 }
116 }
117
118 // Calculate total replay duration
119 let total_time: i32 = replay
120 .replay_data
121 .iter()
122 .map(|event| event.time_delta())
123 .sum();
124
125 if total_time > 0 {
126 let minutes = total_time / 60000;
127 let seconds = (total_time % 60000) / 1000;
128 let milliseconds = total_time % 1000;
129 println!(
130 "\nTotal replay duration: {}:{:02}.{:03}",
131 minutes, seconds, milliseconds
132 );
133 }
134
135 // Try to write the replay back to verify our packer works
136 println!("\n=== Testing Write Functionality ===");
137 let output_path = "assets/test_output.osr";
138 match replay.write_path(output_path) {
139 Ok(()) => {
140 println!("Successfully wrote replay to: {}", output_path);
141
142 // Verify by reading it back
143 match Replay::from_path(output_path) {
144 Ok(replay_copy) => {
145 println!("Successfully verified written replay!");
146 println!("Original username: {}", replay.username);
147 println!("Copy username: {}", replay_copy.username);
148 println!("Scores match: {}", replay.score == replay_copy.score);
149 }
150 Err(e) => {
151 eprintln!("Error reading back written replay: {}", e);
152 }
153 }
154 }
155 Err(e) => {
156 eprintln!("Error writing replay: {}", e);
157 }
158 }
159
160 // Test uncompressed packing
161 println!("\n=== Testing Uncompressed Packing ===");
162 let uncompressed_path = "assets/test_uncompressed.osr";
163 match replay.pack_uncompressed() {
164 Ok(uncompressed_data) => {
165 std::fs::write(uncompressed_path, &uncompressed_data)?;
166 println!(
167 "Successfully wrote uncompressed replay to: {}",
168 uncompressed_path
169 );
170
171 // Compare file sizes
172 let compressed_size = std::fs::metadata(output_path)?.len();
173 let uncompressed_size = std::fs::metadata(uncompressed_path)?.len();
174
175 println!("Compressed file size: {} bytes", compressed_size);
176 println!("Uncompressed file size: {} bytes", uncompressed_size);
177 println!(
178 "Size difference: {} bytes ({}%)",
179 uncompressed_size as i64 - compressed_size as i64,
180 ((uncompressed_size as f64 - compressed_size as f64)
181 / compressed_size as f64
182 * 100.0) as i32
183 );
184
185 // Verify uncompressed replay can be read back
186 match Replay::from_path(uncompressed_path) {
187 Ok(replay_uncompressed) => {
188 println!("Successfully verified uncompressed replay!");
189 println!(
190 "Scores match: {}",
191 replay.score == replay_uncompressed.score
192 );
193 println!(
194 "Event counts match: {}",
195 replay.replay_data.len() == replay_uncompressed.replay_data.len()
196 );
197 }
198 Err(e) => {
199 eprintln!("Error reading back uncompressed replay: {}", e);
200 }
201 }
202 }
203 Err(e) => {
204 eprintln!("Error packing uncompressed replay: {}", e);
205 }
206 }
207 }
208 Err(e) => {
209 eprintln!("Error reading replay: {}", e);
210 eprintln!("Make sure the file is a valid .osr replay file.");
211 }
212 }
213
214 Ok(())
215}Trait Implementations§
impl Copy for Key
Source§impl<'de> Deserialize<'de> for Key
impl<'de> Deserialize<'de> for Key
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
impl Eq for Key
impl StructuralPartialEq for Key
Auto Trait Implementations§
impl Freeze for Key
impl RefUnwindSafe for Key
impl Send for Key
impl Sync for Key
impl Unpin for Key
impl UnsafeUnpin for Key
impl UnwindSafe for Key
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more