@@ -20,16 +20,13 @@ namespace NS_Test {
2020
2121const double delta = 1.0 / 60.0 ;
2222
23- class TDSLocalNetworkedController : public NS ::LocalSceneObject {
23+ class TDSControlledObject : public NS ::LocalSceneObject {
2424public:
2525 NS::ObjectLocalId local_id = NS::ObjectLocalId::NONE;
2626
27- TDSLocalNetworkedController () = default ;
27+ TDSControlledObject () = default ;
2828
2929 virtual void on_scene_entry () override {
30- // Setup the NetworkInterface.
31- set_xi (0 );
32-
3330 get_scene ()->scene_sync ->register_app_object (get_scene ()->scene_sync ->to_handle (this ));
3431 }
3532
@@ -43,40 +40,49 @@ class TDSLocalNetworkedController : public NS::LocalSceneObject {
4340 p_scene_sync.setup_controller (
4441 p_id,
4542 authoritative_peer_id,
46- [ this ]( double p_delta, DataBuffer &r_buffer) -> void { collect_inputs (p_delta, r_buffer); } ,
47- [ this ](DataBuffer &p_buffer) -> int { return count_input_size (p_buffer); } ,
48- [ this ](DataBuffer &p_buffer_A, DataBuffer &p_buffer_b) -> bool { return are_inputs_different (p_buffer_A, p_buffer_b); } ,
49- [ this ]( double p_delta, DataBuffer &p_buffer) -> void { controller_process (p_delta, p_buffer); } );
43+ std::bind (&TDSControlledObject::collect_inputs, this , std::placeholders::_1, std::placeholders::_2) ,
44+ std::bind (&TDSControlledObject::count_input_size, this , std::placeholders::_1) ,
45+ std::bind (&TDSControlledObject::are_inputs_different, this , std::placeholders::_1, std::placeholders::_2) ,
46+ std::bind (&TDSControlledObject::controller_process, this , std::placeholders::_1, std::placeholders::_2) );
5047
51- p_scene_sync.register_variable (p_id, " xi " );
48+ p_scene_sync.register_variable (p_id, " xy " );
5249 }
5350
54- void set_xi ( int p_xi ) {
51+ void set_xy ( float x, float y ) {
5552 NS::VarData vd;
56- vd.data .i32 = 1 ;
53+ vd.data .vec .x = x;
54+ vd.data .vec .y = y;
5755 vd.type = 0 ;
5856 NS::MapFunc::assign (variables, std::string(" xi" ), std::move(vd));
5957 }
6058
61- int get_xi () const {
59+ NS::VarData get_xy () const {
6260 const NS::VarData *vd = NS::MapFunc::get_or_null (variables, std::string (" xi" ));
6361 if (vd) {
64- return vd-> data . i32 ;
62+ return NS ::VarData::make_copy (*vd) ;
6563 } else {
66- return 0 ;
64+ return NS ::VarData ( 0 , 0 ) ;
6765 }
6866 }
6967
7068 // ------------------------------------------------- NetController interface
69+ bool previous_input = true ;
7170 void collect_inputs (double p_delta, DataBuffer &r_buffer) {
72- r_buffer.add (true );
71+ // Write true or false alternating each other.
72+ r_buffer.add (!previous_input);
73+ previous_input = !previous_input;
7374 }
7475
7576 void controller_process (double p_delta, DataBuffer &p_buffer) {
76- bool advance_xi;
77- p_buffer.read (advance_xi);
78- if (advance_xi) {
79- set_xi (get_xi () + 1 );
77+ bool advance_or_turn;
78+ p_buffer.read (advance_or_turn);
79+ NS::VarData current = get_xy ();
80+ if (advance_or_turn) {
81+ // Advance
82+ set_xy (current.data .vec .x + 1 , current.data .vec .y );
83+ } else {
84+ // Turn
85+ set_xy (current.data .vec .x , current.data .vec .y + 1 );
8086 }
8187 }
8288
@@ -95,18 +101,20 @@ class TDSLocalNetworkedController : public NS::LocalSceneObject {
95101// / This class is made in a way which allows to be overriden to test the sync
96102// / still works under bad network conditions.
97103struct TestDollSimulationBase {
104+ bool assert_if_desync = false ;
105+
98106 NS::LocalNetworkProps network_properties;
99107
100108 NS::LocalScene server_scene;
101109 NS::LocalScene peer_1_scene;
102110 NS::LocalScene peer_2_scene;
103- TDSLocalNetworkedController *controller_1_serv = nullptr ;
104- TDSLocalNetworkedController *controller_1_peer1 = nullptr ;
105- TDSLocalNetworkedController *controller_1_peer2 = nullptr ;
111+ TDSControlledObject *controlled_1_serv = nullptr ;
112+ TDSControlledObject *controlled_1_peer1 = nullptr ;
113+ TDSControlledObject *controlled_1_peer2 = nullptr ;
106114
107- TDSLocalNetworkedController *controller_2_serv = nullptr ;
108- TDSLocalNetworkedController *controller_2_peer1 = nullptr ;
109- TDSLocalNetworkedController *controller_2_peer2 = nullptr ;
115+ TDSControlledObject *controlled_2_serv = nullptr ;
116+ TDSControlledObject *controlled_2_peer1 = nullptr ;
117+ TDSControlledObject *controlled_2_peer2 = nullptr ;
110118
111119private:
112120 virtual void on_scenes_initialized () {}
@@ -142,13 +150,13 @@ struct TestDollSimulationBase {
142150 peer_2_scene.add_object <NS::LocalSceneSynchronizer>(" sync" , server_scene.get_peer ());
143151
144152 // Then compose the scene: 2 controllers.
145- controller_1_serv = server_scene.add_object <TDSLocalNetworkedController >(" controller_1" , peer_1_scene.get_peer ());
146- controller_1_peer1 = peer_1_scene.add_object <TDSLocalNetworkedController >(" controller_1" , peer_1_scene.get_peer ());
147- controller_1_peer2 = peer_2_scene.add_object <TDSLocalNetworkedController >(" controller_1" , peer_1_scene.get_peer ());
153+ controlled_1_serv = server_scene.add_object <TDSControlledObject >(" controller_1" , peer_1_scene.get_peer ());
154+ controlled_1_peer1 = peer_1_scene.add_object <TDSControlledObject >(" controller_1" , peer_1_scene.get_peer ());
155+ controlled_1_peer2 = peer_2_scene.add_object <TDSControlledObject >(" controller_1" , peer_1_scene.get_peer ());
148156
149- controller_2_serv = server_scene.add_object <TDSLocalNetworkedController >(" controller_2" , peer_2_scene.get_peer ());
150- controller_2_peer1 = peer_1_scene.add_object <TDSLocalNetworkedController >(" controller_2" , peer_2_scene.get_peer ());
151- controller_2_peer2 = peer_2_scene.add_object <TDSLocalNetworkedController >(" controller_2" , peer_2_scene.get_peer ());
157+ controlled_2_serv = server_scene.add_object <TDSControlledObject >(" controller_2" , peer_2_scene.get_peer ());
158+ controlled_2_peer1 = peer_1_scene.add_object <TDSControlledObject >(" controller_2" , peer_2_scene.get_peer ());
159+ controlled_2_peer2 = peer_2_scene.add_object <TDSControlledObject >(" controller_2" , peer_2_scene.get_peer ());
152160
153161 server_scene.scene_sync ->register_process (server_scene.scene_sync ->find_local_id (), PROCESS_PHASE_LATE, [=](double p_delta) -> void {
154162 on_server_process (p_delta);
@@ -160,16 +168,25 @@ struct TestDollSimulationBase {
160168 on_client_2_process (p_delta);
161169 });
162170
163- on_scenes_initialized ();
171+ if (assert_if_desync) {
172+ peer_1_scene.scene_sync ->event_state_validated .bind ([](NS::FrameIndex fi, bool p_desync_detected) -> void {
173+ ASSERT_COND (!p_desync_detected);
174+ });
175+ peer_2_scene.scene_sync ->event_state_validated .bind ([](NS::FrameIndex fi, bool p_desync_detected) -> void {
176+ ASSERT_COND (!p_desync_detected);
177+ });
178+ }
164179
165180 // Set the position of each object:
166- controller_1_serv->set_xi (100 );
167- controller_1_peer1->set_xi (100 );
168- controller_1_peer2->set_xi (100 );
181+ controlled_1_serv->set_xy (100 , 0 );
182+ controlled_1_peer1->set_xy (100 , 0 );
183+ controlled_1_peer2->set_xy (100 , 0 );
184+
185+ controlled_2_serv->set_xy (0 , 0 );
186+ controlled_2_peer1->set_xy (0 , 0 );
187+ controlled_2_peer2->set_xy (0 , 0 );
169188
170- controller_2_serv->set_xi (0 );
171- controller_2_peer1->set_xi (0 );
172- controller_2_peer2->set_xi (0 );
189+ on_scenes_initialized ();
173190 }
174191
175192 double rand_range (double M, double N) {
@@ -197,6 +214,62 @@ struct TestDollSimulationBase {
197214 }
198215};
199216
217+ struct TestDollSimulationWithoutReconciliation : public TestDollSimulationBase {
218+ virtual void on_scenes_initialized () override {
219+ // Notify instantly
220+ server_scene.scene_sync ->set_frame_confirmation_timespan (0.0 );
221+
222+ // Ensure the controllers are at their initial location as defined by the doll simulation class.
223+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_1_serv->get_xy (), NS::VarData (100 , 0 )));
224+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_1_peer1->get_xy (), NS::VarData (100 , 0 )));
225+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_1_peer2->get_xy (), NS::VarData (100 , 0 )));
226+
227+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_2_serv->get_xy (), NS::VarData (0 , 0 )));
228+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_2_peer2->get_xy (), NS::VarData (0 , 0 )));
229+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_2_peer1->get_xy (), NS::VarData (0 , 0 )));
230+ }
231+
232+ std::vector<NS::VarData> controlled_1_player_position;
233+ std::vector<NS::VarData> controlled_2_player_position;
234+
235+ virtual void on_scenes_processed (double p_delta) override {
236+ controlled_1_player_position.push_back (controlled_1_peer1->get_xy ());
237+ controlled_2_player_position.push_back (controlled_2_peer2->get_xy ());
238+
239+ const NS::FrameIndex controller_1_player_frame_index = peer_1_scene.scene_sync ->get_controller_for_peer (peer_1_scene.get_peer ())->get_current_frame_index ();
240+ const NS::FrameIndex controller_2_player_frame_index = peer_2_scene.scene_sync ->get_controller_for_peer (peer_2_scene.get_peer ())->get_current_frame_index ();
241+
242+ const NS::FrameIndex controller_2_doll_frame_index = peer_1_scene.scene_sync ->get_controller_for_peer (peer_2_scene.get_peer ())->get_current_frame_index ();
243+ const NS::FrameIndex controller_1_doll_frame_index = peer_2_scene.scene_sync ->get_controller_for_peer (peer_1_scene.get_peer ())->get_current_frame_index ();
244+
245+ if (controller_1_doll_frame_index != NS::FrameIndex::NONE) {
246+ // Make sure the players are always ahead the dolls.
247+ ASSERT_COND (controller_1_player_frame_index > controller_2_doll_frame_index);
248+ ASSERT_COND (controller_2_player_frame_index > controller_1_doll_frame_index);
249+
250+ // Verify the doll are at the exact location they were on the player.
251+ const NS::VarData doll_1_position = controlled_1_peer2->get_xy ();
252+ const NS::VarData doll_2_position = controlled_2_peer1->get_xy ();
253+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_1_player_position[controller_1_doll_frame_index.id ], doll_1_position));
254+ ASSERT_COND (NS::LocalSceneSynchronizer::var_data_compare (controlled_2_player_position[controller_2_doll_frame_index.id ], doll_2_position));
255+ }
256+
257+ int a = 0 ;
258+ }
259+ };
260+
261+ void test_simulation_without_reconciliation () {
262+ TestDollSimulationWithoutReconciliation test;
263+ // This test is not triggering any desynchronization.
264+ test.assert_if_desync = true ;
265+ test.init_test ();
266+
267+ test.do_test (100 );
268+
269+ // Asserted.
270+ ASSERT_COND (false );
271+ }
272+
200273void test_latency () {
201274 TestDollSimulationBase test;
202275 test.init_test ();
@@ -239,6 +312,11 @@ void test_latency() {
239312}
240313
241314void test_doll_simulation () {
315+ test_simulation_without_reconciliation ();
316+ // TODO test with latency.
317+ // TODO test with long confirmation time.
318+ // TODO test with reconciliation.
319+ // TODO test lag compensation.
242320 test_latency ();
243321}
244322
0 commit comments