Skip to content

Commit 3f91e63

Browse files
twist84craftycodie
andcommitted
Initial matchmaking implementation (WIP)
Still a lot of logic left to implement and cleanup Co-Authored-By: Codie Newark <11706994+craftycodie@users.noreply.github.com>
1 parent 24b4635 commit 3f91e63

30 files changed

Lines changed: 700 additions & 223 deletions

game/source/_force_includes/_force_included_enums.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,13 @@ enum e_user_interface_session_leave_reason
11461146
k_user_interface_session_leave_reason_count
11471147
};
11481148

1149+
enum e_peer_property_flag_test_type
1150+
{
1151+
_peer_property_flag_test_all_peers = 0,
1152+
_peer_property_flag_test_host,
1153+
_peer_property_flag_test_all_peers_but_host,
1154+
};
1155+
11491156
enum e_network_session_peer_properties_status_flags
11501157
{
11511158
_network_session_peer_properties_status_game_stats_written_bit = 0,
@@ -5323,3 +5330,12 @@ enum e_transition_out_type
53235330
_transition_out_back_out,
53245331
};
53255332

5333+
enum e_network_leaderboard_write_status
5334+
{
5335+
_network_leaderboard_write_status_none = 0,
5336+
_network_leaderboard_write_in_progress,
5337+
_network_leaderboard_write_completed,
5338+
5339+
k_network_leaderboard_write_status_count,
5340+
};
5341+

game/source/networking/logic/life_cycle/life_cycle_handler_matchmaking_arbitration.cpp

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
#include "networking/logic/life_cycle/life_cycle_handler_matchmaking_arbitration.hpp"
22

3+
#include "memory/module.hpp"
4+
#include "networking/session/network_session.hpp"
5+
6+
HOOK_DECLARE_CLASS_MEMBER(0x00494AF0, c_life_cycle_state_handler_matchmaking_arbitration, ready_to_start);
7+
HOOK_DECLARE_CLASS_MEMBER(0x00494C80, c_life_cycle_state_handler_matchmaking_arbitration, session_membership_matches_arbitration_registration_results);
8+
HOOK_DECLARE_CLASS_MEMBER(0x00494EF0, c_life_cycle_state_handler_matchmaking_arbitration, update);
9+
310
c_life_cycle_state_handler_matchmaking_arbitration::c_life_cycle_state_handler_matchmaking_arbitration() :
411
c_life_cycle_state_handler(),
512
m_flags(0),
@@ -37,9 +44,103 @@ void c_life_cycle_state_handler_matchmaking_arbitration::initialize(c_life_cycle
3744
INVOKE_CLASS_MEMBER(0x004949D0, c_life_cycle_state_handler_matchmaking_arbitration, initialize, manager);
3845
}
3946

47+
void c_life_cycle_state_handler_matchmaking_arbitration::mark_arbitration_complete()
48+
{
49+
INVOKE_CLASS_MEMBER(0x00494A10, c_life_cycle_state_handler_matchmaking_arbitration, mark_arbitration_complete);
50+
}
51+
52+
bool c_life_cycle_state_handler_matchmaking_arbitration::ready_to_start()
53+
{
54+
return INVOKE_CLASS_MEMBER(0x00494AF0, c_life_cycle_state_handler_matchmaking_arbitration, ready_to_start);
55+
56+
c_network_session* group_session = get_manager()->get_group_session();
57+
bool arbitration_completed = 0;
58+
bool all_players_have_initial_participants = 0;
59+
bool all_players_session_started = 0;
60+
bool stats_written = 0;
61+
62+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: c_life_cycle_state_handler_matchmaking_arbitration::ready_to_start");
63+
64+
const c_network_session_membership* session_membership = group_session->get_session_membership();
65+
66+
if (m_flags.test(_matchmaking_arbitration_complete_bit))
67+
{
68+
arbitration_completed = !m_flags.test(_matchmaking_arbitration_failed_bit);
69+
}
70+
71+
if (m_flags.test(_matchmaking_arbitration_set_initial_participants_bit))
72+
{
73+
c_network_session_parameters* session_parameters = group_session->get_session_parameters();
74+
all_players_have_initial_participants = session_parameters->parameters_transmitted_to_peers(FLAG(_network_session_parameter_type_initial_participants)) != 0;
75+
if (!all_players_have_initial_participants)
76+
{
77+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Warning! It seems a player hasn't got initial participants!");
78+
}
79+
}
80+
81+
if (m_flags.test(_matchmaking_arbitration_start_match_session_completed_bit) && !m_flags.test(_matchmaking_arbitration_start_match_session_failed_bit))
82+
{
83+
all_players_session_started = session_membership->peer_property_flag_test(_peer_property_flag_test_all_peers, _network_session_peer_properties_status_match_started_bit);
84+
if (!all_players_session_started)
85+
{
86+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Warning! It seems a peer hasn't finished starting their session!");
87+
}
88+
}
89+
90+
if (m_flags.test(_matchmaking_arbitration_start_match_initial_stats_write_completed_bit) && !m_flags.test(_matchmaking_arbitration_start_match_initial_stats_write_failed_bit))
91+
{
92+
stats_written = session_membership->peer_property_flag_test(_peer_property_flag_test_all_peers, _network_session_peer_properties_status_match_initial_stats_written_bit);
93+
}
94+
else
95+
{
96+
stats_written = 0;
97+
}
98+
99+
if (m_flags.test(_matchmaking_arbitration_start_match_session_failed_bit))
100+
{
101+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Warning! Match start has failed!");
102+
}
103+
104+
if (m_flags.test(_matchmaking_arbitration_start_match_initial_stats_write_failed_bit))
105+
{
106+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Warning! Stats write has failed!");
107+
}
108+
109+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Arbitration completed? %s", arbitration_completed ? "YES" : "NO");
110+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Peers have initial participants? %s", all_players_have_initial_participants ? "YES" : "NO");
111+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Session started? %s", all_players_session_started ? "YES" : "NO");
112+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Stats written? %s", stats_written ? "YES" : "NO");
113+
c_console::write_line("donkey:networking:logic:life_cycle:matchmaking_arbitration: Are we ready? %s", arbitration_completed && all_players_have_initial_participants && all_players_session_started && stats_written ? "YES" : "NO");
114+
115+
return arbitration_completed && all_players_have_initial_participants && all_players_session_started && stats_written;
116+
}
117+
118+
bool c_life_cycle_state_handler_matchmaking_arbitration::session_membership_matches_arbitration_registration_results()
119+
{
120+
//return INVOKE_CLASS_MEMBER(0x00494C80, c_life_cycle_state_handler_matchmaking_arbitration, session_membership_matches_arbitration_registration_results);
121+
122+
return true;
123+
}
124+
40125
void c_life_cycle_state_handler_matchmaking_arbitration::update()
41126
{
42-
INVOKE_CLASS_MEMBER(0x00494EF0, c_life_cycle_state_handler_matchmaking_arbitration, update);
127+
//INVOKE_CLASS_MEMBER(0x00494EF0, c_life_cycle_state_handler_matchmaking_arbitration, update);
128+
129+
c_network_session* group_session = get_manager()->get_group_session();
130+
if (group_session->is_host() && !m_flags.test(_matchmaking_arbitration_set_initial_participants_bit))
131+
{
132+
// arbitration isn't implemented so we mark it as complete to make the game progress.
133+
c_life_cycle_state_handler_matchmaking_arbitration::mark_arbitration_complete();
134+
135+
// setup_initial_participants should be called by this function but isn't, so call it manually.
136+
c_life_cycle_state_handler::setup_initial_participants(group_session);
137+
138+
m_flags.set(_matchmaking_arbitration_set_initial_participants_bit, true);
139+
}
140+
141+
// $TODO: confirm this function gets called without the hook
142+
//INVOKE_CLASS_MEMBER(0x00494EF0, c_life_cycle_state_handler_matchmaking_arbitration, update);
143+
HOOK_INVOKE_CLASS_MEMBER(, c_life_cycle_state_handler_matchmaking_arbitration, update);
43144
}
44145

45146
e_life_cycle_state_transition_type c_life_cycle_state_handler_matchmaking_arbitration::update_for_state_transition()

game/source/networking/logic/life_cycle/life_cycle_handler_matchmaking_arbitration.hpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,32 @@
33
#include "networking/logic/life_cycle/life_cycle_state_handler.hpp"
44
#include "networking/logic/network_arbitration.hpp"
55

6-
//typedef c_flags<e_matchmaking_arbitration_flags, uns32, k_matchmaking_arbitration_flags_count> c_matchmaking_arbitration_flags;
7-
typedef uns32 c_matchmaking_arbitration_flags;
6+
enum e_matchmaking_arbitration_flags
7+
{
8+
_matchmaking_arbitration_entered_as_host_bit = 0,
9+
_matchmaking_arbitration_initiated_bit,
10+
_matchmaking_arbitration_blocked_bit,
11+
_matchmaking_arbitration_complete_bit,
12+
_matchmaking_arbitration_complete_as_host_bit,
13+
_matchmaking_arbitration_set_teams_bit,
14+
_matchmaking_arbitration_repeated_play_set_bit,
15+
_matchmaking_arbitration_set_initial_participants_bit,
16+
_matchmaking_arbitration_failed_bit,
17+
_matchmaking_arbitration_start_match_session_initiated_bit,
18+
_matchmaking_arbitration_start_match_session_completed_bit,
19+
_matchmaking_arbitration_start_match_session_failed_bit,
20+
_matchmaking_arbitration_start_match_initial_stats_write_initiated_bit,
21+
_matchmaking_arbitration_start_match_initial_stats_write_completed_bit,
22+
_matchmaking_arbitration_start_match_initial_stats_write_failed_bit,
23+
_matchmaking_arbitration_start_match_initial_stats_write_blocked_bit,
24+
_matchmaking_arbitration_failed_not_enough_hosts_bit,
25+
_matchmaking_arbitration_waiting_for_repeated_play_ready_bit,
26+
_matchmaking_arbitration_waiting_for_clients_to_arbitrate_bit,
27+
28+
k_matchmaking_arbitration_flags_count,
29+
};
30+
31+
typedef c_flags<e_matchmaking_arbitration_flags, uns32, k_matchmaking_arbitration_flags_count> c_matchmaking_arbitration_flags;
832

933
struct c_life_cycle_state_handler_matchmaking_arbitration :
1034
public c_life_cycle_state_handler
@@ -19,6 +43,9 @@ struct c_life_cycle_state_handler_matchmaking_arbitration :
1943

2044
c_life_cycle_state_handler_matchmaking_arbitration();
2145
void initialize(c_life_cycle_state_manager* manager);
46+
void mark_arbitration_complete();
47+
bool ready_to_start();
48+
bool session_membership_matches_arbitration_registration_results();
2249

2350
//protected:
2451
c_matchmaking_arbitration_flags m_flags;

game/source/networking/logic/life_cycle/life_cycle_handler_pre_game.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#include "networking/logic/life_cycle/life_cycle_handler_pre_game.hpp"
22

33
#include "game/multiplayer_game_hopper.hpp"
4+
#include "interface/user_interface_error_manager.hpp"
45
#include "memory/module.hpp"
56
#include "networking/logic/life_cycle/life_cycle_manager.hpp"
67
#include "networking/session/network_session.hpp"
7-
#include <interface/user_interface_error_manager.hpp>
88

99
bool net_skip_countdown = false;
1010

game/source/networking/logic/life_cycle/life_cycle_state_handler.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include "networking/logic/life_cycle/life_cycle_state_handler.hpp"
22

33
#include "cseries/cseries_events.hpp"
4+
#include "memory/module.hpp"
45
#include "networking/logic/life_cycle/life_cycle_manager.hpp"
56
#include "networking/session/network_session.hpp"
67

8+
HOOK_DECLARE_CLASS_MEMBER(0x0048E130, c_life_cycle_state_handler, setup_initial_participants);
9+
710
c_life_cycle_state_handler::c_life_cycle_state_handler() :
811
m_handler_flags()
912
{
@@ -109,7 +112,22 @@ void c_life_cycle_state_handler::initialize(c_life_cycle_state_manager* manager,
109112
//.text:0048DB10 ; private: bool c_life_cycle_state_handler::pick_teams_for_group_internal(bool, uns32)
110113
//.text:0048DE90 ; protected: bool c_life_cycle_state_handler::session_composition_valid(c_network_session const*)
111114
//.text:0048DEE0 ; protected: bool c_life_cycle_state_handler::session_has_minimum_player_count_to_start_game_in_hopper(c_network_session const*)
112-
//.text:0048E130 ; protected: bool c_life_cycle_state_handler::setup_initial_participants(c_network_session*)
115+
116+
bool c_life_cycle_state_handler::setup_initial_participants(c_network_session* session)
117+
{
118+
//return INVOKE_CLASS_MEMBER(0x0048E130, c_life_cycle_state_handler, setup_initial_participants, session);
119+
120+
c_console::write_line("donkey:matchmaking c_life_cycle_state_handler::setup_initial_participants");
121+
if (!session->is_host())
122+
{
123+
return true;
124+
}
125+
126+
bool result = false;
127+
HOOK_INVOKE_CLASS_MEMBER(result =, c_life_cycle_state_handler, setup_initial_participants, session);
128+
return result;
129+
}
130+
113131
//.text:0048E3D0 ; protected: void c_life_cycle_state_handler::squad_session_host_abort_matchmaking()
114132

115133
bool c_life_cycle_state_handler::test_flag(e_life_cycle_state_handler_flags flag)

game/source/networking/logic/life_cycle/life_cycle_state_handler.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
#include "cseries/cseries.hpp"
44

5+
struct c_life_cycle_state_manager;
6+
struct c_network_session;
7+
58
enum e_life_cycle_state_transition_type
69
{
710
_life_cycle_state_transition_unhandled = 0,
@@ -24,7 +27,6 @@ enum e_life_cycle_state_handler_flags
2427
};
2528
typedef c_flags<e_life_cycle_state_handler_flags, uns8, k_life_cycle_state_handler_flags_count> c_life_cycle_state_handler_flags;
2629

27-
struct c_life_cycle_state_manager;
2830
struct c_life_cycle_state_handler
2931
{
3032
public:
@@ -42,6 +44,11 @@ struct c_life_cycle_state_handler
4244
uns64 get_required_squad_session_parameter_mask() const;
4345
e_life_cycle_state get_state() const;
4446
void initialize(c_life_cycle_state_manager* manager, e_life_cycle_state state, c_life_cycle_state_handler_flags const* flags, uns64 required_squad_session_parameter_mask, uns64 required_group_session_parameter_mask);
47+
48+
//protected:
49+
bool setup_initial_participants(c_network_session* session);
50+
51+
public:
4552
bool test_flag(e_life_cycle_state_handler_flags flag);
4653

4754
//protected:

game/source/networking/logic/logic_matchmaking_desirability.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ struct s_matchmaking_session_player_properties
1414
};
1515
static_assert(sizeof(s_matchmaking_session_player_properties) == 0x8);
1616

17+
enum e_network_session_matchmaking_composition_flags
18+
{
19+
_network_session_matchmaking_composition_session_of_quitters_bit = 0,
20+
_network_session_matchmaking_composition_mixed_skill_bit,
21+
_network_session_matchmaking_composition_enable_mixed_skill_restriction_bit,
22+
_network_session_matchmaking_composition_valid_bit,
23+
24+
k_network_session_matchmaking_composition_flags_count,
25+
};
26+
27+
typedef c_flags_no_init<e_network_session_matchmaking_composition_flags, uns8, k_network_session_matchmaking_composition_flags_count> c_network_session_matchmaking_composition_flags;
28+
1729
struct s_matchmaking_session_properties
1830
{
1931
uns16 hopper_identifier;
@@ -34,7 +46,7 @@ struct s_matchmaking_session_properties
3446
e_gamer_region gamer_region;
3547
e_language language;
3648
e_online_nat_type nat_type;
37-
uns8 flags;
49+
c_network_session_matchmaking_composition_flags flags;
3850
};
3951
static_assert(sizeof(s_matchmaking_session_properties) == 0xC4);
4052

game/source/networking/logic/logic_matchmaking_seeker.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#include "networking/logic/logic_matchmaking_seeker.hpp"
22

3+
#include "memory/module.hpp"
4+
#include "networking/network_time.hpp"
5+
6+
HOOK_DECLARE_CLASS_MEMBER(0x004D4560, c_matchmaking_seeker, search_in_progress);
7+
38
c_matchmaking_seeker::c_matchmaking_seeker() :
49
m_flags(0),
510
m_current_session_search_index(),
@@ -21,3 +26,24 @@ c_matchmaking_seeker::c_matchmaking_seeker() :
2126
{
2227
}
2328

29+
bool c_matchmaking_seeker::get_session_to_join(s_suitable_matchmaking_session* session_out)
30+
{
31+
return INVOKE_CLASS_MEMBER(0x004D41F0, c_matchmaking_seeker, get_session_to_join, session_out);
32+
}
33+
34+
bool c_matchmaking_seeker::search_in_progress()
35+
{
36+
//return INVOKE_CLASS_MEMBER(0x004D4560, c_matchmaking_seeker, search_in_progress);
37+
38+
m_search_stage = _matchmaking_search_stage_any;
39+
m_session_searches[m_current_session_search_index].status.start_timestamp = network_time_get();
40+
41+
m_flags.set(_matchmaking_seeker_online_search_in_progress_bit, false);
42+
m_flags.set(_matchmaking_seeker_online_search_results_being_tracked_bit, false);
43+
m_flags.set(_matchmaking_seeker_search_failed_bit, false);
44+
45+
bool result;
46+
HOOK_INVOKE_CLASS_MEMBER(result =, c_matchmaking_seeker, search_in_progress);
47+
return result;
48+
}
49+

game/source/networking/logic/logic_matchmaking_seeker.hpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,40 @@
44
#include "networking/logic/life_cycle/life_cycle_matchmaking_quality.hpp"
55
#include "networking/logic/logic_matchmaking_desirability.hpp"
66

7-
//typedef c_flags<e_matchmaking_seeker_flags, uns8, k_matchmaking_seeker_search_flags_count> c_matchmaking_seeker_flags;
8-
typedef uns8 c_matchmaking_seeker_flags;
7+
struct s_suitable_matchmaking_session;
8+
9+
enum e_matchmaking_seeker_flags
10+
{
11+
_matchmaking_seeker_search_in_progress_bit = 0,
12+
_matchmaking_seeker_expect_local_machine_in_search_results_bit,
13+
_matchmaking_seeker_online_search_in_progress_bit,
14+
_matchmaking_seeker_online_search_failed_bit,
15+
_matchmaking_seeker_online_search_results_being_tracked_bit,
16+
_matchmaking_seeker_online_search_blocked_bit,
17+
_matchmaking_seeker_search_failed_bit,
18+
19+
k_matchmaking_seeker_search_flags_count,
20+
};
21+
typedef c_flags<e_matchmaking_seeker_flags, uns8, k_matchmaking_seeker_search_flags_count> c_matchmaking_seeker_flags;
22+
23+
enum e_matchmaking_search_stage
24+
{
25+
_matchmaking_search_stage_strict_skill = 0,
26+
_matchmaking_search_stage_skill,
27+
_matchmaking_search_stage_any,
28+
_matchmaking_search_stage_desparation,
29+
30+
k_matchmaking_search_stage_count,
31+
k_matchmaking_search_stage_bits = 2,
32+
};
933

1034
struct __declspec(align(8)) c_matchmaking_seeker
1135
{
1236
c_matchmaking_seeker();
1337

38+
bool get_session_to_join(s_suitable_matchmaking_session* session_out);
39+
bool search_in_progress();
40+
1441
c_matchmaking_seeker_flags m_flags;
1542
int32 m_current_session_search_index;
1643
int32 m_search_stage;

game/source/networking/logic/logic_session_tracker.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ bool c_session_tracker::add_session(char const* session_name, s_transport_sessio
9191

9292
tracked_session->flags.set(_session_tracker_session_valid_bit, true);
9393
m_session_count++;
94+
95+
// Matchmaking hack: We don't have a valid QoS payload from transport_qos_get_result,
96+
// but we can just set these to tru to skip the requirement for now.
97+
// $TODO: MM, Reimplement QoS payloads via API.
98+
tracked_session->qos_received[_transport_qos_type_probe_only] = true;
99+
tracked_session->qos_received[_transport_qos_type_default] = true;
100+
94101
return false;
95102
}
96103

0 commit comments

Comments
 (0)