mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-28 22:15:49 -04:00
Added PlanetServer project
This commit is contained in:
@@ -4,4 +4,5 @@ add_subdirectory(ChatServer)
|
||||
add_subdirectory(ConnectionServer)
|
||||
add_subdirectory(LoginServer)
|
||||
add_subdirectory(LogServer)
|
||||
add_subdirectory(PlanetServer)
|
||||
add_subdirectory(TaskManager)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(PlanetServer)
|
||||
|
||||
add_subdirectory(src)
|
||||
@@ -0,0 +1,114 @@
|
||||
|
||||
set(SHARED_SOURCES
|
||||
shared/CentralServerConnection.cpp
|
||||
shared/CentralServerConnection.h
|
||||
shared/ConfigPlanetServer.cpp
|
||||
shared/ConfigPlanetServer.h
|
||||
shared/ConsoleManager.cpp
|
||||
shared/ConsoleManager.h
|
||||
shared/ConsoleCommandParser.cpp
|
||||
shared/ConsoleCommandParser.h
|
||||
shared/FirstPlanetServer.h
|
||||
shared/GameServerConnection.cpp
|
||||
shared/GameServerConnection.h
|
||||
shared/GameServerData.cpp
|
||||
shared/GameServerData.h
|
||||
shared/PlanetProxyObject.cpp
|
||||
shared/PlanetProxyObject.h
|
||||
shared/PlanetServer.cpp
|
||||
shared/PlanetServer.h
|
||||
shared/PlanetServerMetricsData.cpp
|
||||
shared/PlanetServerMetricsData.h
|
||||
shared/PreloadManager.cpp
|
||||
shared/PreloadManager.h
|
||||
shared/QuadtreeNode.cpp
|
||||
shared/QuadtreeNode.h
|
||||
shared/Scene.cpp
|
||||
shared/Scene.h
|
||||
shared/TaskConnection.cpp
|
||||
shared/TaskConnection.h
|
||||
shared/WatcherConnection.cpp
|
||||
shared/WatcherConnection.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
win32/FirstPlanetServer.cpp
|
||||
win32/WinMain.cpp
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
|
||||
else()
|
||||
set(PLATFORM_SOURCES
|
||||
linux/main.cpp
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/linux)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shared
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCommandParser/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCompression/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMathArchive/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedThread/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverMetrics/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
|
||||
)
|
||||
|
||||
link_directories(${STLPORT_LIBDIR})
|
||||
|
||||
add_executable(PlanetServer
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(PlanetServer
|
||||
sharedCommandParser
|
||||
sharedCompression
|
||||
sharedDebug
|
||||
sharedFile
|
||||
sharedFoundation
|
||||
sharedLog
|
||||
sharedMath
|
||||
sharedMemoryManager
|
||||
sharedMessageDispatch
|
||||
sharedNetwork
|
||||
sharedNetworkMessages
|
||||
sharedRandom
|
||||
sharedSynchronization
|
||||
sharedThread
|
||||
sharedUtility
|
||||
serverMetrics
|
||||
serverNetworkMessages
|
||||
serverUtility
|
||||
archive
|
||||
fileInterface
|
||||
localization
|
||||
localizationArchive
|
||||
unicode
|
||||
unicodeArchive
|
||||
udplibrary
|
||||
${ZLIB_LIBRARY}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(PlanetServer mswsock ws2_32)
|
||||
endif()
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "PlanetServer.h"
|
||||
|
||||
#include "sharedCompression/SetupSharedCompression.h"
|
||||
#include "sharedDebug/SetupSharedDebug.h"
|
||||
#include "sharedFile/SetupSharedFile.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedFoundation/SetupSharedFoundation.h"
|
||||
#include "sharedLog/SetupSharedLog.h"
|
||||
#include "sharedNetwork/SetupSharedNetwork.h"
|
||||
#include "sharedNetworkMessages/SetupSharedNetworkMessages.h"
|
||||
#include "sharedRandom/SetupSharedRandom.h"
|
||||
#include "sharedThread/SetupSharedThread.h"
|
||||
#include "sharedUtility/SetupSharedUtility.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void dumpPid(const char * argv)
|
||||
{
|
||||
pid_t p = getpid();
|
||||
char fileName[1024];
|
||||
sprintf(fileName, "%s.%d", argv, p);
|
||||
FILE * f = fopen(fileName, "w+");
|
||||
fclose(f); //lint !e668
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
// dumpPid(argv[0]);
|
||||
|
||||
SetupSharedThread::install();
|
||||
SetupSharedDebug::install(1024);
|
||||
|
||||
//-- setup foundation
|
||||
SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game);
|
||||
setupFoundationData.lpCmdLine = ConvertCommandLine(argc,argv);
|
||||
SetupSharedFoundation::install (setupFoundationData);
|
||||
|
||||
SetupSharedCompression::install();
|
||||
SetupSharedFile::install(false);
|
||||
|
||||
SetupSharedNetwork::SetupData networkSetupData;
|
||||
SetupSharedNetwork::getDefaultServerSetupData(networkSetupData);
|
||||
SetupSharedNetwork::install(networkSetupData);
|
||||
|
||||
SetupSharedNetworkMessages::install();
|
||||
|
||||
SetupSharedRandom::install(time(NULL)); //lint !e732 loss of sign (of 0!)
|
||||
|
||||
SetupSharedUtility::Data sharedUtilityData;
|
||||
SetupSharedUtility::setupGameData (sharedUtilityData);
|
||||
SetupSharedUtility::install (sharedUtilityData);
|
||||
|
||||
Os::setProgramName("PlanetServer");
|
||||
ConfigPlanetServer::install();
|
||||
|
||||
char tmp[92];
|
||||
sprintf(tmp, "PlanetServer:%d", Os::getProcessId());
|
||||
SetupSharedLog::install(tmp);
|
||||
|
||||
//-- run game
|
||||
PlanetServer::run();
|
||||
|
||||
SetupSharedLog::remove();
|
||||
SetupSharedFoundation::remove();
|
||||
SetupSharedThread::remove();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// CentralServerConnection.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "CentralServerConnection.h"
|
||||
|
||||
#include "ConsoleManager.h"
|
||||
#include "serverNetworkMessages/CentralPlanetServerConnect.h"
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
#include "sharedNetworkMessages/ConsoleChannelMessages.h"
|
||||
#include "sharedNetwork/NetworkSetupData.h"
|
||||
#include "sharedNetwork/Service.h"
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "PlanetServer.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
CentralServerConnection::CentralServerConnection(const std::string & a, const unsigned short p) :
|
||||
ServerConnection(a, p, NetworkSetupData())
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
CentralServerConnection::~CentralServerConnection()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void CentralServerConnection::onConnectionClosed()
|
||||
{
|
||||
ServerConnection::onConnectionClosed();
|
||||
|
||||
static MessageConnectionCallback m("CentralConnectionClosed");
|
||||
emitMessage(m);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void CentralServerConnection::onConnectionOpened()
|
||||
{
|
||||
ServerConnection::onConnectionOpened();
|
||||
|
||||
DEBUG_REPORT_LOG(true,("Connection to Central opened.\n"));
|
||||
|
||||
CentralPlanetServerConnect msg(ConfigPlanetServer::getSceneID(), PlanetServer::getInstance().getGameService()->getBindAddress(), PlanetServer::getInstance().getGameServicePort());
|
||||
send(msg,true);
|
||||
|
||||
PlanetServer::getInstance().onCentralConnected(this);
|
||||
|
||||
static MessageConnectionCallback m("CentralConnectionOpened");
|
||||
emitMessage(m);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void CentralServerConnection::onReceive(const Archive::ByteStream & message)
|
||||
{
|
||||
Archive::ReadIterator ri = message.begin();
|
||||
const GameNetworkMessage msg(ri);
|
||||
ri = message.begin();
|
||||
|
||||
if(msg.isType("ConGenericMessage"))
|
||||
{
|
||||
const ConGenericMessage cm(ri);
|
||||
std::string result;
|
||||
ConsoleManager::processString(cm.getMsg(), cm.getMsgId(), result);
|
||||
const ConGenericMessage response(result, cm.getMsgId());
|
||||
send(response, true);
|
||||
}
|
||||
|
||||
ServerConnection::onReceive(message);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -0,0 +1,35 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// CentralServerConnection.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_CentralServerConnection_H
|
||||
#define INCLUDED_CentralServerConnection_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "serverUtility/ServerConnection.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class CentralServerConnection : public ServerConnection
|
||||
{
|
||||
public:
|
||||
CentralServerConnection (const std::string & remoteAddress, const unsigned short port);
|
||||
~CentralServerConnection ();
|
||||
|
||||
void onConnectionClosed ();
|
||||
void onConnectionOpened ();
|
||||
const std::string & getClusterName () const;
|
||||
virtual void onReceive (const Archive::ByteStream & message);
|
||||
private:
|
||||
CentralServerConnection (const CentralServerConnection&);
|
||||
CentralServerConnection& operator= (const CentralServerConnection&);
|
||||
CentralServerConnection();
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigPlanetServer.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "QuadtreeNode.h"
|
||||
#include "serverUtility/ConfigServerUtility.h"
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ConfigPlanetServer::Data * ConfigPlanetServer::data = 0;
|
||||
|
||||
#define KEY_INT(a,b) (data->a = ConfigFile::getKeyInt("PlanetServer", #a, b))
|
||||
#define KEY_BOOL(a,b) (data->a = ConfigFile::getKeyBool("PlanetServer", #a, b))
|
||||
//#define KEY_FLOAT(a,b) (data->a = ConfigFile::getKeyFloat("PlanetServer", #a, b)) // commented out for Lint. Uncomment if you need this macro again
|
||||
#define KEY_STRING(a,b) (data->a = ConfigFile::getKeyString("PlanetServer", #a, b))
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void ConfigPlanetServer::install(void)
|
||||
{
|
||||
|
||||
ConfigServerUtility::install();
|
||||
ExitChain::add(&remove, "ConfigPlanetServer::remove");
|
||||
|
||||
data = new ConfigPlanetServer::Data;
|
||||
|
||||
KEY_STRING (centralServerAddress, "swo-dev1.station.sony.com");
|
||||
KEY_INT (centralServerPort, 44455);
|
||||
KEY_STRING (sceneID, "default");
|
||||
KEY_INT (gameServicePort, 0);
|
||||
KEY_INT (taskManagerPort, 60001);
|
||||
KEY_INT (watcherServicePort, 60002);
|
||||
KEY_INT (maxWatcherConnections, 1);
|
||||
KEY_INT (watcherOverflowLimit, 1024 * 1024 * 8); // 8MB overflow for CS PlanetWatcher tool
|
||||
KEY_BOOL (logObjectLoading, false);
|
||||
KEY_INT (maxWatcherUpdatesPerMessage,500); // Max object updates to send to the watcher in a single message
|
||||
KEY_STRING (gameServiceBindInterface, "");
|
||||
KEY_STRING (watcherServiceBindInterface, "");
|
||||
KEY_BOOL (loadWholePlanet, false);
|
||||
KEY_BOOL (loadWholePlanetMultiserver, false);
|
||||
KEY_BOOL (logPreloading, false);
|
||||
KEY_INT (numTutorialServers, 1);
|
||||
KEY_INT (maxInterestRadius, Node::getNodeSize());
|
||||
KEY_INT (populationCountTime, 60); // seconds
|
||||
KEY_BOOL (logChunkLoading, false);
|
||||
KEY_INT (preloadBailoutTime, 0); // seconds
|
||||
KEY_STRING (preloadDataTableName, "datatables/planet_server/preload_list.iff");
|
||||
KEY_INT (authTransferSanityCheckTimeMs, 15000);
|
||||
KEY_INT (gameServerRestartDelayTimeSeconds, 60);
|
||||
KEY_BOOL (enableContentsChecking, false);
|
||||
KEY_INT (maxGameServers, 0);
|
||||
KEY_BOOL (enableStartupCreateProxies, true);
|
||||
KEY_BOOL (requestDbSaveOnGameServerCrash, true);
|
||||
KEY_BOOL (gameServerProfiling, false);
|
||||
KEY_BOOL (gameServerDebugging, false);
|
||||
KEY_INT (gameServerDebuggingPortBase, 0);
|
||||
KEY_INT (maxTimeToWaitForGameServerStartSeconds, 5*60); // seconds
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool ConfigPlanetServer::getGameServerProfiling()
|
||||
{
|
||||
return data->gameServerProfiling;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool ConfigPlanetServer::getGameServerDebugging()
|
||||
{
|
||||
return data->gameServerDebugging;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void ConfigPlanetServer::remove(void)
|
||||
{
|
||||
delete data;
|
||||
data = 0;
|
||||
ConfigServerUtility::remove();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
int ConfigPlanetServer::getGameServerDebuggingPortBase()
|
||||
{
|
||||
return data->gameServerDebuggingPortBase;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -0,0 +1,287 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigPlanetServer.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_ConfigPlanetServer_H
|
||||
#define INCLUDED_ConfigPlanetServer_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class ConfigPlanetServer
|
||||
{
|
||||
public:
|
||||
struct Data
|
||||
{
|
||||
const char * centralServerAddress;
|
||||
int centralServerPort;
|
||||
const char * sceneID;
|
||||
int gameServicePort;
|
||||
int watcherServicePort;
|
||||
int taskManagerPort;
|
||||
int maxWatcherConnections;
|
||||
int watcherOverflowLimit;
|
||||
bool logObjectLoading;
|
||||
int maxWatcherUpdatesPerMessage;
|
||||
const char * gameServiceBindInterface;
|
||||
const char * watcherServiceBindInterface;
|
||||
bool loadWholePlanet;
|
||||
bool loadWholePlanetMultiserver;
|
||||
bool logPreloading;
|
||||
int numTutorialServers;
|
||||
int maxInterestRadius;
|
||||
int populationCountTime;
|
||||
bool logChunkLoading;
|
||||
int preloadBailoutTime;
|
||||
const char * preloadDataTableName;
|
||||
int authTransferSanityCheckTimeMs;
|
||||
int gameServerRestartDelayTimeSeconds;
|
||||
bool enableContentsChecking;
|
||||
int maxGameServers;
|
||||
bool enableStartupCreateProxies;
|
||||
bool requestDbSaveOnGameServerCrash;
|
||||
bool gameServerDebugging;
|
||||
bool gameServerProfiling;
|
||||
int gameServerDebuggingPortBase;
|
||||
int maxTimeToWaitForGameServerStartSeconds;
|
||||
};
|
||||
|
||||
static void install ();
|
||||
static void remove ();
|
||||
|
||||
static const char * getCentralServerAddress ();
|
||||
static const uint16 getCentralServerPort ();
|
||||
static const char * getSceneID ();
|
||||
static const uint16 getGameServicePort ();
|
||||
static const uint16 getWatcherServicePort ();
|
||||
static const uint16 getTaskManagerPort ();
|
||||
static const int getMaxWatcherConnections();
|
||||
static const int getWatcherOverflowLimit ();
|
||||
static const bool getLogObjectLoading ();
|
||||
static const int getMaxWatcherUpdatesPerMessage();
|
||||
static const char * getGameServiceBindInterface();
|
||||
static const char * getWatcherServiceBindInterface();
|
||||
static const bool getLoadWholePlanet();
|
||||
static const bool getLoadWholePlanetMultiserver();
|
||||
static const bool getLogPreloading();
|
||||
static const int getNumTutorialServers();
|
||||
static const int getMaxInterestRadius();
|
||||
static const int getPopulationCountTime();
|
||||
static const bool getLogChunkLoading();
|
||||
static const int getPreloadBailoutTime();
|
||||
static const char * getPreloadDataTableName();
|
||||
static const int getAuthTransferSanityCheckTimeMs();
|
||||
static const unsigned int getGameServerRestartDelayTimeSeconds();
|
||||
static bool getEnableContentsChecking();
|
||||
static int getMaxGameServers();
|
||||
static bool getEnableStartupCreateProxies();
|
||||
static bool getRequestDbSaveOnGameServerCrash();
|
||||
static bool getGameServerDebugging();
|
||||
static bool getGameServerProfiling();
|
||||
static int getGameServerDebuggingPortBase();
|
||||
static int getMaxTimeToWaitForGameServerStartSeconds();
|
||||
private:
|
||||
static Data * data;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline const char * ConfigPlanetServer::getCentralServerAddress()
|
||||
{
|
||||
return data->centralServerAddress;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline const uint16 ConfigPlanetServer::getCentralServerPort()
|
||||
{
|
||||
return static_cast<const uint16>(data->centralServerPort);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline const char * ConfigPlanetServer::getSceneID()
|
||||
{
|
||||
return data->sceneID;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline const uint16 ConfigPlanetServer::getGameServicePort()
|
||||
{
|
||||
return static_cast<uint16>(data->gameServicePort);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline const uint16 ConfigPlanetServer::getTaskManagerPort()
|
||||
{
|
||||
return static_cast<uint16>(data->taskManagerPort);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const uint16 ConfigPlanetServer::getWatcherServicePort()
|
||||
{
|
||||
return static_cast<uint16>(data->watcherServicePort);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getMaxWatcherConnections()
|
||||
{
|
||||
return data->maxWatcherConnections;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getWatcherOverflowLimit()
|
||||
{
|
||||
return data->watcherOverflowLimit;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const bool ConfigPlanetServer::getLogObjectLoading()
|
||||
{
|
||||
return data->logObjectLoading;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getMaxWatcherUpdatesPerMessage()
|
||||
{
|
||||
return data->maxWatcherUpdatesPerMessage;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const char * ConfigPlanetServer::getGameServiceBindInterface()
|
||||
{
|
||||
return data->gameServiceBindInterface;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const char * ConfigPlanetServer::getWatcherServiceBindInterface()
|
||||
{
|
||||
return data->watcherServiceBindInterface;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const bool ConfigPlanetServer::getLoadWholePlanet()
|
||||
{
|
||||
return data->loadWholePlanet;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const bool ConfigPlanetServer::getLoadWholePlanetMultiserver()
|
||||
{
|
||||
return data->loadWholePlanetMultiserver;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const bool ConfigPlanetServer::getLogPreloading()
|
||||
{
|
||||
return data->logPreloading;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getNumTutorialServers()
|
||||
{
|
||||
return data->numTutorialServers;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getMaxInterestRadius()
|
||||
{
|
||||
return data->maxInterestRadius;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getPopulationCountTime()
|
||||
{
|
||||
return data->populationCountTime;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const bool ConfigPlanetServer::getLogChunkLoading()
|
||||
{
|
||||
return data->logChunkLoading;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getPreloadBailoutTime()
|
||||
{
|
||||
return data->preloadBailoutTime;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const char * ConfigPlanetServer::getPreloadDataTableName()
|
||||
{
|
||||
return data->preloadDataTableName;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const int ConfigPlanetServer::getAuthTransferSanityCheckTimeMs()
|
||||
{
|
||||
return data->authTransferSanityCheckTimeMs;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const unsigned int ConfigPlanetServer::getGameServerRestartDelayTimeSeconds()
|
||||
{
|
||||
return static_cast<unsigned int>(data->gameServerRestartDelayTimeSeconds);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool ConfigPlanetServer::getEnableContentsChecking()
|
||||
{
|
||||
return data->enableContentsChecking;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int ConfigPlanetServer::getMaxGameServers()
|
||||
{
|
||||
return data->maxGameServers;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool ConfigPlanetServer::getEnableStartupCreateProxies()
|
||||
{
|
||||
return data->enableStartupCreateProxies;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool ConfigPlanetServer::getRequestDbSaveOnGameServerCrash()
|
||||
{
|
||||
return data->requestDbSaveOnGameServerCrash;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int ConfigPlanetServer::getMaxTimeToWaitForGameServerStartSeconds()
|
||||
{
|
||||
return data->maxTimeToWaitForGameServerStartSeconds;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
// ConsoleCommandParser.cpp
|
||||
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
|
||||
// Author: Justin Randall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "ConsoleCommandParser.h"
|
||||
#include "UnicodeUtils.h"
|
||||
#include <vector>
|
||||
#include "Unicode.h"
|
||||
|
||||
#pragma warning(disable:4355) // Passing "this" as a parameter to the base class constructor
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace CommandNames
|
||||
{
|
||||
#define MAKE_COMMAND(a) const char * const a = #a
|
||||
#undef MAKE_COMMAND
|
||||
}
|
||||
|
||||
const CommandParser::CmdInfo cmds[] =
|
||||
{
|
||||
{"planet", 0, "", ""},
|
||||
{"", 0, "", ""} // this must be last
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ConsoleCommandParser::ConsoleCommandParser() :
|
||||
CommandParser ("", 0, "...", "console commands", NULL)
|
||||
{
|
||||
createDelegateCommands(cmds);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ConsoleCommandParser::~ConsoleCommandParser()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool ConsoleCommandParser::performParsing(const NetworkId & /* track */, const StringVector_t & argv, const String_t &, String_t & result, const CommandParser *)
|
||||
{
|
||||
bool successResult = false;
|
||||
|
||||
if(isCommand(argv[0], "planet"))
|
||||
{
|
||||
if(argv.size() > 2)
|
||||
{
|
||||
if(isCommand(argv[2], "runState"))
|
||||
{
|
||||
successResult = true;
|
||||
result += Unicode::narrowToWide("running");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return successResult;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -0,0 +1,29 @@
|
||||
// ConsoleCommandParser.h
|
||||
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_ConsoleCommandParser_H
|
||||
#define _INCLUDED_ConsoleCommandParser_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "sharedCommandParser/CommandParser.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class ConsoleCommandParser : public CommandParser
|
||||
{
|
||||
public:
|
||||
ConsoleCommandParser();
|
||||
~ConsoleCommandParser();
|
||||
virtual bool performParsing(const NetworkId & userId, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser * node);
|
||||
|
||||
private:
|
||||
ConsoleCommandParser & operator = (const ConsoleCommandParser & rhs);
|
||||
ConsoleCommandParser(const ConsoleCommandParser & source);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#endif // _INCLUDED_ConsoleCommandParser_H
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// ConsoleManager.cpp
|
||||
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
|
||||
// Author: Justin Randall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
#include "ConsoleManager.h"
|
||||
#include "ConsoleCommandParser.h"
|
||||
#include "UnicodeUtils.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace ConsoleManagerNamespace
|
||||
{
|
||||
ConsoleCommandParser * s_consoleCommandParserRoot = NULL;
|
||||
}
|
||||
|
||||
using namespace ConsoleManagerNamespace;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ConsoleManager::ConsoleManager()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ConsoleManager::~ConsoleManager()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void ConsoleManager::install()
|
||||
{
|
||||
s_consoleCommandParserRoot = new ConsoleCommandParser;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void ConsoleManager::remove()
|
||||
{
|
||||
delete s_consoleCommandParserRoot;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void ConsoleManager::processString(const std::string & msg, int const track, std::string & result)
|
||||
{
|
||||
Unicode::String wideResult;
|
||||
IGNORE_RETURN(s_consoleCommandParserRoot->parse(NetworkId(static_cast<NetworkId::NetworkIdType>(track)), Unicode::narrowToWide(msg), wideResult));
|
||||
result = Unicode::wideToNarrow(wideResult);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// ConsoleManager.h
|
||||
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _INCLUDED_ConsoleManager_H
|
||||
#define _INCLUDED_ConsoleManager_H
|
||||
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class ConsoleManager
|
||||
{
|
||||
public:
|
||||
static void install();
|
||||
static void remove();
|
||||
static void processString(const std::string & msg, int track, std::string & result);
|
||||
private:
|
||||
ConsoleManager & operator = (const ConsoleManager & rhs);
|
||||
ConsoleManager(const ConsoleManager & source);
|
||||
ConsoleManager();
|
||||
~ConsoleManager();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#endif // _INCLUDED_ConsoleManager_H
|
||||
@@ -0,0 +1,24 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstPlanetServer.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_FirstPlanetServer_H
|
||||
#define INCLUDED_FirstPlanetServer_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedDebug/FirstSharedDebug.h"
|
||||
#include "sharedMemoryManager/FirstSharedMemoryManager.h"
|
||||
|
||||
#include "sharedFoundation/NetworkIdArchive.h"
|
||||
|
||||
#include "PlanetServer.h"
|
||||
#include "sharedNetworkMessages/GameNetworkMessage.h"
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// GameServerConnection.cpp
|
||||
//
|
||||
// Copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "GameServerConnection.h"
|
||||
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "PlanetProxyObject.h"
|
||||
#include "Scene.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
GameServerConnection::GameServerConnection(UdpConnectionMT *u, TcpClient *t) :
|
||||
ServerConnection(u, t),
|
||||
m_preloadNumber(0),
|
||||
m_forwardCounts(),
|
||||
m_forwardDestinationServers(),
|
||||
m_forwardMessages()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
GameServerConnection::~GameServerConnection()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerConnection::onConnectionClosed()
|
||||
{
|
||||
ServerConnection::onConnectionClosed();
|
||||
|
||||
static MessageConnectionCallback m("GameConnectionClosed");
|
||||
emitMessage(m);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerConnection::onConnectionOpened()
|
||||
{
|
||||
ServerConnection::onConnectionOpened();
|
||||
|
||||
LOG("PlanetServerConnections", ("%s got a connection from a GameServer", ConfigPlanetServer::getSceneID()));
|
||||
|
||||
static MessageConnectionCallback m("GameConnectionOpened");
|
||||
emitMessage(m);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerConnection::onReceive(Archive::ByteStream const &message)
|
||||
{
|
||||
Archive::ReadIterator ri = message.begin();
|
||||
GameNetworkMessage msg(ri);
|
||||
ri = message.begin();
|
||||
|
||||
if (!m_forwardDestinationServers.empty())
|
||||
{
|
||||
if (isMessageForwardable(msg.getType()))
|
||||
{
|
||||
m_forwardMessages.push_back(std::make_pair(message, m_forwardDestinationServers.back()));
|
||||
return;
|
||||
}
|
||||
else if (msg.isType("EndForward"))
|
||||
{
|
||||
if (--m_forwardCounts.back() == 0)
|
||||
{
|
||||
m_forwardCounts.pop_back();
|
||||
m_forwardDestinationServers.pop_back();
|
||||
if (m_forwardDestinationServers.empty())
|
||||
pushAndClearObjectForwarding();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (msg.isType("BeginForward"))
|
||||
{
|
||||
GenericValueTypeMessage<std::vector<uint32> > const beginForwardMessage(ri);
|
||||
if (beginForwardMessage.getValue() == m_forwardDestinationServers.back())
|
||||
++m_forwardCounts.back();
|
||||
else
|
||||
{
|
||||
m_forwardCounts.push_back(1);
|
||||
m_forwardDestinationServers.push_back(beginForwardMessage.getValue());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.isType("BeginForward"))
|
||||
{
|
||||
GenericValueTypeMessage<std::vector<uint32> > const beginForwardMessage(ri);
|
||||
|
||||
m_forwardCounts.push_back(1);
|
||||
m_forwardDestinationServers.push_back(beginForwardMessage.getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
ServerConnection::onReceive(message);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerConnection::pushAndClearObjectForwarding()
|
||||
{
|
||||
GameNetworkMessage const endForwardMessage("EndForward");
|
||||
std::vector<std::pair<Archive::ByteStream, std::vector<uint32> > > centralForwardMessages;
|
||||
|
||||
{
|
||||
for (std::vector<std::pair<Archive::ByteStream, std::vector<uint32> > >::const_iterator i = m_forwardMessages.begin(); i != m_forwardMessages.end(); ++i)
|
||||
{
|
||||
Archive::ByteStream const &msg = (*i).first;
|
||||
std::vector<uint32> const &destinationServers = (*i).second;
|
||||
std::vector<uint32> centralForwardPids;
|
||||
|
||||
for (std::vector<uint32>::const_iterator j = destinationServers.begin(); j != destinationServers.end(); ++j)
|
||||
{
|
||||
GameServerConnection * const conn = PlanetServer::getInstance().getGameServerConnection(*j);
|
||||
if (conn)
|
||||
conn->Connection::send(msg, true);
|
||||
else
|
||||
centralForwardPids.push_back(*j);
|
||||
}
|
||||
|
||||
if (!centralForwardPids.empty())
|
||||
centralForwardMessages.push_back(std::make_pair(msg, centralForwardPids));
|
||||
}
|
||||
}
|
||||
|
||||
if (!centralForwardMessages.empty())
|
||||
{
|
||||
ServerConnection * const conn = PlanetServer::getInstance().getCentralServerConnection();
|
||||
|
||||
if (conn)
|
||||
{
|
||||
std::vector<uint32> const *lastDestinationServers = &(*centralForwardMessages.begin()).second;
|
||||
bool subBlock = false;
|
||||
|
||||
GenericValueTypeMessage<std::vector<uint32> > const beginForwardMessage("BeginForward", *lastDestinationServers);
|
||||
conn->send(beginForwardMessage, true);
|
||||
|
||||
for (std::vector<std::pair<Archive::ByteStream, std::vector<uint32> > >::const_iterator i = centralForwardMessages.begin(); i != centralForwardMessages.end(); ++i)
|
||||
{
|
||||
Archive::ByteStream const &msg = (*i).first;
|
||||
std::vector<uint32> const &destinationServers = (*i).second;
|
||||
|
||||
if (destinationServers != *lastDestinationServers)
|
||||
{
|
||||
if (subBlock)
|
||||
conn->send(endForwardMessage, true);
|
||||
GenericValueTypeMessage<std::vector<uint32> > const beginForwardMessage("BeginForward", destinationServers);
|
||||
conn->send(beginForwardMessage, true);
|
||||
subBlock = true;
|
||||
lastDestinationServers = &destinationServers;
|
||||
}
|
||||
|
||||
conn->Connection::send(msg, true);
|
||||
}
|
||||
|
||||
if (subBlock)
|
||||
conn->send(endForwardMessage, true);
|
||||
conn->send(endForwardMessage, true);
|
||||
}
|
||||
}
|
||||
|
||||
m_forwardMessages.clear();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// GameServerConnection.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_GameServerConnection_H
|
||||
#define INCLUDED_GameServerConnection_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "serverUtility/ServerConnection.h"
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class GameServerConnection: public ServerConnection
|
||||
{
|
||||
public:
|
||||
GameServerConnection(UdpConnectionMT *, TcpClient *);
|
||||
virtual ~GameServerConnection();
|
||||
virtual void onConnectionClosed();
|
||||
virtual void onConnectionOpened();
|
||||
virtual void onReceive(Archive::ByteStream const &message);
|
||||
|
||||
void setPreloadNumber(int preloadNumber);
|
||||
int getPreloadNumber() const;
|
||||
|
||||
private:
|
||||
GameServerConnection(GameServerConnection const &);
|
||||
GameServerConnection &operator=(GameServerConnection const &);
|
||||
GameServerConnection();
|
||||
|
||||
void pushAndClearObjectForwarding();
|
||||
|
||||
int m_preloadNumber;
|
||||
std::vector<int> m_forwardCounts;
|
||||
std::vector<std::vector<uint32> > m_forwardDestinationServers;
|
||||
std::vector<std::pair<Archive::ByteStream, std::vector<uint32> > > m_forwardMessages;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline void GameServerConnection::setPreloadNumber(int preloadNumber)
|
||||
{
|
||||
m_preloadNumber = preloadNumber;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline int GameServerConnection::getPreloadNumber() const
|
||||
{
|
||||
return m_preloadNumber;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// GameServerData.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "GameServerData.h"
|
||||
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "GameServerConnection.h"
|
||||
#include "PlanetServer.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
GameServerData::GameServerData(GameServerConnection *connection) :
|
||||
m_connection(connection),
|
||||
m_objectCount(0),
|
||||
m_interestObjectCount(0),
|
||||
m_interestCreatureObjectCount(0),
|
||||
m_serverStatus(SS_unready)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
GameServerData::GameServerData(const GameServerData &rhs) :
|
||||
m_connection(NULL), // connection pointer is not copied when we copy GameServerDatas
|
||||
m_objectCount(rhs.m_objectCount),
|
||||
m_interestObjectCount(rhs.m_interestObjectCount),
|
||||
m_interestCreatureObjectCount(rhs.m_interestCreatureObjectCount),
|
||||
m_serverStatus(rhs.m_serverStatus)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
GameServerData::GameServerData() :
|
||||
m_connection(NULL),
|
||||
m_objectCount(0),
|
||||
m_interestObjectCount(0),
|
||||
m_interestCreatureObjectCount(0),
|
||||
m_serverStatus(SS_unready)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
GameServerData &GameServerData::operator=(const GameServerData &rhs)
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this;
|
||||
|
||||
m_connection=NULL; // connection pointer is not copied when we copy GameServerDatas
|
||||
m_objectCount=rhs.m_objectCount;
|
||||
m_interestObjectCount=rhs.m_interestObjectCount;
|
||||
m_interestCreatureObjectCount=rhs.m_interestCreatureObjectCount;
|
||||
m_serverStatus=rhs.m_serverStatus;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerData::universeLoaded()
|
||||
{
|
||||
WARNING_DEBUG_FATAL(m_serverStatus != SS_readyForObjects,("Got UniverseLoaded for server %d when it was not in the \"readyForObjects\" state.",getProcessId()));
|
||||
m_serverStatus = SS_loadedUniverseObjects;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerData::ready()
|
||||
{
|
||||
WARNING_DEBUG_FATAL(m_serverStatus != SS_unready,("Got GameServerReady for server %d when it was not in the \"unready\" state.",getProcessId()));
|
||||
m_serverStatus = SS_readyForObjects;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerData::preloadComplete()
|
||||
{
|
||||
WARNING_DEBUG_FATAL(PlanetServer::getInstance().getEnablePreload() && (m_serverStatus != SS_loadedUniverseObjects),("Got prelaod complete for server %d when it was not in the \"loadedUniverseObjects\" state.",getProcessId()));
|
||||
m_serverStatus = SS_running;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
uint32 GameServerData::getProcessId() const
|
||||
{
|
||||
NOT_NULL(m_connection);
|
||||
return m_connection->getProcessId();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void GameServerData::debugOutputData() const
|
||||
{
|
||||
LOG("LoadBalancing", ("Server %d: %i objects, %i interest objects",getProcessId(),getObjectCount(),getInterestObjectCount()));
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,119 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// GameServerData.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_GameServerData_H
|
||||
#define INCLUDED_GameServerData_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class GameServerConnection;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class GameServerData
|
||||
{
|
||||
public:
|
||||
explicit GameServerData(GameServerConnection *connection);
|
||||
GameServerData(const GameServerData &rhs);
|
||||
GameServerData();
|
||||
GameServerData &operator=(const GameServerData &rhs);
|
||||
|
||||
public:
|
||||
enum ServerStatus {SS_unready, SS_readyForObjects, SS_loadedUniverseObjects, SS_running};
|
||||
|
||||
public:
|
||||
GameServerConnection * getConnection ();
|
||||
int getObjectCount () const;
|
||||
int getInterestObjectCount () const;
|
||||
int getInterestCreatureObjectCount() const;
|
||||
ServerStatus getServerStatus () const;
|
||||
uint32 getProcessId () const;
|
||||
void debugOutputData () const;
|
||||
|
||||
void adjustObjectCount (int adjustment);
|
||||
void adjustInterestObjectCount (int adjustment);
|
||||
void adjustInterestCreatureObjectCount (int adjustment);
|
||||
void universeLoaded ();
|
||||
void ready ();
|
||||
void preloadComplete ();
|
||||
|
||||
bool isRunning () const;
|
||||
|
||||
private:
|
||||
GameServerConnection * m_connection;
|
||||
int m_objectCount;
|
||||
int m_interestObjectCount;
|
||||
int m_interestCreatureObjectCount;
|
||||
ServerStatus m_serverStatus;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline GameServerConnection *GameServerData::getConnection()
|
||||
{
|
||||
return m_connection;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int GameServerData::getObjectCount() const
|
||||
{
|
||||
return m_objectCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void GameServerData::adjustObjectCount(int adjustment)
|
||||
{
|
||||
m_objectCount+=adjustment;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void GameServerData::adjustInterestObjectCount(int adjustment)
|
||||
{
|
||||
m_interestObjectCount+=adjustment;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline GameServerData::ServerStatus GameServerData::getServerStatus() const
|
||||
{
|
||||
return m_serverStatus;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int GameServerData::getInterestObjectCount() const
|
||||
{
|
||||
return m_interestObjectCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool GameServerData::isRunning() const
|
||||
{
|
||||
return m_serverStatus == SS_running;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int GameServerData::getInterestCreatureObjectCount() const
|
||||
{
|
||||
return m_interestCreatureObjectCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void GameServerData::adjustInterestCreatureObjectCount (int adjustment)
|
||||
{
|
||||
m_interestCreatureObjectCount+=adjustment;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,701 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PlanetProxyObject.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "PlanetProxyObject.h"
|
||||
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "GameServerData.h"
|
||||
#include "PlanetServer.h"
|
||||
#include "QuadtreeNode.h"
|
||||
#include "Scene.h"
|
||||
#include "WatcherConnection.h"
|
||||
#include "serverNetworkMessages/LoadObjectMessage.h"
|
||||
#include "serverNetworkMessages/SetAuthoritativeMessage.h"
|
||||
#include "serverNetworkMessages/UnloadProxyMessage.h"
|
||||
#include "sharedFoundation/Clock.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/MemoryBlockManager.h"
|
||||
#include "sharedFoundation/Tag.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "sharedMathArchive/TransformArchive.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
MemoryBlockManager* PlanetProxyObject::memoryBlockManager;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
PlanetProxyObject::PlanetProxyObject (const NetworkId &objectId) :
|
||||
m_objectId(objectId),
|
||||
m_containedBy(NetworkId::cms_invalid),
|
||||
m_x(0),
|
||||
m_y(0),
|
||||
m_z(0),
|
||||
m_authoritativeServer(0),
|
||||
m_lastReportedServer(0),
|
||||
m_interestRadius(0),
|
||||
m_quadtreeNode(NULL),
|
||||
m_authTransferTimeMs(Clock::timeMs()),
|
||||
m_contents(NULL),
|
||||
m_level(0),
|
||||
m_hibernating(false),
|
||||
m_templateCrc(0),
|
||||
m_aiActivity(-1),
|
||||
m_creationType(-1)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PlanetProxyObject::~PlanetProxyObject ()
|
||||
{
|
||||
if (PlanetServer::getInstance().isWatcherPresent())
|
||||
{
|
||||
outputStatusToAll(true);
|
||||
}
|
||||
m_quadtreeNode=0;
|
||||
|
||||
if (m_contents)
|
||||
{
|
||||
for (std::vector<NetworkId>::const_iterator i=m_contents->begin(); i!=m_contents->end(); ++i)
|
||||
WARNING(true,("Object %s was deleted without removing contained object %s first",m_objectId.getValueString().c_str(), i->getValueString().c_str()));
|
||||
delete m_contents;
|
||||
m_contents=0;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Update an object with new data sent from a game server.
|
||||
* Checks to see what changed, then takes appropriate actions.
|
||||
*/
|
||||
void PlanetProxyObject::update(int x, int y, int z, NetworkId containedBy, uint32 authoritativeServer, int interestRadius, int objectTypeTag, int const level, bool const hibernating, uint32 const templateCrc, int const aiActivity, int const creationType)
|
||||
{
|
||||
WARNING_DEBUG_FATAL(m_objectId==NetworkId::cms_invalid,("Object ID was 0."));
|
||||
bool watcherUpdateNeeded = false;
|
||||
|
||||
m_level = level;
|
||||
m_hibernating = hibernating;
|
||||
m_templateCrc = templateCrc;
|
||||
m_aiActivity = aiActivity;
|
||||
m_creationType = creationType;
|
||||
|
||||
if ((m_authoritativeServer != 0 ) && (authoritativeServer != m_authoritativeServer) && (containedBy == NetworkId::cms_invalid))
|
||||
{
|
||||
static unsigned long authTransferSanityCheckTimeMs = ConfigPlanetServer::getAuthTransferSanityCheckTimeMs();
|
||||
if (Clock::timeMs()-m_authTransferTimeMs > authTransferSanityCheckTimeMs)
|
||||
{
|
||||
WARNING(true, ("Resending auth transfer for %s to %lu due to receiving a stale position update.", m_objectId.getValueString().c_str(), authoritativeServer));
|
||||
sendAuthorityChange(authoritativeServer, m_authoritativeServer, false);
|
||||
return;
|
||||
}
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Ignoring update for %s from %lu because server was not authoritative.",m_objectId.getValueString().c_str(),authoritativeServer));
|
||||
return;
|
||||
}
|
||||
|
||||
if (interestRadius>ConfigPlanetServer::getMaxInterestRadius())
|
||||
interestRadius = ConfigPlanetServer::getMaxInterestRadius();
|
||||
|
||||
if (interestRadius>0 && PlanetServer::getInstance().isInTutorialMode())
|
||||
interestRadius = 1;
|
||||
|
||||
if (containedBy!=NetworkId::cms_invalid)
|
||||
{
|
||||
// get coordinates from container
|
||||
PlanetProxyObject *container = Scene::getInstance().findObjectByID(containedBy);
|
||||
if (container)
|
||||
{
|
||||
x=container->getX();
|
||||
y=container->getY();
|
||||
z=container->getZ();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("PlanetUpdate",("Game server said object %s was contained by object %s, but we could not find the container.",m_objectId.getValueString().c_str(),containedBy.getValueString().c_str()));
|
||||
containedBy = NetworkId::cms_invalid; // so that we'll try again when the object moves again, in case we just got objects out-of-order from the game server
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32> oldProxyList;
|
||||
|
||||
Node *newNode=Scene::getInstance().findNodeByPosition(x,z);
|
||||
NOT_NULL(newNode);
|
||||
if (newNode!=m_quadtreeNode || m_interestRadius != interestRadius || m_authoritativeServer != authoritativeServer || m_containedBy != containedBy)
|
||||
{
|
||||
watcherUpdateNeeded = true;
|
||||
|
||||
// For debugging, update the contents of the containers
|
||||
if (ConfigPlanetServer::getEnableContentsChecking() && (m_containedBy!=containedBy))
|
||||
updateContentsTracking(containedBy);
|
||||
|
||||
bool const firstUpdate = (m_quadtreeNode == NULL);
|
||||
|
||||
if (m_quadtreeNode!=NULL) // if this is the first update for this object, m_quadtreeNode will be NULL because it hasn't been placed anywhere yet
|
||||
{
|
||||
removeServerStatistics();
|
||||
|
||||
// remember old list of proxies
|
||||
getServers(oldProxyList);
|
||||
|
||||
// remove from the old location
|
||||
m_quadtreeNode->removeObject(this);
|
||||
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading", ("unsubscribing nodes for object id=[%s]", m_objectId.getValueString().c_str()));
|
||||
unsubscribeSurroundingNodes(false);
|
||||
}
|
||||
|
||||
// update data
|
||||
m_quadtreeNode=newNode;
|
||||
m_x=x;
|
||||
m_y=y;
|
||||
m_z=z;
|
||||
m_interestRadius=interestRadius;
|
||||
m_objectTypeTag = objectTypeTag;
|
||||
m_authoritativeServer=authoritativeServer;
|
||||
m_containedBy=containedBy;
|
||||
|
||||
// make sure the destination is loaded
|
||||
if (!newNode->isLoaded())
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Loading node %s because object %s entered it.",newNode->getDebugNodeString().c_str(), m_objectId.getValueString().c_str()));
|
||||
newNode->load();
|
||||
}
|
||||
|
||||
// check if we're on the right server
|
||||
if (!isAuthorityOk())
|
||||
{
|
||||
uint32 preferredServer = m_quadtreeNode->getPreferredServer();
|
||||
if (m_containedBy==NetworkId::cms_invalid)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Changing authority for object %s from %lu to %lu because node %s is authoritative on that server.",
|
||||
m_objectId.getValueString().c_str(),m_authoritativeServer,preferredServer,m_quadtreeNode->getDebugNodeString().c_str()));
|
||||
changeAuthority(preferredServer, false, false); // changes m_authoritativeServer and sends message
|
||||
|
||||
// we received the object for the first time, and we had to
|
||||
// transfer the object's authority, so we need to make sure
|
||||
// to unload the object on the current authoritative server,
|
||||
// if necessary
|
||||
if (firstUpdate)
|
||||
oldProxyList.push_back(authoritativeServer);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING(true,("Programmer bug: Object %s is in container %s, which is node %s. The object should be authoritative on server %i but it is authoritative on server %i.",
|
||||
m_objectId.getValueString().c_str(),m_containedBy.getValueString().c_str(),m_quadtreeNode->getDebugNodeString().c_str(), m_authoritativeServer, preferredServer));
|
||||
}
|
||||
}
|
||||
|
||||
// place in the new location
|
||||
newNode->addObject(this);
|
||||
|
||||
if (interestRadius > 0)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading", ("subscribing nodes for object id=[%s]", m_objectId.getValueString().c_str()));
|
||||
subscribeSurroundingNodes();
|
||||
}
|
||||
|
||||
// check against new interested servers, and send proxy/unproxy as needed
|
||||
if (m_containedBy==NetworkId::cms_invalid) // we don't manage proxies for containers
|
||||
{
|
||||
std::vector<uint32> newProxyList;
|
||||
getServers(newProxyList);
|
||||
changeProxies(oldProxyList,newProxyList);
|
||||
}
|
||||
|
||||
addServerStatistics();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_interestRadius > 0 || (abs(m_x - x) > 25) || (abs(m_z - z) > 25))
|
||||
watcherUpdateNeeded = true;
|
||||
}
|
||||
|
||||
if (PlanetServer::getInstance().isWatcherPresent() && watcherUpdateNeeded)
|
||||
{
|
||||
m_x=x;
|
||||
m_y=y;
|
||||
m_z=z;
|
||||
m_objectTypeTag = objectTypeTag;
|
||||
|
||||
outputStatusToAll(false);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::unsubscribeSurroundingNodes(bool clearZeroSubscriptions)
|
||||
{
|
||||
if (m_interestRadius <= 0)
|
||||
return;
|
||||
|
||||
Scene::NodeListType nodelist;
|
||||
Scene::getInstance().findIntersection(nodelist,m_x,m_z,m_interestRadius);
|
||||
|
||||
for (Scene::NodeListType::iterator i=nodelist.begin(); i!=nodelist.end(); ++i)
|
||||
{
|
||||
(*i)->unsubscribeServer(m_authoritativeServer, 1, clearZeroSubscriptions);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::subscribeSurroundingNodes()
|
||||
{
|
||||
if (m_interestRadius <= 0)
|
||||
return;
|
||||
|
||||
NOT_NULL(m_quadtreeNode);
|
||||
Scene::NodeListType nodelist;
|
||||
Scene::getInstance().findIntersection(nodelist,m_x,m_z,m_interestRadius);
|
||||
|
||||
for (Scene::NodeListType::iterator i=nodelist.begin(); i!=nodelist.end(); ++i)
|
||||
{
|
||||
(*i)->subscribeServer(m_authoritativeServer, 1);
|
||||
uint32 serverId = (*i)->getPreferredServer();
|
||||
if (serverId != m_authoritativeServer)
|
||||
m_quadtreeNode->subscribeServer(serverId,0); // make sure if we can see them, they can see us
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Restore the object's authority to the specified game server.
|
||||
*/
|
||||
void PlanetProxyObject::restoreAuthority(uint32 gameServer)
|
||||
{
|
||||
m_authoritativeServer = gameServer;
|
||||
m_lastReportedServer = gameServer;
|
||||
|
||||
// Send queued messages
|
||||
PlanetServer::getInstance().sendQueuedMessagesForObject(*this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Make the object authortiative on a different game server. Sends a
|
||||
* message to the game servers to change authority and updates
|
||||
* m_authoritativeServer.
|
||||
*/
|
||||
void PlanetProxyObject::changeAuthority(uint32 newGameServer, bool handlingCrash, bool forcedByGame)
|
||||
{
|
||||
if (handlingCrash)
|
||||
sendAuthorityChange(newGameServer, newGameServer, true);
|
||||
else if (!forcedByGame)
|
||||
sendAuthorityChange(m_authoritativeServer, newGameServer, false);
|
||||
m_authoritativeServer = newGameServer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Make the object authoritative on a different game server and adjust the
|
||||
* subscription counts.
|
||||
*/
|
||||
void PlanetProxyObject::changeAuthorityAndSubscriptions(uint32 newGameServer)
|
||||
{
|
||||
unsubscribeSurroundingNodes(false);
|
||||
changeAuthority(newGameServer, false, false);
|
||||
subscribeSurroundingNodes();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when an object should be unloaded from the world. The object
|
||||
* should be removed from the active game servers, but not deleted from
|
||||
* the database.
|
||||
*
|
||||
* This function also removes the PlanetProxyObject from all data structures.
|
||||
* On exit, it is legal to delete the PlanetProxyObject.
|
||||
*
|
||||
* @param sendToGameServer Set to true if ForceUnloadObjectMessage should be
|
||||
* sent to the game server. In some cases there is no need to tell the game
|
||||
* server to unload the object (such as when handling a crash, for example).
|
||||
*/
|
||||
void PlanetProxyObject::unload(bool tellGameServer)
|
||||
{
|
||||
if (m_quadtreeNode)
|
||||
m_quadtreeNode->removeObject(this);
|
||||
|
||||
Scene::getInstance().removeObjectFromMap(m_objectId,tellGameServer);
|
||||
|
||||
if (tellGameServer)
|
||||
{
|
||||
PlanetServer::getInstance().unloadObject(m_objectId,m_authoritativeServer);
|
||||
}
|
||||
|
||||
removeServerStatistics();
|
||||
|
||||
if (ConfigPlanetServer::getEnableContentsChecking() && m_containedBy!=NetworkId::cms_invalid)
|
||||
{
|
||||
PlanetProxyObject *container = Scene::getInstance().findObjectByID(m_containedBy);
|
||||
if (container)
|
||||
container->removeContainedObject(m_objectId);
|
||||
else
|
||||
WARNING(true,("Unloading object %s in container %s, but the container could not be found.",m_objectId.getValueString().c_str(), m_containedBy.getValueString().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Output the object's position to a watcher.
|
||||
* @param conn the watcher
|
||||
* @param deleteObject if true, tell the watcher to delete this object.
|
||||
*/
|
||||
void PlanetProxyObject::outputStatus(WatcherConnection &conn, bool deleteObject) const
|
||||
{
|
||||
conn.addObjectUpdate(m_objectId, m_x, m_z, m_authoritativeServer, m_interestRadius, deleteObject, m_objectTypeTag, m_level, m_hibernating, m_templateCrc, m_aiActivity, m_creationType);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::outputStatusToAll(bool deleteObject) const
|
||||
{
|
||||
const PlanetServer::WatcherList &connections = PlanetServer::getInstance().getWatchers();
|
||||
for (PlanetServer::WatcherList::const_iterator i= connections.begin(); i!=connections.end(); ++i)
|
||||
{
|
||||
outputStatus(**i, deleteObject);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Update the GameServerData with statistics about this object.
|
||||
*/
|
||||
void PlanetProxyObject::addServerStatistics() const
|
||||
{
|
||||
GameServerData *data=PlanetServer::getInstance().getGameServerData(m_authoritativeServer);
|
||||
if (data)
|
||||
{
|
||||
data->adjustObjectCount(1);
|
||||
if (m_interestRadius!=0)
|
||||
{
|
||||
data->adjustInterestObjectCount(1);
|
||||
if (isCreature())
|
||||
data->adjustInterestCreatureObjectCount(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Remove statistics about this object from the GameServerData.
|
||||
* Should exactly undo addServerStatistics().
|
||||
*/
|
||||
void PlanetProxyObject::removeServerStatistics() const
|
||||
{
|
||||
GameServerData *data=PlanetServer::getInstance().getGameServerData(m_authoritativeServer);
|
||||
if (data)
|
||||
{
|
||||
data->adjustObjectCount(-1);
|
||||
if (m_interestRadius!=0)
|
||||
{
|
||||
data->adjustInterestObjectCount(-1);
|
||||
if (isCreature())
|
||||
data->adjustInterestCreatureObjectCount(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set up memory pool
|
||||
*/
|
||||
void PlanetProxyObject::install()
|
||||
{
|
||||
memoryBlockManager = new MemoryBlockManager("PlanetProxyObject::memoryBlockManager", true, sizeof(PlanetProxyObject), 0, 0, 0);
|
||||
ExitChain::add(&remove, "PlanetProxyObject::remove");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::remove()
|
||||
{
|
||||
WARNING_DEBUG_FATAL(!memoryBlockManager, ("PlanetProxyObject is not installed"));
|
||||
delete memoryBlockManager;
|
||||
memoryBlockManager = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void * PlanetProxyObject::operator new(size_t size)
|
||||
{
|
||||
UNREF(size);
|
||||
|
||||
WARNING_DEBUG_FATAL(!memoryBlockManager, ("PlanetProxyObject is not installed"));
|
||||
|
||||
// do not try to alloc a descendant class with this allocator
|
||||
WARNING_DEBUG_FATAL(size != sizeof(PlanetProxyObject), ("bad size"));
|
||||
|
||||
return memoryBlockManager->allocate();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::operator delete(void* pointer)
|
||||
{
|
||||
WARNING_DEBUG_FATAL(!memoryBlockManager, ("PlanetProxyObject is not installed"));
|
||||
memoryBlockManager->free(pointer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::sendAuthorityChange(uint32 currentAuthServer, uint32 newAuthServer, bool handlingCrash)
|
||||
{
|
||||
DEBUG_WARNING(!isAuthorityClean(), ("Object %s attempted to change authority before previous authority change was complete.",getObjectId().getValueString().c_str()));
|
||||
|
||||
SetAuthoritativeMessage const auth(getObjectId(), newAuthServer, false, handlingCrash, NetworkId::cms_invalid, Transform::identity, false);
|
||||
PlanetServer::getInstance().sendToGameServer(currentAuthServer, auth);
|
||||
m_authTransferTimeMs = Clock::timeMs();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::sendAddProxy(uint32 proxyServer)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Gameserver %lu needs a proxy of object %s",proxyServer,m_objectId.getValueString().c_str()));
|
||||
if (isAuthorityClean())
|
||||
{
|
||||
LoadObjectMessage const loadMsg(getObjectId(), proxyServer);
|
||||
PlanetServer::getInstance().sendToGameServer(m_authoritativeServer, loadMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadObjectMessage * const loadMsg = new LoadObjectMessage(getObjectId(), proxyServer);
|
||||
PlanetServer::getInstance().queueMessageForObject(getObjectId(), loadMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::sendRemoveProxy(uint32 proxyServer)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Gameserver %lu no longer needs a proxy of object %s",proxyServer,m_objectId.getValueString().c_str()));
|
||||
if (isAuthorityClean())
|
||||
{
|
||||
UnloadProxyMessage msg(getObjectId(),proxyServer);
|
||||
PlanetServer::getInstance().sendToGameServer(m_authoritativeServer, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnloadProxyMessage *msg = new UnloadProxyMessage(getObjectId(),proxyServer);
|
||||
PlanetServer::getInstance().queueMessageForObject(getObjectId(), msg);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when we receieve a message about the object from a game server.
|
||||
* Used to keep track of which server is sending us updates, and to send
|
||||
* any messages that were waiting for an authority change.
|
||||
*/
|
||||
void PlanetProxyObject::onReceivedMessageFromServer(uint32 server)
|
||||
{
|
||||
if (m_lastReportedServer != m_authoritativeServer && server == m_authoritativeServer)
|
||||
// we've received a message from the new authoritative server. Send queued messages:
|
||||
PlanetServer::getInstance().sendQueuedMessagesForObject(*this);
|
||||
|
||||
m_lastReportedServer = server;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get the list of servers that should have proxies of this object.
|
||||
*/
|
||||
void PlanetProxyObject::getServers(std::vector<uint32> &serverList) const
|
||||
{
|
||||
Node *effectiveNode;
|
||||
if (m_containedBy == NetworkId::cms_invalid)
|
||||
{
|
||||
effectiveNode = m_quadtreeNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlanetProxyObject *container=Scene::getInstance().findObjectByID(m_containedBy);
|
||||
WARNING_STRICT_FATAL(!container,("Object %s is in container %s, which couldn't be found",m_objectId.getValueString().c_str(),m_containedBy.getValueString().c_str()));
|
||||
if (container)
|
||||
effectiveNode = container->getNode();
|
||||
else
|
||||
effectiveNode = m_quadtreeNode;
|
||||
}
|
||||
|
||||
if (effectiveNode)
|
||||
effectiveNode->getServers(serverList);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given a list of servers that have a proxy and a list of servers
|
||||
* that should have a proxy, send messages to update the servers.
|
||||
* Note: O(n^2), assumes both lists are small, otherwise it would be better
|
||||
* to sort them first.
|
||||
*/
|
||||
void PlanetProxyObject::changeProxies(const std::vector<uint32> &oldServers, const std::vector<uint32> &newServers)
|
||||
{
|
||||
{
|
||||
for (std::vector<uint32>::const_iterator i=oldServers.begin(); i!=oldServers.end(); ++i)
|
||||
{
|
||||
if (*i != m_authoritativeServer)
|
||||
{
|
||||
bool removeNeeded = true;
|
||||
for (std::vector<uint32>::const_iterator j=newServers.begin(); j!=newServers.end(); ++j)
|
||||
{
|
||||
if (*i == *j)
|
||||
{
|
||||
removeNeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (removeNeeded)
|
||||
sendRemoveProxy(*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
for (std::vector<uint32>::const_iterator i=newServers.begin(); i!=newServers.end(); ++i)
|
||||
{
|
||||
if (*i != m_authoritativeServer)
|
||||
{
|
||||
bool addNeeded = true;
|
||||
for (std::vector<uint32>::const_iterator j=oldServers.begin(); j!=oldServers.end(); ++j)
|
||||
{
|
||||
if (*i == *j)
|
||||
{
|
||||
addNeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addNeeded)
|
||||
sendAddProxy(*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check whether we are on a server that's acceptable for where we are.
|
||||
*/
|
||||
bool PlanetProxyObject::isAuthorityOk() const
|
||||
{
|
||||
if (m_authoritativeServer == m_quadtreeNode->getPreferredServer())
|
||||
return true;
|
||||
if (m_quadtreeNode->isBorderNode() && m_quadtreeNode->isServerSubscribed(m_authoritativeServer))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check for whether a desired server would be OK for where we are.
|
||||
* The server is OK if it is the preferred server. If the object is
|
||||
* a creature, the server is also OK if the node is a border node and
|
||||
* the server has a subscription to the node. Non-creatures must always
|
||||
* be on the preferred server.
|
||||
*/
|
||||
bool PlanetProxyObject::wouldAuthorityBeOk(uint32 possibleServer) const
|
||||
{
|
||||
if (possibleServer == m_quadtreeNode->getPreferredServer())
|
||||
return true;
|
||||
if (isCreature() && m_quadtreeNode->isBorderNode() && m_quadtreeNode->isServerSubscribed(possibleServer))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::addContainedObject(const NetworkId &theObject)
|
||||
{
|
||||
if (!m_contents)
|
||||
{
|
||||
m_contents = new std::vector<NetworkId>;
|
||||
}
|
||||
for (std::vector<NetworkId>::const_iterator i=m_contents->begin(); i!=m_contents->end(); ++i)
|
||||
{
|
||||
if (*i==theObject)
|
||||
WARNING(true,("Object %s was placed in container %s twice.", theObject.getValueString().c_str(), m_objectId.getValueString().c_str()));
|
||||
}
|
||||
m_contents->push_back(theObject);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PlanetProxyObject::removeContainedObject(const NetworkId &theObject)
|
||||
{
|
||||
if (!m_contents)
|
||||
{
|
||||
WARNING(true,("Attempted to remove object %s from object %s, but that object has no contents.", theObject.getValueString().c_str(), m_objectId.getValueString().c_str()));
|
||||
return;
|
||||
}
|
||||
std::vector<NetworkId>::iterator newEnd=std::remove(m_contents->begin(), m_contents->end(), theObject);
|
||||
if (newEnd==m_contents->end())
|
||||
{
|
||||
WARNING(true,("Attempted to remove object %s from object %s, but it was not in the container.", theObject.getValueString().c_str(), m_objectId.getValueString().c_str()));
|
||||
return;
|
||||
}
|
||||
m_contents->erase(newEnd, m_contents->end());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper function to update the contents tracking lists, in order to
|
||||
* debug various authority problems
|
||||
*/
|
||||
void PlanetProxyObject::updateContentsTracking(const NetworkId &newContainedBy)
|
||||
{
|
||||
if (m_containedBy!=NetworkId::cms_invalid)
|
||||
{
|
||||
PlanetProxyObject *container = Scene::getInstance().findObjectByID(m_containedBy);
|
||||
if (container)
|
||||
container->removeContainedObject(m_objectId);
|
||||
else
|
||||
WARNING(true,("Removing object %s from container %s, but the container could not be found.",m_objectId.getValueString().c_str(), m_containedBy.getValueString().c_str()));
|
||||
}
|
||||
|
||||
if (newContainedBy!=NetworkId::cms_invalid)
|
||||
{
|
||||
PlanetProxyObject *container = Scene::getInstance().findObjectByID(newContainedBy);
|
||||
if (container)
|
||||
container->addContainedObject(m_objectId);
|
||||
else
|
||||
WARNING(true,("Adding object %s to container %s, but the container could not be found.",m_objectId.getValueString().c_str(), newContainedBy.getValueString().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool PlanetProxyObject::isCreature() const
|
||||
{
|
||||
return m_objectTypeTag==TAG(C,R,E,O);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,237 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PlanetProxyObject.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PlanetProxyObject_H
|
||||
#define INCLUDED_PlanetProxyObject_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
#include "sharedMath/Vector.h"
|
||||
|
||||
class Node;
|
||||
class MemoryBlockManager;
|
||||
class WatcherConnection;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* Lightweight proxy of an object, containing just the data the planet server
|
||||
* cares about.
|
||||
*
|
||||
* Coordinates are made into integers because none of the Planet Server's
|
||||
* algorithms care about sub-meter distances.
|
||||
*/
|
||||
class PlanetProxyObject
|
||||
{
|
||||
public:
|
||||
explicit PlanetProxyObject (const NetworkId &objectId);
|
||||
~PlanetProxyObject ();
|
||||
|
||||
public:
|
||||
void addServerStatistics () const;
|
||||
void changeAuthority (uint32 newGameServer, bool handlingCrash, bool forcedByGame);
|
||||
void changeAuthorityAndSubscriptions(uint32 newGameServer);
|
||||
void onReceivedMessageFromServer (uint32 server);
|
||||
void outputStatus (WatcherConnection &conn, bool deleteObject) const;
|
||||
void outputStatusToAll (bool deleteObject) const;
|
||||
void removeServerStatistics () const;
|
||||
void restoreAuthority (uint32 gameServer);
|
||||
void sendAddProxy (uint32 proxyServer);
|
||||
void sendRemoveProxy (uint32 proxyServer);
|
||||
void setNode (Node *node);
|
||||
void subscribeSurroundingNodes ();
|
||||
void unload (bool tellGameServer);
|
||||
void unsubscribeSurroundingNodes (bool clearZeroSubscriptions);
|
||||
void update (int x, int y, int z, NetworkId containedBy, uint32 authoritativeServer, int interestRadius, int objectTypeTag, int level, bool hibernating, uint32 templateCrc, int aiActivity, int creationType);
|
||||
|
||||
public:
|
||||
int getX () const;
|
||||
int getY () const;
|
||||
int getZ () const;
|
||||
uint32 getAuthoritativeServer () const;
|
||||
int getInterestRadius () const;
|
||||
bool isContained () const;
|
||||
bool isAuthorityClean () const;
|
||||
const NetworkId & getObjectId () const;
|
||||
const NetworkId & getContainedBy () const;
|
||||
Node * getNode () const;
|
||||
bool wouldAuthorityBeOk (uint32 possibleServer) const;
|
||||
bool isCreature () const;
|
||||
int getLevel () const;
|
||||
bool getHibernating () const;
|
||||
uint32 getTemplateCrc () const;
|
||||
int getAiActivity () const;
|
||||
int getCreationType () const;
|
||||
|
||||
public:
|
||||
static void * operator new (size_t size);
|
||||
static void operator delete (void* pointer);
|
||||
static void install ();
|
||||
static void remove ();
|
||||
|
||||
private:
|
||||
void getServers (std::vector<uint32> &serverList) const;
|
||||
void changeProxies (const std::vector<uint32> &oldServers, const std::vector<uint32> &newServers);
|
||||
void sendAuthorityChange (uint32 currentAuthServer, uint32 newAuthServer, bool handlingCrash);
|
||||
bool isAuthorityOk () const;
|
||||
void addContainedObject (const NetworkId & theObject);
|
||||
void removeContainedObject (const NetworkId & theObject);
|
||||
void updateContentsTracking (const NetworkId & newContainedBy);
|
||||
|
||||
private:
|
||||
typedef stdvector<std::pair<uint32, GameNetworkMessage*> > MessageListType;
|
||||
|
||||
private:
|
||||
const NetworkId m_objectId;
|
||||
NetworkId m_containedBy;
|
||||
int m_x;
|
||||
int m_y;
|
||||
int m_z;
|
||||
uint32 m_authoritativeServer;
|
||||
uint32 m_lastReportedServer;
|
||||
int m_interestRadius;
|
||||
int m_objectTypeTag;
|
||||
Node * m_quadtreeNode;
|
||||
unsigned long m_authTransferTimeMs;
|
||||
stdvector<NetworkId>::fwd * m_contents;
|
||||
int m_level;
|
||||
bool m_hibernating;
|
||||
uint32 m_templateCrc;
|
||||
int m_aiActivity;
|
||||
int m_creationType;
|
||||
|
||||
static MemoryBlockManager* memoryBlockManager;
|
||||
|
||||
private:
|
||||
PlanetProxyObject(); //disable
|
||||
PlanetProxyObject &operator=(const PlanetProxyObject&); //disable
|
||||
PlanetProxyObject(const PlanetProxyObject&); //disable
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline const NetworkId &PlanetProxyObject::getObjectId() const
|
||||
{
|
||||
return m_objectId;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetProxyObject::getX() const
|
||||
{
|
||||
return m_x;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetProxyObject::getY() const
|
||||
{
|
||||
return m_y;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetProxyObject::getZ() const
|
||||
{
|
||||
return m_z;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetProxyObject::getLevel() const
|
||||
{
|
||||
return m_level;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool PlanetProxyObject::getHibernating() const
|
||||
{
|
||||
return m_hibernating;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline uint32 PlanetProxyObject::getTemplateCrc() const
|
||||
{
|
||||
return m_templateCrc;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetProxyObject::getAiActivity() const
|
||||
{
|
||||
return m_aiActivity;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetProxyObject::getCreationType() const
|
||||
{
|
||||
return m_creationType;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline uint32 PlanetProxyObject::getAuthoritativeServer() const
|
||||
{
|
||||
return m_authoritativeServer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetProxyObject::getInterestRadius() const
|
||||
{
|
||||
return m_interestRadius;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void PlanetProxyObject::setNode(Node *node)
|
||||
{
|
||||
m_quadtreeNode=node;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if the object's authority is "clean", i.e. the Game Servers
|
||||
* think it is authoritative on the same server the Planet Server does.
|
||||
* This returns false when we've changed the object's authority until the
|
||||
* newly authoritative server sends us an update, at which point we know
|
||||
* that it thinks it is authoritative.
|
||||
*/
|
||||
inline bool PlanetProxyObject::isAuthorityClean() const
|
||||
{
|
||||
return m_lastReportedServer == m_authoritativeServer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline Node *PlanetProxyObject::getNode() const
|
||||
{
|
||||
return m_quadtreeNode;
|
||||
} //lint !e1763
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const NetworkId &PlanetProxyObject::getContainedBy() const
|
||||
{
|
||||
return m_containedBy;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool PlanetProxyObject::isContained() const
|
||||
{
|
||||
return (m_containedBy != NetworkId::cms_invalid);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,190 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PlanetServer.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PlanetServer_H
|
||||
#define INCLUDED_PlanetServer_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "sharedMessageDispatch/Receiver.h"
|
||||
#include "Singleton/Singleton.h"
|
||||
|
||||
#include "PreloadManager.h"
|
||||
#include "TaskConnection.h"
|
||||
|
||||
class CentralServerConnection;
|
||||
class ChunkCompleteMessage;
|
||||
class GameNetworkMessage;
|
||||
class GameServerConnection;
|
||||
class GameServerData;
|
||||
class PlanetProxyObject;
|
||||
class PlanetServerMetricsData;
|
||||
class PreloadListData;
|
||||
class RequestGameServerForLoginMessage;
|
||||
class RequestSceneTransfer;
|
||||
class Service;
|
||||
class Vector;
|
||||
class WatcherConnection;
|
||||
struct CharacterFindInfo;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class PlanetServer : public Singleton<PlanetServer>, public MessageDispatch::Receiver
|
||||
{
|
||||
public:
|
||||
typedef std::vector<WatcherConnection*> WatcherList;
|
||||
typedef unsigned int GameServerSpawnDelaySeconds;
|
||||
|
||||
public:
|
||||
PlanetServer();
|
||||
~PlanetServer();
|
||||
|
||||
static void run(void);
|
||||
void mainLoop(void);
|
||||
void setDone(char const *reasonfmt, ...);
|
||||
|
||||
const unsigned short getGameServicePort() const;
|
||||
const Service * getGameService() const;
|
||||
int getNumberOfGameServers() const;
|
||||
int getObjectCountForServer(uint32 serverId) const;
|
||||
int getInterestObjectCountForServer(uint32 serverId) const;
|
||||
int getInterestCreatureObjectCountForServer(uint32 serverId) const;
|
||||
void getObjectCountsForAllServers(stdmap<uint32, GameServerData>::fwd &counts) const;
|
||||
virtual void receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message);
|
||||
void sendToCentral(const GameNetworkMessage & message, const bool reliable);
|
||||
void sendToGameServer(const uint32 processId, const GameNetworkMessage & message);
|
||||
void setTaskManager(TaskConnection*);
|
||||
void startGameServer(const std::set<PreloadServerId> & preloadServerId, GameServerSpawnDelaySeconds spawnDelay);
|
||||
GameServerData * getGameServerData(uint32 serverId) const;
|
||||
void preloadCompleteOnAllServers();
|
||||
int getCurrentServerInterestObjectLimit() const;
|
||||
void queueMessageForObject(const NetworkId &networkId, GameNetworkMessage *theMessage);
|
||||
void sendQueuedMessagesForObject(const PlanetProxyObject &theObject);
|
||||
void unloadObject (const NetworkId &object, uint32 authServer);
|
||||
void sendChunkRequest(uint32 server, int x, int z);
|
||||
void sendPreloadRequestCompleteMessage(uint32 realServerId, uint32 preloadServerId);
|
||||
void requestAndWaitForSave();
|
||||
void onCentralConnected(CentralServerConnection *connection);
|
||||
|
||||
const WatcherList & getWatchers() const;
|
||||
bool isWatcherPresent() const;
|
||||
bool isInTutorialMode() const;
|
||||
bool getEnablePreload() const;
|
||||
bool isInSpaceMode() const;
|
||||
|
||||
GameServerConnection *getGameServerConnection(uint32 serverId);
|
||||
ServerConnection *getCentralServerConnection();
|
||||
|
||||
private:
|
||||
typedef std::map<uint32, GameServerData*> GameServerMapType;
|
||||
|
||||
private:
|
||||
void handleRequestGameServerForLoginMessage (const RequestGameServerForLoginMessage *&msg);
|
||||
void loadCharacterForLogin(NetworkId const &characterId, Vector const &coords, unsigned long gameServerId);
|
||||
void handleRequestSceneTransfer(const RequestSceneTransfer *& msg);
|
||||
void handleChunkComplete(const ChunkCompleteMessage &msg, const GameServerConnection *conn);
|
||||
void flushWaitingMessages();
|
||||
void findOrLoadCharacter(NetworkId const &characterId, NetworkId const &containerId, Vector const &coords, uint32 stationId, bool forCtsSourceCharacter);
|
||||
void handleFindAuthObjectResponse(NetworkId const &characterId, unsigned int sequence, bool found, uint32 gameServerId);
|
||||
void forceLoadCharacter(NetworkId const &characterId, NetworkId const &containerId, Vector const &coords, uint32 stationId, bool forCtsSourceCharacter);
|
||||
void handleDatabaseSaveComplete(int newSaveCounter);
|
||||
|
||||
private:
|
||||
CentralServerConnection * m_pendingCentralServerConnection;
|
||||
CentralServerConnection * m_centralServerConnection;
|
||||
Service * m_gameService;
|
||||
Service * m_watcherService;
|
||||
GameServerMapType m_gameServers;
|
||||
TaskConnection * m_taskConnection;
|
||||
bool m_done;
|
||||
int m_roundRobinGameServer;
|
||||
stdmap<PreloadServerId, GameServerSpawnDelaySeconds>::fwd * m_pendingServerStarts; // number of game servers to start when central & task manager are ready
|
||||
stdmap<int, std::pair<std::string, time_t> >::fwd * m_startingGameServers; // number of game servers we've started that haven't connected to us yet
|
||||
uint32 m_firstGameServer;
|
||||
bool m_tutorialMode;
|
||||
bool m_spaceMode;
|
||||
std::set<GameServerConnection *> m_pendingGameServerDisconnects;
|
||||
|
||||
std::vector<const GameNetworkMessage *> m_messagesWaitingForGameServer;
|
||||
PlanetServerMetricsData* m_metricsData;
|
||||
TaskConnection* m_taskManagerConnection;
|
||||
stdlist<const RequestSceneTransfer *>::fwd *m_sceneTransferChunkLoads;
|
||||
stdmap<NetworkId, uint32>::fwd *m_pendingCharacterSaves;
|
||||
|
||||
WatcherList m_watchers;
|
||||
bool m_watcherIsPresent;
|
||||
|
||||
typedef std::map<NetworkId, std::vector<GameNetworkMessage*> > QueuedMessagesType;
|
||||
QueuedMessagesType m_queuedMessages;
|
||||
stdmap<NetworkId, CharacterFindInfo>::fwd *m_characterFindMap;
|
||||
unsigned int m_characterFindSequence;
|
||||
int m_waitForSaveCounter;
|
||||
int m_lastSaveCounter;
|
||||
|
||||
private:
|
||||
//disable:
|
||||
PlanetServer(const PlanetServer&);
|
||||
PlanetServer &operator=(const PlanetServer&);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int PlanetServer::getNumberOfGameServers() const
|
||||
{
|
||||
return static_cast<int>(m_gameServers.size());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void PlanetServer::onCentralConnected(CentralServerConnection *connection)
|
||||
{
|
||||
m_pendingCentralServerConnection=NULL;
|
||||
m_centralServerConnection=connection;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void PlanetServer::setTaskManager(TaskConnection* con)
|
||||
{
|
||||
m_taskManagerConnection = con;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool PlanetServer::isWatcherPresent() const
|
||||
{
|
||||
return m_watcherIsPresent;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const PlanetServer::WatcherList & PlanetServer::getWatchers() const
|
||||
{
|
||||
return m_watchers;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool PlanetServer::isInTutorialMode() const
|
||||
{
|
||||
return m_tutorialMode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool PlanetServer::isInSpaceMode() const
|
||||
{
|
||||
return m_spaceMode;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif //_CentralServer_H
|
||||
@@ -0,0 +1,102 @@
|
||||
//PlanetServerMetricsData.cpp
|
||||
//Copyright 2002 Sony Online Entertainment
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "PlanetServerMetricsData.h"
|
||||
|
||||
#include "PlanetServer.h"
|
||||
#include "ConfigPlanetServer.h"
|
||||
#ifndef WIN32
|
||||
#include "MonAPI2/MonitorData.h"
|
||||
#endif
|
||||
#include "serverNetworkMessages/MetricsDataMessage.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedNetworkMessages/GameNetworkMessage.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
PlanetServerMetricsData::PlanetServerMetricsData() :
|
||||
MetricsData(),
|
||||
m_numGameServers(0),
|
||||
m_watcherPort(0),
|
||||
m_gameServerLoadTime()
|
||||
{
|
||||
MetricsPair p;
|
||||
|
||||
ADD_METRICS_DATA(numGameServers, 0, false); //lint !e713 loss of precision, couldn't figure out a cast that made Lint happy
|
||||
ADD_METRICS_DATA(watcherPort, ConfigPlanetServer::getWatcherServicePort(), false);
|
||||
|
||||
std::string label = NetworkHandler::getHostName();
|
||||
|
||||
for (std::string::iterator i = label.begin(); i != label.end(); ++i)
|
||||
{
|
||||
if (*i == '.')
|
||||
{
|
||||
*i = '+';
|
||||
}
|
||||
}
|
||||
|
||||
label += ":";
|
||||
char tmp[256];
|
||||
label += _itoa(Os::getProcessId(), tmp, 10);
|
||||
|
||||
m_data[m_watcherPort].m_description = label;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
PlanetServerMetricsData::~PlanetServerMetricsData()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void PlanetServerMetricsData::updateData()
|
||||
{
|
||||
MetricsData::updateData();
|
||||
m_data[m_numGameServers].m_value = PlanetServer::getInstance().getNumberOfGameServers(); //lint !e732 !e713
|
||||
|
||||
#ifndef WIN32
|
||||
// if all game servers for planet has not finished loading,
|
||||
// set value to "loading" to cause the planet node to appear
|
||||
// yellow to help figure out which planet is still loading
|
||||
if (!PreloadManager::getInstance().isPreloadComplete())
|
||||
m_data[m_watcherPort].m_value = STATUS_LOADING;
|
||||
else
|
||||
#endif
|
||||
m_data[m_watcherPort].m_value = ConfigPlanetServer::getWatcherServicePort();
|
||||
|
||||
// report load time of each game server
|
||||
PreloadManager::ServerMapType const * serverMap = PreloadManager::getInstance().getServerMap();
|
||||
if (serverMap && !serverMap->empty())
|
||||
{
|
||||
std::map<uint32, unsigned long>::const_iterator iter2;
|
||||
MetricsPair p;
|
||||
char buffer[128];
|
||||
for (PreloadManager::ServerMapType::const_iterator iter = serverMap->begin(); iter != serverMap->end(); ++iter)
|
||||
{
|
||||
iter2 = m_gameServerLoadTime.find(iter->first);
|
||||
if (iter2 == m_gameServerLoadTime.end())
|
||||
{
|
||||
// create a node to report load time for this game server
|
||||
snprintf(buffer, sizeof(buffer)-1, "loadTime_%s_%lu", ConfigPlanetServer::getSceneID(), iter->first);
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
|
||||
p.m_label = buffer;
|
||||
p.m_value = std::max(static_cast<int>(0), static_cast<int>((iter->second.m_loadTime != -1) ? iter->second.m_loadTime : (time(0) - iter->second.m_timeLoadStarted)));
|
||||
p.m_description = "seconds";
|
||||
p.m_persistData = true;
|
||||
p.m_summary = false;
|
||||
m_gameServerLoadTime[iter->first] = m_data.size();
|
||||
m_data.push_back(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data[iter2->second].m_value = std::max(static_cast<int>(0), static_cast<int>((iter->second.m_loadTime != -1) ? iter->second.m_loadTime : (time(0) - iter->second.m_timeLoadStarted)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -0,0 +1,38 @@
|
||||
//PlanetServerMetricsData.h
|
||||
//Copyright 2002 Sony Online Entertainment
|
||||
|
||||
|
||||
#ifndef _PlanetServerMetricsData_H
|
||||
#define _PlanetServerMetricsData_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "serverMetrics/MetricsData.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class PlanetServerMetricsData : public MetricsData
|
||||
{
|
||||
public:
|
||||
PlanetServerMetricsData();
|
||||
~PlanetServerMetricsData();
|
||||
|
||||
virtual void updateData();
|
||||
|
||||
private:
|
||||
unsigned long m_numGameServers;
|
||||
unsigned long m_watcherPort;
|
||||
|
||||
// used for reporting load time of each game server
|
||||
stdmap<uint32, unsigned long>::fwd m_gameServerLoadTime;
|
||||
|
||||
private:
|
||||
|
||||
// Disabled.
|
||||
PlanetServerMetricsData(const PlanetServerMetricsData&);
|
||||
PlanetServerMetricsData &operator =(const PlanetServerMetricsData&);
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#endif
|
||||
@@ -0,0 +1,492 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PreloadManager.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "PreloadManager.h"
|
||||
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "GameServerData.h"
|
||||
#include "PlanetProxyObject.h"
|
||||
#include "QuadtreeNode.h"
|
||||
#include "Scene.h"
|
||||
#include "serverUtility/PopulationList.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedUtility/DataTable.h"
|
||||
#include "sharedUtility/DataTableManager.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
PreloadManager::PreloadManager() :
|
||||
Singleton2<PreloadManager>(),
|
||||
m_serverMap(new ServerMapType),
|
||||
m_preloadList(new PreloadListType),
|
||||
m_serversWaiting(new ServersWaitingType),
|
||||
m_listReceived(false)
|
||||
{
|
||||
ExitChain::add(&remove, "PreloadManager::remove");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PreloadManager::~PreloadManager()
|
||||
{
|
||||
delete m_serverMap;
|
||||
delete m_preloadList;
|
||||
delete m_serversWaiting;
|
||||
|
||||
m_serverMap=0;
|
||||
m_preloadList=0;
|
||||
m_serversWaiting=0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set up the preload list, based on the scene and config options.
|
||||
*/
|
||||
void PreloadManager::handlePreloadList()
|
||||
{
|
||||
m_listReceived=true;
|
||||
|
||||
WARNING(ConfigPlanetServer::getLoadWholePlanet() && ConfigPlanetServer::getLoadWholePlanetMultiserver(),("You have specified both loadWholePlanet and loadWholePlanetMultiserver. LoadWholePlanet (single-server) will take precedence."));
|
||||
|
||||
if (ConfigPlanetServer::getLoadWholePlanet() || PlanetServer::getInstance().isInSpaceMode() || !PlanetServer::getInstance().getEnablePreload())
|
||||
{
|
||||
// Set up a single server to handle the whole planet
|
||||
PreloadListData fakeBeacon;
|
||||
fakeBeacon.m_topLeftChunkX = 0;
|
||||
fakeBeacon.m_topLeftChunkZ = 0;
|
||||
fakeBeacon.m_bottomRightChunkX = 100;
|
||||
fakeBeacon.m_bottomRightChunkZ = 100;
|
||||
fakeBeacon.m_cityServerId = 1;
|
||||
fakeBeacon.m_wildernessServerId = 1;
|
||||
|
||||
m_preloadList->clear();
|
||||
m_preloadList->push_back(fakeBeacon);
|
||||
|
||||
m_serversWaiting->insert(1);
|
||||
PreloadServerInformation & psi = (*m_serverMap)[1];
|
||||
psi.m_actualServerId = 0;
|
||||
psi.m_timeLoadStarted = time(0);
|
||||
psi.m_loadTime = -1;
|
||||
}
|
||||
// WTF is this ... the tutorial planet bypasses the preload multiserver setting in favor of this pie slice algorithm
|
||||
// We should not need this anymore with the NPE tutorial
|
||||
// NPE will use the preload tables for multiserver and the 'NewbieTutorial' manager for placing the tutotial instances
|
||||
/*
|
||||
else if(PlanetServer::getInstance().isInTutorialMode())
|
||||
{
|
||||
m_preloadList->clear();
|
||||
|
||||
int n=ConfigPlanetServer::getNumTutorialServers();
|
||||
if ((ConfigPlanetServer::getMaxGameServers() != 0) && (n > ConfigPlanetServer::getMaxGameServers()))
|
||||
n=ConfigPlanetServer::getMaxGameServers();
|
||||
for (int i=0 ; i<n; ++i)
|
||||
{
|
||||
float angle = PI_TIMES_2 * (static_cast<float>(i)/static_cast<float>(n));
|
||||
|
||||
// Make a circle of load beacons. The effect will be to divide the map into wedges
|
||||
PreloadListData fakeBeacon;
|
||||
fakeBeacon.m_topLeftChunkX = Node::roundToNode(static_cast<int>(cos(angle) * 1000.0f));
|
||||
fakeBeacon.m_topLeftChunkZ = Node::roundToNode(static_cast<int>(sin(angle) * 1000.0f));
|
||||
fakeBeacon.m_bottomRightChunkX = fakeBeacon.m_topLeftChunkX + Node::getNodeSize();
|
||||
fakeBeacon.m_bottomRightChunkZ = fakeBeacon.m_topLeftChunkZ + Node::getNodeSize();
|
||||
fakeBeacon.m_cityServerId = i+1;
|
||||
fakeBeacon.m_wildernessServerId = i+1;
|
||||
|
||||
DEBUG_REPORT_LOG(true,("Loadbeacon at %i, %i\n",fakeBeacon.m_topLeftChunkX, fakeBeacon.m_topLeftChunkZ));
|
||||
|
||||
m_preloadList->push_back(fakeBeacon);
|
||||
PreloadServerInformation & psi = (*m_serverMap)[i+1];
|
||||
psi.m_actualServerId = 0;
|
||||
psi.m_timeLoadStarted = time(0);
|
||||
psi.m_loadTime = -1;
|
||||
m_serversWaiting->insert(i+1);
|
||||
}
|
||||
}*/
|
||||
else
|
||||
{
|
||||
if (PlanetServer::getInstance().getEnablePreload())
|
||||
{
|
||||
DataTable * data = DataTableManager::getTable(ConfigPlanetServer::getPreloadDataTableName(),true);
|
||||
FATAL(data==NULL,("Could not find data table %s, needed for preload",ConfigPlanetServer::getPreloadDataTableName()));
|
||||
|
||||
int numRows = data->getNumRows();
|
||||
for (int row=0; row<numRows; ++row)
|
||||
{
|
||||
if (data->getStringValue("Scene",row)==Scene::getInstance().getSceneId())
|
||||
{
|
||||
PreloadListData item;
|
||||
item.m_topLeftChunkX=data->getIntValue("Top Left Chunk X",row);
|
||||
item.m_topLeftChunkZ=data->getIntValue("Top Left Chunk Z",row);
|
||||
item.m_bottomRightChunkX=data->getIntValue("Bottom Right Chunk X",row);
|
||||
item.m_bottomRightChunkZ=data->getIntValue("Bottom Right Chunk Z",row);
|
||||
item.m_cityServerId=data->getIntValue("City Server Id",row);
|
||||
item.m_wildernessServerId=data->getIntValue("Wilderness Server Id",row);
|
||||
|
||||
if (ConfigPlanetServer::getMaxGameServers() != 0)
|
||||
{
|
||||
// Reduce the total number of game servers
|
||||
item.m_cityServerId = ((item.m_cityServerId - 1) % ConfigPlanetServer::getMaxGameServers()) + 1;
|
||||
|
||||
if (item.m_wildernessServerId != 0)
|
||||
item.m_wildernessServerId = ((item.m_wildernessServerId - 1) % ConfigPlanetServer::getMaxGameServers()) + 1;
|
||||
}
|
||||
|
||||
m_preloadList->push_back(item);
|
||||
|
||||
ServerMapType::iterator mapIter = m_serverMap->find(item.m_cityServerId);
|
||||
if (mapIter == m_serverMap->end())
|
||||
{
|
||||
PreloadServerInformation & psi = (*m_serverMap)[item.m_cityServerId];
|
||||
psi.m_actualServerId = 0;
|
||||
psi.m_timeLoadStarted = time(0);
|
||||
psi.m_loadTime = -1;
|
||||
m_serversWaiting->insert(item.m_cityServerId);
|
||||
}
|
||||
|
||||
if (item.m_wildernessServerId != 0)
|
||||
{
|
||||
mapIter = m_serverMap->find(item.m_wildernessServerId);
|
||||
if (mapIter == m_serverMap->end())
|
||||
{
|
||||
PreloadServerInformation & psi = (*m_serverMap)[item.m_wildernessServerId];
|
||||
psi.m_actualServerId = 0;
|
||||
psi.m_timeLoadStarted = time(0);
|
||||
psi.m_loadTime = -1;
|
||||
m_serversWaiting->insert(item.m_wildernessServerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FATAL(PlanetServer::getInstance().getEnablePreload() && m_serversWaiting->size()==0,("Planet server started for scene %s, which was not listed in the preload data table",
|
||||
Scene::getInstance().getSceneId().c_str()));
|
||||
|
||||
std::set<PreloadServerId> startGameServerList;
|
||||
if (m_serversWaiting->size() < 1)
|
||||
{
|
||||
IGNORE_RETURN(startGameServerList.insert(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ServersWaitingType::const_iterator i = m_serversWaiting->begin(); i != m_serversWaiting->end(); ++i)
|
||||
IGNORE_RETURN(startGameServerList.insert(*i));
|
||||
}
|
||||
|
||||
Scene::getInstance().assignPreloadsToNodes();
|
||||
PlanetServer::getInstance().startGameServer(startGameServerList, 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when a game server reports that it is ready to receive objects
|
||||
*/
|
||||
bool PreloadManager::onGameServerReady(uint32 serverId, PreloadServerId preloadServerId)
|
||||
{
|
||||
bool result = true;
|
||||
bool noPreload = true;
|
||||
|
||||
// attempt to assign the game server the specified role in the preload list, if possible
|
||||
bool assigned = false;
|
||||
|
||||
for (ServerMapType::iterator i=m_serverMap->begin(); i!=m_serverMap->end(); ++i)
|
||||
{
|
||||
if (i->first == preloadServerId)
|
||||
{
|
||||
if (i->second.m_actualServerId == 0)
|
||||
{
|
||||
i->second.m_actualServerId = serverId;
|
||||
sendPreloadsToGameServer(serverId, i->first);
|
||||
noPreload = false;
|
||||
assigned = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!assigned)
|
||||
{
|
||||
for (ServerMapType::iterator j=m_serverMap->begin(); j!=m_serverMap->end(); ++j)
|
||||
{
|
||||
if (j->second.m_actualServerId == 0)
|
||||
{
|
||||
// assign the new game server to this role in the preload list
|
||||
j->second.m_actualServerId = serverId;
|
||||
sendPreloadsToGameServer(serverId, j->first);
|
||||
noPreload = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (noPreload)
|
||||
{
|
||||
// this server has nothing to preload, so advance its status right away
|
||||
GameServerData *data = PlanetServer::getInstance().getGameServerData(serverId);
|
||||
if(! PlanetServer::getInstance().getEnablePreload())
|
||||
{
|
||||
if (data)
|
||||
data->preloadComplete();
|
||||
|
||||
// send PreloadRequestCompleteMessage, because things on the game server wait for it
|
||||
PlanetServer::getInstance().sendPreloadRequestCompleteMessage(serverId, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(! PlanetServer::getInstance().isInTutorialMode())
|
||||
{
|
||||
result = false; // disconnect the game server, it's extraneous.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the preload list is empty, preloading is finished as soon as at least 1 game server is up
|
||||
if (m_serverMap->empty())
|
||||
{
|
||||
DEBUG_REPORT_LOG(ConfigPlanetServer::getLogPreloading(),("Preloading is finished on %s because there was nothing to preload.\n",Scene::getInstance().getSceneId().c_str()));
|
||||
PlanetServer::getInstance().preloadCompleteOnAllServers();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PreloadManager::sendPreloadsToGameServer(uint32 realServerId, PreloadServerId preloadServerId) const
|
||||
{
|
||||
if (PlanetServer::getInstance().getEnablePreload())
|
||||
Scene::getInstance().loadAllNodesForServer(realServerId, preloadServerId);
|
||||
|
||||
PlanetServer::getInstance().sendPreloadRequestCompleteMessage(realServerId, preloadServerId);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when a game server drops connection. Remove it from the preload assignments.
|
||||
*/
|
||||
void PreloadManager::removeGameServer(uint32 serverId)
|
||||
{
|
||||
for (ServerMapType::iterator i=m_serverMap->begin(); i!=m_serverMap->end(); ++i)
|
||||
{
|
||||
if (i->second.m_actualServerId == serverId)
|
||||
{
|
||||
i->second.m_actualServerId = 0;
|
||||
i->second.m_timeLoadStarted = time(0);
|
||||
i->second.m_loadTime = -1;
|
||||
m_serversWaiting->insert(i->first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when a game server indicates it has all the preload objects
|
||||
*/
|
||||
void PreloadManager::preloadCompleteOnServer(uint32 serverId)
|
||||
{
|
||||
DEBUG_REPORT_LOG(ConfigPlanetServer::getLogPreloading(),("Preload is finished on server %lu (planet %s)\n",serverId, Scene::getInstance().getSceneId().c_str()));
|
||||
|
||||
PreloadServerId const preloadId = getPreloadServerId(serverId);
|
||||
m_serversWaiting->erase(preloadId);
|
||||
|
||||
// mark how long it took the server to load
|
||||
ServerMapType::iterator i = m_serverMap->find(preloadId);
|
||||
if ((i != m_serverMap->end()) && (i->second.m_loadTime == -1))
|
||||
i->second.m_loadTime = std::max(static_cast<int>(0), static_cast<int>(time(0) - i->second.m_timeLoadStarted));
|
||||
|
||||
if (isPreloadComplete())
|
||||
{
|
||||
if (ConfigPlanetServer::getEnableStartupCreateProxies())
|
||||
{
|
||||
Scene::getInstance().createAllProxies();
|
||||
}
|
||||
|
||||
DEBUG_REPORT_LOG(ConfigPlanetServer::getLogPreloading(),("Preloading is finished on all servers for %s.\n", Scene::getInstance().getSceneId().c_str()));
|
||||
PlanetServer::getInstance().preloadCompleteOnAllServers();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Finds the preload game server for the specified spot.
|
||||
*/
|
||||
PreloadServerId PreloadManager::getPreloadGameServer(int x, int z)
|
||||
{
|
||||
PreloadServerId bestSoFar = 0;
|
||||
int bestDistance = 0;
|
||||
for (std::vector<PreloadListData>::const_iterator item=m_preloadList->begin(); item!=m_preloadList->end(); ++item)
|
||||
{
|
||||
if (item->m_cityServerId != 0)
|
||||
{
|
||||
int minX=Node::roundToNode(item->m_topLeftChunkX);
|
||||
int minZ=Node::roundToNode(item->m_topLeftChunkZ);
|
||||
int maxX=Node::roundToNode(item->m_bottomRightChunkX);
|
||||
int maxZ=Node::roundToNode(item->m_bottomRightChunkZ);
|
||||
|
||||
if ((x >= minX) && (x < maxX) && (z >= minZ) && (z < maxZ))
|
||||
return item->m_cityServerId;
|
||||
}
|
||||
if (item->m_wildernessServerId != 0)
|
||||
{
|
||||
// Pretend there is a "beacon" in the middle of the preload area
|
||||
int beaconX=(item->m_topLeftChunkX + item->m_bottomRightChunkX) / 2;
|
||||
int beaconZ=(item->m_topLeftChunkZ + item->m_bottomRightChunkZ) / 2;
|
||||
int distanceToBeacon = ((x-beaconX)*(x-beaconX) + (z-beaconZ)*(z-beaconZ));
|
||||
|
||||
if (bestSoFar == 0 || distanceToBeacon < bestDistance)
|
||||
{
|
||||
bestDistance = distanceToBeacon;
|
||||
bestSoFar = item->m_wildernessServerId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestSoFar;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Finds the closest operational game server to the specified spot. Used
|
||||
* when the server specified in the preload list isn't available, because
|
||||
* either it crashed or it hasn't started yet.
|
||||
* Considers wilderness first, because city servers are probably more
|
||||
* heavily loaded.
|
||||
*/
|
||||
uint32 PreloadManager::getClosestGameServer (int x, int z)
|
||||
{
|
||||
uint32 bestSoFar = 0;
|
||||
int bestDistance = 0;
|
||||
std::vector<PreloadListData>::const_iterator item;
|
||||
for (item=m_preloadList->begin(); item!=m_preloadList->end(); ++item)
|
||||
{
|
||||
if (item->m_wildernessServerId != 0)
|
||||
{
|
||||
int beaconX=(item->m_topLeftChunkX + item->m_bottomRightChunkX) / 2;
|
||||
int beaconZ=(item->m_topLeftChunkZ + item->m_bottomRightChunkZ) / 2;
|
||||
int distanceToBeacon = ((x-beaconX)*(x-beaconX) + (z-beaconZ)*(z-beaconZ));
|
||||
uint32 realServerId = getRealServerId(item->m_wildernessServerId);
|
||||
if ((realServerId != 0) && (bestSoFar == 0 || distanceToBeacon < bestDistance))
|
||||
{
|
||||
bestDistance = distanceToBeacon;
|
||||
bestSoFar = realServerId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestSoFar==0)
|
||||
{
|
||||
// No wilderness servers. Try city servers
|
||||
for (item=m_preloadList->begin(); item!=m_preloadList->end(); ++item)
|
||||
{
|
||||
if (item->m_cityServerId != 0)
|
||||
{
|
||||
int beaconX=(item->m_topLeftChunkX + item->m_bottomRightChunkX) / 2;
|
||||
int beaconZ=(item->m_topLeftChunkZ + item->m_bottomRightChunkZ) / 2;
|
||||
int distanceToBeacon = ((x-beaconX)*(x-beaconX) + (z-beaconZ)*(z-beaconZ));
|
||||
uint32 realServerId = getRealServerId(item->m_cityServerId);
|
||||
if ((realServerId != 0) && (bestSoFar == 0 || distanceToBeacon < bestDistance))
|
||||
{
|
||||
bestDistance = distanceToBeacon;
|
||||
bestSoFar = realServerId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestSoFar; // returning 0 is possible
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds the loadbeacon locations to a PopulationList structure.
|
||||
*/
|
||||
void PreloadManager::updatePopulationList(PopulationList &theList) const
|
||||
{
|
||||
for (std::vector<PreloadListData>::const_iterator item=m_preloadList->begin(); item!=m_preloadList->end(); ++item)
|
||||
{
|
||||
int chunkX=(item->m_topLeftChunkX + item->m_bottomRightChunkX) / 2;
|
||||
int chunkZ=(item->m_topLeftChunkZ + item->m_bottomRightChunkZ) / 2;
|
||||
theList.setPopulation(Scene::getInstance().getSceneId(),chunkX, chunkZ, Scene::getInstance().getServerPopulationByLocation(chunkX, chunkZ));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PreloadServerId PreloadManager::getPreloadServerId(uint32 realServerId) const
|
||||
{
|
||||
for (ServerMapType::iterator i=m_serverMap->begin(); i!=m_serverMap->end(); ++i)
|
||||
if (i->second.m_actualServerId == realServerId)
|
||||
return i->first;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool PreloadManager::isPreloadComplete() const
|
||||
{
|
||||
return (m_listReceived && m_serversWaiting->empty());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void PreloadManager::getDebugString(std::string &output) const
|
||||
{
|
||||
if (isPreloadComplete())
|
||||
output="finished";
|
||||
else
|
||||
{
|
||||
output="loading";
|
||||
for (ServersWaitingType::const_iterator i=m_serversWaiting->begin(); i!=m_serversWaiting->end(); ++i)
|
||||
{
|
||||
uint32 realServerId=0;
|
||||
int loadTime=0;
|
||||
ServerMapType::const_iterator j=m_serverMap->find(*i);
|
||||
if (j!=m_serverMap->end())
|
||||
{
|
||||
realServerId=j->second.m_actualServerId;
|
||||
|
||||
if (j->second.m_loadTime != -1)
|
||||
loadTime = j->second.m_loadTime;
|
||||
else
|
||||
loadTime = time(0) - j->second.m_timeLoadStarted;
|
||||
}
|
||||
|
||||
char temp[100];
|
||||
sprintf(temp," %lu-%ds (%lu)",*i,loadTime,realServerId);
|
||||
output+=temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
uint32 PreloadManager::getRealServerId(PreloadServerId preloadServerId) const
|
||||
{
|
||||
ServerMapType::iterator i=m_serverMap->find(preloadServerId);
|
||||
if (i!=m_serverMap->end())
|
||||
return i->second.m_actualServerId;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,88 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PreloadManager.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_PreloadManager_H
|
||||
#define INCLUDED_PreloadManager_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "Singleton/Singleton2.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class PopulationList;
|
||||
|
||||
typedef uint32 PreloadServerId; // each server has a id from the preload list, which isn't the same as its processid. Typedef to make the code easier to read.
|
||||
|
||||
class PreloadListData
|
||||
{
|
||||
public:
|
||||
int m_topLeftChunkX;
|
||||
int m_topLeftChunkZ;
|
||||
int m_bottomRightChunkX;
|
||||
int m_bottomRightChunkZ;
|
||||
PreloadServerId m_cityServerId;
|
||||
PreloadServerId m_wildernessServerId;
|
||||
};
|
||||
|
||||
class PreloadServerInformation
|
||||
{
|
||||
public:
|
||||
uint32 m_actualServerId;
|
||||
time_t m_timeLoadStarted;
|
||||
int m_loadTime;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class PreloadManager : public Singleton2<PreloadManager>
|
||||
{
|
||||
public:
|
||||
PreloadManager();
|
||||
virtual ~PreloadManager();
|
||||
|
||||
public:
|
||||
bool onGameServerReady (uint32 serverId, PreloadServerId preloadServerId);
|
||||
void handlePreloadList ();
|
||||
void removeGameServer (uint32 serverId);
|
||||
void preloadCompleteOnServer (uint32 serverId);
|
||||
uint32 getClosestGameServer (int x, int z);
|
||||
PreloadServerId getPreloadGameServer (int x, int z);
|
||||
void updatePopulationList (PopulationList &theList) const;
|
||||
bool isPreloadComplete () const;
|
||||
PreloadServerId getPreloadServerId (uint32 realServerId) const;
|
||||
uint32 getRealServerId (PreloadServerId preloadServerId) const;
|
||||
void getDebugString (std::string &output) const;
|
||||
|
||||
typedef stdmap<PreloadServerId, PreloadServerInformation>::fwd ServerMapType;
|
||||
ServerMapType const * getServerMap () const;
|
||||
|
||||
private:
|
||||
void sendPreloadsToGameServer (uint32 realServerId, PreloadServerId preloadServerId) const;
|
||||
|
||||
private:
|
||||
ServerMapType *m_serverMap; // map of server id in preload list ---> actual server id
|
||||
|
||||
typedef stdvector<PreloadListData>::fwd PreloadListType;
|
||||
PreloadListType *m_preloadList;
|
||||
|
||||
typedef stdset<PreloadServerId>::fwd ServersWaitingType;
|
||||
ServersWaitingType *m_serversWaiting; // set of servers (by list id, not actual id) that still need preloads.
|
||||
|
||||
bool m_listReceived;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
inline PreloadManager::ServerMapType const * PreloadManager::getServerMap () const
|
||||
{
|
||||
return m_serverMap;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,582 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Node.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "QuadtreeNode.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "PlanetProxyObject.h"
|
||||
#include "PlanetServer.h"
|
||||
#include "PreloadManager.h"
|
||||
#include "Scene.h"
|
||||
#include "WatcherConnection.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/MemoryBlockManager.h"
|
||||
#include "sharedNetworkMessages/PlanetNodeStatusMessage.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
//===================================================================
|
||||
|
||||
MemoryBlockManager* Node::memoryBlockManager;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* Create a new spatial subdivision node.
|
||||
*/
|
||||
|
||||
Node::Node(int x, int z) :
|
||||
m_objectList(),
|
||||
m_subscriptionList(),
|
||||
m_preferredServer(0),
|
||||
m_preloadServerId(0),
|
||||
m_loaded(false),
|
||||
m_isBorder(false),
|
||||
m_x(x),
|
||||
m_z(z)
|
||||
{
|
||||
WARNING_DEBUG_FATAL((x!=roundToNode(x)) || (z!=roundToNode(z)),("Creating node %s, coordinates not on a node boundary.",getDebugNodeString().c_str()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Places the object in this node and notifies servers as appropriate.
|
||||
*
|
||||
* @param newObject The object to add
|
||||
*/
|
||||
|
||||
void Node::addObject(PlanetProxyObject *newObject)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Adding object %s to node %s",newObject->getObjectId().getValueString().c_str(),getDebugNodeString().c_str()));
|
||||
|
||||
WARNING_DEBUG_FATAL(!m_loaded,("Attempt to place an object in an unloaded node."));
|
||||
WARNING_DEBUG_FATAL(newObject->getObjectId() == NetworkId::cms_invalid,("Attempt to place object 0 in a node."));
|
||||
|
||||
m_objectList.push_back(newObject);
|
||||
// We don't send add proxy messages here, because PlanetProxyObject::move() does that.
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Remove an object from the node.
|
||||
*/
|
||||
|
||||
void Node::removeObject(const PlanetProxyObject *oldObject)
|
||||
{
|
||||
NOT_NULL(oldObject);
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Removing object %s from node %s",oldObject->getObjectId().getValueString().c_str(),getDebugNodeString().c_str()));
|
||||
ObjectListType::iterator i;
|
||||
for (i=m_objectList.begin();i!=m_objectList.end();++i)
|
||||
if (*i==oldObject)
|
||||
break;
|
||||
if (i==m_objectList.end())
|
||||
{
|
||||
WARNING_DEBUG_FATAL(true,("Attempted to remove object %s that was not in the node.", oldObject->getObjectId().getValueString().c_str()));
|
||||
return; //lint !e527 Unreachable (in debug mode only)
|
||||
}
|
||||
IGNORE_RETURN(m_objectList.erase(i));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Subscribe a server to this node.
|
||||
* Makes sure that the specifed server has proxies of the objects in the
|
||||
* node and gets updates when new objects enter the node.
|
||||
* @param serverId the server
|
||||
* @param count How many objects are interested (Note: 0 is a legal value.
|
||||
* It means that we want the server to know about this node, but there
|
||||
* aren't any interested objects nearby yet.)
|
||||
*/
|
||||
|
||||
void Node::subscribeServer(uint32 serverId, int count)
|
||||
{
|
||||
WARNING_DEBUG_FATAL(serverId==0,("Programmer bug: Server 0 passed to subscribeServer"));
|
||||
WARNING_DEBUG_FATAL(count < 0,("Programmer bug: Passed negative count to subscribeServer"));
|
||||
|
||||
bool newSub=false;
|
||||
|
||||
if (!m_loaded)
|
||||
{
|
||||
load();
|
||||
}
|
||||
|
||||
SubscriptionListType::iterator i=m_subscriptionList.find(serverId);
|
||||
if (i!=m_subscriptionList.end())
|
||||
{
|
||||
((*i).second)+=count;
|
||||
}
|
||||
else
|
||||
{
|
||||
newSub = true;
|
||||
m_subscriptionList[serverId]=count;
|
||||
|
||||
for (ObjectListType::iterator j=m_objectList.begin(); j!=m_objectList.end(); ++j)
|
||||
{
|
||||
if (serverId!=(*j)->getAuthoritativeServer() && (*j)->getContainedBy() == NetworkId::cms_invalid)
|
||||
{
|
||||
(*j)->sendAddProxy(serverId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PlanetServer::getInstance().isWatcherPresent())
|
||||
{
|
||||
outputStatusToAll();
|
||||
}
|
||||
|
||||
if (ConfigPlanetServer::getLogChunkLoading())
|
||||
{
|
||||
if (newSub)
|
||||
LOG("ChunkLoading",("Node %s Server %lu new subscription, count %i",getDebugNodeString().c_str(), serverId, m_subscriptionList[serverId]));
|
||||
else
|
||||
LOG("ChunkLoading",("Node %s Server %lu subscription count changed by %i to %i",getDebugNodeString().c_str(), serverId, count, m_subscriptionList[serverId]));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Decrease the count of objects on a server that are interested in this
|
||||
* node. If the count reaches 0, the subscription is kept, but
|
||||
* the load balancing algorithms may remove it later.
|
||||
*/
|
||||
|
||||
void Node::unsubscribeServer(uint32 serverId, int count, bool clearIfZero)
|
||||
{
|
||||
WARNING_DEBUG_FATAL(serverId==0,("Programmer bug: Server 0 passed to unsubscribeServer"));
|
||||
WARNING_DEBUG_FATAL(count < 0,("Programmer bug: Passed negative count to unsubscribeServer"));
|
||||
|
||||
bool cleared=false;
|
||||
|
||||
SubscriptionListType::iterator i=m_subscriptionList.find(serverId);
|
||||
WARNING(i==m_subscriptionList.end(),("Attempted to unsubscribe server %i that was not subscribed to node %s.",serverId,getDebugNodeString().c_str()));
|
||||
|
||||
if (i!=m_subscriptionList.end())
|
||||
{
|
||||
i->second-=count;
|
||||
|
||||
if (i->second < 0)
|
||||
{
|
||||
WARNING(true,("Programmer bug: Subscription count for server %i on node %s went negative.",serverId,getDebugNodeString().c_str()));
|
||||
i->second = 0;
|
||||
}
|
||||
|
||||
if (clearIfZero && i->second == 0 && m_preferredServer != serverId)
|
||||
{
|
||||
cleared=true;
|
||||
unproxyAllObjects(serverId);
|
||||
m_subscriptionList.erase(i);
|
||||
|
||||
if (PlanetServer::getInstance().isWatcherPresent())
|
||||
{
|
||||
outputStatusToAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigPlanetServer::getLogChunkLoading())
|
||||
{
|
||||
if (cleared)
|
||||
LOG("ChunkLoading",("Node %s Server %lu unsubscribed",getDebugNodeString().c_str(), serverId));
|
||||
else
|
||||
LOG("ChunkLoading",("Node %s Server %lu subscription count changed by -%i to %i",getDebugNodeString().c_str(), serverId, count, m_subscriptionList[serverId]));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper function. Removes the proxies on the specified server.
|
||||
* Does not update the subscription list.
|
||||
*/
|
||||
void Node::unproxyAllObjects(uint32 serverId)
|
||||
{
|
||||
for (ObjectListType::iterator j=m_objectList.begin(); j!=m_objectList.end(); ++j)
|
||||
(*j)->sendRemoveProxy(serverId);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Load a node from the database.
|
||||
* Marks the node as loaded, and instructs the database to put the objects
|
||||
* in the node on a particular game server. The game server will report
|
||||
* the objects back to us after they get loaded.
|
||||
*/
|
||||
|
||||
void Node::load()
|
||||
{
|
||||
if (m_loaded)
|
||||
return;
|
||||
|
||||
if (m_preferredServer == 0)
|
||||
pickPreferredServer();
|
||||
|
||||
if (m_preferredServer == 0)
|
||||
{
|
||||
WARNING_DEBUG_FATAL(true, ("load failed for node %s because m_preferredServer is 0",getDebugNodeString().c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
m_loaded=true;
|
||||
|
||||
bool sendRequest=true; // in certain modes, we don't need to check the DB for objects
|
||||
if (PlanetServer::getInstance().isInTutorialMode())
|
||||
sendRequest=false;
|
||||
if (PlanetServer::getInstance().isInSpaceMode() && !(m_x == 0 && m_z == 0)) // only load (0,0) in space
|
||||
sendRequest=false;
|
||||
|
||||
if (sendRequest)
|
||||
{
|
||||
PlanetServer::getInstance().sendChunkRequest(m_preferredServer, m_x,m_z);
|
||||
if (ConfigPlanetServer::getLogChunkLoading())
|
||||
LOG("ChunkLoading", ("RequestChunk: Node %s Server %i",getDebugNodeString().c_str(),m_preferredServer));
|
||||
}
|
||||
|
||||
subscribeServer(m_preferredServer,0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper function: picks the best server for this node and puts it
|
||||
* into m_preferredServer.
|
||||
*/
|
||||
void Node::pickPreferredServer()
|
||||
{
|
||||
m_preferredServer = PreloadManager::getInstance().getRealServerId(m_preloadServerId);
|
||||
if (m_preferredServer == 0)
|
||||
m_preferredServer = PreloadManager::getInstance().getClosestGameServer(m_x, m_z);
|
||||
WARNING_DEBUG_FATAL(m_preferredServer==0,("Programmer bug: Node::pickPreferredServer could not pick a server"));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get a string listing the coordinates of this node.
|
||||
* For debugging, FATALs, etc.
|
||||
*/
|
||||
std::string Node::getDebugNodeString() const
|
||||
{
|
||||
char buffer[100];
|
||||
snprintf(buffer,sizeof(buffer)-1,"%s (%i,%i)",Scene::getInstance().getSceneId().c_str(),m_x,m_z);
|
||||
buffer[sizeof(buffer)-1]='\0';
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Output the status of the node to the PlanetWatch tool.
|
||||
*/
|
||||
void Node::outputStatus(WatcherConnection &conn) const
|
||||
{
|
||||
std::vector<uint32> servers;
|
||||
std::vector<int> subscriptionCount;
|
||||
for (SubscriptionListType::const_iterator i=m_subscriptionList.begin(); i!=m_subscriptionList.end(); ++i)
|
||||
{
|
||||
servers.push_back((*i).first);
|
||||
subscriptionCount.push_back((*i).second);
|
||||
|
||||
WARNING_DEBUG_FATAL((*i).first==0,("Found a 0 in subscrption list (where did it come from?)"));
|
||||
}
|
||||
|
||||
conn.addNodeUpdate(m_x,m_z,m_loaded, servers, subscriptionCount);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Node::outputStatusToAll() const
|
||||
{
|
||||
const PlanetServer::WatcherList &connections = PlanetServer::getInstance().getWatchers();
|
||||
for (PlanetServer::WatcherList::const_iterator i= connections.begin(); i!=connections.end(); ++i)
|
||||
{
|
||||
outputStatus(**i);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set up a memory pool for QuadTreeNodes.
|
||||
*/
|
||||
|
||||
void Node::install()
|
||||
{
|
||||
memoryBlockManager = new MemoryBlockManager("Node::memoryBlockManager", true, sizeof(Node), 0, 0, 0);
|
||||
|
||||
ExitChain::add(&remove, "Node::remove");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Node::remove()
|
||||
{
|
||||
WARNING_DEBUG_FATAL(!memoryBlockManager,("Node is not installed"));
|
||||
|
||||
delete memoryBlockManager;
|
||||
memoryBlockManager = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void * Node::operator new(size_t size)
|
||||
{
|
||||
UNREF(size);
|
||||
|
||||
WARNING_DEBUG_FATAL(!memoryBlockManager,("Node is not installed"));
|
||||
|
||||
// do not try to alloc a descendant class with this allocator
|
||||
WARNING_DEBUG_FATAL(size != sizeof(Node),("bad size"));
|
||||
|
||||
return memoryBlockManager->allocate();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Node::operator delete(void* pointer)
|
||||
{
|
||||
WARNING_DEBUG_FATAL(!memoryBlockManager,("Node is not installed"));
|
||||
memoryBlockManager->free(pointer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Load the node onto the specified server.
|
||||
*/
|
||||
void Node::load(uint32 serverId)
|
||||
{
|
||||
if (m_loaded)
|
||||
{
|
||||
WARNING_DEBUG_FATAL(m_loaded,("Programmer bug: called load on Node %s,.which was already loaded",getDebugNodeString().c_str()));
|
||||
return;
|
||||
}
|
||||
m_preferredServer = serverId;
|
||||
load();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Node::getServers(std::vector<uint32> &serverList) const
|
||||
{
|
||||
for (SubscriptionListType::const_iterator i=m_subscriptionList.begin(); i!=m_subscriptionList.end(); ++i)
|
||||
{
|
||||
serverList.push_back(i->first);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Migrate the objects to the specfied server, and get rid of any subscribed
|
||||
* servers that aren't interested in the node anymore
|
||||
*/
|
||||
void Node::migrateToServer(uint32 newServer)
|
||||
{
|
||||
WARNING_DEBUG_FATAL (!m_loaded,("Programmer bug: called migrateToServer(%i) on unloaded node %s",newServer,getDebugNodeString().c_str()));
|
||||
|
||||
if (m_preferredServer == newServer)
|
||||
return;
|
||||
|
||||
subscribeServer(newServer,0);
|
||||
m_preferredServer = newServer;
|
||||
|
||||
for (ObjectListType::iterator i=m_objectList.begin(); i!=m_objectList.end(); ++i)
|
||||
{
|
||||
(*i)->unsubscribeSurroundingNodes(true);
|
||||
(*i)->changeAuthority(newServer, false, false);
|
||||
(*i)->subscribeSurroundingNodes();
|
||||
}
|
||||
|
||||
// remove any zero subscriptions:
|
||||
|
||||
std::vector<uint32> unsubscribeList;
|
||||
|
||||
for (SubscriptionListType::iterator subscription=m_subscriptionList.begin(); subscription!=m_subscriptionList.end(); ++subscription)
|
||||
if (subscription->second == 0 && subscription->first != newServer)
|
||||
unsubscribeList.push_back(subscription->first);
|
||||
|
||||
for (std::vector<uint32>::iterator s=unsubscribeList.begin(); s!=unsubscribeList.end(); ++s)
|
||||
{
|
||||
unproxyAllObjects(*s);
|
||||
IGNORE_RETURN(m_subscriptionList.erase(*s));
|
||||
}
|
||||
|
||||
if (PlanetServer::getInstance().isWatcherPresent())
|
||||
{
|
||||
outputStatusToAll();
|
||||
}
|
||||
|
||||
if (ConfigPlanetServer::getLogChunkLoading())
|
||||
LOG("ChunkLoading",("Node %s Migrate to server %lu",getDebugNodeString().c_str(), newServer));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check that this node is assigned to the right server, and fix it if
|
||||
* it isn't.
|
||||
*/
|
||||
void Node::checkServerAssignment()
|
||||
{
|
||||
if (!m_loaded)
|
||||
return;
|
||||
uint32 bestServer = PreloadManager::getInstance().getRealServerId(m_preloadServerId);
|
||||
if (bestServer==0)
|
||||
return;
|
||||
|
||||
if (m_preferredServer != bestServer)
|
||||
migrateToServer(bestServer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Node::handleCrash(uint32 crashedServer, std::vector<PlanetProxyObject*> &subscriptionFixups)
|
||||
{
|
||||
bool wasSubscribed = false;
|
||||
|
||||
{
|
||||
for (SubscriptionListType::iterator i=m_subscriptionList.begin(); i!=m_subscriptionList.end();)
|
||||
{
|
||||
if (i->first == crashedServer)
|
||||
{
|
||||
m_subscriptionList.erase(i++);
|
||||
wasSubscribed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_preferredServer == crashedServer)
|
||||
{
|
||||
if (!m_subscriptionList.empty())
|
||||
{
|
||||
// pick a new server for this node and move the objects
|
||||
|
||||
uint32 newServer = m_subscriptionList.begin()->first;
|
||||
m_preferredServer = newServer;
|
||||
WARNING_DEBUG_FATAL(newServer == crashedServer,("Programmer bug: crashed server was still in the subscription list after it was supposedly removed."));
|
||||
}
|
||||
else
|
||||
{
|
||||
// no other server has proxies. Unload the node.
|
||||
m_loaded = false;
|
||||
m_preferredServer = 0;
|
||||
|
||||
for (ObjectListType::iterator i=m_objectList.begin(); i!=m_objectList.end(); ++i)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",
|
||||
("Handling crash: Dropping object %s because node %s was dropped",
|
||||
(*i)->getObjectId().getValueString().c_str(),getDebugNodeString().c_str()));
|
||||
|
||||
Scene::getInstance().removeObjectFromMap((*i)->getObjectId(),false);
|
||||
delete *i;
|
||||
}
|
||||
m_objectList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
for (ObjectListType::iterator i=m_objectList.begin(); i!=m_objectList.end(); ++i)
|
||||
{
|
||||
if ((*i)->getContainedBy() == NetworkId::cms_invalid)
|
||||
{
|
||||
if (crashedServer==(*i)->getAuthoritativeServer())
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",
|
||||
("Handling crash: moving object %s from server %lu to server %lu",
|
||||
(*i)->getObjectId().getValueString().c_str(),crashedServer,m_preferredServer));
|
||||
|
||||
(*i)->changeAuthority(m_preferredServer, true, false);
|
||||
(*i)->sendRemoveProxy(crashedServer);
|
||||
if ((*i)->getInterestRadius() > 0)
|
||||
subscriptionFixups.push_back(*i);
|
||||
}
|
||||
else
|
||||
{
|
||||
// tell objects they don't have a proxy on this server anymore
|
||||
if (wasSubscribed)
|
||||
(*i)->sendRemoveProxy(crashedServer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PlanetServer::getInstance().isWatcherPresent())
|
||||
{
|
||||
outputStatusToAll();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Node::isBorderNode() const
|
||||
{
|
||||
WARNING_DEBUG_FATAL(getPreferredServer()==0,("Programmer bug: called isBorderNode() on node %s, which has 0 for its preferred server.",getDebugNodeString().c_str()));
|
||||
|
||||
if (m_subscriptionList.size() < 2)
|
||||
{
|
||||
m_isBorder = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_isBorder)
|
||||
return true;
|
||||
|
||||
int maxX=m_x+getNodeSize();
|
||||
int maxZ=m_z+getNodeSize();
|
||||
for (int x=m_x-getNodeSize();x<=maxX;x+=getNodeSize())
|
||||
for (int z=m_z-getNodeSize();z<=maxZ;z+=getNodeSize())
|
||||
if (!(x==m_x && z==m_z))
|
||||
{
|
||||
const Node *node = Scene::getInstance().findNodeByRoundedPositionConst(x,z);
|
||||
if (node && node->getPreferredServer()!=0 && node->getPreferredServer() != getPreferredServer())
|
||||
{
|
||||
m_isBorder = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Node::isServerSubscribed(uint32 serverId) const
|
||||
{
|
||||
return (m_subscriptionList.find(serverId)!=m_subscriptionList.end());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Node::setPreloadServerId(PreloadServerId preloadServerId)
|
||||
{
|
||||
m_preloadServerId = preloadServerId;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PreloadServerId Node::getPreloadServerId() const
|
||||
{
|
||||
return m_preloadServerId;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,119 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Node.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_Node_H
|
||||
#define INCLUDED_Node_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
class PlanetProxyObject;
|
||||
class MemoryBlockManager;
|
||||
class WatcherConnection;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
typedef std::map<uint32, int> SubscriptionListType;
|
||||
|
||||
public:
|
||||
Node(int x, int z);
|
||||
|
||||
public:
|
||||
void addObject (PlanetProxyObject *newObject);
|
||||
void checkServerAssignment();
|
||||
void handleCrash (uint32 crashedServer, stdvector<PlanetProxyObject*>::fwd &subscriptionFixups);
|
||||
void load ();
|
||||
void migrateToServer (uint32 newServerId);
|
||||
void load (uint32 serverId);
|
||||
void removeObject (const PlanetProxyObject *object);
|
||||
void subscribeServer (uint32 serverId, int count);
|
||||
void unsubscribeServer (uint32 serverId, int count, bool clearIfZero);
|
||||
void setPreloadServerId(PreloadServerId preloadServerId);
|
||||
|
||||
public:
|
||||
static int getNodeSize ();
|
||||
static int roundToNode (int coordinate);
|
||||
bool isBorderNode () const;
|
||||
bool isLoaded () const;
|
||||
bool isServerSubscribed(uint32 serverId) const;
|
||||
std::string getDebugNodeString() const;
|
||||
uint32 getPreferredServer() const;
|
||||
PreloadServerId getPreloadServerId() const;
|
||||
void getServers (std::vector<uint32> &serverList) const;
|
||||
void outputStatus (WatcherConnection &conn) const;
|
||||
void outputStatusToAll () const;
|
||||
|
||||
public:
|
||||
static void install ();
|
||||
static void remove ();
|
||||
static void* operator new (size_t size);
|
||||
static void operator delete (void* pointer);
|
||||
|
||||
private:
|
||||
void pickPreferredServer();
|
||||
void unproxyAllObjects (uint32 serverId);
|
||||
|
||||
private:
|
||||
typedef std::vector<PlanetProxyObject*> ObjectListType;
|
||||
|
||||
private:
|
||||
ObjectListType m_objectList;
|
||||
SubscriptionListType m_subscriptionList;
|
||||
uint32 m_preferredServer;
|
||||
PreloadServerId m_preloadServerId;
|
||||
bool m_loaded;
|
||||
mutable bool m_isBorder;
|
||||
|
||||
/**
|
||||
* Coordinates of the node are represented by the minimum X and minimum Z coordinates.
|
||||
*/
|
||||
int m_x, m_z;
|
||||
|
||||
static MemoryBlockManager* memoryBlockManager;
|
||||
|
||||
private:
|
||||
Node(); //disable
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline bool Node::isLoaded() const
|
||||
{
|
||||
return m_loaded;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int Node::roundToNode(int coordinate)
|
||||
{
|
||||
return (coordinate >= 0) ? (coordinate/getNodeSize())*getNodeSize() : ((coordinate-getNodeSize()+1)/getNodeSize())*getNodeSize(); //lint !e834 // Lint doesn't like a-b+c
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int Node::getNodeSize()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline uint32 Node::getPreferredServer() const
|
||||
{
|
||||
return m_preferredServer;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,674 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Scene.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "Scene.h"
|
||||
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "GameServerConnection.h"
|
||||
#include "GameServerData.h"
|
||||
#include "PlanetProxyObject.h"
|
||||
#include "PreloadManager.h"
|
||||
#include "QuadtreeNode.h"
|
||||
#include "serverNetworkMessages/PlanetRemoveObject.h"
|
||||
#include "serverNetworkMessages/PopulationListMessage.h"
|
||||
#include "serverNetworkMessages/UpdateObjectOnPlanetMessage.h"
|
||||
#include "serverUtility/PopulationList.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
|
||||
#include "sharedUtility/LocationManager.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
Scene::Scene() :
|
||||
Singleton2<Scene>(),
|
||||
MessageDispatch::Receiver(),
|
||||
m_sceneId(),
|
||||
m_objects(),
|
||||
m_deletedObjects(),
|
||||
m_nodeMap(),
|
||||
m_populationList(new PopulationList),
|
||||
m_populationCountTimer(static_cast<float>(ConfigPlanetServer::getPopulationCountTime())),
|
||||
m_maxCoordinate(0)
|
||||
{
|
||||
ExitChain::add(&remove, "Scene::remove");
|
||||
|
||||
connectToMessage("GameConnectionClosed");
|
||||
connectToMessage("UpdateObjectOnPlanetMessage");
|
||||
connectToMessage("PlanetRemoveObject");
|
||||
connectToMessage("ForceLoadArea");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the scene ID. Make this part of the constructor if we ever make
|
||||
* this a non-singleton class.
|
||||
*/
|
||||
void Scene::setSceneId(const std::string &sceneId)
|
||||
{
|
||||
m_sceneId=sceneId;
|
||||
|
||||
//-- tell the LocationManager what planet we're on
|
||||
LocationManager::setPlanetName (sceneId.c_str ());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called to add an object to the scene. Scene takes ownership
|
||||
* of the object and will be resposible for deleting it.
|
||||
*/
|
||||
|
||||
void Scene::addObject(PlanetProxyObject *newObject)
|
||||
{
|
||||
m_objects[newObject->getObjectId()]=newObject;
|
||||
newObject->addServerStatistics();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
PlanetProxyObject *Scene::findObjectByID(const NetworkId &objectID) const
|
||||
{
|
||||
ObjectMapType::const_iterator i=m_objects.find(objectID);
|
||||
if (i==m_objects.end())
|
||||
return NULL;
|
||||
else
|
||||
return ((*i).second);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Scene::isObjectLoaded(const NetworkId &networkId) const
|
||||
{
|
||||
return m_objects.find(networkId) != m_objects.end();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Scene::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message)
|
||||
{
|
||||
const GameServerConnection *gameServer=dynamic_cast<const GameServerConnection*>(&source);
|
||||
WARNING_DEBUG_FATAL(gameServer==0,("Source was NULL or source was not a GameServerConnection."));
|
||||
|
||||
if (message.isType("GameConnectionClosed"))
|
||||
{
|
||||
DEBUG_REPORT_LOG(true, ("Handling a game server crash for server %lu\n", gameServer->getProcessId()));
|
||||
handleCrash(gameServer->getProcessId());
|
||||
}
|
||||
|
||||
else if (message.isType("UpdateObjectOnPlanetMessage"))
|
||||
{
|
||||
Archive::ReadIterator ri = static_cast<const GameNetworkMessage &>(message).getByteStream().begin();
|
||||
UpdateObjectOnPlanetMessage msg(ri);
|
||||
|
||||
int interestRadius = msg.getInterestRadius();
|
||||
|
||||
if(msg.getWatched() && interestRadius == 0)
|
||||
interestRadius = 1;
|
||||
|
||||
if (m_deletedObjects.find(msg.getObjectId())!=m_deletedObjects.end())
|
||||
{
|
||||
DEBUG_REPORT_LOG(true,("Ignoring update for object %s which has been removed.\n",msg.getObjectId().getValueString().c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkId container(msg.getTopmostContainer());
|
||||
if (container==msg.getObjectId()) // game server sends container == objectId if the object is not contained
|
||||
container=NetworkId::cms_invalid;
|
||||
|
||||
bool processUpdate = true;
|
||||
if (container != NetworkId::cms_invalid)
|
||||
{
|
||||
PlanetProxyObject const *const containerObject = findObjectByID(container);
|
||||
if (containerObject)
|
||||
{
|
||||
if (containerObject->getAuthoritativeServer() != gameServer->getProcessId())
|
||||
{
|
||||
// This update message came from a server that is not
|
||||
// authoritative for the container of this object. This
|
||||
// can happen when the planet server is in control of
|
||||
// switching the container's authority but is not in
|
||||
// charge of changing the container content's authority.
|
||||
// This happens to the rider of a mount when the mount
|
||||
// switches authority.
|
||||
processUpdate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (processUpdate)
|
||||
{
|
||||
PlanetProxyObject *theObject=findObjectByID(msg.getObjectId());
|
||||
if (!theObject)
|
||||
{
|
||||
// this is a new object
|
||||
theObject=new PlanetProxyObject(msg.getObjectId());
|
||||
addObject(theObject);
|
||||
}
|
||||
|
||||
theObject->onReceivedMessageFromServer(gameServer->getProcessId());
|
||||
theObject->update(msg.getX(), msg.getY(), msg.getZ(), container, gameServer->getProcessId(), interestRadius, msg.getObjectTypeTag(), msg.getLevel(), msg.getHibernating(), msg.getTemplateCrc(), msg.getAiActivity(), msg.getCreationType());
|
||||
|
||||
//-- handle updating LocationManager
|
||||
if (msg.getLocationReservationRadius () > 0.f)
|
||||
LocationManager::updateObject (msg.getObjectId (), msg.getX (), msg.getZ (), msg.getLocationReservationRadius ());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.isType("PlanetRemoveObject"))
|
||||
{
|
||||
Archive::ReadIterator ri = static_cast<const GameNetworkMessage &>(message).getByteStream().begin();
|
||||
PlanetRemoveObject msg(ri);
|
||||
handleRemoveObject(msg.getObjectId());
|
||||
|
||||
//-- handle updating LocationManager
|
||||
LocationManager::removeObject (msg.getObjectId ());
|
||||
}
|
||||
else if (message.isType("ForceLoadArea"))
|
||||
{
|
||||
Archive::ReadIterator ri = static_cast<const GameNetworkMessage &>(message).getByteStream().begin();
|
||||
GenericValueTypeMessage<std::pair<uint32, std::pair<std::pair<float, float>, std::pair<float, float> > > > const msg(ri);
|
||||
|
||||
handleForceLoadArea(
|
||||
msg.getValue().first,
|
||||
static_cast<int>(msg.getValue().second.first.first),
|
||||
static_cast<int>(msg.getValue().second.first.second),
|
||||
static_cast<int>(msg.getValue().second.second.first),
|
||||
static_cast<int>(msg.getValue().second.second.second));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_REPORT_LOG(true,("Scene.cpp received an unidentified message.\n"));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Scene::subscribeServer(uint32 server, int x, int z, int interestRadius, int count)
|
||||
{
|
||||
NodeListType nodelist;
|
||||
findIntersection(nodelist,x,z,interestRadius);
|
||||
|
||||
for (NodeListType::iterator i=nodelist.begin(); i!=nodelist.end(); ++i)
|
||||
{
|
||||
(*i)->subscribeServer(server, count);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given coordinates, return the node that encloses those coordinates.
|
||||
* Creates the node if it doesn't exist already.
|
||||
*/
|
||||
Node *Scene::findNodeByPosition(int x, int z)
|
||||
{
|
||||
return findNodeByRoundedPosition(Node::roundToNode(x),Node::roundToNode(z));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given coordinates, return a const pointer to the node that encloses
|
||||
* those coordinates. Will not create new nodes, so it may return NULL.
|
||||
*/
|
||||
const Node *Scene::findNodeByPositionConst(int x, int z) const
|
||||
{
|
||||
return findNodeByRoundedPositionConst(Node::roundToNode(x),Node::roundToNode(z));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given coordinates that are known to be a node boundary, return the node.
|
||||
* Creates the node if it doesn't exist already.
|
||||
*/
|
||||
Node *Scene::findNodeByRoundedPosition(int x, int z)
|
||||
{
|
||||
DEBUG_FATAL((x!=Node::roundToNode(x)) || (z!=Node::roundToNode(z)),("Parameters to findNodeByRoundedPosistion weren't rounded."));
|
||||
Node *result=m_nodeMap[Coordinates(x,z)];
|
||||
if (!result)
|
||||
{
|
||||
result=new Node(x,z);
|
||||
m_nodeMap[Coordinates(x,z)]=result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given coordinates that are known to be a node boundary, return a const pointer
|
||||
* to the node. Does not create new nodes, so may return NULL.
|
||||
*/
|
||||
const Node *Scene::findNodeByRoundedPositionConst(int x, int z) const
|
||||
{
|
||||
WARNING_DEBUG_FATAL((x!=Node::roundToNode(x)) || (z!=Node::roundToNode(z)),("Parameters to findNodeByRoundedPosistionConst weren't rounded."));
|
||||
NodeMapType::const_iterator i=m_nodeMap.find(Coordinates(x,z));
|
||||
if (i!=m_nodeMap.end())
|
||||
return (*i).second;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given coordinates and a radius, find a set of nodes that contains the circle.
|
||||
*
|
||||
* May return some nodes that don't contain any part of the circle, but
|
||||
* is guaranteed to return at least every node that the circle intersects.
|
||||
* Will add nodes if they don't exist.
|
||||
*/
|
||||
|
||||
void Scene::findIntersection(NodeListType &results,int x, int z, int radius)
|
||||
{
|
||||
int minX=Node::roundToNode(x-radius);
|
||||
int minZ=Node::roundToNode(z-radius);
|
||||
int maxX=Node::roundToNode(x+radius);
|
||||
int maxZ=Node::roundToNode(z+radius);
|
||||
int nodeSize=Node::getNodeSize();
|
||||
|
||||
for (int loopX=minX; loopX <= maxX; loopX+=nodeSize)
|
||||
for (int loopZ=minZ; loopZ <= maxZ; loopZ+=nodeSize)
|
||||
results.push_back(findNodeByRoundedPosition(loopX,loopZ));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Removes an object from the list of objects.
|
||||
*
|
||||
* Places the object in a list of pending deletes. Further updates to
|
||||
* this object will be ignored.
|
||||
* Doesn't remove the object from the quadtree or notify any servers.
|
||||
* This function should only be called by PlanetProxyObject::unload().
|
||||
*
|
||||
* @param objectId Object to remove.
|
||||
* @param addToDeletedList true if we should remember that we deleted the object,
|
||||
* false if not. Generally, we don't need to put the object in the deleted map
|
||||
* if the game server initated the removal. If we initated it, we remember
|
||||
* the object in the deleted map so that we ignore all updates to it until
|
||||
* the game server acknowledges the removal.
|
||||
*/
|
||||
void Scene::removeObjectFromMap(const NetworkId &objectId, bool addToDeletedList)
|
||||
{
|
||||
ObjectMapType::iterator i=m_objects.find(objectId);
|
||||
if (i==m_objects.end())
|
||||
{
|
||||
DEBUG_REPORT_LOG(true,("Requested removing object %s, but it was not in the list.\n",objectId.getValueString().c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_objects.erase(i);
|
||||
}
|
||||
|
||||
if (addToDeletedList)
|
||||
IGNORE_RETURN(m_deletedObjects.insert(objectId));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Handler for the PlanetRemoveObject message.
|
||||
*/
|
||||
|
||||
void Scene::handleRemoveObject(const NetworkId &objectId)
|
||||
{
|
||||
DeletedSetType::iterator i=m_deletedObjects.find(objectId);
|
||||
if (i!=m_deletedObjects.end())
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Removal of object %s confirmed.",objectId.getValueString().c_str()));
|
||||
m_deletedObjects.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Removal of object %s initiated by GameServer.",objectId.getValueString().c_str()));
|
||||
PlanetProxyObject *theObject=findObjectByID(objectId);
|
||||
if (theObject)
|
||||
{
|
||||
theObject->unload(false);
|
||||
|
||||
if (theObject->getInterestRadius()>0)
|
||||
theObject->unsubscribeSurroundingNodes(false);
|
||||
delete theObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Object %s was unknown. Removal request ignored.",objectId.getValueString().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given an object, find which server it is on.
|
||||
* Used by the login process, for example, to find where the building
|
||||
* a player is in is loaded.
|
||||
*/
|
||||
uint32 Scene::getGameServerForObject(const NetworkId &object) const
|
||||
{
|
||||
ObjectMapType::const_iterator i=m_objects.find(object);
|
||||
if (i!=m_objects.end())
|
||||
{
|
||||
const PlanetProxyObject *obj=(*i).second;
|
||||
NOT_NULL(obj);
|
||||
return obj->getAuthoritativeServer();
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Output the status of the scene to a Watcher. (Call when a new watcher
|
||||
* connects, for example.)
|
||||
*/
|
||||
void Scene::outputStatus(WatcherConnection &conn) const
|
||||
{
|
||||
for (NodeMapType::const_iterator i=m_nodeMap.begin(); i!=m_nodeMap.end(); ++i)
|
||||
{
|
||||
(*i).second->outputStatus(conn);
|
||||
}
|
||||
|
||||
for (ObjectMapType::const_iterator j=m_objects.begin(); j!=m_objects.end(); ++j)
|
||||
{
|
||||
(*j).second->outputStatus(conn, false);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Scene::~Scene()
|
||||
{
|
||||
for (NodeMapType::iterator i=m_nodeMap.begin(); i!=m_nodeMap.end(); ++i)
|
||||
{
|
||||
delete (*i).second;
|
||||
(*i).second=0;
|
||||
}
|
||||
|
||||
for (ObjectMapType::iterator j=m_objects.begin(); j!=m_objects.end(); ++j)
|
||||
{
|
||||
delete (*j).second;
|
||||
(*j).second = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Every so often, check for nodes that can be unloaded. If any are found,
|
||||
* unload one node each frame to avoid sending too many unloads to the
|
||||
* game servers at the same time.
|
||||
*/
|
||||
void Scene::update(float time)
|
||||
{
|
||||
//-- Update population count
|
||||
if (m_populationCountTimer.updateSubtract(time))
|
||||
{
|
||||
PreloadManager::getInstance().updatePopulationList(*m_populationList);
|
||||
|
||||
PopulationListMessage msg(*m_populationList);
|
||||
PlanetServer::getInstance().sendToCentral(msg, true);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* For each node, record the preload server id.
|
||||
*/
|
||||
void Scene::assignPreloadsToNodes()
|
||||
{
|
||||
for (int x=-getMaxCoordinate(); x<= getMaxCoordinate(); x+=Node::getNodeSize())
|
||||
{
|
||||
for (int z=-getMaxCoordinate(); z<= getMaxCoordinate(); z+=Node::getNodeSize())
|
||||
{
|
||||
Node *node = findNodeByRoundedPosition(x,z);
|
||||
node->setPreloadServerId(PreloadManager::getInstance().getPreloadGameServer(x,z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check the map for any nodes that belong to the specified server, and
|
||||
* load them. If they are already loaded, move them to the right server.
|
||||
*/
|
||||
void Scene::loadAllNodesForServer(uint32 server, PreloadServerId preloadServerId)
|
||||
{
|
||||
for (int x=-getMaxCoordinate(); x<= getMaxCoordinate(); x+=Node::getNodeSize())
|
||||
{
|
||||
for (int z=-getMaxCoordinate(); z<= getMaxCoordinate(); z+=Node::getNodeSize())
|
||||
{
|
||||
Node *node = findNodeByRoundedPosition(x,z);
|
||||
if (node->getPreloadServerId()==preloadServerId)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogChunkLoading())
|
||||
LOG("ChunkLoading",("Node %s preload to server %lu",node->getDebugNodeString().c_str(), server));
|
||||
|
||||
if (!node->isLoaded())
|
||||
node->load(server);
|
||||
else
|
||||
node->migrateToServer(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Make sure that all nodes are on the server that they should be.
|
||||
* Move any nodes that aren't. They could be on the wrong server due
|
||||
* to server crashes, etc.
|
||||
*/
|
||||
void Scene::checkServerAssignments()
|
||||
{
|
||||
for (NodeMapType::iterator i=m_nodeMap.begin(); i!=m_nodeMap.end(); ++i)
|
||||
i->second->checkServerAssignment();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Scene::handleCrash(uint32 gameServerId)
|
||||
{
|
||||
// wait for the next save before allowing new loads
|
||||
if (ConfigPlanetServer::getRequestDbSaveOnGameServerCrash())
|
||||
PlanetServer::getInstance().requestAndWaitForSave();
|
||||
|
||||
PreloadManager::getInstance().removeGameServer(gameServerId);
|
||||
|
||||
std::vector<PlanetProxyObject*> subscriptionFixups;
|
||||
|
||||
for (NodeMapType::iterator nodeMapIter = m_nodeMap.begin(); nodeMapIter != m_nodeMap.end(); ++nodeMapIter)
|
||||
{
|
||||
nodeMapIter->second->handleCrash(gameServerId, subscriptionFixups);
|
||||
}
|
||||
|
||||
// These have to be done after all the nodes are examined, because otherwise it might think
|
||||
// a server has proxies of the objects on a crashed node when it really doesn't
|
||||
for (std::vector<PlanetProxyObject*>::iterator j=subscriptionFixups.begin(); j!=subscriptionFixups.end(); ++j)
|
||||
(*j)->subscribeSurroundingNodes();
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int Scene::getServerPopulationByLocation(int x, int z) const
|
||||
{
|
||||
const Node *node=findNodeByPositionConst(x,z);
|
||||
if (node && node->isLoaded())
|
||||
{
|
||||
uint32 server = node->getPreferredServer();
|
||||
return PlanetServer::getInstance().getInterestCreatureObjectCountForServer(server);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Scene::requestSameServer(const NetworkId &id1, const NetworkId &id2)
|
||||
{
|
||||
PlanetProxyObject *obj1 = findObjectByID(id1);
|
||||
PlanetProxyObject *obj2 = findObjectByID(id2);
|
||||
if (!obj1 || !obj2)
|
||||
return false;
|
||||
|
||||
if (!obj1->isAuthorityClean() || !obj2->isAuthorityClean())
|
||||
return false;
|
||||
|
||||
uint32 server1 = obj1->getAuthoritativeServer();
|
||||
uint32 server2 = obj2->getAuthoritativeServer();
|
||||
if (server1 == server2)
|
||||
return true;
|
||||
|
||||
if (!obj1->getNode() || !obj2->getNode())
|
||||
return false;
|
||||
|
||||
uint32 preferredServer = obj1->getNode()->getPreferredServer();
|
||||
if (obj2->getNode()->getPreferredServer() == preferredServer)
|
||||
{
|
||||
if (server1 == preferredServer)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Moving object %s to server %lu, so that it is on the same server as %s",id2.getValueString().c_str(),server1,id1.getValueString().c_str()));
|
||||
obj2->changeAuthorityAndSubscriptions(server1);
|
||||
return true;
|
||||
}
|
||||
else if (server2 == preferredServer)
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Moving object %s to server %lu, so that it is on the same server as %s",id1.getValueString().c_str(),server2,id2.getValueString().c_str()));
|
||||
obj1->changeAuthorityAndSubscriptions(server2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj2->wouldAuthorityBeOk(server1))
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Moving object %s to server %lu, so that it is on the same server as %s",id2.getValueString().c_str(),server1,id1.getValueString().c_str()));
|
||||
obj2->changeAuthorityAndSubscriptions(server1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj1->wouldAuthorityBeOk(server2))
|
||||
{
|
||||
if (ConfigPlanetServer::getLogObjectLoading())
|
||||
LOG("ObjectLoading",("Moving object %s to server %lu, so that it is on the same server as %s",id1.getValueString().c_str(),server2,id2.getValueString().c_str()));
|
||||
obj1->changeAuthorityAndSubscriptions(server2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Neither server will work.
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
bool Scene::requestAuthTransfer(const NetworkId &id1, uint32 newServer)
|
||||
{
|
||||
PlanetProxyObject *obj1 = findObjectByID(id1);
|
||||
if (!obj1)
|
||||
return false;
|
||||
|
||||
uint32 server1 = obj1->getAuthoritativeServer();
|
||||
|
||||
if (server1 == newServer)
|
||||
return true;
|
||||
|
||||
if (obj1->wouldAuthorityBeOk(newServer))
|
||||
{
|
||||
obj1->changeAuthorityAndSubscriptions(newServer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Requested server cannot be used.
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Scene::handleForceLoadArea(uint32 gameServerId, int x1, int z1, int x2, int z2)
|
||||
{
|
||||
typedef Node QuadTreeNode;
|
||||
|
||||
int const zStart = QuadTreeNode::roundToNode(static_cast<int>(z1));
|
||||
int const xStart = QuadTreeNode::roundToNode(static_cast<int>(x1));
|
||||
|
||||
for (int nz = zStart; nz <= z2; nz += 100)
|
||||
{
|
||||
for (int nx = xStart; nx <= x2; nx += 100)
|
||||
{
|
||||
Node * const node = findNodeByPosition(nx, nz);
|
||||
node->subscribeServer(gameServerId, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int Scene::getMaxCoordinate() const
|
||||
{
|
||||
if (m_maxCoordinate==0)
|
||||
return 8000; // Assume largest possible map until m_maxCoordiate is set
|
||||
return m_maxCoordinate;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Scene::setMapSize(int mapSize)
|
||||
{
|
||||
int maxCoordinate = Node::roundToNode(mapSize/2) + Node::getNodeSize();
|
||||
if (m_maxCoordinate == 0)
|
||||
m_maxCoordinate = maxCoordinate;
|
||||
else
|
||||
FATAL(m_maxCoordinate!=maxCoordinate,("Game servers for planet %s sent different sizes for the maps. Possible sizes are %i and %i", m_sceneId.c_str(), m_maxCoordinate, maxCoordinate));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create all the proxies that would ever be needed, in a single pass
|
||||
*/
|
||||
void Scene::createAllProxies()
|
||||
{
|
||||
static int const subscriptionRange = ConfigPlanetServer::getMaxInterestRadius() + Node::getNodeSize(); // The logic in PlanetProxyObject effectively creates an overlap area of interestRadius + nodeSize, so don't change this without changing the logic in PlanetProxyObject
|
||||
|
||||
for (int x=-getMaxCoordinate(); x<= getMaxCoordinate(); x+=Node::getNodeSize())
|
||||
{
|
||||
for (int z=-getMaxCoordinate(); z<= getMaxCoordinate(); z+=Node::getNodeSize())
|
||||
{
|
||||
Node * const node = findNodeByRoundedPosition(x,z);
|
||||
uint32 serverId = NON_NULL(node)->getPreferredServer();
|
||||
|
||||
if (serverId!=0)
|
||||
{
|
||||
for (int subX=x-subscriptionRange; subX<= x+subscriptionRange; subX+=Node::getNodeSize())
|
||||
{
|
||||
for (int subZ=z-subscriptionRange; subZ<= z+subscriptionRange; subZ+=Node::getNodeSize())
|
||||
{
|
||||
NON_NULL(findNodeByRoundedPosition(subX, subZ))->subscribeServer(serverId, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Scene.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_Scene_H
|
||||
#define INCLUDED_Scene_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include <hash_map>
|
||||
#include <hash_set>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
#include "sharedFoundation/Timer.h"
|
||||
#include "sharedMessageDispatch/Receiver.h"
|
||||
#include "Singleton/Singleton2.h"
|
||||
#include "sharedMath/Vector.h"
|
||||
|
||||
class PlanetProxyObject;
|
||||
class PopulationList;
|
||||
class Node;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* Organizes all data on the Planet server relating to a particular scene.
|
||||
*/
|
||||
class Scene : public Singleton2<Scene>, public MessageDispatch::Receiver
|
||||
{
|
||||
public:
|
||||
// Some functions return lists of nodes
|
||||
typedef std::vector<Node*> NodeListType;
|
||||
|
||||
public:
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
public:
|
||||
virtual void receiveMessage (const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message);
|
||||
Node * findNodeByPosition (int x, int z);
|
||||
Node * findNodeByRoundedPosition (int x, int z);
|
||||
void addObject (PlanetProxyObject *newObject);
|
||||
void findIntersection (NodeListType &results,int x, int z, int radius);
|
||||
void assignPreloadsToNodes ();
|
||||
void loadAllNodesForServer (uint32 server, PreloadServerId preloadServerId);
|
||||
void checkServerAssignments ();
|
||||
void removeObjectFromMap (const NetworkId &objectId, bool addToDeletedList);
|
||||
void setSceneId (const std::string &sceneId);
|
||||
void subscribeServer (uint32 server, int x, int z, int interestRadius, int count=1);
|
||||
void update (float time);
|
||||
bool requestSameServer (const NetworkId &id1, const NetworkId &id2);
|
||||
bool requestAuthTransfer (const NetworkId &id1, uint32 newServer);
|
||||
void setMapSize (int mapSize);
|
||||
void createAllProxies ();
|
||||
|
||||
public:
|
||||
const Node * findNodeByPositionConst (int x, int z) const;
|
||||
const Node * findNodeByRoundedPositionConst (int x, int z) const;
|
||||
bool isObjectLoaded (const NetworkId &networkId) const;
|
||||
PlanetProxyObject * findObjectByID (const NetworkId &objectID) const;
|
||||
const std::string & getSceneId () const;
|
||||
uint32 getGameServerForObject (const NetworkId &object) const;
|
||||
void outputStatus (WatcherConnection &conn) const;
|
||||
int getServerPopulationByLocation (int x, int z) const;
|
||||
int getMaxCoordinate () const;
|
||||
|
||||
private:
|
||||
void handleRemoveObject (const NetworkId &objectId);
|
||||
void handleCrash (uint32 gameServerId);
|
||||
void handleForceLoadArea (uint32 gameServerId, int x1, int z1, int x2, int z2);
|
||||
|
||||
private:
|
||||
struct Coordinates
|
||||
{
|
||||
public:
|
||||
int m_x;
|
||||
int m_z;
|
||||
Coordinates(int x, int z);
|
||||
bool operator==(const Coordinates &rhs) const;
|
||||
|
||||
class Hasher
|
||||
{
|
||||
public:
|
||||
size_t operator()(const Coordinates &c) const;
|
||||
};
|
||||
|
||||
private:
|
||||
Coordinates();
|
||||
};
|
||||
|
||||
typedef std::hash_map<NetworkId, PlanetProxyObject*, NetworkId::Hash> ObjectMapType;
|
||||
typedef std::hash_set<NetworkId, NetworkId::Hash> DeletedSetType;
|
||||
typedef std::hash_map<Coordinates, Node*, Coordinates::Hasher> NodeMapType;
|
||||
|
||||
private:
|
||||
std::string m_sceneId;
|
||||
ObjectMapType m_objects;
|
||||
DeletedSetType m_deletedObjects;
|
||||
NodeMapType m_nodeMap;
|
||||
PopulationList * m_populationList;
|
||||
Timer m_populationCountTimer;
|
||||
int m_maxCoordinate;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline Scene::Coordinates::Coordinates(int x, int z) :
|
||||
m_x(x),
|
||||
m_z(z)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool Scene::Coordinates::operator==(const Coordinates &rhs) const
|
||||
{
|
||||
return ((m_x==rhs.m_x) && (m_z==rhs.m_z));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline size_t Scene::Coordinates::Hasher::operator()(const Coordinates &c) const
|
||||
{
|
||||
// will need to change this if we make planets bigger than 32k * 32k
|
||||
return (c.m_x<<16 | c.m_z); //lint !e701 shift left of signed
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const std::string &Scene::getSceneId() const
|
||||
{
|
||||
return m_sceneId;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
// TaskConnection.cpp
|
||||
// copyright 2000 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "serverNetworkMessages/TaskConnectionIdMessage.h"
|
||||
#include "serverNetworkMessages/TaskUtilization.h"
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
#include "sharedNetwork/NetworkSetupData.h"
|
||||
#include "TaskConnection.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TaskConnection::TaskConnection(const std::string & a, const unsigned short p) :
|
||||
ServerConnection(a, p, NetworkSetupData())
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TaskConnection::TaskConnection(UdpConnectionMT * u, TcpClient * t) :
|
||||
ServerConnection(u, t)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
TaskConnection::~TaskConnection()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void TaskConnection::onConnectionClosed()
|
||||
{
|
||||
static MessageConnectionCallback m("TaskConnectionClosed");
|
||||
emitMessage(m);
|
||||
PlanetServer::getInstance().setTaskManager(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void TaskConnection::onConnectionOpened()
|
||||
{
|
||||
PlanetServer::getInstance().setTaskManager(this);
|
||||
|
||||
// get cluster name
|
||||
std::string clusterName;
|
||||
ConfigFile::Section const * const sec = ConfigFile::getSection("TaskManager");
|
||||
if (sec)
|
||||
{
|
||||
ConfigFile::Key const * const ky = sec->findKey("clusterName");
|
||||
if (ky)
|
||||
{
|
||||
clusterName = ky->getAsString(ky->getCount()-1, "");
|
||||
}
|
||||
}
|
||||
|
||||
TaskConnectionIdMessage id(TaskConnectionIdMessage::Planet, "", clusterName);
|
||||
send(id, true);
|
||||
static MessageConnectionCallback m("TaskConnectionOpened");
|
||||
emitMessage(m);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void TaskConnection::onReceive(const Archive::ByteStream & message)
|
||||
{
|
||||
Archive::ReadIterator r(message);
|
||||
GameNetworkMessage m(r);
|
||||
if(m.isType("TaskUtilization"))
|
||||
{
|
||||
// generate utilization messages for the task manager
|
||||
TaskUtilization sysCpu(static_cast<int>(TaskUtilization::SYSTEM_CPU), 0.5f);
|
||||
TaskUtilization sysMem(static_cast<int>(TaskUtilization::SYSTEM_MEMORY), 0.5f);
|
||||
TaskUtilization sysNet(static_cast<int>(TaskUtilization::SYSTEM_NETWORK_IO), 50000.0f);
|
||||
TaskUtilization procCpu(static_cast<int>(TaskUtilization::PROCESS_CPU), 0.5f);
|
||||
TaskUtilization procMem(static_cast<int>(TaskUtilization::PROCESS_MEMORY), 0.5f);
|
||||
TaskUtilization procNet(static_cast<int>(TaskUtilization::PROCESS_NETWORK_IO), 50000.0f);
|
||||
|
||||
send(sysCpu, true);
|
||||
send(sysMem, true);
|
||||
send(sysNet, true);
|
||||
send(procCpu, true);
|
||||
send(procMem, true);
|
||||
send(procNet, true);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -0,0 +1,39 @@
|
||||
// TaskConnection.h
|
||||
// copyright 2001 Verant Interactive
|
||||
// Author: Justin Randall
|
||||
|
||||
#ifndef _TaskConnection_H
|
||||
#define _TaskConnection_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class TaskCommandChannel;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "serverUtility/ServerConnection.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
class TaskConnection : public ServerConnection
|
||||
{
|
||||
public:
|
||||
TaskConnection(const std::string & remoteAddress, const unsigned short remotePort);
|
||||
TaskConnection(UdpConnectionMT * u, TcpClient *);
|
||||
~TaskConnection();
|
||||
|
||||
void onConnectionClosed();
|
||||
void onConnectionOpened();
|
||||
void onReceive(const Archive::ByteStream & message);
|
||||
|
||||
private:
|
||||
TaskConnection(const TaskConnection&);
|
||||
TaskConnection& operator= (const TaskConnection&);
|
||||
TaskConnection();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#endif // _TaskConnection_H
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// WatcherConnection.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "WatcherConnection.h"
|
||||
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "sharedNetworkMessages/PlanetNodeStatusMessage.h"
|
||||
#include "sharedNetworkMessages/PlanetObjectStatusMessage.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
WatcherConnection::WatcherConnection(UdpConnectionMT * u, TcpClient * t) :
|
||||
ServerConnection(u, t),
|
||||
m_objectData(new ObjectDataList),
|
||||
m_nodeData(new NodeDataList)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
WatcherConnection::~WatcherConnection()
|
||||
{
|
||||
delete m_objectData;
|
||||
delete m_nodeData;
|
||||
m_objectData = 0;
|
||||
m_nodeData = 0;
|
||||
|
||||
} //lint !e1740 // thinks we didn't delete m_objectData and m_nodeData, but clearly we did
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void WatcherConnection::onConnectionClosed()
|
||||
{
|
||||
DEBUG_REPORT_LOG(true,("WatcherConnection closed.\n"));
|
||||
ServerConnection::onConnectionClosed();
|
||||
|
||||
static MessageConnectionCallback m("WatcherConnectionClosed");
|
||||
emitMessage(m);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void WatcherConnection::onConnectionOpened()
|
||||
{
|
||||
DEBUG_REPORT_LOG(true,("WatcherConnection opened.\n"));
|
||||
ServerConnection::onConnectionOpened();
|
||||
|
||||
static MessageConnectionCallback m("WatcherConnectionOpened");
|
||||
emitMessage(m);
|
||||
setOverflowLimit(ConfigPlanetServer::getWatcherOverflowLimit());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void WatcherConnection::addObjectUpdate(const NetworkId &objectId, int x, int z, uint32 authoritativeServer, int interestRadius, bool deleteObject, int objectTypeTag, int const level, bool const hibernating, uint32 const templateCrc, int const aiActivity, int const creationType)
|
||||
{
|
||||
NOT_NULL(m_objectData);
|
||||
m_objectData->push_back(PlanetObjectStatusMessageData(objectId, x,z, authoritativeServer, interestRadius, static_cast<int>(deleteObject), objectTypeTag, level, hibernating, templateCrc, aiActivity, creationType));
|
||||
|
||||
if (static_cast<int>(m_objectData->size()) > ConfigPlanetServer::getMaxWatcherUpdatesPerMessage())
|
||||
{
|
||||
flushQueuedObjectData();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void WatcherConnection::flushQueuedObjectData()
|
||||
{
|
||||
NOT_NULL(m_objectData);
|
||||
if (m_objectData->size() != 0)
|
||||
{
|
||||
PlanetObjectStatusMessage msg(*m_objectData);
|
||||
send(msg,true);
|
||||
m_objectData->clear();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void WatcherConnection::addNodeUpdate(int x, int z, bool loaded, const stdvector<uint32>::fwd &servers, const stdvector<int>::fwd &subscriptionCounts)
|
||||
{
|
||||
NOT_NULL(m_nodeData);
|
||||
m_nodeData->push_back(PlanetNodeStatusMessageData(x,z,loaded,servers,subscriptionCounts));
|
||||
|
||||
if (static_cast<int>(m_objectData->size()) > ConfigPlanetServer::getMaxWatcherUpdatesPerMessage())
|
||||
{
|
||||
flushQueuedNodeData();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void WatcherConnection::flushQueuedNodeData()
|
||||
{
|
||||
NOT_NULL(m_nodeData);
|
||||
if (m_nodeData->size() != 0)
|
||||
{
|
||||
PlanetNodeStatusMessage msg(*m_nodeData);
|
||||
send(msg,true);
|
||||
m_nodeData->clear();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -0,0 +1,59 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// WatcherConnection.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_WatcherConnection_H
|
||||
#define INCLUDED_WatcherConnection_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "serverUtility/ServerConnection.h"
|
||||
|
||||
class PlanetObjectStatusMessageData;
|
||||
class PlanetNodeStatusMessageData;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class WatcherConnection : public ServerConnection
|
||||
{
|
||||
public:
|
||||
WatcherConnection(UdpConnectionMT *, TcpClient *);
|
||||
~WatcherConnection();
|
||||
void onConnectionClosed ();
|
||||
void onConnectionOpened ();
|
||||
|
||||
void addObjectUpdate (const NetworkId &objectId, int x, int z, uint32 authoritativeServer, int interestRadius, bool deleteObject, int objectTypeTag, int level, bool hibernating, uint32 templateCrc, int aiActivity, int creationType);
|
||||
void addNodeUpdate (int x, int z, bool loaded, const stdvector<uint32>::fwd &servers, const stdvector<int>::fwd &subscriptionCounts);
|
||||
void flushQueuedData ();
|
||||
|
||||
private:
|
||||
void flushQueuedObjectData();
|
||||
void flushQueuedNodeData();
|
||||
|
||||
private:
|
||||
typedef stdvector<PlanetObjectStatusMessageData>::fwd ObjectDataList;
|
||||
ObjectDataList *m_objectData;
|
||||
|
||||
typedef stdvector<PlanetNodeStatusMessageData>::fwd NodeDataList;
|
||||
NodeDataList *m_nodeData;
|
||||
|
||||
private:
|
||||
WatcherConnection (const WatcherConnection&);
|
||||
WatcherConnection& operator= (const WatcherConnection&);
|
||||
WatcherConnection();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void WatcherConnection::flushQueuedData()
|
||||
{
|
||||
flushQueuedObjectData();
|
||||
flushQueuedNodeData();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstPlanetServer.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstPlanetServer.h"
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "FirstPlanetServer.h"
|
||||
#include "ConfigPlanetServer.h"
|
||||
#include "PlanetServer.h"
|
||||
|
||||
#include "sharedCompression/SetupSharedCompression.h"
|
||||
#include "sharedDebug/SetupSharedDebug.h"
|
||||
#include "sharedFile/SetupSharedFile.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedFoundation/SetupSharedFoundation.h"
|
||||
#include "sharedLog/SetupSharedLog.h"
|
||||
#include "sharedNetwork/SetupSharedNetwork.h"
|
||||
#include "sharedNetworkMessages/SetupSharedNetworkMessages.h"
|
||||
#include "sharedRandom/SetupSharedRandom.h"
|
||||
#include "sharedThread/SetupSharedThread.h"
|
||||
#include "sharedUtility/SetupSharedUtility.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
//_____________________________________________________________________
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
SetupSharedThread::install();
|
||||
SetupSharedDebug::install(1024);
|
||||
|
||||
//-- setup foundation
|
||||
SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game);
|
||||
|
||||
setupFoundationData.argc = argc;
|
||||
setupFoundationData.argv = argv;
|
||||
setupFoundationData.createWindow = false;
|
||||
setupFoundationData.clockUsesSleep = true;
|
||||
|
||||
SetupSharedFoundation::install (setupFoundationData);
|
||||
|
||||
SetupSharedCompression::install();
|
||||
SetupSharedFile::install(false);
|
||||
|
||||
SetupSharedNetwork::SetupData networkSetupData;
|
||||
SetupSharedNetwork::getDefaultServerSetupData(networkSetupData);
|
||||
SetupSharedNetwork::install(networkSetupData);
|
||||
|
||||
SetupSharedNetworkMessages::install();
|
||||
|
||||
SetupSharedRandom::install(int(time(NULL)));
|
||||
|
||||
SetupSharedUtility::Data sharedUtilityData;
|
||||
SetupSharedUtility::setupGameData (sharedUtilityData);
|
||||
SetupSharedUtility::install (sharedUtilityData);
|
||||
|
||||
//-- setup server
|
||||
ConfigPlanetServer::install ();
|
||||
|
||||
char tmp[92];
|
||||
sprintf(tmp, "PlanetServer:%d", Os::getProcessId());
|
||||
SetupSharedLog::install(tmp);
|
||||
|
||||
//-- run server
|
||||
SetupSharedFoundation::callbackWithExceptionHandling(PlanetServer::run);
|
||||
|
||||
SetupSharedLog::remove();
|
||||
SetupSharedFoundation::remove();
|
||||
SetupSharedThread::remove();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________
|
||||
Reference in New Issue
Block a user