From 412617ca8cabd62cc7944345d321577cfff4ecb4 Mon Sep 17 00:00:00 2001 From: nukeulater <18323679+nukeulater@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:30:04 +0200 Subject: [PATCH] initial network session refactor * game life cycle updates * fix shell flag, fix map load status reporting regression --- .../discord/discord_interface.cpp | 23 +- xlive/Blam/Engine/game/game.cpp | 10 +- xlive/Blam/Engine/game/game_engine.h | 2 +- xlive/Blam/Engine/game/game_options.h | 2 +- .../screens/screen_squad_settings.cpp | 2 +- .../NetworkMessageTypeCollection.cpp | 70 ++--- .../networking/NetworkMessageTypeCollection.h | 4 +- ...NetworkSession.cpp => network_session.cpp} | 122 +++------ .../{NetworkSession.h => network_session.h} | 244 ++++++++++++------ .../networking/logic/life_cycle_manager.cpp | 64 +++-- .../networking/logic/life_cycle_manager.h | 77 +++--- .../networking/transport/network_channel.h | 4 +- .../networking/transport/network_observer.cpp | 10 +- .../networking/transport/network_observer.h | 14 +- .../render/render_cartographer_ingame_ui.cpp | 16 +- xlive/Blam/Engine/shell/shell.h | 6 +- .../Engine/simulation/simulation_encoding.h | 2 +- xlive/Blam/Engine/sound/sound_manager.h | 2 +- xlive/H2MOD.cpp | 23 +- .../Console/CommandCollection.cpp | 114 ++++---- .../ImGui_NetworkStatsOverlay.cpp | 6 +- .../CustomVariantSettings.cpp | 48 ++-- .../CustomVariantSettings.h | 2 +- xlive/H2MOD/Modules/MapManager/MapManager.cpp | 166 ++++++------ xlive/H2MOD/Variants/GunGame/GunGame.cpp | 2 +- xlive/H2MOD/Variants/Infection/Infection.cpp | 67 +++-- xlive/Project_Cartographer.vcxproj | 4 +- xlive/Project_Cartographer.vcxproj.filters | 4 +- xlive/XLive/XUser/XUserContext.cpp | 2 +- 29 files changed, 596 insertions(+), 516 deletions(-) rename xlive/Blam/Engine/networking/Session/{NetworkSession.cpp => network_session.cpp} (68%) rename xlive/Blam/Engine/networking/Session/{NetworkSession.h => network_session.h} (68%) diff --git a/xlive/Blam/Engine/cartographer/discord/discord_interface.cpp b/xlive/Blam/Engine/cartographer/discord/discord_interface.cpp index 678b76797..6b178333d 100644 --- a/xlive/Blam/Engine/cartographer/discord/discord_interface.cpp +++ b/xlive/Blam/Engine/cartographer/discord/discord_interface.cpp @@ -6,7 +6,7 @@ #include "cseries/cseries_strings.h" #include "main/main_game.h" #include "game/game.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" /* constants */ @@ -232,11 +232,11 @@ void discord_interface_zero_player_count(void) void discord_interface_set_player_counts(void) { - c_network_session* session = nullptr; - if (NetworkSession::GetActiveNetworkSession(&session)) + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { - g_discord_globals.activity.party.size.current_size = session->membership[0].player_count; - g_discord_globals.activity.party.size.max_size = session->parameters[0].max_party_players; + g_discord_globals.activity.party.size.current_size = session->m_session_membership.player_count; + g_discord_globals.activity.party.size.max_size = session->m_session_parameters.max_party_players; } else { @@ -325,17 +325,20 @@ void discord_rich_presence_update(s_discord_data* discord) g_discord_globals.activity.application_id = k_discord_client_id; g_discord_globals.activity.supported_platforms = DiscordActivitySupportedPlatformFlags_Desktop; - c_network_session* network_session = NetworkSession::GetActiveNetworkSession(); - if (network_session && (network_session->session_host_peer_index != NONE && network_session->local_session_state != _network_session_state_peer_leaving)) + c_network_session* network_session = NULL; + if (network_life_cycle_in_squad_session(&network_session) + && (network_session->m_session_host_peer_index != NONE + && network_session->m_local_state != _network_session_state_peer_leaving)) { - bool not_session_host = !NetworkSession::LocalPeerIsSessionHost(); + bool session_host = network_session->is_host(); XSESSION_INFO session; - const int32 observer_index = NetworkSession::GetPeerObserverChannel(network_session->session_host_peer_index)->observer_index; + const int32 observer_index = network_session->get_session_peer(network_session->m_session_host_peer_index)->observer_channel_index; session.sessionID = network_session->session_id; session.keyExchangeKey = network_session->xnkey; - session.hostAddress = (not_session_host ? network_session->p_network_observer->observer_channels[observer_index].xnaddr : network_session->virtual_couch[0].xsession_info.hostAddress); + session.hostAddress = + (session_host ? network_session->m_session_virtual_couch.xsession_info.hostAddress : network_session->m_network_observer->m_observer_channels[observer_index].xnaddr); XUID host; XUserGetXUID(0, &host); diff --git a/xlive/Blam/Engine/game/game.cpp b/xlive/Blam/Engine/game/game.cpp index 14197c494..cea7562da 100644 --- a/xlive/Blam/Engine/game/game.cpp +++ b/xlive/Blam/Engine/game/game.cpp @@ -147,7 +147,7 @@ void game_time_get_date_and_time(s_date_and_time* date_and_time) void game_direct_connect_to_session(XNKID kid, XNKEY key, const XNADDR* addr, int8 exe_type, int32 exe_version, int32 comp_version) { - auto handler = (c_game_life_cycle_handler_joining*)c_game_life_cycle_manager::get()->life_cycle_handlers[e_game_life_cycle::_life_cycle_joining]; + auto handler = (c_game_life_cycle_handler_joining*)c_game_life_cycle_manager::get()->m_life_cycle_handlers[_life_cycle_joining]; handler->joining_xnkid = kid; handler->joining_xnkey = key; handler->joining_xnaddr = *addr; @@ -161,7 +161,7 @@ void game_direct_connect_to_session(XNKID kid, XNKEY key, const XNADDR* addr, in wchar_t local_usernames[k_number_of_users][XUSER_NAME_SIZE] = {}; s_player_identifier local_identifiers[k_number_of_users]; int valid_local_player_count = 0; - for (auto i = 0; i < 4; i++) + for (int32 i = 0; i < k_number_of_users; i++) { s_player_identifier temp_identifier; s_player_properties temp_properties; @@ -173,7 +173,7 @@ void game_direct_connect_to_session(XNKID kid, XNKEY key, const XNADDR* addr, in } } user_interface_networking_reset_player_counts(); - network_session_init_session(2, 1); + network_globals_switch_environment(2, 1); csmemset(&handler->player_identifiers, 0, sizeof(handler->player_identifiers)); csmemcpy(&handler->player_identifiers, local_identifiers, sizeof(s_player_identifier) * valid_local_player_count); csmemcpy(&handler->player_names, local_usernames, sizeof(wchar_t) * 16 * valid_local_player_count); @@ -202,7 +202,7 @@ void __cdecl game_initialize(void) real_math_reset_precision(); s_game_systems* g_game_systems = get_game_systems(); - for (size_t i = 0; i < 70; ++i) + for (int32 i = 0; i < 70; ++i) { g_game_systems[i].initialize_proc(); } @@ -306,7 +306,7 @@ void __cdecl game_initialize_for_new_map(s_game_options* options) game_info_initialize_for_new_map(options); s_game_systems* g_game_systems = get_game_systems(); - for (uint32 i = 0; i < 70; i++) + for (int32 i = 0; i < 70; i++) { if (g_game_systems[i].reset_proc) { diff --git a/xlive/Blam/Engine/game/game_engine.h b/xlive/Blam/Engine/game/game_engine.h index 4efec3073..b105996d2 100644 --- a/xlive/Blam/Engine/game/game_engine.h +++ b/xlive/Blam/Engine/game/game_engine.h @@ -161,7 +161,7 @@ struct s_simulation_player_netdebug_data int16 client_rtt_msec; int16 client_packet_rate; int16 client_throughput; - int16 client_packet_loss; + int16 client_packet_loss_percentage; }; ASSERT_STRUCT_SIZE(s_simulation_player_netdebug_data, 16); diff --git a/xlive/Blam/Engine/game/game_options.h b/xlive/Blam/Engine/game/game_options.h index a550c5afa..20f8bb688 100644 --- a/xlive/Blam/Engine/game/game_options.h +++ b/xlive/Blam/Engine/game/game_options.h @@ -1,5 +1,5 @@ #pragma once -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #include "saved_games/game_variant.h" #include "simulation/machine_id.h" diff --git a/xlive/Blam/Engine/interface/screens/screen_squad_settings.cpp b/xlive/Blam/Engine/interface/screens/screen_squad_settings.cpp index f313b016f..5f5dd9a55 100644 --- a/xlive/Blam/Engine/interface/screens/screen_squad_settings.cpp +++ b/xlive/Blam/Engine/interface/screens/screen_squad_settings.cpp @@ -12,7 +12,7 @@ #include "interface/user_interface_globals.h" #include "main/levels.h" #include "main/level_definitions.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #include "saved_games/game_variant.h" #include "tag_files/global_string_ids.h" #include "tag_files/tag_loader/tag_injection.h" diff --git a/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.cpp b/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.cpp index 3b2f38126..b3f0e22ad 100644 --- a/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.cpp +++ b/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.cpp @@ -146,8 +146,9 @@ void __stdcall handle_channel_message_hook(void* thisx, int network_channel_inde LOG_TRACE_NETWORK(" - network address: {:x}", ntohl(addr.address.ipv4)); int32 peer_index = NetworkSession::GetPeerIndexFromNetworkAddress(&addr); - c_network_session* session = NetworkSession::GetActiveNetworkSession(); - if (peer_index != NONE && !NetworkSession::IsPeerIndexLocal(peer_index)) + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); + if (peer_index != NONE && !session->is_peer_local(peer_index)) { s_custom_map_filename data; ZeroMemory(&data, sizeof(s_custom_map_filename)); @@ -163,10 +164,11 @@ void __stdcall handle_channel_message_hook(void* thisx, int network_channel_inde received_data->player_id, peer_index, map_filename.c_str(), received_data->map_download_id); - c_network_observer* observer = session->p_network_observer; - s_session_observer_channel* observer_channel = NetworkSession::GetPeerObserverChannel(peer_index); + c_network_observer* observer = session->m_network_observer; + s_session_peer* peer = session->get_session_peer(peer_index); - observer->send_message(session->session_index, observer_channel->observer_index, false, _custom_map_filename, sizeof(s_custom_map_filename), &data); + if (peer->is_remote_peer) + observer->send_message(session->m_session_index, peer->observer_channel_index, false, _custom_map_filename, sizeof(s_custom_map_filename), &data); } else { @@ -290,63 +292,67 @@ void __stdcall handle_channel_message_hook(void* thisx, int network_channel_inde void NetworkMessage::SendRequestMapFilename(int mapDownloadId) { - c_network_session* session = NetworkSession::GetActiveNetworkSession(); + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); - if (session->local_session_state == _network_session_state_peer_established) + if (session->established() + && !session->is_host()) { s_request_map_filename data; XUserGetXUID(0, &data.player_id); data.map_download_id = mapDownloadId; - c_network_observer* observer = session->p_network_observer; - s_session_observer_channel* observer_channel = NetworkSession::GetPeerObserverChannel(session->session_host_peer_index); + c_network_observer* observer = session->m_network_observer; + s_session_peer* peer = session->get_session_peer(session->m_session_host_peer_index); - if (observer_channel->field_1) { - observer->send_message(session->session_index, observer_channel->observer_index, false, _request_map_filename, sizeof(s_request_map_filename), &data); + if (peer->is_remote_peer) { + observer->send_message(session->m_session_index, peer->observer_channel_index, false, _request_map_filename, sizeof(s_request_map_filename), &data); - LOG_TRACE_NETWORK("{} session host peer index: {}, observer index {}, observer bool unk: {}, session index: {}", + LOG_TRACE_NETWORK("{} session host peer index: {}, observer index {}, observer is remote peer: {}, session index: {}", __FUNCTION__, - session->session_host_peer_index, - observer_channel->observer_index, - observer_channel->field_1, - session->session_index); + session->m_session_host_peer_index, + peer->observer_channel_index, + peer->is_remote_peer, + session->m_session_index); } } } -void NetworkMessage::SendRankChange(int peerIdx, BYTE rank) +void NetworkMessage::SendRankChange(int peer_index, BYTE rank) { - c_network_session* session = NetworkSession::GetActiveNetworkSession(); - if (NetworkSession::LocalPeerIsSessionHost()) + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); + if (session->is_host()) { s_rank_change data; data.rank = rank; - c_network_observer* observer = session->p_network_observer; - s_session_observer_channel* observer_channel = NetworkSession::GetPeerObserverChannel(peerIdx); + c_network_observer* observer = session->m_network_observer; + s_session_peer* peer = session->get_session_peer(peer_index); - if (peerIdx != NONE && !NetworkSession::IsPeerIndexLocal(peerIdx)) + if (peer_index != NONE && !session->is_peer_local(peer_index)) { - if (observer_channel->field_1) { - observer->send_message(session->session_index, observer_channel->observer_index, false, _rank_change, sizeof(s_rank_change), &data); + if (peer->is_remote_peer) { + observer->send_message(session->m_session_index, peer->observer_channel_index, false, _rank_change, sizeof(s_rank_change), &data); } } } } -void NetworkMessage::SendAntiCheat(int peerIdx) +void NetworkMessage::SendAntiCheat(int peer_index) { - c_network_session* session = NetworkSession::GetActiveNetworkSession(); + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); - if (NetworkSession::LocalPeerIsSessionHost()) + if (session->is_host()) { - c_network_observer* observer = session->p_network_observer; - s_session_observer_channel* observer_channel = NetworkSession::GetPeerObserverChannel(peerIdx); + c_network_observer* observer = session->m_network_observer; + s_session_peer* peer = session->get_session_peer(peer_index); s_anti_cheat data; data.enabled = g_twizzler_status; - if (peerIdx != NONE && !NetworkSession::IsPeerIndexLocal(peerIdx)) { - if (observer_channel->field_1) { - observer->send_message(session->session_index, observer_channel->observer_index, false, _anti_cheat, sizeof(s_anti_cheat), &data); + if (peer_index != NONE && !session->is_peer_local(peer_index)) { + if (peer->is_remote_peer) { + observer->send_message(session->m_session_index, peer->observer_channel_index, false, _anti_cheat, sizeof(s_anti_cheat), &data); } } } diff --git a/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.h b/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.h index 5ec74b0f6..d4a9b050b 100644 --- a/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.h +++ b/xlive/Blam/Engine/networking/NetworkMessageTypeCollection.h @@ -177,6 +177,6 @@ namespace NetworkMessage { void ApplyGamePatches(); void SendRequestMapFilename(int mapDownloadId); - void SendRankChange(int peerIdx, BYTE rank); - void SendAntiCheat(int peerIdx); + void SendRankChange(int peer_index, BYTE rank); + void SendAntiCheat(int peer_index); } \ No newline at end of file diff --git a/xlive/Blam/Engine/networking/Session/NetworkSession.cpp b/xlive/Blam/Engine/networking/Session/network_session.cpp similarity index 68% rename from xlive/Blam/Engine/networking/Session/NetworkSession.cpp rename to xlive/Blam/Engine/networking/Session/network_session.cpp index 7f77ab7a9..87c4ff387 100644 --- a/xlive/Blam/Engine/networking/Session/NetworkSession.cpp +++ b/xlive/Blam/Engine/networking/Session/network_session.cpp @@ -1,16 +1,24 @@ #include "stdafx.h" -#include "NetworkSession.h" +#include "network_session.h" #include "game/game.h" #include "networking/logic/life_cycle_manager.h" #include "interface/user_interface_controller.h" -// ### TODO Cleanup +/* public code */ + +/* PRIVATE NAMESPACE, acts like static keyword */ +// +namespace NetworkSession +{ + c_network_session* GetNetworkSessions(); + c_network_session* GetActiveNetworkSession(); +} bool NetworkSession::PlayerIsActive(datum player_index) { - return GetActiveNetworkSession()->session_player_active(player_index); + return GetActiveNetworkSession()->is_session_player_active(player_index); } std::vector NetworkSession::GetActivePlayerIdList() @@ -53,38 +61,24 @@ c_network_session* NetworkSession::GetNetworkSessions() c_network_session* NetworkSession::GetActiveNetworkSession() { - return *Memory::GetAddress(0x420FE8, 0x3C40D0); -} - -bool NetworkSession::GetActiveNetworkSession(c_network_session** outSession) -{ - typedef bool(__cdecl* get_lobby_globals_t)(c_network_session**); - return Memory::GetAddress(0x1AD736, 0x1A66B3)(outSession); -} - -e_network_session_state NetworkSession::GetLocalSessionState() -{ - return GetActiveNetworkSession()->local_session_state; + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); + return session; } bool NetworkSession::LocalPeerIsSessionHost() { - return GetActiveNetworkSession()->local_state_session_host(); -} - -bool NetworkSession::LocalPeerIsEstablishedClient() -{ - return GetActiveNetworkSession()->local_state_established_client(); + return GetActiveNetworkSession()->is_host(); } bool NetworkSession::LocalPeerIsSessionLeader() { - return GetActiveNetworkSession()->local_peer_session_leader(); + return GetActiveNetworkSession()->is_local_peer_session_leader(); } bool NetworkSession::LocalPeerIsEstablished() { - return GetActiveNetworkSession()->local_state_established(); + return GetActiveNetworkSession()->established(); } // returns NONE (-1) if fails @@ -103,7 +97,7 @@ bool NetworkSession::GetMapFileLocation(wchar_t* buffer, size_t size) int32 NetworkSession::GetPeerCount() { - return GetActiveNetworkSession()->membership[0].peer_count; + return GetActiveNetworkSession()->m_session_membership.peer_count; } int32 NetworkSession::GetLocalPeerIndex() @@ -111,19 +105,9 @@ int32 NetworkSession::GetLocalPeerIndex() return GetActiveNetworkSession()->get_local_peer_index(); } -bool NetworkSession::IsPeerIndexLocal(int32 peer_index) -{ - return GetLocalPeerIndex() == peer_index; -} - -bool NetworkSession::IsPlayerLocal(datum player_index) -{ - return IsPeerIndexLocal(GetPeerIndex(player_index)); -} - IN_ADDR NetworkSession::GetLocalNetworkAddress() { - return GetActiveNetworkSession()->membership[0].peers[GetLocalPeerIndex()].secure_address.inaOnline; + return GetActiveNetworkSession()->m_session_membership.membership_peers[GetLocalPeerIndex()].secure_address.inaOnline; } int32 NetworkSession::GetPeerIndex(datum player_index) @@ -133,12 +117,12 @@ int32 NetworkSession::GetPeerIndex(datum player_index) int32 NetworkSession::GetPlayerCount() { - return GetActiveNetworkSession()->membership[0].player_count; + return GetActiveNetworkSession()->m_session_membership.player_count; } s_membership_player* NetworkSession::GetPlayerInformation(datum player_index) { - return &GetActiveNetworkSession()->membership[0].players[DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index)]; + return &GetActiveNetworkSession()->m_session_membership.players[DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index)]; } const wchar_t* NetworkSession::GetPlayerName(datum player_index) @@ -186,19 +170,14 @@ void NetworkSession::EndGame() INVOKE(0x215470, 0x197F32, NetworkSession::EndGame); } -s_session_observer_channel* NetworkSession::GetPeerObserverChannel(int32 peer_index) -{ - return &GetActiveNetworkSession()->observer_channels[peer_index]; -} - wchar_t* NetworkSession::GetGameVariantName() { - return GetActiveNetworkSession()->parameters[0].game_variant.variant_name; + return GetActiveNetworkSession()->m_session_parameters.game_variant.variant_name; } bool NetworkSession::IsVariantTeamPlay() { - return TEST_BIT(GetActiveNetworkSession()->parameters[0].game_variant.flags, _game_engine_teams_bit); + return TEST_BIT(GetActiveNetworkSession()->m_session_parameters.game_variant.flags, _game_engine_teams_bit); } void NetworkSession::LeaveSession() @@ -221,11 +200,6 @@ void NetworkSession::LeaveSession() p_leave_session(0); } -s_membership_peer* network_session_get_peer(int32 peer_index) -{ - return NetworkSession::GetActiveNetworkSession()->get_peer_membership(peer_index); -} - s_session_interface_globals* s_session_interface_globals::get() { return Memory::GetAddress(0x51A590, 0x520408); @@ -241,12 +215,12 @@ e_network_session_class network_squad_session_get_session_class() //return INVOKE(0x1B1643, 0x0, network_squad_session_get_session_class); e_network_session_class out_class = _network_session_class_unknown; - c_network_session* active_session; - if (network_life_cycle_in_squad_session(&active_session)) + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { - if (active_session->local_state_established()) + if (session->established()) { - out_class = active_session->m_session_class; + out_class = session->m_session_class; } } return out_class; @@ -291,9 +265,9 @@ bool __cdecl network_session_interface_get_local_user_properties(int32 user_inde return INVOKE(0x1B10E0, 0x1970A8, network_session_interface_get_local_user_properties, user_index, out_controller_index, out_properties, out_player_voice, out_player_text_chat); } -void __cdecl network_session_init_session(int32 a1, char a2) +void __cdecl network_globals_switch_environment(int32 a1, bool a2) { - INVOKE(0x1B54CF, 0x1A922D, network_session_init_session, a1, a2); + INVOKE(0x1B54CF, 0x1A922D, network_globals_switch_environment, a1, a2); } void network_session_apply_patches() @@ -302,19 +276,19 @@ void network_session_apply_patches() void network_session_membership_update_local_players_teams() { - c_network_session* active_session; - if (network_life_cycle_in_squad_session(&active_session)) + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { - if (active_session->local_state_established() || active_session->local_state_joining_session()) + if (session->established() || session->local_state_joining_session()) { - int32 local_peer_index = active_session->get_local_peer_index(); + int32 local_peer_index = session->get_local_peer_index(); for (int32 i = 0; i < k_number_of_users; i++) { - datum player_index = active_session->get_peer_membership(local_peer_index)->local_players_indexes[i]; + datum player_index = session->get_peer_membership(local_peer_index)->local_players_indexes[i]; if (player_index != NONE) { - const s_membership_player* membership_player = active_session->get_player_membership(player_index); + const s_membership_player* membership_player = session->get_player_membership(player_index); user_interface_controller_set_desired_team_index((e_controller_index)i, (e_game_team)membership_player->properties[0].team_index); user_interface_controller_update_network_properties((e_controller_index)i); } @@ -325,16 +299,16 @@ void network_session_membership_update_local_players_teams() void network_session_set_player_team(datum player_index, e_game_team team) { - c_network_session* active_session; - if (network_life_cycle_in_squad_session(&active_session)) + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { - if (active_session->local_state_established() - && active_session->local_state_session_host()) + if (session->established() + && session->is_host()) { - s_membership_player* membership_player = active_session->get_player_membership(player_index); + s_membership_player* membership_player = session->get_player_membership(player_index); membership_player->properties[0].team_index = team; - if (active_session->peer_index_local_peer(membership_player->peer_index)) + if (session->peer_index_local_peer(membership_player->peer_index)) { user_interface_controller_set_desired_team_index((e_controller_index)membership_player->controller_index, (e_game_team)membership_player->properties[0].team_index); user_interface_controller_update_network_properties((e_controller_index)membership_player->controller_index); @@ -343,21 +317,9 @@ void network_session_set_player_team(datum player_index, e_game_team team) } } -bool network_life_cycle_in_squad_session(c_network_session** out_active_session) -{ - if (!c_game_life_cycle_manager::game_life_cycle_initialized() - || NetworkSession::GetActiveNetworkSession()->local_state_none()) - return false; - - if (out_active_session != NULL) - *out_active_session = NetworkSession::GetActiveNetworkSession(); - - return true; -} - void c_network_session::switch_players_to_teams(datum* player_indexes, int32 player_count, e_game_team* team_indexes) { - if (local_state_session_host()) + if (is_host()) { for (int32 i = 0; i < player_count; i++) { diff --git a/xlive/Blam/Engine/networking/Session/NetworkSession.h b/xlive/Blam/Engine/networking/Session/network_session.h similarity index 68% rename from xlive/Blam/Engine/networking/Session/NetworkSession.h rename to xlive/Blam/Engine/networking/Session/network_session.h index 7e22a2625..fc8f1e70b 100644 --- a/xlive/Blam/Engine/networking/Session/NetworkSession.h +++ b/xlive/Blam/Engine/networking/Session/network_session.h @@ -6,7 +6,7 @@ #include "networking/Transport/network_observer.h" #include "saved_games/game_variant.h" -// ### TODO Cleanup +/* enums */ enum e_network_session_map_status : int32 { @@ -47,43 +47,53 @@ enum e_network_session_class k_network_session_class_count = 0x3, }; +enum e_network_session_mode +{ + _network_session_mode_none = 0, + _network_session_mode_idle = 1, + _network_session_mode_in_game = 4, + _network_session_mode_migration_start = 6, + _network_session_mode_migration_joining = 7, + _network_session_mode_migration_disbanding = 9, + + k_network_session_mode_count = 10 +}; + +/* constants */ + +#define k_network_maximum_sessions 2 +#define k_network_maximum_machines_per_session (k_maximum_players + 1) + +/* forward declarations */ + +class c_network_session; -// forward declarations -struct c_network_session; struct s_session_membership; struct s_membership_player; struct s_membership_peer; -struct s_session_observer_channel; - -#define k_network_maximum_machines_per_session (k_maximum_players + 1) +struct s_session_peer; +// THE FOLLOWING FUNCTIONS ARE NOW DEPRECATED, AND WILL BE REMOVED EVENTUALLY +// WHEN PORTING IS FINISHED +// USE/IMPLEMENT THE HELPER FUNCTIONS IN THE c_network_session CLASS !!!!!! namespace NetworkSession { - // network session getters and misc - c_network_session* GetNetworkSessions(); - c_network_session* GetActiveNetworkSession(); - bool GetActiveNetworkSession(c_network_session** outSession); - e_network_session_state GetLocalSessionState(); int32 GetPeerIndexFromNetworkAddress(const network_address* address); bool GetMapFileLocation(wchar_t* buffer, size_t size); bool LocalPeerIsSessionHost(); - bool LocalPeerIsEstablishedClient(); bool LocalPeerIsSessionLeader(); bool LocalPeerIsEstablished(); // peer functions int32 GetPeerCount(); int32 GetLocalPeerIndex(); - bool IsPeerIndexLocal(int32 peer_index); IN_ADDR GetLocalNetworkAddress(); void KickPeer(int32 peer_index); void EndGame(); - s_session_observer_channel* GetPeerObserverChannel(int32 peer_index); // peer-player functions int32 GetPeerIndex(datum player_index); - bool IsPlayerLocal(datum player_index); // player functions @@ -107,22 +117,21 @@ namespace NetworkSession void LeaveSession(); } -s_membership_peer* network_session_get_peer(int32 peer_index); - #pragma pack(push, 1) -struct s_session_observer_channel +struct s_session_peer { - bool field_0; - bool field_1; - char pad[2]; - int32 observer_index; + bool peer_valid; + bool is_remote_peer; + bool peer_needs_reestablishment; + uint8 gap_3; + int32 observer_channel_index; int32 membership_update_number; int32 parameters_update_number; int32 virtual_couch_update_number; int32 vote_update_number; int32 field_18; }; -ASSERT_STRUCT_SIZE(s_session_observer_channel, 28); +ASSERT_STRUCT_SIZE(s_session_peer, 28); struct s_session_virtual_couch { @@ -232,7 +241,7 @@ struct s_session_membership uint64 dedicated_server_xuid; // 0x78 int32 xbox_session_leader_peer_index; // 0x80 int32 peer_count; // 0x84 - s_membership_peer peers[k_network_maximum_machines_per_session]; // 0x88 + s_membership_peer membership_peers[k_network_maximum_machines_per_session]; // 0x88 int32 player_count; // 0x1254 uint32 players_active_mask; // 0x1258 s_membership_player players[k_maximum_players]; // 0x125C @@ -240,7 +249,6 @@ struct s_session_membership }; ASSERT_STRUCT_SIZE(s_session_membership, 9328); - struct s_session_interface_user { bool user_exists; @@ -261,13 +269,13 @@ struct s_session_interface_globals { bool initialised; uint8 gap_1; - wchar_t m_machine_name[16]; - wchar_t m_session_name[32]; - uint8 m_qos_active; + wchar_t machine_name[16]; + wchar_t session_name[32]; + uint8 qos_active; uint8 gap_63; uint8 gap_64[16]; - uint32 m_upstream_bandwidth_bps; - uint32 m_downstream_bandwidth_bps; + uint32 upstream_bandwidth_bps; + uint32 downstream_bandwidth_bps; uint8 gap_7C[8]; uint32 nat_type; uint32 field_88; @@ -284,15 +292,18 @@ struct s_session_interface_globals }; ASSERT_STRUCT_SIZE(s_session_interface_globals, 0x638); -struct c_network_session +/* classes */ + +class c_network_session { +public: void* vtbl; - void* p_network_message_gateway; - c_network_observer* p_network_observer; - void* session_manager_ptr; - uint32 text_chat; - int32 session_index; - int32 field_18; + void* m_network_message_gateway; + c_network_observer* m_network_observer; + void* m_session_manager; + uint32 field_10; + int32 m_session_index; + int32 m_session_type; e_network_session_class m_session_class; XNKID session_id; wchar_t field_28[16]; @@ -301,20 +312,29 @@ struct c_network_session char pad[3]; int32 xnkey_index; int32 field_60; - int32 session_host_peer_index; - int32 elected_host_peer_index; + int32 m_session_host_peer_index; + int32 m_elected_host_peer_index; uint32 field_6C; - s_session_membership membership[2]; // 0x70 - s_session_virtual_couch virtual_couch[2]; - s_session_vote voting_data[2]; // unused + + s_session_membership m_session_membership; + s_session_membership m_session_transmitted_membership; + s_session_virtual_couch m_session_virtual_couch; + s_session_virtual_couch m_session_transmitted_virtual_couch; + + /* unused and unfinished leftover voting system */ + s_session_vote m_session_voting_data; + s_session_vote m_session_transmitted_voting_data; + uint8 gap_4B84[64]; - s_session_parameters parameters[2]; - int32 local_peer_index; - s_session_observer_channel observer_channels[k_network_maximum_machines_per_session]; - e_network_session_state local_session_state; - uint32 time_unk_2; - uint32 time_unk_3; - uint32 time_unk; + s_session_parameters m_session_parameters; + s_session_parameters m_session_transmitted_parameters; + + int32 m_local_peer_index; + s_session_peer m_session_peers[k_network_maximum_machines_per_session]; + e_network_session_state m_local_state; + uint32 field_73A4; + uint32 field_73A8; + uint32 field_73AC; uint32 possible_new_peer_host_index; uint32 field_73B4; uint32 field_73B8; @@ -371,22 +391,47 @@ struct c_network_session s_membership_peer* get_peer_membership(int32 peer_index) { - return &membership[0].peers[peer_index]; + return &m_session_membership.membership_peers[peer_index]; } s_membership_player* get_player_membership(datum player_index) { - return &membership[0].players[DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index)]; + return &m_session_membership.players[DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index)]; + } + + s_session_peer* get_session_peer(int32 peer_index) + { + return &m_session_peers[peer_index]; + } + + int32 get_peer_count() const + { + return m_session_membership.peer_count; + } + + int32 get_player_count() const + { + return m_session_membership.player_count; + } + + const wchar_t* get_player_name(datum player_index) + { + return get_player_membership(player_index)->properties[0].player_name; } int32 get_local_peer_index() const { - return local_peer_index; + return m_local_peer_index; + } + + const wchar_t* get_game_variant_name() const + { + return m_session_parameters.game_variant.variant_name; } int32 get_session_host_peer_index() const { - return session_host_peer_index; + return m_session_host_peer_index; } bool peer_index_local_peer(int32 peer_index) const @@ -394,35 +439,67 @@ struct c_network_session return get_local_peer_index() == peer_index; } - bool local_state_none() const + bool disconnected() const { - return local_session_state == _network_session_state_none; + return m_local_state == _network_session_state_none; } - bool local_state_established_client() const + bool leaving() const { - return local_session_state == _network_session_state_peer_established - || local_session_state == _network_session_state_peer_leaving; + bool result = false; + + switch (m_local_state) + { + case _network_session_state_peer_join_abort: + case _network_session_state_peer_leaving: + case _network_session_state_host_disband: + result = true; + break; + case _network_session_state_host_handoff: + case _network_session_state_host_reestablish: + result = field_73A4; + break; + default: + break; + } + + return result; } - bool local_state_session_host() const + bool is_client() const { - return local_session_state == _network_session_state_host_established - || local_session_state == _network_session_state_host_disband - || local_session_state == _network_session_state_host_handoff - || local_session_state == _network_session_state_host_reestablish; + return m_local_state == _network_session_state_peer_established + || m_local_state == _network_session_state_peer_leaving; + } + + bool is_host() const + { + return m_local_state == _network_session_state_host_established + || m_local_state == _network_session_state_host_disband + || m_local_state == _network_session_state_host_handoff + || m_local_state == _network_session_state_host_reestablish; + } + + bool is_peer_local(int32 peer_index) const + { + return get_local_peer_index() == peer_index; + } + + bool is_peer_session_host(int32 peer_index) const + { + return get_session_host_peer_index() == peer_index; } bool local_state_joining_session() const { - return local_session_state == _network_session_state_peer_joining; + return m_local_state == _network_session_state_peer_joining; } - bool local_state_established() const + bool established() const { bool result = false; - switch (local_session_state) + switch (m_local_state) { case _network_session_state_none: case _network_session_state_peer_joining: @@ -440,19 +517,23 @@ struct c_network_session case _network_session_state_host_reestablish: result = true; break; + + default: + DISPLAY_ASSERT("unreachable"); + break; } return result; } - bool local_peer_session_leader() const + bool is_local_peer_session_leader() const { - return membership[0].session_leader_peer_index == local_peer_index; + return m_session_membership.session_leader_peer_index == m_local_peer_index; } - bool session_player_active(datum player_index) const + bool is_session_player_active(datum player_index) const { - return TEST_BIT(membership[0].players_active_mask, DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index)); + return TEST_BIT(m_session_membership.players_active_mask, DATUM_INDEX_TO_ABSOLUTE_INDEX(player_index)); } int32 get_peer_index_from_address(const network_address* address) @@ -462,13 +543,18 @@ struct c_network_session void request_membership_update() { - this->membership[0].update_number++; + this->m_session_membership.update_number++; this->local_membership_update_number++; } + int32 session_mode() const + { + return m_session_parameters.session_mode; + } + void switch_player_team(datum player_index, e_game_team team_index) { - if (local_state_session_host()) + if (is_host()) { get_player_membership(player_index)->properties[0].team_index = team_index; request_membership_update(); @@ -480,27 +566,27 @@ struct c_network_session const char* describe_network_protocol_type() const { - static const char* network_protocols_str[] = + static const char* const k_network_protocols_text[] = { "", "System-Link", "LIVE", }; - return IN_RANGE(this->m_session_class, _network_session_class_offline, k_network_session_class_count - 1) ? network_protocols_str[this->m_session_class] : ""; + return IN_RANGE(this->m_session_class, _network_session_class_offline, k_network_session_class_count - 1) ? k_network_protocols_text[this->m_session_class] : ""; } }; ASSERT_STRUCT_SIZE(c_network_session, 31624); -ASSERT_STRUCT_OFFSET(c_network_session, membership[0], 0x70); -ASSERT_STRUCT_OFFSET(c_network_session, parameters[0], 0x4C60); +ASSERT_STRUCT_OFFSET(c_network_session, m_session_membership, 0x70); +ASSERT_STRUCT_OFFSET(c_network_session, m_session_parameters, 0x4C60); #pragma pack(pop) +/* prototypes */ + s_session_interface_user* session_interface_get_local_user_properties(int32 user_index); void network_session_apply_patches(); -bool network_life_cycle_in_squad_session(c_network_session** out_active_session); - void network_session_membership_update_local_players_teams(); e_network_session_class network_squad_session_get_session_class(); @@ -508,4 +594,4 @@ bool network_session_interface_set_local_user_character_type(int32 user_index, e bool network_session_interface_get_local_user_identifier(int32 user_index, s_player_identifier* out_identifier); void network_session_interface_set_local_user_rank(int32 user_index, int8 rank); bool __cdecl network_session_interface_get_local_user_properties(int32 user_index, int32* out_controller_index, s_player_properties* out_properties, int32* out_player_voice, int32* out_player_text_chat); -void __cdecl network_session_init_session(int32 a1, char a2); \ No newline at end of file +void __cdecl network_globals_switch_environment(int32 a1, bool a2); \ No newline at end of file diff --git a/xlive/Blam/Engine/networking/logic/life_cycle_manager.cpp b/xlive/Blam/Engine/networking/logic/life_cycle_manager.cpp index b75e8898a..144cd7ae7 100644 --- a/xlive/Blam/Engine/networking/logic/life_cycle_manager.cpp +++ b/xlive/Blam/Engine/networking/logic/life_cycle_manager.cpp @@ -1,24 +1,43 @@ #include "stdafx.h" #include "life_cycle_manager.h" +#define g_game_life_cycle_handler c_game_life_cycle_handler::get() +bool game_life_cycle_initialized() +{ + return *Memory::GetAddress(0x420FC0, 0x3C40A8); +} e_game_life_cycle __cdecl get_game_life_cycle() { c_game_life_cycle_manager* life_cycle_manager = c_game_life_cycle_manager::get(); - if (life_cycle_manager->initialized) - return life_cycle_manager->life_cycle_state; + if (game_life_cycle_initialized()) + return life_cycle_manager->m_state; return _life_cycle_none; } -void c_game_life_cycle_handler::initialize(void* life_cycle_manager, e_game_life_cycle life_cycle, bool a3) +bool network_life_cycle_in_squad_session(c_network_session** out_active_session) +{ + c_game_life_cycle_manager* life_cycle_manager = c_game_life_cycle_manager::get(); + + if (!game_life_cycle_initialized() + || life_cycle_manager->m_active_squad_session->disconnected()) + return false; + + if (out_active_session != NULL) + *out_active_session = life_cycle_manager->m_active_squad_session; + + return true; +} + +void c_game_life_cycle_handler::initialize(c_game_life_cycle_manager* life_cycle_manager, e_game_life_cycle life_cycle, bool a3) { this->life_cycle_manager = life_cycle_manager; this->life_cycle = life_cycle; this->field_C = a3; - static_cast(this->life_cycle_manager)->life_cycle_handlers[this->life_cycle] = this; + this->life_cycle_manager->m_life_cycle_handlers[this->life_cycle] = this; } void __cdecl c_game_life_cycle_handler_joining::check_joining_capability() @@ -29,18 +48,16 @@ void __cdecl c_game_life_cycle_handler_joining::check_joining_capability() bool c_game_life_cycle_manager::get_active_session(c_network_session** out_session) { - c_network_session* active_session = NetworkSession::GetActiveNetworkSession(); - bool result = false; *out_session = NULL; c_game_life_cycle_manager* life_cycle_manager = get(); - if (life_cycle_manager->initialized - && IN_RANGE(life_cycle_manager->life_cycle_state, _life_cycle_pre_game, _life_cycle_joining) - && !active_session->local_state_none() + if (game_life_cycle_initialized() + && IN_RANGE(life_cycle_manager->m_state, _life_cycle_pre_game, _life_cycle_joining) + && !m_active_squad_session->disconnected() ) { - *out_session = active_session; + *out_session = m_active_squad_session; result = true; } @@ -49,12 +66,7 @@ bool c_game_life_cycle_manager::get_active_session(c_network_session** out_sessi c_game_life_cycle_manager* c_game_life_cycle_manager::get() { - return Memory::GetAddress(0x420FC0, 0x3C40A8); -} - -bool c_game_life_cycle_manager::game_life_cycle_initialized() -{ - return c_game_life_cycle_manager::get()->initialized; + return Memory::GetAddress(0x420FC4, 0x3C40AC); } e_game_life_cycle c_game_life_cycle_manager::get_life_cycle() const @@ -62,7 +74,7 @@ e_game_life_cycle c_game_life_cycle_manager::get_life_cycle() const e_game_life_cycle result = _life_cycle_none; if (game_life_cycle_initialized()) { - result = life_cycle_state; + result = m_state; } return result; } @@ -71,7 +83,7 @@ bool c_game_life_cycle_manager::state_is_joining() const { if (!game_life_cycle_initialized()) return false; - if (life_cycle_state == _life_cycle_joining) + if (m_state == _life_cycle_joining) return true; return false; @@ -81,20 +93,20 @@ bool c_game_life_cycle_manager::state_is_in_game(void) const { if (!game_life_cycle_initialized()) return false; - if (life_cycle_state == _life_cycle_in_game) + if (m_state == _life_cycle_in_game) return true; return false; } -void c_game_life_cycle_manager::request_state_change(e_game_life_cycle requested_state, int a3, void* a4) +void c_game_life_cycle_manager::request_state_change(e_game_life_cycle requested_state, int entry_data_size, void* entry_data) { - this->requested_life_cycle = requested_state; - this->update_requested = true; - this->field_3C = a3; - this->field_40 = 0; - if (this->field_3C > 0) + this->m_requested_life_cycle = requested_state; + this->m_update_requested = true; + this->m_entry_data_size = entry_data_size; + csmemset(m_entry_data, 0, sizeof(m_entry_data)); + if (m_entry_data > 0) { - memcpy(&field_40, a4, field_3C); + csmemcpy(&m_entry_data, entry_data, this->m_entry_data_size); } } diff --git a/xlive/Blam/Engine/networking/logic/life_cycle_manager.h b/xlive/Blam/Engine/networking/logic/life_cycle_manager.h index d8e1e1a14..437386fe2 100644 --- a/xlive/Blam/Engine/networking/logic/life_cycle_manager.h +++ b/xlive/Blam/Engine/networking/logic/life_cycle_manager.h @@ -1,5 +1,7 @@ #pragma once -#include "networking/Session/NetworkSession.h" + +#include "networking/session/network_session.h" +#include "networking/transport/network_observer.h" enum e_game_life_cycle : int32 { @@ -18,6 +20,7 @@ typedef bool (*life_cycle_update)(void* life_cycle_handler); typedef void (*life_cycle_initialize)(void* life_cycle_handler_requested, void* life_cycle_handler_current, int32 unk_1, void* unk_2); typedef void (*life_cycle_dispose)(void* life_cycle_handler_current, void* life_cycle_handler_requested); +class c_game_life_cycle_manager; class c_game_life_cycle_handler_functions { @@ -32,9 +35,9 @@ class c_game_life_cycle_handler public: c_game_life_cycle_handler_functions* functions; e_game_life_cycle life_cycle; - void* life_cycle_manager; + c_game_life_cycle_manager* life_cycle_manager; bool field_C; - void initialize(void* life_cycle_manager, e_game_life_cycle life_cycle, bool a3); + void initialize(c_game_life_cycle_manager* life_cycle_manager, e_game_life_cycle life_cycle, bool a3); }; struct c_game_life_cycle_handler_none : c_game_life_cycle_handler @@ -118,48 +121,52 @@ ASSERT_STRUCT_SIZE(c_game_life_cycle_handler_match_making, 0x18); class c_game_life_cycle_manager { public: - bool initialized; - e_game_life_cycle life_cycle_state; - c_game_life_cycle_handler* life_cycle_handlers[e_game_life_cycle::k_life_cycle_count]; - void* network_session_manager; - c_network_session* network_session; - void* text_chat_manager_maybe; - void* network_message_gateway; - void* network_observer; - bool life_cycle_changing; - bool life_cycle_updating; - bool update_requested; - e_game_life_cycle requested_life_cycle; - int32 field_3C; - void* field_40; + e_game_life_cycle m_state; + c_game_life_cycle_handler* m_life_cycle_handlers[k_life_cycle_count]; + void* m_network_session_manager; + c_network_session* m_active_squad_session; + c_network_session* m_secondary_squad_session; + void* m_network_message_gateway; + c_network_observer* m_network_observer; + bool m_state_change_active; + bool m_update_active; + bool m_update_requested; + + e_game_life_cycle m_requested_life_cycle; + int32 m_entry_data_size; + uint8 m_entry_data[4]; + c_game_life_cycle_manager( void* network_message_gateway, - void* network_observer, + c_network_observer* network_observer, void* network_session_manager, - c_network_session* network_session, - void* text_chat_manager_maybe) + c_network_session* squad_session_one, + c_network_session* squad_session_two) { - this->life_cycle_state = _life_cycle_none; - this->network_message_gateway = network_message_gateway; - this->network_observer = network_observer; - this->network_session_manager = network_session_manager; - this->network_session = network_session; - this->text_chat_manager_maybe = text_chat_manager_maybe; - this->life_cycle_updating = false; - this->life_cycle_changing = false; - this->update_requested = false; - this->requested_life_cycle = _life_cycle_none; - this->field_3C = 0; - this->field_40 = nullptr; + csmemset(m_life_cycle_handlers, 0, sizeof(m_life_cycle_handlers)); + this->m_state = _life_cycle_none; + this->m_network_message_gateway = network_message_gateway; + this->m_network_observer = network_observer; + this->m_network_session_manager = network_session_manager; + this->m_active_squad_session = squad_session_one; + this->m_secondary_squad_session = squad_session_two; + this->m_update_active = false; + this->m_state_change_active = false; + this->m_update_requested = false; + this->m_requested_life_cycle = _life_cycle_none; } - static bool game_life_cycle_initialized(); static c_game_life_cycle_manager* get(); - static bool get_active_session(c_network_session** out_session); + e_game_life_cycle get_life_cycle() const; + bool get_active_session(c_network_session** out_session); + bool state_is_joining() const; bool state_is_in_game() const; void request_state_change(e_game_life_cycle requested_state, int a3, void* a4); }; -ASSERT_STRUCT_SIZE(c_game_life_cycle_manager, 0x48); +ASSERT_STRUCT_SIZE(c_game_life_cycle_manager, 68); + +bool game_life_cycle_initialized(); +bool network_life_cycle_in_squad_session(c_network_session** out_network_session); \ No newline at end of file diff --git a/xlive/Blam/Engine/networking/transport/network_channel.h b/xlive/Blam/Engine/networking/transport/network_channel.h index 777d9ba2c..552dd8891 100644 --- a/xlive/Blam/Engine/networking/transport/network_channel.h +++ b/xlive/Blam/Engine/networking/transport/network_channel.h @@ -35,8 +35,8 @@ enum e_network_channel_state struct alignas(8) s_network_channel { - void* network_link; - void* network_message_gateway; + void* m_network_link; + void* m_network_message_gateway; void* network_message_handler; void* network_channel_config; int32 network_connection_index; diff --git a/xlive/Blam/Engine/networking/transport/network_observer.cpp b/xlive/Blam/Engine/networking/transport/network_observer.cpp index e188e44c1..21a6c9190 100644 --- a/xlive/Blam/Engine/networking/transport/network_observer.cpp +++ b/xlive/Blam/Engine/networking/transport/network_observer.cpp @@ -160,7 +160,7 @@ bool __thiscall c_network_observer::get_bandwidth_results(int32 *out_throughput, return false; } -void __declspec(naked) call_get_bandwidth_results() { __asm jmp c_network_observer::get_bandwidth_results } +void __declspec(naked) jmp_get_bandwidth_results() { __asm jmp c_network_observer::get_bandwidth_results } // raw WinSock has a 28 bytes packet overhead for the packet header, unlike Xbox LIVE, which has 44 bytes (28 bytes + whatever LIVE packet header adds) int32 __cdecl transport_get_packet_overhead_hook(int32 protocol_type) @@ -213,8 +213,8 @@ bool __thiscall c_network_observer::channel_should_send_packet_hook( int32 observer_index = NONE; for (int32 i = 0; i < 16; i++) { - if (this->observer_channels[i].state != _observer_channel_state_none - && this->observer_channels[i].channel_index == network_channel_index) + if (this->m_observer_channels[i].state != _observer_channel_state_none + && this->m_observer_channels[i].channel_index == network_channel_index) { observer_index = i; break; @@ -225,7 +225,7 @@ bool __thiscall c_network_observer::channel_should_send_packet_hook( return false; s_network_channel* network_channel = s_network_channel::get(network_channel_index); - s_observer_channel* observer_channel = &this->observer_channels[observer_index]; + s_observer_channel* observer_channel = &this->m_observer_channels[observer_index]; // we modify the network channel paramters to force the network tickrate const real32 _temp_network_rate = observer_channel->net_rate_managed_stream; @@ -342,7 +342,7 @@ void c_network_observer::apply_patches() // increase the network heap size WriteValue(Memory::GetAddress(0x1ACCC8, 0x1ACE96) + 6, k_network_heap_size); - PatchCall(Memory::GetAddress(0x1E0FEE, 0x1B5EDE), call_get_bandwidth_results); + PatchCall(Memory::GetAddress(0x1E0FEE, 0x1B5EDE), jmp_get_bandwidth_results); WriteJmpTo(Memory::GetAddressRelative(0x5AC1BD, 0x5A6B76), transport_get_packet_overhead_hook); diff --git a/xlive/Blam/Engine/networking/transport/network_observer.h b/xlive/Blam/Engine/networking/transport/network_observer.h index db9aee8d6..24018fb88 100644 --- a/xlive/Blam/Engine/networking/transport/network_observer.h +++ b/xlive/Blam/Engine/networking/transport/network_observer.h @@ -57,7 +57,7 @@ struct alignas(8) s_observer_channel int32 state; int32 field_4; uint8 observer_flags; - uint8 field_9; + uint8 owner_flags; uint16 field_A; int32 channel_index; int32 field_10; @@ -156,10 +156,10 @@ ASSERT_STRUCT_SIZE(s_observer_channel, 0x740); struct alignas(8) c_network_observer { public: - void* network_observer_vtbl; // vtable at the start - void* network_link; - void* network_message_gateway; - void* message_types; + void* vtbl; + void* m_network_link; + void* m_network_message_gateway; + void* m_message_types; s_network_observer_configuration* configuration; int32 *field_14; uint8 gap_18[8]; @@ -173,7 +173,7 @@ struct alignas(8) c_network_observer uint8 gap_68[12]; int32 field_74; uint8 gap_78[8]; - s_observer_channel observer_channels[k_network_channel_count]; + s_observer_channel m_observer_channels[k_network_channel_count]; bool network_observer_enabled; int8 field_7481; int32 field_7484; @@ -225,7 +225,7 @@ struct alignas(8) c_network_observer uint8* out_voice_chat_data_buffer); bool __thiscall get_bandwidth_results(int32 *out_throughput, real32 *out_satiation, int32 *a4); - int32 get_observer_channel_state(int32 observer_index) { return observer_channels[observer_index].state; }; + int32 get_observer_channel_state(int32 observer_index) { return m_observer_channels[observer_index].state; }; void send_message(int32 session_index, int32 observer_index, bool send_out_of_band, int32 type, int32 size, void* data); private: diff --git a/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp b/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp index 2bf486286..56e97a1a7 100644 --- a/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp +++ b/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp @@ -266,24 +266,24 @@ void render_netdebug_text(void) { if (ImGuiHandler::g_network_stats_overlay != _network_stats_display_none) { - c_network_session* session; - if (NetworkSession::GetActiveNetworkSession(&session)) + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { s_simulation_player_netdebug_data netdebug_data_default{}; s_simulation_player_netdebug_data* netdebug_data = &netdebug_data_default; - if (!session->local_state_session_host()) + if (!session->is_host()) { s_membership_peer* membership_peer = session->get_peer_membership(session->get_local_peer_index()); - int32 channel_index = session->observer_channels[session->get_session_host_peer_index()].observer_index; - if (channel_index != NONE) + int32 observer_channel_index = session->m_session_peers[session->get_session_host_peer_index()].observer_channel_index; + if (observer_channel_index != NONE) { - s_observer_channel* observer_channel = &session->p_network_observer->observer_channels[channel_index]; + s_observer_channel* observer_channel = &session->m_network_observer->m_observer_channels[observer_channel_index]; netdebug_data->client_rtt_msec = observer_channel->net_rtt; netdebug_data->client_packet_rate = observer_channel->net_rate_managed_stream * 10.f; netdebug_data->client_throughput = (observer_channel->throughput_bps * 10.f) / 1024.f; - netdebug_data->client_packet_loss = observer_channel->field_440.average_values_in_window() * 100.f; + netdebug_data->client_packet_loss_percentage = observer_channel->field_440.average_values_in_window() * 100.f; // NOT UPDATED IN REAL-TIME //for (int32 i = 0; i < k_number_of_users; i++) @@ -316,7 +316,7 @@ void render_netdebug_text(void) netdebug_data->client_rtt_msec, (real32)netdebug_data->client_packet_rate / 10.f, ((real32)netdebug_data->client_throughput / 10.f) * 1024.f, - netdebug_data->client_packet_loss + netdebug_data->client_packet_loss_percentage ); draw_string_reset(); diff --git a/xlive/Blam/Engine/shell/shell.h b/xlive/Blam/Engine/shell/shell.h index 0bd32461e..3646d10b6 100644 --- a/xlive/Blam/Engine/shell/shell.h +++ b/xlive/Blam/Engine/shell/shell.h @@ -23,10 +23,10 @@ enum e_shell_command_line_flags : int32 _shell_command_line_flag_unk12, // some tag thing? _shell_command_line_flag_unk13, // some tag thing? _shell_command_line_flag_unk14, // some tag thing? - _shell_command_line_flag_custom_map_entry_test_map_name_instead_of_hash, // flag to test the map name instead of the hash of the custom map - _shell_command_line_flag_unk16, + _shell_command_line_flag_unk15, + _shell_command_line_flag_unk16, // fuzzer/automated testing? (sapien) _shell_command_line_flag_xbox_live_silver_account, // if true, disables 'gold-only' features, like quickmatch etc - _shell_command_line_flag_unk18, // fuzzer/automated testing? (sapien) + _shell_command_line_flag_custom_map_entry_test_map_name_instead_of_hash, // flag to test the map name instead of the hash of the custom map _shell_command_line_flag_ui_fast_test_no_start, // same as below but doesn't start a game _shell_command_line_flag_ui_fast_test, // auto navigates the UI selecting the default option _shell_command_line_flag_unk21, // player controls related, is checked when using a vehicle diff --git a/xlive/Blam/Engine/simulation/simulation_encoding.h b/xlive/Blam/Engine/simulation/simulation_encoding.h index 503460e92..20e1dab5b 100644 --- a/xlive/Blam/Engine/simulation/simulation_encoding.h +++ b/xlive/Blam/Engine/simulation/simulation_encoding.h @@ -3,7 +3,7 @@ #include "simulation_players.h" #include "memory/bitstream.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" struct simulation_machine_update { diff --git a/xlive/Blam/Engine/sound/sound_manager.h b/xlive/Blam/Engine/sound/sound_manager.h index e92dde92b..fe2b17254 100644 --- a/xlive/Blam/Engine/sound/sound_manager.h +++ b/xlive/Blam/Engine/sound/sound_manager.h @@ -1,5 +1,5 @@ #pragma once -#include "Networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #define MAXIMUM_SOUND_INSTANCES_PER_DEFINITION 16 #define MAXIMUM_SOUND_INSTANCES_PER_OBJECT_PER_DEFINITION MAXIMUM_SOUND_INSTANCES_PER_DEFINITION diff --git a/xlive/H2MOD.cpp b/xlive/H2MOD.cpp index fac33c22e..d91bccc69 100644 --- a/xlive/H2MOD.cpp +++ b/xlive/H2MOD.cpp @@ -511,12 +511,14 @@ user_interface_controller_set_desired_team_index_t p_user_interface_controller_s void __cdecl user_interface_controller_set_desired_team_index_hook(e_controller_index controller_index, e_game_team team) { - c_network_session* session = NetworkSession::GetActiveNetworkSession(); + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); // prevent team switch in the pregame lobby, when the game already started - if (session) { - if ((session->parameters[0].session_mode == 4 - && get_game_life_cycle() == _life_cycle_pre_game)) + if (session + && session->session_mode() == _network_session_mode_in_game + && get_game_life_cycle() == _life_cycle_pre_game) + { return; } p_user_interface_controller_set_desired_team_index(controller_index, team); @@ -553,10 +555,10 @@ uint16 __cdecl get_enabled_team_flags(c_network_session* session) std::wstring selected_map_file_name; // skip if we're not host, let the host control - if (!NetworkSession::LocalPeerIsSessionHost()) + if (!session->is_host()) return default_teams_enabled_flags; - if (CustomVariantHandler::ContainsGameVariant(NetworkSession::GetGameVariantName(), _id_infection)) + if (CustomVariantHandler::ContainsGameVariant(session->get_game_variant_name(), _id_infection)) { // infection overrides H2Config // TODO get infection_teams through the interface @@ -569,7 +571,7 @@ uint16 __cdecl get_enabled_team_flags(c_network_session* session) LOG_WARNING_FUNCW(" - perhaps current selected map - {} doesn't support these teams?? overriding anyway", selected_map_file_name.c_str()); } } - else if (StrStrIW(NetworkSession::GetGameVariantName(), L"rvb") != NULL) + else if (StrStrIW(session->get_game_variant_name(), L"rvb") != NULL) { // same with rvb, overrides H2Config new_teams_enabled_flags = red_versus_blue_teams; @@ -615,15 +617,18 @@ bool __cdecl should_start_pregame_countdown_hook() // dedicated server only auto p_should_start_pregame_countdown = Memory::GetAddress(0x0, 0xBC2A); + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); + // if the game already thinks the game timer doesn't need to start, return false and skip any processing if (!p_should_start_pregame_countdown() - || !NetworkSession::LocalPeerIsSessionLeader()) + || !session->is_local_peer_session_leader()) return false; bool minimumPlayersConditionMet = true; if (H2Config_minimum_player_start > 0) { - if (NetworkSession::GetPlayerCount() >= H2Config_minimum_player_start) + if (session->get_player_count() >= H2Config_minimum_player_start) { LOG_INFO_GAME(L"{} - minimum Player count met", __FUNCTIONW__); minimumPlayersConditionMet = true; diff --git a/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp b/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp index 2c3f905a4..f60338218 100644 --- a/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp +++ b/xlive/H2MOD/GUI/imgui_integration/Console/CommandCollection.cpp @@ -10,7 +10,7 @@ #include "main/main_game_time.h" #include "main/main_render.h" #include "main/main_screenshot.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #include "networking/NetworkMessageTypeCollection.h" #include "render/render_cartographer_ingame_ui.h" #include "objects/objects.h" @@ -254,7 +254,7 @@ int CommandCollection::LogSelectedMapFilenameCmd(const std::vector& { TextOutputCb* outputCb = ctx.outputCb; - if (!NetworkSession::GetActiveNetworkSession(nullptr)) + if (!network_life_cycle_in_squad_session(NULL)) { outputCb(StringFlag_None, "# not in a network session"); return 0; @@ -265,7 +265,7 @@ int CommandCollection::LogSelectedMapFilenameCmd(const std::vector& utf8 map_name[256]; wchar_string_to_utf8_string(mapFilenameWide.c_str(), map_name, NUMBEROF(map_name)); - outputCb(StringFlag_None, "# map file name: %s", map_name); + outputCb(StringFlag_None, "# map file name: %s", map_name); return 0; } @@ -273,7 +273,7 @@ int CommandCollection::RequestFileNameCmd(const std::vector& tokens { TextOutputCb* outputCb = ctx.outputCb; - if (!NetworkSession::GetActiveNetworkSession(nullptr)) + if (!network_life_cycle_in_squad_session(NULL)) { outputCb(StringFlag_None, "# not in a network session"); return 0; @@ -292,7 +292,7 @@ int CommandCollection::LeaveNetworkSessionCmd(const std::vector& to { TextOutputCb* outputCb = ctx.outputCb; - if (!NetworkSession::GetActiveNetworkSession(nullptr)) + if (!network_life_cycle_in_squad_session(NULL)) { outputCb(StringFlag_None, "# not in a network session"); return 0; @@ -310,8 +310,8 @@ int CommandCollection::IsSessionHostCmd(const std::vector& tokens, { TextOutputCb* outputCb = ctx.outputCb; - c_network_session* session; - if (!NetworkSession::GetActiveNetworkSession(&session)) + c_network_session* session = NULL; + if (!network_life_cycle_in_squad_session(&session)) { outputCb(StringFlag_None, "# not in a network session"); return 0; @@ -319,8 +319,8 @@ int CommandCollection::IsSessionHostCmd(const std::vector& tokens, std::string isHostStr; isHostStr += "# Session host: "; - isHostStr += (NetworkSession::LocalPeerIsSessionHost() ? "yes" : "no"); - isHostStr += ", value=" + std::to_string(session->local_session_state); + isHostStr += (session->is_host() ? "yes" : "no"); + isHostStr += ", value=" + std::to_string(session->m_local_state); outputCb(StringFlag_None, isHostStr.c_str()); return 0; } @@ -328,12 +328,12 @@ int CommandCollection::IsSessionHostCmd(const std::vector& tokens, int CommandCollection::KickPeerCmd(const std::vector& tokens, ConsoleCommandCtxData ctx) { TextOutputCb* outputCb = ctx.outputCb; - int peerIndex; + int32 peer_index; std::string exception; do { - if (!ComVar(&peerIndex).SetFromStr(tokens[1], 0, exception)) + if (!ComVar(&peer_index).SetFromStr(tokens[1], 0, exception)) { outputCb(StringFlag_None, command_error_bad_arg); outputCb(StringFlag_None, " %s", exception.c_str()); @@ -347,16 +347,16 @@ int CommandCollection::KickPeerCmd(const std::vector& tokens, Conso outputCb(StringFlag_None, "# only the host can kick players"); break; } - else if (NetworkSession::GetLocalPeerIndex() == peerIndex) { + else if (NetworkSession::GetLocalPeerIndex() == peer_index) { outputCb(StringFlag_None, "# don't kick yourself"); break; } - else if (peerIndex >= NetworkSession::GetPeerCount()) { + else if (peer_index >= NetworkSession::GetPeerCount()) { outputCb(StringFlag_None, "# peer at the specified index doesn't exist"); break; } - NetworkSession::KickPeer(peerIndex); + NetworkSession::KickPeer(peer_index); } while (0); return 0; @@ -437,35 +437,36 @@ int CommandCollection::LogPlayersCmd(const std::vector& tokens, Con TextOutputCb* outputCb = ctx.outputCb; const ConsoleCommand* command_data = ctx.consoleCommand; - if (!NetworkSession::GetActiveNetworkSession(nullptr)) + c_network_session* session = NULL; + if (!network_life_cycle_in_squad_session(&session)) { outputCb(StringFlag_None, "# not in a network session"); return 0; } - else if (!NetworkSession::LocalPeerIsSessionHost()) + else if (!session->is_host()) { outputCb(StringFlag_None, "# must be network session host"); return 0; } - outputCb(StringFlag_None, "# %i players: ", NetworkSession::GetPlayerCount()); + outputCb(StringFlag_None, "# %i players: ", session->get_player_count()); - for (int playerIdx = 0; playerIdx < k_maximum_players; playerIdx++) + for (int32 player_index = 0; player_index < k_maximum_players; player_index++) { - if (NetworkSession::PlayerIsActive(playerIdx)) + if (session->is_session_player_active(player_index)) { - std::wstring playerNameWide(NetworkSession::GetPlayerName(playerIdx)); + std::wstring playerNameWide(session->get_player_name(player_index)); std::string playerName(playerNameWide.begin(), playerNameWide.end()); - std::string outStr = "# Player index=" + std::to_string(playerIdx); - outStr += ", Peer index=" + std::to_string(NetworkSession::GetPeerIndex(playerIdx)); + std::string outStr = "# Player index=" + std::to_string(player_index); + outStr += ", Peer index=" + std::to_string(NetworkSession::GetPeerIndex(player_index)); outStr += ", PlayerName=" + playerName; - playerNameWide = s_player::get_name(playerIdx); + playerNameWide = s_player::get_name(player_index); playerName = std::string(playerNameWide.begin(), playerNameWide.end()); outStr += ", Name from game player state=" + playerName; - outStr += ", Team=" + std::to_string(NetworkSession::GetPlayerTeam(playerIdx)); - outStr += ", Identifier=" + std::to_string(NetworkSession::GetPlayerId(playerIdx)); + outStr += ", Team=" + std::to_string(NetworkSession::GetPlayerTeam(player_index)); + outStr += ", Identifier=" + std::to_string(NetworkSession::GetPlayerId(player_index)); outputCb(StringFlag_None, outStr.c_str()); } @@ -479,38 +480,37 @@ int CommandCollection::LogPeersCmd(const std::vector& tokens, Conso TextOutputCb* outputCb = ctx.outputCb; const ConsoleCommand* command_data = ctx.consoleCommand; - c_network_session* session; - - if (!NetworkSession::GetActiveNetworkSession(&session)) + c_network_session* session = NULL; + if (!network_life_cycle_in_squad_session(&session)) { outputCb(StringFlag_None, "# not in a network session"); return 0; } - else if (!NetworkSession::LocalPeerIsSessionHost()) + else if (!session->is_host()) { outputCb(StringFlag_None, "# must be network session host"); return 0; } - c_network_observer* observer = NetworkSession::GetActiveNetworkSession()->p_network_observer; + c_network_observer* observer = session->m_network_observer; - outputCb(StringFlag_None, "# %i peers: ", NetworkSession::GetPeerCount()); + outputCb(StringFlag_None, "# %i peers: ", session->get_peer_count()); - for (int32 peer_index = 0; peer_index < NetworkSession::GetPeerCount(); peer_index++) + for (int32 peer_index = 0; peer_index < session->get_peer_count(); peer_index++) { - auto peer_observer_channel = &observer->observer_channels[session->observer_channels[peer_index].observer_index]; + auto peer_observer_channel = &observer->m_observer_channels[session->m_session_peers[peer_index].observer_channel_index]; - std::wstring peerNameWide(session->membership[0].peers[peer_index].name); + std::wstring peerNameWide(session->m_session_membership.membership_peers[peer_index].name); std::string peerName(peerNameWide.begin(), peerNameWide.end()); std::string outStr = "# Peer index=" + std::to_string(peer_index); outStr += ", Peer Name=" + peerName; outStr += ", Connection Status=" + std::to_string(peer_observer_channel->state); - outStr += ", Peer map state: " + std::to_string(session->membership[0].peers[peer_index].map_status); - datum player_index = session->membership[0].peers[peer_index].local_players_indexes[0]; + outStr += ", Peer map state: " + std::to_string(session->m_session_membership.membership_peers[peer_index].map_status); + datum player_index = session->m_session_membership.membership_peers[peer_index].local_players_indexes[0]; if (player_index != NONE) { - std::wstring playerNameWide(NetworkSession::GetPlayerName(player_index)); + std::wstring playerNameWide(session->get_player_membership(player_index)->properties[0].player_name); std::string playerName(playerNameWide.begin(), playerNameWide.end()); outStr += ", Player index=" + std::to_string(player_index); outStr += ", Player name=" + playerName; @@ -534,7 +534,13 @@ int CommandCollection::SetMaxPlayersCmd(const std::vector& tokens, do { - if (!NetworkSession::LocalPeerIsSessionHost()) { + c_network_session* session = NULL; + if (!network_life_cycle_in_squad_session(&session)) + { + outputCb(StringFlag_None, "# not in a network session"); + break; + } + else if (!session->is_host()) { outputCb(StringFlag_None, "# can be only used by host"); break; } @@ -548,12 +554,12 @@ int CommandCollection::SetMaxPlayersCmd(const std::vector& tokens, outputCb(StringFlag_None, "# the value needs to be between 1 and 16"); break; } - else if (max_players < NetworkSession::GetPlayerCount()) { + else if (max_players < session->get_player_count()) { outputCb(StringFlag_None, "# you can't set a value of max players smaller than the actual number of players on the server"); break; } - NetworkSession::GetActiveNetworkSession()->parameters[0].max_party_players = max_players; + session->m_session_parameters.max_party_players = max_players; outputCb(StringFlag_None, "# maximum players set: %i", max_players); } while (0); @@ -894,17 +900,17 @@ int CommandCollection::game_mode(const std::vector& tokens, Console int CommandCollection::invite(const std::vector& tokens, ConsoleCommandCtxData ctx) { TextOutputCb* outputCb = ctx.outputCb; - c_network_session* network_session = NetworkSession::GetActiveNetworkSession(); - bool not_session_host = !NetworkSession::LocalPeerIsSessionHost(); + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); + bool session_host = session->is_host(); - XSESSION_INFO session; - session.sessionID = network_session->session_id; - session.keyExchangeKey = network_session->xnkey; - session.hostAddress = (not_session_host ? - network_session->p_network_observer->observer_channels[NetworkSession::GetPeerObserverChannel(network_session->session_host_peer_index)->observer_index].xnaddr - : network_session->virtual_couch[0].xsession_info.hostAddress); + XSESSION_INFO x_session_info; + x_session_info.sessionID = session->session_id; + x_session_info.keyExchangeKey = session->xnkey; + x_session_info.hostAddress = (session_host ? session->m_session_virtual_couch.xsession_info.hostAddress : + session->m_network_observer->m_observer_channels[session->get_session_peer(session->m_session_host_peer_index)->observer_channel_index].xnaddr); - uint8* session_bytes = (uint8*)&session; + uint8* session_bytes = (uint8*)&x_session_info; char connect_string[sizeof(XSESSION_INFO) * 2 + 1]; // Encode the data into hex string @@ -937,13 +943,21 @@ int CommandCollection::connect(const std::vector& tokens, ConsoleCo int CommandCollection::change_player_team(const std::vector& tokens, ConsoleCommandCtxData ctx) { + TextOutputCb* outputCb = ctx.outputCb; + int32 player_index = NONE; int32 new_team_index = NONE; if (ComVar(&player_index).SetFromStr(tokens[1]) && ComVar(&new_team_index).SetFromStr(tokens[2])) { - c_network_session* session = NetworkSession::GetActiveNetworkSession(); + c_network_session* session = NULL; + if (!network_life_cycle_in_squad_session(&session)) + { + outputCb(StringFlag_None, "# not in a network session"); + return 0; + } + session->switch_player_team(player_index, (e_game_team)new_team_index); } diff --git a/xlive/H2MOD/GUI/imgui_integration/ImGui_NetworkStatsOverlay.cpp b/xlive/H2MOD/GUI/imgui_integration/ImGui_NetworkStatsOverlay.cpp index 3d4f72214..cbbd316fe 100644 --- a/xlive/H2MOD/GUI/imgui_integration/ImGui_NetworkStatsOverlay.cpp +++ b/xlive/H2MOD/GUI/imgui_integration/ImGui_NetworkStatsOverlay.cpp @@ -5,7 +5,7 @@ #include "game/game_time.h" #include "networking/memory/networking_memory.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #include "simulation/simulation.h" #include "XLive/xnet/IpManagement/XnIp.h" @@ -77,8 +77,8 @@ void ShowNetworkStatsOverlay(bool* p_open) ImGui::Text("Network stats overlay\n"); ImGui::Separator(); - c_network_session* session; - if (NetworkSession::GetActiveNetworkSession(&session)) + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { ImGui::Text("Network protocol: %s", session->describe_network_protocol_type()); } diff --git a/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.cpp b/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.cpp index bee7972fe..de5887387 100644 --- a/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.cpp +++ b/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.cpp @@ -7,7 +7,6 @@ #include "game/game_time.h" #include "networking/logic/life_cycle_manager.h" #include "networking/NetworkMessageTypeCollection.h" -#include "networking/Session/NetworkSession.h" #include "physics/physics_constants.h" #include "units/units.h" @@ -51,10 +50,11 @@ namespace CustomVariantSettings currentVariantSettings = *data; } - void SendCustomVariantSettings(int peerIndex) + void SendCustomVariantSettings(int32 peer_index) { - c_network_session* session = NetworkSession::GetActiveNetworkSession(); - if (NetworkSession::LocalPeerIsSessionHost() && Memory::IsDedicatedServer()) + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); + if (session->is_host() && Memory::IsDedicatedServer()) { //TODO: Find and map out struct with current variant information. auto VariantName = std::wstring(Memory::GetAddress(0, 0x534A18)); @@ -64,12 +64,18 @@ namespace CustomVariantSettings { currentVariantSettings = customVariantSetting->second; if (currentVariantSettings != defaultCustomVariantSettings) { - c_network_observer* observer = session->p_network_observer; - s_session_observer_channel* observer_channel = NetworkSession::GetPeerObserverChannel(peerIndex); - if (peerIndex != -1 && !NetworkSession::IsPeerIndexLocal(peerIndex)) + c_network_observer* observer = session->m_network_observer; + s_session_peer* peer = session->get_session_peer(peer_index); + if (peer_index != NONE && !session->is_peer_local(peer_index)) { - if (observer_channel->field_1) - observer->send_message(session->session_index, observer_channel->observer_index, false, _custom_variant_settings, CustomVariantSettingsPacketSize, ¤tVariantSettings); + if (peer->is_remote_peer) + observer->send_message( + session->m_session_index, + peer->observer_channel_index, + false, + _custom_variant_settings, + CustomVariantSettingsPacketSize, + ¤tVariantSettings); } } } @@ -146,13 +152,9 @@ namespace CustomVariantSettings } - //Host Only - if (NetworkSession::LocalPeerIsSessionHost()) - { - // *((_DWORD *)v1 + 94) = seconds_to_ticks_imprecise(1); - //Changing the argument passed to seconds_to_ticks_impercise. - WriteValue(Memory::GetAddress(0x55d01, 0x5e1f9), (BYTE)newVariantSettings->spawnProtection); - } + // *((_DWORD *)v1 + 94) = seconds_to_ticks_imprecise(1); + //Changing the argument passed to seconds_to_ticks_impercise. + WriteValue(Memory::GetAddress(0x55d01, 0x5e1f9), (BYTE)newVariantSettings->spawnProtection); } void ApplyCurrentSettings() { @@ -184,13 +186,15 @@ namespace CustomVariantSettings } void OnMatchCountdown() { - // - //Anything host related before the game starts goes here. - // - for (auto i = 0; i < NetworkSession::GetPeerCount(); i++) + // Anything host related before the game starts goes here. + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { - if (!NetworkSession::IsPeerIndexLocal(i)) - SendCustomVariantSettings(i); + for (int32 i = 0; i < session->get_peer_count(); i++) + { + if (!session->is_peer_local(i)) + SendCustomVariantSettings(i); + } } } diff --git a/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.h b/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.h index 5cb69fa76..015ef28d0 100644 --- a/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.h +++ b/xlive/H2MOD/Modules/CustomVariantSettings/CustomVariantSettings.h @@ -49,7 +49,7 @@ namespace CustomVariantSettings void ApplyCustomSettings(s_variant_settings* newVariantSettings); void UpdateCustomVariantSettings(s_variant_settings* data); - void SendCustomVariantSettings(int peerIndex); + void SendCustomVariantSettings(int32 peer_index); void ApplyHooks(); void Initialize(); } diff --git a/xlive/H2MOD/Modules/MapManager/MapManager.cpp b/xlive/H2MOD/Modules/MapManager/MapManager.cpp index 5c6bb8101..b720475b3 100644 --- a/xlive/H2MOD/Modules/MapManager/MapManager.cpp +++ b/xlive/H2MOD/Modules/MapManager/MapManager.cpp @@ -7,14 +7,14 @@ #include "H2MOD/Modules/OnScreenDebug/OnscreenDebug.h" #include "networking/NetworkMessageTypeCollection.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #include "networking/logic/life_cycle_manager.h" #include "main/game_preferences.h" std::unique_ptr mapManager(std::make_unique()); -const wchar_t* k_map_download_source_text[k_language_count] = +const wchar_t* k_map_download_source_text[k_language_count] = { L"repository", }; @@ -26,85 +26,74 @@ network_life_cycle_session_get_global_map_precache_status_t p_network_life_cycle // allow hosts to start the game while other peers didn't load the map // TODO: simplify and cleanup -int32 __cdecl network_life_cycle_session_get_global_map_precache_status_hook(int32 *out_lowest_load_percentage, e_network_session_map_status *out_host_map_status) { +int32 __cdecl network_life_cycle_session_get_global_map_precache_status_hook(int32* out_lowest_load_percentage, e_network_session_map_status* out_host_map_status) { // this just gets the current network_session, but has some extra misc checks c_network_session* session = nullptr; e_network_session_map_status result_map_status = _network_session_map_status_none; uint32 result_precache_percentage = 0; bool someone_downloading_map = false; - e_network_session_map_status local_peer_map_status, host_peer_map_status; + e_network_session_map_status local_peer_map_status, host_peer_map_status; local_peer_map_status = host_peer_map_status = _network_session_map_status_none; int32 peer_count_with_map_status_precached = 0; int32 peer_count_with_map_status_downloading = 0; int32 peer_count_with_map_status_unable_to_precache = 0; - if (c_game_life_cycle_manager::get_active_session(&session)) { - switch (session->local_session_state) + if (c_game_life_cycle_manager::get()->get_active_session(&session) + && session->established()) + { + s_session_membership* membership = &session->m_session_membership; + + if (out_host_map_status) { - case _network_session_state_none: - case _network_session_state_peer_joining: - case _network_session_state_peer_join_abort: - case _network_session_state_election: - case _network_session_state_dead: - break; - - case _network_session_state_peer_established: - case _network_session_state_peer_leaving: - case _network_session_state_host_established: - case _network_session_state_host_disband: - case _network_session_state_host_handoff: - case _network_session_state_host_reestablish: - s_session_membership* membership = &session->membership[0]; - - if (out_host_map_status) - *out_host_map_status = membership->peers[session->session_host_peer_index].map_status; - - result_map_status = _network_session_map_status_loaded; - result_precache_percentage = 100; // i don't think this is used anymore, it has been replaced by the loading screen in H2v from Xbox - - for (int32 i = 0; i < membership->peer_count; i++) { - - // NOTE UPDATE 7/29/2021: now this checks if there's any peer that can load the map, instead of if there's any peer that cannot load the map - // ************* - - // now we only check our peer and session host peer, instead of all the peers - // but make sure the game won't start if we have just 1 player that doesn't have the map - if (session->local_peer_index == i) - local_peer_map_status = membership->peers[i].map_status; - - if (session->session_host_peer_index == i) - host_peer_map_status = membership->peers[i].map_status; - - switch (membership->peers[i].map_status) - { - case _network_session_map_status_unable_to_precache: - result_precache_percentage = 0; - peer_count_with_map_status_unable_to_precache++; - break; + *out_host_map_status = membership->membership_peers[session->m_session_host_peer_index].map_status; + } - case _network_session_map_status_precaching: - result_precache_percentage = MIN(membership->peers[i].map_progress_percentage, result_precache_percentage); // get the least map precaching percentage - break; + result_map_status = _network_session_map_status_loaded; + result_precache_percentage = 100; // i don't think this is used anymore, it has been replaced by the loading screen in H2v from Xbox - case _network_session_map_status_loaded: - case _network_session_map_status_precached: - peer_count_with_map_status_precached++; - break; + for (int32 i = 0; i < membership->peer_count; i++) + { + // NOTE UPDATE 7/29/2021: now this checks if there's any peer that can load the map, instead of if there's any peer that cannot load the map + // ************* - case _network_session_map_status_downloading: - someone_downloading_map = true; - peer_count_with_map_status_downloading++; - break; + // now we only check our peer and session host peer, instead of all the membership_peers + // but make sure the game won't start if we have just 1 player that doesn't have the map + if (session->m_local_peer_index == i) + local_peer_map_status = membership->membership_peers[i].map_status; - default: - break; - } + if (session->m_session_host_peer_index == i) + host_peer_map_status = membership->membership_peers[i].map_status; + + switch (membership->membership_peers[i].map_status) + { + case _network_session_map_status_unable_to_precache: + result_precache_percentage = 0; + peer_count_with_map_status_unable_to_precache++; + break; + + case _network_session_map_status_precaching: + result_precache_percentage = MIN(membership->membership_peers[i].map_progress_percentage, result_precache_percentage); // get the least map precaching percentage + break; + + case _network_session_map_status_loaded: + case _network_session_map_status_precached: + peer_count_with_map_status_precached++; + break; + + case _network_session_map_status_downloading: + someone_downloading_map = true; + peer_count_with_map_status_downloading++; + break; + + default: + break; } + } - // checks if local/host map status is fine - // if not just let the game know map cannot be loaded - auto test_map_status = [&](e_network_session_map_status status) -> bool + // checks if local/host map status is fine + // if not just let the game know map cannot be loaded + auto test_map_status = [&](e_network_session_map_status status) -> bool { switch (status) { @@ -137,13 +126,12 @@ int32 __cdecl network_life_cycle_session_get_global_map_precache_status_hook(int return false; } }; - - // first test the host map load - if (test_map_status(host_peer_map_status)) - { - // then the local peer - test_map_status(local_peer_map_status); - } + + // first test the host map load + if (test_map_status(host_peer_map_status)) + { + // then the local peer + test_map_status(local_peer_map_status); } } @@ -153,9 +141,9 @@ int32 __cdecl network_life_cycle_session_get_global_map_precache_status_hook(int return result_map_status; } -bool __stdcall game_life_cycle_get_map_load_status(void* thisx, c_network_session *session, uint32 *out_peers_unable_to_load_map_mask) +bool __stdcall game_life_cycle_get_map_load_status(void* thisx, c_network_session* session, uint32* out_peers_unable_to_load_map_mask) { - s_session_membership* membership = &session->membership[0]; + s_session_membership* membership = &session->m_session_membership; uint32 peers_map_not_loaded_mask = 0; if (membership->peer_count > 0) @@ -169,16 +157,16 @@ bool __stdcall game_life_cycle_get_map_load_status(void* thisx, c_network_sessio // ************* // check only session host and local peer indexes - //if ((i == session->local_peer_index || i == session->session_host_peer_index) + //if ((i == session->local_peer_index || i == session->m_session_host_peer_index) //|| !more_than_one_peer_other_than_dedicated_server(session)) { - switch (membership->peers[i].map_status) + switch (membership->membership_peers[i].map_status) { case _network_session_map_status_none: case _network_session_map_status_unable_to_precache: case _network_session_map_status_precaching: case _network_session_map_status_downloading: - if (NetworkSession::IsPeerIndexLocal(i) || i == session->session_host_peer_index) + if (session->is_peer_local(i) || session->is_peer_session_host(i)) local_or_host_peer_cannot_load_map = true; break; case _network_session_map_status_precached: @@ -196,7 +184,7 @@ bool __stdcall game_life_cycle_get_map_load_status(void* thisx, c_network_sessio *out_peers_unable_to_load_map_mask = peers_map_not_loaded_mask; // subtract 1 from peers_that_can_load_map to remove the host/local peer - return !local_or_host_peer_cannot_load_map && peers_that_can_load_map - (session->parameters[0].dedicated_server ? 1 : 0) > 0; + return !local_or_host_peer_cannot_load_map && peers_that_can_load_map - (session->m_session_parameters.dedicated_server ? 1 : 0) > 0; } #pragma endregion @@ -245,7 +233,7 @@ int32 __cdecl map_download_get_progress_percentage() } void map_download_get_download_source_text(int32 a1, wchar_t* out_text) -{ +{ if (out_text != NULL) wcsncpy_s(out_text, 512, k_map_download_source_text[0], _TRUNCATE); } @@ -278,7 +266,7 @@ void MapManager::ApplyPatches() { PatchCall(Memory::GetAddress(0x244A4A), ui_open_map_download_confirm_dialog); /* Redirect the menu constructor to our code to replace the game's map downloading code callback */ /* Redirects map downloading percentage to our custom downloader */ - PatchCall(Memory::GetAddress(0x244B77), map_download_get_progress_percentage); + PatchCall(Memory::GetAddress(0x244B77), map_download_get_progress_percentage); PatchCall(Memory::GetAddress(0x22EE41), map_download_get_progress_percentage); PatchCall(Memory::GetAddress(0x244B8F), map_download_get_download_source_text); @@ -286,10 +274,10 @@ void MapManager::ApplyPatches() { PatchCall(Memory::GetAddress(0x593F0), load_map_data_for_display_nak); user_interface_data = Memory::GetAddress(0x9712C8); } - + // allow host to start the game, even if there are peers that didn't load the map p_network_life_cycle_session_get_global_map_precache_status = (network_life_cycle_session_get_global_map_precache_status_t)DetourFunc(Memory::GetAddress(0x1B1929, 0x197879), (BYTE*)network_life_cycle_session_get_global_map_precache_status_hook, 8); - + DetourClassFunc(Memory::GetAddress(0x1D76C5, 0x1BCD32), (BYTE*)game_life_cycle_get_map_load_status, 8); // disable the game's downloading implementation @@ -309,10 +297,10 @@ void MapManager::ReloadAllMaps() { bool MapManager::GetMapFilename(std::wstring& buffer) { wchar_t map_file_location[256]; - c_network_session* session = nullptr; + c_network_session* session = NULL; // we want this to work in-game too - if (/*p_get_lobby_state() == game_lobby_states::in_lobby && */ NetworkSession::GetActiveNetworkSession(&session)) { + if (/*p_get_lobby_state() == game_lobby_states::in_lobby && */ network_life_cycle_in_squad_session(&session)) { ZeroMemory(map_file_location, sizeof(map_file_location)); NetworkSession::GetMapFileLocation(map_file_location, ARRAYSIZE(map_file_location)); @@ -362,11 +350,11 @@ MapDownloadQuery::MapDownloadQuery(const std::wstring& _mapToDownload, unsigned SetMapNameToDownload(_mapToDownload); } -size_t map_download_curl_write_data_cb(void *ptr, size_t size, size_t nmemb, FILE *stream) { +size_t map_download_curl_write_data_cb(void* ptr, size_t size, size_t nmemb, FILE* stream) { return fwrite(ptr, size, nmemb, stream); } -static int32 map_download_curl_xferinfo_cb(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { +static int32 map_download_curl_xferinfo_cb(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { MapDownloadQuery* mapDownloadQuery = (MapDownloadQuery*)p; mapDownloadQuery->SetDownloadPercentage(((float)dlnow / (float)dltotal) * 100.f); return mapDownloadQuery->ShouldStopDownload(); @@ -375,8 +363,8 @@ static int32 map_download_curl_xferinfo_cb(void *p, curl_off_t dltotal, curl_off bool MapDownloadQuery::DownloadFromRepo() { std::string url(cartographerMapRepoURL + "/"); - FILE *fp = nullptr; - CURL *curl = nullptr; + FILE* fp = nullptr; + CURL* curl = nullptr; CURLcode res; std::wstring mapFilePathWide(get_custom_map_folder_path()); @@ -392,7 +380,7 @@ bool MapDownloadQuery::DownloadFromRepo() { return false; } - char *url_encoded_map_filename = curl_easy_escape(curl, m_clientMapFilename.c_str(), m_clientMapFilename.length()); + char* url_encoded_map_filename = curl_easy_escape(curl, m_clientMapFilename.c_str(), m_clientMapFilename.length()); url += url_encoded_map_filename; curl_free(url_encoded_map_filename); @@ -424,7 +412,7 @@ bool MapDownloadQuery::DownloadFromRepo() { LOG_ERROR_GAME("{} - {} failed with error: {}", __FUNCTION__, STRINGIFY(curl_easy_perform()), (uint32)res); if (res == CURLE_ABORTED_BY_CALLBACK) addDebugText("Map downloading aborted because of user input!"); - + remove(nonUnicodeMapFilePath.c_str()); return false; @@ -454,7 +442,7 @@ void MapDownloadQuery::StartMapDownload() //TODO: set map filesize //TODO: if downloading from repo files, try p2p - if (!DownloadFromRepo() + if (!DownloadFromRepo() && !NetworkSession::LocalPeerIsSessionHost()) { LOG_TRACE_GAME("[h2mod-mapmanager] {}() - {}() failed, leaving session!", diff --git a/xlive/H2MOD/Variants/GunGame/GunGame.cpp b/xlive/H2MOD/Variants/GunGame/GunGame.cpp index 6aba6b0f8..df51b62d1 100644 --- a/xlive/H2MOD/Variants/GunGame/GunGame.cpp +++ b/xlive/H2MOD/Variants/GunGame/GunGame.cpp @@ -2,7 +2,7 @@ #include "GunGame.h" #include "game/game.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #include "units/units.h" #include "H2MOD.h" diff --git a/xlive/H2MOD/Variants/Infection/Infection.cpp b/xlive/H2MOD/Variants/Infection/Infection.cpp index 0d81d47a3..340e00d45 100644 --- a/xlive/H2MOD/Variants/Infection/Infection.cpp +++ b/xlive/H2MOD/Variants/Infection/Infection.cpp @@ -40,17 +40,20 @@ const wchar_t* infectionSoundTable[k_language_count][e_infection_sounds::_infect int Infection::calculateZombiePlayerIndex() { - if (NetworkSession::GetPlayerCount() > 0) + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); + + if (session->get_player_count() > 0) { std::mt19937 mt_rand(rd()); std::vector activePlayersIndices = NetworkSession::GetActivePlayerIndicesList(); - std::uniform_int_distribution dist(0, NetworkSession::GetPlayerCount() - 1); + std::uniform_int_distribution dist(0, session->get_player_count() - 1); if (activePlayersIndices.empty()) return NONE; int32 infectedPlayerIndex = activePlayersIndices[dist(mt_rand)]; - LOG_TRACE_GAME(L"[h2mod-infection] random infection player index: {}, with name: {}", infectedPlayerIndex, NetworkSession::GetPlayerName(infectedPlayerIndex)); + LOG_TRACE_GAME(L"[h2mod-infection] random infection player index: {}, with name: {}", infectedPlayerIndex, session->get_player_name(infectedPlayerIndex)); return infectedPlayerIndex; } @@ -60,49 +63,39 @@ int Infection::calculateZombiePlayerIndex() void Infection::sendTeamChange() { - if (NetworkSession::LocalPeerIsSessionHost()) + c_network_session* session = NULL; + if (network_life_cycle_in_squad_session(&session)) { - int32 player_count = NetworkSession::GetPlayerCount(); - - if (player_count > 0) + if (session->is_host()) { - int32 player_array_index = 0; - datum player_indexes[k_maximum_players] = {}; - e_game_team player_teams[k_maximum_players] = {}; + int32 player_count = session->get_player_count(); - for (int32 i = 0; i < k_maximum_players; i++) + if (player_count > 0) { - if (NetworkSession::PlayerIsActive(i)) - { - e_game_team team = zombiePlayerIndex == i ? k_zombie_team : k_humans_team; - bool is_current_player_zombie = zombiePlayerIndex == i; + int32 player_array_index = 0; + datum player_indexes[k_maximum_players] = {}; + e_game_team player_teams[k_maximum_players] = {}; - //if (!NetworkSession::IsPlayerLocal(i)) + for (int32 i = 0; i < k_maximum_players; i++) + { + if (session->is_session_player_active(i)) { + e_game_team team = zombiePlayerIndex == i ? k_zombie_team : k_humans_team; + bool is_current_player_zombie = zombiePlayerIndex == i; + player_indexes[player_array_index] = i; player_teams[player_array_index++] = team; - LOG_TRACE_GAME(L"[h2mod-infection] sent team change packet to player index: {}, with name: {}, infected?: {}", - i, - NetworkSession::GetPlayerName(i), + LOG_TRACE_GAME(L"[h2mod-infection] sent team change packet to player index: {}, with name: {}, infected?: {}", + i, + session->get_player_name(i), is_current_player_zombie ); } - /*else - { - if (!Memory::IsDedicatedServer()) - { - s_player* local_player = s_player::get(i); - - user_interface_controller_set_desired_team_index(local_player->controller_index, team); - user_interface_controller_update_network_properties(local_player->controller_index); - LOG_TRACE_GAME(L"[h2mod-infection] setting local player team index, infected?: {}", is_current_player_zombie); - } - }*/ } - } - NetworkSession::GetActiveNetworkSession()->switch_players_to_teams(player_indexes, player_array_index, player_teams); + session->switch_players_to_teams(player_indexes, player_array_index, player_teams); + } } } } @@ -196,6 +189,9 @@ void Infection::preSpawnServerSetup() { /* Game state players should be initialized when we are about to spawn a player */ + + c_network_session* session = NULL; + network_life_cycle_in_squad_session(&session); player_iterator player_it; while (player_it.get_next_active_player()) @@ -217,11 +213,8 @@ void Infection::preSpawnServerSetup() { s_player::set_unit_character_type(currentPlayerIndex, _character_type_flood); if (s_player::get_team(currentPlayerIndex) != k_zombie_team) { - if (NetworkSession::LocalPeerIsSessionHost()) - { - // prevent the fucks from switching to humans in the pre-game lobby after joining - NetworkSession::GetActiveNetworkSession()->switch_player_team(player_it.get_current_player_datum_index(), k_zombie_team); - } + // prevent the fucks from switching to humans in the pre-game lobby after joining + session->switch_player_team(player_it.get_current_player_datum_index(), k_zombie_team); } } else diff --git a/xlive/Project_Cartographer.vcxproj b/xlive/Project_Cartographer.vcxproj index 2ed91f4b7..13ad27d56 100644 --- a/xlive/Project_Cartographer.vcxproj +++ b/xlive/Project_Cartographer.vcxproj @@ -907,7 +907,7 @@ - + @@ -1343,7 +1343,7 @@ - + diff --git a/xlive/Project_Cartographer.vcxproj.filters b/xlive/Project_Cartographer.vcxproj.filters index 5348f7139..805d6ff08 100644 --- a/xlive/Project_Cartographer.vcxproj.filters +++ b/xlive/Project_Cartographer.vcxproj.filters @@ -9,7 +9,7 @@ - + @@ -541,7 +541,7 @@ - + diff --git a/xlive/XLive/XUser/XUserContext.cpp b/xlive/XLive/XUser/XUserContext.cpp index 8c5af6f48..d5352207a 100644 --- a/xlive/XLive/XUser/XUserContext.cpp +++ b/xlive/XLive/XUser/XUserContext.cpp @@ -4,7 +4,7 @@ #include "cartographer/discord/discord_interface.h" #include "cseries/cseries_strings.h" #include "game/game.h" -#include "networking/Session/NetworkSession.h" +#include "networking/logic/life_cycle_manager.h" #include "text/unicode.h" #include "H2MOD/Modules/Shell/Config.h"