Pyrogenesis  trunk
TurnManager.h
Go to the documentation of this file.
1 /* Copyright (C) 2017 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_TURNMANAGER
19 #define INCLUDED_TURNMANAGER
20 
22 
23 #include <list>
24 #include <map>
25 #include <vector>
26 
27 extern const u32 DEFAULT_TURN_LENGTH_SP;
28 extern const u32 DEFAULT_TURN_LENGTH_MP;
29 
30 extern const int COMMAND_DELAY;
31 
32 class CSimulationMessage;
33 class CSimulation2;
34 class IReplayLogger;
35 
36 /**
37  * This file defines the base class of the turn managers for clients, local games and replays.
38  * The basic idea of our turn managing system across a network is as in this article:
39  * http://www.gamasutra.com/view/feature/3094/1500_archers_on_a_288_network_.php?print=1
40  *
41  * Each player performs the simulation for turn N.
42  * User input is translated into commands scheduled for execution in turn N+2 which are
43  * distributed to all other clients.
44  * After a while, a client wants to perform the simulation for turn N+1,
45  * which first requires that it has all the other clients' commands for turn N+1.
46  * In that case, it does the simulation and tells all the other clients (via the server)
47  * it has finished sending commands for turn N+2, and it starts sending commands for turn N+3.
48  *
49  * Commands are redistributed immediately by the server.
50  * To ensure a consistent execution of commands, they are each associated with a
51  * client session ID (which is globally unique and consistent), which is used to sort them.
52  */
53 
54 /**
55  * Common turn system (used by clients and offline games).
56  */
58 {
60 public:
61  /**
62  * Construct for a given network session ID.
63  */
64  CTurnManager(CSimulation2& simulation, u32 defaultTurnLength, int clientId, IReplayLogger& replay);
65 
66  virtual ~CTurnManager() { }
67 
68  void ResetState(u32 newCurrentTurn, u32 newReadyTurn);
69 
70  /**
71  * Set the current user's player ID, which will be added into command messages.
72  */
73  void SetPlayerID(int playerId);
74 
75  /**
76  * Advance the simulation by a certain time. If this brings us past the current
77  * turn length, the next turns are processed and the function returns true.
78  * Otherwise, nothing happens and it returns false.
79  *
80  * @param simFrameLength Length of the previous frame, in simulation seconds
81  * @param maxTurns Maximum number of turns to simulate at once
82  */
83  bool Update(float simFrameLength, size_t maxTurns);
84 
85  /**
86  * Advance the simulation by as much as possible. Intended for catching up
87  * over a small number of turns when rejoining a multiplayer match.
88  * Returns true if it advanced by at least one turn.
89  */
90  bool UpdateFastForward();
91 
92  /**
93  * Returns whether Update(simFrameLength, ...) will process at least one new turn.
94  * @param simFrameLength Length of the previous frame, in simulation seconds
95  */
96  bool WillUpdate(float simFrameLength) const;
97 
98  /**
99  * Advance the graphics by a certain time.
100  * @param simFrameLength Length of the previous frame, in simulation seconds
101  * @param realFrameLength Length of the previous frame, in real time seconds
102  */
103  void Interpolate(float simFrameLength, float realFrameLength);
104 
105  /**
106  * Called by networking code when a simulation message is received.
107  */
108  virtual void OnSimulationMessage(CSimulationMessage* msg) = 0;
109 
110  /**
111  * Called by simulation code, to add a new command to be distributed to all clients and executed soon.
112  */
113  virtual void PostCommand(JS::HandleValue data) = 0;
114 
115  /**
116  * Called when all commands for a given turn have been received.
117  * This allows Update to progress to that turn.
118  */
119  void FinishedAllCommands(u32 turn, u32 turnLength);
120 
121  /**
122  * Enables the recording of state snapshots every @p numTurns,
123  * which can be jumped back to via RewindTimeWarp().
124  * If @p numTurns is 0 then recording is disabled.
125  */
126  void EnableTimeWarpRecording(size_t numTurns);
127 
128  /**
129  * Jumps back to the latest recorded state snapshot (if any).
130  */
131  void RewindTimeWarp();
132 
133  void QuickSave();
134  void QuickLoad();
135 
137 
138 protected:
139  /**
140  * Store a command to be executed at a given turn.
141  */
142  void AddCommand(int client, int player, JS::HandleValue data, u32 turn);
143 
144  /**
145  * Called when this client has finished sending all its commands scheduled for the given turn.
146  */
147  virtual void NotifyFinishedOwnCommands(u32 turn) = 0;
148 
149  /**
150  * Called when this client has finished a simulation update.
151  */
152  virtual void NotifyFinishedUpdate(u32 turn) = 0;
153 
154  /**
155  * Returns whether we should compute a complete state hash for the given turn,
156  * instead of a quick less-complete hash.
157  */
158  bool TurnNeedsFullHash(u32 turn) const;
159 
161 
162  /// The turn that we have most recently executed
164 
165  /// The latest turn for which we have received all commands from all clients
167 
168  // Current turn length
170 
171  /// Commands queued at each turn (index 0 is for m_CurrentTurn+1)
172  std::deque<std::map<u32, std::vector<SimulationCommand>>> m_QueuedCommands;
173 
176 
177  /// Simulation time remaining until we ought to execute the next turn (as a negative value to
178  /// add elapsed time increments to until we reach 0).
180 
182 
184 
185  // The number of the last turn that is allowed to be executed (used for replays)
187 
188 private:
189  size_t m_TimeWarpNumTurns; // 0 if disabled
190  std::list<std::string> m_TimeWarpStates;
191  std::string m_QuickSaveState; // TODO: should implement a proper disk-based quicksave system
192  std::string m_QuickSaveMetadata;
193 };
194 
195 #endif // INCLUDED_TURNMANAGER
u32 m_CurrentTurn
The turn that we have most recently executed.
Definition: TurnManager.h:163
CSimulation2 & m_Simulation2
Definition: TurnManager.h:160
int m_PlayerId
Definition: TurnManager.h:174
bool Update(float simFrameLength, size_t maxTurns)
Advance the simulation by a certain time.
Definition: TurnManager.cpp:86
bool WillUpdate(float simFrameLength) const
Returns whether Update(simFrameLength, ...) will process at least one new turn.
Definition: TurnManager.cpp:70
uint m_ClientId
Definition: TurnManager.h:175
virtual void NotifyFinishedUpdate(u32 turn)=0
Called when this client has finished a simulation update.
void AddCommand(int client, int player, JS::HandleValue data, u32 turn)
Store a command to be executed at a given turn.
Definition: TurnManager.cpp:226
NONCOPYABLE(CTurnManager)
bool TurnNeedsFullHash(u32 turn) const
Returns whether we should compute a complete state hash for the given turn, instead of a quick less-c...
Definition: TurnManager.cpp:253
bool UpdateFastForward()
Advance the simulation by as much as possible.
Definition: TurnManager.cpp:174
void QuickSave()
Definition: TurnManager.cpp:291
bool m_HasSyncError
Definition: TurnManager.h:181
virtual void OnSimulationMessage(CSimulationMessage *msg)=0
Called by networking code when a simulation message is received.
void QuickLoad()
Definition: TurnManager.cpp:312
u32 m_ReadyTurn
The latest turn for which we have received all commands from all clients.
Definition: TurnManager.h:166
Replay log recorder interface.
Definition: Replay.h:30
IReplayLogger & m_Replay
Definition: TurnManager.h:183
void RewindTimeWarp()
Jumps back to the latest recorded state snapshot (if any).
Definition: TurnManager.cpp:275
virtual ~CTurnManager()
Definition: TurnManager.h:66
This file defines the base class of the turn managers for clients, local games and replays...
Definition: TurnManager.h:57
u32 m_FinalTurn
Definition: TurnManager.h:186
Public API for simulation system.
Definition: Simulation2.h:47
CTurnManager(CSimulation2 &simulation, u32 defaultTurnLength, int clientId, IReplayLogger &replay)
Construct for a given network session ID.
Definition: TurnManager.cpp:41
std::string m_QuickSaveMetadata
Definition: TurnManager.h:192
std::deque< std::map< u32, std::vector< SimulationCommand > > > m_QueuedCommands
Commands queued at each turn (index 0 is for m_CurrentTurn+1)
Definition: TurnManager.h:172
void Interpolate(float simFrameLength, float realFrameLength)
Advance the graphics by a certain time.
Definition: TurnManager.cpp:212
uint32_t u32
Definition: types.h:39
float m_DeltaSimTime
Simulation time remaining until we ought to execute the next turn (as a negative value to add elapsed...
Definition: TurnManager.h:179
void EnableTimeWarpRecording(size_t numTurns)
Enables the recording of state snapshots every numTurns, which can be jumped back to via RewindTimeWa...
Definition: TurnManager.cpp:269
const int COMMAND_DELAY
Definition: TurnManager.cpp:33
std::string m_QuickSaveState
Definition: TurnManager.h:191
void SetPlayerID(int playerId)
Set the current user&#39;s player ID, which will be added into command messages.
Definition: TurnManager.cpp:65
std::list< std::string > m_TimeWarpStates
Definition: TurnManager.h:190
size_t m_TimeWarpNumTurns
Definition: TurnManager.h:189
u32 m_TurnLength
Definition: TurnManager.h:169
unsigned int uint
Definition: types.h:42
const u32 DEFAULT_TURN_LENGTH_MP
Definition: TurnManager.cpp:30
u32 GetCurrentTurn()
Definition: TurnManager.h:136
void ResetState(u32 newCurrentTurn, u32 newReadyTurn)
Definition: TurnManager.cpp:55
void FinishedAllCommands(u32 turn, u32 turnLength)
Called when all commands for a given turn have been received.
Definition: TurnManager.cpp:244
const u32 DEFAULT_TURN_LENGTH_SP
Definition: TurnManager.cpp:31
virtual void PostCommand(JS::HandleValue data)=0
Called by simulation code, to add a new command to be distributed to all clients and executed soon...
virtual void NotifyFinishedOwnCommands(u32 turn)=0
Called when this client has finished sending all its commands scheduled for the given turn...
Special message type for simulation commands.
Definition: NetMessage.h:113