00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "landscape.h"
00014 #include "company_func.h"
00015 #include "thread/thread.h"
00016 #include "genworld.h"
00017 #include "gfxinit.h"
00018 #include "window_func.h"
00019 #include "network/network.h"
00020 #include "heightmap.h"
00021 #include "viewport_func.h"
00022 #include "gfx_func.h"
00023 #include "date_func.h"
00024 #include "engine_func.h"
00025 #include "newgrf_storage.h"
00026 #include "water.h"
00027 #include "blitter/factory.hpp"
00028 #include "tilehighlight_func.h"
00029 #include "saveload/saveload.h"
00030 #include "void_map.h"
00031 #include "town.h"
00032 #include "newgrf.h"
00033 #include "core/random_func.hpp"
00034 #include "core/backup_type.hpp"
00035
00036 #include "table/sprites.h"
00037
00038 void GenerateClearTile();
00039 void GenerateIndustries();
00040 void GenerateObjects();
00041 void GenerateTrees();
00042
00043 void StartupEconomy();
00044 void StartupCompanies();
00045 void StartupDisasters();
00046
00047 void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings);
00048
00055 GenWorldInfo _gw;
00056
00058 ThreadMutex *_genworld_mapgen_mutex = ThreadMutex::New();
00060 ThreadMutex *_genworld_paint_mutex = ThreadMutex::New();
00061
00063 bool _generating_world;
00064
00069 bool IsGenerateWorldThreaded()
00070 {
00071 return _gw.threaded && !_gw.quit_thread;
00072 }
00073
00078 static void CleanupGeneration()
00079 {
00080 _generating_world = false;
00081
00082 if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
00083
00084 if (_gw.threaded && _game_mode != GM_MENU) ShowVitalWindows();
00085 _gw.active = false;
00086 _gw.proc = NULL;
00087 _gw.abortp = NULL;
00088 _gw.threaded = false;
00089
00090 DeleteWindowById(WC_GENERATE_PROGRESS_WINDOW, 0);
00091 MarkWholeScreenDirty();
00092 }
00093
00097 static void _GenerateWorld(void *)
00098 {
00099
00100 Backup<CompanyByte> _cur_company(_current_company, OWNER_NONE, FILE_LINE);
00101
00102 try {
00103 _generating_world = true;
00104 _genworld_mapgen_mutex->BeginCritical();
00105 if (_network_dedicated) DEBUG(net, 0, "Generating map, please wait...");
00106
00107 if (_settings_game.game_creation.generation_seed == GENERATE_NEW_SEED) _settings_game.game_creation.generation_seed = _settings_newgame.game_creation.generation_seed = InteractiveRandom();
00108 _random.SetSeed(_settings_game.game_creation.generation_seed);
00109 SetGeneratingWorldProgress(GWP_MAP_INIT, 2);
00110 SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0);
00111
00112 IncreaseGeneratingWorldProgress(GWP_MAP_INIT);
00113
00114 StartupEconomy();
00115
00116
00117 if (_gw.mode == GWM_EMPTY) {
00118 SetGeneratingWorldProgress(GWP_OBJECT, 1);
00119
00120
00121 if (_settings_game.construction.freeform_edges) {
00122 for (uint row = 0; row < MapSizeY(); row++) MakeVoid(TileXY(0, row));
00123 for (uint col = 0; col < MapSizeX(); col++) MakeVoid(TileXY(col, 0));
00124 }
00125
00126
00127 if (_game_mode != GM_MENU) FlatEmptyWorld(_settings_game.game_creation.se_flat_world_height);
00128
00129 ConvertGroundTilesIntoWaterTiles();
00130 IncreaseGeneratingWorldProgress(GWP_OBJECT);
00131 } else {
00132 GenerateLandscape(_gw.mode);
00133 GenerateClearTile();
00134
00135
00136 if (_game_mode != GM_EDITOR) {
00137 if (!GenerateTowns(_settings_game.economy.town_layout)) {
00138 _cur_company.Restore();
00139 HandleGeneratingWorldAbortion();
00140 return;
00141 }
00142 GenerateIndustries();
00143 GenerateObjects();
00144 GenerateTrees();
00145 }
00146 }
00147
00148 ClearStorageChanges(true);
00149
00150
00151 SetGeneratingWorldProgress(GWP_GAME_INIT, 3);
00152 StartupCompanies();
00153 IncreaseGeneratingWorldProgress(GWP_GAME_INIT);
00154 StartupEngines();
00155 IncreaseGeneratingWorldProgress(GWP_GAME_INIT);
00156 StartupDisasters();
00157 _generating_world = false;
00158
00159
00160 if (_gw.mode != GWM_EMPTY) {
00161 uint i;
00162
00163 SetGeneratingWorldProgress(GWP_RUNTILELOOP, 0x500);
00164 for (i = 0; i < 0x500; i++) {
00165 RunTileLoop();
00166 IncreaseGeneratingWorldProgress(GWP_RUNTILELOOP);
00167 }
00168 }
00169
00170 ResetObjectToPlace();
00171 _cur_company.Trash();
00172 _current_company = _local_company = _gw.lc;
00173
00174 SetGeneratingWorldProgress(GWP_GAME_START, 1);
00175
00176 if (_gw.proc != NULL) _gw.proc();
00177 IncreaseGeneratingWorldProgress(GWP_GAME_START);
00178
00179 CleanupGeneration();
00180 _genworld_mapgen_mutex->EndCritical();
00181
00182 ShowNewGRFError();
00183
00184 if (_network_dedicated) DEBUG(net, 0, "Map generated, starting game");
00185 DEBUG(desync, 1, "new_map: %08x", _settings_game.game_creation.generation_seed);
00186
00187 if (_debug_desync_level > 0) {
00188 char name[MAX_PATH];
00189 snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
00190 SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR, false);
00191 }
00192 } catch (...) {
00193 if (_cur_company.IsValid()) _cur_company.Restore();
00194 _generating_world = false;
00195 _genworld_mapgen_mutex->EndCritical();
00196 throw;
00197 }
00198 }
00199
00205 void GenerateWorldSetCallback(GWDoneProc *proc)
00206 {
00207 _gw.proc = proc;
00208 }
00209
00215 void GenerateWorldSetAbortCallback(GWAbortProc *proc)
00216 {
00217 _gw.abortp = proc;
00218 }
00219
00224 void WaitTillGeneratedWorld()
00225 {
00226 if (_gw.thread == NULL) return;
00227
00228 _genworld_mapgen_mutex->EndCritical();
00229 _genworld_paint_mutex->EndCritical();
00230 _gw.quit_thread = true;
00231 _gw.thread->Join();
00232 delete _gw.thread;
00233 _gw.thread = NULL;
00234 _gw.threaded = false;
00235 _genworld_mapgen_mutex->BeginCritical();
00236 _genworld_paint_mutex->BeginCritical();
00237 }
00238
00242 void AbortGeneratingWorld()
00243 {
00244 _gw.abort = true;
00245 }
00246
00251 bool IsGeneratingWorldAborted()
00252 {
00253 return _gw.abort;
00254 }
00255
00259 void HandleGeneratingWorldAbortion()
00260 {
00261
00262 _switch_mode = (_game_mode == GM_EDITOR) ? SM_EDITOR : SM_MENU;
00263
00264 if (_gw.abortp != NULL) _gw.abortp();
00265
00266 CleanupGeneration();
00267
00268 if (_gw.thread != NULL) _gw.thread->Exit();
00269
00270 extern void SwitchToMode(SwitchMode new_mode);
00271 SwitchToMode(_switch_mode);
00272 }
00273
00281 void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_settings)
00282 {
00283 if (_gw.active) return;
00284 _gw.mode = mode;
00285 _gw.size_x = size_x;
00286 _gw.size_y = size_y;
00287 _gw.active = true;
00288 _gw.abort = false;
00289 _gw.abortp = NULL;
00290 _gw.lc = _local_company;
00291 _gw.quit_thread = false;
00292 _gw.threaded = true;
00293
00294
00295 SetLocalCompany(COMPANY_SPECTATOR);
00296
00297 InitializeGame(_gw.size_x, _gw.size_y, true, reset_settings);
00298 PrepareGenerateWorldProgress();
00299
00300
00301 GfxLoadSprites();
00302 LoadStringWidthTable();
00303
00304
00305 ResetWindowSystem();
00306
00307
00308 SetupColoursAndInitialWindow();
00309 SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0);
00310
00311 if (_gw.thread != NULL) {
00312 _gw.thread->Join();
00313 delete _gw.thread;
00314 _gw.thread = NULL;
00315 }
00316
00317 if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 0 ||
00318 !ThreadObject::New(&_GenerateWorld, NULL, &_gw.thread)) {
00319 DEBUG(misc, 1, "Cannot create genworld thread, reverting to single-threaded mode");
00320 _gw.threaded = false;
00321 _genworld_mapgen_mutex->EndCritical();
00322 _GenerateWorld(NULL);
00323 _genworld_mapgen_mutex->BeginCritical();
00324 return;
00325 }
00326
00327
00328 DeleteAllNonVitalWindows();
00329
00330 HideVitalWindows();
00331
00332
00333 ShowGenerateWorldProgress();
00334
00335
00336 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) {
00337 ScrollMainWindowToTile(TileXY(MapSizeX() / 2, MapSizeY() / 2), true);
00338 }
00339 }