Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Game.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2013 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 #include "precompiled.h"
19 
20 #include "Game.h"
21 
22 #include "graphics/GameView.h"
23 #include "graphics/LOSTexture.h"
25 #include "graphics/UnitManager.h"
26 #include "gui/GUIManager.h"
27 #include "lib/config2.h"
28 #include "lib/timer.h"
29 #include "network/NetClient.h"
30 #include "network/NetServer.h"
31 #include "network/NetTurnManager.h"
32 #include "ps/CConsole.h"
33 #include "ps/CLogger.h"
34 #include "ps/CStr.h"
35 #include "ps/Loader.h"
36 #include "ps/LoaderThunks.h"
37 #include "ps/Overlay.h"
38 #include "ps/Profile.h"
39 #include "ps/Replay.h"
40 #include "ps/World.h"
41 #include "ps/GameSetup/GameSetup.h"
42 #include "renderer/Renderer.h"
43 #include "renderer/TimeManager.h"
50 
51 extern bool g_GameRestarted;
52 
53 /**
54  * Globally accessible pointer to the CGame object.
55  **/
56 CGame *g_Game=NULL;
57 
58 /**
59  * Constructor
60  *
61  **/
62 CGame::CGame(bool disableGraphics):
63  m_World(new CWorld(this)),
64  m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), m_World->GetTerrain())),
65  m_GameView(disableGraphics ? NULL : new CGameView(this)),
66  m_GameStarted(false),
67  m_Paused(false),
68  m_SimRate(1.0f),
69  m_PlayerID(-1),
70  m_IsSavedGame(false)
71 {
73  // TODO: should use CDummyReplayLogger unless activated by cmd-line arg, perhaps?
74 
75  // Need to set the CObjectManager references after various objects have
76  // been initialised, so do it here rather than via the initialisers above.
77  if (m_GameView)
79 
80  m_TurnManager = new CNetLocalTurnManager(*m_Simulation2, GetReplayLogger()); // this will get replaced if we're a net server/client
81 
83 }
84 
85 /**
86  * Destructor
87  *
88  **/
90 {
91  // Again, the in-game call tree is going to be different to the main menu one.
93  g_Profiler.StructuralReset();
94 
95  delete m_TurnManager;
96  delete m_GameView;
97  delete m_Simulation2;
98  delete m_World;
99  delete m_ReplayLogger;
100 }
101 
103 {
104  if (m_TurnManager)
105  delete m_TurnManager;
106 
107  m_TurnManager = turnManager;
108 
109  if (m_TurnManager)
111 }
112 
113 
114 /**
115  * Initializes the game with the set of attributes provided.
116  * Makes calls to initialize the game view, world, and simulation objects.
117  * Calls are made to facilitate progress reporting of the initialization.
118  **/
119 void CGame::RegisterInit(const CScriptValRooted& attribs, const std::string& savedState)
120 {
121  m_InitialSavedState = savedState;
122  m_IsSavedGame = !savedState.empty();
123 
125 
126  std::string mapType;
127  m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "mapType", mapType);
128 
129  float speed;
130  if (m_Simulation2->GetScriptInterface().HasProperty(attribs.get(), "gameSpeed") && m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "gameSpeed", speed))
131  SetSimRate(speed);
132 
134 
135  RegMemFun(m_Simulation2, &CSimulation2::ProgressiveLoad, L"Simulation init", 1000);
136 
137  // RC, 040804 - GameView needs to be initialized before World, otherwise GameView initialization
138  // overwrites anything stored in the map file that gets loaded by CWorld::Initialize with default
139  // values. At the minute, it's just lighting settings, but could be extended to store camera position.
140  // Storing lighting settings in the game view seems a little odd, but it's no big deal; maybe move it at
141  // some point to be stored in the world object?
142  if (m_GameView)
144 
145  if (mapType == "random")
146  {
147  // Load random map attributes
148  std::wstring scriptFile;
149  CScriptValRooted settings;
150 
151  m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "script", scriptFile);
152  m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "settings", settings);
153 
154  m_World->RegisterInitRMS(scriptFile, settings, m_PlayerID);
155  }
156  else
157  {
158  std::wstring mapFile;
159  m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "map", mapFile);
160  CScriptValRooted settings;
161  if (mapType == "skirmish")
162  m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "settings", settings);
163 
164  m_World->RegisterInit(mapFile, settings, m_PlayerID);
165  }
166 
167  if (m_IsSavedGame)
168  RegMemFun(this, &CGame::LoadInitialState, L"Loading game", 1000);
169 
171 }
172 
174 {
176  ENSURE(!m_InitialSavedState.empty());
177 
178  std::string state;
179  m_InitialSavedState.swap(state); // deletes the original to save a bit of memory
180 
181  std::stringstream stream(state);
182 
183  bool ok = m_Simulation2->DeserializeState(stream);
184  if (!ok)
185  {
186  CancelLoad(L"Failed to load saved game state. It might have been\nsaved with an incompatible version of the game.");
187  return 0;
188  }
189 
190  return 0;
191 }
192 
193 /**
194  * Game initialization has been completed. Set game started flag and start the session.
195  *
196  * @return PSRETURN 0
197  **/
199 {
200  // Call the script function InitGame only for new games, and InitSavedGame for saved games
201  if (!m_IsSavedGame)
202  {
203  CScriptVal settings;
205  m_Simulation2->InitGame(settings);
206  }
207  else
208  {
210  }
211 
212  // We need to do an initial Interpolate call to set up all the models etc,
213  // because Update might never interpolate (e.g. if the game starts paused)
214  // and we could end up rendering before having set up any models (so they'd
215  // all be invisible)
216  Interpolate(0, 0);
217 
218  m_GameStarted=true;
219 
220  // Render a frame to begin loading assets
222  Render();
223 
224  // Call the reallyStartGame GUI function, but only if it exists
225  if (g_GUI && g_GUI->HasPages())
226  {
227  jsval fval, rval;
228  JSBool ok = JS_GetProperty(g_ScriptingHost.getContext(), g_GUI->GetScriptObject(), "reallyStartGame", &fval);
229  ENSURE(ok);
230  if (ok && !JSVAL_IS_VOID(fval))
231  JS_CallFunctionValue(g_ScriptingHost.getContext(), g_GUI->GetScriptObject(), fval, 0, NULL, &rval);
232  }
233 
234  if (g_NetClient)
236 
237  debug_printf(L"GAME STARTED, ALL INIT COMPLETE\n");
238 
239  // The call tree we've built for pregame probably isn't useful in-game.
241  g_Profiler.StructuralReset();
242 
243  // Mark terrain as modified so the minimap can repaint (is there a cleaner way of handling this?)
244  g_GameRestarted = true;
245 
246  return 0;
247 }
248 
250 {
251  return m_PlayerID;
252 }
253 
254 void CGame::SetPlayerID(int playerID)
255 {
256  m_PlayerID = playerID;
257  if (m_TurnManager)
259 }
260 
261 void CGame::StartGame(const CScriptValRooted& attribs, const std::string& savedState)
262 {
263  m_ReplayLogger->StartGame(attribs);
264 
265  RegisterInit(attribs, savedState);
266 }
267 
268 // TODO: doInterpolate is optional because Atlas interpolates explicitly,
269 // so that it has more control over the update rate. The game might want to
270 // do the same, and then doInterpolate should be redundant and removed.
271 
272 bool CGame::Update(const double deltaRealTime, bool doInterpolate)
273 {
274  if (m_Paused)
275  return true;
276 
277  if (!m_TurnManager)
278  return true;
279 
280  const double deltaSimTime = deltaRealTime * m_SimRate;
281 
282  bool ok = true;
283  if (deltaSimTime)
284  {
285  // To avoid confusing the profiler, we need to trigger the new turn
286  // while we're not nested inside any PROFILE blocks
287  if (m_TurnManager->WillUpdate(deltaSimTime))
288  g_Profiler.Turn();
289 
290  // At the normal sim rate, we currently want to render at least one
291  // frame per simulation turn, so let maxTurns be 1. But for fast-forward
292  // sim rates we want to allow more, so it's not bounded by framerate,
293  // so just use the sim rate itself as the number of turns per frame.
294  size_t maxTurns = (size_t)m_SimRate;
295 
296  if (m_TurnManager->Update(deltaSimTime, maxTurns))
297  {
298  {
299  PROFILE3("gui sim update");
300  g_GUI->SendEventToAll("SimulationUpdate");
301  }
302 
304  }
305 
307  g_Renderer.GetTimeManager().Update(deltaSimTime);
308  }
309 
310  if (doInterpolate)
311  {
312  m_TurnManager->Interpolate(deltaSimTime, deltaRealTime);
313 
314  if ( g_SoundManager )
316  }
317 
318  return ok;
319 }
320 
321 void CGame::Interpolate(float simFrameLength, float realFrameLength)
322 {
323  if (!m_TurnManager)
324  return;
325 
326  m_TurnManager->Interpolate(simFrameLength, realFrameLength);
327 }
328 
329 
330 static CColor BrokenColor(0.3f, 0.3f, 0.3f, 1.0f);
331 
333 {
334  m_PlayerColours.clear();
335 
337  if (!cmpPlayerManager)
338  return;
339 
340  int numPlayers = cmpPlayerManager->GetNumPlayers();
341  m_PlayerColours.resize(numPlayers);
342 
343  for (int i = 0; i < numPlayers; ++i)
344  {
345  CmpPtr<ICmpPlayer> cmpPlayer(*m_Simulation2, cmpPlayerManager->GetPlayerByID(i));
346  if (!cmpPlayer)
348  else
349  m_PlayerColours[i] = cmpPlayer->GetColour();
350  }
351 }
352 
353 
355 {
356  if (player < 0 || player >= (int)m_PlayerColours.size())
357  return BrokenColor;
358 
359  return m_PlayerColours[player];
360 }
The container that holds the rules, resources and attributes of the game.
Definition: Game.h:39
void InitSavedGame()
static CColor BrokenColor(0.3f, 0.3f, 0.3f, 1.0f)
CNetClient * g_NetClient
Global network client for the standard game.
Definition: NetClient.cpp:37
CUnitManager & GetUnitManager()
Get a reference to the unit manager object.
Definition: World.h:96
void SetInitAttributes(const CScriptValRooted &settings)
Set the attributes identifying the scenario/RMS used to initialise this simulation.
bool HasProperty(jsval obj, const char *name)
Check the named property has been defined on the given object.
void CachePlayerColours()
Retrieving player colours from scripts is slow, so this updates an internal cache of all players&#39; col...
Definition: Game.cpp:332
ISoundManager * g_SoundManager
Definition: Overlay.h:34
bool DeserializeState(std::istream &stream)
int LoadInitialState()
Definition: Game.cpp:173
void LoadFinished()
Call when the game has started and all data files have been loaded, to signal to the server that we a...
Definition: NetClient.cpp:293
CWorld * m_World
pointer to the CWorld object representing the game world.
Definition: Game.h:45
virtual void IdleTask()=0
void SetObjectManager(CObjectManager &objectManager)
Definition: UnitManager.h:58
A trivial wrapper around a jsval.
Definition: ScriptVal.h:29
void RegisterInitRMS(const CStrW &scriptFile, const CScriptValRooted &settings, int playerID)
Definition: World.cpp:98
bool m_IsSavedGame
Definition: Game.h:173
Implementation of CNetTurnManager for offline games.
void RegisterInit(const CStrW &mapFile, const CScriptValRooted &settings, int playerID)
Initializes the game world with the attributes provided.
Definition: World.cpp:68
CGUIManager * g_GUI
Definition: GUIManager.cpp:32
bool LoadDefaultScripts()
Call LoadScripts for each of the game&#39;s standard simulation script paths.
~CGame()
Destructor.
Definition: Game.cpp:89
const entity_id_t SYSTEM_ENTITY
Entity ID for singleton &#39;system&#39; components.
Definition: Entity.h:44
CGameView * m_GameView
pointer to the CGameView object representing the view into the game world.
Definition: Game.h:53
Public API for simulation system.
Definition: Simulation2.h:46
void InitGame(const CScriptVal &data)
Initialise a new game, based on some script data.
#define g_Renderer
Definition: Renderer.h:61
bool WillUpdate(float simFrameLength)
Returns whether Update(simFrameLength, ...) will process at least one new turn.
int GetPlayerID()
Definition: Game.cpp:249
void Interpolate(float simFrameLength, float realFrameLength)
Definition: Game.cpp:321
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
#define g_ScriptingHost
CWorld is a general data class containing whatever is needed to accurately represent the world...
Definition: World.h:47
#define g_Profiler
Definition: Profile.h:147
void SetPlayerID(int playerID)
Definition: Game.cpp:254
bool Update(const double deltaRealTime, bool doInterpolate=true)
Periodic heartbeat that controls the process.
Definition: Game.cpp:272
u32 PSRETURN
Definition: Errors.h:75
void SetTurnManager(CNetTurnManager *turnManager)
Replace the current turn manager.
Definition: Game.cpp:102
virtual entity_id_t GetPlayerByID(int32_t id)=0
void StartGame(const CScriptValRooted &attribs, const std::string &savedState)
Definition: Game.cpp:261
bool m_Paused
the game is paused and no updates will be performed if true.
Definition: Game.h:74
JSObject * GetScriptObject()
See CGUI::GetScriptObject; applies to the currently active page.
Definition: GUIManager.cpp:290
ScriptInterface & GetScriptInterface() const
std::string m_InitialSavedState
Definition: Game.h:172
Common network turn system (used by clients and offline games).
bool g_GameRestarted
Definition: MiniMap.cpp:46
void MakeDirty()
Marks the LOS texture as needing recomputation.
Definition: LOSTexture.cpp:90
CGame * g_Game
Globally accessible pointer to the CGame object.
Definition: Game.cpp:56
void SetSimRate(float simRate)
Set the simulation scale multiplier.
Definition: Game.h:147
static bool IsInitialised()
Definition: Singleton.h:63
void RegisterInit(const CScriptValRooted &attribs, const std::string &savedState)
Initializes the game with the set of attributes provided.
Definition: Game.cpp:119
void Render()
Definition: GameSetup.cpp:192
A simplified syntax for accessing entity components.
Definition: CmpPtr.h:55
CNetTurnManager * m_TurnManager
Definition: Game.h:65
void CancelLoad(const CStrW &message)
Definition: GameSetup.cpp:1326
bool Update(float simFrameLength, size_t maxTurns)
Advance the simulation by a certain time.
std::vector< CColor > m_PlayerColours
Definition: Game.h:169
bool GetProperty(jsval obj, const char *name, T &out)
Get the named property on the given object.
void SetPlayerID(int playerId)
Set the current user&#39;s player ID, which will be added into command messages.
void Interpolate(float simFrameLength, float realFrameLength)
Advance the graphics by a certain time.
void RegisterInit()
Definition: GameView.cpp:461
CGameView * GetView()
Get the pointer to the game view object.
Definition: Game.h:128
#define PROFILE3(name)
Definition: Profile.h:201
int m_PlayerID
Definition: Game.h:63
CGame(bool disableGraphics=false)
Constructor.
Definition: Game.cpp:62
virtual CLOSTexture & GetLOSTexture()
Return the LOS texture to be used for rendering this scene.
Definition: GameView.cpp:400
void LDR_EndRegistering()
Definition: Loader.cpp:130
CColor GetPlayerColour(int player) const
Definition: Game.cpp:354
jsval get() const
Returns the current value (or JSVAL_VOID if uninitialised).
Definition: ScriptVal.cpp:45
CObjectManager & GetObjectManager() const
Definition: GameView.cpp:385
virtual void StartGame(const CScriptValRooted &attribs)=0
Started the game with the given game attributes.
void RegMemFun(T *this_, int(T::*func)(void), const wchar_t *description, int estimated_duration_ms)
Definition: LoaderThunks.h:67
Implementation of IReplayLogger that saves data to a file in the logs directory.
Definition: Replay.h:65
float m_SimRate
Timescale multiplier for simulation rate.
Definition: Game.h:61
int ProgressiveLoad()
RegMemFun incremental loader function.
PSRETURN ReallyStartGame()
Game initialization has been completed.
Definition: Game.cpp:198
IReplayLogger * m_ReplayLogger
Definition: Game.h:167
virtual int32_t GetNumPlayers()=0
bool HasPages()
Returns whether there are any current pages.
Definition: GUIManager.cpp:64
bool m_GameStarted
the game has been initialized and ready for use if true.
Definition: Game.h:57
CScriptValRooted GetInitAttributes()
Get the data passed to SetInitAttributes.
void SendEventToAll(const CStr &eventName)
See CGUI::SendEventToAll; applies to the currently active page.
Definition: GUIManager.cpp:256
IReplayLogger & GetReplayLogger() const
Definition: Game.h:162
void LDR_BeginRegistering()
Definition: Loader.cpp:101
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
Definition: debug.cpp:142
static enum @41 state
CSimulation2 * m_Simulation2
pointer to the CSimulation2 object operating on the game world.
Definition: Game.h:49