This commit is contained in:
2025-06-09 22:13:12 +02:00
parent 326b99c464
commit 0aee847089
11 changed files with 583 additions and 389 deletions
+98
View File
@@ -0,0 +1,98 @@
use std::{
ffi::{CStr, c_char},
fs::File,
};
use bincode::{Decode, Encode};
#[derive(Decode, Encode, Clone)]
#[repr(C)]
pub struct PlayerStat {
kills: u32,
deaths: u32,
team_damage: u32,
}
#[derive(Decode, Encode, Clone, Default)]
#[repr(C)]
pub struct ItemStat {
item_name: String,
item_count: u32,
}
#[derive(Decode, Encode, Clone)]
#[repr(C)]
pub struct Player {
player_id: String,
player_stats: PlayerStat,
player_items: [ItemStat; 256],
}
impl Default for Player {
fn default() -> Self {
Self {
player_id: String::new(),
player_stats: PlayerStat {
kills: 0,
deaths: 0,
team_damage: 0,
},
player_items: std::array::from_fn(|_| ItemStat::default()),
}
}
}
#[unsafe(no_mangle)]
/// # Safety
/// `player_id` must be a valid, null-terminated C string pointer.
pub unsafe extern "C" fn get_player_stats(player_id: *const c_char) -> *const Player {
let player_id = unsafe { CStr::from_ptr(player_id) }
.to_string_lossy()
.into_owned();
let db_location = "./stats.data";
let player_stats: Vec<Player> = match File::open(db_location) {
Ok(mut data) => bincode::decode_from_std_read(&mut data, bincode::config::standard())
.unwrap_or_default(),
Err(_) => Vec::new(),
};
player_stats
.iter()
.find(|p| p.player_id == player_id)
.unwrap_or(&Player::default())
}
#[unsafe(no_mangle)]
/// # Safety
/// `player` must be a valid pointer to a `Player` struct.
pub unsafe extern "C" fn save_player_stats(player: *const Player) -> bool {
let player = unsafe { &*player };
let db_location = "./stats.data";
let mut player_stats: Vec<Player> = match File::open(db_location) {
Ok(mut data) => bincode::decode_from_std_read(&mut data, bincode::config::standard())
.unwrap_or_default(),
Err(_) => Vec::new(),
};
// Find and update existing player or add new player
if let Some(existing_player) = player_stats
.iter_mut()
.find(|p| p.player_id == player.player_id)
{
*existing_player = player.clone();
} else {
player_stats.push(player.clone());
}
// Save updated stats
match File::create(db_location) {
Ok(mut file) => {
bincode::encode_into_std_write(&player_stats, &mut file, bincode::config::standard())
.is_ok()
}
Err(_) => false,
}
}