mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-08-03 04:19:20 -04:00
554 lines
16 KiB
C++
Executable File
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
|
|
|
|
//_____________________________________________________________________
|