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