mirror of
https://github.com/beerpiss/saekawa.git
synced 2025-02-21 12:20:16 +01:00
feat: add feature to allow FAILED to take precedence over lamps
I don't know why you would want this, but an ALL JUSTICE showing as FAILED is funny.
This commit is contained in:
parent
70f85e7418
commit
6c3fbe3378
@ -3,6 +3,8 @@
|
|||||||
enable = true
|
enable = true
|
||||||
# Whether the hook should export your class medals and emblems or not.
|
# Whether the hook should export your class medals and emblems or not.
|
||||||
export_class = true
|
export_class = true
|
||||||
|
# Whether FAILED should override FULL COMBO and ALL JUSTICE.
|
||||||
|
fail_over_lamp = false
|
||||||
# Timeout for web requests, in milliseconds
|
# Timeout for web requests, in milliseconds
|
||||||
timeout = 3000
|
timeout = 3000
|
||||||
|
|
||||||
|
@ -28,8 +28,13 @@ impl Configuration {
|
|||||||
pub struct GeneralConfiguration {
|
pub struct GeneralConfiguration {
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
#[serde(default)]
|
|
||||||
|
#[serde(default = "default_true")]
|
||||||
pub export_class: bool,
|
pub export_class: bool,
|
||||||
|
|
||||||
|
#[serde(default = "default_false")]
|
||||||
|
pub fail_over_lamp: bool,
|
||||||
|
|
||||||
#[serde(default = "default_timeout")]
|
#[serde(default = "default_timeout")]
|
||||||
pub timeout: u64,
|
pub timeout: u64,
|
||||||
}
|
}
|
||||||
@ -38,6 +43,10 @@ fn default_true() -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_false() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn default_timeout() -> u64 {
|
fn default_timeout() -> u64 {
|
||||||
3000
|
3000
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use winapi::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
helpers::{call_tachi, read_hinternet_url, read_potentially_deflated_buffer, self},
|
helpers::{call_tachi, read_hinternet_url, read_potentially_deflated_buffer, request_tachi},
|
||||||
types::{
|
types::{
|
||||||
game::UpsertUserAllRequest,
|
game::UpsertUserAllRequest,
|
||||||
tachi::{ClassEmblem, Import, ImportClasses, ImportScore},
|
tachi::{ClassEmblem, Import, ImportClasses, ImportScore},
|
||||||
@ -33,7 +33,7 @@ pub fn hook_init() -> Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let resp: serde_json::Value = helpers::request_tachi("GET", TACHI_STATUS_URL.as_str(), None::<()>)?;
|
let resp: serde_json::Value = request_tachi("GET", TACHI_STATUS_URL.as_str(), None::<()>)?;
|
||||||
let user_id = resp["body"]["whoami"]
|
let user_id = resp["body"]["whoami"]
|
||||||
.as_u64()
|
.as_u64()
|
||||||
.ok_or(anyhow::anyhow!("Couldn't parse user from Tachi response"))?;
|
.ok_or(anyhow::anyhow!("Couldn't parse user from Tachi response"))?;
|
||||||
@ -47,14 +47,13 @@ pub fn hook_init() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
DetourWriteData.initialize(winhttpwritedata, move |a, b, c, d| {
|
DetourWriteData
|
||||||
winhttpwritedata_hook(a, b, c, d)
|
.initialize(winhttpwritedata, winhttpwritedata_hook)?
|
||||||
})?;
|
.enable()?;
|
||||||
|
|
||||||
DetourWriteData.enable()?;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Hook successfully initialized");
|
info!("Hook successfully initialized");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ pub fn hook_release() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn winhttpwritedata_hook(
|
fn winhttpwritedata_hook(
|
||||||
h_request: HINTERNET,
|
h_request: HINTERNET,
|
||||||
lp_buffer: LPCVOID,
|
lp_buffer: LPCVOID,
|
||||||
dw_number_of_bytes_to_write: DWORD,
|
dw_number_of_bytes_to_write: DWORD,
|
||||||
@ -76,12 +75,14 @@ unsafe fn winhttpwritedata_hook(
|
|||||||
) -> BOOL {
|
) -> BOOL {
|
||||||
debug!("hit winhttpwritedata");
|
debug!("hit winhttpwritedata");
|
||||||
|
|
||||||
let orig = || DetourWriteData.call(
|
let orig = || unsafe {
|
||||||
h_request,
|
DetourWriteData.call(
|
||||||
lp_buffer,
|
h_request,
|
||||||
dw_number_of_bytes_to_write,
|
lp_buffer,
|
||||||
lpdw_number_of_bytes_written,
|
dw_number_of_bytes_to_write,
|
||||||
);
|
lpdw_number_of_bytes_written,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let url = match read_hinternet_url(h_request) {
|
let url = match read_hinternet_url(h_request) {
|
||||||
Ok(url) => url,
|
Ok(url) => url,
|
||||||
@ -92,10 +93,12 @@ unsafe fn winhttpwritedata_hook(
|
|||||||
};
|
};
|
||||||
debug!("winhttpwritedata URL: {url}");
|
debug!("winhttpwritedata URL: {url}");
|
||||||
|
|
||||||
let request_body = match read_potentially_deflated_buffer(
|
let request_body = match unsafe {
|
||||||
lp_buffer as *const u8,
|
read_potentially_deflated_buffer(
|
||||||
dw_number_of_bytes_to_write as usize,
|
lp_buffer as *const u8,
|
||||||
) {
|
dw_number_of_bytes_to_write as usize,
|
||||||
|
)
|
||||||
|
} {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("There was an error reading the request body: {:#}", err);
|
error!("There was an error reading the request body: {:#}", err);
|
||||||
@ -141,7 +144,9 @@ unsafe fn winhttpwritedata_hook(
|
|||||||
.user_playlog_list
|
.user_playlog_list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|playlog| {
|
.filter_map(|playlog| {
|
||||||
if let Ok(score) = ImportScore::try_from(playlog) {
|
if let Ok(score) =
|
||||||
|
ImportScore::try_from_playlog(playlog, CONFIGURATION.general.fail_over_lamp)
|
||||||
|
{
|
||||||
if score.difficulty.as_str() == "WORLD'S END" {
|
if score.difficulty.as_str() == "WORLD'S END" {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -157,7 +162,10 @@ unsafe fn winhttpwritedata_hook(
|
|||||||
return orig();
|
return orig();
|
||||||
}
|
}
|
||||||
|
|
||||||
if classes.clone().is_some_and(|v| v.dan.is_none() && v.emblem.is_none()) {
|
if classes
|
||||||
|
.clone()
|
||||||
|
.is_some_and(|v| v.dan.is_none() && v.emblem.is_none())
|
||||||
|
{
|
||||||
return orig();
|
return orig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use anyhow::anyhow;
|
use anyhow::{anyhow, Result};
|
||||||
use chrono::{FixedOffset, NaiveDateTime, TimeZone};
|
use chrono::{FixedOffset, NaiveDateTime, TimeZone};
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -107,11 +107,11 @@ pub struct OptionalMetrics {
|
|||||||
pub max_combo: u32,
|
pub max_combo: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<UserPlaylog> for ImportScore {
|
impl ImportScore {
|
||||||
type Error = anyhow::Error;
|
pub fn try_from_playlog(p: UserPlaylog, fail_over_lamp: bool) -> Result<ImportScore> {
|
||||||
|
let lamp = if !p.is_clear && fail_over_lamp {
|
||||||
fn try_from(p: UserPlaylog) -> Result<ImportScore, Self::Error> {
|
TachiLamp::Failed
|
||||||
let lamp = if p.is_all_justice {
|
} else if p.is_all_justice {
|
||||||
if p.judge_justice + p.judge_attack + p.judge_guilty == 0 {
|
if p.judge_justice + p.judge_attack + p.judge_guilty == 0 {
|
||||||
TachiLamp::AllJusticeCritical
|
TachiLamp::AllJusticeCritical
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user