Files
src-1.2/game/server/application/SwgGameServer/src/win32/WinMain.cpp
T

554 lines
16 KiB
C++
Executable File

#include "FirstSwgGameServer.h"
#include "serverGame/GameServer.h"
#include "LocalizationManager.h"
#include "serverGame/SetupServerGame.h"
#include "serverGame/ServerWorld.h"
#include "serverGame/ServerObjectTemplate.h"
#include "ServerObjectLint.h"
#include "serverPathfinding/SetupServerPathfinding.h"
#include "serverScript/SetupScript.h"
#include "serverUtility/SetupServerUtility.h"
#include "sharedDebug/SetupSharedDebug.h"
#include "sharedFile/SetupSharedFile.h"
#include "sharedFile/TreeFile.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/FormattedString.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedGame/SetupSharedGame.h"
#include "sharedGame/SharedObjectTemplate.h"
#include "sharedImage/SetupSharedImage.h"
#include "sharedLog/LogManager.h"
#include "sharedLog/SetupSharedLog.h"
#include "sharedMath/SetupSharedMath.h"
#include "sharedNetwork/NetworkHandler.h"
#include "sharedNetwork/SetupSharedNetwork.h"
#include "sharedObject/SetupSharedObject.h"
#include "sharedObject/ObjectTemplateList.h"
#include "sharedRandom/SetupSharedRandom.h"
#include "sharedRegex/SetupSharedRegex.h"
#include "sharedRemoteDebugServer/SharedRemoteDebugServer.h"
#include "sharedTerrain/SetupSharedTerrain.h"
#include "sharedThread/SetupSharedThread.h"
#include "sharedUtility/SetupSharedUtility.h"
#include "sharedNetworkMessages/SetupSharedNetworkMessages.h"
#include "SwgGameServer/SwgGameServer.h"
#include "SwgGameServer/WorldSnapshotParser.h"
#include "swgSharedNetworkMessages/SetupSwgSharedNetworkMessages.h"
#include "swgServerNetworkMessages/SetupSwgServerNetworkMessages.h"
#include <cstdio>
#include <ctime>
#include <direct.h>
#include <vector>
#ifdef _DEBUG
#include "sharedDebug/DataLint.h"
#include "sharedDebug/PerformanceTimer.h"
#include "sharedFoundation/Os.h"
#include "sharedObject/Object.h"
#include "sharedObject/ObjectTemplate.h"
void runDataLint(char const *responsePath);
void verifyUpdateRanges (const char* filename);
#endif // _DEBUG
//_____________________________________________________________________
/*
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
)
*/
int main(int argc, char ** argv)
{
int i = 0;
// UNREF(hPrevInstance);
// UNREF(nCmdShow);
//-- setup foundation
SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game);
// command line hack
std::string cmdLine;
for(i = 1; i < argc; ++i)
{
cmdLine += argv[i];
if(i + 1 < argc)
{
cmdLine += " ";
}
}
// setupFoundationData.hInstance = hInstance;
setupFoundationData.commandLine = cmdLine.c_str();
setupFoundationData.createWindow = false;
setupFoundationData.clockUsesSleep = true;
SetupSharedThread::install();
SetupSharedDebug::install(1024);
SetupSharedFoundation::install (setupFoundationData);
SetupServerUtility::install();
SetupSharedRegex::install();
SetupSharedFile::install(false);
SetupSharedNetwork::SetupData networkSetupData;
SetupSharedNetwork::getDefaultServerSetupData(networkSetupData);
SetupSharedNetwork::install(networkSetupData);
SetupSharedMath::install();
SetupSharedUtility::Data setupUtilityData;
SetupSharedUtility::setupGameData (setupUtilityData);
SetupSharedUtility::install (setupUtilityData);
SetupSharedRandom::install(int(time(NULL)));
{
SetupSharedObject::Data data;
SetupSharedObject::setupDefaultGameData(data);
// we want the SlotIdManager initialized, but we don't need the associated hardpoint names on the server.
SetupSharedObject::addSlotIdManagerData(data, false);
// we want movement table information on this server
SetupSharedObject::addMovementTableData(data);
// we want CustomizationData support on this server.
SetupSharedObject::addCustomizationSupportData(data);
// we want POB ejection point override support.
SetupSharedObject::addPobEjectionTransformData(data);
// objects should not automatically alter their children and contents
data.objectsAlterChildrenAndContents = false;
SetupSharedObject::install(data);
}
SetupSharedLog::install(FormattedString<92>().sprintf("SwgGameServer:%d", Os::getProcessId()));
TreeFile::addSearchAbsolute(0);
TreeFile::addSearchPath(".",0);
SetupSharedNetworkMessages::install();
SetupSwgServerNetworkMessages::install();
SetupSwgSharedNetworkMessages::install();
SetupSharedImage::Data setupImageData;
SetupSharedImage::setupDefaultData (setupImageData);
SetupSharedImage::install (setupImageData);
SetupSharedGame::Data setupSharedGameData;
setupSharedGameData.setUseMountValidScaleRangeTable(true);
setupSharedGameData.setUseClientCombatManagerSupport(true);
SetupSharedGame::install (setupSharedGameData);
SetupSharedTerrain::Data setupSharedTerrainData;
SetupSharedTerrain::setupGameData (setupSharedTerrainData);
SetupSharedTerrain::install (setupSharedTerrainData);
SetupScript::Data setupScriptData;
SetupScript::setupDefaultGameData(setupScriptData);
SetupScript::install();
SetupServerPathfinding::install();
//-- setup game server
SetupServerGame::install();
SharedRemoteDebugServer::install();
//-- setup game server
cmdLine.clear();
// now, the real command line
for(i = 0; i < argc; ++i)
{
cmdLine += argv[i];
if(i + 1 < argc)
{
cmdLine += " ";
}
}
Archive::ByteStream bs;
UNREF(bs);
NetworkHandler::install();
SwgGameServer::install();
GameServer::getInstance().setCommandLine(cmdLine);
#ifdef _DEBUG
//-- see if the game server is being run in a mode to parse the database dump to create planetary snapshot files
const char* const createWorldSnapshots = ConfigFile::getKeyString("WorldSnapshot", "createWorldSnapshots", 0);
if (createWorldSnapshots)
{
WorldSnapshotParser::createWorldSnapshots (createWorldSnapshots);
}
else
//-- see if the gameserver is to be run in a mode to scan update ranges
if (ConfigFile::getKeyBool ("SwgGameServer", "verifyUpdateRanges", false))
{
ServerWorld::install ();
verifyUpdateRanges ("../../exe/win32/serverobjecttemplates.txt");
ServerWorld::remove ();
}
else
if (!ConfigFile::getKeyBool("SwgGameServer/DataLint", "disable", true))
{
runDataLint("../../exe/win32/DataLintServer.rsp");
}
else
#endif // _DEBUG
{
//-- run game
SetupSharedFoundation::callbackWithExceptionHandling(GameServer::run);
}
NetworkHandler::remove();
SetupServerGame::remove();
SharedRemoteDebugServer::remove();
SetupSharedLog::remove();
SetupSharedFoundation::remove();
SetupSharedThread::remove ();
return 0;
}
#ifdef _DEBUG
void verifyUpdateRanges (const char* const filename)
{
FILE* const infile = fopen (filename, "rt");
if (!infile)
{
DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: response file %s could not be opened\n", filename));
return;
}
char serverObjectTemplateName [1024];
while (fscanf (infile, "%s", serverObjectTemplateName) != EOF)
{
//-- does the name contain test?
if (strstr (serverObjectTemplateName, "test") != 0)
{
DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: skipping test object template %s\n", serverObjectTemplateName));
continue;
}
if (strstr (serverObjectTemplateName, "e3_") != 0)
{
DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: skipping test object template %s\n", serverObjectTemplateName));
continue;
}
//-- get the object template
const ObjectTemplate* const objectTemplate = ObjectTemplateList::fetch (serverObjectTemplateName);
if (!objectTemplate)
{
DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid object template\n", serverObjectTemplateName));
continue;
}
//-- make sure its a server object template
const ServerObjectTemplate* const serverObjectTemplate = dynamic_cast<const ServerObjectTemplate*> (objectTemplate);
if (!serverObjectTemplate)
{
objectTemplate->releaseReference ();
DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid server object template\n", serverObjectTemplateName));
continue;
}
//-- make sure it has a shared object template
const std::string& sharedObjectTemplateName = serverObjectTemplate->getSharedTemplate ();
if (sharedObjectTemplateName.empty ())
{
objectTemplate->releaseReference ();
continue;
}
//-- make sure the shared template exists
const SharedObjectTemplate* const sharedObjectTemplate = safe_cast<const SharedObjectTemplate*> (ObjectTemplateList::fetch (sharedObjectTemplateName.c_str ()));
if (!sharedObjectTemplate)
{
DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid shared object template for server object template %s\n", sharedObjectTemplateName.c_str (), serverObjectTemplateName));
objectTemplate->releaseReference ();
continue;
}
const float farUpdateRange = serverObjectTemplate->getUpdateRanges (ServerObjectTemplate::UR_far);
DEBUG_REPORT_LOG (true, ("OK:\t%s\t%s\t%1.1f\n", serverObjectTemplateName, sharedObjectTemplateName.c_str (), farUpdateRange));
objectTemplate->releaseReference ();
}
fclose(infile);
}
static std::string currentLintedAsset;
static int m_startIndex = 0;
static int m_numberOfFilesToLint = -1;
//-----------------------------------------------------------------------------
static int ExceptionHandler(LPEXCEPTION_POINTERS exceptionPointers)
{
UNREF(exceptionPointers);
static bool entered = false;
// make the routine safe from re-entrance
if (entered)
{
return EXCEPTION_CONTINUE_SEARCH;
}
entered = true;
// tell the Os not to abort so we can rethrow the exception
Os::returnFromAbort();
// Let the ExitChain do its job
DataLint::pushAsset(currentLintedAsset.c_str());
FATAL(true, ("ExceptionHandler invoked - A crash just occured. The asset is bad or it is constructed improperly with DataLint."));
DataLint::popAsset();
// rethrow the exception so that the debugger can catch it
return EXCEPTION_CONTINUE_SEARCH; //lint !e527 // Unreachable
}
//-----------------------------------------------------------------------------
static void lintType(char const *filePath, DataLint::AssetType const assetType, bool const skip)
{
DataLint::setCurrentAssetType(assetType);
static int assetNumber = 0;
if (!skip)
{
DEBUG_REPORT_LOG (true, ("%5i Linting file %s... ", assetNumber, filePath));
bool failed = false;
try
{
switch (assetType)
{
case DataLint::AT_objectTemplate:
{
const ObjectTemplate *objectTemplate = ObjectTemplateList::fetch(filePath);
if (objectTemplate)
{
objectTemplate->testValues();
// if file has the directory "base" in it's path, don't
// create an object
if (strstr(filePath, "/base/") == NULL)
{
Object* const object = objectTemplate->createObject ();
delete object;
}
objectTemplate->releaseReference();
}
else
{
failed = true;
}
}
break;
case DataLint::AT_unSupported:
{
}
break;
}
if (failed)
{
DEBUG_REPORT_LOG (true, ("failed\n"));
}
else
{
DEBUG_REPORT_LOG (true, ("ok\n"));
}
}
catch (FatalException const &e)
{
DEBUG_REPORT_LOG (true, ("failed\n"));
DataLint::logWarning(e.getMessage());
}
}
++assetNumber;
}
//-----------------------------------------------------------------------------
static void makeMicrosoftHappyAboutObjectUnWinding(char const *filePath, DataLint::AssetType const assetType, bool const skip)
{
__try
{
lintType(filePath, assetType, skip);
}
__except (ExceptionHandler(GetExceptionInformation()))
{
}
}
//-----------------------------------------------------------------------------
static void lint(char const *dataTypeString, DataLint::AssetType const assetType)
{
DataLint::StringPairList stringPairList(DataLint::getList(assetType));
DataLint::StringPairList::const_iterator dataLintStringListIter = stringPairList.begin();
DEBUG_REPORT_LOG_PRINT(1, ("Linting %d %s assets\n", stringPairList.size(), dataTypeString));
int currentIndex = 0;
for (; dataLintStringListIter != stringPairList.end(); ++dataLintStringListIter)
{
{
if ((currentIndex % 10) == 0)
{
//-- see if a file exists to abort
FILE *file = fopen("stoplint.dat", "rt");
if (file)
{
fclose(file);
DEBUG_REPORT_LOG_PRINT(1, ("Stopping all DataLint processing for %s.\n", dataTypeString));
DataLint::logWarning("Forced DataLint stop. Delete \"stoplint.dat\" to DataLint all the assets.");
break;
}
}
}
char const *filePath = dataLintStringListIter->first.c_str();
currentLintedAsset = dataLintStringListIter->second.c_str();
//DataLint::pushAsset(filePath);
makeMicrosoftHappyAboutObjectUnWinding(filePath, assetType, (currentIndex < m_startIndex));
//DataLint::popAsset();
DataLint::clearAssetStack();
++currentIndex;
if ((m_numberOfFilesToLint != -1) && (currentIndex >= (m_startIndex + m_numberOfFilesToLint)))
{
break;
}
}
}
//-----------------------------------------------------------------------------
void runDataLint(char const *responsePath)
{
ServerObjectLint::install();
ServerWorld::install();
DataLint::setServerMode();
PerformanceTimer performanceTimer;
performanceTimer.start();
FILE *fp = fopen(responsePath, "r");
if (fp)
{
// Default to start with the first asset
m_startIndex = ConfigFile::getKeyInt("SwgGameServer/DataLint", "startIndex", 0);
// Default to lint all assets
m_numberOfFilesToLint = ConfigFile::getKeyInt("SwgGameServer/DataLint", "numberOfFilesToLint", -1);
// Verify this is a valid resonse file
char text[4096];
fgets(text, sizeof(text), fp);
if (strstr(text, "Valid DataLint Rsp") == NULL)
{
DEBUG_REPORT_LOG_PRINT(1, ("DataLint: Invalid Rsp file: %s\n", responsePath));
#ifdef WIN32
char text[4096];
sprintf(text, "Invalid Rsp file specified: %s. Make sure to run DataLintRspBuilder before running DataLint.", responsePath);
MessageBox(NULL, text, "DataLint Error!", MB_OK | MB_ICONERROR);
#endif // WIN32
}
else
{
DataLint::install();
typedef std::vector<std::string> StringList;
StringList stringList;
stringList.reserve(32768);
DEBUG_REPORT_LOG_PRINT(1, ("Loading assets to lint from: %s\n", responsePath));
while (fgets(text, sizeof(text), fp))
{
// Remove the newline character
char *newLineTest = strchr(text, '\n');
if (newLineTest)
{
*newLineTest = '\0';
}
// Add the files to the master file list
stringList.push_back(text);
}
fclose(fp);
// Add files to data lint
DEBUG_REPORT_LOG_PRINT(1, ("Adding %d assets to DataLint to be categorized\n", stringList.size()));
StringList::iterator stringListIter = stringList.begin();
for (; stringListIter != stringList.end(); ++stringListIter)
{
DataLint::addFilePath((*stringListIter).c_str());
}
if (ConfigFile::getKeyBool("SwgGameServer/DataLint", "objectTemplate", true))
{
lint("Objects Template", DataLint::AT_objectTemplate);
}
DataLint::report();
}
}
else
{
DEBUG_REPORT_LOG_PRINT(1, ("Bad response path specified: %s", responsePath));
#ifdef WIN32
char text[4096];
sprintf(text, "Bad response file specified: %s. Make sure to run DataLintRspBuilder before running DataLint.", responsePath);
MessageBox(NULL, text, "DataLint Error!", MB_OK | MB_ICONERROR);
#endif // WIN32
}
// Dump the time required to data lint
performanceTimer.stop();
float const dataLintTime = performanceTimer.getElapsedTime();
int const seconds = static_cast<int>(dataLintTime) % 60;
int const minutes = (static_cast<int>(dataLintTime) - seconds) / 60;
DEBUG_REPORT_LOG_PRINT(1, ("DateLint took: %dm %ds\n", minutes, seconds));
}
#endif // _DEBUG
//_____________________________________________________________________