ServerNewGameState.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <set>
00022 #include <server/ServerNewGameState.h>
00023 #include <server/ServerState.h>
00024 #include <server/ScorchedServer.h>
00025 #include <server/ServerMessageHandler.h>
00026 #include <server/ServerChannelManager.h>
00027 #include <server/TurnController.h>
00028 #include <server/ServerCommon.h>
00029 #ifndef S3D_SERVER
00030         #include <client/ClientSave.h>
00031 #endif
00032 #include <tankai/TankAIAdder.h>
00033 #include <tank/TankContainer.h>
00034 #include <tank/TankSort.h>
00035 #include <tank/TankTeamScore.h>
00036 #include <tank/TankDeadContainer.h>
00037 #include <tank/TankModelStore.h>
00038 #include <tank/TankState.h>
00039 #include <tank/TankScore.h>
00040 #include <tank/TankPosition.h>
00041 #include <tank/TankAccessories.h>
00042 #include <tank/TankModelContainer.h>
00043 #include <target/TargetLife.h>
00044 #include <tankai/TankAI.h>
00045 #include <weapons/EconomyStore.h>
00046 #include <coms/ComsNewGameMessage.h>
00047 #include <coms/ComsMessageSender.h>
00048 #include <landscapemap/LandscapeMaps.h>
00049 #include <landscapedef/LandscapeDefn.h>
00050 #include <landscapedef/LandscapeDefinitions.h>
00051 #include <placement/PlacementTankPosition.h>
00052 #include <lua/LUAScriptHook.h>
00053 #include <common/RandomGenerator.h>
00054 #include <common/OptionsTransient.h>
00055 #include <common/OptionsScorched.h>
00056 #include <common/Clock.h>
00057 #include <common/StatsLogger.h>
00058 #include <common/Logger.h>
00059 #include <common/Defines.h>
00060 #include <algorithm>
00061 
00062 extern Clock serverTimer;
00063 
00064 ServerNewGameState::ServerNewGameState() :
00065         GameStateI("ServerNewGameState")
00066 {
00067         ScorchedServer::instance()->getLUAScriptHook().addHookProvider("server_newgame");
00068 }
00069 
00070 ServerNewGameState::~ServerNewGameState()
00071 {
00072 }
00073 
00074 void ServerNewGameState::enterState(const unsigned state)
00075 {
00076         std::list<Tank *> currentTanks;
00077         std::map<unsigned int, Tank *> &playingTanks =
00078                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00079         std::map<unsigned int, Tank *>::iterator playingTanksItor;
00080         for (playingTanksItor = playingTanks.begin();
00081                 playingTanksItor != playingTanks.end();
00082                 playingTanksItor++)
00083         {
00084                 Tank *tank = (*playingTanksItor).second;
00085                 currentTanks.push_back(tank);
00086         }
00087         StatsLogger::instance()->gameStart(currentTanks);
00088 
00089         // Tell clients a new game is starting
00090         ServerChannelManager::instance()->sendText(
00091                 ChannelText("info", "NEXT_ROUND", "Next Round"),
00092                 true);
00093 
00094         // Make any enconomic changes
00095         EconomyStore::instance()->getEconomy()->calculatePrices();
00096         EconomyStore::instance()->getEconomy()->savePrices();
00097 
00098         // Make sure the most up-to-date options are used and sent to the client
00099         // The original options are sent in the connection accept message
00100         // but send new options if the server has changed the options
00101         bool sendGameState = false;
00102         if (ScorchedServer::instance()->getOptionsGame().commitChanges())
00103         {
00104                 sendGameState = true;
00105                 ServerChannelManager::instance()->sendText(
00106                         ChannelText("info", 
00107                                 "GAME_OPTIONS_CHANGED", 
00108                                 "Game options have been changed!"),
00109                         true);
00110         }
00111 
00112         // Get a landscape definition to use
00113         LandscapeDefinition defn = ScorchedServer::instance()->getLandscapes().getRandomLandscapeDefn(
00114                 ScorchedServer::instance()->getContext().getOptionsGame(),
00115                 ScorchedServer::instance()->getContext().getTankContainer());
00116 
00117         // Load the per level options
00118         ScorchedServer::instance()->getOptionsGame().updateLevelOptions(
00119                 ScorchedServer::instance()->getContext(), defn);
00120 
00121         // Set all options (wind etc..)
00122         ScorchedServer::instance()->getContext().getOptionsTransient().newGame();
00123         ScorchedServer::instance()->getContext().getTankTeamScore().newGame();
00124 
00125         // Check if we can load/save a game
00126 #ifndef S3D_SERVER
00127         //if (ClientParams::instance()->getConnectedToServer() == false)
00128         {
00129                 if (ScorchedServer::instance()->getTankContainer().getNoOfTanks() == 0 ||
00130                         ScorchedServer::instance()->getTankContainer().getNoOfTanks() -
00131                         ScorchedServer::instance()->getTankContainer().getNoOfNonSpectatorTanks() > 1)
00132                 {
00133                         // We have not loaded players yet
00134                         // this is the very first landscape
00135                 }
00136                 else
00137                 {
00138                         // Not the first landscape
00139                         if (ClientSave::stateRestored())
00140                         {
00141                                 ClientSave::restoreClient(false, true);
00142                                 ClientSave::setStateNotRestored();
00143                         }
00144                         else
00145                         {
00146                                 ClientSave::storeClient();
00147                         }
00148                 }
00149         }
00150 #endif
00151 
00152         // Setup landscape and tank start pos
00153         ServerCommon::serverLog( "Generating landscape");
00154 
00155         // Remove any old targets
00156         removeTargets();
00157 
00158         // Check that we dont have too many bots
00159         checkBots(true);
00160 
00161         // Check teams are even
00162         checkTeams();
00163 
00164         // Make sure all tanks that should be playing are playing
00165         resetTankStates(state);
00166 
00167         // Generate the new level
00168         ScorchedServer::instance()->getLandscapeMaps().generateMaps(
00169                 ScorchedServer::instance()->getContext(), defn);
00170 
00171         // Add pending tanks (all tanks should be pending) into the game
00172         addTanksToGame(state, sendGameState);
00173 
00174         // Create the player order for this game
00175         TurnController::instance()->newGame();
00176 
00177         // Notify scripts of a new game starting
00178         ScorchedServer::instance()->getLUAScriptHook().callHook("server_newgame");
00179 
00180         // As we have not returned to the main loop for ages the
00181         // timer will have a lot of time in it
00182         // Get rid of this time so we don't screw things up
00183         serverTimer.getTimeDifference();
00184 
00185         // Move into the state that waits for players to become ready
00186         ScorchedServer::instance()->getTankContainer().setAllNotReady();
00187         ScorchedServer::instance()->getGameState().stimulate(ServerState::ServerStimulusNewGameReady);
00188 }
00189 
00190 int ServerNewGameState::addTanksToGame(const unsigned state,
00191                                                                            bool addState)
00192 {
00193         std::list<Tank *> tanks = resetTankStates(state);
00194         if (tanks.empty()) return 0;
00195 
00196         // Generate the level message
00197         ComsNewGameMessage newGameMessage;
00198         if (addState)
00199         {
00200                 // Tell client(s) of game settings changes
00201                 newGameMessage.addGameState(); 
00202         }
00203 
00204         // Add info about what targets are still alive
00205         std::map<unsigned int, Target *> &targets =
00206                 ScorchedServer::instance()->getTargetContainer().getTargets();
00207         std::map<unsigned int, Target *>::iterator targetItor;
00208         for (targetItor = targets.begin();
00209                 targetItor != targets.end();
00210                 targetItor++)
00211         {
00212                 Target *target = targetItor->second;
00213                 if (target->getPlayerId() >= TargetID::MIN_TARGET_ID &&
00214                         target->getPlayerId() < TargetID::MIN_TARGET_TRANSIENT_ID)
00215                 {
00216                         // Targets generated by the level code
00217                         newGameMessage.getLevelMessage().getTargetIds().insert(
00218                                 target->getPlayerId());
00219                         if (state != ServerState::ServerStateNewGame &&
00220                                 target->isTarget())
00221                         {
00222                                 newGameMessage.getLevelMessage().getOldTargets().addToBuffer(target->getPlayerId());
00223                                 target->writeMessage(newGameMessage.getLevelMessage().getOldTargets());                         
00224                         }
00225                 } 
00226                 else if (target->getPlayerId() >= TargetID::MIN_TARGET_TRANSIENT_ID &&
00227                         target->getPlayerId() < TargetID::MAX_TARGET_ID)
00228                 {
00229                         // Targets generated during play
00230                         newGameMessage.getLevelMessage().getNewTargets().addToBuffer(target->getPlayerId());
00231                         target->writeMessage(newGameMessage.getLevelMessage().getNewTargets());
00232                 }
00233         }
00234 
00235         // Add the height map info
00236         newGameMessage.getLevelMessage().createMessage(
00237                 ScorchedServer::instance()->getLandscapeMaps().getDefinitions().getDefinition());
00238         newGameMessage.getLevelMessage().getDeformInfos() = 
00239                 DeformLandscape::getInfos();
00240         LandscapeDefinitionCache &definitions =
00241                 ScorchedServer::instance()->getLandscapeMaps().getDefinitions();
00242         ServerCommon::serverLog(
00243                 S3D::formatStringBuffer("Finished generating landscape (%u, %s, %s)", 
00244                 definitions.getSeed(), 
00245                 definitions.getDefinition().getDefn(), 
00246                 definitions.getDefinition().getTex()));
00247 
00248         // Check if the generated landscape is too large to send to the clients
00249         int sendSize = int(newGameMessage.getLevelMessage().getDeformInfos().size()) *
00250                 sizeof(DeformLandscape::DeformInfo);
00251         if (sendSize > ScorchedServer::instance()->getOptionsGame().getMaxLandscapeSize())
00252         {
00253                 ServerChannelManager::instance()->sendText(
00254                         ChannelText("info", 
00255                                 "LANDSCAPE_TOO_LARGE",
00256                                 "Landscape too large to send to waiting clients ({0} bytes).", 
00257                                 sendSize),
00258                         true);
00259                 return 0;
00260         }
00261 
00262         // Used to ensure we only send messages to each
00263         // destination once
00264         std::list<unsigned int> sendDestinations;
00265         std::set<unsigned int> destinations;
00266         std::set<unsigned int>::iterator findItor;
00267 
00268         std::list<Tank *>::iterator itor;
00269         for (itor = tanks.begin();
00270                 itor != tanks.end();
00271                 itor++)
00272         {
00273                 Tank *tank = *itor;
00274 
00275                 // We need to wait for a ready message
00276                 tank->getState().setNotReady();
00277 
00278                 // Add to the list of destinations to send this message to
00279                 // (if not already added)
00280                 unsigned int destination = tank->getDestinationId();
00281                 findItor = destinations.find(destination);
00282                 if (findItor == destinations.end())
00283                 {
00284                         destinations.insert(destination);
00285                         sendDestinations.push_back(destination);
00286                 }
00287         }
00288 
00289         // Send after all of the states have been set
00290         // Do this after incase the message contains the new states
00291         ComsMessageSender::sendToMultipleClients(newGameMessage, sendDestinations);
00292 
00293         return (int) tanks.size();
00294 }
00295 
00296 std::list<Tank *> ServerNewGameState::resetTankStates(unsigned int state)
00297 {
00298         std::list<Tank *> resultingTanks;
00299 
00300         // Tell any pending tanks to join the game
00301         std::map<unsigned int, Tank *> &tanks = 
00302                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00303         std::map<unsigned int, Tank *>::iterator itor;
00304         for (itor = tanks.begin();
00305                 itor != tanks.end();
00306                 itor++)
00307         {
00308                 Tank *tank = (*itor).second;
00309                 // Check to see if any tanks are pending being added
00310                 if (tank->getState().getState() == TankState::sPending ||
00311                         (state == ServerState::ServerStateNewGame && (
00312                         tank->getState().getState() == TankState::sDead ||
00313                         tank->getState().getState() == TankState::sNormal)))
00314                 {
00315                         resultingTanks.push_back(tank);
00316 
00317                         // This is the very first time this tank
00318                         // has played the game, load it with the starting
00319                         // weapons etc...
00320                         if (tank->getState().getState() == TankState::sPending)
00321                         {
00322                                 tank->newMatch();
00323 
00324                                 // Check if this is a bot
00325                                 // if not update from any residual tank we have.
00326                                 // Residual tanks are only available until the next
00327                                 // whole game starts.
00328                                 if (ScorchedServer::instance()->getTankDeadContainer().getTank(tank))
00329                                 {
00330                                         Logger::log( "Found residual player info");
00331                                 }
00332                         }
00333 
00334                         if (tank->getState().getSpectator())
00335                         {
00336                                 // This tank is now playing (but dead)
00337                                 tank->getState().setState(TankState::sDead);
00338                         }
00339                         else if (state == ServerState::ServerStateNewGame)
00340                         {
00341                                 // This tank is now playing
00342                                 tank->newGame();
00343                         }
00344                         else
00345                         {
00346                                 // This tank is now playing (but dead)
00347                                 tank->getState().setState(TankState::sDead);
00348                         }
00349                 }
00350         }
00351 
00352         return resultingTanks;
00353 }
00354 
00355 void ServerNewGameState::checkTeams()
00356 {
00357         // Make sure everyone is in a team if they should be
00358         std::map<unsigned int, Tank *> &playingTanks = 
00359                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00360         std::map<unsigned int, Tank *>::iterator mainitor;
00361         for (mainitor = playingTanks.begin();
00362                  mainitor != playingTanks.end();
00363                  mainitor++)
00364         {
00365                 Tank *current = (*mainitor).second;
00366                 if (!current->getState().getSpectator())
00367                 {
00368                         if (ScorchedServer::instance()->getOptionsGame().getTeams() > 1 &&
00369                                 current->getTeam() == 0) current->setTeam(1); 
00370                         if (ScorchedServer::instance()->getOptionsGame().getTeams() == 1 &&
00371                                 current->getTeam() > 0) current->setTeam(0); 
00372                 }
00373         }
00374 
00375         // Do we check teams ballance
00376         if (ScorchedServer::instance()->getOptionsGame().getTeams() != 1)
00377         {
00378                 // Check for team ballance types
00379                 switch (ScorchedServer::instance()->getOptionsGame().getTeamBallance())
00380                 {
00381                         case OptionsGame::TeamBallanceAuto:
00382                         case OptionsGame::TeamBallanceAutoByScore:
00383                         case OptionsGame::TeamBallanceAutoByBots:
00384                                 checkTeamsAuto();
00385                                 break;
00386                         case OptionsGame::TeamBallanceBotsVs:
00387                                 checkTeamsBotsVs();
00388                                 break;
00389                         default:
00390                                 break;
00391                 }
00392         }
00393 
00394         // Make sure everyone is using a team model
00395         for (mainitor = playingTanks.begin();
00396                  mainitor != playingTanks.end();
00397                  mainitor++)
00398         {
00399                 Tank *current = (*mainitor).second;
00400                 if (!current->getState().getSpectator())
00401                 {
00402                         TankModel *model = 
00403                                 ScorchedServer::instance()->getTankModels().getModelByName(
00404                                         current->getModelContainer().getTankModelName(),
00405                                         current->getTeam(),
00406                                         current->isTemp());
00407                         if (0 != strcmp(model->getName(),
00408                                 current->getModelContainer().getTankModelName()))
00409                         {
00410                                 // The model is not allowed for this team,
00411                                 // use the correct model
00412                                 current->getModelContainer().setTankModelName(
00413                                         model->getName(), 
00414                                         model->getName(),
00415                                         model->getTypeName());
00416                         }
00417                 }
00418         }
00419 }
00420 
00421 static inline bool lt_score(const Tank *o1, const Tank *o2) 
00422 { 
00423         return ((Tank*)o1)->getScore().getScore() > ((Tank *)o2)->getScore().getScore();
00424 }
00425 
00426 static inline bool lt_bots(const Tank *o1, const Tank *o2) 
00427 { 
00428         return ((Tank*)o1)->getTankAI() < ((Tank *)o2)->getTankAI();
00429 }
00430 
00431 void ServerNewGameState::checkTeamsAuto()
00432 {
00433         // Count players in each team
00434         std::vector<Tank *> teamPlayers[4];
00435         std::map<unsigned int, Tank *> &playingTanks = 
00436                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00437         std::map<unsigned int, Tank *>::iterator mainitor;
00438         for (mainitor = playingTanks.begin();
00439                  mainitor != playingTanks.end();
00440                  mainitor++)
00441         {
00442                 Tank *current = (*mainitor).second;
00443                 if (!current->getState().getSpectator())
00444                 {
00445                         if (current->getTeam() > 0)
00446                         {
00447                                 teamPlayers[current->getTeam() - 1].push_back(current);
00448                         }
00449                 }
00450         }
00451 
00452         bool ballanced = false;
00453         bool check = true;
00454         while (check)
00455         {
00456                 check = false;
00457         
00458                 // Find the teams with the min and max players in them
00459                 std::vector<Tank *> *minPlayers = &teamPlayers[0];
00460                 std::vector<Tank *> *maxPlayers = &teamPlayers[0];
00461                 for (int i=0; i<ScorchedServer::instance()->getOptionsGame().getTeams(); i++)
00462                 {
00463                         if (teamPlayers[i].size() < minPlayers->size()) minPlayers = &teamPlayers[i];
00464                         if (teamPlayers[i].size() > maxPlayers->size()) maxPlayers = &teamPlayers[i];                   
00465                 }
00466                 
00467                 // Is the difference between the min and max teams >= 2 players
00468                 if (maxPlayers->size() - minPlayers->size() >= 2)
00469                 {
00470                         check = true;
00471                         ballanced = true;
00472                         
00473                         // Sort teams (if needed)
00474                         if (ScorchedServer::instance()->getOptionsGame().getTeamBallance() ==
00475                                 OptionsGame::TeamBallanceAutoByScore)
00476                         {
00477                                 std::sort(minPlayers->begin(), minPlayers->end(), lt_score); 
00478                                 std::sort(maxPlayers->begin(), maxPlayers->end(), lt_score); 
00479                         }
00480                         else if (ScorchedServer::instance()->getOptionsGame().getTeamBallance() ==
00481                                 OptionsGame::TeamBallanceAutoByBots)
00482                         {
00483                                 std::sort(minPlayers->begin(), minPlayers->end(), lt_bots); 
00484                                 std::sort(maxPlayers->begin(), maxPlayers->end(), lt_bots); 
00485                         }
00486                 
00487                         // Find out which team has the least players
00488                         for (int i=0; i<ScorchedServer::instance()->getOptionsGame().getTeams(); i++)
00489                         {       
00490                                 if (minPlayers == &teamPlayers[i])
00491                                 {
00492                                         // Ballance the teams
00493                                         Tank *tank = maxPlayers->back();
00494                                         maxPlayers->pop_back();
00495                                         minPlayers->push_back(tank);
00496                                         tank->setTeam(i+1);
00497                                 }
00498                         }
00499                 }
00500         }
00501 
00502         // Check if we needed to ballance
00503         if (ballanced)
00504         {
00505                 if (ScorchedServer::instance()->getOptionsGame().getTeamBallance() ==
00506                         OptionsGame::TeamBallanceAutoByScore)
00507                 {
00508                         ServerChannelManager::instance()->sendText(
00509                                 ChannelText("info", 
00510                                         "SCORE_AUTO_BALLANCE", 
00511                                         "Auto ballancing teams, by score"),
00512                                 true);
00513                 }
00514                 else if (ScorchedServer::instance()->getOptionsGame().getTeamBallance() ==
00515                         OptionsGame::TeamBallanceAutoByBots)
00516                 {
00517                         ServerChannelManager::instance()->sendText(
00518                                 ChannelText("info",
00519                                         "BOTS_AUTO_BALLANCE",
00520                                         "Auto ballancing teams, by bots"),
00521                                 true);
00522                 }
00523                 else
00524                 {
00525                         ServerChannelManager::instance()->sendText(
00526                                 ChannelText("info",
00527                                         "NORMAL_AUTO_BALLANCE",
00528                                         "Auto ballancing teams"),
00529                                 true);
00530                 }
00531         }
00532 }
00533 
00534 void ServerNewGameState::checkTeamsBotsVs()
00535 {
00536         std::map<unsigned int, Tank *> &playingTanks = 
00537                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00538         std::map<unsigned int, Tank *>::iterator mainitor;
00539         for (mainitor = playingTanks.begin();
00540                  mainitor != playingTanks.end();
00541                  mainitor++)
00542         {
00543                 Tank *current = (*mainitor).second;
00544                 if (!current->getState().getSpectator())
00545                 {
00546                         if (current->getDestinationId() == 0) current->setTeam(1);
00547                         else current->setTeam(2);
00548                 }
00549         }
00550 }
00551 
00552 void ServerNewGameState::checkBots(bool removeBots)
00553 {
00554         int requiredPlayers =
00555                 ScorchedServer::instance()->getOptionsGame().
00556                         getRemoveBotsAtPlayers();
00557         if (requiredPlayers == 0)
00558         {
00559                 // Check if this feature is turned off
00560                 return;
00561         }
00562 
00563         // Add up the number of tanks that are either
00564         // human and not spectators
00565         // or an ai
00566         int noPlayers = 0;
00567         std::map<unsigned int, Tank *> &playingTanks = 
00568                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00569         std::map<unsigned int, Tank *>::iterator mainitor;
00570         for (mainitor = playingTanks.begin();
00571                 mainitor != playingTanks.end();
00572                 mainitor++)
00573         {
00574                 Tank *current = (*mainitor).second;
00575                 if (!current->getState().getSpectator() ||
00576                         current->getDestinationId() == 0)
00577                 {
00578                         noPlayers++;
00579                 }
00580         }
00581 
00582         if (noPlayers > requiredPlayers &&
00583                 removeBots)
00584         {
00585                 std::multimap<unsigned int, unsigned int> ais_;
00586 
00587                 // Get this list of computer players and sort them
00588                 // by the time they have been playing for
00589                 for (mainitor = playingTanks.begin();
00590                         mainitor != playingTanks.end();
00591                         mainitor++)
00592                 {
00593                         Tank *current = (*mainitor).second;
00594                         if (current->getDestinationId() == 0)
00595                         {
00596                                 unsigned int startTime = (unsigned int)
00597                                         current->getScore().getStartTime();
00598                                 ais_.insert(std::pair<unsigned int, unsigned int>
00599                                         (startTime, current->getPlayerId()));
00600                         }
00601                 }
00602 
00603                 // Kick the ais that have been on the server the longest
00604                 std::multimap<unsigned int, unsigned int>::reverse_iterator
00605                         aiItor = ais_.rbegin();
00606                 while (noPlayers > requiredPlayers)
00607                 {
00608                         if (aiItor != ais_.rend())
00609                         {
00610                                 std::pair<unsigned int, unsigned int> item = *aiItor;
00611                                 ServerMessageHandler::instance()->destroyPlayer(
00612                                         item.second, "Auto-kick");
00613                                 aiItor++;
00614                         }
00615                         noPlayers--;
00616                 }
00617         }
00618         if (noPlayers < requiredPlayers)
00619         {
00620                 std::multimap<std::string, unsigned int> ais_;
00621 
00622                 // Get this list of computer players and sort them
00623                 // by ai name
00624                 for (mainitor = playingTanks.begin();
00625                         mainitor != playingTanks.end();
00626                         mainitor++)
00627                 {
00628                         Tank *current = (*mainitor).second;
00629                         if (current->getDestinationId() == 0)
00630                         {
00631                                 ais_.insert(std::pair<std::string, unsigned int>
00632                                         (current->getTankAI()->getName(), 
00633                                         current->getPlayerId()));
00634                         }
00635                 }
00636 
00637                 // Add any computer players that should be playing 
00638                 // and that are not in the list of currently playing
00639                 int maxComputerAIs = 
00640                         ScorchedServer::instance()->getOptionsGame().getNoMaxPlayers();
00641                 for (int i=0; i<maxComputerAIs; i++)
00642                 {
00643                         const char *playerType = 
00644                                 ScorchedServer::instance()->getOptionsGame().getPlayerType(i);
00645                         if (0 != stricmp(playerType, "Human") &&
00646                                 0 != stricmp(playerType, "Random"))
00647                         {
00648                                 std::multimap<std::string, unsigned int>::iterator findItor =
00649                                         ais_.find(playerType);
00650                                 if (findItor == ais_.end())
00651                                 {
00652                                         if (noPlayers < requiredPlayers)
00653                                         {
00654                                                 // This player does not exist add them
00655                                                 TankAIAdder::addTankAI(*ScorchedServer::instance(), playerType);
00656                                                 noPlayers++;
00657                                         }
00658                                 }
00659                                 else
00660                                 {
00661                                         // This player does exist dont add them
00662                                         ais_.erase(findItor);
00663                                 }
00664                         }
00665                 }
00666                 for (int i=0; i<maxComputerAIs; i++)
00667                 {
00668                         const char *playerType = 
00669                                 ScorchedServer::instance()->getOptionsGame().getPlayerType(i);
00670                         if (0 != stricmp(playerType, "Human") &&
00671                                 0 == stricmp(playerType, "Random"))
00672                         {
00673                                 if (ais_.empty())
00674                                 {
00675                                         if (noPlayers < requiredPlayers)
00676                                         {
00677                                                 // This player does not exist add them
00678                                                 TankAIAdder::addTankAI(*ScorchedServer::instance(), playerType);
00679                                                 noPlayers++;
00680                                         }                                                                               
00681                                 }
00682                                 else
00683                                 {
00684                                         // This player does exist dont add them
00685                                         ais_.erase(ais_.begin());
00686                                 }
00687                         }
00688                 }
00689         }
00690 }
00691 
00692 void ServerNewGameState::removeTargets()
00693 {
00694         std::map<unsigned int, Target *> targets = // Note copy
00695                 ScorchedServer::instance()->getTargetContainer().getTargets();
00696         std::map<unsigned int, Target *>::iterator itor;
00697         for (itor = targets.begin();
00698                 itor != targets.end();
00699                 itor++)
00700         {
00701                 unsigned int playerId = (*itor).first;
00702                 Target *target = (*itor).second;
00703                 if (target->isTemp())
00704                 {
00705                         if (target->isTarget())
00706                         {
00707                                 Target *removedTarget = 
00708                                         ScorchedServer::instance()->getTargetContainer().removeTarget(playerId);
00709                                 delete removedTarget;
00710                         }
00711                         else
00712                         {
00713                                 Tank *removedTank = 
00714                                         ScorchedServer::instance()->getTankContainer().removeTank(playerId);
00715                                 delete removedTank;
00716                         }
00717                 }
00718         }
00719 }

Generated on Mon Feb 16 15:14:53 2009 for Scorched3D by  doxygen 1.5.3