static void MakeNewGameDone() { SettingsDisableElrail(_settings_game.vehicle.disable_elrails); /* In a dedicated server, the server does not play */ if (!VideoDriver::GetInstance()->HasGUI()) { SetLocalCompany(COMPANY_SPECTATOR); if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE); IConsoleCmdExec("exec scripts/game_start.scr 0"); return; } /* Create a single company */ DoStartupNewCompany(false); Company *c = Company::Get(COMPANY_FIRST); c->settings = _settings_client.company; IConsoleCmdExec("exec scripts/game_start.scr 0"); SetLocalCompany(COMPANY_FIRST); InitializeRailGUI(); #ifdef ENABLE_NETWORK /* We are the server, we start a new company (not dedicated), * so set the default password *if* needed. */ if (_network_server && !StrEmpty(_settings_client.network.default_company_pass)) { NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); } #endif /* ENABLE_NETWORK */ if (_settings_client.gui.pause_on_newgame) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE); CheckEngines(); CheckIndustries(); MarkWholeScreenDirty(); }
static void MakeNewEditorWorldDone() { SetLocalCompany(OWNER_NONE); }
void SwitchToMode(SwitchMode new_mode) { #ifdef ENABLE_NETWORK /* If we are saving something, the network stays in his current state */ if (new_mode != SM_SAVE_GAME) { /* If the network is active, make it not-active */ if (_networking) { if (_network_server && (new_mode == SM_LOAD_GAME || new_mode == SM_NEWGAME || new_mode == SM_RESTARTGAME)) { NetworkReboot(); } else { NetworkDisconnect(); } } /* If we are a server, we restart the server */ if (_is_network_server) { /* But not if we are going to the menu */ if (new_mode != SM_MENU) { /* check if we should reload the config */ if (_settings_client.network.reload_cfg) { LoadFromConfig(); MakeNewgameSettingsLive(); ResetGRFConfig(false); } NetworkServerStart(); } else { /* This client no longer wants to be a network-server */ _is_network_server = false; } } } #endif /* ENABLE_NETWORK */ /* Make sure all AI controllers are gone at quitting game */ if (new_mode != SM_SAVE_GAME) AI::KillAll(); switch (new_mode) { case SM_EDITOR: // Switch to scenario editor MakeNewEditorWorld(); break; case SM_RESTARTGAME: // Restart --> 'Random game' with current settings case SM_NEWGAME: // New Game --> 'Random game' #ifdef ENABLE_NETWORK if (_network_server) { seprintf(_network_game_info.map_name, lastof(_network_game_info.map_name), "Random Map"); } #endif /* ENABLE_NETWORK */ MakeNewGame(false, new_mode == SM_NEWGAME); break; case SM_LOAD_GAME: { // Load game, Play Scenario ResetGRFConfig(true); ResetWindowSystem(); if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_NORMAL, NO_DIRECTORY)) { SetDParamStr(0, GetSaveLoadErrorString()); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); } else { if (_file_to_saveload.abstract_ftype == FT_SCENARIO) { /* Reset engine pool to simplify changing engine NewGRFs in scenario editor. */ EngineOverrideManager::ResetToCurrentNewGRFConfig(); } /* Update the local company for a loaded game. It is either always * company #1 (eg 0) or in the case of a dedicated server a spectator */ SetLocalCompany(_network_dedicated ? COMPANY_SPECTATOR : COMPANY_FIRST); /* Execute the game-start script */ IConsoleCmdExec("exec scripts/game_start.scr 0"); /* Decrease pause counter (was increased from opening load dialog) */ DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE); #ifdef ENABLE_NETWORK if (_network_server) { seprintf(_network_game_info.map_name, lastof(_network_game_info.map_name), "%s (Loaded game)", _file_to_saveload.title); } #endif /* ENABLE_NETWORK */ } break; } case SM_START_HEIGHTMAP: // Load a heightmap and start a new game from it #ifdef ENABLE_NETWORK if (_network_server) { seprintf(_network_game_info.map_name, lastof(_network_game_info.map_name), "%s (Heightmap)", _file_to_saveload.title); } #endif /* ENABLE_NETWORK */ MakeNewGame(true, true); break; case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor SetLocalCompany(OWNER_NONE); GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); MarkWholeScreenDirty(); break; case SM_LOAD_SCENARIO: { // Load scenario from scenario editor if (SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_EDITOR, NO_DIRECTORY)) { SetLocalCompany(OWNER_NONE); _settings_newgame.game_creation.starting_year = _cur_year; /* Cancel the saveload pausing */ DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE); } else { SetDParamStr(0, GetSaveLoadErrorString()); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); } break; } case SM_MENU: // Switch to game intro menu LoadIntroGame(); if (BaseSounds::ini_set == NULL && BaseSounds::GetUsedSet()->fallback) { ShowErrorMessage(STR_WARNING_FALLBACK_SOUNDSET, INVALID_STRING_ID, WL_CRITICAL); BaseSounds::ini_set = stredup(BaseSounds::GetUsedSet()->name); } break; case SM_SAVE_GAME: // Save game. /* Make network saved games on pause compatible to singleplayer */ if (SaveOrLoad(_file_to_saveload.name, SLO_SAVE, DFT_GAME_FILE, NO_DIRECTORY) != SL_OK) { SetDParamStr(0, GetSaveLoadErrorString()); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); } else { DeleteWindowById(WC_SAVELOAD, 0); } break; case SM_SAVE_HEIGHTMAP: // Save heightmap. MakeHeightmapScreenshot(_file_to_saveload.name); DeleteWindowById(WC_SAVELOAD, 0); break; case SM_GENRANDLAND: // Generate random land within scenario editor SetLocalCompany(OWNER_NONE); GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); /* XXX: set date */ MarkWholeScreenDirty(); break; default: NOT_REACHED(); } }
/** * Control the companies: add, delete, etc. * @param tile unused * @param flags operation to perform * @param p1 various functionality * - bits 0..15: * = 0 - create a new company * = 1 - create a new AI company * = 2 - delete a company * - bits 16..24: CompanyID * @param p2 ClientID * @param text unused * @return the cost of this operation or an error */ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0); CompanyID company_id = (CompanyID)GB(p1, 16, 8); #ifdef ENABLE_NETWORK ClientID client_id = (ClientID)p2; #endif /* ENABLE_NETWORK */ switch (GB(p1, 0, 16)) { case 0: { // Create a new company /* This command is only executed in a multiplayer game */ if (!_networking) return CMD_ERROR; #ifdef ENABLE_NETWORK /* Has the network client a correct ClientIndex? */ if (!(flags & DC_EXEC)) return CommandCost(); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); #ifndef DEBUG_DUMP_COMMANDS /* When replaying the client ID is not a valid client; there * are actually no clients at all. However, the company has to * be created, otherwise we cannot rerun the game properly. * So only allow a NULL client info in that case. */ if (ci == NULL) return CommandCost(); #endif /* NOT DEBUG_DUMP_COMMANDS */ /* Delete multiplayer progress bar */ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); Company *c = DoStartupNewCompany(false); /* A new company could not be created, revert to being a spectator */ if (c == NULL) { if (_network_server) { ci->client_playas = COMPANY_SPECTATOR; NetworkUpdateClientInfo(ci->client_id); } break; } /* This is the client (or non-dedicated server) who wants a new company */ if (client_id == _network_own_client_id) { assert(_local_company == COMPANY_SPECTATOR); SetLocalCompany(c->index); if (!StrEmpty(_settings_client.network.default_company_pass)) { NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); } /* Now that we have a new company, broadcast our company settings to * all clients so everything is in sync */ SyncCompanySettings(); MarkWholeScreenDirty(); } if (_network_server) { if (ci != NULL) { /* ci is only NULL when replaying. * When replaying no client is actually in need of an update. */ ci->client_playas = c->index; NetworkUpdateClientInfo(ci->client_id); } if (Company::IsValidID(c->index)) { _network_company_states[c->index].months_empty = 0; _network_company_states[c->index].password[0] = '\0'; NetworkServerUpdateCompanyPassworded(c->index, false); /* XXX - When a client joins, we automatically set its name to the * client's name (for some reason). As it stands now only the server * knows the client's name, so it needs to send out a "broadcast" to * do this. To achieve this we send a network command. However, it * uses _local_company to execute the command as. To prevent abuse * (eg. only yourself can change your name/company), we 'cheat' by * impersonation _local_company as the server. Not the best solution; * but it works. * TODO: Perhaps this could be improved by when the client is ready * with joining to let it send itself the command, and not the server? * For example in network_client.c:534? */ if (ci != NULL) { /* ci is only NULL when replaying. * When replaying, the command to rename the president will * automatically be ran, so this is not even needed to get * the exact same state. */ NetworkSendCommand(0, 0, 0, CMD_RENAME_PRESIDENT, NULL, ci->client_name, c->index); } } /* Announce new company on network. */ NetworkAdminCompanyInfo(c, true); if (ci != NULL) { /* ci is only NULL when replaying. * When replaying, the message that someone started a new company * is not interesting at all. */ NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, c->index + 1); } } #endif /* ENABLE_NETWORK */ break; } case 1: // Make a new AI company if (!(flags & DC_EXEC)) return CommandCost(); if (company_id != INVALID_COMPANY && (company_id >= MAX_COMPANIES || Company::IsValidID(company_id))) return CMD_ERROR; DoStartupNewCompany(true, company_id); break; case 2: { // Delete a company CompanyRemoveReason reason = (CompanyRemoveReason)GB(p2, 0, 2); if (reason >= CRR_END) return CMD_ERROR; Company *c = Company::GetIfValid(company_id); if (c == NULL) return CMD_ERROR; if (!(flags & DC_EXEC)) return CommandCost(); /* Delete any open window of the company */ DeleteCompanyWindows(c->index); CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1); cni->FillData(c); /* Show the bankrupt news */ SetDParam(0, STR_NEWS_COMPANY_BANKRUPT_TITLE); SetDParam(1, STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION); SetDParamStr(2, cni->company_name); AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni); /* Remove the company */ ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER); if (c->is_ai) AI::Stop(c->index); CompanyID c_index = c->index; delete c; AI::BroadcastNewEvent(new ScriptEventCompanyBankrupt(c_index)); Game::NewEvent(new ScriptEventCompanyBankrupt(c_index)); CompanyAdminRemove(c_index, (CompanyRemoveReason)reason); break; } default: return CMD_ERROR; } InvalidateWindowClassesData(WC_GAME_OPTIONS); InvalidateWindowClassesData(WC_AI_SETTINGS); InvalidateWindowClassesData(WC_AI_LIST); return CommandCost(); }
/** Control the companies: add, delete, etc. * @param tile unused * @param flags operation to perform * @param p1 various functionality * - p1 = 0 - create a new company, Which company (network) it will be is in p2 * - p1 = 1 - create a new AI company * - p1 = 2 - delete a company. Company is identified by p2 * @param p2 various functionality, dictated by p1 * - p1 = 0 - ClientID of the newly created client * - p1 = 1 - CompanyID to start AI (INVALID_COMPANY for first available) * - p1 = 2 - CompanyID of the that is getting deleted * @param text unused * @return the cost of this operation or an error * * @todo In the case of p1=0, create new company, the clientID of the new client is in parameter * p2. This parameter is passed in at function DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) * on the server itself. First of all this is unbelievably ugly; second of all, well, * it IS ugly! <b>Someone fix this up :)</b> So where to fix?@n * @arg - network_server.c:838 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)@n * @arg - network_client.c:536 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP) from where the map has been received */ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0); switch (p1) { case 0: { // Create a new company /* This command is only executed in a multiplayer game */ if (!_networking) return CMD_ERROR; #ifdef ENABLE_NETWORK /* Joining Client: * _local_company: COMPANY_SPECTATOR * cid = clientid * * Other client(s)/server: * _local_company: what they play as * cid = requested company/company of joining client */ ClientID cid = (ClientID)p2; /* Has the network client a correct ClientIndex? */ if (!(flags & DC_EXEC)) return CommandCost(); NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(cid); if (ci == NULL) return CommandCost(); /* Delete multiplayer progress bar */ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0); Company *c = DoStartupNewCompany(false); /* A new company could not be created, revert to being a spectator */ if (c == NULL) { if (_network_server) { ci->client_playas = COMPANY_SPECTATOR; NetworkUpdateClientInfo(ci->client_id); } break; } /* This is the client (or non-dedicated server) who wants a new company */ if (cid == _network_own_client_id) { assert(_local_company == COMPANY_SPECTATOR); SetLocalCompany(c->index); if (!StrEmpty(_settings_client.network.default_company_pass)) { NetworkChangeCompanyPassword(_settings_client.network.default_company_pass); } /* Now that we have a new company, broadcast our company settings to * all clients so everything is in sync */ SyncCompanySettings(); MarkWholeScreenDirty(); } if (_network_server) { /* XXX - UGLY! p2 (pid) is mis-used to fetch the client-id, done at * server side in network_server.c:838, function * DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) */ CompanyID old_playas = ci->client_playas; ci->client_playas = c->index; NetworkUpdateClientInfo(ci->client_id); if (Company::IsValidID(ci->client_playas)) { _network_company_states[c->index].months_empty = 0; _network_company_states[c->index].password[0] = '\0'; NetworkServerUpdateCompanyPassworded(ci->client_playas, false); /* XXX - When a client joins, we automatically set its name to the * client's name (for some reason). As it stands now only the server * knows the client's name, so it needs to send out a "broadcast" to * do this. To achieve this we send a network command. However, it * uses _local_company to execute the command as. To prevent abuse * (eg. only yourself can change your name/company), we 'cheat' by * impersonation _local_company as the server. Not the best solution; * but it works. * TODO: Perhaps this could be improved by when the client is ready * with joining to let it send itself the command, and not the server? * For example in network_client.c:534? */ NetworkSend_Command(0, 0, 0, CMD_RENAME_PRESIDENT, NULL, ci->client_name, ci->client_playas); } /* Announce new company on network, if the client was a SPECTATOR before */ if (old_playas == COMPANY_SPECTATOR) { NetworkServerSendChat(NETWORK_ACTION_COMPANY_NEW, DESTTYPE_BROADCAST, 0, "", ci->client_id, ci->client_playas + 1); } } #endif /* ENABLE_NETWORK */ } break; case 1: // Make a new AI company if (!(flags & DC_EXEC)) return CommandCost(); if (p2 != INVALID_COMPANY && (p2 >= MAX_COMPANIES || Company::IsValidID(p2))) return CMD_ERROR; DoStartupNewCompany(true, (CompanyID)p2); break; case 2: { // Delete a company Company *c = Company::GetIfValid(p2); if (c == NULL) return CMD_ERROR; if (!(flags & DC_EXEC)) return CommandCost(); /* Delete any open window of the company */ DeleteCompanyWindows(c->index); CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1); cni->FillData(c); /* Show the bankrupt news */ SetDParam(0, STR_NEWS_COMPANY_BANKRUPT_TITLE); SetDParam(1, STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION); SetDParamStr(2, cni->company_name); AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, NS_COMPANY_BANKRUPT, cni); /* Remove the company */ ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER); if (c->is_ai) AI::Stop(c->index); CompanyID c_index = c->index; delete c; AI::BroadcastNewEvent(new AIEventCompanyBankrupt(c_index)); } break; default: return CMD_ERROR; } return CommandCost(); }
/** * Control the companies: add, delete, etc. * @param tile unused * @param flags operation to perform * @param p1 various functionality * - bits 0..15: * = 0 - create a new company * = 1 - create a new AI company * = 2 - delete a company * - bits 16..24: CompanyID * @param p2 ClientID * @param text unused * @return the cost of this operation or an error */ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0); CompanyID company_id = (CompanyID)GB(p1, 16, 8); #ifdef ENABLE_NETWORK ClientID client_id = (ClientID)p2; #endif /* ENABLE_NETWORK */ switch (GB(p1, 0, 16)) { case 0: { // Create a new company /* This command is only executed in a multiplayer game */ if (!_networking) return CMD_ERROR; #ifdef ENABLE_NETWORK /* Has the network client a correct ClientIndex? */ if (!(flags & DC_EXEC)) return CommandCost(); NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); #ifndef DEBUG_DUMP_COMMANDS /* When replaying the client ID is not a valid client; there * are actually no clients at all. However, the company has to * be created, otherwise we cannot rerun the game properly. * So only allow a NULL client info in that case. */ if (ci == NULL) return CommandCost(); #endif /* NOT DEBUG_DUMP_COMMANDS */ /* Delete multiplayer progress bar */ DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); Company *c = DoStartupNewCompany(false); /* A new company could not be created, revert to being a spectator */ if (c == NULL) { if (_network_server) { ci->client_playas = COMPANY_SPECTATOR; NetworkUpdateClientInfo(ci->client_id); } break; } /* This is the client (or non-dedicated server) who wants a new company */ if (client_id == _network_own_client_id) { assert(_local_company == COMPANY_SPECTATOR); SetLocalCompany(c->index); if (!StrEmpty(_settings_client.network.default_company_pass)) { NetworkChangeCompanyPassword(_local_company, _settings_client.network.default_company_pass); } /* Now that we have a new company, broadcast our company settings to * all clients so everything is in sync */ SyncCompanySettings(); MarkWholeScreenDirty(); } NetworkServerNewCompany(c, ci); #endif /* ENABLE_NETWORK */ break; } case 1: { // Make a new AI company if (!(flags & DC_EXEC)) return CommandCost(); if (company_id != INVALID_COMPANY && (company_id >= MAX_COMPANIES || Company::IsValidID(company_id))) return CMD_ERROR; Company *c = DoStartupNewCompany(true, company_id); #ifdef ENABLE_NETWORK if (c != NULL) NetworkServerNewCompany(c, NULL); #endif /* ENABLE_NETWORK */ break; } case 2: { // Delete a company CompanyRemoveReason reason = (CompanyRemoveReason)GB(p2, 0, 2); if (reason >= CRR_END) return CMD_ERROR; Company *c = Company::GetIfValid(company_id); if (c == NULL) return CMD_ERROR; if (!(flags & DC_EXEC)) return CommandCost(); /* Delete any open window of the company */ DeleteCompanyWindows(c->index); CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1); cni->FillData(c); /* Show the bankrupt news */ SetDParam(0, STR_NEWS_COMPANY_BANKRUPT_TITLE); SetDParam(1, STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION); SetDParamStr(2, cni->company_name); AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni); /* Remove the company */ ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER); if (c->is_ai) AI::Stop(c->index); CompanyID c_index = c->index; delete c; AI::BroadcastNewEvent(new ScriptEventCompanyBankrupt(c_index)); Game::NewEvent(new ScriptEventCompanyBankrupt(c_index)); CompanyAdminRemove(c_index, (CompanyRemoveReason)reason); if (StoryPage::GetNumItems() == 0 || Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0); break; } default: return CMD_ERROR; } InvalidateWindowClassesData(WC_GAME_OPTIONS); InvalidateWindowClassesData(WC_AI_SETTINGS); InvalidateWindowClassesData(WC_AI_LIST); return CommandCost(); }