ServerMain.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 #define WIN32_LEAN_AND_MEAN
00022 #include <windows.h>
00023 #include <stdlib.h>
00024 #include <weapons/AccessoryStore.h>
00025 #include <weapons/EconomyStore.h>
00026 #include <net/NetLoopBack.h>
00027 #include <net/NetServerTCP3.h>
00028 #include <lua/LUAScriptHook.h>
00029 #include <common/Defines.h>
00030 #include <common/Clock.h>
00031 #include <common/ARGParser.h>
00032 #include <common/Defines.h>
00033 #include <common/Logger.h>
00034 #include <common/OptionsScorched.h>
00035 #include <common/OptionsTransient.h>
00036 #include <engine/ActionController.h>
00037 #include <engine/ModFiles.h>
00038 #include <landscapedef/LandscapeDefinitions.h>
00039 #include <tankai/TankAIAdder.h>
00040 #include <tankai/TankAIStore.h>
00041 #include <tank/TankModelStore.h>
00042 #include <server/ServerLinesHandler.h>
00043 #include <server/ServerMessageHandler.h>
00044 #include <server/ServerPlayerReadyHandler.h>
00045 #include <server/ServerGiftMoneyHandler.h>
00046 #include <server/ServerDefenseHandler.h>
00047 #include <server/ServerPlayedMoveHandler.h>
00048 #include <server/ServerAddPlayerHandler.h>
00049 #include <server/ServerAdminHandler.h>
00050 #include <server/ServerHaveModFilesHandler.h>
00051 #include <server/ServerBuyAccessoryHandler.h>
00052 #include <server/ServerKeepAliveHandler.h>
00053 #include <server/ServerFileAkHandler.h>
00054 #include <server/ServerInitializeHandler.h>
00055 #include <server/ServerChannelManager.h>
00056 #include <server/ServerConnectHandler.h>
00057 #include <server/ServerConnectAuthHandler.h>
00058 #include <server/ServerOperationResultHandler.h>
00059 #include <server/ServerFileServer.h>
00060 #include <server/ServerRegistration.h>
00061 #include <server/ServerLog.h>
00062 #include <server/ServerBrowserInfo.h>
00063 #include <server/ServerState.h>
00064 #include <server/ServerCommon.h>
00065 #include <server/ServerBanned.h>
00066 #include <server/ServerMain.h>
00067 #include <server/ScorchedServer.h>
00068 #include <server/ScorchedServerUtil.h>
00069 #include <SDL/SDL.h>
00070 
00071 #ifdef S3D_SERVER
00072 #include <webserver/ServerWebServer.h>
00073 #endif
00074 
00075 Clock serverTimer;
00076 
00077 void checkSettings()
00078 {
00079         ScorchedServer::instance()->getLandscapes().checkEnabled(
00080                 ScorchedServer::instance()->getOptionsGame());
00081         
00082         if (ScorchedServer::instance()->getOptionsGame().getTeamBallance() == 
00083                 OptionsGame::TeamBallanceBotsVs &&
00084                 ScorchedServer::instance()->getOptionsGame().getTeams() > 2)
00085         {
00086                 S3D::dialogExit("ScorchedServer",
00087                         "Cannot start a game with more than 2 teams in the bots vs mode");              
00088         }
00089 }
00090 
00091 bool startServer(bool local, ProgressCounter *counter)
00092 {
00093         Logger::log(S3D::formatStringBuffer("Scorched3D - Version %s (%s) - %s",
00094                 S3D::ScorchedVersion.c_str(), 
00095                 S3D::ScorchedProtocolVersion.c_str(), 
00096                 S3D::ScorchedBuildTime.c_str()));
00097 
00098         // Setup the message handling classes
00099         if (!local)
00100         {
00101                 // Only create a net server for the actual multiplayer case
00102                 // A loopback is created by the client for a single player game 
00103                 ScorchedServer::instance()->getContext().setNetInterface(
00104                         //new NetServerTCP(new NetServerTCPScorchedProtocol());
00105                         //new NetServerUDP();
00106                         //new NetServerTCP2();
00107                         new NetServerTCP3());
00108         }
00109 
00110         ScorchedServer::instance()->getOptionsGame().updateChangeSet();
00111         ScorchedServer::instance()->getNetInterface().setMessageHandler(
00112                 &ScorchedServer::instance()->getComsMessageHandler());
00113         ScorchedServer::instance()->getComsMessageHandler().setConnectionHandler(
00114                 ServerMessageHandler::instance());
00115         ServerConnectHandler::instance();
00116         ServerConnectAuthHandler::instance();
00117         ServerLinesHandler::instance();
00118         ServerChannelManager::instance();
00119         ServerGiftMoneyHandler::instance();
00120         ServerPlayerReadyHandler::instance();
00121         ServerAdminHandler::instance();
00122         ServerHaveModFilesHandler::instance();
00123         ServerInitializeHandler::instance();
00124         ServerKeepAliveHandler::instance();
00125         ServerPlayedMoveHandler::instance();
00126         ServerFileAkHandler::instance();
00127         ServerBuyAccessoryHandler::instance();
00128         ServerAddPlayerHandler::instance();
00129         ServerDefenseHandler::instance();
00130         ServerOperationResultHandler::instance();
00131 
00132         // Set the mod
00133         S3D::setDataFileMod(
00134                 ScorchedServer::instance()->getOptionsGame().getMod());
00135 
00136         // Load mod
00137 #ifdef S3D_SERVER
00138         {
00139                 if (!ScorchedServer::instance()->getModFiles().loadModFiles(
00140                         ScorchedServer::instance()->getOptionsGame().getMod(), false,
00141                         counter)) return false;
00142         }
00143 #endif
00144 
00145         if (!ScorchedServer::instance()->getAccessoryStore().parseFile(
00146                 ScorchedServer::instance()->getContext(),
00147                 counter)) return false;
00148         if (!ScorchedServer::instance()->getTankModels().loadTankMeshes(
00149                 ScorchedServer::instance()->getContext(), 2, counter))
00150                 return false;
00151         ScorchedServer::instance()->getOptionsTransient().reset();
00152         if (!ScorchedServer::instance()->getLandscapes().readLandscapeDefinitions()) return false;
00153 
00154         // Add the server side bots
00155         // Add any new AIs
00156         if (!ScorchedServer::instance()->getTankAIs().loadAIs()) return false;
00157         TankAIAdder::addTankAIs(*ScorchedServer::instance());
00158 
00159         // Start the state machine
00160         ServerState::setupStates(ScorchedServer::instance()->getGameState());
00161         EconomyStore::instance();
00162 
00163         checkSettings();
00164 
00165         // Load all script hooks
00166         if (!ScorchedServer::instance()->getLUAScriptHook().loadHooks()) return false;
00167 
00168         return true;
00169 }
00170 
00171 void serverMain(ProgressCounter *counter)
00172 {
00173         // Create the server states
00174         if (!startServer(false, counter)) exit(64);
00175 
00176         // Try to start the server
00177         if (!ScorchedServer::instance()->getContext().getNetInterface().start(
00178                 ScorchedServer::instance()->getOptionsGame().getPortNo()) ||
00179                 !ServerBrowserInfo::instance()->start())
00180         {
00181                 S3D::dialogExit("Scorched3D Server", 
00182                         S3D::formatStringBuffer("Failed to start the server.\n\n"
00183                         "Could not bind to the server ports.\n"
00184                         "Ensure the specified ports (%i, %i) do not conflict with any other program.",
00185                         ScorchedServer::instance()->getOptionsGame().getPortNo(),
00186                         ScorchedServer::instance()->getOptionsGame().getPortNo() + 1));
00187         }
00188 
00189         if (ScorchedServer::instance()->getOptionsGame().getPublishServer()) 
00190         {
00191                 ServerRegistration::instance()->start();
00192         }
00193 
00194 #ifdef S3D_SERVER
00195         if (ScorchedServer::instance()->getOptionsGame().getManagementPortNo() > 0)
00196         {
00197                 ServerWebServer::instance()->start(
00198                         ScorchedServer::instance()->getOptionsGame().getManagementPortNo());
00199 
00200                 Logger::log(S3D::formatStringBuffer("Management server running on url http://127.0.0.1:%i",
00201                         ScorchedServer::instance()->getOptionsGame().getManagementPortNo()));
00202         }
00203 #endif
00204         ServerLog::instance();
00205 
00206         std::string startTime = S3D::getStartTime();
00207         Logger::log(S3D::formatStringBuffer("Server started : %s", startTime.c_str()));
00208 }
00209 
00210 void serverLoop()
00211 {
00212         // Main server loop:
00213         if (ScorchedServer::instance()->getContext().getNetInterfaceValid())
00214         {
00215                 Logger::processLogEntries();
00216                 ScorchedServer::instance()->getNetInterface().processMessages();
00217 #ifdef S3D_SERVER
00218                 {
00219                         ServerBrowserInfo::instance()->processMessages();
00220                         ServerWebServer::instance()->processMessages();
00221                 }
00222 #endif
00223 
00224                 float timeDifference = serverTimer.getTimeDifference();
00225                 ScorchedServer::instance()->getGameState().draw();
00226                 ScorchedServer::instance()->getGameState().simulate(timeDifference);
00227                 ServerFileServer::instance()->simulate(timeDifference);
00228                 ServerChannelManager::instance()->simulate(timeDifference);
00229                 ScorchedServerUtil::instance()->timedMessage.simulate();
00230                 ServerKeepAliveHandler::instance()->checkKeepAlives();
00231 
00232                 if (timeDifference > 5.0f)
00233                 {
00234                         Logger::log(S3D::formatStringBuffer("Warning: Server loop took %.2f seconds", 
00235                                 timeDifference));
00236                 }
00237         }
00238 }
00239 
00240 class ConsoleServerProgressCounter : public ProgressCounterI
00241 {
00242 public:
00243         ConsoleServerProgressCounter() : lastOp_(), hashes_(0) {}
00244 
00245         virtual void drawHashes(int neededHashes)
00246         {
00247                 if (hashes_ < neededHashes)
00248                 {
00249                         for (int h=hashes_;h<neededHashes; h++)
00250                         {
00251                                 printf("#");
00252                                 if (h == 24)
00253                                 {
00254                                         printf("\n");
00255                                 }
00256                         }
00257                         hashes_ = neededHashes;
00258                 }
00259                 fflush(stdout);
00260         }
00261 
00262         virtual void progressChange(const LangString &op, const float percentage)
00263         {
00264                 if (op != lastOp_)
00265                 {
00266                         if (!lastOp_.empty())
00267                         {
00268                                 drawHashes(25);
00269                         }
00270 
00271                         std::string opStr = LangStringUtil::convertFromLang(op);
00272 
00273                         Logger::log(opStr);
00274                         printf("%s:", opStr.c_str());
00275                         lastOp_ = op;
00276                         hashes_ = 0;
00277                 }
00278 
00279                 int neededHashes = int(percentage / 4.0f);
00280                 drawHashes(neededHashes);
00281         }
00282 protected:
00283         LangString lastOp_;
00284         int hashes_;
00285 };
00286 
00287 class ConsoleLogger : public LoggerI
00288 {
00289 public:
00290         virtual void logMessage(LoggerInfo &info)
00291         {
00292                 printf("%s - %s\n", info.getTime(), info.getMessage());
00293         }
00294 };
00295 
00296 void consoleServer()
00297 {
00298         ConsoleLogger consoleLogger;
00299         ProgressCounter progressCounter;
00300         ConsoleServerProgressCounter progressCounterI;
00301         progressCounter.setUser(&progressCounterI);
00302 
00303         ServerCommon::startFileLogger();
00304         Logger::instance()->addLogger(&consoleLogger);
00305         serverMain(&progressCounter);
00306 
00307         for (;;)
00308         {
00309                 SDL_Delay(10);
00310                 serverLoop();
00311         }
00312 }
00313 

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