From 7eadf64a81388175e978044483e1b38fba03bfba Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Mon, 31 May 2021 23:49:10 -0400 Subject: [PATCH 01/24] Add Proxy and Unv Process Console Commands --- .../console/ConsoleCommandParserObject.cpp | 16 ++++++++++++++++ .../console/ConsoleCommandParserServer.cpp | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp index 9ae54ff5..dc2fd5f0 100755 --- a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp +++ b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserObject.cpp @@ -475,6 +475,7 @@ static const CommandParser::CmdInfo cmds[] = {"reloadSwgTcgAccountFeatureId", 1, "", "Retrieve the SWG TCG account feature Ids for the specified character"}, {"unloadBuildingContents", 1, "", "Unload the contents of a player-placed authoritative demand-loaded building"}, {"isOnSolidFloor", 1, "", "Checks to see if the specified object is \"on solid floor\""}, + {"proxyToAllGameServers", 1, "", "Creates a Proxy of the given object on all Game Servers."}, {"", 0, "", ""} // this must be last }; @@ -4204,6 +4205,21 @@ bool ConsoleCommandParserObject::performParsing2(const NetworkId & userId, const // ---------------------------------------------------------------------- + else if (isAbbrev(argv[0], "proxyToAllGameServers")) + { + NetworkId const oid(Unicode::wideToNarrow(argv[1])); + auto * const object = dynamic_cast(NetworkIdManager::getObjectById(oid)); + GameServer &gs = GameServer::getInstance(); + if(object) { + gs.createProxyOnAllServers(object); + result += getErrorMessage(argv[0], ERR_SUCCESS); + } else { + result += getErrorMessage(argv[0], ERR_FAIL); + } + } + + // ---------------------------------------------------------------------- + else { result += getErrorMessage(argv[0], ERR_NO_HANDLER); diff --git a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserServer.cpp b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserServer.cpp index 63d8fb1d..e0558251 100755 --- a/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserServer.cpp +++ b/engine/server/library/serverGame/src/shared/console/ConsoleCommandParserServer.cpp @@ -195,6 +195,7 @@ static const CommandParser::CmdInfo cmds[] = {"getCommoditiesAuctionLocationPriorityQueue", 1, "", "Gets the top items in the auction location priority queue"}, {"getCommoditiesItemTypeMap", 1, "", "For the specified game object type, gets the list of item type"}, {"setCompletedTutorial", 1, "", "Mark the account belonging to the specified character (character does not have to be logged in) as having completed the tutorial, so that the skip tutorial option will be available during character creation for that account"}, + {"getUniverseProcess", 0, "", "Returns the Game Server Universe Process ID"}, #ifdef _DEBUG {"setExtraDelayPerFrameMs", 1, "", "Do an intentional sleep each frame, to emulate long loop time"}, {"serverinfo", 0, "", "Serverinformation"}, @@ -3449,6 +3450,11 @@ bool ConsoleCommandParserServer::performParsing2(const NetworkId & userId, const result += Unicode::narrowToWide(FormattedString<512>().sprintf("There is no character on this galaxy with id (%s)\n", oid.getValueString().c_str())); } } + else if (isAbbrev(argv[0], "getUniverseProcess")) + { + result += Unicode::narrowToWide(FormattedString<512>().sprintf("Universe Process ID is: %d\n", ServerUniverse::getInstance().getUniverseProcess())); + result += getErrorMessage(argv[0], ERR_SUCCESS); + } #ifdef _DEBUG else if (isAbbrev(argv[0], "setExtraDelayPerFrameMs")) { From 31eb505151034ffec68195518b0ec2ccbea36d5d Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Tue, 1 Jun 2021 05:27:47 -0400 Subject: [PATCH 02/24] Add Support for Custom Universe Objects --- .../src/shared/core/ConfigServerGame.cpp | 2 +- .../src/shared/core/ServerUniverse.cpp | 255 +++++++++++------- .../src/shared/core/ServerUniverse.h | 4 + .../src/shared/ScriptMethodsObjectCreate.cpp | 15 ++ 4 files changed, 173 insertions(+), 103 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp index 219b08f6..58f1e43e 100755 --- a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp +++ b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp @@ -312,7 +312,7 @@ void ConfigServerGame::install(void) KEY_BOOL (exceptionOnObjVarZeroLengthArray, false); KEY_BOOL (trackNonAuthoritativeObjvarSets, false); KEY_FLOAT (triggerVolumeWarpDistance, 128.0f); - KEY_NETWORKID(maxGoldNetworkId, "0"); + KEY_NETWORKID(maxGoldNetworkId, "10000000"); // should match ConfigServerDatabase setting KEY_BOOL (fatalOnMovingGoldObject, false); KEY_INT (spatialChatLogMinutes, 5); KEY_FLOAT (behaviorMaxAvoidanceStuckTime, 10.0f); diff --git a/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp b/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp index 8878ba49..efcf4464 100755 --- a/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp +++ b/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp @@ -41,7 +41,7 @@ namespace ServerUniverseNamespace const Tag TAG_PLTS = TAG (P,L,T,S); const Tag TAG_PLNT = TAG (P,L,N,T); - std::string s_emptyString = ""; + std::string s_emptyString; } using namespace ServerUniverseNamespace; @@ -79,7 +79,8 @@ ServerUniverse::ServerUniverse() : m_populationList (new PopulationList), m_pendingProxyRequests (), m_pendingUniverseLoadedAckList(), - m_timeUniverseDataSent (0) + m_timeUniverseDataSent (0), + m_customUniverseObjects() { } @@ -87,9 +88,13 @@ ServerUniverse::ServerUniverse() : ServerUniverse::~ServerUniverse() { - for (UniverseObjectList::const_iterator j=m_universeObjectList->begin(); j!=m_universeObjectList->end(); ++j) - delete *j; - + for (auto j : *m_universeObjectList) { + delete j; + } + for (auto j : m_customUniverseObjects) { + delete j; + } + delete m_pendingUniverseObjects; delete m_planetNameMap; delete m_resourceTypeNameMap; @@ -101,28 +106,28 @@ ServerUniverse::~ServerUniverse() delete m_theaterNameIdMap; delete m_theaterIdNameMap; - m_pendingUniverseObjects =0; - m_planetNameMap=0; - m_resourceTreeRoot=0; - m_resourceTypeNameMap=0; - m_resourceTypeIdMap=0; - m_importedResourceTypeIdMap=0; - m_resourcesToSend=0; - m_universeObjectList = 0; - m_populationList = 0; - m_thisPlanet = 0; - m_tatooinePlanet = 0; - m_masterGuildObject = 0; - m_masterCityObject = 0; - m_theaterNameIdMap = 0; - m_theaterIdNameMap = 0; + m_pendingUniverseObjects = nullptr; + m_planetNameMap = nullptr; + m_resourceTreeRoot = nullptr; + m_resourceTypeNameMap = nullptr; + m_resourceTypeIdMap = nullptr; + m_importedResourceTypeIdMap = nullptr; + m_resourcesToSend = nullptr; + m_universeObjectList = nullptr; + m_populationList = nullptr; + m_thisPlanet = nullptr; + m_tatooinePlanet = nullptr; + m_masterGuildObject = nullptr; + m_masterCityObject = nullptr; + m_theaterNameIdMap = nullptr; + m_theaterIdNameMap = nullptr; } // ---------------------------------------------------------------------- PlanetObject *ServerUniverse::getPlanetByName(const std::string &sceneId) const { - PlanetNameMap::iterator i=m_planetNameMap->find(sceneId); + auto i=m_planetNameMap->find(sceneId); if (i!=m_planetNameMap->end()) { return (*i).second; @@ -140,7 +145,7 @@ PlanetObject *ServerUniverse::getPlanetByName(const std::string &sceneId) const ResourceTypeObject *ServerUniverse::getResourceTypeByName(std::string const & name) const { - ResourceTypeNameMap::iterator i=m_resourceTypeNameMap->find(name); + auto i=m_resourceTypeNameMap->find(name); if (i!=m_resourceTypeNameMap->end()) return (*i).second; else @@ -156,7 +161,7 @@ ResourceTypeObject * ServerUniverse::getResourceTypeById(NetworkId const & id) c if (id.getValue() <= NetworkId::cms_maxNetworkIdWithoutClusterId) { - ResourceTypeIdMap::const_iterator i=m_resourceTypeIdMap->find(id); + auto i=m_resourceTypeIdMap->find(id); if (i!=m_resourceTypeIdMap->end()) return (*i).second; else @@ -164,7 +169,7 @@ ResourceTypeObject * ServerUniverse::getResourceTypeById(NetworkId const & id) c } else { - ResourceTypeIdMap::const_iterator i=m_importedResourceTypeIdMap->find(id); + auto i=m_importedResourceTypeIdMap->find(id); if (i!=m_importedResourceTypeIdMap->end()) return (*i).second; else @@ -179,7 +184,7 @@ ResourceTypeObject * ServerUniverse::getImportedResourceTypeById(NetworkId const if (id==NetworkId::cms_invalid) return nullptr; - ResourceTypeIdMap::const_iterator i=m_importedResourceTypeIdMap->find(id); + auto i=m_importedResourceTypeIdMap->find(id); if (i!=m_importedResourceTypeIdMap->end()) return (*i).second; else @@ -262,6 +267,18 @@ void ServerUniverse::addUniverseObject(UniverseObject &newObject) // ---------------------------------------------------------------------- +/** + * Adds a ServerObject as a pseudo-Universe Object for proxy-purposes + * such that it has the effect of being a Universe Object + */ +void ServerUniverse::addCustomUniverseObject(ServerObject &newObject) +{ + m_customUniverseObjects.push_back(&newObject); + GameServer::getInstance().createProxyOnAllServers(&newObject); +} + +// ---------------------------------------------------------------------- + /** * Give a new server proxies of all of the universe objects. */ @@ -275,36 +292,40 @@ void ServerUniverse::createProxiesOnServer(std::vector const & remotePro NameManager::getInstance().sendAllNamesToServer(remoteProcesses); // So are attrib mod names AttribModNameManager::getInstance().sendAllNamesToServer(remoteProcesses); - - { - for (std::vector::const_iterator remoteProcessId=remoteProcesses.begin(); remoteProcessId!=remoteProcesses.end(); ++remoteProcessId) - { - for (UniverseObjectList::const_iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) - { - if ((*i)->getObject()) - GameServer::getInstance().createRemoteProxy(*remoteProcessId, safe_cast((*i)->getObject())); - else - DEBUG_REPORT_LOG(true,("Not proxying Universe Object %s because it has been deleted.\n",(*i)->getValueString().c_str())); - } - } - } + for (unsigned long remoteProcess : remoteProcesses) + { + for (auto i : *m_universeObjectList) + { + if (i->getObject()) + { + GameServer::getInstance().createRemoteProxy(remoteProcess, safe_cast(i->getObject())); + } + else + { + DEBUG_REPORT_LOG(true,("Not proxying Universe Object %s because it has been deleted.\n", i->getValueString().c_str())); + } + for (auto &m_customUniverseObject : m_customUniverseObjects) + { + GameServer::getInstance().createRemoteProxy(remoteProcess, m_customUniverseObject); + } + } + } ServerMessageForwarding::begin(remoteProcesses); - { - std::vector resourceTypeDataVector; - AddResourceTypeMessageNamespace::ResourceTypeData resourceTypeData; - resourceTypeDataVector.reserve(m_resourceTypeIdMap->size()); - - for (ResourceTypeIdMap::const_iterator i=m_resourceTypeIdMap->begin(); i!=m_resourceTypeIdMap->end(); ++i) - { - NON_NULL(i->second)->getDataForMessage(resourceTypeData); - resourceTypeDataVector.push_back(resourceTypeData); - } - AddResourceTypeMessage const addResourceTypeMessage(resourceTypeDataVector); - ServerMessageForwarding::send(addResourceTypeMessage); + std::vector resourceTypeDataVector; + AddResourceTypeMessageNamespace::ResourceTypeData resourceTypeData; + resourceTypeDataVector.reserve(m_resourceTypeIdMap->size()); + + for (auto i=m_resourceTypeIdMap->begin(); i!=m_resourceTypeIdMap->end(); ++i) + { + NON_NULL(i->second)->getDataForMessage(resourceTypeData); + resourceTypeDataVector.push_back(resourceTypeData); } + + AddResourceTypeMessage const addResourceTypeMessage(resourceTypeDataVector); + ServerMessageForwarding::send(addResourceTypeMessage); GenericValueTypeMessage const universeCompleteMessage("UniverseCompleteMessage", GameServer::getInstance().getProcessId()); ServerMessageForwarding::send(universeCompleteMessage); @@ -315,13 +336,16 @@ void ServerUniverse::createProxiesOnServer(std::vector const & remotePro { std::string serverListAsString; char oneServer[10]; - for (std::vector::const_iterator i=remoteProcesses.begin(); i!=remoteProcesses.end(); ++i) + for (auto i=remoteProcesses.begin(); i!=remoteProcesses.end(); ++i) { if (ConfigServerGame::getTimeoutToAckUniverseDataReceived() > 0) - IGNORE_RETURN(m_pendingUniverseLoadedAckList.insert(*i)); - + { + IGNORE_RETURN(m_pendingUniverseLoadedAckList.insert(*i)); + } if (i!=remoteProcesses.begin()) - serverListAsString+=", "; + { + serverListAsString+=", "; + } snprintf(oneServer,sizeof(oneServer)-1,"%lu",*i); oneServer[sizeof(oneServer)-1] = '\0'; serverListAsString+=oneServer; @@ -329,13 +353,17 @@ void ServerUniverse::createProxiesOnServer(std::vector const & remotePro LOG("UniverseLoading", ("Game Server %lu sent UniverseComplete to Game Servers %s.", GameServer::getInstance().getProcessId(), serverListAsString.c_str())); if (ConfigServerGame::getTimeoutToAckUniverseDataReceived() > 0) - m_timeUniverseDataSent = ::time(nullptr); + { + m_timeUniverseDataSent = ::time(nullptr); + } } } else { if (!remoteProcesses.empty()) - IGNORE_RETURN(m_pendingProxyRequests.insert(remoteProcesses.begin(),remoteProcesses.end())); + { + IGNORE_RETURN(m_pendingProxyRequests.insert(remoteProcesses.begin(),remoteProcesses.end())); + } } } @@ -358,11 +386,13 @@ void ServerUniverse::setUniverseProcess(uint32 processId) if (processId==GameServer::getInstance().getProcessId()) { - for (UniverseObjectList::iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) + for (auto & i : *m_universeObjectList) { - ServerObject *obj=safe_cast((*i)->getObject()); + auto *obj=safe_cast(i->getObject()); if (obj) - obj->setAuthority(); + { + obj->setAuthority(); + } } m_authoritative=true; @@ -370,22 +400,25 @@ void ServerUniverse::setUniverseProcess(uint32 processId) m_nextCheckTimer.reset(); // let all universe objects know that we have gained authority for universe objects - for (UniverseObjectList::iterator j=m_universeObjectList->begin(); j!=m_universeObjectList->end(); ++j) + for (auto & j : *m_universeObjectList) { - UniverseObject *obj=safe_cast((*j)->getObject()); + auto *obj=safe_cast(j->getObject()); if (obj) - obj->onServerUniverseGainedAuthority(); + { + obj->onServerUniverseGainedAuthority(); + } } } else { - for (UniverseObjectList::iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) + for (auto & i : *m_universeObjectList) { - ServerObject *obj=safe_cast((*i)->getObject()); + auto *obj=safe_cast(i->getObject()); if (obj && obj->isAuthoritative()) - obj->releaseAuthority(processId); + { + obj->releaseAuthority(processId); + } } - m_authoritative=false; } } @@ -443,19 +476,19 @@ void ServerUniverse::universeComplete(uint32 sourceServer) m_loaded=true; { - for (UniverseObjectList::iterator i=m_pendingUniverseObjects->begin(); i!=m_pendingUniverseObjects->end(); ++i) + for (auto & m_pendingUniverseObject : *m_pendingUniverseObjects) { - UniverseObject *obj=safe_cast((*i)->getObject()); + auto *obj=safe_cast(m_pendingUniverseObject->getObject()); if (obj) { - m_universeObjectList->push_back(*i); + m_universeObjectList->push_back(m_pendingUniverseObject); obj->setupUniverse(); } else { - DEBUG_REPORT_LOG(true,("Pending Universe Object %s was deleted.\n",(*i)->getValueString().c_str())); - delete *i; - *i=0; + DEBUG_REPORT_LOG(true,("Pending Universe Object %s was deleted.\n",m_pendingUniverseObject->getValueString().c_str())); + delete m_pendingUniverseObject; + m_pendingUniverseObject=0; } } } @@ -503,7 +536,7 @@ CityObject *ServerUniverse::getMasterCityObject() */ void ServerUniverse::renameResourceType (const std::string &oldname, const std::string &newname) { - ResourceTypeNameMap::iterator i=m_resourceTypeNameMap->find(oldname); + auto i=m_resourceTypeNameMap->find(oldname); if (i!=m_resourceTypeNameMap->end()) { ResourceTypeObject *theObj=(*i).second; @@ -556,7 +589,7 @@ void ServerUniverse::updateAndValidateData() if (!m_masterGuildObject) { FATAL(!ConfigServerGame::getAllowMasterObjectCreation(), ("Master guild object was not found!")); - ServerObjectTemplate const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/guild/guild.iff")); + auto const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/guild/guild.iff")); m_masterGuildObject = safe_cast(ServerWorld::createNewObject(*objTemplate, Transform::identity, 0, true)); m_masterGuildObject->addToWorld(); } @@ -565,7 +598,7 @@ void ServerUniverse::updateAndValidateData() if (!m_masterCityObject) { FATAL(!ConfigServerGame::getAllowMasterObjectCreation(), ("Master city object was not found!")); - ServerObjectTemplate const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/city/city.iff")); + auto const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/city/city.iff")); m_masterCityObject = safe_cast(ServerWorld::createNewObject(*objTemplate, Transform::identity, 0, true)); m_masterCityObject->addToWorld(); } @@ -616,7 +649,7 @@ void ServerUniverse::updateAndValidateData() } //Spawn resources - ServerResourceClassObject *root=safe_cast(getResourceTreeRoot()); + auto *root=safe_cast(getResourceTreeRoot()); if (root) { root->checkRanges(); @@ -625,9 +658,9 @@ void ServerUniverse::updateAndValidateData() } //trigger scripts - for (UniverseObjectList::iterator j = m_universeObjectList->begin(); j != m_universeObjectList->end(); ++j) + for (auto & j : *m_universeObjectList) { - UniverseObject *obj=safe_cast((*j)->getObject()); + auto *obj=safe_cast(j->getObject()); if (obj) { ScriptParams params; @@ -646,14 +679,19 @@ ResourceTypeObject const * ServerUniverse::pickRandomNonDepletedResource(const s { ResourceClassObject *parentClass = getResourceClassByName(parentResourceClassName); if (!parentClass) - return 0; - + { + return 0; + } std::vector possibleTypes; if (!getCurrentPlanet()) - return 0; + { + return 0; + } getCurrentPlanet()->getAvailableResourceList(possibleTypes,*parentClass); - if (possibleTypes.size() == 0) - return 0; + if (possibleTypes.empty()) + { + return 0; + } int choice = Random::random(static_cast(possibleTypes.size())-1); return possibleTypes[static_cast(choice)]; } @@ -682,12 +720,18 @@ void ServerUniverse::onServerConnectionClosed(uint32 processId) if (m_authoritative) { // remove proxies on the crashed server - for (UniverseObjectList::iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) + for (auto & i : *m_universeObjectList) { - ServerObject *obj=safe_cast((*i)->getObject()); + auto *obj=safe_cast(i->getObject()); if (obj) - obj->removeServerFromProxyList(processId); - } + { + obj->removeServerFromProxyList(processId); + } + } + for (auto &m_customUniverseObject : m_customUniverseObjects) + { + m_customUniverseObject->removeServerFromProxyList(processId); + } } } @@ -734,10 +778,12 @@ void ServerUniverse::update(float frameTime) { std::string serverListAsString; char oneServer[10]; - for (PendingUniverseLoadedAckList::const_iterator i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) + for (auto i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) { if (i!=m_pendingUniverseLoadedAckList.begin()) - serverListAsString+=", "; + { + serverListAsString+=", "; + } snprintf(oneServer,sizeof(oneServer)-1,"%lu",*i); oneServer[sizeof(oneServer)-1] = '\0'; serverListAsString+=oneServer; @@ -755,10 +801,12 @@ void ServerUniverse::update(float frameTime) { std::string serverListAsString; char oneServer[10]; - for (PendingUniverseLoadedAckList::const_iterator i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) + for (auto i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) { if (i!=m_pendingUniverseLoadedAckList.begin()) - serverListAsString+=", "; + { + serverListAsString+=", "; + } snprintf(oneServer,sizeof(oneServer)-1,"%lu",*i); oneServer[sizeof(oneServer)-1] = '\0'; serverListAsString+=oneServer; @@ -783,9 +831,10 @@ void ServerUniverse::update(float frameTime) m_pendingProxyRequests.erase(iter); --maxGameServerToSendUniverseData; } - if (!servers.empty()) - createProxiesOnServer(servers); + { + createProxiesOnServer(servers); + } } if (m_nextCheckTimer.updateZero(frameTime) || m_doImmediateCheck || !m_resourcesToSend->empty()) @@ -803,9 +852,9 @@ void ServerUniverse::update(float frameTime) AddResourceTypeMessageNamespace::ResourceTypeData resourceTypeData; resourceTypeDataVector.reserve(m_resourcesToSend->size()); - for (ResourcesToSendType::const_iterator i=m_resourcesToSend->begin(); i!=m_resourcesToSend->end(); ++i) + for (auto i : *m_resourcesToSend) { - NON_NULL(*i)->getDataForMessage(resourceTypeData); + NON_NULL(i)->getDataForMessage(resourceTypeData); resourceTypeDataVector.push_back(resourceTypeData); } @@ -839,15 +888,15 @@ void ServerUniverse::handleAddResourceTypeMessage(AddResourceTypeMessage const & typedef std::vector DataVectorType; DataVectorType const & data = message.getData(); - for (DataVectorType::const_iterator i=data.begin(); i!=data.end(); ++i) + for (auto i=data.begin(); i!=data.end(); ++i) { - ServerResourceClassObject * const parentClass = safe_cast(getResourceClassByName(i->m_parentClass)); + auto * const parentClass = safe_cast(getResourceClassByName(i->m_parentClass)); if (parentClass) { ResourceTypeObject * const existingType = getResourceTypeById(i->m_networkId); if (!existingType) { - ResourceTypeObject * const newType = new ResourceTypeObject(*i, *parentClass); + auto * const newType = new ResourceTypeObject(*i, *parentClass); registerResourceTypeObject(*newType, false); parentClass->addType(*newType); } //lint !e429 // didn't delete newType (registerResourceTypeObject keeps a pointer to it) @@ -869,7 +918,7 @@ const NetworkId & ServerUniverse::findTheaterId(const std::string & name) if (m_theaterNameIdMap == nullptr) return NetworkId::cms_invalid; - TheaterNameIdMap::const_iterator result = m_theaterNameIdMap->find(name); + auto result = m_theaterNameIdMap->find(name); if (result == m_theaterNameIdMap->end()) return NetworkId::cms_invalid; @@ -885,7 +934,7 @@ static const std::string emptyString; if (m_theaterIdNameMap == nullptr) return emptyString; - TheaterIdNameMap::const_iterator result = m_theaterIdNameMap->find(id); + auto result = m_theaterIdNameMap->find(id); if (result == m_theaterIdNameMap->end()) return emptyString; @@ -1010,9 +1059,11 @@ bool ServerUniverse::manualDepleteResource(NetworkId const & resourceToDeplete) if (isAuthoritative()) { resType->deplete(); - ServerResourceClassObject *root=safe_cast(getResourceTreeRoot()); + auto *root=safe_cast(getResourceTreeRoot()); if (root) - root->spawnAsNeeded(); + { + root->spawnAsNeeded(); + } m_doImmediateCheck=true; } else diff --git a/engine/server/library/serverGame/src/shared/core/ServerUniverse.h b/engine/server/library/serverGame/src/shared/core/ServerUniverse.h index 667a63a0..01bc5319 100755 --- a/engine/server/library/serverGame/src/shared/core/ServerUniverse.h +++ b/engine/server/library/serverGame/src/shared/core/ServerUniverse.h @@ -124,6 +124,8 @@ public: static void removeUniverseEvent(std::string const & eventName); static std::string const & getCurrentEvents(); + void addCustomUniverseObject(ServerObject &newObject); + protected: virtual void updateAndValidateData (); @@ -144,6 +146,8 @@ private: uint32 m_universeProcess; Timer m_nextCheckTimer; bool m_doImmediateCheck; + + std::vector m_customUniverseObjects; // // Planet Objects diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp index 25b4382a..f59d32da 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp @@ -113,6 +113,7 @@ namespace ScriptMethodsObjectCreateNamespace jlong JNICALL createNewObjectTransformInternal(JNIEnv *env, jobject self, jstring templateName, jobject transform, jlong cell, bool hyperspace = false); jlong JNICALL createNewObjectTransformCrcInternal(JNIEnv *env, jobject self, jint templateCrc, jobject transform, jlong cell, bool hyperspace = false); jboolean JNICALL updateNetworkTriggerVolume(JNIEnv *env, jobject self, jlong target, jfloat radius); + void JNICALL registerObjectToUniverse(JNIEnv *env, jobject self, jlong target); } @@ -165,6 +166,7 @@ const JNINativeMethod NATIVES[] = { JF("_createObjectHyperspace", "(Ljava/lang/String;Lscript/transform;J)J", createNewObjectTransformHyperspace), JF("_createObjectHyperspace", "(ILscript/transform;J)J", createNewObjectTransformCrcHyperspace), JF("_updateNetworkTriggerVolume", "(JF)Z", updateNetworkTriggerVolume), + JF("_registerObjectToUniverse", "(J)V", registerObjectToUniverse), }; return JavaLibrary::registerNatives(NATIVES, sizeof(NATIVES)/sizeof(NATIVES[0])); @@ -2270,5 +2272,18 @@ jboolean JNICALL ScriptMethodsObjectCreateNamespace::updateNetworkTriggerVolume( return JNI_TRUE; } + +// ---------------------------------------------------------------------- + +void JNICALL ScriptMethodsObjectCreateNamespace::registerObjectToUniverse(JNIEnv *env, jobject self, jlong target) +{ + ServerObject * object = nullptr; + if (!JavaLibrary::getObject(target, object)) + { + WARNING(true, ("Invalid Object passed to ::registerObjectToUniverse().")); + return; + } + ServerUniverse::getInstance().addCustomUniverseObject(*object); +} // ====================================================================== From d8f4b549cb00e81a12c20b130f673cbd467f4518 Mon Sep 17 00:00:00 2001 From: AconiteGodOfSWG Date: Tue, 1 Jun 2021 19:09:31 -0400 Subject: [PATCH 03/24] Revert "Add Support for Custom Universe Objects" This reverts commit 31eb505151034ffec68195518b0ec2ccbea36d5d. --- .../src/shared/core/ConfigServerGame.cpp | 2 +- .../src/shared/core/ServerUniverse.cpp | 259 +++++++----------- .../src/shared/core/ServerUniverse.h | 4 - .../src/shared/ScriptMethodsObjectCreate.cpp | 15 - 4 files changed, 105 insertions(+), 175 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp index 58f1e43e..219b08f6 100755 --- a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp +++ b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp @@ -312,7 +312,7 @@ void ConfigServerGame::install(void) KEY_BOOL (exceptionOnObjVarZeroLengthArray, false); KEY_BOOL (trackNonAuthoritativeObjvarSets, false); KEY_FLOAT (triggerVolumeWarpDistance, 128.0f); - KEY_NETWORKID(maxGoldNetworkId, "10000000"); // should match ConfigServerDatabase setting + KEY_NETWORKID(maxGoldNetworkId, "0"); KEY_BOOL (fatalOnMovingGoldObject, false); KEY_INT (spatialChatLogMinutes, 5); KEY_FLOAT (behaviorMaxAvoidanceStuckTime, 10.0f); diff --git a/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp b/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp index efcf4464..8878ba49 100755 --- a/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp +++ b/engine/server/library/serverGame/src/shared/core/ServerUniverse.cpp @@ -41,7 +41,7 @@ namespace ServerUniverseNamespace const Tag TAG_PLTS = TAG (P,L,T,S); const Tag TAG_PLNT = TAG (P,L,N,T); - std::string s_emptyString; + std::string s_emptyString = ""; } using namespace ServerUniverseNamespace; @@ -79,8 +79,7 @@ ServerUniverse::ServerUniverse() : m_populationList (new PopulationList), m_pendingProxyRequests (), m_pendingUniverseLoadedAckList(), - m_timeUniverseDataSent (0), - m_customUniverseObjects() + m_timeUniverseDataSent (0) { } @@ -88,13 +87,9 @@ ServerUniverse::ServerUniverse() : ServerUniverse::~ServerUniverse() { - for (auto j : *m_universeObjectList) { - delete j; - } - for (auto j : m_customUniverseObjects) { - delete j; - } - + for (UniverseObjectList::const_iterator j=m_universeObjectList->begin(); j!=m_universeObjectList->end(); ++j) + delete *j; + delete m_pendingUniverseObjects; delete m_planetNameMap; delete m_resourceTypeNameMap; @@ -106,28 +101,28 @@ ServerUniverse::~ServerUniverse() delete m_theaterNameIdMap; delete m_theaterIdNameMap; - m_pendingUniverseObjects = nullptr; - m_planetNameMap = nullptr; - m_resourceTreeRoot = nullptr; - m_resourceTypeNameMap = nullptr; - m_resourceTypeIdMap = nullptr; - m_importedResourceTypeIdMap = nullptr; - m_resourcesToSend = nullptr; - m_universeObjectList = nullptr; - m_populationList = nullptr; - m_thisPlanet = nullptr; - m_tatooinePlanet = nullptr; - m_masterGuildObject = nullptr; - m_masterCityObject = nullptr; - m_theaterNameIdMap = nullptr; - m_theaterIdNameMap = nullptr; + m_pendingUniverseObjects =0; + m_planetNameMap=0; + m_resourceTreeRoot=0; + m_resourceTypeNameMap=0; + m_resourceTypeIdMap=0; + m_importedResourceTypeIdMap=0; + m_resourcesToSend=0; + m_universeObjectList = 0; + m_populationList = 0; + m_thisPlanet = 0; + m_tatooinePlanet = 0; + m_masterGuildObject = 0; + m_masterCityObject = 0; + m_theaterNameIdMap = 0; + m_theaterIdNameMap = 0; } // ---------------------------------------------------------------------- PlanetObject *ServerUniverse::getPlanetByName(const std::string &sceneId) const { - auto i=m_planetNameMap->find(sceneId); + PlanetNameMap::iterator i=m_planetNameMap->find(sceneId); if (i!=m_planetNameMap->end()) { return (*i).second; @@ -145,7 +140,7 @@ PlanetObject *ServerUniverse::getPlanetByName(const std::string &sceneId) const ResourceTypeObject *ServerUniverse::getResourceTypeByName(std::string const & name) const { - auto i=m_resourceTypeNameMap->find(name); + ResourceTypeNameMap::iterator i=m_resourceTypeNameMap->find(name); if (i!=m_resourceTypeNameMap->end()) return (*i).second; else @@ -161,7 +156,7 @@ ResourceTypeObject * ServerUniverse::getResourceTypeById(NetworkId const & id) c if (id.getValue() <= NetworkId::cms_maxNetworkIdWithoutClusterId) { - auto i=m_resourceTypeIdMap->find(id); + ResourceTypeIdMap::const_iterator i=m_resourceTypeIdMap->find(id); if (i!=m_resourceTypeIdMap->end()) return (*i).second; else @@ -169,7 +164,7 @@ ResourceTypeObject * ServerUniverse::getResourceTypeById(NetworkId const & id) c } else { - auto i=m_importedResourceTypeIdMap->find(id); + ResourceTypeIdMap::const_iterator i=m_importedResourceTypeIdMap->find(id); if (i!=m_importedResourceTypeIdMap->end()) return (*i).second; else @@ -184,7 +179,7 @@ ResourceTypeObject * ServerUniverse::getImportedResourceTypeById(NetworkId const if (id==NetworkId::cms_invalid) return nullptr; - auto i=m_importedResourceTypeIdMap->find(id); + ResourceTypeIdMap::const_iterator i=m_importedResourceTypeIdMap->find(id); if (i!=m_importedResourceTypeIdMap->end()) return (*i).second; else @@ -267,18 +262,6 @@ void ServerUniverse::addUniverseObject(UniverseObject &newObject) // ---------------------------------------------------------------------- -/** - * Adds a ServerObject as a pseudo-Universe Object for proxy-purposes - * such that it has the effect of being a Universe Object - */ -void ServerUniverse::addCustomUniverseObject(ServerObject &newObject) -{ - m_customUniverseObjects.push_back(&newObject); - GameServer::getInstance().createProxyOnAllServers(&newObject); -} - -// ---------------------------------------------------------------------- - /** * Give a new server proxies of all of the universe objects. */ @@ -292,40 +275,36 @@ void ServerUniverse::createProxiesOnServer(std::vector const & remotePro NameManager::getInstance().sendAllNamesToServer(remoteProcesses); // So are attrib mod names AttribModNameManager::getInstance().sendAllNamesToServer(remoteProcesses); - - for (unsigned long remoteProcess : remoteProcesses) + { - for (auto i : *m_universeObjectList) - { - if (i->getObject()) - { - GameServer::getInstance().createRemoteProxy(remoteProcess, safe_cast(i->getObject())); - } - else - { - DEBUG_REPORT_LOG(true,("Not proxying Universe Object %s because it has been deleted.\n", i->getValueString().c_str())); - } - for (auto &m_customUniverseObject : m_customUniverseObjects) - { - GameServer::getInstance().createRemoteProxy(remoteProcess, m_customUniverseObject); - } - } - } - ServerMessageForwarding::begin(remoteProcesses); - - - std::vector resourceTypeDataVector; - AddResourceTypeMessageNamespace::ResourceTypeData resourceTypeData; - resourceTypeDataVector.reserve(m_resourceTypeIdMap->size()); - - for (auto i=m_resourceTypeIdMap->begin(); i!=m_resourceTypeIdMap->end(); ++i) - { - NON_NULL(i->second)->getDataForMessage(resourceTypeData); - resourceTypeDataVector.push_back(resourceTypeData); + for (std::vector::const_iterator remoteProcessId=remoteProcesses.begin(); remoteProcessId!=remoteProcesses.end(); ++remoteProcessId) + { + for (UniverseObjectList::const_iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) + { + if ((*i)->getObject()) + GameServer::getInstance().createRemoteProxy(*remoteProcessId, safe_cast((*i)->getObject())); + else + DEBUG_REPORT_LOG(true,("Not proxying Universe Object %s because it has been deleted.\n",(*i)->getValueString().c_str())); + } + } } - AddResourceTypeMessage const addResourceTypeMessage(resourceTypeDataVector); - ServerMessageForwarding::send(addResourceTypeMessage); + ServerMessageForwarding::begin(remoteProcesses); + + { + std::vector resourceTypeDataVector; + AddResourceTypeMessageNamespace::ResourceTypeData resourceTypeData; + resourceTypeDataVector.reserve(m_resourceTypeIdMap->size()); + + for (ResourceTypeIdMap::const_iterator i=m_resourceTypeIdMap->begin(); i!=m_resourceTypeIdMap->end(); ++i) + { + NON_NULL(i->second)->getDataForMessage(resourceTypeData); + resourceTypeDataVector.push_back(resourceTypeData); + } + + AddResourceTypeMessage const addResourceTypeMessage(resourceTypeDataVector); + ServerMessageForwarding::send(addResourceTypeMessage); + } GenericValueTypeMessage const universeCompleteMessage("UniverseCompleteMessage", GameServer::getInstance().getProcessId()); ServerMessageForwarding::send(universeCompleteMessage); @@ -336,16 +315,13 @@ void ServerUniverse::createProxiesOnServer(std::vector const & remotePro { std::string serverListAsString; char oneServer[10]; - for (auto i=remoteProcesses.begin(); i!=remoteProcesses.end(); ++i) + for (std::vector::const_iterator i=remoteProcesses.begin(); i!=remoteProcesses.end(); ++i) { if (ConfigServerGame::getTimeoutToAckUniverseDataReceived() > 0) - { - IGNORE_RETURN(m_pendingUniverseLoadedAckList.insert(*i)); - } + IGNORE_RETURN(m_pendingUniverseLoadedAckList.insert(*i)); + if (i!=remoteProcesses.begin()) - { - serverListAsString+=", "; - } + serverListAsString+=", "; snprintf(oneServer,sizeof(oneServer)-1,"%lu",*i); oneServer[sizeof(oneServer)-1] = '\0'; serverListAsString+=oneServer; @@ -353,17 +329,13 @@ void ServerUniverse::createProxiesOnServer(std::vector const & remotePro LOG("UniverseLoading", ("Game Server %lu sent UniverseComplete to Game Servers %s.", GameServer::getInstance().getProcessId(), serverListAsString.c_str())); if (ConfigServerGame::getTimeoutToAckUniverseDataReceived() > 0) - { - m_timeUniverseDataSent = ::time(nullptr); - } + m_timeUniverseDataSent = ::time(nullptr); } } else { if (!remoteProcesses.empty()) - { - IGNORE_RETURN(m_pendingProxyRequests.insert(remoteProcesses.begin(),remoteProcesses.end())); - } + IGNORE_RETURN(m_pendingProxyRequests.insert(remoteProcesses.begin(),remoteProcesses.end())); } } @@ -386,13 +358,11 @@ void ServerUniverse::setUniverseProcess(uint32 processId) if (processId==GameServer::getInstance().getProcessId()) { - for (auto & i : *m_universeObjectList) + for (UniverseObjectList::iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) { - auto *obj=safe_cast(i->getObject()); + ServerObject *obj=safe_cast((*i)->getObject()); if (obj) - { - obj->setAuthority(); - } + obj->setAuthority(); } m_authoritative=true; @@ -400,25 +370,22 @@ void ServerUniverse::setUniverseProcess(uint32 processId) m_nextCheckTimer.reset(); // let all universe objects know that we have gained authority for universe objects - for (auto & j : *m_universeObjectList) + for (UniverseObjectList::iterator j=m_universeObjectList->begin(); j!=m_universeObjectList->end(); ++j) { - auto *obj=safe_cast(j->getObject()); + UniverseObject *obj=safe_cast((*j)->getObject()); if (obj) - { - obj->onServerUniverseGainedAuthority(); - } + obj->onServerUniverseGainedAuthority(); } } else { - for (auto & i : *m_universeObjectList) + for (UniverseObjectList::iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) { - auto *obj=safe_cast(i->getObject()); + ServerObject *obj=safe_cast((*i)->getObject()); if (obj && obj->isAuthoritative()) - { - obj->releaseAuthority(processId); - } + obj->releaseAuthority(processId); } + m_authoritative=false; } } @@ -476,19 +443,19 @@ void ServerUniverse::universeComplete(uint32 sourceServer) m_loaded=true; { - for (auto & m_pendingUniverseObject : *m_pendingUniverseObjects) + for (UniverseObjectList::iterator i=m_pendingUniverseObjects->begin(); i!=m_pendingUniverseObjects->end(); ++i) { - auto *obj=safe_cast(m_pendingUniverseObject->getObject()); + UniverseObject *obj=safe_cast((*i)->getObject()); if (obj) { - m_universeObjectList->push_back(m_pendingUniverseObject); + m_universeObjectList->push_back(*i); obj->setupUniverse(); } else { - DEBUG_REPORT_LOG(true,("Pending Universe Object %s was deleted.\n",m_pendingUniverseObject->getValueString().c_str())); - delete m_pendingUniverseObject; - m_pendingUniverseObject=0; + DEBUG_REPORT_LOG(true,("Pending Universe Object %s was deleted.\n",(*i)->getValueString().c_str())); + delete *i; + *i=0; } } } @@ -536,7 +503,7 @@ CityObject *ServerUniverse::getMasterCityObject() */ void ServerUniverse::renameResourceType (const std::string &oldname, const std::string &newname) { - auto i=m_resourceTypeNameMap->find(oldname); + ResourceTypeNameMap::iterator i=m_resourceTypeNameMap->find(oldname); if (i!=m_resourceTypeNameMap->end()) { ResourceTypeObject *theObj=(*i).second; @@ -589,7 +556,7 @@ void ServerUniverse::updateAndValidateData() if (!m_masterGuildObject) { FATAL(!ConfigServerGame::getAllowMasterObjectCreation(), ("Master guild object was not found!")); - auto const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/guild/guild.iff")); + ServerObjectTemplate const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/guild/guild.iff")); m_masterGuildObject = safe_cast(ServerWorld::createNewObject(*objTemplate, Transform::identity, 0, true)); m_masterGuildObject->addToWorld(); } @@ -598,7 +565,7 @@ void ServerUniverse::updateAndValidateData() if (!m_masterCityObject) { FATAL(!ConfigServerGame::getAllowMasterObjectCreation(), ("Master city object was not found!")); - auto const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/city/city.iff")); + ServerObjectTemplate const * const objTemplate = safe_cast(ObjectTemplateList::fetch("object/city/city.iff")); m_masterCityObject = safe_cast(ServerWorld::createNewObject(*objTemplate, Transform::identity, 0, true)); m_masterCityObject->addToWorld(); } @@ -649,7 +616,7 @@ void ServerUniverse::updateAndValidateData() } //Spawn resources - auto *root=safe_cast(getResourceTreeRoot()); + ServerResourceClassObject *root=safe_cast(getResourceTreeRoot()); if (root) { root->checkRanges(); @@ -658,9 +625,9 @@ void ServerUniverse::updateAndValidateData() } //trigger scripts - for (auto & j : *m_universeObjectList) + for (UniverseObjectList::iterator j = m_universeObjectList->begin(); j != m_universeObjectList->end(); ++j) { - auto *obj=safe_cast(j->getObject()); + UniverseObject *obj=safe_cast((*j)->getObject()); if (obj) { ScriptParams params; @@ -679,19 +646,14 @@ ResourceTypeObject const * ServerUniverse::pickRandomNonDepletedResource(const s { ResourceClassObject *parentClass = getResourceClassByName(parentResourceClassName); if (!parentClass) - { - return 0; - } + return 0; + std::vector possibleTypes; if (!getCurrentPlanet()) - { - return 0; - } + return 0; getCurrentPlanet()->getAvailableResourceList(possibleTypes,*parentClass); - if (possibleTypes.empty()) - { - return 0; - } + if (possibleTypes.size() == 0) + return 0; int choice = Random::random(static_cast(possibleTypes.size())-1); return possibleTypes[static_cast(choice)]; } @@ -720,18 +682,12 @@ void ServerUniverse::onServerConnectionClosed(uint32 processId) if (m_authoritative) { // remove proxies on the crashed server - for (auto & i : *m_universeObjectList) + for (UniverseObjectList::iterator i=m_universeObjectList->begin(); i!=m_universeObjectList->end(); ++i) { - auto *obj=safe_cast(i->getObject()); + ServerObject *obj=safe_cast((*i)->getObject()); if (obj) - { - obj->removeServerFromProxyList(processId); - } - } - for (auto &m_customUniverseObject : m_customUniverseObjects) - { - m_customUniverseObject->removeServerFromProxyList(processId); - } + obj->removeServerFromProxyList(processId); + } } } @@ -778,12 +734,10 @@ void ServerUniverse::update(float frameTime) { std::string serverListAsString; char oneServer[10]; - for (auto i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) + for (PendingUniverseLoadedAckList::const_iterator i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) { if (i!=m_pendingUniverseLoadedAckList.begin()) - { - serverListAsString+=", "; - } + serverListAsString+=", "; snprintf(oneServer,sizeof(oneServer)-1,"%lu",*i); oneServer[sizeof(oneServer)-1] = '\0'; serverListAsString+=oneServer; @@ -801,12 +755,10 @@ void ServerUniverse::update(float frameTime) { std::string serverListAsString; char oneServer[10]; - for (auto i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) + for (PendingUniverseLoadedAckList::const_iterator i=m_pendingUniverseLoadedAckList.begin(); i!=m_pendingUniverseLoadedAckList.end(); ++i) { if (i!=m_pendingUniverseLoadedAckList.begin()) - { - serverListAsString+=", "; - } + serverListAsString+=", "; snprintf(oneServer,sizeof(oneServer)-1,"%lu",*i); oneServer[sizeof(oneServer)-1] = '\0'; serverListAsString+=oneServer; @@ -831,10 +783,9 @@ void ServerUniverse::update(float frameTime) m_pendingProxyRequests.erase(iter); --maxGameServerToSendUniverseData; } + if (!servers.empty()) - { - createProxiesOnServer(servers); - } + createProxiesOnServer(servers); } if (m_nextCheckTimer.updateZero(frameTime) || m_doImmediateCheck || !m_resourcesToSend->empty()) @@ -852,9 +803,9 @@ void ServerUniverse::update(float frameTime) AddResourceTypeMessageNamespace::ResourceTypeData resourceTypeData; resourceTypeDataVector.reserve(m_resourcesToSend->size()); - for (auto i : *m_resourcesToSend) + for (ResourcesToSendType::const_iterator i=m_resourcesToSend->begin(); i!=m_resourcesToSend->end(); ++i) { - NON_NULL(i)->getDataForMessage(resourceTypeData); + NON_NULL(*i)->getDataForMessage(resourceTypeData); resourceTypeDataVector.push_back(resourceTypeData); } @@ -888,15 +839,15 @@ void ServerUniverse::handleAddResourceTypeMessage(AddResourceTypeMessage const & typedef std::vector DataVectorType; DataVectorType const & data = message.getData(); - for (auto i=data.begin(); i!=data.end(); ++i) + for (DataVectorType::const_iterator i=data.begin(); i!=data.end(); ++i) { - auto * const parentClass = safe_cast(getResourceClassByName(i->m_parentClass)); + ServerResourceClassObject * const parentClass = safe_cast(getResourceClassByName(i->m_parentClass)); if (parentClass) { ResourceTypeObject * const existingType = getResourceTypeById(i->m_networkId); if (!existingType) { - auto * const newType = new ResourceTypeObject(*i, *parentClass); + ResourceTypeObject * const newType = new ResourceTypeObject(*i, *parentClass); registerResourceTypeObject(*newType, false); parentClass->addType(*newType); } //lint !e429 // didn't delete newType (registerResourceTypeObject keeps a pointer to it) @@ -918,7 +869,7 @@ const NetworkId & ServerUniverse::findTheaterId(const std::string & name) if (m_theaterNameIdMap == nullptr) return NetworkId::cms_invalid; - auto result = m_theaterNameIdMap->find(name); + TheaterNameIdMap::const_iterator result = m_theaterNameIdMap->find(name); if (result == m_theaterNameIdMap->end()) return NetworkId::cms_invalid; @@ -934,7 +885,7 @@ static const std::string emptyString; if (m_theaterIdNameMap == nullptr) return emptyString; - auto result = m_theaterIdNameMap->find(id); + TheaterIdNameMap::const_iterator result = m_theaterIdNameMap->find(id); if (result == m_theaterIdNameMap->end()) return emptyString; @@ -1059,11 +1010,9 @@ bool ServerUniverse::manualDepleteResource(NetworkId const & resourceToDeplete) if (isAuthoritative()) { resType->deplete(); - auto *root=safe_cast(getResourceTreeRoot()); + ServerResourceClassObject *root=safe_cast(getResourceTreeRoot()); if (root) - { - root->spawnAsNeeded(); - } + root->spawnAsNeeded(); m_doImmediateCheck=true; } else diff --git a/engine/server/library/serverGame/src/shared/core/ServerUniverse.h b/engine/server/library/serverGame/src/shared/core/ServerUniverse.h index 01bc5319..667a63a0 100755 --- a/engine/server/library/serverGame/src/shared/core/ServerUniverse.h +++ b/engine/server/library/serverGame/src/shared/core/ServerUniverse.h @@ -124,8 +124,6 @@ public: static void removeUniverseEvent(std::string const & eventName); static std::string const & getCurrentEvents(); - void addCustomUniverseObject(ServerObject &newObject); - protected: virtual void updateAndValidateData (); @@ -146,8 +144,6 @@ private: uint32 m_universeProcess; Timer m_nextCheckTimer; bool m_doImmediateCheck; - - std::vector m_customUniverseObjects; // // Planet Objects diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp index f59d32da..25b4382a 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsObjectCreate.cpp @@ -113,7 +113,6 @@ namespace ScriptMethodsObjectCreateNamespace jlong JNICALL createNewObjectTransformInternal(JNIEnv *env, jobject self, jstring templateName, jobject transform, jlong cell, bool hyperspace = false); jlong JNICALL createNewObjectTransformCrcInternal(JNIEnv *env, jobject self, jint templateCrc, jobject transform, jlong cell, bool hyperspace = false); jboolean JNICALL updateNetworkTriggerVolume(JNIEnv *env, jobject self, jlong target, jfloat radius); - void JNICALL registerObjectToUniverse(JNIEnv *env, jobject self, jlong target); } @@ -166,7 +165,6 @@ const JNINativeMethod NATIVES[] = { JF("_createObjectHyperspace", "(Ljava/lang/String;Lscript/transform;J)J", createNewObjectTransformHyperspace), JF("_createObjectHyperspace", "(ILscript/transform;J)J", createNewObjectTransformCrcHyperspace), JF("_updateNetworkTriggerVolume", "(JF)Z", updateNetworkTriggerVolume), - JF("_registerObjectToUniverse", "(J)V", registerObjectToUniverse), }; return JavaLibrary::registerNatives(NATIVES, sizeof(NATIVES)/sizeof(NATIVES[0])); @@ -2272,18 +2270,5 @@ jboolean JNICALL ScriptMethodsObjectCreateNamespace::updateNetworkTriggerVolume( return JNI_TRUE; } - -// ---------------------------------------------------------------------- - -void JNICALL ScriptMethodsObjectCreateNamespace::registerObjectToUniverse(JNIEnv *env, jobject self, jlong target) -{ - ServerObject * object = nullptr; - if (!JavaLibrary::getObject(target, object)) - { - WARNING(true, ("Invalid Object passed to ::registerObjectToUniverse().")); - return; - } - ServerUniverse::getInstance().addCustomUniverseObject(*object); -} // ====================================================================== From 7f103fa6dab3c044d4feae3c8de5d69792fa5d5d Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Mon, 7 Jun 2021 16:47:50 -0400 Subject: [PATCH 04/24] Track Original OID in Buildout Objects --- .../src/shared/core/ServerBuildoutManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/ServerBuildoutManager.cpp b/engine/server/library/serverGame/src/shared/core/ServerBuildoutManager.cpp index 53e6063c..7bbbb1a9 100755 --- a/engine/server/library/serverGame/src/shared/core/ServerBuildoutManager.cpp +++ b/engine/server/library/serverGame/src/shared/core/ServerBuildoutManager.cpp @@ -662,6 +662,7 @@ void ServerBuildoutManagerNamespace::loadArea(AreaInfo &areaInfo) std::set< int64 > objects; + int64 originalObjId = 0; for (int buildoutRow = 0; buildoutRow < buildoutRowCount; ++buildoutRow) { int64 objId = 0; @@ -726,7 +727,8 @@ void ServerBuildoutManagerNamespace::loadArea(AreaInfo &areaInfo) } else { - objId = areaBuildoutTable.getIntValue(objIdColumn, buildoutRow); + originalObjId = areaBuildoutTable.getIntValue(objIdColumn, buildoutRow); + objId = originalObjId; containerId = areaBuildoutTable.getIntValue(containerColumn, buildoutRow); // with new buildout files, the object id is a random 31-bit negative value @@ -776,6 +778,10 @@ void ServerBuildoutManagerNamespace::loadArea(AreaInfo &areaInfo) if (containerId == 0 || objects.find(containerId) != objects.end()) { + // store original ObjId from buildout table as ObjVar on item for reference in-game if needed + std::string objVars = areaBuildoutTable.getStringValue(objvarsColumn, buildoutRow); + objVars.insert(0, "buildoutObjectId|0|" + std::to_string(originalObjId) + "|"); + areaInfo.buildoutRows.push_back( BuildoutRow( objId, @@ -784,7 +790,7 @@ void ServerBuildoutManagerNamespace::loadArea(AreaInfo &areaInfo) transform_p, serverTemplate, areaBuildoutTable.getStringValue(scriptsColumn, buildoutRow), - areaBuildoutTable.getStringValue(objvarsColumn, buildoutRow), + objVars, eventRequired, requiredLoadLevel)); } From af69351a7e247d5eae3ceb23408da98cb4099832 Mon Sep 17 00:00:00 2001 From: John <63141077+AconiteX@users.noreply.github.com> Date: Mon, 7 Jun 2021 20:10:53 -0400 Subject: [PATCH 05/24] Update CMakeLists.txt --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf7130a3..e6140156 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,8 +117,7 @@ elseif (UNIX) -Wno-write-strings -Wno-unknown-pragmas \ -Wno-uninitialized -Wno-reorder -Wno-tautological-constant-out-of-range-compare") - # if you'd like to opt in to our statistics, remove "-DSTELLA_INTERNAL" and your server will send us a heartbeat at startup - add_definitions(-DLINUX -D_REENTRANT -Dlinux -D_USING_STL -D_GNU_SOURCE -D_XOPEN_SOURCE=500 -U_FORTIFY_SOURCE -DSTELLA_INTERNAL) + add_definitions(-DLINUX -D_REENTRANT -Dlinux -D_USING_STL -D_GNU_SOURCE -D_XOPEN_SOURCE=500 -U_FORTIFY_SOURCE) # this is so some profile specific stuff is turned on in the code if (${CMAKE_BUILD_TYPE} STREQUAL "RELWITHDEBINFO") From 62edbcf662f4252780cf5bed027427d186dc3b97 Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Mon, 7 Jun 2021 22:16:17 -0400 Subject: [PATCH 06/24] Prevent opening crafting tools --- .../serverGame/src/shared/command/CommandCppFuncs.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp index 7a03d1aa..427f933c 100755 --- a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp +++ b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp @@ -3392,9 +3392,12 @@ static void commandFuncOpenContainer(Command const & cmd, NetworkId const &actor return; } - //-- don't open factory crates - if (container->getGameObjectType() == SharedObjectTemplate::GOT_misc_factory_crate) + //-- don't open factory crates or crafting tools + const int got = container->getGameObjectType(); + if (got == SharedObjectTemplate::GOT_misc_factory_crate || got == SharedObjectTemplate::GOT_tool_crafting) + { return; + } //-- if they are opening a crafting station, what they really want is the hopper //-- but only if the object is not a volume container From 9d985491e8470d9234400eccc53a06b71ba48328 Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Wed, 16 Jun 2021 18:36:23 -0400 Subject: [PATCH 07/24] Add ReportManager Script Trigger Support --- .../src/shared/core/ReportManager.cpp | 20 +++++++++++++++---- .../src/shared/ScriptFunctionTable.cpp | 1 + .../src/shared/ScriptFunctionTable.h | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/ReportManager.cpp b/engine/server/library/serverGame/src/shared/core/ReportManager.cpp index b73e89ff..843373c7 100755 --- a/engine/server/library/serverGame/src/shared/core/ReportManager.cpp +++ b/engine/server/library/serverGame/src/shared/core/ReportManager.cpp @@ -18,6 +18,10 @@ #include "sharedFoundation/FormattedString.h" #include "sharedGame/ProsePackage.h" #include "sharedGame/ProsePackageParticipant.h" +#include "serverScript/GameScriptObject.h" +#include "serverScript/ScriptDictionary.h" +#include "serverScript/ScriptFunctionTable.h" +#include "serverScript/ScriptParameters.h" #include "sharedLog/Log.h" #include "sharedNetworkMessages/ChatAvatarId.h" #include "sharedNetworkMessages/ChatOnRequestLog.h" @@ -331,10 +335,18 @@ void ReportManager::handleMessage(ChatOnRequestLog const &chatOnRequestLog) report.append(reportData.m_clientData); } - if (!reportData.m_reportLogChannel.empty()) - LOGU("CustomerService", (reportData.m_reportLogChannel.c_str()), report); - else - LOGU("CustomerService", ("Report:"), report); + //if (!reportData.m_reportLogChannel.empty()) + // LOGU("CustomerService", (reportData.m_reportLogChannel.c_str()), report); + //else + // LOGU("CustomerService", ("Report:"), report); + + if(reportingCreatureObject->getScriptObject()) + { + ScriptParams p; + p.addParam(reportData.m_harassingNetworkId); + p.addParam(report); + IGNORE_RETURN(reportingCreatureObject->getScriptObject()->trigAllScripts(Scripting::TRIG_ON_PLAYER_REPORTED_CHAT, p)); + } // System message for success diff --git a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp index 3a56b674..48f8bdbe 100755 --- a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp @@ -330,6 +330,7 @@ static const Scripting::ScriptFuncTable ScriptFuncList[] = {Scripting::TRIG_ENTER_REGION, "OnEnterRegion", "ss"}, {Scripting::TRIG_EXIT_REGION, "OnExitRegion", "ss"}, + {Scripting::TRIG_ON_PLAYER_REPORTED_CHAT, "OnPlayerReportedChat", "Ou"}, //---------------------------------------------------------------------- {Scripting::TRIG_VENDOR_ITEM_COUNT_REPLY, "OnVendorItemCountReply", "ii"}, diff --git a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h index 63b508c0..262233eb 100755 --- a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h +++ b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h @@ -480,6 +480,7 @@ enum TrigId TRIG_ON_ABANDON_PLAYER_QUEST = 302, TRIG_ON_GCW_SCORE_CATEGORY_PERCENTILE_CHANGE = 303, TRIG_WAYPOINT_WARP = 304, + TRIG_ON_PLAYER_REPORTED_CHAT = 305, TRIG_LAST_TRIGGER }; From f8a5b0505ed957d67ed8df2af4308b8fe2ad0ed4 Mon Sep 17 00:00:00 2001 From: John <63141077+AconiteX@users.noreply.github.com> Date: Thu, 17 Jun 2021 03:13:04 -0400 Subject: [PATCH 08/24] Add Security for Open Data Container Requests --- .../src/shared/command/CommandCppFuncs.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp index 427f933c..949b5e23 100755 --- a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp +++ b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp @@ -3398,6 +3398,21 @@ static void commandFuncOpenContainer(Command const & cmd, NetworkId const &actor { return; } + + //-- if we are requesting to open an inventory, datapad, or bank, make sure it belongs to us or we're a CSR + //-- this provides better security for /editDatapad /editInventory and /editBank admin commands. + const uint32 crc = container->getTemplateCrc(); + if((player->isPlayerControlled()) && (crc == 2007924155 || crc == -1783727815 || crc == -172438875)) + { + Client * const clientObj = player->getClient(); + if(clientObj) + { + if(container->getOwnerId() != actor && !clientObj->isGod()) + { + return; + } + } + } //-- if they are opening a crafting station, what they really want is the hopper //-- but only if the object is not a volume container From 782f806ca5abef364f6cd78819ed31673bcf31c3 Mon Sep 17 00:00:00 2001 From: John <63141077+AconiteX@users.noreply.github.com> Date: Sat, 19 Jun 2021 00:24:47 -0400 Subject: [PATCH 09/24] Fix getBuildoutAreaName fail in instanced cloning contexts --- .../library/serverScript/src/shared/ScriptMethodsPlanet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/server/library/serverScript/src/shared/ScriptMethodsPlanet.cpp b/engine/server/library/serverScript/src/shared/ScriptMethodsPlanet.cpp index 9f708a22..f0743a00 100755 --- a/engine/server/library/serverScript/src/shared/ScriptMethodsPlanet.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptMethodsPlanet.cpp @@ -479,7 +479,7 @@ jstring JNICALL ScriptMethodsPlanetNamespace::getBuildoutAreaName( JNIEnv *const return 0; } - const BuildoutArea * const area = SharedBuildoutAreaManager::findBuildoutAreaAtPosition(sceneId.c_str(), x, z, false ); + const BuildoutArea * const area = SharedBuildoutAreaManager::findBuildoutAreaAtPosition(sceneId, x, z, false, false); return area ? JavaString( area->areaName ).getReturnValue() : 0; } From 3431403409daf15b7c2a683abde7a9a836230fa6 Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 09:52:52 -0700 Subject: [PATCH 10/24] Create main.yml --- .github/workflows/main.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..669c3538 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,30 @@ +# This is a basic workflow to help you get started with Actions + +name: CI Build Server + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: [ master ] + pull_request: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + # Runs a single command using the runners shell + - name: Compile C code + run: ant compile_src From 0befd921e57e088de9b0cf2115ae6485e00afe4c Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 09:55:16 -0700 Subject: [PATCH 11/24] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 669c3538..8018a2f6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,4 +27,4 @@ jobs: # Runs a single command using the runners shell - name: Compile C code - run: ant compile_src + run: ant -DbaseDir=. compile_src From fd98f483e4dc28abef5b0376a8fcca66d3933aa6 Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 09:56:30 -0700 Subject: [PATCH 12/24] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8018a2f6..7ef497b1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,4 +27,4 @@ jobs: # Runs a single command using the runners shell - name: Compile C code - run: ant -DbaseDir=. compile_src + run: ant -Dbasedir=. compile_src From c18d6380655778c1b9d27157be36cfc69e849b44 Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 11:43:25 -0700 Subject: [PATCH 13/24] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7ef497b1..1be180e5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,4 +27,4 @@ jobs: # Runs a single command using the runners shell - name: Compile C code - run: ant -Dbasedir=. compile_src + run: ant -Dbasedir=. build_src From d517c3bf4dd4c393d24b1afbdf5645a6807d3560 Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 11:53:21 -0700 Subject: [PATCH 14/24] Update main.yml --- .github/workflows/main.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1be180e5..6902bcc5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,6 +24,13 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 + with: + path: 'src/' + + - name: Make dependency directories + - run: | + mkdir -p exe/linux/bin + mkdir -p build/bin # Runs a single command using the runners shell - name: Compile C code From 12f3060ad8ac29142dedc8b27ff8a92b3b9aeb04 Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 11:58:05 -0700 Subject: [PATCH 15/24] Update main.yml --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6902bcc5..28496d4d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,6 +23,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - name: Checkout code - uses: actions/checkout@v2 with: path: 'src/' From 3a45f0943bb7fb7672b1383a77f4b6b76b679be3 Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 11:58:55 -0700 Subject: [PATCH 16/24] Update main.yml --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 28496d4d..0c8e1c51 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,12 +24,12 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Checkout code - - uses: actions/checkout@v2 + uses: actions/checkout@v2 with: path: 'src/' - name: Make dependency directories - - run: | + run: | mkdir -p exe/linux/bin mkdir -p build/bin From 06df64c7a6a43dad285ee288d458f447d9f5f288 Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 12:00:44 -0700 Subject: [PATCH 17/24] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0c8e1c51..3bac28bb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,4 +35,4 @@ jobs: # Runs a single command using the runners shell - name: Compile C code - run: ant -Dbasedir=. build_src + run: ant -buildfile src/build.xml -Dbasedir=. build_src From 5278762ed110701b5dec23d02abe84869b0a3edc Mon Sep 17 00:00:00 2001 From: Cekis Date: Sun, 20 Jun 2021 12:12:42 -0700 Subject: [PATCH 18/24] Delete .github/workflows directory --- .github/workflows/main.yml | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 3bac28bb..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: CI Build Server - -# Controls when the action will run. -on: - # Triggers the workflow on push or pull request events but only for the master branch - push: - branches: [ master ] - pull_request: - branches: [ master ] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - name: Checkout code - uses: actions/checkout@v2 - with: - path: 'src/' - - - name: Make dependency directories - run: | - mkdir -p exe/linux/bin - mkdir -p build/bin - - # Runs a single command using the runners shell - - name: Compile C code - run: ant -buildfile src/build.xml -Dbasedir=. build_src From 5c96c3343c6ed1d12e1466987eb6294fd1ff7a97 Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Tue, 10 Aug 2021 20:50:00 -0400 Subject: [PATCH 19/24] Cleanup Warden/Squelch/Spammer Permissions --- .../src/shared/command/CommandCppFuncs.cpp | 57 ++++++++++++++++--- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp index 949b5e23..c8a7749b 100755 --- a/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp +++ b/engine/server/library/serverGame/src/shared/command/CommandCppFuncs.cpp @@ -7947,6 +7947,10 @@ static void commandFuncSquelch(Command const &, NetworkId const &actor, NetworkI const Client * gmClient = gm->getClient(); if (gmClient) { + if(!gmClient->isGod()) + { + return; + } char buffer[2048]; if (!target.isValid()) { @@ -8016,6 +8020,10 @@ static void commandFuncUnsquelch(Command const &, NetworkId const &actor, Networ const Client * gmClient = gm->getClient(); if (gmClient) { + if(!gmClient->isGod()) + { + return; + } char buffer[2048]; if (!target.isValid()) { @@ -8085,6 +8093,10 @@ static void commandFuncGrantWarden(Command const &, NetworkId const &actor, Netw const Client * gmClient = gm->getClient(); if (gmClient) { + if(!gmClient->isGod()) + { + return; + } char buffer[2048]; if (!target.isValid()) { @@ -8156,6 +8168,10 @@ static void commandFuncRevokeWarden(Command const &, NetworkId const &actor, Net const Client * gmClient = gm->getClient(); if (gmClient) { + if(!gmClient->isGod()) + { + return; + } char buffer[2048]; if (!target.isValid()) { @@ -8228,16 +8244,16 @@ static void commandFuncSpammer(Command const &, NetworkId const &actor, NetworkI const Client * gmClient = gm->getClient(); if (gmClient) { - // check warden permission first + // check warden permission first or if god const PlayerObject * gmPlayerObject = PlayerCreatureController::getPlayerObject(gm); - if (!gmPlayerObject || !gmPlayerObject->isWarden()) + if (!gmPlayerObject || (!gmPlayerObject->isWarden()) && !gmClient->isGod()) { Chat::sendSystemMessage(*gm, StringId("warden", "not_authorized"), Unicode::emptyString); return; } - // check to see if warden functionality is enabled - if (!ConfigServerGame::getEnableWarden()) + // check to see if warden functionality is enabled but don't restrict if god + if (!ConfigServerGame::getEnableWarden() && !gmClient->isGod()) { Chat::sendSystemMessage(*gm, StringId("warden", "warden_functionality_disabled"), Unicode::emptyString); return; @@ -8322,6 +8338,16 @@ static void commandFuncSpammer(Command const &, NetworkId const &actor, NetworkI } } + // can't spammer someone in god mode or another warden + if(so->getClient()->isGod() || p->isWarden()) + { + ProsePackage prosePackage; + prosePackage.stringId = StringId("warden", "cannot_spammer_target"); + prosePackage.target.str = so->getAssignedObjectName(); + Chat::sendSystemMessage(*gm, prosePackage); + return; + } + // cannot /spammer self if (target == actor) { @@ -8369,9 +8395,9 @@ static void commandFuncUnspammer(Command const &, NetworkId const &actor, Networ const Client * gmClient = gm->getClient(); if (gmClient) { - // check warden permission first + // check warden permission first or if god const PlayerObject * gmPlayerObject = PlayerCreatureController::getPlayerObject(gm); - if (!gmPlayerObject || !gmPlayerObject->isWarden()) + if (!gmPlayerObject || (!gmPlayerObject->isWarden()) && !gmClient->isGod()) { Chat::sendSystemMessage(*gm, StringId("warden", "not_authorized"), Unicode::emptyString); return; @@ -8449,8 +8475,8 @@ static void commandFuncUnspammer(Command const &, NetworkId const &actor, Networ return; } - // can only /unspammer target that I /spammer(ed) - if (p->getSquelchedById() != actor) + // can only /unspammer target that I /spammer(ed) unless I'm god + if (p->getSquelchedById() != actor && !gmClient->isGod()) { ProsePackage prosePackage; prosePackage.stringId = StringId("warden", "cannot_unspammer_target"); @@ -8476,8 +8502,16 @@ static void commandFuncUnspammer(Command const &, NetworkId const &actor, Networ //----------------------------------------------------------------------- +/** + * @deprecated This ungodly idea to empower wardens to grant warden permissions to other players is horrible + * and I don't believe this functionality should remotely exist at all absent intentional implementation + * by a specific server. GMs can use /grantWarden if they want a Warden or the grant can be scripted. + * + * Aconite - SWG Source - 2021 + */ static void commandFuncDeputizeWarden(Command const &, NetworkId const &actor, NetworkId const & target, Unicode::String const ¶ms) { + /* const CreatureObject * gm = dynamic_cast(NetworkIdManager::getObjectById(actor)); if (gm) { @@ -8549,12 +8583,18 @@ static void commandFuncDeputizeWarden(Command const &, NetworkId const &actor, N "C++DeputizeWardenRspCannotDeputize"); } } + */ } //----------------------------------------------------------------------- +/** + * @deprecated + * @see commandFuncDeputizeWarden + */ static void commandFuncUndeputizeWarden(Command const &, NetworkId const &actor, NetworkId const & target, Unicode::String const ¶ms) { + /* const CreatureObject * gm = dynamic_cast(NetworkIdManager::getObjectById(actor)); if (gm) { @@ -8612,6 +8652,7 @@ static void commandFuncUndeputizeWarden(Command const &, NetworkId const &actor, "C++UndeputizeWardenRspCannotUndeputize"); } } + */ } //----------------------------------------------------------------------- From 89169339c669c1aaa84119876db82b3b0390cb8b Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Sat, 14 Aug 2021 00:43:41 -0400 Subject: [PATCH 20/24] Move no trade removal script attach from baselines to initialization --- .../serverGame/src/shared/object/ServerObject.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/object/ServerObject.cpp b/engine/server/library/serverGame/src/shared/object/ServerObject.cpp index 598f2e1f..585cd19f 100755 --- a/engine/server/library/serverGame/src/shared/object/ServerObject.cpp +++ b/engine/server/library/serverGame/src/shared/object/ServerObject.cpp @@ -1963,9 +1963,6 @@ void ServerObject::serverObjectEndBaselines(bool fromDatabase) // If the object was created authoritative, trigger if needed if (isAuthoritative()) triggerMadeAuthoritative(); - - if (markedNoTradeRemovable()) - getScriptObject()->attachScript("item.special.no_trade_removable", true); } if (isPlayerControlled()) @@ -2566,7 +2563,13 @@ bool ServerObject::serverObjectInitializeFirstTimeObject(ServerObject *cell, Tra int count = newTemplate->getScriptsCount(); for (int i = 0; i < count; ++i) + { getScriptObject()->attachScript(newTemplate->getScripts(i), true); + } + if (markedNoTradeRemovable()) + { + getScriptObject()->attachScript("item.special.no_trade_removable", true); + } if (cell) { From 55976968a0986a73b8d12d63b016500aade9cabe Mon Sep 17 00:00:00 2001 From: AconiteX <63141077+AconiteX@users.noreply.github.com> Date: Mon, 16 Aug 2021 11:44:25 -0400 Subject: [PATCH 21/24] Admin Account Routing Refactor --- .../src/shared/ClientConnection.cpp | 32 +++- .../src/shared/ConfigConnectionServer.cpp | 2 + .../src/shared/ConfigConnectionServer.h | 10 + .../LoginServer/src/shared/LoginServer.cpp | 67 +++---- .../serverGame/src/shared/core/Client.cpp | 172 ++++++++++++++---- .../serverGame/src/shared/core/Client.h | 2 + .../src/shared/ScriptFunctionTable.cpp | 4 +- .../src/shared/ScriptFunctionTable.h | 3 +- .../ClientPermissionsMessage.cpp | 10 +- .../ClientPermissionsMessage.h | 11 +- .../clientLoginServer/LoginClusterStatus.h | 15 ++ 11 files changed, 236 insertions(+), 92 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 54d2d0b7..187997ed 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -394,19 +394,41 @@ ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, b // Save lists of claimed rewards, which won't be used again until later in the login sequence m_consumedRewardEvents = consumedRewardEvents; m_claimedRewardItems = claimedRewardItems; + bool isAdmin = false; - - int level = 0; - if (AdminAccountManager::isAdminAccount(Unicode::toLower(getAccountName()), level) && (level != - 0)) // Note: not checking IP, so that owners of god accounts can create characters to play from home without having to erase the characters they use for work + // Revised - SWG Source - 2021 (Aconite) + // Determine if this account is in the Admin Table + if(AdminAccountManager::getAdminLevel(Unicode::toLower(getAccountName())) > 0) { + // Determine if we are using Secure Login (IP restricted) + if(ConfigConnectionServer::getUseSecureLoginForGodAccess()) + { + // If we *require* secure login, and we are *not* from a secure IP, disconnect the client + // as they should not be inside this account + if(!AdminAccountManager::isInternalIp(getRemoteAddress())) + { + LOG("GodMode", ("[%s : %s : %s : %s] login to this admin account failed because secure login was required but the remote IP address connected was not in the allowed range.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getRemoteAddress().c_str())); + disconnect(); + return; + } + else + { + m_isSecure = true; + } + } + // If we're here, we're an admin account, and we have the correct IP (if applicable) + // so we're overriding the ClientPermissionMessage values canLogin = true; canCreateRegularCharacter = true; canSkipTutorial = true; m_isAdminAccount = true; + isAdmin = true; // this flag goes to the client to let it know we can connect to a Locked Cluster + LOG("GodMode", ("[%s : %s : %s : %s] validating this account to the Connection Server after successful authentication.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getRemoteAddress().c_str())); } - ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial); + ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial, isAdmin); send(c, true); DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID())); diff --git a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp index 538e2c01..2eef9f77 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp @@ -117,6 +117,8 @@ void ConfigConnectionServer::install(void) KEY_STRING (altPublicBindAddress, ""); KEY_BOOL (useOldSuidGenerator, false); + KEY_BOOL (useSecureLoginForGodAccess, false); + int index = 0; char const * result = 0; do diff --git a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h index 7d5edc42..67741268 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h +++ b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h @@ -68,6 +68,8 @@ public: int connectionServerNumber; int fakeBuddyPoints; + bool useSecureLoginForGodAccess; + bool useOldSuidGenerator; const char *altPublicBindAddress; @@ -187,6 +189,9 @@ public: static const char *getPublicBindAddress(); static bool getUseOldSuidGenerator(); + + static bool getUseSecureLoginForGodAccess(); + private: static Data *data; }; @@ -480,4 +485,9 @@ inline bool ConfigConnectionServer::getUseOldSuidGenerator() { return data->useOldSuidGenerator; } +inline bool ConfigConnectionServer::getUseSecureLoginForGodAccess() +{ + return data->useSecureLoginForGodAccess; +} + #endif // _ConfigConnectionServer_H diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 677ad357..bd053af2 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -943,10 +943,10 @@ LoginServer::validateAccount(const StationId &stationId, uint32 clusterId, uint3 bool clientIsInternal = false; ClientConnection *conn = getValidatedClient(stationId); if (conn) { - clientIsInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); + clientIsInternal = conn->getAdminLevel() > 0; } - if (clientIsInternal && ConfigLoginServer::getInternalBypassOnlineLimit()) { + if (clientIsInternal) { canLogin = true; } else if (cle->m_numPlayers <= cle->m_onlinePlayerLimit) { canLogin = true; @@ -968,6 +968,12 @@ LoginServer::validateAccount(const StationId &stationId, uint32 clusterId, uint3 canSkipTutorial = true; } + // double check locked cluster + if(cle->m_locked) + { + canLogin = clientIsInternal; + } + ValidateAccountReplyMessage msg(stationId, canLogin, canCreateRegular, canCreateJedi, canSkipTutorial, track, consumedRewardEvents, claimedRewardItems); cle->m_centralServerConnection->send(msg, true); } @@ -1228,32 +1234,8 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien NOT_NULL(conn); WARNING_STRICT_FATAL(getValidatedClient(suid), ("Validating an already valid client in onValidateClient(). StationId: %d UserName: %s", suid, username.c_str())); - int adminLevel = 0; - const bool isAdminAccount = AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel); - - if (conn->getRequestedAdminSuid() != 0) { - //verify internal, secure, is on the god list - bool loginOK = false; - if (!isSecure) { - LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, conn->getRequestedAdminSuid())); - } else { - if (!AdminAccountManager::isInternalIp(conn->getRemoteAddress())) { - LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not logging in from an internal IP", username.c_str(), suid, conn->getRequestedAdminSuid())); - } else { - if (!isAdminAccount || adminLevel < 10) { - LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but did not have sufficient permissions", username.c_str(), suid, conn->getRequestedAdminSuid())); - } else { - suid = conn->getRequestedAdminSuid(); - loginOK = true; - } - } - } - - if (!loginOK) { - conn->disconnect(); - return; - } - } + // determine if this is an admin account + const bool isAdminAccount = AdminAccountManager::getAdminLevel(username) > 0; // encrypt the clients credentials with the key, return // the cipher text to the client for use as a connection @@ -1297,14 +1279,11 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien conn->send(k, true); delete[] keyBuffer; - // send cluster enum - bool clientInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); - std::vector data; for (ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) { ClusterListEntry *cle = *j; - if (cle && cle->m_clusterId != 0 && cle->m_clusterName.size() != 0 && (clientInternal || !cle->m_secret)) { + if (cle && cle->m_clusterId != 0 && cle->m_clusterName.size() != 0 && (isAdminAccount || !cle->m_secret)) { LoginEnumCluster::ClusterData item; item.m_clusterId = cle->m_clusterId; item.m_clusterName = cle->m_clusterName; @@ -1331,7 +1310,7 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien conn->setIsValidated(true); conn->setStationId(suid); conn->setIsSecure(isSecure); - conn->setAdminLevel(isAdminAccount ? adminLevel : -1); + conn->setAdminLevel(isAdminAccount ? AdminAccountManager::getAdminLevel(username) : -1); IGNORE_RETURN(m_validatedClientMap.insert(std::pair(suid, conn))); //Must be done after setting various information in the connection object above @@ -1408,11 +1387,16 @@ void LoginServer::sendExtendedClusterInfo(ClientConnection &client) const { /** * Send the list of active clusters to a client. * Also picks a connection server for the client to use. - * @todo We'd like to resend this to all clients whenever the status - * of any servers changes + * + * Note: *** should send to individual clients - NOT all connected + * clients due to admin permissions check *** */ void LoginServer::sendClusterStatus(ClientConnection &conn) const { - const bool clientIsPrivate = AdminAccountManager::isInternalIp(conn.getRemoteAddress()); + + // Validate admin level here as clientIsPrivate. We don't need to check secure/IP because the + // connection server will force disconnect non-secure connections if they are required by configuration. + const bool clientIsPrivate = conn.getAdminLevel() > 0; + const unsigned int subscriptionBits = conn.getSubscriptionBits(); const bool isFreeTrialAccount = (((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) && ((subscriptionBits & ClientSubscriptionFeature::Base) == 0)); @@ -1451,10 +1435,7 @@ void LoginServer::sendClusterStatus(ClientConnection &conn) const { if (item.m_connectionServerPort) { item.m_connectionServerPingPort = connServer.pingPort; - // for security/confidential information issue, only report - // population count to secured internal connections with - // admin privilege >= 10 - if (clientIsPrivate && conn.getIsSecure() && (conn.getAdminLevel() >= 10)) { + if (clientIsPrivate) { item.m_populationOnline = cle->m_numPlayers; } else { item.m_populationOnline = -1; @@ -1493,10 +1474,14 @@ void LoginServer::sendClusterStatus(ClientConnection &conn) const { } else { item.m_status = LoginClusterStatus::ClusterData::S_loading; } - if (cle->m_locked && !clientIsPrivate) { + if (cle->m_locked) { item.m_status = LoginClusterStatus::ClusterData::S_locked; } // locked takes precedence over up or loading + // flag as admin/secret (see LoginClusterStatus.h) + item.m_isAdmin = clientIsPrivate; + item.m_isSecret = cle->m_secret; + item.m_dontRecommend = (cle->m_notRecommendedDatabase || cle->m_notRecommendedCentral); item.m_onlinePlayerLimit = cle->m_onlinePlayerLimit; item.m_onlineFreeTrialLimit = cle->m_onlineFreeTrialLimit; diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 7d327942..79bc4f56 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -501,6 +501,12 @@ void Client::addControlledObject(ServerObject &object) { setGodMode(true); } } + + // validate isUsingAdminLogin each onClientReady() call per SWG Source change - 2021 (Aconite) + // isUsingAdminLogin is used to check if an *account* is in the admin table + // so we can monitor admin accessed accounts *regardless* of their current god mode/level + setUsingAdminLogin(AdminAccountManager::getAdminLevel(getAccountName()) > 0); + } // ---------------------------------------------------------------------- @@ -1937,53 +1943,131 @@ float Client::computeDeltaTimeInSeconds(uint32 const syncStampLong) const { //----------------------------------------------------------------------- +/** + * setGodMode + * Processes the request to turn God Mode in the Client on, + * enabling admin commands and admin-treatment of a CreatureObject. + * + * @param value true = god mode on; false = god mode off + * @return true if successful, false if not + * + * Handling was rewritten by SWG Source - 2021 for applicability + * to Source/VM context + * Authors: Aconite + */ bool Client::setGodMode(bool value) { - // (re?) check god permissions - m_godLevel = AdminAccountManager::getAdminLevel(m_accountName.c_str()); - if (ConfigServerGame::getAdminGodToAll() || (m_godLevel > 0)) { - m_godValidated = true; - if (ConfigServerGame::getAdminGodToAll()) { - m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); - } - } + const bool wasInGodMode = m_godMode; + auto * creatureObject = safe_cast(m_primaryControlledObject.getObject()); + ScriptParams params; - bool wasInGodMode = m_godMode; - m_godMode = value; - - if (value && !m_godValidated) { - LOG("CustomerService", ("Avatar:%s denied god mode because it wasn't validated.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str())); - m_godMode = false; - } - - CreatureObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); - if (!primaryControlledObject) { - if (value && !wasInGodMode) { - LOG("CustomerService", ("Avatar:%s denied god mode because it has no associated character.", m_accountName.c_str())); - } - m_godMode = false; + if(!creatureObject) + { + LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode failed because we couldn't get the CreatureObject.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str())); return false; } - if (m_godMode) { - IGNORE_RETURN(primaryControlledObject->grantCommand(AdminAccountManager::getAdminCommandName(), false)); - } else { - primaryControlledObject->revokeCommand(AdminAccountManager::getAdminCommandName(), false, true); - } - - if (m_godMode != wasInGodMode) { - if (m_godMode) { - LOG("CustomerService", ("Avatar:%s granted god mode %s level %d.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), AdminAccountManager::getAdminCommandName(), m_godLevel)); - } else { - LOG("CustomerService", ("Avatar:%s dropped god mode.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str())); + // Request to turn God Mode Off, in which case we don't need to validate permissions, because off isn't bad + if(!value) + { + // If we were already in god mode, then we've already made an authenticated request to be in god mode, + // so log the event and proceed as an authorized activity, unless a script trigger blocks the switch. + if(wasInGodMode) + { + // allow a SCRIPT_OVERRIDE to block turning god mode off if necessary + // see OnTurnedGodModeOff in script.player.base_player.java + if(creatureObject->getScriptObject()->trigAllScripts(Scripting::TRIG_ON_SET_GOD_MODE_OFF, params) != SCRIPT_CONTINUE) + { + LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode off failed because OnSetGodModeOff did not return SCRIPT_CONTINUE.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str())); + return false; + } + else + { + LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode off success.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str())); + } } - - // cell permissions may change for us for all cells, so observe all buildings in range for the change - CellPermissions::ViewerChangeObserver o(primaryControlledObject); - - ObserveTracker::onGodModeChanged(*this); + m_godLevel = 0; + m_godMode = false; + m_godValidated = false; + // remove the characterAbility "admin" so GM commands aren't sent by the client while not in God Mode + IGNORE_RETURN(creatureObject->revokeCommand(AdminAccountManager::getAdminCommandName(), false, true)); + return true; } - return (value == m_godMode); // return true if the value was set to what was requested, false otherwise + + // If we're here, it's because the request is to turn God Mode ON + // First, determine if we're using Secure Login Mode (IP-restricted) + if(ConfigServerGame::getUseSecureLoginForGodAccess()) + { + if(!AdminAccountManager::isInternalIp(getIpAddress())) + { + LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on failed because secure login was required and the connection IP was not approved.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str())); + return false; + } + } + + // If we aren't required to be secure, or if we are and we are secure, begin permission checks + // Start with if everyone can have God Mode, in which case we don't need to bother otherwise + int godLevel = 0; + if(ConfigServerGame::getAdminGodToAll() && ConfigServerGame::getAdminGodToAllGodLevel() > 0) + { + // Make sure the account isn't in the admin table, because that should supersede + // whatever the adminGodToAll level is. + if(AdminAccountManager::getAdminLevel(m_accountName) == 0) + { + godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); + } + else + { + godLevel = AdminAccountManager::getAdminLevel(m_accountName); + } + } + // We aren't giving god to everyone, so validate actual god level permissions + else + { + godLevel = AdminAccountManager::getAdminLevel(m_accountName); + } + // Grant God Mode + if(godLevel > 0) + { + // Allow a SCRIPT_OVERRIDE to block turning God Mode on via OnSetGodModeOn trigger + // see script.player.player_base.java + if(creatureObject->getScriptObject()->trigAllScripts(Scripting::TRIG_ON_SET_GOD_MODE_ON, params) != SCRIPT_CONTINUE) + { + LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on failed because OnSetGodModeOn did not return SCRIPT_CONTINUE.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str())); + return false; + } + else + { + // flags + m_godMode = true; + m_godValidated = true; + m_godLevel = godLevel; + + // grant all commands with the "admin" characterAbility + IGNORE_RETURN(creatureObject->grantCommand(AdminAccountManager::getAdminCommandName(), false)); + + // reset observers and notify cells of potential change + CellPermissions::ViewerChangeObserver o(creatureObject); + ObserveTracker::onGodModeChanged(*this); + + LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on success.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str())); + return true; + } + } + // If we're here, it's because someone tried to use /setGod who doesn't have permissions + else + { + LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on failed because the requesting account does not have permissions.", + getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str())); + return false; + } + } //----------------------------------------------------------------------- @@ -2165,12 +2249,20 @@ void Client::launchWebBrowser(std::string const &url) const { // ---------------------------------------------------------------------- -bool Client::isUsingAdminLogin() const { +bool Client::isUsingAdminLogin() const +{ return m_usingAdminLogin; } // ---------------------------------------------------------------------- +void Client::setUsingAdminLogin(bool value) +{ + m_usingAdminLogin = value; +} + +// ---------------------------------------------------------------------- + bool Client::shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const { PROFILER_AUTO_BLOCK_DEFINE("Client::shouldReceiveCombatSpam"); diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index e495059b..9fcf1724 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -105,6 +105,8 @@ public: bool isUsingAdminLogin() const; + void setUsingAdminLogin(bool value); + CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const; int getCombatSpamRangeSquaredFilter() const; diff --git a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp index 48f8bdbe..b9d91ae4 100755 --- a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp @@ -330,7 +330,6 @@ static const Scripting::ScriptFuncTable ScriptFuncList[] = {Scripting::TRIG_ENTER_REGION, "OnEnterRegion", "ss"}, {Scripting::TRIG_EXIT_REGION, "OnExitRegion", "ss"}, - {Scripting::TRIG_ON_PLAYER_REPORTED_CHAT, "OnPlayerReportedChat", "Ou"}, //---------------------------------------------------------------------- {Scripting::TRIG_VENDOR_ITEM_COUNT_REPLY, "OnVendorItemCountReply", "ii"}, @@ -380,6 +379,9 @@ static const Scripting::ScriptFuncTable ScriptFuncList[] = {Scripting::TRIG_PVP_RANKING_CHANGED, "OnPvpRankingChanged", "ii"}, + {Scripting::TRIG_ON_SET_GOD_MODE_ON, "OnSetGodModeOn", ""}, + {Scripting::TRIG_ON_SET_GOD_MODE_OFF, "OnSetGodModeOff", ""}, + //----------------------------------------------------------------------- //-- buff builder diff --git a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h index 262233eb..19cead31 100755 --- a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h +++ b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h @@ -480,7 +480,8 @@ enum TrigId TRIG_ON_ABANDON_PLAYER_QUEST = 302, TRIG_ON_GCW_SCORE_CATEGORY_PERCENTILE_CHANGE = 303, TRIG_WAYPOINT_WARP = 304, - TRIG_ON_PLAYER_REPORTED_CHAT = 305, + TRIG_ON_SET_GOD_MODE_ON = 305, + TRIG_ON_SET_GOD_MODE_OFF = 306, TRIG_LAST_TRIGGER }; diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.cpp b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.cpp index 8e3c0aea..7d4652f5 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.cpp +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.cpp @@ -10,17 +10,19 @@ // ====================================================================== -ClientPermissionsMessage::ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial) : +ClientPermissionsMessage::ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, bool isAdmin) : GameNetworkMessage("ClientPermissionsMessage"), m_canLogin(canLogin), m_canCreateRegularCharacter(canCreateRegularCharacter), m_canCreateJediCharacter(canCreateJediCharacter), - m_canSkipTutorial(canSkipTutorial) + m_canSkipTutorial(canSkipTutorial), + m_isAdmin(isAdmin) { addVariable(m_canLogin); addVariable(m_canCreateRegularCharacter); addVariable(m_canCreateJediCharacter); addVariable(m_canSkipTutorial); + addVariable(m_isAdmin); } //----------------------------------------------------------------------- @@ -30,12 +32,14 @@ ClientPermissionsMessage::ClientPermissionsMessage(Archive::ReadIterator & sourc m_canLogin(), m_canCreateRegularCharacter(), m_canCreateJediCharacter(), - m_canSkipTutorial() + m_canSkipTutorial(), + m_isAdmin() { addVariable(m_canLogin); addVariable(m_canCreateRegularCharacter); addVariable(m_canCreateJediCharacter); addVariable(m_canSkipTutorial); + addVariable(m_isAdmin); unpack(source); } diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.h index 8ad6c9da..374a63d8 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientGameServer/ClientPermissionsMessage.h @@ -24,7 +24,7 @@ class ClientPermissionsMessage : public GameNetworkMessage { public: - ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial); + ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, bool isAdmin); explicit ClientPermissionsMessage(Archive::ReadIterator & source); virtual ~ClientPermissionsMessage(); @@ -33,12 +33,14 @@ class ClientPermissionsMessage : public GameNetworkMessage bool getCanCreateRegularCharacter() const; bool getCanCreateJediCharacter() const; bool getCanSkipTutorial() const; + bool getIsAdmin() const; private: Archive::AutoVariable m_canLogin; Archive::AutoVariable m_canCreateRegularCharacter; Archive::AutoVariable m_canCreateJediCharacter; Archive::AutoVariable m_canSkipTutorial; + Archive::AutoVariable m_isAdmin; ClientPermissionsMessage(); ClientPermissionsMessage(const ClientPermissionsMessage&); @@ -73,6 +75,13 @@ inline bool ClientPermissionsMessage::getCanSkipTutorial() const return m_canSkipTutorial.get(); } +// ---------------------------------------------------------------------- + +inline bool ClientPermissionsMessage::getIsAdmin() const +{ + return m_isAdmin.get(); +} + // ====================================================================== #endif // _INCLUDED_ClientCentralMessages_H diff --git a/engine/shared/library/sharedNetworkMessages/src/shared/clientLoginServer/LoginClusterStatus.h b/engine/shared/library/sharedNetworkMessages/src/shared/clientLoginServer/LoginClusterStatus.h index 6c074132..69897510 100755 --- a/engine/shared/library/sharedNetworkMessages/src/shared/clientLoginServer/LoginClusterStatus.h +++ b/engine/shared/library/sharedNetworkMessages/src/shared/clientLoginServer/LoginClusterStatus.h @@ -31,6 +31,17 @@ struct LoginClusterStatus_ClusterData bool m_dontRecommend; uint32 m_onlinePlayerLimit; uint32 m_onlineFreeTrialLimit; + + // This flag tells the client that the account which requested the cluster information + // is considered an admin by the server (in Admin Account Table). This enables connection + // to locked clusters and viewing secret clusters. We don't need to worry about this flag + // being manipulated because the Connection Server verifies admin permissions after the fact. + // This flag merely unblocks client-side user interface elements for locked/secret clusters. + // We also send this flag in the ClientPermissionsMessage header for character creation. + bool m_isAdmin; + // Flag so we can append (Secret) in Client (for admins) + bool m_isSecret; + }; /** @@ -85,6 +96,8 @@ namespace Archive get(source,c.m_dontRecommend); get(source,c.m_onlinePlayerLimit); get(source,c.m_onlineFreeTrialLimit); + get(source, c.m_isAdmin); + get(source,c.m_isSecret); } inline void put(ByteStream & target, const LoginClusterStatus_ClusterData &c) @@ -101,6 +114,8 @@ namespace Archive put(target,c.m_dontRecommend); put(target,c.m_onlinePlayerLimit); put(target,c.m_onlineFreeTrialLimit); + put(target,c.m_isAdmin); + put(target,c.m_isSecret); } } From c4290801b0911ffc714cdf23b09cdfb8b6f21432 Mon Sep 17 00:00:00 2001 From: John <63141077+AconiteX@users.noreply.github.com> Date: Tue, 17 Aug 2021 09:30:48 -0400 Subject: [PATCH 22/24] Update ScriptFunctionTable.h --- .../library/serverScript/src/shared/ScriptFunctionTable.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h index 19cead31..3bb59f51 100755 --- a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h +++ b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.h @@ -480,8 +480,9 @@ enum TrigId TRIG_ON_ABANDON_PLAYER_QUEST = 302, TRIG_ON_GCW_SCORE_CATEGORY_PERCENTILE_CHANGE = 303, TRIG_WAYPOINT_WARP = 304, - TRIG_ON_SET_GOD_MODE_ON = 305, - TRIG_ON_SET_GOD_MODE_OFF = 306, + TRIG_ON_PLAYER_REPORTED_CHAT = 305, + TRIG_ON_SET_GOD_MODE_ON = 306, + TRIG_ON_SET_GOD_MODE_OFF = 307, TRIG_LAST_TRIGGER }; From b0b8f6d7990a7e3c9838ff1221b20ce17e5788f6 Mon Sep 17 00:00:00 2001 From: John <63141077+AconiteX@users.noreply.github.com> Date: Tue, 17 Aug 2021 09:32:05 -0400 Subject: [PATCH 23/24] Update ScriptFunctionTable.cpp --- .../library/serverScript/src/shared/ScriptFunctionTable.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp index b9d91ae4..c3f80bd8 100755 --- a/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp +++ b/engine/server/library/serverScript/src/shared/ScriptFunctionTable.cpp @@ -330,6 +330,7 @@ static const Scripting::ScriptFuncTable ScriptFuncList[] = {Scripting::TRIG_ENTER_REGION, "OnEnterRegion", "ss"}, {Scripting::TRIG_EXIT_REGION, "OnExitRegion", "ss"}, + {Scripting::TRIG_ON_PLAYER_REPORTED_CHAT, "OnPlayerReportedChat", "Ou"}, //---------------------------------------------------------------------- {Scripting::TRIG_VENDOR_ITEM_COUNT_REPLY, "OnVendorItemCountReply", "ii"}, From cec47798d191435f33654088d617c1426eaa3b9a Mon Sep 17 00:00:00 2001 From: John <63141077+AconiteX@users.noreply.github.com> Date: Tue, 17 Aug 2021 10:47:57 -0400 Subject: [PATCH 24/24] Update Client.cpp --- engine/server/library/serverGame/src/shared/core/Client.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 79bc4f56..78f2c8ca 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -1992,6 +1992,9 @@ bool Client::setGodMode(bool value) { m_godLevel = 0; m_godMode = false; m_godValidated = false; + // reset observers and notify cells of potential change + CellPermissions::ViewerChangeObserver o(creatureObject); + ObserveTracker::onGodModeChanged(*this); // remove the characterAbility "admin" so GM commands aren't sent by the client while not in God Mode IGNORE_RETURN(creatureObject->revokeCommand(AdminAccountManager::getAdminCommandName(), false, true)); return true;