Maintain a circular buffer of recent commands, add to crashlog.
[openttd-joker.git] / src / game / game_core.cpp
blob7e20db40d2287c8967ab063ef9c7de90039f7c2d
1 /* $Id: game_core.cpp 25592 2013-07-12 18:54:27Z rubidium $ */
3 /*
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/>.
8 */
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"
18 #include "game.hpp"
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);
81 Game::info = info;
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;
96 Game::info = NULL;
98 cur_company.Restore();
100 if (keepConfig) {
101 Rescan();
102 } else {
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 */
137 event->AddRef();
139 /* Clients should ignore events */
140 if (_networking && !_network_server) {
141 event->Release();
142 return;
145 /* Check if Game instance is alive */
146 if (Game::instance == NULL) {
147 event->Release();
148 return;
151 /* Queue the event */
152 Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
153 Game::instance->InsertEvent(event);
154 cur_company.Restore();
156 event->Release();
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;
170 Game::info = 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();
190 ResetConfig();
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();
204 } else {
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();
215 } else {
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;