fix: read card id based on cardmng request instead of refid which is serverside implementation dependant

This commit is contained in:
Adamaq01 2023-07-16 08:14:20 +02:00
parent 6ca06aaa82
commit 832fc3e344
5 changed files with 108 additions and 25 deletions

View File

@ -5,11 +5,23 @@ use anyhow::Result;
use log::info; use log::info;
pub fn process_save(save: GameSave) -> Result<()> { pub fn process_save(save: GameSave) -> Result<()> {
let card = save.ref_id; if save.ref_id.is_none() {
if !CONFIGURATION.cards.whitelist.is_empty() && !CONFIGURATION.cards.whitelist.contains(&card) { info!("Guest play, skipping class update");
info!("Card {} is not whitelisted, skipping class update", card);
return Ok(()); return Ok(());
} }
let card = if let Some(card) = helpers::get_current_card_id() {
if !CONFIGURATION.cards.whitelist.is_empty()
&& !CONFIGURATION.cards.whitelist.contains(&card)
{
info!("Card {} is not whitelisted, skipping class update", card);
return Ok(());
}
card
} else {
info!("Card ID is not set, skipping class update");
return Ok(());
};
let import = Import { let import = Import {
meta: Default::default(), meta: Default::default(),

View File

@ -6,11 +6,26 @@ use either::Either;
use log::info; use log::info;
pub fn process_scores(scores: GameScores) -> Result<()> { pub fn process_scores(scores: GameScores) -> Result<()> {
let card = scores.ref_id; if scores.ref_id.is_none() {
if !CONFIGURATION.cards.whitelist.is_empty() && !CONFIGURATION.cards.whitelist.contains(&card) { info!("Guest play, skipping score(s) submission");
info!("Card {} is not whitelisted, skipping score(s)", card);
return Ok(()); return Ok(());
} }
let card = if let Some(card) = helpers::get_current_card_id() {
if !CONFIGURATION.cards.whitelist.is_empty()
&& !CONFIGURATION.cards.whitelist.contains(&card)
{
info!(
"Card {} is not whitelisted, skipping score(s) submission",
card
);
return Ok(());
}
card
} else {
info!("Card ID is not set, skipping score(s) submission");
return Ok(());
};
let tracks = match scores.tracks { let tracks = match scores.tracks {
Either::Left(track) => vec![track], Either::Left(track) => vec![track],

View File

@ -1,7 +1,8 @@
use crate::mikado::CURRENT_CARD_ID;
use crate::sys::{property_node_refer, NodeType}; use crate::sys::{property_node_refer, NodeType};
use crate::CONFIGURATION; use crate::CONFIGURATION;
use anyhow::Result; use anyhow::Result;
use log::debug; use log::{debug, error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
@ -63,6 +64,15 @@ where
Ok(response) Ok(response)
} }
pub fn get_current_card_id() -> Option<String> {
let guard = CURRENT_CARD_ID.read().unwrap_or_else(|err| {
error!("Current card ID RwLock is poisoned: {:#}", err);
err.into_inner()
});
guard.clone()
}
pub fn read_node_str(node: *const (), path: *const u8, length: usize) -> Option<String> { pub fn read_node_str(node: *const (), path: *const u8, length: usize) -> Option<String> {
let mut buffer = [0u8; 32]; let mut buffer = [0u8; 32];
let result = unsafe { let result = unsafe {

View File

@ -1,3 +1,11 @@
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::RwLock;
use anyhow::Result;
use bytes::Bytes;
use kbinxml::{CompressionType, Node, Options, Value};
use log::{debug, error, info, warn};
use crate::handlers::save::process_save; use crate::handlers::save::process_save;
use crate::handlers::scores::process_scores; use crate::handlers::scores::process_scores;
use crate::sys::{ use crate::sys::{
@ -6,13 +14,9 @@ use crate::sys::{
}; };
use crate::types::game::Property; use crate::types::game::Property;
use crate::{helpers, CONFIGURATION, TACHI_STATUS_URL}; use crate::{helpers, CONFIGURATION, TACHI_STATUS_URL};
use anyhow::Result;
use bytes::Bytes;
use kbinxml::{CompressionType, Node, Options, Value};
use log::{debug, error, info, warn};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
static USER: AtomicU64 = AtomicU64::new(0); pub static USER: AtomicU64 = AtomicU64::new(0);
pub static CURRENT_CARD_ID: RwLock<Option<String>> = RwLock::new(None);
pub fn hook_init(ea3_node: *const ()) -> Result<()> { pub fn hook_init(ea3_node: *const ()) -> Result<()> {
if !CONFIGURATION.general.enable { if !CONFIGURATION.general.enable {
@ -217,34 +221,39 @@ pub unsafe fn property_destroy_hook(property: *mut ()) -> i32 {
return 0; return 0;
} }
let game_node = property_search(property, std::ptr::null(), b"/call/game\0".as_ptr()); let node = property_search(property, std::ptr::null(), b"/call/game\0".as_ptr());
if game_node.is_null() { let node = if node.is_null() {
property_search(property, std::ptr::null(), b"/call/cardmng\0".as_ptr())
} else {
node
};
if node.is_null() {
property_clear_error(property); property_clear_error(property);
return call_original!(property); return call_original!(property);
} }
let mut buffer = [0u8; 256]; let mut buffer = [0u8; 256];
let result = property_node_name(game_node, buffer.as_mut_ptr(), buffer.len() as u32); let result = property_node_name(node, buffer.as_mut_ptr(), buffer.len() as u32);
if result < 0 { if result < 0 {
return call_original!(property); return call_original!(property);
} }
let name = { let name = {
let result = std::str::from_utf8(&buffer[0..4]); let result = std::str::from_utf8(&buffer[0..32]);
if let Err(err) = result { if let Err(err) = result {
error!("Could not convert buffer to string: {:#}", err); error!("Could not convert buffer to string: {:#}", err);
return call_original!(property); return call_original!(property);
} }
result.unwrap() result.unwrap().replace('\0', "")
}; };
if name != "game" { if name != "game" && name != "cardmng" {
return call_original!(property); return call_original!(property);
} }
let result = property_node_refer( let result = property_node_refer(
property, property,
game_node, node,
b"method@\0".as_ptr(), b"method@\0".as_ptr(),
NodeType::NodeAttr, NodeType::NodeAttr,
buffer.as_mut_ptr() as *mut (), buffer.as_mut_ptr() as *mut (),
@ -263,7 +272,44 @@ pub unsafe fn property_destroy_hook(property: *mut ()) -> i32 {
result.unwrap().replace('\0', "") result.unwrap().replace('\0', "")
}; };
debug!("Intercepted Game Method: {}", method); debug!("Intercepted '{}' method: {}", name, method);
if name == "cardmng" {
if method != "inquire" {
return call_original!(property);
}
let result = property_node_refer(
property,
node,
b"cardid@\0".as_ptr(),
NodeType::NodeAttr,
buffer.as_mut_ptr() as *mut (),
256,
);
if result < 0 {
return call_original!(property);
}
let cardid = {
let result = std::str::from_utf8(&buffer[..32]);
if let Err(err) = result {
error!("Could not convert buffer to string: {:#}", err);
return call_original!(property);
}
result.unwrap().replace('\0', "")
};
if let Ok(mut guard) = CURRENT_CARD_ID.write() {
debug!("Set current card id to {}", cardid);
*guard = Some(cardid);
} else {
warn!("Could not acquire write lock on current card id");
}
return call_original!(property);
}
if CONFIGURATION.general.inject_cloud_pbs { if CONFIGURATION.general.inject_cloud_pbs {
if method == "sv6_load_m" { if method == "sv6_load_m" {

View File

@ -14,8 +14,8 @@ pub struct CallStruct {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GameScores { pub struct GameScores {
#[serde(rename = "refid")] #[serde(rename = "refid", default)]
pub ref_id: String, pub ref_id: Option<String>,
#[serde(with = "either::serde_untagged", rename = "track")] #[serde(with = "either::serde_untagged", rename = "track")]
pub tracks: Either<Track, Vec<Track>>, pub tracks: Either<Track, Vec<Track>>,
} }
@ -39,7 +39,7 @@ pub struct Track {
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GameSave { pub struct GameSave {
#[serde(rename = "refid")] #[serde(rename = "refid", default)]
pub ref_id: String, pub ref_id: Option<String>,
pub skill_level: u32, pub skill_level: u32,
} }