game_core.cpp

Go to the documentation of this file.
00001 /* $Id: game_core.cpp 25592 2013-07-12 18:54:27Z 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   config->AnchorUnchangeableSettings();
00075 
00076   Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00077   cur_company.Change(OWNER_DEITY);
00078 
00079   Game::info = info;
00080   Game::instance = new GameInstance();
00081   Game::instance->Initialize(info);
00082 
00083   cur_company.Restore();
00084 
00085   InvalidateWindowData(WC_AI_DEBUG, 0, -1);
00086 }
00087 
00088 /* static */ void Game::Uninitialize(bool keepConfig)
00089 {
00090   Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00091 
00092   delete Game::instance;
00093   Game::instance = NULL;
00094   Game::info = NULL;
00095 
00096   cur_company.Restore();
00097 
00098   if (keepConfig) {
00099     Rescan();
00100   } else {
00101     delete Game::scanner_info;
00102     delete Game::scanner_library;
00103     Game::scanner_info = NULL;
00104     Game::scanner_library = NULL;
00105 
00106     if (_settings_game.game_config != NULL) {
00107       delete _settings_game.game_config;
00108       _settings_game.game_config = NULL;
00109     }
00110     if (_settings_newgame.game_config != NULL) {
00111       delete _settings_newgame.game_config;
00112       _settings_newgame.game_config = NULL;
00113     }
00114   }
00115 }
00116 
00117 /* static */ void Game::Pause()
00118 {
00119   if (Game::instance != NULL) Game::instance->Pause();
00120 }
00121 
00122 /* static */ void Game::Unpause()
00123 {
00124   if (Game::instance != NULL) Game::instance->Unpause();
00125 }
00126 
00127 /* static */ bool Game::IsPaused()
00128 {
00129   return Game::instance != NULL? Game::instance->IsPaused() : false;
00130 }
00131 
00132 /* static */ void Game::NewEvent(ScriptEvent *event)
00133 {
00134   /* AddRef() and Release() need to be called at least once, so do it here */
00135   event->AddRef();
00136 
00137   /* Clients should ignore events */
00138   if (_networking && !_network_server) {
00139     event->Release();
00140     return;
00141   }
00142 
00143   /* Check if Game instance is alive */
00144   if (Game::instance == NULL) {
00145     event->Release();
00146     return;
00147   }
00148 
00149   /* Queue the event */
00150   Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
00151   Game::instance->InsertEvent(event);
00152   cur_company.Restore();
00153 
00154   event->Release();
00155 }
00156 
00157 /* static */ void Game::ResetConfig()
00158 {
00159   /* Check for both newgame as current game if we can reload the GameInfo inside
00160    *  the GameConfig. If not, remove the Game from the list. */
00161   if (_settings_game.game_config != NULL && _settings_game.game_config->HasScript()) {
00162     if (!_settings_game.game_config->ResetInfo(true)) {
00163       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());
00164       _settings_game.game_config->Change(NULL);
00165       if (Game::instance != NULL) {
00166         delete Game::instance;
00167         Game::instance = NULL;
00168         Game::info = NULL;
00169       }
00170     } else if (Game::instance != NULL) {
00171       Game::info = _settings_game.game_config->GetInfo();
00172     }
00173   }
00174   if (_settings_newgame.game_config != NULL && _settings_newgame.game_config->HasScript()) {
00175     if (!_settings_newgame.game_config->ResetInfo(false)) {
00176       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());
00177       _settings_newgame.game_config->Change(NULL);
00178     }
00179   }
00180 }
00181 
00182 /* static */ void Game::Rescan()
00183 {
00184   TarScanner::DoScan(TarScanner::GAME);
00185 
00186   Game::scanner_info->RescanDir();
00187   Game::scanner_library->RescanDir();
00188   ResetConfig();
00189 
00190   InvalidateWindowData(WC_AI_LIST, 0, 1);
00191   SetWindowClassesDirty(WC_AI_DEBUG);
00192   InvalidateWindowClassesData(WC_AI_SETTINGS);
00193 }
00194 
00195 
00196 /* static */ void Game::Save()
00197 {
00198   if (Game::instance != NULL && (!_networking || _network_server)) {
00199     Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
00200     Game::instance->Save();
00201     cur_company.Restore();
00202   } else {
00203     GameInstance::SaveEmpty();
00204   }
00205 }
00206 
00207 /* static */ void Game::Load(int version)
00208 {
00209   if (Game::instance != NULL && (!_networking || _network_server)) {
00210     Backup<CompanyByte> cur_company(_current_company, OWNER_DEITY, FILE_LINE);
00211     Game::instance->Load(version);
00212     cur_company.Restore();
00213   } else {
00214     /* Read, but ignore, the load data */
00215     GameInstance::LoadEmpty();
00216   }
00217 }
00218 
00219 /* static */ char *Game::GetConsoleList(char *p, const char *last, bool newest_only)
00220 {
00221   return Game::scanner_info->GetConsoleList(p, last, newest_only);
00222 }
00223 
00224 /* static */ char *Game::GetConsoleLibraryList(char *p, const char *last)
00225 {
00226    return Game::scanner_library->GetConsoleList(p, last, true);
00227 }
00228 
00229 /* static */ const ScriptInfoList *Game::GetInfoList()
00230 {
00231   return Game::scanner_info->GetInfoList();
00232 }
00233 
00234 /* static */ const ScriptInfoList *Game::GetUniqueInfoList()
00235 {
00236   return Game::scanner_info->GetUniqueInfoList();
00237 }
00238 
00239 /* static */ GameInfo *Game::FindInfo(const char *name, int version, bool force_exact_match)
00240 {
00241   return Game::scanner_info->FindInfo(name, version, force_exact_match);
00242 }
00243 
00244 /* static */ GameLibrary *Game::FindLibrary(const char *library, int version)
00245 {
00246   return Game::scanner_library->FindLibrary(library, version);
00247 }
00248 
00249 #if defined(ENABLE_NETWORK)
00250 
00257 /* static */ bool Game::HasGame(const ContentInfo *ci, bool md5sum)
00258 {
00259   return Game::scanner_info->HasScript(ci, md5sum);
00260 }
00261 
00262 /* static */ bool Game::HasGameLibrary(const ContentInfo *ci, bool md5sum)
00263 {
00264   return Game::scanner_library->HasScript(ci, md5sum);
00265 }
00266 
00267 #endif /* defined(ENABLE_NETWORK) */
00268 
00269 /* static */ GameScannerInfo *Game::GetScannerInfo()
00270 {
00271   return Game::scanner_info;
00272 }
00273 /* static */ GameScannerLibrary *Game::GetScannerLibrary()
00274 {
00275   return Game::scanner_library;
00276 }