1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2018 Joerg Henrichs
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 3
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 #include "items/network_item_manager.hpp"
20
21 #include "karts/abstract_kart.hpp"
22 #include "modes/world.hpp"
23 #include "network/network_config.hpp"
24 #include "network/network_string.hpp"
25 #include "network/protocols/game_protocol.hpp"
26 #include "network/rewind_manager.hpp"
27 #include "network/stk_host.hpp"
28 #include "network/stk_peer.hpp"
29
30 bool NetworkItemManager::m_network_item_debugging = false;
31 // ============================================================================
32 /** Creates a new instance of the item manager. This is done at startup
33 * of each race.
34 * We must save the item state first (so that it is restored first), otherwise
35 * state updates for a kart could be overwritten by e.g. simulating the item
36 * collection later (which resets bubblegum counter), so a rewinder uid of
37 * "I" which is less than "Kx" (kart rewinder with id x)
38 */
NetworkItemManager()39 NetworkItemManager::NetworkItemManager()
40 : Rewinder({RN_ITEM_MANAGER}), ItemManager()
41 {
42 m_confirmed_switch_ticks = -1;
43 m_last_confirmed_item_ticks.clear();
44 initServer();
45 } // NetworkItemManager
46
47 //-----------------------------------------------------------------------------
48 /** If this is a server, initializing the peers in game
49 */
initServer()50 void NetworkItemManager::initServer()
51 {
52 if (NetworkConfig::get()->isServer())
53 {
54 auto peers = STKHost::get()->getPeers();
55 for (auto& p : peers)
56 {
57 if (!p->isValidated() || p->isWaitingForGame())
58 continue;
59 m_last_confirmed_item_ticks[p] = 0;
60 }
61 }
62 } // initServer
63
64 //-----------------------------------------------------------------------------
65 /** Destructor. Cleans up all items and meshes stored.
66 */
~NetworkItemManager()67 NetworkItemManager::~NetworkItemManager()
68 {
69 for (ItemState* is : m_confirmed_state)
70 {
71 delete is;
72 }
73 } // ~NetworkItemManager
74
75 //-----------------------------------------------------------------------------
reset()76 void NetworkItemManager::reset()
77 {
78 m_confirmed_switch_ticks = -1;
79 ItemManager::reset();
80 } // reset
81
82 //-----------------------------------------------------------------------------
83 /** Called when a kart collects an item. In network games only the server
84 * acts on this event.
85 * \param item The item that was collected.
86 * \param kart The kart that collected the item.
87 */
collectedItem(ItemState * item,AbstractKart * kart)88 void NetworkItemManager::collectedItem(ItemState *item, AbstractKart *kart)
89 {
90 if (m_network_item_debugging)
91 Log::info("NIM", "collectedItem at %d index %d type %d ttr %d",
92 World::getWorld()->getTicksSinceStart(),
93 item->getItemId(), item->getType(), item->getTicksTillReturn());
94
95 if(NetworkConfig::get()->isServer())
96 {
97 ItemManager::collectedItem(item, kart);
98 // The server saves the collected item as item event info
99 m_item_events.lock();
100 m_item_events.getData().emplace_back(World::getWorld()->getTicksSinceStart(),
101 item->getItemId(),
102 kart->getWorldKartId(),
103 item->getTicksTillReturn());
104 m_item_events.unlock();
105 }
106 else
107 {
108 // The client predicts item collection:
109 ItemManager::collectedItem(item, kart);
110 }
111 } // collectedItem
112
113 // ----------------------------------------------------------------------------
114 /** Called when a switch is activated. On the server adds this information to
115 * the item state so it can be sent to all clients.
116 */
switchItems()117 void NetworkItemManager::switchItems()
118 {
119 if (NetworkConfig::get()->isServer())
120 {
121 // The server saves the collected item as item event info
122 m_item_events.lock();
123 // Create a switch event - the constructor called determines
124 // the type of the event automatically.
125 m_item_events.getData()
126 .emplace_back(World::getWorld()->getTicksSinceStart());
127 m_item_events.unlock();
128 }
129 ItemManager::switchItems();
130 } // switchItems
131
132 // ----------------------------------------------------------------------------
133 /** Called when a new item is created, e.g. bubble gum.
134 * \param type Type of the item.
135 * \param kart In case of a dropped item used to avoid that a kart
136 * is affected by its own items.
137 * \param server_xyz In case of rewind the server's position of this item.
138 * \param server_normal In case of rewind the server's normal of this item.
139 */
dropNewItem(ItemState::ItemType type,const AbstractKart * kart,const Vec3 * server_xyz,const Vec3 * server_normal)140 Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
141 const AbstractKart *kart,
142 const Vec3 *server_xyz,
143 const Vec3 *server_normal)
144 {
145 Item *item = ItemManager::dropNewItem(type, kart, server_xyz, server_normal);
146
147 if(!item) return NULL;
148
149 // Nothing else to do for client
150 if (NetworkConfig::get()->isClient()) return item;
151
152 assert(!server_xyz);
153 // Server: store the data for this event:
154 m_item_events.lock();
155 m_item_events.getData().emplace_back(World::getWorld()->getTicksSinceStart(),
156 type, item->getItemId(),
157 kart->getWorldKartId(),
158 item->getXYZ(),
159 item->getNormal());
160 m_item_events.unlock();
161 return item;
162 } // dropNewItem
163
164 // ----------------------------------------------------------------------------
165 /** Called by the GameProtocol when a confirmation for an item event is
166 * received by the server. Once all hosts have confirmed an event, it can be
167 * deleted and won't be sent to any clients again.
168 * \param peer Peer confirming the latest event time received.
169 * \param ticks Time at which the last event was received.
170 */
setItemConfirmationTime(std::weak_ptr<STKPeer> peer,int ticks)171 void NetworkItemManager::setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
172 int ticks)
173 {
174 assert(NetworkConfig::get()->isServer());
175 std::unique_lock<std::mutex> ul(m_live_players_mutex);
176 // Peer may get removed earlier if peer request to go back to lobby
177 if (m_last_confirmed_item_ticks.find(peer) !=
178 m_last_confirmed_item_ticks.end() &&
179 ticks > m_last_confirmed_item_ticks.at(peer))
180 m_last_confirmed_item_ticks.at(peer) = ticks;
181
182 // Now discard unneeded events and expired (disconnected) peer, i.e. all
183 // events that have been confirmed by all clients:
184 int min_time = std::numeric_limits<int32_t>::max();
185 for (auto it = m_last_confirmed_item_ticks.begin();
186 it != m_last_confirmed_item_ticks.end();)
187 {
188 if (it->first.expired())
189 {
190 it = m_last_confirmed_item_ticks.erase(it);
191 }
192 else
193 {
194 if (it->second < min_time) min_time = it->second;
195 it++;
196 }
197 }
198 ul.unlock();
199
200 // Find the last entry before the minimal confirmed time.
201 // Since the event list is sorted, all events up to this
202 // entry can be deleted.
203 m_item_events.lock();
204 auto p = m_item_events.getData().begin();
205 while (p != m_item_events.getData().end() && p->getTicks() < min_time)
206 p++;
207 m_item_events.getData().erase(m_item_events.getData().begin(), p);
208 m_item_events.unlock();
209
210 } // setItemConfirmationTime
211
212 //-----------------------------------------------------------------------------
213 /** Saves the state of all items. This is done by using a state that has
214 * been confirmed by all clients as a base, and then only adding any
215 * changes applied to that state later. As clients keep on confirming events
216 * the confirmed event will be moved forward in time, and older events can
217 * be deleted (and not sent to the clients anymore).
218 * This function is also called on the client in the first frame of a race
219 * to save the initial state, which is the first confirmed state by all
220 * clients.
221 */
saveState(std::vector<std::string> * ru)222 BareNetworkString* NetworkItemManager::saveState(std::vector<std::string>* ru)
223 {
224 ru->push_back(getUniqueIdentity());
225 // On the server:
226 // ==============
227 m_item_events.lock();
228 uint16_t n = (uint16_t)m_item_events.getData().size();
229 if(n==0)
230 {
231 BareNetworkString *s = new BareNetworkString();
232 m_item_events.unlock();
233 return s;
234 }
235
236 BareNetworkString *s =
237 new BareNetworkString(n * ( sizeof(int) + sizeof(uint16_t)
238 + sizeof(uint8_t) ) );
239 for (auto p : m_item_events.getData())
240 {
241 p.saveState(s);
242 }
243 m_item_events.unlock();
244 return s;
245 } // saveState
246
247 //-----------------------------------------------------------------------------
248 /** Progresses the time for all item by the given number of ticks. Used
249 * when computing a new state from a confirmed state.
250 * \param ticks Number of ticks that need to be simulated.
251 */
forwardTime(int ticks)252 void NetworkItemManager::forwardTime(int ticks)
253 {
254 int new_ticks = World::getWorld()->getTicksSinceStart() + ticks;
255 World::getWorld()->setTicksForRewind(new_ticks);
256
257 for(auto &i : m_confirmed_state)
258 {
259 if (i) i->update(ticks);
260 } // for m_all_items
261 if(m_switch_ticks>ticks)
262 m_switch_ticks -= ticks;
263 else if (m_switch_ticks >= 0)
264 {
265 switchItemsInternal(m_confirmed_state);
266 m_switch_ticks = -1;
267 }
268 } // forwardTime
269
270 //-----------------------------------------------------------------------------
271 /** Restores the state of the items to the current world time. It takes the
272 * last saved confirmed state, applies any updates from the server, and
273 * then syncs up the confirmed state to the in-race items.
274 * It uses exactly 'count' bytes of the message.
275 * \param buffer the state content.
276 * \param count Number of bytes used for this state.
277 */
restoreState(BareNetworkString * buffer,int count)278 void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
279 {
280 assert(NetworkConfig::get()->isClient());
281 // The state at World::getTicksSinceStart() needs to be restored. The
282 // confirmed state saved here was taken at m_confirmed_state_time
283 // (which is before getTicksSinceStart()). So first forward the confirmed
284 // state to the time we need to rewind to (i.e. getTicksSinceStart()).
285 // Then copy the new confirmed state to the current items. Any new
286 // items (dropped bubblegums) that have been predicted on a client
287 // and not been confirmed by the server data will be removed automatically
288 // at this stage. In more detail:
289 //
290 // 1) Apply all events included in this state to the confirmed state.
291 // It is possible that the server inludes events that have happened
292 // before the confirmed time on this client (the server keeps on
293 // sending all event updates till all clients have confirmed that
294 // that they have received them!!) - which will simply be ignored/
295 // This phase will only act on the confirmed ItemState in the
296 // NetworkItemManager, nothing in the ItemManager will be changed.
297 // a) When a collection event is found, adjust the confirmed item state
298 // only (this state will later be copied to the current items).
299 // It still call collected() in the item, which will update e.g.
300 // the previous owner, use up counter etc. for that item.
301 // b) When a new item is created, create an ItemState instance for
302 // this item, and put it in the confirmed state. Make sure the
303 // same index position is used.
304 // c) If a switch is used, this will be recorded in
305 // m_confirmed_switch_ticks.
306 //
307 // 2) Inform the server that those item events have been received.
308 // Once the server has received confirmation from all clients
309 // for events, they will not be resent anymore.
310 //
311 // 3) Once all new events have been applied to the confirmed state the
312 // time must be <= world time. Forward the confirmed state to
313 // world time (i.e. all confirmed items will get their ticksTillReturn
314 // value updated), and update m_confirmed_state_time to the world time.
315 //
316 // 4) Finally update the ItemManager state from the confirmed state:
317 // Any items that exist in both data structures will be updated.
318 // If an item exist in the ItemManager but not in the confirmed state
319 // of the NetworkItemManager, the item in the item manager will be
320 // delete - it was a predict item, which has not been confirmed by
321 // the server (e.g. a kart drops a bubble gum, and either the server
322 // has not received that event yet to confirm it, or perhaps the
323 // server detects that the kart did not even have a bubble gum).
324 // Similary, if an item is not in the confirmed state anymore,
325 // but in the ItemManager, it can mean that an item was collected
326 // on the server, which was not predicted. The item in the ItemManager
327 // will be deleted (if a kart has collected this item, the kart state
328 // will include the changed state information for the kart, so no need
329 // to update the kart for this).
330 //
331 // From here the replay can happen.
332
333
334 // 1) Apply all events to current confirmed state:
335 // -----------------------------------------------
336 World *world = World::getWorld();
337
338 // The world clock was set by the RewindManager to be the time
339 // of the state we are rewinding to. But the confirmed state of
340 // the network manager is before this (we are replaying item events
341 // since the last confirmed state in order to get a new confirmed state).
342 // So we need to reset the clock to the time of the confirmed state,
343 // and then forward this time accordingly. Getting the world time right
344 // during forwarding the item state is important since e.g. the bubble
345 // gum torque depends on the time. If the world time would be incorrect
346 // at the time the collection event happens, the torque would be
347 // predicted incorrectly, resulting in stuttering.
348
349 int current_time = m_confirmed_state_time;
350 // Reset the ItemManager's switch ticks to the value it had a the
351 // confirmed time:
352 m_switch_ticks = m_confirmed_switch_ticks;
353 int rewind_to_time = world->getTicksSinceStart(); // Save time we rewind to
354 world->setTicksForRewind(current_time);
355 bool has_state = count > 0;
356
357 // Note that the actual ItemManager states must NOT be changed here, only
358 // the confirmed states in the Network manager are allowed to be modified.
359 // They will all be copied to the ItemManager states after the loop.
360 while(count > 0)
361 {
362 // 1.1) Decode the event in the message
363 // ------------------------------------
364 ItemEventInfo iei(buffer, &count);
365 if(m_network_item_debugging)
366 Log::info("NIM", "Rewindto %d current %d iei.index %d iei tick %d iei.coll %d iei.new %d iei.ttr %d confirmed %lx",
367 rewind_to_time, current_time,
368 iei.getIndex(),
369 iei.getTicks(), iei.isItemCollection(), iei.isNewItem(),
370 iei.getTicksTillReturn(),
371 iei.getIndex() < (int)m_confirmed_state.size() && iei.getIndex() != -1 ?
372 m_confirmed_state[iei.getIndex()] : NULL);
373 // 1.2) If the event needs to be applied, forward
374 // the time to the time of this event:
375 // ----------------------------------------------
376 int dt = iei.getTicks() - current_time;
377
378 // Skip any events that are 'in the past' (i.e. have been sent again by
379 // the server because it has not yet received confirmation from all
380 // clients).
381 if(dt<0) continue;
382
383 // Forward the saved state:
384 if (dt>0) forwardTime(dt);
385
386 if(iei.isItemCollection())
387 {
388 int index = iei.getIndex();
389 // An item on the track was collected:
390 AbstractKart *kart = world->getKart(iei.getKartId());
391
392 assert(m_confirmed_state[index] != NULL);
393 m_confirmed_state[index]->collected(kart); // Collect item
394 // Reset till ticks return from state (required for eating banana with bomb)
395 int ttr = iei.getTicksTillReturn();
396 m_confirmed_state[index]->setTicksTillReturn(ttr);
397
398 if (m_confirmed_state[index]->isUsedUp())
399 {
400 delete m_confirmed_state[index];
401 m_confirmed_state[index] = NULL;
402 }
403 }
404 else if(iei.isNewItem())
405 {
406 AbstractKart *kart = world->getKart(iei.getKartId());
407 ItemState *is = new ItemState(iei.getNewItemType(), kart,
408 iei.getIndex() );
409 is->initItem(iei.getNewItemType(), iei.getXYZ(), iei.getNormal());
410 if (m_switch_ticks >= 0)
411 {
412 ItemState::ItemType new_type = m_switch_to[is->getType()];
413 is->switchTo(new_type);
414 }
415
416 // A new confirmed item must either be inserted at the end of all
417 // items, or in an existing unused entry.
418 if (m_confirmed_state.size() <= is->getItemId())
419 {
420 // In case that the server should send items in the wrong
421 // order, e.g. it sends an item for index n+2, then the item
422 // for index n -> we might need to add NULL item states
423 // into the state array to make sure the indices are correct.
424 while(m_confirmed_state.size()<is->getItemId())
425 m_confirmed_state.push_back(NULL);
426 m_confirmed_state.push_back(is);
427 }
428 else
429 {
430 // If the new item has an already existing index,
431 // the slot in the confirmed state array must be free
432 assert(m_confirmed_state[is->getItemId()] == NULL);
433 m_confirmed_state[is->getItemId()] = is;
434 }
435 }
436 else if(iei.isSwitch())
437 {
438 // Switch all confirmed items:
439 ItemManager::switchItemsInternal(m_confirmed_state);
440 }
441 else
442 {
443 Log::error("NetworkItemManager",
444 "Received unknown event type at %d",
445 iei.getTicks());
446 }
447 current_time = iei.getTicks();
448 } // while count >0
449
450
451 // 2. Update Server
452 // ================
453 // Inform the server which events have been received (if there has
454 // been any updates - no need to send messages if nothing has changed)
455
456 if (has_state)
457 {
458 if (auto gp = GameProtocol::lock())
459 gp->sendItemEventConfirmation(world->getTicksSinceStart());
460 }
461
462 // 3. Forward the confirmed item state to the world time
463 // =====================================================
464 int dt = rewind_to_time - current_time;
465 if(dt>0) forwardTime(dt);
466
467 // 4. Copy the confirmed state to the current item state
468 // ======================================================
469
470 // We need to test all items - and confirmed or all_items could
471 // be the larger group (confirmed: when a new item was dropped
472 // by a remote kart; all_items: if an item is predicted on
473 // the client, but not yet confirmed). So
474 size_t max_index = std::max(m_confirmed_state.size(),
475 m_all_items.size() );
476 m_all_items.resize(max_index, NULL);
477
478 for(unsigned int i=0; i<max_index; i++)
479 {
480 ItemState *item = m_all_items[i];
481 const ItemState *is = i < m_confirmed_state.size()
482 ? m_confirmed_state[i] : NULL;
483 // For every *(ItemState*)item = *is, all deactivated ticks, item id
484 // ... will be copied from item state to item
485 if (is && item)
486 {
487 *(ItemState*)item = *is;
488 }
489 else if (is && !item)
490 {
491 // A new item was dropped according to the server that is not
492 // yet part of the current state --> create new item
493 Vec3 xyz = is->getXYZ();
494 Vec3 normal = is->getNormal();
495 Item *item_new = dropNewItem(is->getType(), is->getPreviousOwner(),
496 &xyz, &normal );
497 *((ItemState*)item_new) = *is;
498 m_all_items[i] = item_new;
499 insertItemInQuad(item_new);
500 }
501 else if (!is && item)
502 {
503 deleteItemInQuad(item);
504 delete item;
505 m_all_items[i] = NULL;
506 }
507 } // for i < max_index
508 // Clean up the rest
509 m_all_items.resize(m_confirmed_state.size());
510
511 // Now set the clock back to the 'rewindto' time:
512 world->setTicksForRewind(rewind_to_time);
513
514 // Save the current local time as confirmed time
515 m_confirmed_state_time = world->getTicksSinceStart();
516 m_confirmed_switch_ticks = m_switch_ticks;
517 } // restoreState
518
519 //-----------------------------------------------------------------------------
520 /** Save all current items at current ticks in server for live join
521 */
saveCompleteState(BareNetworkString * buffer) const522 void NetworkItemManager::saveCompleteState(BareNetworkString* buffer) const
523 {
524 const uint32_t all_items = (uint32_t)m_all_items.size();
525 buffer->addUInt32(World::getWorld()->getTicksSinceStart())
526 .addUInt32(m_switch_ticks).addUInt32(all_items);
527 for (unsigned i = 0; i < all_items; i++)
528 {
529 if (m_all_items[i])
530 {
531 buffer->addUInt8(1);
532 m_all_items[i]->saveCompleteState(buffer);
533 }
534 else
535 buffer->addUInt8(0);
536 }
537 } // saveCompleteState
538
539 //-----------------------------------------------------------------------------
540 /** Restore all current items at current ticks in client for live join
541 * or at the start of a race.
542 */
restoreCompleteState(const BareNetworkString & buffer)543 void NetworkItemManager::restoreCompleteState(const BareNetworkString& buffer)
544 {
545 m_confirmed_state_time = buffer.getUInt32();
546 m_confirmed_switch_ticks = buffer.getUInt32();
547 uint32_t all_items = buffer.getUInt32();
548 for (ItemState* is : m_confirmed_state)
549 {
550 delete is;
551 }
552 m_confirmed_state.clear();
553 for (unsigned i = 0; i < all_items; i++)
554 {
555 const bool has_item = buffer.getUInt8() == 1;
556 if (has_item)
557 {
558 ItemState* is = new ItemState(buffer);
559 m_confirmed_state.push_back(is);
560 }
561 else
562 m_confirmed_state.push_back(NULL);
563 }
564 } // restoreCompleteState
565