game_core.cpp

Go to the documentation of this file.
00001 /* $Id: game_core.cpp 25169 2013-04-08 20:56:30Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "../stdafx.h"
00013 #include "../core/backup_type.hpp"
00014 #include "../company_base.h"
00015 #include "../company_func.h"
00016 #include "../network/network.h"
00017 #include "../window_func.h"
00018 #include "game.hpp"
00019 #include "game_scanner.hpp"
00020 #include "game_config.hpp"
00021 #include "game_instance.hpp"
00022 #include "game_info.hpp"
00023 
00024 /* static */ uint Game::frame_counter = 0;
00025 /* static */ GameInfo *Game::info = NULL;
00026 /* static */ GameInstance *Game::instance = NULL;
00027 /* static */ GameScannerInfo *Game::scanner_info = NULL;
00028 /* static */ GameScannerLibrary *Game::scanner_library = NULL;
00029 
00030 /* static */ void Game::GameLoop()
00031 {
00032   if (_networking && !_network_server) return;
00033   if (Game::instance == NULL) return;
00034 
00035   Game::frame_counter++;
00036 
00037   Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00038   cur_company.Change(OWNER_DEITY);
00039   Game::instance->GameLoop();
00040   cur_company.Restore();
00041 
00042   /* Occasionally collect garbage */
00043   if ((Game::frame_counter & 255) == 0) {
00044     Game::instance->CollectGarbage();
00045   }
00046 }
00047 
00048 /* static */ void Game::Initialize()
00049 {
00050   if (Game::instance != NULL) Game::Uninitialize(true);
00051 
00052   Game::frame_counter = 0;
00053 
00054   if (Game::scanner_info == NULL) {
00055     TarScanner::DoScan(TarScanner::GAME);
00056     Game::scanner_info = new GameScannerInfo();
00057     Game::scanner_info->Initialize();
00058     Game::scanner_library = new GameScannerLibrary();
00059     Game::scanner_library->Initialize();
00060   }
00061 }
00062 
00063 /* static */ void Game::StartNew()
00064 {
00065   if (Game::instance != NULL) return;
00066 
00067   /* Clients shouldn't start GameScripts */
00068   if (_networking && !_network_server) return;
00069 
00070   GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
00071   GameInfo *info = config->GetInfo();
00072   if (info == NULL) return;
00073 
00074   Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00075   cur_company.Change(OWNER_DEITY);
00076 
00077   Game::info = info;
00078   Game::instance = new GameInstance();
00079   Game::instance->Initialize(info);
00080 
00081   cur_company.Restore();
00082 
00083   InvalidateWindowData(WC_AI_DEBUG, 0, -1);
00084 }
00085 
00086 /* static */ void Game::Uninitialize(bool keepConfig)
00087 {
00088   Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00089 
00090   delete Game::instance;
00091   Game::instance = NULL;
00092   Game::info = NULL;
00093 
00094   cur_company.Restore();
00095 
00096   if (keepConfig) {
00097     Rescan();
00098   } else {
00099     delete Game::scanner_info;
00100     delete Game::scanner_library;
00101     Game::scanner_info = NULL;
00102     Game::scanner_library = NULL;
00103 
00104     if (_settings_game.game_config != NULL) {
00105       delete _settings_game.game_config;
00106       _settings_game.game_config = NULL;
00107     }
00108     if (_settings_newgame.game_config != NULL) {
00109       delete _settings_newgame.game_config;
00110       _settings_newgame.game_config = NULL;
00111     }
00112   }
00113 }
00114 
00115 /* static */ void Game::Pause()
00116 {
00117   if (Game::instance != NULL) Game::instance->Pause();
00118 }
00119 
00120 /* static */ void Game::Unpause()
00121 {
00122   if (Game::instance != NULL) Game::instance->Unpause();
00123 }
00124 
00125 /* static */ bool Game::IsPaused()
00126 {
00127   return Game::instance != NULL? Game::instance->IsPaused() : false;
00128 }
00129 
00130 /* static */ void Game::NewEvent(ScriptEvent *event)
00131 {
00132   /* AddRef() and Release() need to be called at least once, so do it here */
00133   event->AddRef();
00134 
00135   /* Clients should ignore events */
00136   if (_networking && !_network_server) {
00137     event->Release();
00138     return;
00139   }
00140 
00141   /* Check if Game instance is alive */
00142   if (Game::instance == NULL) {
00143     event->Release();
00144     return;
00145   }
00146 
00147   /* Queue the event */
00148   Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
00149   Game::instance->InsertEvent(event);
00150   cur_company.Restore();
00151 
00152   event->Release();
00153 }
00154 
00155 /* static */ void Game::ResetConfig()
00156 {
00157   /* Check for both newgame as current game if we can reload the GameInfo inside
00158    *  the GameConfig. If not, remove the Game from the list. */
00159   if (_settings_game.game_config != NULL && _settings_game.game_config->HasScript()) {
00160     if (!_settings_game.game_config->ResetInfo(true)) {
00161       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());
00162       _settings_game.game_config->Change(NULL);
00163       if (Game::instance != NULL) {
00164         delete Game::instance;
00165         Game::instance = NULL;
00166         Game::info = NULL;
00167       }
00168     } else if (Game::instance != NULL) {
00169       Game::info = _settings_game.game_config->GetInfo();
00170     }
00171   }
00172   if (_settings_newgame.game_config != NULL && _settings_newgame.game_config->HasScript()) {
00173     if (!_settings_newgame.game_config->ResetInfo(false)) {
00174       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());
00175       _settings_newgame.game_config->Change(NULL);
00176     }
00177   }
00178 }
00179 
00180 /* static */ void Game::Rescan()
00181 {
00182   TarScanner::DoScan(TarScanner::GAME);
00183 
00184   Game::scanner_info->RescanDir();
00185   Game::scanner_library->RescanDir();
00186   ResetConfig();
00187 
00188   InvalidateWindowData(WC_AI_LIST, 0, 1);
00189   SetWindowClassesDirty(WC_AI_DEBUG);
00190   InvalidateWindowClassesData(WC_AI_SETTINGS);
00191 }
00192 
00193 
00194 /* static */ void Game::Save()
00195 {
00196   if (Game::instance != NULL && (!_networking || _network_server)) {
00197     Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
00198     Game::instance->Save();
00199     cur_company.Restore();
00200   } else {
00201     GameInstance::SaveEmpty();
00202   }
00203 }
00204 
00205 /* static */ void Game::Load(int version)
00206 {
00207   if (Game::instance != NULL && (!_networking || _network_server)) {
00208     Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
00209     Game::instance->Load(version);
00210     cur_company.Restore();
00211   } else {
00212     /* Read, but ignore, the load data */
00213     GameInstance::LoadEmpty();
00214   }
00215 }
00216 
00217 /* static */ char *Game::GetConsoleList(char *p, const char *last, bool newest_only)
00218 {
00219   return Game::scanner_info->GetConsoleList(p, last, newest_only);
00220 }
00221 
00222 /* static */ char *Game::GetConsoleLibraryList(char *p, const char *last)
00223 {
00224    return Game::scanner_library->GetConsoleList(p, last, true);
00225 }
00226 
00227 /* static */ const ScriptInfoList *Game::GetInfoList()
00228 {
00229   return Game::scanner_info->GetInfoList();
00230 }
00231 
00232 /* static */ const ScriptInfoList *Game::GetUniqueInfoList()
00233 {
00234   return Game::scanner_info->GetUniqueInfoList();
00235 }
00236 
00237 /* static */ GameInfo *Game::FindInfo(const char *name, int version, bool force_exact_match)
00238 {
00239   return Game::scanner_info->FindInfo(name, version, force_exact_match);
00240 }
00241 
00242 /* static */ GameLibrary *Game::FindLibrary(const char *library, int version)
00243 {
00244   return Game::scanner_library->FindLibrary(library, version);
00245 }
00246 
00247 #if defined(ENABLE_NETWORK)
00248 
00255 /* static */ bool Game::HasGame(const ContentInfo *ci, bool md5sum)
00256 {
00257   return Game::scanner_info->HasScript(ci, md5sum);
00258 }
00259 
00260 /* static */ bool Game::HasGameLibrary(const ContentInfo *ci, bool md5sum)
00261 {
00262   return Game::scanner_library->HasScript(ci, md5sum);
00263 }
00264 
00265 #endif /* defined(ENABLE_NETWORK) */
00266 
00267 /* static */ GameScannerInfo *Game::GetScannerInfo()
00268 {
00269   return Game::scanner_info;
00270 }
00271 /* static */ GameScannerLibrary *Game::GetScannerLibrary()
00272 {
00273   return Game::scanner_library;
00274 }