1 /* $Id: game_core.cpp 25592 2013-07-12 18:54:27Z rubidium $ */
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
10 /** @file game_core.cpp Implementation of Game. */
12 #include "../stdafx.h"
13 #include "../core/backup_type.hpp"
14 #include "../company_base.h"
15 #include "../company_func.h"
16 #include "../network/network.h"
17 #include "../window_func.h"
19 #include "game_scanner.hpp"
20 #include "game_config.hpp"
21 #include "game_instance.hpp"
22 #include "game_info.hpp"
24 #include "../safeguards.h"
26 /* static */ uint
Game::frame_counter
= 0;
27 /* static */ GameInfo
*Game::info
= NULL
;
28 /* static */ GameInstance
*Game::instance
= NULL
;
29 /* static */ GameScannerInfo
*Game::scanner_info
= NULL
;
30 /* static */ GameScannerLibrary
*Game::scanner_library
= NULL
;
32 /* static */ void Game::GameLoop()
34 if (_networking
&& !_network_server
) return;
35 if (Game::instance
== NULL
) return;
37 Game::frame_counter
++;
39 Backup
<CompanyByte
> cur_company(_current_company
, FILE_LINE
);
40 cur_company
.Change(OWNER_DEITY
);
41 Game::instance
->GameLoop();
42 cur_company
.Restore();
44 /* Occasionally collect garbage */
45 if ((Game::frame_counter
& 255) == 0) {
46 Game::instance
->CollectGarbage();
50 /* static */ void Game::Initialize()
52 if (Game::instance
!= NULL
) Game::Uninitialize(true);
54 Game::frame_counter
= 0;
56 if (Game::scanner_info
== NULL
) {
57 TarScanner::DoScan(TarScanner::GAME
);
58 Game::scanner_info
= new GameScannerInfo();
59 Game::scanner_info
->Initialize();
60 Game::scanner_library
= new GameScannerLibrary();
61 Game::scanner_library
->Initialize();
65 /* static */ void Game::StartNew()
67 if (Game::instance
!= NULL
) return;
69 /* Clients shouldn't start GameScripts */
70 if (_networking
&& !_network_server
) return;
72 GameConfig
*config
= GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME
);
73 GameInfo
*info
= config
->GetInfo();
74 if (info
== NULL
) return;
76 config
->AnchorUnchangeableSettings();
78 Backup
<CompanyByte
> cur_company(_current_company
, FILE_LINE
);
79 cur_company
.Change(OWNER_DEITY
);
82 Game::instance
= new GameInstance();
83 Game::instance
->Initialize(info
);
85 cur_company
.Restore();
87 InvalidateWindowData(WC_AI_DEBUG
, 0, -1);
90 /* static */ void Game::Uninitialize(bool keepConfig
)
92 Backup
<CompanyByte
> cur_company(_current_company
, FILE_LINE
);
94 delete Game::instance
;
95 Game::instance
= NULL
;
98 cur_company
.Restore();
103 delete Game::scanner_info
;
104 delete Game::scanner_library
;
105 Game::scanner_info
= NULL
;
106 Game::scanner_library
= NULL
;
108 if (_settings_game
.game_config
!= NULL
) {
109 delete _settings_game
.game_config
;
110 _settings_game
.game_config
= NULL
;
112 if (_settings_newgame
.game_config
!= NULL
) {
113 delete _settings_newgame
.game_config
;
114 _settings_newgame
.game_config
= NULL
;
119 /* static */ void Game::Pause()
121 if (Game::instance
!= NULL
) Game::instance
->Pause();
124 /* static */ void Game::Unpause()
126 if (Game::instance
!= NULL
) Game::instance
->Unpause();
129 /* static */ bool Game::IsPaused()
131 return Game::instance
!= NULL
? Game::instance
->IsPaused() : false;
134 /* static */ void Game::NewEvent(ScriptEvent
*event
)
136 /* AddRef() and Release() need to be called at least once, so do it here */
139 /* Clients should ignore events */
140 if (_networking
&& !_network_server
) {
145 /* Check if Game instance is alive */
146 if (Game::instance
== NULL
) {
151 /* Queue the event */
152 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_DEITY
, FILE_LINE
);
153 Game::instance
->InsertEvent(event
);
154 cur_company
.Restore();
159 /* static */ void Game::ResetConfig()
161 /* Check for both newgame as current game if we can reload the GameInfo inside
162 * the GameConfig. If not, remove the Game from the list. */
163 if (_settings_game
.game_config
!= NULL
&& _settings_game
.game_config
->HasScript()) {
164 if (!_settings_game
.game_config
->ResetInfo(true)) {
165 DEBUG(script
, 0, "After a reload, the GameScript by the name '%s' was no longer found, and removed from the list.", _settings_game
.game_config
->GetName());
166 _settings_game
.game_config
->Change(NULL
);
167 if (Game::instance
!= NULL
) {
168 delete Game::instance
;
169 Game::instance
= NULL
;
172 } else if (Game::instance
!= NULL
) {
173 Game::info
= _settings_game
.game_config
->GetInfo();
176 if (_settings_newgame
.game_config
!= NULL
&& _settings_newgame
.game_config
->HasScript()) {
177 if (!_settings_newgame
.game_config
->ResetInfo(false)) {
178 DEBUG(script
, 0, "After a reload, the GameScript by the name '%s' was no longer found, and removed from the list.", _settings_newgame
.game_config
->GetName());
179 _settings_newgame
.game_config
->Change(NULL
);
184 /* static */ void Game::Rescan()
186 TarScanner::DoScan(TarScanner::GAME
);
188 Game::scanner_info
->RescanDir();
189 Game::scanner_library
->RescanDir();
192 InvalidateWindowData(WC_AI_LIST
, 0, 1);
193 SetWindowClassesDirty(WC_AI_DEBUG
);
194 InvalidateWindowClassesData(WC_AI_SETTINGS
);
198 /* static */ void Game::Save()
200 if (Game::instance
!= NULL
&& (!_networking
|| _network_server
)) {
201 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_DEITY
, FILE_LINE
);
202 Game::instance
->Save();
203 cur_company
.Restore();
205 GameInstance::SaveEmpty();
209 /* static */ void Game::Load(int version
)
211 if (Game::instance
!= NULL
&& (!_networking
|| _network_server
)) {
212 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_DEITY
, FILE_LINE
);
213 Game::instance
->Load(version
);
214 cur_company
.Restore();
216 /* Read, but ignore, the load data */
217 GameInstance::LoadEmpty();
221 /* static */ char *Game::GetConsoleList(char *p
, const char *last
, bool newest_only
)
223 return Game::scanner_info
->GetConsoleList(p
, last
, newest_only
);
226 /* static */ char *Game::GetConsoleLibraryList(char *p
, const char *last
)
228 return Game::scanner_library
->GetConsoleList(p
, last
, true);
231 /* static */ const ScriptInfoList
*Game::GetInfoList()
233 return Game::scanner_info
->GetInfoList();
236 /* static */ const ScriptInfoList
*Game::GetUniqueInfoList()
238 return Game::scanner_info
->GetUniqueInfoList();
241 /* static */ GameInfo
*Game::FindInfo(const char *name
, int version
, bool force_exact_match
)
243 return Game::scanner_info
->FindInfo(name
, version
, force_exact_match
);
246 /* static */ GameLibrary
*Game::FindLibrary(const char *library
, int version
)
248 return Game::scanner_library
->FindLibrary(library
, version
);
251 #if defined(ENABLE_NETWORK)
254 * Check whether we have an Game (library) with the exact characteristics as ci.
255 * @param ci the characteristics to search on (shortname and md5sum)
256 * @param md5sum whether to check the MD5 checksum
257 * @return true iff we have an Game (library) matching.
259 /* static */ bool Game::HasGame(const ContentInfo
*ci
, bool md5sum
)
261 return Game::scanner_info
->HasScript(ci
, md5sum
);
264 /* static */ bool Game::HasGameLibrary(const ContentInfo
*ci
, bool md5sum
)
266 return Game::scanner_library
->HasScript(ci
, md5sum
);
269 #endif /* defined(ENABLE_NETWORK) */
271 /* static */ GameScannerInfo
*Game::GetScannerInfo()
273 return Game::scanner_info
;
275 /* static */ GameScannerLibrary
*Game::GetScannerLibrary()
277 return Game::scanner_library
;