use std::fmt;
use crate::types::steam_id::BitVector64;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub enum GameType {
#[default]
App = 0,
GameMod = 1,
Shortcut = 2,
P2P = 3,
}
impl GameType {
pub const fn value(self) -> u32 {
self as u32
}
pub const fn from_raw(raw: u32) -> GameType {
match raw {
1 => GameType::GameMod,
2 => GameType::Shortcut,
3 => GameType::P2P,
_ => GameType::App,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct GameID {
gameid: BitVector64,
}
impl GameID {
pub fn new() -> GameID {
GameID::from_value(0)
}
pub fn from_value(id: u64) -> GameID {
GameID {
gameid: BitVector64::new(id),
}
}
pub fn from_app_id(n_app_id: i32) -> GameID {
GameID::from_value(n_app_id as u64)
}
pub fn from_mod(n_app_id: u32, mod_path: &str) -> GameID {
let mut game_id = GameID::from_value(0);
game_id.set_app_id(n_app_id);
game_id.set_app_type(GameType::GameMod);
game_id.set_mod_id(crc32_of(mod_path.as_bytes()));
game_id
}
pub fn from_shortcut(exe_path: &str, app_name: &str) -> GameID {
let mut combined = String::with_capacity(exe_path.len() + app_name.len());
combined.push_str(exe_path);
combined.push_str(app_name);
let mut game_id = GameID::from_value(0);
game_id.set_app_id(0);
game_id.set_app_type(GameType::Shortcut);
game_id.set_mod_id(crc32_of(combined.as_bytes()));
game_id
}
pub fn set(&mut self, game_id: u64) {
self.gameid.set_data(game_id);
}
pub fn to_u64(&self) -> u64 {
self.gameid.data()
}
pub fn app_id(&self) -> u32 {
self.gameid.get(0, 0xFF_FFFF) as u32
}
pub fn set_app_id(&mut self, value: u32) {
self.gameid.set(0, 0xFF_FFFF, value as u64);
}
pub fn app_type(&self) -> GameType {
GameType::from_raw(self.gameid.get(24, 0xFF) as u32)
}
pub fn set_app_type(&mut self, value: GameType) {
self.gameid.set(24, 0xFF, value.value() as u64);
}
pub fn mod_id(&self) -> u32 {
self.gameid.get(32, 0xFFFF_FFFF) as u32
}
pub fn set_mod_id(&mut self, value: u32) {
self.gameid.set(32, 0xFFFF_FFFF, value as u64);
self.gameid.set(63, 0xFF, 1);
}
pub fn is_mod(&self) -> bool {
self.app_type() == GameType::GameMod
}
pub fn is_shortcut(&self) -> bool {
self.app_type() == GameType::Shortcut
}
pub fn is_p2p_file(&self) -> bool {
self.app_type() == GameType::P2P
}
pub fn is_steam_app(&self) -> bool {
self.app_type() == GameType::App
}
}
impl fmt::Display for GameID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_u64())
}
}
impl fmt::Debug for GameID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl From<GameID> for u64 {
fn from(gid: GameID) -> u64 {
gid.to_u64()
}
}
impl From<u64> for GameID {
fn from(id: u64) -> GameID {
GameID::from_value(id)
}
}
impl From<GameID> for String {
fn from(gid: GameID) -> String {
gid.to_u64().to_string()
}
}
fn crc32_of(data: &[u8]) -> u32 {
crc32fast::hash(data)
}