Skip to content

Commit

Permalink
Rework server list implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
trumank committed Jun 7, 2024
1 parent 3e05bd8 commit bd55be3
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 96 deletions.
78 changes: 6 additions & 72 deletions hook/src/hooks/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![allow(clippy::missing_transmute_annotations)]

mod server_list;

use std::{
ffi::c_void,
path::{Path, PathBuf},
Expand All @@ -20,11 +22,9 @@ use crate::{

retour::static_detour! {
static HookUFunctionBind: unsafe extern "system" fn(*mut ue::UFunction);
static GetServerName: unsafe extern "system" fn(*const c_void, *const c_void) -> *const ue::FString;
static SaveGameToSlot: unsafe extern "system" fn(*const USaveGame, *const ue::FString, i32) -> bool;
static LoadGameFromSlot: unsafe extern "system" fn(*const ue::FString, i32) -> *const USaveGame;
static DoesSaveGameExist: unsafe extern "system" fn(*const ue::FString, i32) -> bool;
static USessionHandlingFSDFillSessionSetting: unsafe extern "system" fn(*const c_void, *mut c_void, bool);
static UObjectTemperatureComponentTimerCallback: unsafe extern "system" fn(*mut c_void);
}

Expand All @@ -49,7 +49,9 @@ pub unsafe fn initialize() -> Result<()> {
exec_print_string as ExecFn,
),
]
.into_iter()
.iter()
.chain(server_list::kismet_hooks().iter())
.cloned()
.collect::<std::collections::HashMap<_, ExecFn>>();

HookUFunctionBind.initialize(
Expand All @@ -75,59 +77,7 @@ pub unsafe fn initialize() -> Result<()> {
)?;
HookUFunctionBind.enable()?;

if let Ok(server_name) = &globals().resolution.server_name {
GetServerName
.initialize(
std::mem::transmute(server_name.get_server_name.0),
get_server_name_detour,
)?
.enable()?;
}

if let Ok(server_mods) = &globals().resolution.server_mods {
let patch_addr = server_mods.semicolon_h_replace.0 as *mut u8;
patch_mem(patch_addr.add(2), [0xC3])?;
patch_mem(patch_addr.add(7), [0x0F, 0x1F, 0x44, 0x00, 0x00])?;
patch_mem(patch_addr.add(102), [0xEB])?;

let mods_fname = server_mods.mods_fname.0;
let set_fstring = server_mods.set_fstring.0;
USessionHandlingFSDFillSessionSetting
.initialize(
std::mem::transmute(server_mods.fill_session_setting.0),
move |world, game_settings, full_server| {
USessionHandlingFSDFillSessionSetting.call(world, game_settings, full_server);

#[derive(serde::Serialize)]
struct Wrapper {
name: String,
version: String,
category: i32,
}

let s = serde_json::to_string(&vec![Wrapper {
name: globals().meta.to_server_list_string(),
version: "mint".into(),
category: 0,
}])
.unwrap();

let s = ue::FString::from(s.as_str());

type Fn = unsafe extern "system" fn(
*const c_void,
*const c_void,
*const ue::FString,
u32,
);

let f: Fn = std::mem::transmute(set_fstring);

f(game_settings, *(mods_fname as *const *const c_void), &s, 3);
},
)?
.enable()?;
}
server_list::init_hooks()?;

if !globals().meta.config.disable_fix_exploding_gas {
if let Ok(gas_fix) = &globals().resolution.gas_fix {
Expand Down Expand Up @@ -322,22 +272,6 @@ fn does_save_game_exist_detour(slot_name: *const ue::FString, user_index: i32) -
}
}

fn get_server_name_detour(a: *const c_void, b: *const c_void) -> *const ue::FString {
unsafe {
let name = GetServerName.call(a, b).cast_mut().as_mut().unwrap();

let mut new_name = widestring::U16String::new();
new_name.push_str("[MODDED] ");
new_name.push_slice(name.as_slice());

name.clear();
name.extend_from_slice(new_name.as_slice());
name.push(0);

name
}
}

unsafe extern "system" fn exec_get_mod_json(
_context: *mut ue::UObject,
stack: *mut ue::kismet::FFrame,
Expand Down
2 changes: 1 addition & 1 deletion hook/src/hooks/server_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn detour_get_server_name(a: *const c_void, b: *const c_void) -> *const ue::FStr
let name = GetServerName.call(a, b).cast_mut().as_mut().unwrap();

let mut new_name = widestring::U16String::new();
new_name.push_slice([0x5b, 0x4d, 0x4f, 0x44, 0x44, 0x45, 0x44, 0x5d, 0x20, 0x0a]);
new_name.push_slice([0x5b, 0x4d, 0x4f, 0x44, 0x44, 0x45, 0x44, 0x5d, 0x20]);
new_name.push_slice(name.as_slice());

name.clear();
Expand Down
27 changes: 8 additions & 19 deletions hook_resolvers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ impl_resolver_singleton!(PEImage, FOnlineSessionSettingsSetFString, |ctx| async
feature = "serde-resolvers",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct USessionHandlingFSDFillSessionSettting(pub usize);
impl_resolver_singleton!(collect, USessionHandlingFSDFillSessionSettting);
pub struct USessionHandlingFSDFillSessionSetttingInner(pub usize);
impl_resolver_singleton!(collect, USessionHandlingFSDFillSessionSetttingInner);
impl_resolver_singleton!(
PEImage,
USessionHandlingFSDFillSessionSettting,
USessionHandlingFSDFillSessionSetttingInner,
|ctx| async {
let patterns = ["48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 50 48 8B B9"];
let patterns = [
"48 89 5C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 81 EC 80 00 00 00 4C 8B FA",
"48 89 5C 24 ?? 4C 89 4C 24 ?? 48 89 4C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 70",
];
let res = join_all(patterns.iter().map(|p| ctx.scan(Pattern::new(p).unwrap()))).await;
Ok(Self(ensure_one(res.into_iter().flatten())?))
}
Expand Down Expand Up @@ -99,19 +102,6 @@ impl_resolver_singleton!(PEImage, ModsFName, |ctx| async {
)?))
});

#[derive(Debug, PartialEq)]
#[cfg_attr(
feature = "serde-resolvers",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct SemicolonHReplace(pub usize);
impl_resolver_singleton!(collect, SemicolonHReplace);
impl_resolver_singleton!(PEImage, SemicolonHReplace, |ctx| async {
let patterns = ["48 8B CB 48 8D 55 E0 E8 ?? ?? ?? ?? 4D 63 FE 48 8B F0 45 8D 77 01 44 89 75 B8 45 3B F4 7E 18 41 8B D7 48 8D 4D B0 E8 ?? ?? ?? ?? 44 8B 65 BC 44 8B 75 B8 4C 8B 6D B0 33 D2 49 8B CF 48 C1 E1 04 49 03 CD 48 89 11 48 8B 06 48 89 01 48 89 16 8B 46 08 89 41 08 8B 46 0C 89 41 0C 48 89 56 08 48 8B 4D E0 48 85 C9 74 05 E8"];
let res = join_all(patterns.iter().map(|p| ctx.scan(Pattern::new(p).unwrap()))).await;
Ok(Self(ensure_one(res.into_iter().flatten())?))
});

#[derive(Debug, PartialEq)]
#[cfg_attr(
feature = "serde-resolvers",
Expand Down Expand Up @@ -164,9 +154,8 @@ impl_try_collector! {
)]
pub struct ServerModsResolution {
pub set_fstring: FOnlineSessionSettingsSetFString,
pub fill_session_setting: USessionHandlingFSDFillSessionSettting,
pub fill_session_setting: USessionHandlingFSDFillSessionSetttingInner,
pub mods_fname: ModsFName,
pub semicolon_h_replace: SemicolonHReplace,
}
}

Expand Down
35 changes: 31 additions & 4 deletions src/integrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1172,20 +1172,47 @@ fn patch_server_list_entry<C: Seek + Read>(asset: &mut Asset<C>) -> Result<(), I
})
.map(|(pi, _)| PackageIndex::from_import(pi as i32).unwrap());

let fsd_target_platform = asset
.imports
.iter()
.enumerate()
.find(|(_, i)| {
i.class_package.get_content(|s| s == "/Script/CoreUObject")
&& i.class_name.get_content(|s| s == "Function")
&& i.object_name.get_content(|s| s == "FSDTargetPlatform")
})
.map(|(pi, _)| PackageIndex::from_import(pi as i32).unwrap());

let ver = AssetVersion::new_from(asset);
let mut statements = extract_tracked_statements(asset, ver, &None);

for (_pi, statements) in statements.iter_mut() {
for (pi, statements) in statements.iter_mut() {
let name = &asset
.asset_data
.get_export(*pi)
.unwrap()
.get_base_export()
.object_name;

let swap_platform = name.get_content(|c| ["GetMissionToolTip", "SetSession"].contains(&c));

for statement in statements {
walk(&mut statement.ex, &|ex| {
if let KismetExpression::ExCallMath(ex) = ex {
if Some(ex.stack_node) == get_mods_installed && ex.parameters.len() == 2 {
ex.parameters[1] = ExFalse {
if let KismetExpression::ExCallMath(cm) = ex {
if Some(cm.stack_node) == get_mods_installed && cm.parameters.len() == 2 {
cm.parameters[1] = ExFalse {
token: EExprToken::ExFalse,
}
.into();
info!("patched server list entry");
}
if swap_platform && Some(cm.stack_node) == fsd_target_platform {
*ex = ExByteConst {
token: EExprToken::ExByteConst,
value: 0,
}
.into();
}
}
});
}
Expand Down

0 comments on commit bd55be3

Please sign in to comment.