Skip to content

Commit 4747efc

Browse files
committed
WIP Separating the controlled object snapshot apply.
1 parent 2c69555 commit 4747efc

10 files changed

Lines changed: 182 additions & 29 deletions

core/ensure.h

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ void _ns_print_flush_stdout();
4141

4242
/// Ensures `m_cond` is true.
4343
/// If `m_cond` is false the current function returns.
44-
#define ENSURE(m_cond) \
45-
if make_likely (m_cond) { \
46-
} else { \
47-
return; \
44+
#define ENSURE(m_cond) \
45+
if make_likely (m_cond) { \
46+
} else { \
47+
_ns_print_code_message(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is false.", "", NS::PrintMessageType::ERROR); \
48+
return; \
4849
}
4950

5051
/// Ensures `m_cond` is true.
@@ -58,10 +59,11 @@ void _ns_print_flush_stdout();
5859

5960
/// Ensures `m_cond` is true.
6061
/// If `m_cond` is false, the current function returns `m_retval`.
61-
#define ENSURE_V(m_cond, m_retval) \
62-
if make_likely (m_cond) { \
63-
} else { \
64-
return m_retval; \
62+
#define ENSURE_V(m_cond, m_retval) \
63+
if make_likely (m_cond) { \
64+
} else { \
65+
_ns_print_code_message(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is false. Returning: " _STR(m_retval), "", NS::PrintMessageType::ERROR); \
66+
return m_retval; \
6567
}
6668

6769
/// Ensures `m_cond` is true.
@@ -73,6 +75,24 @@ void _ns_print_flush_stdout();
7375
return m_retval; \
7476
}
7577

78+
/// Ensures `m_cond` is true.
79+
/// If `m_cond` is false the current function returns.
80+
#define ENSURE_CONTINUE(m_cond) \
81+
if make_likely (m_cond) { \
82+
} else { \
83+
_ns_print_code_message(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is false.", "", NS::PrintMessageType::ERROR); \
84+
continue; \
85+
}
86+
87+
/// Ensures `m_cond` is true.
88+
/// If `m_cond` is false the current function returns.
89+
#define ENSURE_CONTINUE_MSG(m_cond, m_msg) \
90+
if make_likely (m_cond) { \
91+
} else { \
92+
_ns_print_code_message(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is false.", m_msg, NS::PrintMessageType::ERROR); \
93+
continue; \
94+
}
95+
7696
#define ASSERT_NO_ENTRY() \
7797
_ns_print_code_message(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Ne entry triggered.", "", NS::PrintMessageType::ERROR); \
7898
_ns_print_flush_stdout(); \

core/object_data.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,29 @@
66

77
NS_NAMESPACE_BEGIN
88

9+
NameAndVar::NameAndVar(NameAndVar &&p_other) :
10+
name(std::move(p_other.name)),
11+
value(std::move(p_other.value)) {
12+
}
13+
14+
NameAndVar &NameAndVar::operator=(NameAndVar &&p_other) {
15+
name = std::move(p_other.name);
16+
value = std::move(p_other.value);
17+
return *this;
18+
}
19+
920
void NameAndVar::copy(const NameAndVar &p_nav) {
1021
name = p_nav.name;
1122
value.copy(p_nav.value);
1223
}
1324

25+
NameAndVar NameAndVar::make_copy(const NameAndVar &p_other) {
26+
NameAndVar named_var;
27+
named_var.name = p_other.name;
28+
named_var.value.copy(p_other.value);
29+
return named_var;
30+
}
31+
1432
VarDescriptor::VarDescriptor(VarId p_id, const std::string &p_name, VarData &&p_val, bool p_skip_rewinding, bool p_enabled) :
1533
id(p_id),
1634
skip_rewinding(p_skip_rewinding),

core/object_data.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@ struct NameAndVar {
1616
std::string name;
1717
VarData value;
1818

19+
NameAndVar() = default;
20+
21+
NameAndVar(const NameAndVar &) = delete;
22+
NameAndVar &operator=(const NameAndVar &) = delete;
23+
24+
NameAndVar(NameAndVar &&p_other);
25+
NameAndVar &operator=(NameAndVar &&p_other);
26+
1927
void copy(const NameAndVar &p_nav);
28+
static NameAndVar make_copy(const NameAndVar &p_other);
2029
};
2130

2231
struct VarDescriptor {

core/peer_networked_controller.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,15 @@ bool PlayerController::can_accept_new_inputs() const {
13391339

13401340
DollController::DollController(PeerNetworkedController *p_peer_controller) :
13411341
RemotelyControlledController(p_peer_controller) {
1342+
event_handler_received_snapshot = peer_controller->scene_synchronizer->event_received_snapshot.bind(
1343+
[this](const Snapshot &p_received_snapshot) -> void {
1344+
received_snapshot(p_received_snapshot);
1345+
});
1346+
}
1347+
1348+
DollController::~DollController() {
1349+
peer_controller->scene_synchronizer->event_received_snapshot.unbind(event_handler_received_snapshot);
1350+
event_handler_received_snapshot = NS::NullPHandler;
13421351
}
13431352

13441353
bool DollController::receive_inputs(const Vector<uint8_t> &p_data) {
@@ -1396,6 +1405,49 @@ bool DollController::receive_inputs(const Vector<uint8_t> &p_data) {
13961405
return success;
13971406
}
13981407

1408+
bool is_doll_snap_A_older(const DollController::DollSnapshot &p_snap_a, const DollController::DollSnapshot &p_snap_b) {
1409+
return p_snap_a.index < p_snap_b.index;
1410+
}
1411+
1412+
void DollController::received_snapshot(const Snapshot &p_snapshot) {
1413+
const std::vector<ObjectData *> *controlled_objects = peer_controller->scene_synchronizer->get_peer_controlled_objects_data(peer_controller->get_authority_peer());
1414+
if (!controlled_objects) {
1415+
// Nothing to store.
1416+
return;
1417+
}
1418+
1419+
if (last_checked_input != FrameIndex::NONE && last_checked_input >= p_snapshot.input_id) {
1420+
// Snapshot already checked, no need to store this.
1421+
return;
1422+
}
1423+
1424+
DollSnapshot *snap;
1425+
if (VecFunc::has(snapshots, DollSnapshot(p_snapshot.input_id))) {
1426+
std::vector<DollSnapshot>::iterator it = VecFunc::find(snapshots, DollSnapshot(p_snapshot.input_id));
1427+
snap = &*it;
1428+
} else {
1429+
snapshots.push_back(DollSnapshot(p_snapshot.input_id));
1430+
snap = &snapshots.back();
1431+
}
1432+
1433+
// This can't trigger because of the above check.
1434+
ASSERT_COND(snap->index == p_snapshot.input_id);
1435+
1436+
for (ObjectData *object_data : *controlled_objects) {
1437+
const std::vector<NameAndVar> *vars = p_snapshot.get_object_vars(object_data->get_net_id());
1438+
ENSURE_CONTINUE_MSG(vars, "The snapshot didn't contain the object: " + object_data->get_net_id() + ". If this error spams for a long period (5/10 seconds), it's a bug.");
1439+
std::map<ObjectNetId, std::vector<NameAndVar>>::iterator snap_object_vars = MapFunc::insert_if_new(snap->objects_vars, object_data->get_net_id(), std::vector<NameAndVar>());
1440+
for (const NameAndVar &nav : *vars) {
1441+
snap_object_vars->second.push_back(NameAndVar::make_copy(nav));
1442+
}
1443+
}
1444+
1445+
std::sort(
1446+
snapshots.begin(),
1447+
snapshots.end(),
1448+
is_doll_snap_A_older);
1449+
}
1450+
13991451
void DollController::queue_instant_process(FrameIndex p_frame_index, int p_index, int p_count) {
14001452
if (streaming_paused) {
14011453
return;
@@ -1482,7 +1534,7 @@ void DollController::notify_frame_checked(FrameIndex p_frame_index) {
14821534
return;
14831535
}
14841536

1485-
// Removes all the inputs older the known one (included).
1537+
// Removes all the inputs older than the known one (included).
14861538
while (frames_input.empty() == false && frames_input.front().id <= p_frame_index) {
14871539
if (frames_input.front().id == p_frame_index) {
14881540
// Pause the streaming if the last frame is empty.
@@ -1494,6 +1546,10 @@ void DollController::notify_frame_checked(FrameIndex p_frame_index) {
14941546
last_checked_input = p_frame_index;
14951547
}
14961548

1549+
void DollController::notify_applied_snapshot(FrameIndex frame_index, ObjectNetId p_id) {
1550+
ASSERT_NO_ENTRY(); // TODO implement.
1551+
}
1552+
14971553
NoNetController::NoNetController(PeerNetworkedController *p_peer_controller) :
14981554
Controller(p_peer_controller),
14991555
frame_id(FrameIndex{ 0 }) {

core/peer_networked_controller.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "core.h"
55
#include "net_utilities.h"
66
#include "processor.h"
7+
#include "snapshot.h"
78
#include <deque>
89

910
NS_NAMESPACE_BEGIN
@@ -369,17 +370,44 @@ struct PlayerController final : public Controller {
369370
/// After the execution of the inputs, the puppet start to act like the player,
370371
/// because it wait the player status from the server to correct its motion.
371372
struct DollController final : public RemotelyControlledController {
372-
DollController(PeerNetworkedController *p_node);
373+
public:
374+
struct DollSnapshot {
375+
FrameIndex index = FrameIndex::NONE;
376+
std::map<ObjectNetId, std::vector<NameAndVar>> objects_vars;
377+
378+
DollSnapshot() = default;
379+
DollSnapshot(DollSnapshot &&p_other) = default;
380+
DollSnapshot &operator=(DollSnapshot &&p_other) = default;
381+
382+
DollSnapshot(const DollSnapshot &p_other) = delete;
383+
DollSnapshot operator=(const DollSnapshot &p_other) = delete;
384+
385+
DollSnapshot(FrameIndex p_index) :
386+
index(p_index) {}
387+
388+
bool operator==(const DollSnapshot &p_other) const { return index == p_other.index; }
389+
};
373390

391+
public:
392+
NS::PHandler event_handler_received_snapshot = NS::NullPHandler;
374393
FrameIndex last_checked_input = FrameIndex::NONE;
375394
int queued_instant_to_process = -1;
395+
// Contains the controlled nodes frames snapshot.
396+
std::vector<DollSnapshot> snapshots;
397+
398+
public:
399+
DollController(PeerNetworkedController *p_node);
400+
~DollController();
376401

377402
virtual bool receive_inputs(const Vector<uint8_t> &p_data) override;
403+
void received_snapshot(const Snapshot &p_snapshot);
378404
virtual void queue_instant_process(FrameIndex p_input_id, int p_index, int p_count) override;
379405
virtual bool fetch_next_input(double p_delta) override;
380406
virtual void process(double p_delta) override;
381407
virtual void on_state_validated(FrameIndex p_frame_index) override;
382408
void notify_frame_checked(FrameIndex p_input_id);
409+
410+
void notify_applied_snapshot(FrameIndex frame_index, ObjectNetId p_id);
383411
};
384412

385413
/// This controller is used when the game instance is not a peer of any kind.

snapshot.cpp renamed to core/snapshot.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
#include "snapshot.h"
22

3-
#include "scene/main/node.h"
4-
#include "scene_synchronizer.h"
5-
#include <cstddef>
3+
#include "../scene_synchronizer.h"
64

7-
NS::Snapshot::operator String() const {
8-
String s;
9-
s += "Snapshot input ID: " + uitos(input_id.id);
5+
NS::Snapshot::operator std::string() const {
6+
std::string s;
7+
s += "Snapshot input ID: " + input_id;
108

119
for (std::size_t net_node_id = 0; net_node_id < object_vars.size(); net_node_id += 1) {
12-
s += "\nNode Data: " + itos(net_node_id);
10+
s += "\nObject Data: " + std::to_string(net_node_id);
1311
for (std::size_t i = 0; i < object_vars[net_node_id].size(); i += 1) {
1412
s += "\n|- Variable: ";
15-
s += object_vars[net_node_id][i].name.c_str();
13+
s += object_vars[net_node_id][i].name;
1614
s += " = ";
17-
s += SceneSynchronizerBase::var_data_stringify(object_vars[net_node_id][i].value).c_str();
15+
s += SceneSynchronizerBase::var_data_stringify(object_vars[net_node_id][i].value);
1816
}
1917
}
2018
s += "\nCUSTOM DATA:\n";
@@ -103,6 +101,13 @@ bool compare_vars(
103101
#endif
104102
}
105103

104+
const std::vector<NS::NameAndVar> *NS::Snapshot::get_object_vars(ObjectNetId p_id) const {
105+
if (object_vars.size() > p_id.id) {
106+
return &object_vars[p_id.id];
107+
}
108+
return nullptr;
109+
}
110+
106111
NS::Snapshot NS::Snapshot::make_copy(const Snapshot &p_other) {
107112
Snapshot s;
108113
s.copy(p_other);

snapshot.h renamed to core/snapshot.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#pragma once
22

3-
#include "core/object_data.h"
4-
#include "core/var_data.h"
5-
#include "core/net_utilities.h"
3+
#include "net_utilities.h"
4+
#include "object_data.h"
5+
#include "var_data.h"
66

77
namespace NS {
88
class SceneSynchronizerBase;
@@ -11,7 +11,7 @@ struct Snapshot {
1111
FrameIndex input_id = FrameIndex::NONE;
1212
std::vector<NS::ObjectNetId> simulated_objects;
1313
/// The Node variables in a particular frame. The order of this vector
14-
/// matters because the index is the `NetNodeId`.
14+
/// matters because the index is the `ObjectNetId`.
1515
/// The variable array order also matter.
1616
std::vector<std::vector<NameAndVar>> object_vars;
1717

@@ -22,7 +22,9 @@ struct Snapshot {
2222
VarData custom_data;
2323

2424
public:
25-
operator String() const;
25+
operator std::string() const;
26+
27+
const std::vector<NameAndVar> *get_object_vars(ObjectNetId p_id) const;
2628

2729
/// Copy the given snapshot.
2830
static Snapshot make_copy(const Snapshot &p_other);

godot4/gd_scene_synchronizer.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "modules/network_synchronizer/godot4/gd_network_interface.h"
1414
#include "modules/network_synchronizer/godot4/gd_scene_synchronizer.h"
1515
#include "modules/network_synchronizer/scene_synchronizer.h"
16-
#include "modules/network_synchronizer/snapshot.h"
1716
#include "scene/main/multiplayer_api.h"
1817
#include "scene/main/node.h"
1918
#include "scene/main/window.h"

scene_synchronizer.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
#include "core/object_data.h"
1111
#include "core/peer_networked_controller.h"
1212
#include "core/scene_synchronizer_debugger.h"
13+
#include "core/snapshot.h"
1314
#include "core/var_data.h"
1415
#include "data_buffer.h"
15-
#include "snapshot.h"
1616
#include <chrono>
1717
#include <limits>
1818
#include <string>
@@ -2479,6 +2479,8 @@ void ClientSynchronizer::receive_snapshot(DataBuffer &p_snapshot) {
24792479
return;
24802480
}
24812481

2482+
scene_synchronizer->event_received_snapshot.broadcast(last_received_snapshot);
2483+
24822484
// Finalize data.
24832485
store_controllers_snapshot(last_received_snapshot);
24842486
}
@@ -3665,10 +3667,23 @@ void ClientSynchronizer::apply_snapshot(
36653667
continue;
36663668
}
36673669

3670+
if (object_data->get_controlled_by_peer() > 0) {
3671+
PeerNetworkedController *controller = scene_synchronizer->get_controller_for_peer(object_data->get_controlled_by_peer(), false);
3672+
if (controller && controller->is_doll_controller()) {
3673+
// This object data is being controller by a doll controller;
3674+
// in this case the rewind is handled by the controller.
3675+
controller->get_doll_controller()->notify_applied_snapshot(p_snapshot.input_id, object_data->get_net_id());
3676+
if (r_applied_data_info) {
3677+
r_applied_data_info->push_back("Applied snapshot forwarded to DollController for the object: " + object_data->object_name);
3678+
}
3679+
continue;
3680+
}
3681+
}
3682+
36683683
const std::vector<NS::NameAndVar> &snap_object_vars = snap_objects_vars[net_node_id.id];
36693684

36703685
if (r_applied_data_info) {
3671-
r_applied_data_info->push_back("Applied snapshot data on the node: " + std::string(object_data->object_name.c_str()));
3686+
r_applied_data_info->push_back("Applied snapshot on the object: " + object_data->object_name);
36723687
}
36733688

36743689
// NOTE: The vars may not contain ALL the variables: it depends on how
@@ -3711,7 +3726,7 @@ void ClientSynchronizer::apply_snapshot(
37113726
object_data->app_object_handle,
37123727
variable_name.c_str(),
37133728
current_val);
3714-
ASSERT_COND_MSG(SceneSynchronizerBase::var_data_compare(current_val, snap_value), "There was a fatal error while setting the propertly `" + variable_name + "` on the object `" + object_data->object_name + "`. The set data differs from the property set by the NetSync: set data `" + scene_synchronizer->var_data_stringify(current_val, true).c_str() + "` NetSync data `" + scene_synchronizer->var_data_stringify(snap_value, true) + "`");
3729+
ASSERT_COND_MSG(SceneSynchronizerBase::var_data_compare(current_val, snap_value), "There was a fatal error while setting the propertly `" + variable_name + "` on the object `" + object_data->object_name + "`. The set data differs from the property set by the NetSync: set data `" + scene_synchronizer->var_data_stringify(current_val, true) + "` NetSync data `" + scene_synchronizer->var_data_stringify(snap_value, true) + "`");
37153730
}
37163731
#endif
37173732

scene_synchronizer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "core/network_interface.h"
66
#include "core/object_data_storage.h"
77
#include "core/processor.h"
8-
#include "snapshot.h"
8+
#include "core/snapshot.h"
99
#include <deque>
1010
#include <map>
1111
#include <optional>
@@ -220,6 +220,7 @@ class SceneSynchronizerBase {
220220
Processor<int /*p_peer*/, bool /*p_connected*/, bool /*p_enabled*/> event_peer_status_updated;
221221
Processor<FrameIndex, bool /*p_desync_detected*/> event_state_validated;
222222
Processor<FrameIndex, int /*p_peer*/> event_sent_snapshot;
223+
Processor<const Snapshot & /*p_received_snapshot*/> event_received_snapshot;
223224
Processor<FrameIndex, int /*p_index*/, int /*p_count*/> event_rewind_frame_begin;
224225
Processor<FrameIndex, ObjectHandle /*p_app_object_handle*/, const std::vector<std::string> & /*p_var_names*/, const std::vector<VarData> & /*p_client_values*/, const std::vector<VarData> & /*p_server_values*/> event_desync_detected_with_info;
225226

0 commit comments

Comments
 (0)