|
@@ -179,25 +179,25 @@ static void ShowHelp()
|
|
|
" -b drv = Set the blitter to use (see below)\n"
|
|
|
" -r res = Set resolution (for instance 800x600)\n"
|
|
|
" -h = Display this help text\n"
|
|
|
" -t year = Set starting year\n"
|
|
|
" -d [[fac=]lvl[,...]]= Debug mode\n"
|
|
|
" -e = Start Editor\n"
|
|
|
" -g [savegame] = Start new/save game immediately\n"
|
|
|
" -G seed = Set random seed\n"
|
|
|
" -n [ip:port#company]= Join network game\n"
|
|
|
" -p password = Password to join server\n"
|
|
|
" -P password = Password to join company\n"
|
|
|
" -D [ip][:port] = Start dedicated server\n"
|
|
|
" -l ip[:port] = Redirect DEBUG()\n"
|
|
|
" -l ip[:port] = Redirect Debug()\n"
|
|
|
#if !defined(_WIN32)
|
|
|
" -f = Fork into the background (dedicated only)\n"
|
|
|
#endif
|
|
|
" -I graphics_set = Force the graphics set (see below)\n"
|
|
|
" -S sounds_set = Force the sounds set (see below)\n"
|
|
|
" -M music_set = Force the music set (see below)\n"
|
|
|
" -c config_file = Use 'config_file' instead of 'openttd.cfg'\n"
|
|
|
" -x = Never save configuration changes to disk\n"
|
|
|
" -X = Don't use global folders to search for files\n"
|
|
|
" -q savegame = Write some information about the savegame and exit\n"
|
|
|
"\n",
|
|
|
lastof(buf)
|
|
@@ -657,25 +657,25 @@ int openttd_main(int argc, char *argv[])
|
|
|
DeterminePaths(argv[0], only_local_path);
|
|
|
TarScanner::DoScan(TarScanner::BASESET);
|
|
|
BaseGraphics::FindSets();
|
|
|
BaseSounds::FindSets();
|
|
|
BaseMusic::FindSets();
|
|
|
ShowHelp();
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
DeterminePaths(argv[0], only_local_path);
|
|
|
TarScanner::DoScan(TarScanner::BASESET);
|
|
|
|
|
|
if (dedicated) DEBUG(net, 3, "Starting dedicated server, version %s", _openttd_revision);
|
|
|
if (dedicated) Debug(net, 3, "Starting dedicated server, version {}", _openttd_revision);
|
|
|
if (_dedicated_forks && !dedicated) _dedicated_forks = false;
|
|
|
|
|
|
#if defined(UNIX)
|
|
|
/* We must fork here, or we'll end up without some resources we need (like sockets) */
|
|
|
if (_dedicated_forks) DedicatedFork();
|
|
|
#endif
|
|
|
|
|
|
LoadFromConfig(true);
|
|
|
|
|
|
if (resolution.width != 0) _cur_resolution = resolution;
|
|
|
|
|
|
/* Limit width times height times bytes per pixel to fit a 32 bit
|
|
@@ -706,25 +706,25 @@ int openttd_main(int argc, char *argv[])
|
|
|
if (!graphics_set.empty()) {
|
|
|
BaseGraphics::SetSet({});
|
|
|
|
|
|
ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND);
|
|
|
msg.SetDParamStr(0, graphics_set);
|
|
|
ScheduleErrorMessage(msg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Initialize game palette */
|
|
|
GfxInitPalettes();
|
|
|
|
|
|
DEBUG(misc, 1, "Loading blitter...");
|
|
|
Debug(misc, 1, "Loading blitter...");
|
|
|
if (blitter.empty() && !_ini_blitter.empty()) blitter = _ini_blitter;
|
|
|
_blitter_autodetected = blitter.empty();
|
|
|
/* Activate the initial blitter.
|
|
|
* This is only some initial guess, after NewGRFs have been loaded SwitchNewGRFBlitter may switch to a different one.
|
|
|
* - Never guess anything, if the user specified a blitter. (_blitter_autodetected)
|
|
|
* - Use 32bpp blitter if baseset or 8bpp-support settings says so.
|
|
|
* - Use 8bpp blitter otherwise.
|
|
|
*/
|
|
|
if (!_blitter_autodetected ||
|
|
|
(_support8bpp != S8BPP_NONE && (BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->blitter == BLT_8BPP)) ||
|
|
|
BlitterFactory::SelectBlitter("32bpp-anim") == nullptr) {
|
|
|
if (BlitterFactory::SelectBlitter(blitter) == nullptr) {
|
|
@@ -936,25 +936,25 @@ bool SafeLoad(const std::string &filenam
|
|
|
|
|
|
switch (lf == nullptr ? SaveOrLoad(filename, fop, dft, subdir) : LoadWithFilter(lf)) {
|
|
|
case SL_OK: return true;
|
|
|
|
|
|
case SL_REINIT:
|
|
|
if (_network_dedicated) {
|
|
|
/*
|
|
|
* We need to reinit a network map...
|
|
|
* We can't simply load the intro game here as that game has many
|
|
|
* special cases which make clients desync immediately. So we fall
|
|
|
* back to just generating a new game with the current settings.
|
|
|
*/
|
|
|
DEBUG(net, 0, "Loading game failed, so a new (random) game will be started");
|
|
|
Debug(net, 0, "Loading game failed, so a new (random) game will be started");
|
|
|
MakeNewGame(false, true);
|
|
|
return false;
|
|
|
}
|
|
|
if (_network_server) {
|
|
|
/* We can't load the intro game as server, so disconnect first. */
|
|
|
NetworkDisconnect();
|
|
|
}
|
|
|
|
|
|
switch (ogm) {
|
|
|
default:
|
|
|
case GM_MENU: LoadIntroGame(); break;
|
|
|
case GM_EDITOR: MakeNewEditorWorld(); break;
|
|
@@ -1127,40 +1127,40 @@ static void CheckCaches()
|
|
|
std::vector<TownCache> old_town_caches;
|
|
|
for (const Town *t : Town::Iterate()) {
|
|
|
old_town_caches.push_back(t->cache);
|
|
|
}
|
|
|
|
|
|
extern void RebuildTownCaches();
|
|
|
RebuildTownCaches();
|
|
|
RebuildSubsidisedSourceAndDestinationCache();
|
|
|
|
|
|
uint i = 0;
|
|
|
for (Town *t : Town::Iterate()) {
|
|
|
if (MemCmpT(old_town_caches.data() + i, &t->cache) != 0) {
|
|
|
DEBUG(desync, 2, "town cache mismatch: town %i", (int)t->index);
|
|
|
Debug(desync, 2, "town cache mismatch: town {}", t->index);
|
|
|
}
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
/* Check company infrastructure cache. */
|
|
|
std::vector<CompanyInfrastructure> old_infrastructure;
|
|
|
for (const Company *c : Company::Iterate()) old_infrastructure.push_back(c->infrastructure);
|
|
|
|
|
|
extern void AfterLoadCompanyStats();
|
|
|
AfterLoadCompanyStats();
|
|
|
|
|
|
i = 0;
|
|
|
for (const Company *c : Company::Iterate()) {
|
|
|
if (MemCmpT(old_infrastructure.data() + i, &c->infrastructure) != 0) {
|
|
|
DEBUG(desync, 2, "infrastructure cache mismatch: company %i", (int)c->index);
|
|
|
Debug(desync, 2, "infrastructure cache mismatch: company {}", c->index);
|
|
|
}
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
/* Strict checking of the road stop cache entries */
|
|
|
for (const RoadStop *rs : RoadStop::Iterate()) {
|
|
|
if (IsStandardRoadStopTile(rs->xy)) continue;
|
|
|
|
|
|
assert(rs->GetEntry(DIAGDIR_NE) != rs->GetEntry(DIAGDIR_NW));
|
|
|
rs->GetEntry(DIAGDIR_NE)->CheckIntegrity(rs);
|
|
|
rs->GetEntry(DIAGDIR_NW)->CheckIntegrity(rs);
|
|
|
}
|
|
@@ -1199,41 +1199,41 @@ static void CheckCaches()
|
|
|
switch (v->type) {
|
|
|
case VEH_TRAIN: Train::From(v)->ConsistChanged(CCF_TRACK); break;
|
|
|
case VEH_ROAD: RoadVehUpdateCache(RoadVehicle::From(v)); break;
|
|
|
case VEH_AIRCRAFT: UpdateAircraftCache(Aircraft::From(v)); break;
|
|
|
case VEH_SHIP: Ship::From(v)->UpdateCache(); break;
|
|
|
default: break;
|
|
|
}
|
|
|
|
|
|
length = 0;
|
|
|
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
|
|
|
FillNewGRFVehicleCache(u);
|
|
|
if (memcmp(&grf_cache[length], &u->grf_cache, sizeof(NewGRFCache)) != 0) {
|
|
|
DEBUG(desync, 2, "newgrf cache mismatch: type %i, vehicle %i, company %i, unit number %i, wagon %i", (int)v->type, v->index, (int)v->owner, v->unitnumber, length);
|
|
|
Debug(desync, 2, "newgrf cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
|
|
|
}
|
|
|
if (memcmp(&veh_cache[length], &u->vcache, sizeof(VehicleCache)) != 0) {
|
|
|
DEBUG(desync, 2, "vehicle cache mismatch: type %i, vehicle %i, company %i, unit number %i, wagon %i", (int)v->type, v->index, (int)v->owner, v->unitnumber, length);
|
|
|
Debug(desync, 2, "vehicle cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
|
|
|
}
|
|
|
switch (u->type) {
|
|
|
case VEH_TRAIN:
|
|
|
if (memcmp(&gro_cache[length], &Train::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
|
|
|
DEBUG(desync, 2, "train ground vehicle cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
|
|
|
Debug(desync, 2, "train ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
|
|
|
}
|
|
|
if (memcmp(&tra_cache[length], &Train::From(u)->tcache, sizeof(TrainCache)) != 0) {
|
|
|
DEBUG(desync, 2, "train cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
|
|
|
Debug(desync, 2, "train cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
|
|
|
}
|
|
|
break;
|
|
|
case VEH_ROAD:
|
|
|
if (memcmp(&gro_cache[length], &RoadVehicle::From(u)->gcache, sizeof(GroundVehicleCache)) != 0) {
|
|
|
DEBUG(desync, 2, "road vehicle ground vehicle cache mismatch: vehicle %i, company %i, unit number %i, wagon %i", v->index, (int)v->owner, v->unitnumber, length);
|
|
|
Debug(desync, 2, "road vehicle ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
length++;
|
|
|
}
|
|
|
|
|
|
free(grf_cache);
|
|
|
free(veh_cache);
|
|
|
free(gro_cache);
|
|
|
free(tra_cache);
|
|
@@ -1262,52 +1262,52 @@ static void CheckCaches()
|
|
|
assert(memcmp(&st->goods[c].cargo, buff, sizeof(StationCargoList)) == 0);
|
|
|
}
|
|
|
|
|
|
/* Check docking tiles */
|
|
|
TileArea ta;
|
|
|
std::map<TileIndex, bool> docking_tiles;
|
|
|
for (TileIndex tile : st->docking_station) {
|
|
|
ta.Add(tile);
|
|
|
docking_tiles[tile] = IsDockingTile(tile);
|
|
|
}
|
|
|
UpdateStationDockingTiles(st);
|
|
|
if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) {
|
|
|
DEBUG(desync, 2, "station docking mismatch: station %i, company %i", st->index, (int)st->owner);
|
|
|
Debug(desync, 2, "station docking mismatch: station {}, company {}", st->index, st->owner);
|
|
|
}
|
|
|
for (TileIndex tile : ta) {
|
|
|
if (docking_tiles[tile] != IsDockingTile(tile)) {
|
|
|
DEBUG(desync, 2, "docking tile mismatch: tile %i", (int)tile);
|
|
|
Debug(desync, 2, "docking tile mismatch: tile {}", tile);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Check industries_near */
|
|
|
IndustryList industries_near = st->industries_near;
|
|
|
st->RecomputeCatchment();
|
|
|
if (st->industries_near != industries_near) {
|
|
|
DEBUG(desync, 2, "station industries near mismatch: station %i", st->index);
|
|
|
Debug(desync, 2, "station industries near mismatch: station {}", st->index);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Check stations_near */
|
|
|
i = 0;
|
|
|
for (Town *t : Town::Iterate()) {
|
|
|
if (t->stations_near != old_town_stations_near[i]) {
|
|
|
DEBUG(desync, 2, "town stations near mismatch: town %i", t->index);
|
|
|
Debug(desync, 2, "town stations near mismatch: town {}", t->index);
|
|
|
}
|
|
|
i++;
|
|
|
}
|
|
|
i = 0;
|
|
|
for (Industry *ind : Industry::Iterate()) {
|
|
|
if (ind->stations_near != old_industry_stations_near[i]) {
|
|
|
DEBUG(desync, 2, "industry stations near mismatch: industry %i", ind->index);
|
|
|
Debug(desync, 2, "industry stations near mismatch: industry {}", ind->index);
|
|
|
}
|
|
|
i++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* State controlling game loop.
|
|
|
* The state must not be changed from anywhere but here.
|
|
|
* That check is enforced in DoCommand.
|
|
|
*/
|
|
|
void StateGameLoop()
|
|
|
{
|
|
@@ -1397,25 +1397,25 @@ static void DoAutosave()
|
|
|
if (_settings_client.gui.keep_all_autosave) {
|
|
|
GenerateDefaultSaveName(buf, lastof(buf));
|
|
|
strecat(buf, ".sav", lastof(buf));
|
|
|
} else {
|
|
|
static int _autosave_ctr = 0;
|
|
|
|
|
|
/* generate a savegame name and number according to _settings_client.gui.max_num_autosaves */
|
|
|
seprintf(buf, lastof(buf), "autosave%d.sav", _autosave_ctr);
|
|
|
|
|
|
if (++_autosave_ctr >= _settings_client.gui.max_num_autosaves) _autosave_ctr = 0;
|
|
|
}
|
|
|
|
|
|
DEBUG(sl, 2, "Autosaving to '%s'", buf);
|
|
|
Debug(sl, 2, "Autosaving to '{}'", buf);
|
|
|
if (SaveOrLoad(buf, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR) != SL_OK) {
|
|
|
ShowErrorMessage(STR_ERROR_AUTOSAVE_FAILED, INVALID_STRING_ID, WL_ERROR);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Request a new NewGRF scan. This will be executed on the next game-tick.
|
|
|
* This is mostly needed to ensure NewGRF scans (which are blocking) are
|
|
|
* done in the game-thread, and not in the draw-thread (which most often
|
|
|
* triggers this request).
|
|
|
* @param callback Optional callback to call when NewGRF scan is completed.
|
|
|
* @return True when the NewGRF scan was actually requested, false when the scan was already running.
|