1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2013 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 #ifndef HEADER_REWIND_MANAGER_HPP
20 #define HEADER_REWIND_MANAGER_HPP
21 
22 #include "network/rewind_queue.hpp"
23 #include "utils/stk_process.hpp"
24 
25 #include <assert.h>
26 #include <atomic>
27 #include <functional>
28 #include <memory>
29 #include <map>
30 #include <set>
31 #include <string>
32 #include <vector>
33 
34 class Rewinder;
35 class RewindInfo;
36 class RewindInfoEventFunction;
37 class EventRewinder;
38 
39 /** \ingroup network
40  *  This class manages rewinding. It keeps track of:
41  *  -  states for each rewindable object (for example a kart would have
42  *     its position, rotation, linear and angular velocity etc as state)
43  *     States can be confirmed (i.e. were received by the network server
44  *     and are therefore confirmed to be conrrect), or not (just a snapshot
45  *     on this client, which can save time in rewinding later).
46  *  -  events for each rewindable object (for example any change in the kart
47  *     controls, like steering, fire, ... are an event). While states can be
48  *     discarded (especially unconfirmed ones), e.g. to save space, events
49  *     will always be kept (in order to allow replaying).
50  *  For each object that is to be rewinded an instance of Rewinder needs to be
51  *  declared (usually inside of the object it can rewind). This instance
52  *  is automatically registered with the RewindManager.
53  *  All states and events are stored in a RewindInfo object. All RewindInfo
54  *  objects are stored in a list sorted by time.
55  *  When a rewind to time T is requested, the following takes place:
56  *  1. Go back in time:
57  *     Determine the latest time t_min < T so that each rewindable objects
58  *     has at least one state before T. For each state that is skipped during
59  *     this process `undoState()` is being called, and for each event
60  *     `undoEvent()` of the Rewinder.
61  *  2. Restore state at time `t_min`
62  *     For each Rewinder the state at time t_min is restored by calling
63  *     `rewindToState(char *)`.
64  *     TODO: atm there is no guarantee that each object will have a state
65  *     at a given time. We either need to work around that, or make sure
66  *     to store at least an unconfirmed state whenever we receive a
67  *     confirmed state.
68  *  3. Rerun the simulation till the current time t_current is reached:
69  *     1. Determine the time `t_next` of the next frame. This is either
70  *        current_time + 1/60 (physics default time step size), or less
71  *        if RewindInfo at an earlier time is available).
72  *        This determines the time step size for the next frame (i.e.
73  *        `t_next - t_current`).
74  *     2. For all RewindInfo at time t_next call:
75  *        - `restoreState()` if the RewindInfo is a confirmed state
76  *        - `discardState()` if the RewindInfo is an unconfirmed state
77  *          TODO: still missing, and instead of discard perhaps
78  *                store a new state??
79  *        - `rewindToEvent()` if the RewindInfo is an event
80  *     3. Do one step of world simulation, using the updated (confirmed)
81  *        states and newly set events (e.g. kart input).
82  */
83 
84 class RewindManager
85 {
86 private:
87     /** Singleton pointer. */
88     static RewindManager *m_rewind_manager[PT_COUNT];
89 
90     /** En- or Disable the rewind manager. This is used to disable storing
91      *  rewind data in case of local races only. */
92     static std::atomic_bool m_enable_rewind_manager;
93 
94     std::map<int, std::vector<std::function<void()> > > m_local_state;
95 
96     /** A list of all objects that can be rewound. */
97     std::map<std::string, std::weak_ptr<Rewinder> > m_all_rewinder;
98 
99     /** The queue that stores all rewind infos. */
100     RewindQueue m_rewind_queue;
101 
102     /** Overall amount of memory allocated by states. */
103     unsigned int m_overall_state_size;
104 
105     /** Indicates if currently a rewind is happening. */
106     bool m_is_rewinding;
107 
108     /** How much time between consecutive state saves. */
109     int m_state_frequency;
110 
111     /** This stores the original World time in ticks during a rewind. It is
112      *  used to detect if a client's local time need adjustment to reduce
113      *  rewinds. */
114     std::atomic<int> m_not_rewound_ticks;
115 
116     std::vector<RewindInfoEventFunction*> m_pending_rief;
117 
118     bool m_schedule_reset_network_body;
119 
120     RewindManager();
121    ~RewindManager();
122     // ------------------------------------------------------------------------
clearExpiredRewinder()123     void clearExpiredRewinder()
124     {
125         for (auto it = m_all_rewinder.begin(); it != m_all_rewinder.end();)
126         {
127             if (it->second.expired())
128             {
129                 it = m_all_rewinder.erase(it);
130                 continue;
131             }
132             it++;
133         }
134     }
135     // ------------------------------------------------------------------------
136     void mergeRewindInfoEventFunction();
137 
138 public:
139     // First static functions to manage rewinding.
140     // ===========================================
141     static RewindManager *create();
142     static void destroy();
143     // ------------------------------------------------------------------------
144     /** En- or disables rewinding. */
setEnable(bool m)145     static void setEnable(bool m) { m_enable_rewind_manager = m; }
146     // ------------------------------------------------------------------------
147     /** Returns if rewinding is enabled or not. */
isEnabled()148     static bool isEnabled() { return m_enable_rewind_manager; }
149     // ------------------------------------------------------------------------
150     /** Returns the singleton. This function will not automatically create
151      *  the singleton. */
get()152     static RewindManager *get()
153     {
154         ProcessType pt = STKProcess::getType();
155         assert(m_rewind_manager[pt]);
156         return m_rewind_manager[pt];
157     }   // get
158 
159     // Non-static function declarations:
160 
161     void reset();
162     void update(int ticks);
163     void rewindTo(int target_ticks, int ticks_now, bool fast_forward);
164     void playEventsTill(int world_ticks, bool fast_forward);
165     void addEvent(EventRewinder *event_rewinder, BareNetworkString *buffer,
166                   bool confirmed, int ticks = -1);
167     void addNetworkEvent(EventRewinder *event_rewinder,
168                          BareNetworkString *buffer, int ticks);
169     void addNetworkState(BareNetworkString *buffer, int ticks);
170     void saveState();
171     // ------------------------------------------------------------------------
getRewinder(const std::string & name)172     std::shared_ptr<Rewinder> getRewinder(const std::string& name)
173     {
174         auto it = m_all_rewinder.find(name);
175         if (it != m_all_rewinder.end())
176         {
177             if (auto r = it->second.lock())
178                 return r;
179         }
180         return nullptr;
181     }
182     // ------------------------------------------------------------------------
183     bool addRewinder(std::shared_ptr<Rewinder> rewinder);
184     // ------------------------------------------------------------------------
185     /** Returns true if currently a rewind is happening. */
isRewinding() const186     bool isRewinding() const { return m_is_rewinding; }
187 
188     // ------------------------------------------------------------------------
getNotRewoundWorldTicks() const189     int getNotRewoundWorldTicks() const
190     {
191         return m_not_rewound_ticks.load(std::memory_order_relaxed);
192     }   // getNotRewoundWorldTicks
193     // ------------------------------------------------------------------------
194     /** Returns the time of the latest confirmed state. */
getLatestConfirmedState() const195     int getLatestConfirmedState() const
196     {
197         return m_rewind_queue.getLatestConfirmedState();
198     }   // getLatestConfirmedState
199     // ------------------------------------------------------------------------
200     bool useLocalEvent() const;
201     // ------------------------------------------------------------------------
addRewindInfoEventFunction(RewindInfoEventFunction * rief)202     void addRewindInfoEventFunction(RewindInfoEventFunction* rief)
203                                             { m_pending_rief.push_back(rief); }
204     // ------------------------------------------------------------------------
addNetworkRewindInfo(RewindInfo * ri)205     void addNetworkRewindInfo(RewindInfo* ri)
206                                    { m_rewind_queue.addNetworkRewindInfo(ri); }
207     // ------------------------------------------------------------------------
shouldSaveState(int ticks)208     bool shouldSaveState(int ticks)
209     {
210         int a = ticks - m_state_frequency + 1;
211         return ticks != 0 && a >= 0 && a % m_state_frequency == 0;
212     }
213     // ------------------------------------------------------------------------
resetSmoothNetworkBody()214     void resetSmoothNetworkBody()     { m_schedule_reset_network_body = true; }
215     // ------------------------------------------------------------------------
216     void handleResetSmoothNetworkBody();
217 
218 };   // RewindManager
219 
220 
221 #endif
222 
223