00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00099 if (!local)
00100 {
00101
00102
00103 ScorchedServer::instance()->getContext().setNetInterface(
00104
00105
00106
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
00133 S3D::setDataFileMod(
00134 ScorchedServer::instance()->getOptionsGame().getMod());
00135
00136
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
00155
00156 if (!ScorchedServer::instance()->getTankAIs().loadAIs()) return false;
00157 TankAIAdder::addTankAIs(*ScorchedServer::instance());
00158
00159
00160 ServerState::setupStates(ScorchedServer::instance()->getGameState());
00161 EconomyStore::instance();
00162
00163 checkSettings();
00164
00165
00166 if (!ScorchedServer::instance()->getLUAScriptHook().loadHooks()) return false;
00167
00168 return true;
00169 }
00170
00171 void serverMain(ProgressCounter *counter)
00172 {
00173
00174 if (!startServer(false, counter)) exit(64);
00175
00176
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
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