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