chore: replace osynic_osudb with own osudb parser
This commit is contained in:
1 parent
4dc83c882d
commit
bf4ce18671
7 files changed
+291
-78
No files matched your search
@@ -12,8 +12,8 @@
|
|||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
"@tailwindcss/vite": "^4.1.11",
|
||||||
"@tauri-apps/api": "^2.10.1",
|
"@tauri-apps/api": "^2.10.1",
|
||||||
"@tauri-apps/plugin-dialog": "^2.6.0",
|
"@tauri-apps/plugin-dialog": "^2.7.0",
|
||||||
"@tauri-apps/plugin-fs": "^2.4.5",
|
"@tauri-apps/plugin-fs": "^2.5.0",
|
||||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||||
"@types/umami": "^2.10.1",
|
"@types/umami": "^2.10.1",
|
||||||
"animejs": "^4.1.3",
|
"animejs": "^4.1.3",
|
||||||
@@ -284,9 +284,9 @@
|
|||||||
|
|
||||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ=="],
|
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.6.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg=="],
|
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.7.0", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-4nS/hfGMGCXiAS3LtVjH9AgsSAPJeG/7R+q8agTFqytjnMa4Zq95Bq8WzVDkckpanX+yyRHXnRtrKXkANKDHvw=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-fs": ["@tauri-apps/plugin-fs@2.4.5", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-dVxWWGE6VrOxC7/jlhyE+ON/Cc2REJlM35R3PJX3UvFw2XwYhLGQVAIyrehenDdKjotipjYEVc4YjOl3qq90fA=="],
|
"@tauri-apps/plugin-fs": ["@tauri-apps/plugin-fs@2.5.0", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-c83kbz61AK+rKjhS+je9+stIO27nXj7p9cqeg36TwkIUtxpCFTttlHHtqon6h6FN54cXjyAjlMPOJcW3mwE5XQ=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-shell": ["@tauri-apps/[email protected]", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg=="],
|
"@tauri-apps/plugin-shell": ["@tauri-apps/[email protected]", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg=="],
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -25,8 +25,8 @@
|
|||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
"@tailwindcss/vite": "^4.1.11",
|
||||||
"@tauri-apps/api": "^2.10.1",
|
"@tauri-apps/api": "^2.10.1",
|
||||||
"@tauri-apps/plugin-dialog": "^2.6.0",
|
"@tauri-apps/plugin-dialog": "^2.7.0",
|
||||||
"@tauri-apps/plugin-fs": "^2.4.5",
|
"@tauri-apps/plugin-fs": "^2.5.0",
|
||||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||||
"@types/umami": "^2.10.1",
|
"@types/umami": "^2.10.1",
|
||||||
"animejs": "^4.1.3",
|
"animejs": "^4.1.3",
|
||||||
|
|||||||
Generated
+6
-48
@@ -43,9 +43,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.100"
|
version = "1.0.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-broadcast"
|
name = "async-broadcast"
|
||||||
@@ -475,10 +475,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
|
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
"wasm-bindgen",
|
|
||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -990,14 +988,15 @@ dependencies = [
|
|||||||
name = "ezpplauncher"
|
name = "ezpplauncher"
|
||||||
version = "3.1.4"
|
version = "3.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
"byteorder",
|
||||||
"discord-rich-presence",
|
"discord-rich-presence",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hardware-id",
|
"hardware-id",
|
||||||
"md5",
|
"md5",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"open",
|
"open",
|
||||||
"osynic_osudb",
|
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -2055,26 +2054,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "liblzma"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b6033b77c21d1f56deeae8014eb9fbe7bdf1765185a6c508b5ca82eeaed7f899"
|
|
||||||
dependencies = [
|
|
||||||
"liblzma-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "liblzma-sys"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1a60851d15cd8c5346eca4ab8babff585be2ae4bc8097c067291d3ffe2add3b6"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
@@ -2285,15 +2264,6 @@ version = "0.1.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom"
|
|
||||||
version = "8.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ntapi"
|
name = "ntapi"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -2509,9 +2479,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open"
|
name = "open"
|
||||||
version = "5.3.3"
|
version = "5.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43bb73a7fa3799b198970490a51174027ba0d4ec504b03cd08caf513d40024bc"
|
checksum = "9f3bab717c29a857abf75fcef718d441ec7cb2725f937343c734740a985d37fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dunce",
|
"dunce",
|
||||||
"is-wsl",
|
"is-wsl",
|
||||||
@@ -2551,18 +2521,6 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "osynic_osudb"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3b084931ebdadc8c8b778d662f9904d779e2749bdde3aa761cab3678d57bda1b"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"liblzma",
|
|
||||||
"nom",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.18.3"
|
version = "0.18.3"
|
||||||
|
|||||||
@@ -31,11 +31,12 @@ sysinfo = "0.38.4"
|
|||||||
reqwest = { version = "0.13.2", features = ["json", "stream", "query"] }
|
reqwest = { version = "0.13.2", features = ["json", "stream", "query"] }
|
||||||
md5 = "0.8.0"
|
md5 = "0.8.0"
|
||||||
tokio = { version = "1.52.1", features = ["full"] }
|
tokio = { version = "1.52.1", features = ["full"] }
|
||||||
open = "5.3.3"
|
open = "5.3.4"
|
||||||
discord-rich-presence = "1.1.0"
|
discord-rich-presence = "1.1.0"
|
||||||
once_cell = "1.21.4"
|
once_cell = "1.21.4"
|
||||||
futures-util = "0.3.32"
|
futures-util = "0.3.32"
|
||||||
osynic_osudb = "0.1.5"
|
byteorder = "1.5.0"
|
||||||
|
anyhow = "1.0.102"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winreg = "0.56.0"
|
winreg = "0.56.0"
|
||||||
|
|||||||
+19
-22
@@ -1,5 +1,4 @@
|
|||||||
use hardware_id::get_id;
|
use hardware_id::get_id;
|
||||||
use osynic_osudb::entity::osu::osudb::OsuDB;
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@@ -13,6 +12,7 @@ use tokio::io::AsyncWriteExt;
|
|||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
use tokio::time::{Duration, sleep};
|
use tokio::time::{Duration, sleep};
|
||||||
|
|
||||||
|
use crate::osudb::parse_osudb;
|
||||||
use crate::presence;
|
use crate::presence;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
check_folder_completeness, encrypt_password, get_osu_config, get_osu_user_config,
|
check_folder_completeness, encrypt_password, get_osu_config, get_osu_user_config,
|
||||||
@@ -161,10 +161,10 @@ pub async fn get_beatmapsets_count(folder: String) -> Option<u64> {
|
|||||||
if !osu_db_path.exists() {
|
if !osu_db_path.exists() {
|
||||||
return Some(0);
|
return Some(0);
|
||||||
}
|
}
|
||||||
let mut osudb = OsuDB::from_file(&osu_db_path).unwrap();
|
let osu_db_bytes = fs::read(osu_db_path).await.ok()?;
|
||||||
let beatmaps = osudb.beatmaps.iter_mut();
|
let osu_db = parse_osudb(osu_db_bytes).ok()?;
|
||||||
let beatmap_sets = beatmaps.map(|b| b.beatmapset_id).collect::<HashSet<_>>();
|
let beatmap_sets = osu_db.beatmaps.iter().map(|b| b.beatmapset_id).collect::<HashSet<_>>().len();
|
||||||
return Some(beatmap_sets.len() as u64);
|
Some(beatmap_sets as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
@@ -620,28 +620,25 @@ pub fn replace_ui_files(folder: String, revert: bool) -> Result<(), ReplaceUIErr
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fs::copy(source, dest).map_err(|e| {
|
std::fs::copy(source, dest)
|
||||||
ReplaceUIError::IoError(format!("Failed to copy {}: {}", name, e))
|
.map_err(|e| ReplaceUIError::IoError(format!("Failed to copy {}: {}", name, e)))?;
|
||||||
})?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
let restore_backup = |bak: &PathBuf,
|
let restore_backup =
|
||||||
dest: &PathBuf,
|
|bak: &PathBuf, dest: &PathBuf, name: &str| -> Result<(), ReplaceUIError> {
|
||||||
name: &str|
|
if bak.exists() {
|
||||||
-> Result<(), ReplaceUIError> {
|
if dest.exists() {
|
||||||
if bak.exists() {
|
std::fs::remove_file(dest).map_err(|e| {
|
||||||
if dest.exists() {
|
ReplaceUIError::IoError(format!("Failed to remove {}: {}", name, e))
|
||||||
std::fs::remove_file(dest).map_err(|e| {
|
})?;
|
||||||
ReplaceUIError::IoError(format!("Failed to remove {}: {}", name, e))
|
}
|
||||||
|
std::fs::rename(bak, dest).map_err(|e| {
|
||||||
|
ReplaceUIError::IoError(format!("Failed to rename {} from backup: {}", name, e))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
std::fs::rename(bak, dest).map_err(|e| {
|
Ok(())
|
||||||
ReplaceUIError::IoError(format!("Failed to rename {} from backup: {}", name, e))
|
};
|
||||||
})?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
};
|
|
||||||
|
|
||||||
if !revert {
|
if !revert {
|
||||||
if osu_ui.exists() && !osu_ui_bak.exists() {
|
if osu_ui.exists() && !osu_ui_bak.exists() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use tauri::Manager;
|
|||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod presence;
|
pub mod presence;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
pub mod osudb;
|
||||||
use crate::commands::{
|
use crate::commands::{
|
||||||
check_for_corruption, download_ezpp_launcher_update, download_ezpp_launcher_update_files,
|
check_for_corruption, download_ezpp_launcher_update, download_ezpp_launcher_update_files,
|
||||||
encrypt_string, exit, find_osu_installation, get_beatmapsets_count,
|
encrypt_string, exit, find_osu_installation, get_beatmapsets_count,
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
use std::io::{Cursor, Read};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
|
|
||||||
|
pub struct OsuReader {
|
||||||
|
cursor: Cursor<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsuReader {
|
||||||
|
pub fn new(data: Vec<u8>) -> Self {
|
||||||
|
Self {
|
||||||
|
cursor: Cursor::new(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_i16(&mut self) -> Result<i16> {
|
||||||
|
Ok(self.cursor.read_i16::<LittleEndian>()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_i32(&mut self) -> Result<i32> {
|
||||||
|
Ok(self.cursor.read_i32::<LittleEndian>()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_i64(&mut self) -> Result<i64> {
|
||||||
|
Ok(self.cursor.read_i64::<LittleEndian>()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_u8(&mut self) -> Result<u8> {
|
||||||
|
Ok(self.cursor.read_u8()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_f32(&mut self) -> Result<f32> {
|
||||||
|
Ok(self.cursor.read_f32::<LittleEndian>()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_f64(&mut self) -> Result<f64> {
|
||||||
|
Ok(self.cursor.read_f64::<LittleEndian>()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bool(&mut self) -> Result<bool> {
|
||||||
|
Ok(self.read_u8()? != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self) -> Result<Option<String>> {
|
||||||
|
let indicator = self.read_u8()?;
|
||||||
|
|
||||||
|
if indicator == 0 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if indicator != 0x0B {
|
||||||
|
return Err(anyhow!("Invalid osu string indicator"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = self.read_uleb128()? as usize;
|
||||||
|
let mut buf = vec![0; len];
|
||||||
|
self.cursor.read_exact(&mut buf)?;
|
||||||
|
|
||||||
|
Ok(Some(String::from_utf8(buf)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_uleb128(&mut self) -> Result<u64> {
|
||||||
|
let mut result = 0;
|
||||||
|
let mut shift = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let byte = self.read_u8()?;
|
||||||
|
result |= ((byte & 0x7F) as u64) << shift;
|
||||||
|
|
||||||
|
if (byte & 0x80) == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TimingPoint {
|
||||||
|
pub bpm: f64,
|
||||||
|
pub offset: f64,
|
||||||
|
pub inherited: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Beatmap {
|
||||||
|
pub artist_name: Option<String>,
|
||||||
|
pub song_title: Option<String>,
|
||||||
|
pub difficulty: Option<String>,
|
||||||
|
pub md5: Option<String>,
|
||||||
|
|
||||||
|
pub beatmap_id: i32,
|
||||||
|
pub beatmapset_id: i32,
|
||||||
|
pub mode: u8,
|
||||||
|
|
||||||
|
pub timing_points: Vec<TimingPoint>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OsuDbData {
|
||||||
|
pub osuver: i32,
|
||||||
|
pub folder_count: i32,
|
||||||
|
pub is_unlocked: bool,
|
||||||
|
pub date_unlock_ticks: i64,
|
||||||
|
pub username: Option<String>,
|
||||||
|
pub beatmaps: Vec<Beatmap>,
|
||||||
|
pub userperms: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// =========================
|
||||||
|
// PARSER
|
||||||
|
// =========================
|
||||||
|
//
|
||||||
|
|
||||||
|
pub fn parse_osudb(bytes: Vec<u8>) -> Result<OsuDbData> {
|
||||||
|
let mut reader = OsuReader::new(bytes);
|
||||||
|
|
||||||
|
let osuver = reader.read_i32()?;
|
||||||
|
let folder_count = reader.read_i32()?;
|
||||||
|
let is_unlocked = reader.read_bool()?;
|
||||||
|
let date_unlock_ticks = reader.read_i64()?;
|
||||||
|
let username = reader.read_string()?;
|
||||||
|
let beatmaps_count = reader.read_i32()?;
|
||||||
|
|
||||||
|
let mut beatmaps = Vec::new();
|
||||||
|
|
||||||
|
for _ in 0..beatmaps_count {
|
||||||
|
if osuver < 20191107 {
|
||||||
|
reader.read_i32()?; // entry size
|
||||||
|
}
|
||||||
|
|
||||||
|
let artist_name = reader.read_string()?;
|
||||||
|
reader.read_string()?; // artist unicode
|
||||||
|
let song_title = reader.read_string()?;
|
||||||
|
reader.read_string()?; // title unicode
|
||||||
|
reader.read_string()?; // creator
|
||||||
|
let difficulty = reader.read_string()?;
|
||||||
|
reader.read_string()?; // audio
|
||||||
|
let md5 = reader.read_string()?;
|
||||||
|
reader.read_string()?; // osu file name
|
||||||
|
|
||||||
|
reader.read_u8()?; // ranked
|
||||||
|
reader.read_i16()?;
|
||||||
|
reader.read_i16()?;
|
||||||
|
reader.read_i16()?;
|
||||||
|
reader.read_i64()?; // last modification
|
||||||
|
|
||||||
|
if osuver < 20140609 {
|
||||||
|
reader.read_u8()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
} else {
|
||||||
|
reader.read_f32()?;
|
||||||
|
reader.read_f32()?;
|
||||||
|
reader.read_f32()?;
|
||||||
|
reader.read_f32()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.read_f64()?; // slider velocity
|
||||||
|
|
||||||
|
for _ in 0..4 {
|
||||||
|
let len = reader.read_i32()?;
|
||||||
|
for _ in 0..len {
|
||||||
|
reader.read_u8()?;
|
||||||
|
reader.read_i32()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
if osuver > 20250107 {
|
||||||
|
reader.read_f32()?;
|
||||||
|
} else {
|
||||||
|
reader.read_f64()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.read_i32()?; // drain
|
||||||
|
reader.read_i32()?; // total
|
||||||
|
reader.read_i32()?; // preview
|
||||||
|
|
||||||
|
let timing_len = reader.read_i32()?;
|
||||||
|
let mut timing_points = Vec::new();
|
||||||
|
for _ in 0..timing_len {
|
||||||
|
timing_points.push(TimingPoint {
|
||||||
|
bpm: reader.read_f64()?,
|
||||||
|
offset: reader.read_f64()?,
|
||||||
|
inherited: reader.read_bool()?,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let beatmap_id = reader.read_i32()?;
|
||||||
|
let beatmapset_id = reader.read_i32()?;
|
||||||
|
reader.read_i32()?; // thread id
|
||||||
|
|
||||||
|
reader.read_u8()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
|
||||||
|
reader.read_i16()?;
|
||||||
|
reader.read_f32()?;
|
||||||
|
|
||||||
|
let mode = reader.read_u8()?;
|
||||||
|
reader.read_string()?;
|
||||||
|
reader.read_string()?;
|
||||||
|
|
||||||
|
reader.read_i16()?;
|
||||||
|
reader.read_string()?;
|
||||||
|
|
||||||
|
reader.read_bool()?;
|
||||||
|
reader.read_i64()?;
|
||||||
|
reader.read_bool()?;
|
||||||
|
reader.read_string()?;
|
||||||
|
reader.read_i64()?;
|
||||||
|
|
||||||
|
reader.read_bool()?;
|
||||||
|
reader.read_bool()?;
|
||||||
|
reader.read_bool()?;
|
||||||
|
reader.read_bool()?;
|
||||||
|
reader.read_bool()?;
|
||||||
|
|
||||||
|
if osuver < 20140609 {
|
||||||
|
reader.read_i16()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.read_i32()?;
|
||||||
|
reader.read_u8()?;
|
||||||
|
|
||||||
|
beatmaps.push(Beatmap {
|
||||||
|
artist_name,
|
||||||
|
song_title,
|
||||||
|
difficulty,
|
||||||
|
md5,
|
||||||
|
beatmap_id,
|
||||||
|
beatmapset_id,
|
||||||
|
mode,
|
||||||
|
timing_points,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let userperms = reader.read_i32()?;
|
||||||
|
|
||||||
|
Ok(OsuDbData {
|
||||||
|
osuver,
|
||||||
|
folder_count,
|
||||||
|
is_unlocked,
|
||||||
|
date_unlock_ticks,
|
||||||
|
username,
|
||||||
|
beatmaps,
|
||||||
|
userperms,
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in new issue
Block a user