| 197 | } |
| 198 | |
| 199 | void hook_steamclient_interface( |
| 200 | void* steamclient_handle, |
| 201 | const std::string& steam_client_interface_version |
| 202 | ) noexcept { |
| 203 | try { |
| 204 | // Create a copy for modification |
| 205 | auto virtual_hook_map = get_virtual_hook_map(); |
| 206 | |
| 207 | // Remove steam client map since we don't want to hook its methods |
| 208 | virtual_hook_map.erase(STEAM_CLIENT); |
| 209 | |
| 210 | // Map virtual hook map to a set of keys |
| 211 | const auto prefixes = std::views::keys(virtual_hook_map) | std::ranges::to<std::set>(); |
| 212 | |
| 213 | const auto CreateInterface$ = KB_LIB_GET_FUNC(steamclient_handle, CreateInterface); |
| 214 | |
| 215 | DECLARE_ARGS(); |
| 216 | THIS = CreateInterface$(steam_client_interface_version.c_str(), nullptr); |
| 217 | hook_virtuals(THIS, steam_client_interface_version); |
| 218 | |
| 219 | const auto interface_lookup = read_interface_lookup(); |
| 220 | for(const auto& interface_version : interface_lookup | std::views::keys) { |
| 221 | // SteamUser and SteamPipe handles must match the ones previously used by the game, |
| 222 | // otherwise SteamAPI will just create new instances of interfaces, instead of returning |
| 223 | // existing instances that are used by the game. Usually these handles default to 1, |
| 224 | // but if a game creates several of them, then we need to somehow find them out dynamically. |
| 225 | constexpr auto steam_pipe = 1; |
| 226 | constexpr auto steam_user = 1; |
| 227 | |
| 228 | bool should_hook = false; |
| 229 | for(const auto& prefix : prefixes) { |
| 230 | if(interface_version.starts_with(prefix)) { |
| 231 | should_hook = true; |
| 232 | break; |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | if(not should_hook) { |
| 237 | continue; |
| 238 | } |
| 239 | |
| 240 | ISteamClient_GetISteamGenericInterface( |
| 241 | ARGS(steam_user, steam_pipe, interface_version.c_str()) |
| 242 | ); |
| 243 | |
| 244 | } |
| 245 | } catch(const std::exception& e) { |
| 246 | LOG_ERROR("{} -> Unhandled exception: {}", __func__, e.what()); |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | void* find_function( |
| 251 | const void* instance_ptr, |
no test coverage detected