Skip to content

Commit 3c13a27

Browse files
committed
Fixed SyncGroup bug and adds UnitTest that verifies the implementation.
1 parent 4593454 commit 3c13a27

9 files changed

Lines changed: 386 additions & 72 deletions

core/core.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ const char *get_process_phase_name(ProcessPhase pp) {
3232

3333
std::string get_log_level_txt(NS::PrintMessageType p_level) {
3434
std::string log_level_str = "";
35-
if (NS::PrintMessageType::INFO == p_level) {
35+
if (NS::PrintMessageType::VERBOSE == p_level) {
36+
log_level_str = "[VERBOSE] ";
37+
} else if (NS::PrintMessageType::INFO == p_level) {
3638
log_level_str = "[INFO] ";
3739
} else if (NS::PrintMessageType::WARNING == p_level) {
3840
log_level_str = "[WARNING] ";
3941
} else if (NS::PrintMessageType::ERROR == p_level) {
4042
log_level_str = "[ERROR] ";
41-
} else if (NS::PrintMessageType::__INTERNAL == p_level) {
42-
log_level_str = "";
4343
}
4444
return log_level_str;
4545
}

core/core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const char *get_process_phase_name(ProcessPhase pp);
7171
NS_NAMESPACE_BEGIN
7272

7373
enum PrintMessageType : std::uint8_t {
74-
__INTERNAL = 0,
74+
VERBOSE = 0,
7575
INFO = 1,
7676
WARNING = 2,
7777
ERROR = 3,

godot4/gd_scene_synchronizer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,15 +649,15 @@ const NS::SyncGroup *GdSceneSynchronizer::sync_group_get(uint32_t p_group_id) co
649649
}
650650

651651
void GdSceneSynchronizer::sync_group_add_node_by_id(uint32_t p_net_id, uint32_t p_group_id, bool p_realtime) {
652-
scene_synchronizer.sync_group_add_object_by_id({ p_net_id }, NS::SyncGroupId{ p_group_id }, p_realtime);
652+
scene_synchronizer.sync_group_add_object(NS::ObjectNetId{ p_net_id }, NS::SyncGroupId{ p_group_id }, p_realtime);
653653
}
654654

655655
void GdSceneSynchronizer::sync_group_add_node(NS::ObjectData *p_object_data, uint32_t p_group_id, bool p_realtime) {
656656
scene_synchronizer.sync_group_add_object(p_object_data, NS::SyncGroupId{ p_group_id }, p_realtime);
657657
}
658658

659659
void GdSceneSynchronizer::sync_group_remove_node_by_id(uint32_t p_net_id, uint32_t p_group_id) {
660-
scene_synchronizer.sync_group_remove_object_by_id({ p_net_id }, NS::SyncGroupId{ p_group_id });
660+
scene_synchronizer.sync_group_remove_object(NS::ObjectNetId{ p_net_id }, NS::SyncGroupId{ p_group_id });
661661
}
662662

663663
void GdSceneSynchronizer::sync_group_remove_node(NS::ObjectData *p_object_data, uint32_t p_group_id) {

net_utilities.cpp

Lines changed: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -63,33 +63,12 @@ void NS::SyncGroup::mark_changes_as_notified() {
6363

6464
void NS::SyncGroup::add_listening_peer(int p_peer) {
6565
NS::VecFunc::insert_unique(listening_peers, p_peer);
66-
if (NS::VecFunc::insert_unique(networked_peers, p_peer)) {
67-
NS::VecFunc::insert_unique(peers_with_newly_calculated_latency, p_peer);
68-
}
69-
70-
// Make all the controlled objects as simulated.
71-
const std::vector<ObjectData *> *controlled_objects_ptr = scene_sync->get_peer_controlled_objects_data(p_peer);
72-
if (controlled_objects_ptr) {
73-
for (ObjectData *od : (*controlled_objects_ptr)) {
74-
add_new_sync_object(od, true);
75-
}
76-
}
77-
78-
notify_controllers_about_simulating_peer(p_peer, true);
66+
notify_simulating_peers_about_listener_status(p_peer, true);
7967
}
8068

8169
void NS::SyncGroup::remove_listening_peer(int p_peer) {
8270
NS::VecFunc::remove_unordered(listening_peers, p_peer);
83-
84-
// Remove all the controlled objects.
85-
const std::vector<ObjectData *> *controlled_objects_ptr = scene_sync->get_peer_controlled_objects_data(p_peer);
86-
if (controlled_objects_ptr) {
87-
for (ObjectData *od : (*controlled_objects_ptr)) {
88-
remove_sync_object(*od);
89-
}
90-
}
91-
92-
notify_controllers_about_simulating_peer(p_peer, false);
71+
notify_simulating_peers_about_listener_status(p_peer, false);
9372
}
9473

9574
uint32_t NS::SyncGroup::add_new_sync_object(ObjectData *p_object_data, bool p_is_simulated) {
@@ -100,13 +79,6 @@ uint32_t NS::SyncGroup::add_new_sync_object(ObjectData *p_object_data, bool p_is
10079
if (NS::VecFunc::insert_unique(networked_peers, peer)) {
10180
NS::VecFunc::insert_unique(peers_with_newly_calculated_latency, peer);
10281
}
103-
104-
const bool is_listener_controlled = NS::VecFunc::has(listening_peers, peer);
105-
if (is_listener_controlled && !p_is_simulated) {
106-
// This object is controlled by a listener, so it's always simulated.
107-
p_is_simulated = true;
108-
SceneSynchronizerDebugger::singleton()->print(NS::WARNING, "The object `" + p_object_data->object_name + "` is being controlled by a peer listening to this sync group, so it can't be made non simulating.");
109-
}
11082
}
11183

11284
if (p_is_simulated) {
@@ -133,7 +105,8 @@ uint32_t NS::SyncGroup::add_new_sync_object(ObjectData *p_object_data, bool p_is
133105
}
134106

135107
if (p_object_data->get_controlled_by_peer() > 0) {
136-
notify_controller_about_simulating_peers(p_object_data->get_controlled_by_peer(), true);
108+
VecFunc::insert_unique(simulating_peers, p_object_data->get_controlled_by_peer());
109+
update_listeners_to_simulating_peer(p_object_data->get_controlled_by_peer(), true);
137110
}
138111
}
139112

@@ -172,9 +145,6 @@ void NS::SyncGroup::remove_sync_object(std::size_t p_index, bool p_is_simulated)
172145
}
173146
}
174147

175-
const bool is_listener_controlled = NS::VecFunc::has(listening_peers, associted_peer);
176-
ENSURE_MSG(!is_listener_controlled, "It's not possible to remove an object controlled by a listening peer from sync group.");
177-
178148
if (p_is_simulated) {
179149
simulated_sync_objects.remove_at_unordered(p_index);
180150
simulated_sync_objects_list_changed = true;
@@ -212,8 +182,9 @@ void NS::SyncGroup::remove_sync_object(std::size_t p_index, bool p_is_simulated)
212182
}
213183

214184
if (!is_simulating) {
215-
// No other objects associated to this peer are simulated, so notify the peer as non simulating.
216-
notify_controller_about_simulating_peers(associted_peer, false);
185+
// No other objects associated to this peer are simulated, remove from simulating peers.
186+
VecFunc::remove_unordered(simulating_peers, associted_peer);
187+
update_listeners_to_simulating_peer(associted_peer, false);
217188
}
218189

219190
if (!is_networking) {
@@ -353,20 +324,17 @@ void NS::SyncGroup::notify_peer_has_newly_calculated_latency(int p_peer) {
353324
}
354325
}
355326

356-
void NS::SyncGroup::notify_controller_about_simulating_peers(int p_peer_controller, bool p_simulating) {
357-
NS::NetworkedControllerBase *controller = scene_sync->get_controller_for_peer(p_peer_controller);
358-
if (controller) {
359-
// This is a controller, notify about simulating peers.
360-
for (int peer : listening_peers) {
361-
controller->server_set_peer_simulating_this_controller(peer, p_simulating);
362-
}
327+
void NS::SyncGroup::notify_simulating_peers_about_listener_status(int p_peer_listener, bool p_simulating) {
328+
for (int peer : simulating_peers) {
329+
NetworkedControllerBase *controller = scene_sync->get_controller_for_peer(peer);
330+
controller->server_set_peer_simulating_this_controller(p_peer_listener, p_simulating);
363331
}
364332
}
365333

366-
void NS::SyncGroup::notify_controllers_about_simulating_peer(int p_peer, bool p_simulating) {
367-
for (const int listening_peer : listening_peers) {
368-
NetworkedControllerBase *controller = scene_sync->get_controller_for_peer(listening_peer, false);
369-
controller->server_set_peer_simulating_this_controller(p_peer, p_simulating);
334+
void NS::SyncGroup::update_listeners_to_simulating_peer(int p_simulating_peer, bool p_simulating) {
335+
NetworkedControllerBase *controller = scene_sync->get_controller_for_peer(p_simulating_peer);
336+
for (int peer : listening_peers) {
337+
controller->server_set_peer_simulating_this_controller(peer, p_simulating);
370338
}
371339
}
372340

net_utilities.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "core/core.h"
77
#include "core/processor.h"
88
#include "core/var_data.h"
9+
#include "modules/network_synchronizer/core/core.h"
910
#include <chrono>
1011
#include <map>
1112
#include <memory>
@@ -523,6 +524,7 @@ struct SyncGroup {
523524
};
524525

525526
public:
527+
SyncGroupId group_id = SyncGroupId::NONE;
526528
SceneSynchronizerBase *scene_sync = nullptr;
527529

528530
private:
@@ -533,7 +535,13 @@ struct SyncGroup {
533535
LocalVector<TrickledObjectInfo> trickled_sync_objects;
534536

535537
/// Contains the list of peers being networked by this sync group.
538+
/// In other terms, if an object controller by peer 76 is contained into
539+
/// the simulated or trickled list that peer is into this array.
536540
std::vector<int> networked_peers;
541+
/// The list of peers that have at least one objects into the simulated
542+
/// vector.
543+
std::vector<int> simulating_peers;
544+
/// The peers for which the server measured the latency.
537545
std::vector<int> peers_with_newly_calculated_latency;
538546

539547
std::vector<int> listening_peers;
@@ -558,6 +566,8 @@ struct SyncGroup {
558566
void remove_listening_peer(int p_peer);
559567
const std::vector<int> &get_listening_peers() const { return listening_peers; };
560568

569+
const std::vector<int> &get_simulating_peers() const { return simulating_peers; }
570+
561571
/// Returns the `index` or `UINT32_MAX` on error.
562572
uint32_t add_new_sync_object(struct ObjectData *p_object_data, bool p_is_simulated);
563573
void remove_sync_object(std::size_t p_index, bool p_is_simulated);
@@ -575,10 +585,13 @@ struct SyncGroup {
575585

576586
void notify_peer_has_newly_calculated_latency(int p_peer);
577587

578-
private:
579-
void notify_controller_about_simulating_peers(int p_peer, bool p_simulating);
580-
void notify_controllers_about_simulating_peer(int p_peer, bool p_simulating);
588+
// Used when a new listener is added or removed.
589+
void notify_simulating_peers_about_listener_status(int p_peer_listener, bool p_simulating);
590+
// Used when a new simulated object (which is controlled) is added, to notify
591+
// such controller about the listeners.
592+
void update_listeners_to_simulating_peer(int p_simulating_peer, bool p_simulating);
581593

594+
private:
582595
std::size_t find_simulated(const struct ObjectData &p_object_data) const;
583596
std::size_t find_trickled(const struct ObjectData &p_object_data) const;
584597
};

scene_synchronizer.cpp

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,13 @@ const NS::SyncGroup *SceneSynchronizerBase::sync_group_get(SyncGroupId p_group_i
686686
return static_cast<ServerSynchronizer *>(synchronizer)->sync_group_get(p_group_id);
687687
}
688688

689-
void SceneSynchronizerBase::sync_group_add_object_by_id(ObjectNetId p_node_id, SyncGroupId p_group_id, bool p_realtime) {
690-
NS::ObjectData *nd = get_object_data(p_node_id);
689+
void SceneSynchronizerBase::sync_group_add_object(ObjectLocalId p_id, SyncGroupId p_group_id, bool p_realtime) {
690+
NS::ObjectData *nd = get_object_data(p_id);
691+
sync_group_add_object(nd, p_group_id, p_realtime);
692+
}
693+
694+
void SceneSynchronizerBase::sync_group_add_object(ObjectNetId p_id, SyncGroupId p_group_id, bool p_realtime) {
695+
NS::ObjectData *nd = get_object_data(p_id);
691696
sync_group_add_object(nd, p_group_id, p_realtime);
692697
}
693698

@@ -696,8 +701,13 @@ void SceneSynchronizerBase::sync_group_add_object(NS::ObjectData *p_object_data,
696701
static_cast<ServerSynchronizer *>(synchronizer)->sync_group_add_object(p_object_data, p_group_id, p_realtime);
697702
}
698703

699-
void SceneSynchronizerBase::sync_group_remove_object_by_id(ObjectNetId p_node_id, SyncGroupId p_group_id) {
700-
NS::ObjectData *nd = get_object_data(p_node_id);
704+
void SceneSynchronizerBase::sync_group_remove_object(ObjectLocalId p_id, SyncGroupId p_group_id) {
705+
NS::ObjectData *nd = get_object_data(p_id);
706+
sync_group_remove_object(nd, p_group_id);
707+
}
708+
709+
void SceneSynchronizerBase::sync_group_remove_object(ObjectNetId p_id, SyncGroupId p_group_id) {
710+
NS::ObjectData *nd = get_object_data(p_id);
701711
sync_group_remove_object(nd, p_group_id);
702712
}
703713

@@ -706,6 +716,21 @@ void SceneSynchronizerBase::sync_group_remove_object(NS::ObjectData *p_object_da
706716
static_cast<ServerSynchronizer *>(synchronizer)->sync_group_remove_object(p_object_data, p_group_id);
707717
}
708718

719+
void SceneSynchronizerBase::sync_group_fetch_object_grups(NS::ObjectLocalId p_id, std::vector<SyncGroupId> &r_simulated_groups, std::vector<SyncGroupId> &r_trickled_groups) const {
720+
const NS::ObjectData *object_data = get_object_data(p_id);
721+
sync_group_fetch_object_grups(object_data, r_simulated_groups, r_trickled_groups);
722+
}
723+
724+
void SceneSynchronizerBase::sync_group_fetch_object_grups(NS::ObjectNetId p_id, std::vector<SyncGroupId> &r_simulated_groups, std::vector<SyncGroupId> &r_trickled_groups) const {
725+
const NS::ObjectData *object_data = get_object_data(p_id);
726+
sync_group_fetch_object_grups(object_data, r_simulated_groups, r_trickled_groups);
727+
}
728+
729+
void SceneSynchronizerBase::sync_group_fetch_object_grups(const NS::ObjectData *p_object_data, std::vector<SyncGroupId> &r_simulated_groups, std::vector<SyncGroupId> &r_trickled_groups) const {
730+
ENSURE_MSG(is_server(), "This function CAN be used only on the server.");
731+
static_cast<ServerSynchronizer *>(synchronizer)->sync_group_fetch_object_grups(p_object_data, r_simulated_groups, r_trickled_groups);
732+
}
733+
709734
void SceneSynchronizerBase::sync_group_replace_objects(SyncGroupId p_group_id, LocalVector<NS::SyncGroup::SimulatedObjectInfo> &&p_new_realtime_nodes, LocalVector<NS::SyncGroup::TrickledObjectInfo> &&p_new_trickled_nodes) {
710735
ENSURE_MSG(is_server(), "This function CAN be used only on the server.");
711736
static_cast<ServerSynchronizer *>(synchronizer)->sync_group_replace_object(p_group_id, std::move(p_new_realtime_nodes), std::move(p_new_trickled_nodes));
@@ -748,6 +773,11 @@ const std::vector<int> *SceneSynchronizerBase::sync_group_get_listening_peers(Sy
748773
return static_cast<ServerSynchronizer *>(synchronizer)->sync_group_get_listening_peers(p_group_id);
749774
}
750775

776+
const std::vector<int> *SceneSynchronizerBase::sync_group_get_simulating_peers(SyncGroupId p_group_id) const {
777+
ENSURE_V_MSG(is_server(), nullptr, "This function CAN be used only on the server.");
778+
return static_cast<ServerSynchronizer *>(synchronizer)->sync_group_get_simulating_peers(p_group_id);
779+
}
780+
751781
void SceneSynchronizerBase::sync_group_set_trickled_update_rate(ObjectLocalId p_node_id, SyncGroupId p_group_id, float p_update_rate) {
752782
NS::ObjectData *od = get_object_data(p_node_id);
753783
ENSURE_MSG(is_server(), "This function CAN be used only on the server.");
@@ -1769,6 +1799,7 @@ SyncGroupId ServerSynchronizer::sync_group_create() {
17691799
SyncGroupId id;
17701800
id.id = sync_groups.size();
17711801
sync_groups.resize(id.id + 1);
1802+
sync_groups[id.id].group_id = id;
17721803
sync_groups[id.id].scene_sync = scene_synchronizer;
17731804
return id;
17741805
}
@@ -1779,19 +1810,39 @@ const NS::SyncGroup *ServerSynchronizer::sync_group_get(SyncGroupId p_group_id)
17791810
}
17801811

17811812
void ServerSynchronizer::sync_group_add_object(NS::ObjectData *p_object_data, SyncGroupId p_group_id, bool p_realtime) {
1782-
ERR_FAIL_COND(p_object_data == nullptr);
1813+
ENSURE(p_object_data);
17831814
ERR_FAIL_COND_MSG(p_group_id.id >= sync_groups.size(), "The group id `" + itos(p_group_id.id) + "` doesn't exist.");
17841815
ERR_FAIL_COND_MSG(p_group_id == SyncGroupId::GLOBAL, "You can't change this SyncGroup in any way. Create a new one.");
17851816
sync_groups[p_group_id.id].add_new_sync_object(p_object_data, p_realtime);
17861817
}
17871818

17881819
void ServerSynchronizer::sync_group_remove_object(NS::ObjectData *p_object_data, SyncGroupId p_group_id) {
1789-
ERR_FAIL_COND(p_object_data == nullptr);
17901820
ERR_FAIL_COND_MSG(p_group_id.id >= sync_groups.size(), "The group id `" + itos(p_group_id.id) + "` doesn't exist.");
1821+
ENSURE(p_object_data);
17911822
ERR_FAIL_COND_MSG(p_group_id == SyncGroupId::GLOBAL, "You can't change this SyncGroup in any way. Create a new one.");
17921823
sync_groups[p_group_id.id].remove_sync_object(*p_object_data);
17931824
}
17941825

1826+
void ServerSynchronizer::sync_group_fetch_object_grups(const ObjectData *p_object_data, std::vector<SyncGroupId> &r_simulated_groups, std::vector<SyncGroupId> &r_trickled_groups) const {
1827+
ENSURE(p_object_data);
1828+
1829+
r_simulated_groups.clear();
1830+
r_trickled_groups.clear();
1831+
1832+
SyncGroupId id = { 0 };
1833+
for (const SyncGroup &group : sync_groups) {
1834+
if (group.get_simulated_sync_objects().find(SyncGroup::SimulatedObjectInfo(const_cast<ObjectData *>(p_object_data))) != -1) {
1835+
r_simulated_groups.push_back(id);
1836+
}
1837+
1838+
if (group.get_trickled_sync_objects().find(SyncGroup::TrickledObjectInfo(const_cast<ObjectData *>(p_object_data))) != -1) {
1839+
r_trickled_groups.push_back(id);
1840+
}
1841+
1842+
id += 1;
1843+
}
1844+
}
1845+
17951846
void ServerSynchronizer::sync_group_replace_object(SyncGroupId p_group_id, LocalVector<NS::SyncGroup::SimulatedObjectInfo> &&p_new_realtime_nodes, LocalVector<NS::SyncGroup::TrickledObjectInfo> &&p_new_trickled_nodes) {
17961847
ERR_FAIL_COND_MSG(p_group_id.id >= sync_groups.size(), "The group id `" + itos(p_group_id.id) + "` doesn't exist.");
17971848
ERR_FAIL_COND_MSG(p_group_id == SyncGroupId::GLOBAL, "You can't change this SyncGroup in any way. Create a new one.");
@@ -1834,10 +1885,15 @@ void ServerSynchronizer::sync_group_update(int p_peer_id) {
18341885
}
18351886

18361887
const std::vector<int> *ServerSynchronizer::sync_group_get_listening_peers(SyncGroupId p_group_id) const {
1837-
ERR_FAIL_COND_V_MSG(p_group_id.id >= sync_groups.size(), nullptr, "The group id `" + itos(p_group_id.id) + "` doesn't exist.");
1888+
ENSURE_V_MSG(p_group_id.id < sync_groups.size(), nullptr, "The group id `" + std::string(p_group_id) + "` doesn't exist.");
18381889
return &sync_groups[p_group_id.id].get_listening_peers();
18391890
}
18401891

1892+
const std::vector<int> *ServerSynchronizer::sync_group_get_simulating_peers(SyncGroupId p_group_id) const {
1893+
ENSURE_V_MSG(p_group_id.id < sync_groups.size(), nullptr, "The group id `" + std::string(p_group_id) + "` doesn't exist.");
1894+
return &sync_groups[p_group_id.id].get_simulating_peers();
1895+
}
1896+
18411897
void ServerSynchronizer::set_peer_networking_enable(int p_peer, bool p_enable) {
18421898
PeerData *pd = MapFunc::get_or_null(scene_synchronizer->peer_data, p_peer);
18431899
ENSURE(pd);
@@ -2622,7 +2678,7 @@ void ClientSynchronizer::process_received_server_state() {
26222678
if (need_rewind) {
26232679
SceneSynchronizerDebugger::singleton()->notify_event(SceneSynchronizerDebugger::FrameEvent::CLIENT_DESYNC_DETECTED);
26242680
SceneSynchronizerDebugger::singleton()->print(
2625-
__INTERNAL,
2681+
VERBOSE,
26262682
std::string("Recover input: ") + std::string(last_checked_input) + " - Last input: " + std::string(inner_player_controller->get_stored_frame_index(-1)),
26272683
scene_synchronizer->get_network_interface().get_owner_name());
26282684

0 commit comments

Comments
 (0)