From 8f48391b79a6e29b6d2bcf59c82a227ba98d1230 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Thu, 29 Dec 2016 00:59:54 -0600 Subject: [PATCH 01/55] trying to figure out where i'm causing us to hang --- .../serverDatabase/src/shared/Persister.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/engine/server/library/serverDatabase/src/shared/Persister.cpp b/engine/server/library/serverDatabase/src/shared/Persister.cpp index a28fb55e..eef85c8e 100755 --- a/engine/server/library/serverDatabase/src/shared/Persister.cpp +++ b/engine/server/library/serverDatabase/src/shared/Persister.cpp @@ -392,8 +392,6 @@ void Persister::startSave(void) */ Snapshot * Persister::getSnapshotForObject(const NetworkId &networkId, uint32 serverId) { - pad.lock(); - auto i = m_objectSnapshotMap.find(networkId); if (i!=m_objectSnapshotMap.end()) { @@ -406,6 +404,9 @@ Snapshot * Persister::getSnapshotForObject(const NetworkId &networkId, uint32 se else { Snapshot *snap = getSnapshotForServer(serverId); + + pad.lock(); + m_objectSnapshotMap[networkId]=snap; pad.unlock(); @@ -426,8 +427,6 @@ bool Persister::hasDataForObject(const NetworkId &objectId) const Snapshot *Persister::getSnapshotForServer(uint32 serverId) { - pad.lock(); - if (serverId==0) { if (!m_arbitraryGameDataSnapshot) @@ -435,9 +434,6 @@ Snapshot *Persister::getSnapshotForServer(uint32 serverId) m_arbitraryGameDataSnapshot = makeSnapshot(DB::ModeQuery::mode_UPDATE); m_currentSnapshots[0] = m_arbitraryGameDataSnapshot; } - - pad.unlock(); - return m_arbitraryGameDataSnapshot; } else @@ -452,18 +448,12 @@ Snapshot *Persister::getSnapshotForServer(uint32 serverId) if (!m_arbitraryGameDataSnapshot) { m_arbitraryGameDataSnapshot = snap; } - - pad.unlock(); - return snap; } else { NOT_NULL (j->second); - - pad.unlock(); - return j->second; } } From 46d49e9bac11a54b1e291d5d9c111d7693851f7d Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sat, 31 Dec 2016 21:13:11 -0600 Subject: [PATCH 02/55] i know this is probably broken but i'll get it working --- .../src/shared/ConnectionServer.cpp | 24 +++---- .../src/shared/ClientConnection.cpp | 63 ++++++++++--------- .../LoginServer/src/shared/LoginServer.cpp | 24 +++---- .../projects/Session/CommonAPI/CommonAPI.h | 2 +- 4 files changed, 59 insertions(+), 54 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp index ef838c04..6eb0c07d 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp @@ -98,7 +98,6 @@ ConnectionServer::ConnectionServer() : networkBarrier(0), pingSocket(new UdpSock), m_recoverTime(0), - m_sessionApiClient(0), m_pingTrafficNumBytes(0), m_recoveringClientList() { @@ -1106,10 +1105,10 @@ void ConnectionServer::update() } } - if (m_sessionApiClient) + /*if (m_sessionApiClient) { m_sessionApiClient->update(); - } + }*/ static const int ping_throttle_max = 1024; @@ -1430,7 +1429,7 @@ CentralConnection * ConnectionServer::getCentralConnection() void ConnectionServer::installSessionValidation() { - int i = 0; + /*int i = 0; std::vector sessionServers; int const numberOfSessionServers = ConfigConnectionServer::getNumberOfSessionServers(); for (i = 0; i < numberOfSessionServers; ++i) @@ -1445,7 +1444,8 @@ void ConnectionServer::installSessionValidation() // if there were none specified, use defaults FATAL(i == 0, ("No session servers specified for session API")); - m_sessionApiClient = new SessionApiClient(&sessionServers[0], i); + m_sessionApiClient = new SessionApiClient(&sessionServers[0], i);*/ + return; } // ---------------------------------------------------------------------- @@ -1575,14 +1575,14 @@ SessionApiClient* ConnectionServer::getSessionApiClient() { // this is causing crashes when ConnectionServer is shutdown and something calls this function // because instance() returns 0. - if (s_connectionServer) - { - return instance().m_sessionApiClient; - } - else - { + //if (s_connectionServer) + //{ + // return instance().m_sessionApiClient; + //} + //else + //{ return 0; - } + //} } // ---------------------------------------------------------------------- diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 1fc22180..5f5046dd 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -10,7 +10,7 @@ #include "DatabaseConnection.h" #include "ConfigLoginServer.h" -#include "SessionApiClient.h" +//#include "SessionApiClient.h" #include "sharedLog/Log.h" #include "sharedNetworkMessages/ClientLoginMessages.h" #include "sharedNetworkMessages/DeleteCharacterMessage.h" @@ -58,12 +58,12 @@ void ClientConnection::onConnectionClosed() { LoginServer::getInstance().removeClient(m_clientId); - if ((ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) && !m_isValidated) { + /* if ((ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) && !m_isValidated) { SessionApiClient *session = LoginServer::getInstance().getSessionApiClient(); if (session) { session->dropClient(this); } - } + }*/ } @@ -171,13 +171,14 @@ void ClientConnection::validateClient(const std::string &id, const std::string & std::string uname; std::string parentAccount; + std::string sessionID; StationId user_id; StationId parent_id; std::unordered_map childAccounts; if (!authURL.empty()) { // create the object - webAPI api(authURL); + webAPI api(authURL); // add our data api.addJsonData("user_name", id); @@ -187,15 +188,16 @@ void ClientConnection::validateClient(const std::string &id, const std::string & if (api.submit()) { bool status = api.getNullableValue("status"); uname = api.getString("username"); + sessionID = api.getString("session_key"); - if (status && !uname.empty()) { + if (status && !sessionID.empty() && !uname.empty()) { authOK = true; parentAccount = api.getString("mainAccount"); childAccounts = api.getStringMap("subAccounts"); - user_id = static_cast(api.getNullableValue("user_id")); - parent_id = static_cast(api.getNullableValue("parent_id")); + user_id = static_cast(api.getNullableValue("user_id")); + parent_id = static_cast(api.getNullableValue("parent_id")); } else { std::string msg(api.getString("message")); if (msg.empty()) { @@ -216,38 +218,39 @@ void ClientConnection::validateClient(const std::string &id, const std::string & } if (authOK && user_id && parent_id) { - REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); + REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); - if (!parentAccount.empty()) { - if (parentAccount != uname) { - REPORT_LOG(true, ("\t%s's parent is %s (%i) \n", uname.c_str(), parentAccount.c_str(), parent_id)); - } - } else { - parentAccount = "(Empty Parent!) "+uname; - } + if (!parentAccount.empty()) { + if (parentAccount != uname) { + REPORT_LOG(true, ("\t%s's parent is %s (%i) \n", uname.c_str(), parentAccount.c_str(), parent_id)); + } + } else { + parentAccount = "(Empty Parent!) " + uname; + } for (auto i : childAccounts) { - StationId child_id = static_cast(i.first); - std::string child(i.second); + StationId child_id = static_cast(i.first); + std::string child(i.second); - if (!child.empty()) { - REPORT_LOG((parent_id != child_id), ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); - - // insert all related accounts, if not already there, into the db - if (parent_id != child_id) { - DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); - } - } else { - WARNING(true, ("Login API returned empty child account(s).")); - } - } + if (!child.empty()) { + REPORT_LOG((parent_id != child_id), + ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); + + // insert all related accounts, if not already there, into the db + if (parent_id != child_id) { + DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); + } + } else { + WARNING(true, ("Login API returned empty child account(s).")); + } + } LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); - m_stationId = user_id; + m_stationId = user_id; - LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, NULL, 0xFFFFFFFF, 0xFFFFFFFF); + LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, sessionID.c_str(), 0xFFFFFFFF, 0xFFFFFFFF); } } diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index db98bbb0..d5dff322 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -22,7 +22,7 @@ #include "MonAPI2/MonitorAPI.h" #include "PingConnection.h" #include "PurgeManager.h" -#include "SessionApiClient.h" +//#include "SessionApiClient.h" #include "UnicodeUtils.h" #include "serverKeyShare/KeyServer.h" #include "serverNetworkMessages/AccountFeatureIdRequest.h" @@ -140,7 +140,6 @@ LoginServer::LoginServer() : keyServer(0), m_clientMap(), m_clusterList(), - m_sessionApiClient(0), m_validatedClientMap(), m_clusterStatusChanged(false), m_soeMonitor(0) @@ -203,10 +202,10 @@ LoginServer::LoginServer() : connectToMessage("FeatureIdTransactionSyncUpdate"); keyServer = new KeyServer; - if (ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) + /*if (ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) { installSessionValidation(); - } + }*/ } //----------------------------------------------------------------------- @@ -269,7 +268,7 @@ void LoginServer::removeClient(int clientId) void LoginServer::installSessionValidation() { - int i = 0; + /*int i = 0; std::vector sessionServers; int numberOfSessionServers = ConfigLoginServer::getNumberOfSessionServers(); @@ -286,7 +285,9 @@ void LoginServer::installSessionValidation() // if there were none specified, use defaults FATAL(i == 0, ("No session servers specified for session API")); - m_sessionApiClient = new SessionApiClient(&sessionServers[0], i); + m_sessionApiClient = new SessionApiClient(&sessionServers[0], i);*/ + + return; } //----------------------------------------------------------------------- @@ -334,7 +335,8 @@ const KeyShare::Key & LoginServer::getCurrentKey(void) const SessionApiClient * LoginServer::getSessionApiClient() { - return m_sessionApiClient; + return true; + //return m_sessionApiClient; } //----------------------------------------------------------------------- @@ -913,7 +915,7 @@ void LoginServer::receiveMessage(const MessageDispatch::Emitter & source, const { if (m_sessionApiClient) { - if (consumeAccountFeatureId) + /*if (consumeAccountFeatureId) { // request session/Platform to update the account feature id // SessionApiClient will own (and delete) msg @@ -931,7 +933,7 @@ void LoginServer::receiveMessage(const MessageDispatch::Emitter & source, const DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), requiredAccountFeatureId, false, oldFeature.GetConsumeCount(), newFeature.GetConsumeCount()); delete msg; - } + }*/ } else { @@ -1200,8 +1202,8 @@ void LoginServer::run(void) getInstance().m_clusterStatusChanged = false; } - if (getInstance().m_sessionApiClient) - getInstance().m_sessionApiClient->Process(); + //if (getInstance().m_sessionApiClient) + // getInstance().m_sessionApiClient->Process(); totalTime += limit; //TODO: make a better way to do this if (!ConfigLoginServer::getDevelopmentMode() && (totalTime > 10000)) diff --git a/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h b/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h index aaa9d668..fa6e214d 100755 --- a/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h +++ b/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h @@ -306,7 +306,7 @@ class apiSubscription unsigned mParentalLimitSeconds; }; -static const int apiSessionIdWidth = 17; +static const int apiSessionIdWidth = 45; struct apiSession_v1; class apiSession { From 0e6ac65c2a89a7eb8c61ba42237453cad51155a2 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sat, 31 Dec 2016 21:49:22 -0600 Subject: [PATCH 03/55] dumb of me --- .../application/LoginServer/src/shared/ClientConnection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 5f5046dd..55bd2094 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -10,7 +10,7 @@ #include "DatabaseConnection.h" #include "ConfigLoginServer.h" -//#include "SessionApiClient.h" +#include "SessionApiClient.h" #include "sharedLog/Log.h" #include "sharedNetworkMessages/ClientLoginMessages.h" #include "sharedNetworkMessages/DeleteCharacterMessage.h" @@ -217,7 +217,7 @@ void ClientConnection::validateClient(const std::string &id, const std::string & uname = id; } - if (authOK && user_id && parent_id) { + if (authOK) { REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); if (!parentAccount.empty()) { From a0f86b45e75593dfa6d16cbc3f114f3f5c728dea Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 03:51:21 +0000 Subject: [PATCH 04/55] also dumb --- .../application/LoginServer/src/shared/LoginServer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index d5dff322..56cb3758 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -22,7 +22,7 @@ #include "MonAPI2/MonitorAPI.h" #include "PingConnection.h" #include "PurgeManager.h" -//#include "SessionApiClient.h" +#include "SessionApiClient.h" #include "UnicodeUtils.h" #include "serverKeyShare/KeyServer.h" #include "serverNetworkMessages/AccountFeatureIdRequest.h" @@ -335,8 +335,7 @@ const KeyShare::Key & LoginServer::getCurrentKey(void) const SessionApiClient * LoginServer::getSessionApiClient() { - return true; - //return m_sessionApiClient; + return m_sessionApiClient; } //----------------------------------------------------------------------- From b144bbd265d3c8b75daeab7a5eb349d855023dba Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sat, 31 Dec 2016 21:56:41 -0600 Subject: [PATCH 05/55] maybe get closer... --- .../application/LoginServer/src/shared/LoginServer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 56cb3758..a2abb2d5 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -1422,9 +1422,9 @@ void LoginServer::onValidateClient(StationId suid, const std::string & username, if (ConfigLoginServer::getDoConsumption() || ConfigLoginServer::getDoSessionLogin()) { // pass the sessionkey - len = apiSessionIdWidth + sizeof(StationId); - memcpy(keyBufferPointer, sessionKey, apiSessionIdWidth); - keyBufferPointer += apiSessionIdWidth; + //len = apiSessionIdWidth + sizeof(StationId); + memcpy(keyBufferPointer, sessionKey, sizeof(sessionKey)); + keyBufferPointer += sizeof(sessionKey); memcpy(keyBufferPointer, &suid, sizeof(StationId)); // if LoginServer did session login, send the session key back to the client; @@ -1432,7 +1432,7 @@ void LoginServer::onValidateClient(StationId suid, const std::string & username, // where the LoginServer does the session login, it will get it from the LoginServer if (ConfigLoginServer::getDoSessionLogin()) { - std::string const strSessionKey(sessionKey, apiSessionIdWidth); + std::string const strSessionKey(sessionKey, sizeof(sessionKey)); GenericValueTypeMessage const msg("SetSessionKey", strSessionKey); conn->send(msg, true); } From a00bff8842cc2e0f8e6f5b73e38dab6f5fca7f65 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sat, 31 Dec 2016 22:35:15 -0600 Subject: [PATCH 06/55] this may just work --- .../src/shared/ClientConnection.cpp | 2545 ++++++++--------- .../src/shared/ConfigConnectionServer.cpp | 1 + .../src/shared/ConfigConnectionServer.h | 526 ++-- .../LoginServer/src/shared/LoginServer.cpp | 8 +- 4 files changed, 1506 insertions(+), 1574 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 1f31a950..35b9c496 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -54,11 +54,14 @@ #include +#include "webAPI.h" + +using namespace StellaBellum; + //----------------------------------------------------------------------- -namespace ClientConnectionNamespace -{ - unsigned long gs_receiveDelayMaxMs = 16384; +namespace ClientConnectionNamespace { + unsigned long gs_receiveDelayMaxMs = 16384; } using namespace ClientConnectionNamespace; @@ -69,228 +72,217 @@ using namespace ClientConnectionNamespace; //----------------------------------------------------------------------- -std::map< std::string, uint32 > ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute -std::map< std::string, uint32 > ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute -uint32 ClientConnection::sm_outgoingBytesMap_Worktime = 0 ; // time we started filling in the working map +std::map ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute +std::map ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute +uint32 ClientConnection::sm_outgoingBytesMap_Worktime = 0; // time we started filling in the working map //----------------------------------------------------------------------- -ClientConnection::ClientConnection(UdpConnectionMT * u, TcpClient * t) : -ServerConnection(u, t), -m_accountName(""), -m_canCreateRegularCharacter(false), -m_canCreateJediCharacter(false), -m_hasRequestedCharacterCreate(false), -m_hasCreatedCharacter(false), -m_pendingCharacterCreate(nullptr), -m_canSkipTutorial(false), -m_characterId(NetworkId::cms_invalid), -m_characterName(), -m_startPlayTime(0), -m_lastActiveTime(0), -m_activePlayTimeDuration(0), -m_client(0), -m_containerId(NetworkId::cms_invalid), -m_featureBitsGame(0), -m_featureBitsSubscription(0), -m_hasBeenSentToGameServer(false), -m_hasBeenValidated(false), -m_hasSelectedCharacter(false), -m_isSecure(false), -m_isAdminAccount(false), -m_hasCSLoggedAccountFeatureIds(false), -m_suid(0), -m_requestedSuid(0), -m_usingAdminLogin(false), -m_targetCoordinates(), -m_targetScene(""), -m_validatingCharacter(false), -m_receiveHistoryBytes(0), -m_receiveHistoryPackets(0), -m_receiveHistoryMs(0), -m_receiveLastTimeMs(0), -m_sendLastTimeMs(0), -m_sessionId(""), -m_sessionValidated(false), -m_connectionServerLag(0), -m_gameServerLag(0), -m_countSpamLimitResetTime(0), -m_entitlementTotalTime(0), -m_entitlementEntitledTime(0), -m_entitlementTotalTimeSinceLastLogin(0), -m_entitlementEntitledTimeSinceLastLogin(0), -m_buddyPoints(0), -m_sendToStarport(false), -m_pendingChatEnterRoomRequests(), -m_pendingChatQueryRoomRequests() -{ - static const std::string loginTrace("TRACE_LOGIN"); - LOG(loginTrace, ("new ClientConnection")); +ClientConnection::ClientConnection(UdpConnectionMT *u, TcpClient *t) : + ServerConnection(u, t), + m_accountName(""), + m_canCreateRegularCharacter(false), + m_canCreateJediCharacter(false), + m_hasRequestedCharacterCreate(false), + m_hasCreatedCharacter(false), + m_pendingCharacterCreate(nullptr), + m_canSkipTutorial(false), + m_characterId(NetworkId::cms_invalid), + m_characterName(), + m_startPlayTime(0), + m_lastActiveTime(0), + m_activePlayTimeDuration(0), + m_client(0), + m_containerId(NetworkId::cms_invalid), + m_featureBitsGame(0), + m_featureBitsSubscription(0), + m_hasBeenSentToGameServer(false), + m_hasBeenValidated(false), + m_hasSelectedCharacter(false), + m_isSecure(false), + m_isAdminAccount(false), + m_hasCSLoggedAccountFeatureIds(false), + m_suid(0), + m_requestedSuid(0), + m_usingAdminLogin(false), + m_targetCoordinates(), + m_targetScene(""), + m_validatingCharacter(false), + m_receiveHistoryBytes(0), + m_receiveHistoryPackets(0), + m_receiveHistoryMs(0), + m_receiveLastTimeMs(0), + m_sendLastTimeMs(0), + m_sessionId(""), + m_sessionValidated(false), + m_connectionServerLag(0), + m_gameServerLag(0), + m_countSpamLimitResetTime(0), + m_entitlementTotalTime(0), + m_entitlementEntitledTime(0), + m_entitlementTotalTimeSinceLastLogin(0), + m_entitlementEntitledTimeSinceLastLogin(0), + m_buddyPoints(0), + m_sendToStarport(false), + m_pendingChatEnterRoomRequests(), + m_pendingChatQueryRoomRequests() { + static const std::string loginTrace("TRACE_LOGIN"); + LOG(loginTrace, ("new ClientConnection")); - setNoDataTimeout(600000); + setNoDataTimeout(600000); } //----------------------------------------------------------------------- -ClientConnection::~ClientConnection() -{ - bool hasBeenKicked = false; +ClientConnection::~ClientConnection() { + bool hasBeenKicked = false; - if (ConnectionServer::getClientConnection(m_suid) == this) - { - ConnectionServer::removeConnectedCharacter(m_suid); - } - if (m_client) - { - hasBeenKicked = m_client->hasBeenKicked(); - delete m_client; - m_client = nullptr; - } + if (ConnectionServer::getClientConnection(m_suid) == this) { + ConnectionServer::removeConnectedCharacter(m_suid); + } + if (m_client) { + hasBeenKicked = m_client->hasBeenKicked(); + delete m_client; + m_client = nullptr; + } - // tell Session to stop recording play time for the character - if (m_hasBeenValidated && m_sessionValidated && ConnectionServer::getSessionApiClient() && (m_lastActiveTime > 0) && ConfigConnectionServer::getSessionRecordPlayTime()) - { - LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + // tell Session to stop recording play time for the character + if (m_hasBeenValidated && m_sessionValidated && ConnectionServer::getSessionApiClient() && (m_lastActiveTime > 0) && + ConfigConnectionServer::getSessionRecordPlayTime()) { + LOG("CustomerService", + ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); - // log total active play time for the session to the balance log - LOG("GameBalance", ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); + // log total active play time for the session to the balance log + LOG("GameBalance", + ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); - ConnectionServer::getSessionApiClient()->stopPlay(*this); - } + ConnectionServer::getSessionApiClient()->stopPlay(*this); + } - if (ConnectionServer::getSessionApiClient()) - { - ConnectionServer::getSessionApiClient()->dropClient(this, hasBeenKicked); - } + if (ConnectionServer::getSessionApiClient()) { + ConnectionServer::getSessionApiClient()->dropClient(this, hasBeenKicked); + } - std::map::const_iterator iter; - for (iter = m_pendingChatEnterRoomRequests.begin(); iter != m_pendingChatEnterRoomRequests.end(); ++iter) - { - delete iter->second; - } - m_pendingChatEnterRoomRequests.clear(); + std::map::const_iterator iter; + for (iter = m_pendingChatEnterRoomRequests.begin(); iter != m_pendingChatEnterRoomRequests.end(); ++iter) { + delete iter->second; + } + m_pendingChatEnterRoomRequests.clear(); - for (iter = m_pendingChatQueryRoomRequests.begin(); iter != m_pendingChatQueryRoomRequests.end(); ++iter) - { - delete iter->second; - } - m_pendingChatQueryRoomRequests.clear(); + for (iter = m_pendingChatQueryRoomRequests.begin(); iter != m_pendingChatQueryRoomRequests.end(); ++iter) { + delete iter->second; + } + m_pendingChatQueryRoomRequests.clear(); - delete m_pendingCharacterCreate; - m_pendingCharacterCreate = nullptr; + delete m_pendingCharacterCreate; + m_pendingCharacterCreate = nullptr; } //----------------------------------------------------------------------- -const NetworkId & ClientConnection::getCharacterId() const -{ - return m_characterId; +const NetworkId &ClientConnection::getCharacterId() const { + return m_characterId; } //----------------------------------------------------------------------- -const std::string & ClientConnection::getCharacterName() const -{ - return m_characterName; +const std::string &ClientConnection::getCharacterName() const { + return m_characterName; } //----------------------------------------------------------------------- -std::string ClientConnection::getPlayTimeDuration() const -{ - int playTimeDuration = 0; +std::string ClientConnection::getPlayTimeDuration() const { + int playTimeDuration = 0; - if (m_startPlayTime > 0) - playTimeDuration = static_cast(::time(nullptr) - m_startPlayTime); + if (m_startPlayTime > 0) + playTimeDuration = static_cast(::time(nullptr) - m_startPlayTime); - return CalendarTime::convertSecondsToHMS(static_cast(playTimeDuration)); + return CalendarTime::convertSecondsToHMS(static_cast(playTimeDuration)); } //----------------------------------------------------------------------- -std::string ClientConnection::getActivePlayTimeDuration() const -{ - int activePlayTimeDuration = static_cast(m_activePlayTimeDuration); +std::string ClientConnection::getActivePlayTimeDuration() const { + int activePlayTimeDuration = static_cast(m_activePlayTimeDuration); - if (m_lastActiveTime > 0) - activePlayTimeDuration += static_cast(::time(nullptr) - m_lastActiveTime); + if (m_lastActiveTime > 0) + activePlayTimeDuration += static_cast(::time(nullptr) - m_lastActiveTime); - return CalendarTime::convertSecondsToHMS(static_cast(activePlayTimeDuration)); + return CalendarTime::convertSecondsToHMS(static_cast(activePlayTimeDuration)); } //----------------------------------------------------------------------- -std::string ClientConnection::getCurrentActivePlayTimeDuration() const -{ - int activePlayTimeDuration = 0; +std::string ClientConnection::getCurrentActivePlayTimeDuration() const { + int activePlayTimeDuration = 0; - if (m_lastActiveTime > 0) - activePlayTimeDuration = static_cast(::time(nullptr) - m_lastActiveTime); + if (m_lastActiveTime > 0) + activePlayTimeDuration = static_cast(::time(nullptr) - m_lastActiveTime); - return CalendarTime::convertSecondsToHMS(static_cast(activePlayTimeDuration)); + return CalendarTime::convertSecondsToHMS(static_cast(activePlayTimeDuration)); } //----------------------------------------------------------------------- -void ClientConnection::sendPlayTimeInfoToGameServer() const -{ - if (m_client && m_client->getGameConnection()) - { - // update the game server with play time info - GenericValueTypeMessage > > const msgPlayTimeInfo( - "UpdateSessionPlayTimeInfo", - std::make_pair(static_cast(m_startPlayTime), - std::make_pair(static_cast(m_lastActiveTime), m_activePlayTimeDuration) - ) - ); +void ClientConnection::sendPlayTimeInfoToGameServer() const { + if (m_client && m_client->getGameConnection()) { + // update the game server with play time info + GenericValueTypeMessage > > const msgPlayTimeInfo( + "UpdateSessionPlayTimeInfo", + std::make_pair(static_cast(m_startPlayTime), + std::make_pair(static_cast(m_lastActiveTime), m_activePlayTimeDuration) + ) + ); - std::vector v; - v.push_back(m_client->getNetworkId()); - GameClientMessage const gcm(v, true, msgPlayTimeInfo); - m_client->getGameConnection()->send(gcm, true); - } + std::vector v; + v.push_back(m_client->getNetworkId()); + GameClientMessage const gcm(v, true, msgPlayTimeInfo); + m_client->getGameConnection()->send(gcm, true); + } } // ---------------------------------------------------------------------- -void ClientConnection::handleSelectCharacterMessage(const SelectCharacter& msg) -{ - //Only accept this message from clients who have been validated and - //haven't already selected. - if (m_hasSelectedCharacter || m_validatingCharacter || !m_hasBeenValidated || !m_sessionValidated) - { - if(m_hasSelectedCharacter) - { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has already selected a character", getSUID())); - } - if(m_validatingCharacter) - { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not yet received validation", getSUID())); - } - if(!m_hasBeenValidated) - { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been validated", getSUID())); - } - if (!m_sessionValidated) - { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been session validated", getSUID())); - } +void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) { + //Only accept this message from clients who have been validated and + //haven't already selected. + if (m_hasSelectedCharacter || m_validatingCharacter || !m_hasBeenValidated || !m_sessionValidated) { + if (m_hasSelectedCharacter) { + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has already selected a character", getSUID())); + } + if (m_validatingCharacter) { + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has not yet received validation", getSUID())); + } + if (!m_hasBeenValidated) { + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has not been validated", getSUID())); + } + if (!m_sessionValidated) { + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has not been session validated", getSUID())); + } - return; - } + return; + } - m_validatingCharacter = true; + m_validatingCharacter = true; - // The client is picking a character from the list the Login Server gave him. - // But we don't trust him not to cheat, so we double-check that he really - // owns the character he selected. + // The client is picking a character from the list the Login Server gave him. + // But we don't trust him not to cheat, so we double-check that he really + // owns the character he selected. - ValidateCharacterForLoginMessage vclm(getSUID(), msg.getId()); - ConnectionServer::sendToCentralProcess(vclm); - LOG("TraceCharacterSelection", ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); + ValidateCharacterForLoginMessage vclm(getSUID(), msg.getId()); + ConnectionServer::sendToCentralProcess(vclm); + LOG("TraceCharacterSelection", + ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); } @@ -301,10 +293,9 @@ void ClientConnection::handleSelectCharacterMessage(const SelectCharacter& msg) * is in the process of logging in). * Connect the player with the game server. */ -void ClientConnection::handleGameServerForLoginMessage(uint32 serverId) -{ - DEBUG_WARNING(serverId==0,("Got handleGameServerForLoginMessage with serverId=0.\n")); - IGNORE_RETURN( sendToGameServer(serverId) ); +void ClientConnection::handleGameServerForLoginMessage(uint32 serverId) { + DEBUG_WARNING(serverId == 0, ("Got handleGameServerForLoginMessage with serverId=0.\n")); + IGNORE_RETURN(sendToGameServer(serverId)); } //---------------------------------------------------------------------- @@ -314,919 +305,880 @@ void ClientConnection::handleGameServerForLoginMessage(uint32 serverId) * to be validated. Central will reply with a list of permissions. * @see onIdValidated */ -void ClientConnection::handleClientIdMessage(const ClientIdMsg& msg) -{ - //Only check clients that have not been validated. - if (m_hasBeenValidated) - return; +void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { + //Only check clients that have not been validated. + if (m_hasBeenValidated) + return; - DEBUG_FATAL(m_hasSelectedCharacter, ("Trying to validate a client who already has a character selected.\n")); - bool result = false; - char sessionId[apiSessionIdWidth]; + DEBUG_FATAL(m_hasSelectedCharacter, ("Trying to validate a client who already has a character selected.\n")); + bool result = false; + char sessionId[apiSessionIdWidth]; - m_gameBitsToClear = msg.getGameBitsToClear(); + m_gameBitsToClear = msg.getGameBitsToClear(); - if(msg.getTokenSize() > 0) - { - Archive::ByteStream t(msg.getToken(), msg.getTokenSize()); - Archive::ReadIterator ri(t); - KeyShare::Token token(ri); + if (msg.getTokenSize() > 0) { + Archive::ByteStream t(msg.getToken(), msg.getTokenSize()); + Archive::ReadIterator ri(t); + KeyShare::Token token(ri); - if (!ConfigConnectionServer::getValidateStationKey()) - { - // get SUID from token - result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); - } - else - { - result = ConnectionServer::decryptToken(token, sessionId, m_requestedSuid); - } + static const std::string authURL(ConfigConnectionServer::getSessionURL()); - static const std::string loginTrace("TRACE_LOGIN"); - LOG(loginTrace, ("ClientConnection SUID = %d", m_suid)); + if (!authURL.empty()) { + webAPI api(authURL); - } - if (result) - { - //check for duplicate login - ClientConnection * oldConnection = ConnectionServer::getClientConnection(m_suid); - if (oldConnection) - { - //There is already someone connected to this cluster with this suid. - LOG("Network", ("SUID %d already logged in, disconnecting client.\n", m_suid)); + std::string clientIP = getRemoteAddress(); - ConnectionServer::dropClient(oldConnection, "Already Connected"); + // add our data + api.addJsonData("session_key", std::string(sessionId)); + api.addJsonData("ip", clientIP); - disconnect(); - return; - } + if (api.submit()) { + bool status = api.getNullableValue("status"); - // verify version - if (ConfigConnectionServer::getValidateClientVersion() && msg.getVersion() != GameNetworkMessage::NetworkVersionId) - { - std::string strSessionId(sessionId, apiSessionIdWidth); - strSessionId += '\0'; + if (status) { + StationId apiSuid = api.getNullableValue("user_id"); + int expired = api.getNullableValue("expired"); + std::string apiUser = api.getString("user_name"); + std::string apiIP = api.getString("ip"); - const int bufferSize = 255 + apiSessionIdWidth; - char * buffer = new char[bufferSize]; - snprintf(buffer, bufferSize-1, "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), GameNetworkMessage::NetworkVersionId.c_str()); - buffer[bufferSize-1] = '\0'; + if (!expired) { + if (apiSuid && apiSuid == m_suid && apiIP == clientIP) { + result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + } + } + } + } else { + result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + } + } else { // assume local testing + result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + } - ConnectionServer::dropClient(this, std::string(buffer)); - disconnect(); + static const std::string loginTrace("TRACE_LOGIN"); + LOG(loginTrace, ("ClientConnection SUID = %d", m_suid)); - delete[] buffer; + } + if (result) { + //check for duplicate login + ClientConnection *oldConnection = ConnectionServer::getClientConnection(m_suid); + if (oldConnection) { + //There is already someone connected to this cluster with this suid. + LOG("Network", ("SUID %d already logged in, disconnecting client.\n", m_suid)); - return; - } + ConnectionServer::dropClient(oldConnection, "Already Connected"); - if (ConfigConnectionServer::getValidateStationKey()) - { - SessionApiClient * session = ConnectionServer::getSessionApiClient(); - NOT_NULL(session); - if(session) - { - session->validateClient(this, sessionId); - } - else - { - ConnectionServer::dropClient(this, "SessionApiClient is not available!"); - disconnect(); - } - } - else - { - if (!m_suid) { - m_suid = atoi(m_accountName.c_str()); - if (m_suid == 0) - { - - std::hash h; - m_suid = h(m_accountName.c_str()); - } - } - onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, ConfigConnectionServer::getDefaultGameFeatures(), ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, ConfigConnectionServer::getFakeBuddyPoints()); - } - } - else - { - // They sent us a token that was no good -- either a hack attempt, or - // possibly it was just too old. - LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); - disconnect(); - } + disconnect(); + return; + } + + // verify version + if (ConfigConnectionServer::getValidateClientVersion() && + msg.getVersion() != GameNetworkMessage::NetworkVersionId) { + std::string strSessionId(sessionId, apiSessionIdWidth); + strSessionId += '\0'; + + const int bufferSize = 255 + apiSessionIdWidth; + char *buffer = new char[bufferSize]; + snprintf(buffer, bufferSize - 1, + "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", + getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), + GameNetworkMessage::NetworkVersionId.c_str()); + buffer[bufferSize - 1] = '\0'; + + ConnectionServer::dropClient(this, std::string(buffer)); + disconnect(); + + delete[] buffer; + + return; + } + + if (ConfigConnectionServer::getValidateStationKey()) { + SessionApiClient *session = ConnectionServer::getSessionApiClient(); + NOT_NULL(session); + if (session) { + session->validateClient(this, sessionId); + } else { + ConnectionServer::dropClient(this, "SessionApiClient is not available!"); + disconnect(); + } + } else { + if (!m_suid) { + m_suid = atoi(m_accountName.c_str()); + if (m_suid == 0) { + + std::hash h; + m_suid = h(m_accountName.c_str()); + } + } + onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, + ConfigConnectionServer::getDefaultGameFeatures(), + ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, + ConfigConnectionServer::getFakeBuddyPoints()); + } + } else { + // They sent us a token that was no good -- either a hack attempt, or + // possibly it was just too old. + LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); + disconnect(); + } } //----------------------------------------------------------------------- -void ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems) -{ - //@todo start session with station. - //@todo add more permissions to this message as needed. +void ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, + bool canSkipTutorial, + std::vector > const &consumedRewardEvents, + std::vector > const &claimedRewardItems) { + //@todo start session with station. + //@todo add more permissions to this message as needed. - // resume character creation - if (m_pendingCharacterCreate) - { - if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n",getSUID())); - disconnect(); - } - else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n",getSUID())); - disconnect(); - } - else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n",getSUID())); - disconnect(); - } - else - { - ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); - LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); + // resume character creation + if (m_pendingCharacterCreate) { + if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + disconnect(); + } else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + disconnect(); + } else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + disconnect(); + } else { + ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); + LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); - m_hasRequestedCharacterCreate = true; - } + m_hasRequestedCharacterCreate = true; + } - delete m_pendingCharacterCreate; - m_pendingCharacterCreate = nullptr; + delete m_pendingCharacterCreate; + m_pendingCharacterCreate = nullptr; - return; - } + return; + } - // Save lists of claimed rewards, which won't be used again until later in the login sequence - m_consumedRewardEvents = consumedRewardEvents; - m_claimedRewardItems = claimedRewardItems; + // Save lists of claimed rewards, which won't be used again until later in the login sequence + m_consumedRewardEvents = consumedRewardEvents; + m_claimedRewardItems = claimedRewardItems; - 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 - { - canLogin = true; - canCreateRegularCharacter = true; - canSkipTutorial = true; - m_isAdminAccount = true; - } + 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 + { + canLogin = true; + canCreateRegularCharacter = true; + canSkipTutorial = true; + m_isAdminAccount = true; + } - ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial); - send(c, true); + ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial); + send(c, true); - DEBUG_REPORT_LOG(true,("Permissions for %lu:\n",getSUID())); - DEBUG_REPORT_LOG(canLogin,("\tcanLogin\n")); - DEBUG_REPORT_LOG(canCreateRegularCharacter,("\tcanCreateRegularCharacter\n")); - DEBUG_REPORT_LOG(canCreateJediCharacter,("\tcanCreateJediCharacter\n")); - DEBUG_REPORT_LOG(canSkipTutorial,("\tcanSkipTutorial\n")); - DEBUG_REPORT_LOG(!(canLogin || canCreateRegularCharacter || canCreateJediCharacter || canSkipTutorial),("\tnone\n")); + DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID())); + DEBUG_REPORT_LOG(canLogin, ("\tcanLogin\n")); + DEBUG_REPORT_LOG(canCreateRegularCharacter, ("\tcanCreateRegularCharacter\n")); + DEBUG_REPORT_LOG(canCreateJediCharacter, ("\tcanCreateJediCharacter\n")); + DEBUG_REPORT_LOG(canSkipTutorial, ("\tcanSkipTutorial\n")); + DEBUG_REPORT_LOG(!(canLogin || canCreateRegularCharacter || canCreateJediCharacter || canSkipTutorial), + ("\tnone\n")); - if (canLogin) - { - m_hasBeenValidated = true; - m_canCreateRegularCharacter = canCreateRegularCharacter; - m_canCreateJediCharacter = canCreateJediCharacter; - m_canSkipTutorial = canSkipTutorial; - } - else - { - LOG("TRACE_LOGIN", ("%d does not have permissions to log in", getSUID())); - LOG("ClientDisconnect", ("Client (SUID %u) does not have permissions to log in. Disconnecting.", getSUID())); - disconnect(); - } + if (canLogin) { + m_hasBeenValidated = true; + m_canCreateRegularCharacter = canCreateRegularCharacter; + m_canCreateJediCharacter = canCreateJediCharacter; + m_canSkipTutorial = canSkipTutorial; + } else { + LOG("TRACE_LOGIN", ("%d does not have permissions to log in", getSUID())); + LOG("ClientDisconnect", ("Client (SUID %u) does not have permissions to log in. Disconnecting.", getSUID())); + disconnect(); + } } //----------------------------------------------------------------------- -void ClientConnection::onConnectionClosed() -{ - ServerConnection::onConnectionClosed(); - static MessageConnectionCallback m("ClientConnectionClosed"); - emitMessage(m); +void ClientConnection::onConnectionClosed() { + ServerConnection::onConnectionClosed(); + static MessageConnectionCallback m("ClientConnectionClosed"); + emitMessage(m); - LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); - if (m_client) - { - if (!m_client->hasBeenKicked()) - { - LOG("CustomerService", ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount(this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); - } - ChatServerConnection * chatConnection = m_client->getChatConnection(); - if(chatConnection) - { - ChatDisconnectAvatar m(m_characterId); - chatConnection->send(m, true); - } - // We cannot do this here, as this connection will be deleted on - // return from this function already. - //m_client->kick(); - } + LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); + if (m_client) { + if (!m_client->hasBeenKicked()) { + LOG("CustomerService", + ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount( + this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); + } + ChatServerConnection *chatConnection = m_client->getChatConnection(); + if (chatConnection) { + ChatDisconnectAvatar m(m_characterId); + chatConnection->send(m, true); + } + // We cannot do this here, as this connection will be deleted on + // return from this function already. + //m_client->kick(); + } } //----------------------------------------------------------------------- -void ClientConnection::onConnectionOpened() -{ - ServerConnection::onConnectionOpened(); - static MessageConnectionCallback m("ClientConnectionOpened"); - emitMessage(m); - setOverflowLimit(ConfigConnectionServer::getClientOverflowLimit()); +void ClientConnection::onConnectionOpened() { + ServerConnection::onConnectionOpened(); + static MessageConnectionCallback m("ClientConnectionOpened"); + emitMessage(m); + setOverflowLimit(ConfigConnectionServer::getClientOverflowLimit()); } //----------------------------------------------------------------------- -void ClientConnection::onConnectionOverflowing (const unsigned int bytesPending) -{ - char errbuf[1024]; - snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", bytesPending); - LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); +void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) { + char errbuf[1024]; + snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", + bytesPending); + LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); - std::vector >::const_iterator i; - for(i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) - { - LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); - } + std::vector >::const_iterator i; + for (i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) { + LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); + } // ErrorMessage err(name, desc, false); // send(err, true); - WARNING(true, (errbuf)); - LOG("ClientDisconnect", ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); + WARNING(true, (errbuf)); + LOG("ClientDisconnect", + ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); - snprintf(errbuf, sizeof(errbuf)-1, "Connection Overflow (bytes pending=%u)", bytesPending); - errbuf[sizeof(errbuf)-1] = '\0'; - ConnectionServer::dropClient(this, std::string(errbuf)); + snprintf(errbuf, sizeof(errbuf) - 1, "Connection Overflow (bytes pending=%u)", bytesPending); + errbuf[sizeof(errbuf) - 1] = '\0'; + ConnectionServer::dropClient(this, std::string(errbuf)); } //----------------------------------------------------------------------- -bool ClientConnection::checkSpamLimit(unsigned int messageSize) -{ - if (!ConfigConnectionServer::getSpamLimitEnabled()) - return true; +bool ClientConnection::checkSpamLimit(unsigned int messageSize) { + if (!ConfigConnectionServer::getSpamLimitEnabled()) + return true; - unsigned long curTimeMs = Clock::timeMs(); - if (m_receiveLastTimeMs) - { - ++m_receiveHistoryPackets; - m_receiveHistoryBytes += messageSize; - m_receiveHistoryMs += curTimeMs-m_receiveLastTimeMs; + unsigned long curTimeMs = Clock::timeMs(); + if (m_receiveLastTimeMs) { + ++m_receiveHistoryPackets; + m_receiveHistoryBytes += messageSize; + m_receiveHistoryMs += curTimeMs - m_receiveLastTimeMs; - // rescale the history information if we've exceeded the reset time; this - // must be done before the spam check below or else we may run into overflow - // issues because m_receiveHistoryMs could be pretty large if we haven't - // received anything from the client for a while - while (m_receiveHistoryMs > ConfigConnectionServer::getSpamLimitResetTimeMs()) - { - ++m_countSpamLimitResetTime; + // rescale the history information if we've exceeded the reset time; this + // must be done before the spam check below or else we may run into overflow + // issues because m_receiveHistoryMs could be pretty large if we haven't + // received anything from the client for a while + while (m_receiveHistoryMs > ConfigConnectionServer::getSpamLimitResetTimeMs()) { + ++m_countSpamLimitResetTime; - unsigned int resetScale = ConfigConnectionServer::getSpamLimitResetScaleFactor(); - m_receiveHistoryMs /= resetScale; - m_receiveHistoryBytes /= resetScale; - m_receiveHistoryPackets /= resetScale; - } + unsigned int resetScale = ConfigConnectionServer::getSpamLimitResetScaleFactor(); + m_receiveHistoryMs /= resetScale; + m_receiveHistoryBytes /= resetScale; + m_receiveHistoryPackets /= resetScale; + } - // check for exceeding limits, but wait for at least - // one reset cycle so that there has been enough - // elapsed time, so we won't get a false positive - if (m_countSpamLimitResetTime) - { - if (m_receiveHistoryBytes >= m_receiveHistoryMs*ConfigConnectionServer::getSpamLimitBytesPerSec()/1000) - { - LOG("Network", ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); - return false; - } - if (m_receiveHistoryPackets >= m_receiveHistoryMs*ConfigConnectionServer::getSpamLimitPacketsPerSec()/1000) - { - LOG("Network", ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); - return false; - } - } - } - m_receiveLastTimeMs = curTimeMs; - return true; + // check for exceeding limits, but wait for at least + // one reset cycle so that there has been enough + // elapsed time, so we won't get a false positive + if (m_countSpamLimitResetTime) { + if (m_receiveHistoryBytes >= + m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitBytesPerSec() / 1000) { + LOG("Network", + ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); + return false; + } + if (m_receiveHistoryPackets >= + m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitPacketsPerSec() / 1000) { + LOG("Network", + ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); + return false; + } + } + } + m_receiveLastTimeMs = curTimeMs; + return true; } //----------------------------------------------------------------------- -void ClientConnection::onReceive(const Archive::ByteStream & message) -{ - try - { - if (!checkSpamLimit(message.getSize())) - { - ConnectionServer::dropClient(this, "Spam Detected"); - return; - } +void ClientConnection::onReceive(const Archive::ByteStream &message) { + try { + if (!checkSpamLimit(message.getSize())) { + ConnectionServer::dropClient(this, "Spam Detected"); + return; + } - unsigned long curTimeMs = Clock::timeMs(); - if (m_sendLastTimeMs + std::min(gs_receiveDelayMaxMs, static_cast(Clock::frameTime()*1000.0f)) < curTimeMs) - { - static HeartBeat h; - send(h, false); - } + unsigned long curTimeMs = Clock::timeMs(); + if (m_sendLastTimeMs + + std::min(gs_receiveDelayMaxMs, static_cast(Clock::frameTime() * 1000.0f)) < curTimeMs) { + static HeartBeat h; + send(h, false); + } - Archive::ReadIterator ri = message.begin(); - GameNetworkMessage m(ri); - ri = message.begin(); - - const uint32 messageType = m.getType(); + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage m(ri); + ri = message.begin(); - //Clients with a selected character get routed to a game server. - //@todo check for filtering out bad messages. - if (m_hasSelectedCharacter) - { - // if it is a chat message, send it directly to the chat server - switch(messageType) { - case constcrc("ChatAddFriend") : - case constcrc("ChatAddModeratorToRoom") : - case constcrc("ChatBanAvatarFromRoom") : - case constcrc("ChatCreateRoom") : - case constcrc("ChatDeletePersistentMessage") : - case constcrc("ChatDeleteAllPersistentMessages") : - case constcrc("ChatDestroyRoom") : - case constcrc("ChatInstantMessageToCharacter") : - case constcrc("ChatInviteAvatarToRoom") : - case constcrc("ChatKickAvatarFromRoom") : - case constcrc("ChatRemoveAvatarFromRoom") : - case constcrc("ChatRemoveFriend") : - case constcrc("ChatRemoveModeratorFromRoom") : - case constcrc("ChatRequestPersistentMessage") : - case constcrc("ChatRequestRoomList") : - case constcrc("ChatSendToRoom") : - case constcrc("ChatUninviteFromRoom") : - case constcrc("ChatUnbanAvatarFromRoom") : - case constcrc("VerifyPlayerNameMessage") : - { - DEBUG_REPORT_LOG(true, ("ConnServ: ClientConnection::onReceive()\n")); + const uint32 messageType = m.getType(); - NOT_NULL(m_client); - if(m_client) - { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, ri); - if(m_client->getChatConnection()) - { - m_client->getChatConnection()->send(gcm , true); - } - else - { - // defer chat messages until a server is back online - Archive::ByteStream bs; - m.pack(bs); - m_client->deferChatMessage(bs); - } - } - else - { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - // ChatEnterRoom and ChatEnterRoomById needs to go to the game server to determine - // if the character is not allowed to enter the room because of game rule restrictions; - // only if that test pass do we forward the message on to the chat server to request - // to enter the room - case constcrc("ChatEnterRoom") : - case constcrc("ChatEnterRoomById") : - { - NOT_NULL(m_client); + //Clients with a selected character get routed to a game server. + //@todo check for filtering out bad messages. + if (m_hasSelectedCharacter) { + // if it is a chat message, send it directly to the chat server + switch (messageType) { + case constcrc("ChatAddFriend") : + case constcrc("ChatAddModeratorToRoom") : + case constcrc("ChatBanAvatarFromRoom") : + case constcrc("ChatCreateRoom") : + case constcrc("ChatDeletePersistentMessage") : + case constcrc("ChatDeleteAllPersistentMessages") : + case constcrc("ChatDestroyRoom") : + case constcrc("ChatInstantMessageToCharacter") : + case constcrc("ChatInviteAvatarToRoom") : + case constcrc("ChatKickAvatarFromRoom") : + case constcrc("ChatRemoveAvatarFromRoom") : + case constcrc("ChatRemoveFriend") : + case constcrc("ChatRemoveModeratorFromRoom") : + case constcrc("ChatRequestPersistentMessage") : + case constcrc("ChatRequestRoomList") : + case constcrc("ChatSendToRoom") : + case constcrc("ChatUninviteFromRoom") : + case constcrc("ChatUnbanAvatarFromRoom") : + case constcrc("VerifyPlayerNameMessage") : { + DEBUG_REPORT_LOG(true, ("ConnServ: ClientConnection::onReceive()\n")); - unsigned int sequence; - std::string roomName; + NOT_NULL(m_client); + if (m_client) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + GameClientMessage gcm(v, true, ri); + if (m_client->getChatConnection()) { + m_client->getChatConnection()->send(gcm, true); + } else { + // defer chat messages until a server is back online + Archive::ByteStream bs; + m.pack(bs); + m_client->deferChatMessage(bs); + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + // ChatEnterRoom and ChatEnterRoomById needs to go to the game server to determine + // if the character is not allowed to enter the room because of game rule restrictions; + // only if that test pass do we forward the message on to the chat server to request + // to enter the room + case constcrc("ChatEnterRoom") : + case constcrc("ChatEnterRoomById") : { + NOT_NULL(m_client); - Archive::ReadIterator cri = message.begin(); + unsigned int sequence; + std::string roomName; - if (messageType == constcrc("ChatEnterRoom")) - { - ChatEnterRoom const cer(cri); - sequence = cer.getSequence(); - roomName = cer.getRoomName(); - } - else - { - ChatEnterRoomById const cerbi(cri); - sequence = cerbi.getSequence(); - roomName = cerbi.getRoomName(); - } + Archive::ReadIterator cri = message.begin(); - if(m_client && m_client->getGameConnection()) - { - if (m_pendingChatEnterRoomRequests.count(sequence) == 0) - { - GenericValueTypeMessage, unsigned int> > const cervr( - "ChatEnterRoomValidationRequest", - std::make_pair( - std::make_pair(m_client->getNetworkId(), roomName), - sequence)); + if (messageType == constcrc("ChatEnterRoom")) { + ChatEnterRoom const cer(cri); + sequence = cer.getSequence(); + roomName = cer.getRoomName(); + } else { + ChatEnterRoomById const cerbi(cri); + sequence = cerbi.getSequence(); + roomName = cerbi.getRoomName(); + } - m_client->getGameConnection()->send(cervr, true); + if (m_client && m_client->getGameConnection()) { + if (m_pendingChatEnterRoomRequests.count(sequence) == 0) { + GenericValueTypeMessage, unsigned int> > const cervr( + "ChatEnterRoomValidationRequest", + std::make_pair( + std::make_pair(m_client->getNetworkId(), roomName), + sequence)); - // queue up request until game server responds - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); - } - } - else - { - // send back response to client saying game server not available + m_client->getGameConnection()->send(cervr, true); - // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_NO_GAME_SERVER, 0, ChatAvatarId()); - send(fail, true); - } - - break; - } - // ChatQueryRoom needs to go to the game server to determine if the character is - // not allowed to query the room because of game rule restrictions; only if that - // test pass do we forward the message on to the chat server for completion - case constcrc("ChatQueryRoom") : - { - NOT_NULL(m_client); + // queue up request until game server responds + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); + } + } else { + // send back response to client saying game server not available - Archive::ReadIterator cri = message.begin(); - ChatQueryRoom cqr(cri); + // the client only cares about sequence and result when it's a failure + ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_NO_GAME_SERVER, 0, ChatAvatarId()); + send(fail, true); + } - if(m_client && m_client->getGameConnection()) - { - if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) - { - GenericValueTypeMessage, unsigned int> > const cqrvr( - "ChatQueryRoomValidationRequest", - std::make_pair( - std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), - cqr.getSequence())); + break; + } + // ChatQueryRoom needs to go to the game server to determine if the character is + // not allowed to query the room because of game rule restrictions; only if that + // test pass do we forward the message on to the chat server for completion + case constcrc("ChatQueryRoom") : { + NOT_NULL(m_client); - m_client->getGameConnection()->send(cqrvr, true); + Archive::ReadIterator cri = message.begin(); + ChatQueryRoom cqr(cri); - // queue up request until game server responds - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); - } - } - break; - } - // ChatInviteGroupToRoom needs to go to the game server to get group information - case constcrc("ChatInviteGroupToRoom") : - { - NOT_NULL(m_client); - if(m_client) - { - if (m_client->getGameConnection()) - { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } - else - { - // defer chat messages until a server is back online - Archive::ByteStream bs; - m.pack(bs); - m_client->deferChatMessage(bs); - } - } - else - { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - // ChatPersistentMessageToServer may need to be passed off to the game server for guild or citizens messages - case constcrc("ChatPersistentMessageToServer") : - { - NOT_NULL(m_client); - if(m_client) - { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); + if (m_client && m_client->getGameConnection()) { + if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) { + GenericValueTypeMessage, unsigned int> > const cqrvr( + "ChatQueryRoomValidationRequest", + std::make_pair( + std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), + cqr.getSequence())); - Archive::ReadIterator cri = message.begin(); - ChatPersistentMessageToServer chat(cri); - std::string const &toName = chat.getToCharacterName().name; - if (!_stricmp(toName.c_str(), "guild") || !_strnicmp(toName.c_str(), "guild ", 6) || !_stricmp(toName.c_str(), "citizens")) - { - if (m_client->getGameConnection()) - { - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } - } - else - { - if (m_client->getChatConnection()) - { - GameClientMessage gcm(v, true, ri); - m_client->getChatConnection()->send(gcm, true); - } - else - { - // defer chat messages until a server is back online - Archive::ByteStream bs; - m.pack(bs); - m_client->deferChatMessage(bs); - } - } - } - else - { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - // if it is a cs message, send it directly to the cs server - case constcrc("ConnectPlayerMessage") : - case constcrc("DisconnectPlayerMessage") : - case constcrc("CreateTicketMessage") : - case constcrc("AppendCommentMessage") : - case constcrc("CancelTicketMessage") : - case constcrc("GetTicketsMessage") : - case constcrc("GetCommentsMessage") : - case constcrc("SearchKnowledgeBaseMessage") : - case constcrc("GetArticleMessage") : - case constcrc("RequestCategoriesMessage") : - case constcrc("NewTicketActivityMessage") : - { - NOT_NULL(m_client); - if(m_client) - { - CustomerServiceConnection *customerServiceConnection = m_client->getCustomerServiceConnection(); + m_client->getGameConnection()->send(cqrvr, true); - //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); + // queue up request until game server responds + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); + } + } + break; + } + // ChatInviteGroupToRoom needs to go to the game server to get group information + case constcrc("ChatInviteGroupToRoom") : { + NOT_NULL(m_client); + if (m_client) { + if (m_client->getGameConnection()) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); + } else { + // defer chat messages until a server is back online + Archive::ByteStream bs; + m.pack(bs); + m_client->deferChatMessage(bs); + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + // ChatPersistentMessageToServer may need to be passed off to the game server for guild or citizens messages + case constcrc("ChatPersistentMessageToServer") : { + NOT_NULL(m_client); + if (m_client) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); - if (customerServiceConnection != nullptr) - { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); + Archive::ReadIterator cri = message.begin(); + ChatPersistentMessageToServer chat(cri); + std::string const &toName = chat.getToCharacterName().name; + if (!_stricmp(toName.c_str(), "guild") || !_strnicmp(toName.c_str(), "guild ", 6) || + !_stricmp(toName.c_str(), "citizens")) { + if (m_client->getGameConnection()) { + GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); + } + } else { + if (m_client->getChatConnection()) { + GameClientMessage gcm(v, true, ri); + m_client->getChatConnection()->send(gcm, true); + } else { + // defer chat messages until a server is back online + Archive::ByteStream bs; + m.pack(bs); + m_client->deferChatMessage(bs); + } + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + // if it is a cs message, send it directly to the cs server + case constcrc("ConnectPlayerMessage") : + case constcrc("DisconnectPlayerMessage") : + case constcrc("CreateTicketMessage") : + case constcrc("AppendCommentMessage") : + case constcrc("CancelTicketMessage") : + case constcrc("GetTicketsMessage") : + case constcrc("GetCommentsMessage") : + case constcrc("SearchKnowledgeBaseMessage") : + case constcrc("GetArticleMessage") : + case constcrc("RequestCategoriesMessage") : + case constcrc("NewTicketActivityMessage") : { + NOT_NULL(m_client); + if (m_client) { + CustomerServiceConnection *customerServiceConnection = m_client->getCustomerServiceConnection(); - // TODO: this shit could be made into a template - switch (messageType) { - case constcrc("ConnectPlayerMessage") : { - ConnectPlayerMessage message(ri); - message.setStationId(getSUID()); + //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm , true); - break; - } - case constcrc("CreateTicketMessage") : { - CreateTicketMessage message(ri); - message.setStationId(getSUID()); + if (customerServiceConnection != nullptr) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm , true); - break; - } - case constcrc("AppendCommentMessage") : { - AppendCommentMessage message(ri); - message.setStationId(getSUID()); + // TODO: this shit could be made into a template + switch (messageType) { + case constcrc("ConnectPlayerMessage") : { + ConnectPlayerMessage message(ri); + message.setStationId(getSUID()); - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm , true); - break; - } - case constcrc("CancelTicketMessage") : { - CancelTicketMessage message(ri); - message.setStationId(getSUID()); + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("CreateTicketMessage") : { + CreateTicketMessage message(ri); + message.setStationId(getSUID()); - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm , true); - break; - } - case constcrc("GetTicketsMessage") : { - GetTicketsMessage message(ri); - message.setStationId(getSUID()); + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("AppendCommentMessage") : { + AppendCommentMessage message(ri); + message.setStationId(getSUID()); - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm , true); - break; - } - case constcrc("NewTicketActivityMessage") : { - NewTicketActivityMessage message(ri); - message.setStationId(getSUID()); + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("CancelTicketMessage") : { + CancelTicketMessage message(ri); + message.setStationId(getSUID()); - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm , true); - break; - } - default : { - GameClientMessage gcm(v, true, ri); - customerServiceConnection->send(gcm , true); - break; - } - } - } - } - else - { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - case constcrc("28afefcc187a11dc888b001") : // obfuscation for ClientInactivityMessage message - { - GenericValueTypeMessage msg(ri); + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("GetTicketsMessage") : { + GetTicketsMessage message(ri); + message.setStationId(getSUID()); - if (m_hasBeenValidated && m_sessionValidated) - { - // client went inactive - if (msg.getValue()) - { - if (m_lastActiveTime > 0) - { - // record the amount of active time - m_activePlayTimeDuration += static_cast(::time(nullptr) - m_lastActiveTime); + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("NewTicketActivityMessage") : { + NewTicketActivityMessage message(ri); + message.setStationId(getSUID()); - // tell Session to stop recording play time for the character - if (ConnectionServer::getSessionApiClient() && ConfigConnectionServer::getSessionRecordPlayTime()) - { - LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); - ConnectionServer::getSessionApiClient()->stopPlay(*this); - } + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + default : { + GameClientMessage gcm(v, true, ri); + customerServiceConnection->send(gcm, true); + break; + } + } + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + case constcrc("28afefcc187a11dc888b001") : // obfuscation for ClientInactivityMessage message + { + GenericValueTypeMessage msg(ri); - // client is no longer active; this needs to be set after the LOG() statement - // above because getCurrentActivePlayTimeDuration() uses m_lastActiveTime - m_lastActiveTime = 0; + if (m_hasBeenValidated && m_sessionValidated) { + // client went inactive + if (msg.getValue()) { + if (m_lastActiveTime > 0) { + // record the amount of active time + m_activePlayTimeDuration += static_cast(::time(nullptr) - + m_lastActiveTime); - // update the play time info on the game server - sendPlayTimeInfoToGameServer(); + // tell Session to stop recording play time for the character + if (ConnectionServer::getSessionApiClient() && + ConfigConnectionServer::getSessionRecordPlayTime()) { + LOG("CustomerService", + ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + ConnectionServer::getSessionApiClient()->stopPlay(*this); + } - // drop inactive character - if (ConfigConnectionServer::getDisconnectOnInactive()) - { - LOG("ClientDisconnect", ("Disconnecting %u because the player was inactive for too long.",getSUID())); - ConnectionServer::dropClient(this, "Client inactivity"); - disconnect(); - } - else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) - { - LOG("ClientDisconnect", ("Disconnecting (free trial) %u because the player was inactive for too long.",getSUID())); - ConnectionServer::dropClient(this, "Client inactivity (free trial)"); - disconnect(); - } - } - } - // client went active - else - { - if (m_lastActiveTime == 0) - { - // record the time client went active - m_lastActiveTime = ::time(nullptr); + // client is no longer active; this needs to be set after the LOG() statement + // above because getCurrentActivePlayTimeDuration() uses m_lastActiveTime + m_lastActiveTime = 0; - // tell Session to start recording play time for the character - if (ConnectionServer::getSessionApiClient() && ConfigConnectionServer::getSessionRecordPlayTime()) - { - LOG("CustomerService", ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); - ConnectionServer::getSessionApiClient()->startPlay(*this); - } + // update the play time info on the game server + sendPlayTimeInfoToGameServer(); - // update the play time info on the game server - sendPlayTimeInfoToGameServer(); - } - } - } - break; - } - default : - { - //Forward on to Game Server - DEBUG_REPORT_LOG((!m_client || !m_client->getGameConnection()), ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); + // drop inactive character + if (ConfigConnectionServer::getDisconnectOnInactive()) { + LOG("ClientDisconnect", + ("Disconnecting %u because the player was inactive for too long.", getSUID())); + ConnectionServer::dropClient(this, "Client inactivity"); + disconnect(); + } else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && + ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { + LOG("ClientDisconnect", + ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); + ConnectionServer::dropClient(this, "Client inactivity (free trial)"); + disconnect(); + } + } + } + // client went active + else { + if (m_lastActiveTime == 0) { + // record the time client went active + m_lastActiveTime = ::time(nullptr); - if (m_client && m_client->getGameConnection()) - { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } - - break; - } - } - } else { - switch (messageType) { - case constcrc("ClientIdMsg") : - { - DEBUG_REPORT_LOG(true,("Recieved ClientIdMsg\n")); - ClientIdMsg k(ri); + // tell Session to start recording play time for the character + if (ConnectionServer::getSessionApiClient() && + ConfigConnectionServer::getSessionRecordPlayTime()) { + LOG("CustomerService", + ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); + ConnectionServer::getSessionApiClient()->startPlay(*this); + } - handleClientIdMessage(k); - break; - } - case constcrc("SelectCharacter") : - { - SelectCharacter s(ri); - DEBUG_REPORT_LOG(true,("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); + // update the play time info on the game server + sendPlayTimeInfoToGameServer(); + } + } + } + break; + } + default : { + //Forward on to Game Server + DEBUG_REPORT_LOG((!m_client || !m_client->getGameConnection()), + ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); - handleSelectCharacterMessage(s); - break; - } - case constcrc("ClientCreateCharacter") : - { - if (m_hasBeenValidated && !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true - { - ClientCreateCharacter clientCreate(ri); - DEBUG_REPORT_LOG(true,("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str())); - LOG("TraceCharacterCreation", ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", - getSUID(), - Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), - clientCreate.getTemplateName().c_str(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation().c_str(), - clientCreate.getHairTemplateName().c_str(), - clientCreate.getProfession().c_str(), - static_cast(clientCreate.getJedi()), - static_cast(clientCreate.getUseNewbieTutorial()), - clientCreate.getSkillTemplate().c_str(), - clientCreate.getWorkingSkill().c_str())); + if (m_client && m_client->getGameConnection()) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); + } - if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n",getSUID())); - disconnect(); - } - else if (clientCreate.getJedi() && !m_canCreateJediCharacter) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n",getSUID())); - disconnect(); - } - else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n",getSUID())); - disconnect(); - } - else if (m_hasRequestedCharacterCreate) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because the client has already requested character creation on this connection.\n",getSUID())); - disconnect(); - } - else if (m_hasCreatedCharacter) - { - LOG("TraceCharacterCreation", ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n",getSUID())); - disconnect(); - } - else if (clientCreate.getCharacterName().length()==0) - { - LOG("TraceCharacterCreation", ("%d failed character creation. The character's name is empty", getSUID())); - LOG("ClientDisconnect",("Disconnecting %u because they tried to create a character with no name.\n",getSUID())); - disconnect(); - } - else - { - Unicode::String biography(clientCreate.getBiography()); - if (biography.length() > 1024) - { - IGNORE_RETURN( biography.erase(1024) ); - DEBUG_REPORT_LOG(true,("Biography shortened to 1024 characters.\n")); - } - - if (m_isAdminAccount) - { - ConnectionCreateCharacter connectionCreate( - m_suid, - clientCreate.getCharacterName(), - clientCreate.getTemplateName(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation(), - clientCreate.getAppearanceData(), - clientCreate.getHairTemplateName(), - clientCreate.getHairAppearanceData(), - clientCreate.getProfession(), - clientCreate.getJedi(), - biography, - clientCreate.getUseNewbieTutorial(), - clientCreate.getSkillTemplate(), - clientCreate.getWorkingSkill(), - m_isAdminAccount, - false, - m_featureBitsGame); + break; + } + } + } else { + switch (messageType) { + case constcrc("ClientIdMsg") : { + DEBUG_REPORT_LOG(true, ("Recieved ClientIdMsg\n")); + ClientIdMsg k(ri); - ConnectionServer::sendToCentralProcess(connectionCreate); - LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); - } - else - { - // for regular players, do one final check with the LoginServer - // to make sure the character can be created (i.e. that character - // limits have not been exceeded) - delete m_pendingCharacterCreate; - m_pendingCharacterCreate = new ConnectionCreateCharacter( - m_suid, - clientCreate.getCharacterName(), - clientCreate.getTemplateName(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation(), - clientCreate.getAppearanceData(), - clientCreate.getHairTemplateName(), - clientCreate.getHairAppearanceData(), - clientCreate.getProfession(), - clientCreate.getJedi(), - biography, - clientCreate.getUseNewbieTutorial(), - clientCreate.getSkillTemplate(), - clientCreate.getWorkingSkill(), - m_isAdminAccount, - false, - m_featureBitsGame); + handleClientIdMessage(k); + break; + } + case constcrc("SelectCharacter") : { + SelectCharacter s(ri); + DEBUG_REPORT_LOG(true, + ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); - LOG("TraceCharacterCreation", ("%d character creation request awaiting final verification from LoginServer", getSUID())); + handleSelectCharacterMessage(s); + break; + } + case constcrc("ClientCreateCharacter") : { + if (m_hasBeenValidated && !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true + { + ClientCreateCharacter clientCreate(ri); + DEBUG_REPORT_LOG(true, + ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow( + clientCreate.getCharacterName()).c_str())); + LOG("TraceCharacterCreation", + ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", + getSUID(), + Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), + clientCreate.getTemplateName().c_str(), + clientCreate.getScaleFactor(), + clientCreate.getStartingLocation().c_str(), + clientCreate.getHairTemplateName().c_str(), + clientCreate.getProfession().c_str(), + static_cast(clientCreate.getJedi()), + static_cast(clientCreate.getUseNewbieTutorial()), + clientCreate.getSkillTemplate().c_str(), + clientCreate.getWorkingSkill().c_str())); - ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); - ConnectionServer::sendToCentralProcess(vcm); - } + if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + disconnect(); + } else if (clientCreate.getJedi() && !m_canCreateJediCharacter) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + disconnect(); + } else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + disconnect(); + } else if (m_hasRequestedCharacterCreate) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); + disconnect(); + } else if (m_hasCreatedCharacter) { + LOG("TraceCharacterCreation", + ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); + disconnect(); + } else if (clientCreate.getCharacterName().length() == 0) { + LOG("TraceCharacterCreation", + ("%d failed character creation. The character's name is empty", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); + disconnect(); + } else { + Unicode::String biography(clientCreate.getBiography()); + if (biography.length() > 1024) { + IGNORE_RETURN(biography.erase(1024)); + DEBUG_REPORT_LOG(true, ("Biography shortened to 1024 characters.\n")); + } - m_hasRequestedCharacterCreate = true; - } - } - break; - } - case constcrc("ClientRandomNameRequest") : - { - ClientRandomNameRequest clientRandomName(ri); + if (m_isAdminAccount) { + ConnectionCreateCharacter connectionCreate( + m_suid, + clientCreate.getCharacterName(), + clientCreate.getTemplateName(), + clientCreate.getScaleFactor(), + clientCreate.getStartingLocation(), + clientCreate.getAppearanceData(), + clientCreate.getHairTemplateName(), + clientCreate.getHairAppearanceData(), + clientCreate.getProfession(), + clientCreate.getJedi(), + biography, + clientCreate.getUseNewbieTutorial(), + clientCreate.getSkillTemplate(), + clientCreate.getWorkingSkill(), + m_isAdminAccount, + false, + m_featureBitsGame); - RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); - ConnectionServer::sendToCentralProcess(randomNameRequest); - LOG("TraceCharacterCreation", ("%d requested a random name. Request sent to CentralServer", getSUID())); - break; - } - case constcrc("ClientVerifyAndLockNameRequest") : - { - ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); + ConnectionServer::sendToCentralProcess(connectionCreate); + LOG("TraceCharacterCreation", + ("%d character creation request sent to CentralServer", getSUID())); + } else { + // for regular players, do one final check with the LoginServer + // to make sure the character can be created (i.e. that character + // limits have not been exceeded) + delete m_pendingCharacterCreate; + m_pendingCharacterCreate = new ConnectionCreateCharacter( + m_suid, + clientCreate.getCharacterName(), + clientCreate.getTemplateName(), + clientCreate.getScaleFactor(), + clientCreate.getStartingLocation(), + clientCreate.getAppearanceData(), + clientCreate.getHairTemplateName(), + clientCreate.getHairAppearanceData(), + clientCreate.getProfession(), + clientCreate.getJedi(), + biography, + clientCreate.getUseNewbieTutorial(), + clientCreate.getSkillTemplate(), + clientCreate.getWorkingSkill(), + m_isAdminAccount, + false, + m_featureBitsGame); - VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, clientVerifyAndLockNameRequest.getTemplateName(), clientVerifyAndLockNameRequest.getCharacterName(), m_featureBitsGame); - ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); - LOG("TraceCharacterCreation", ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow(verifyAndLockNameRequest.getCharacterName()).c_str())); - break; - } - case constcrc("LagRequest") : - { - // TODO: why is this commented out? - // handleLagRequest(); - break; - } - } - } - } - catch(const Archive::ReadException & readException) - { - WARNING(true, ("Archive read error (%s) from client. Disconnecting client", readException.what())); - LOG("ClientDisconnect", ("Archive read error (%s) from client. Disconnecting client", readException.what())); - disconnect(); - } + LOG("TraceCharacterCreation", + ("%d character creation request awaiting final verification from LoginServer", getSUID())); + + ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); + ConnectionServer::sendToCentralProcess(vcm); + } + + m_hasRequestedCharacterCreate = true; + } + } + break; + } + case constcrc("ClientRandomNameRequest") : { + ClientRandomNameRequest clientRandomName(ri); + + RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); + ConnectionServer::sendToCentralProcess(randomNameRequest); + LOG("TraceCharacterCreation", + ("%d requested a random name. Request sent to CentralServer", getSUID())); + break; + } + case constcrc("ClientVerifyAndLockNameRequest") : { + ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); + + VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, + clientVerifyAndLockNameRequest.getTemplateName(), + clientVerifyAndLockNameRequest.getCharacterName(), + m_featureBitsGame); + ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); + LOG("TraceCharacterCreation", + ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow( + verifyAndLockNameRequest.getCharacterName()).c_str())); + break; + } + case constcrc("LagRequest") : { + // TODO: why is this commented out? + // handleLagRequest(); + break; + } + } + } + } + catch (const Archive::ReadException &readException) { + WARNING(true, ("Archive read error (%s) from client. Disconnecting client", readException.what())); + LOG("ClientDisconnect", ("Archive read error (%s) from client. Disconnecting client", readException.what())); + disconnect(); + } } //----------------------------------------------------------------------- -void ClientConnection::handleLagRequest() -{ - // client is requesting a lag ping (reliable trace) - GameNetworkMessage response("ConnectionServerLagResponse"); - send(response, true); +void ClientConnection::handleLagRequest() { + // client is requesting a lag ping (reliable trace) + GameNetworkMessage response("ConnectionServerLagResponse"); + send(response, true); - if(m_hasSelectedCharacter && m_client && m_client->getGameConnection()) - { - // send to game server - GameNetworkMessage request("LagRequest"); - std::vector v; - v.push_back(m_characterId); - GameClientMessage gcm(v, true, request); - m_client->getGameConnection()->send(gcm, true); - } - else - { - // send game response immediately - GameNetworkMessage gameResponse("GameServerLagResponse"); - send(gameResponse, true); - } + if (m_hasSelectedCharacter && m_client && m_client->getGameConnection()) { + // send to game server + GameNetworkMessage request("LagRequest"); + std::vector v; + v.push_back(m_characterId); + GameClientMessage gcm(v, true, request); + m_client->getGameConnection()->send(gcm, true); + } else { + // send game response immediately + GameNetworkMessage gameResponse("GameServerLagResponse"); + send(gameResponse, true); + } } @@ -1236,130 +1188,113 @@ void ClientConnection::handleLagRequest() * to associate the connection with the new client they created with that * character. We no longer need the character map. */ -void ClientConnection::setClient(Client* newClient) -{ - //This fatal is here to try to catch the reconnect bug. - WARNING_STRICT_FATAL(m_client, ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); - // jrandall - I've removed the fatal because it is blocking some people from getting some work - // done. I'm on a high priority fix at the moment. If this warning starts appearing, - // set a break point or something. - //DEBUG_FATAL(client, ("Attempting to set the client on a connection that already has one.\n")); - m_client = newClient; +void ClientConnection::setClient(Client *newClient) { + //This fatal is here to try to catch the reconnect bug. + WARNING_STRICT_FATAL(m_client, + ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); + // jrandall - I've removed the fatal because it is blocking some people from getting some work + // done. I'm on a high priority fix at the moment. If this warning starts appearing, + // set a break point or something. + //DEBUG_FATAL(client, ("Attempting to set the client on a connection that already has one.\n")); + m_client = newClient; - // todo put this in: characterMap.clear(); + // todo put this in: characterMap.clear(); } //----------------------------------------------------------------------- -void ClientConnection::send(const GameNetworkMessage & message, const bool reliable) -{ - m_sendLastTimeMs = Clock::timeMs(); +void ClientConnection::send(const GameNetworkMessage &message, const bool reliable) { + m_sendLastTimeMs = Clock::timeMs(); - if ( sm_outgoingBytesMap_Worktime == 0 ) - sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; - else if ( (m_sendLastTimeMs - sm_outgoingBytesMap_Worktime) > 60000 ) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map< std::string, uint32 >::iterator iter; - for ( iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter ) - { - iter->second = 0; - } - sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; - } - sm_outgoingBytesMap_Working[ message.getCmdName() ] += message.getByteStream().getSize(); + if (sm_outgoingBytesMap_Worktime == 0) + sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; + else if ((m_sendLastTimeMs - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds + { + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; + } + sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; + } + sm_outgoingBytesMap_Working[message.getCmdName()] += message.getByteStream().getSize(); - ServerConnection::send(message, reliable); + ServerConnection::send(message, reliable); } //----------------------------------------------------------------------- -std::map< std::string, uint32 >& ClientConnection::getPacketBytesPerMinStats() -{ - uint32 now = Clock::timeMs(); - if ( sm_outgoingBytesMap_Worktime == 0 ) - sm_outgoingBytesMap_Worktime = now; - else if ( (now - sm_outgoingBytesMap_Worktime) > 60000 ) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map< std::string, uint32 >::iterator iter; - for ( iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter ) - { - iter->second = 0; - } - sm_outgoingBytesMap_Worktime = now; +std::map &ClientConnection::getPacketBytesPerMinStats() { + uint32 now = Clock::timeMs(); + if (sm_outgoingBytesMap_Worktime == 0) + sm_outgoingBytesMap_Worktime = now; + else if ((now - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds + { + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; + } + sm_outgoingBytesMap_Worktime = now; + } + + return sm_outgoingBytesMap_Stats; +} + +//----------------------------------------------------------------------- + +void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) { + std::map::iterator iterFind = m_pendingChatEnterRoomRequests.find(sequence); + if (iterFind != m_pendingChatEnterRoomRequests.end()) { + if (result == CHATRESULT_SUCCESS) { + if (m_client && m_client->getChatConnection()) { + // game server says it's ok to enter the chat room, + // so forward the request on to the chat server + m_client->getChatConnection()->send(*(iterFind->second), true); + } else { + // send back response to client saying chat server not available + + // the client only cares about sequence and result when it's a failure + ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_CHAT_SERVER_UNAVAILABLE, 0, ChatAvatarId()); + send(fail, true); + } + } else { + // send back response to client saying game server denied enter room request + + // the client only cares about sequence and result when it's a failure + ChatOnEnteredRoom fail(sequence, result, 0, ChatAvatarId()); + send(fail, true); } - return sm_outgoingBytesMap_Stats; + delete iterFind->second; + m_pendingChatEnterRoomRequests.erase(iterFind); + } } //----------------------------------------------------------------------- -void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) -{ - std::map::iterator iterFind = m_pendingChatEnterRoomRequests.find(sequence); - if (iterFind != m_pendingChatEnterRoomRequests.end()) - { - if (result == CHATRESULT_SUCCESS) - { - if (m_client && m_client->getChatConnection()) - { - // game server says it's ok to enter the chat room, - // so forward the request on to the chat server - m_client->getChatConnection()->send(*(iterFind->second), true); - } - else - { - // send back response to client saying chat server not available +void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) { + std::map::iterator iterFind = m_pendingChatQueryRoomRequests.find(sequence); + if (iterFind != m_pendingChatQueryRoomRequests.end()) { + if (success) { + if (m_client && m_client->getChatConnection()) { + // game server says it's ok to query the chat room, + // so forward the request on to the chat server + m_client->getChatConnection()->send(*(iterFind->second), true); + } + } - // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_CHAT_SERVER_UNAVAILABLE, 0, ChatAvatarId()); - send(fail, true); - } - } - else - { - // send back response to client saying game server denied enter room request - - // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, result, 0, ChatAvatarId()); - send(fail, true); - } - - delete iterFind->second; - m_pendingChatEnterRoomRequests.erase(iterFind); - } + delete iterFind->second; + m_pendingChatQueryRoomRequests.erase(iterFind); + } } //----------------------------------------------------------------------- -void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) -{ - std::map::iterator iterFind = m_pendingChatQueryRoomRequests.find(sequence); - if (iterFind != m_pendingChatQueryRoomRequests.end()) - { - if (success) - { - if (m_client && m_client->getChatConnection()) - { - // game server says it's ok to query the chat room, - // so forward the request on to the chat server - m_client->getChatConnection()->send(*(iterFind->second), true); - } - } - - delete iterFind->second; - m_pendingChatQueryRoomRequests.erase(iterFind); - } -} - -//----------------------------------------------------------------------- - -void ClientConnection::sendByteStream(const Archive::ByteStream& bs, bool reliable) -{ - Connection::send(bs, reliable); +void ClientConnection::sendByteStream(const Archive::ByteStream &bs, bool reliable) { + Connection::send(bs, reliable); } //----------------------------------------------------------------------- @@ -1367,10 +1302,9 @@ void ClientConnection::sendByteStream(const Archive::ByteStream& bs, bool reliab /** * Send the client to an arbitratry game server based on the current scene */ -const bool ClientConnection::sendToGameServer() -{ - GameConnection * c = const_cast(ConnectionServer::getGameConnection(m_targetScene)); - return sendToGameServer(c); +const bool ClientConnection::sendToGameServer() { + GameConnection *c = const_cast(ConnectionServer::getGameConnection(m_targetScene)); + return sendToGameServer(c); } // ---------------------------------------------------------------------- @@ -1379,33 +1313,30 @@ const bool ClientConnection::sendToGameServer() * Send the client to a particular game server, sepcified by process id. */ -const bool ClientConnection::sendToGameServer(uint32 gameServerId) -{ - GameConnection * c = const_cast(ConnectionServer::getGameConnection(gameServerId)); - return sendToGameServer(c); +const bool ClientConnection::sendToGameServer(uint32 gameServerId) { + GameConnection *c = const_cast(ConnectionServer::getGameConnection(gameServerId)); + return sendToGameServer(c); } // ---------------------------------------------------------------------- -bool ClientConnection::sendToGameServer(GameConnection *c) -{ - bool result = false; +bool ClientConnection::sendToGameServer(GameConnection *c) { + bool result = false; - if(c && m_hasSelectedCharacter && m_hasBeenValidated) - { - //create a new client - ConnectionServer::addNewClient(this, - m_characterId, - c, - m_targetScene, - m_sendToStarport); + if (c && m_hasSelectedCharacter && m_hasBeenValidated) { + //create a new client + ConnectionServer::addNewClient(this, + m_characterId, + c, + m_targetScene, + m_sendToStarport); - LoggedInMessage m(m_suid); - ConnectionServer::sendToCentralProcess(m); - result = true; - m_hasBeenSentToGameServer = true; - } - return result; + LoggedInMessage m(m_suid); + ConnectionServer::sendToCentralProcess(m); + result = true; + m_hasBeenSentToGameServer = true; + } + return result; } //----------------------------------------------------------------------- @@ -1415,256 +1346,250 @@ bool ClientConnection::sendToGameServer(GameConnection *c) * Now we know whether the character is valid and where in the world it * is located. */ -void ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, const NetworkId &container, const std::string &scene, const Vector &coordinates) -{ - if (!m_validatingCharacter) - { - LOG("TraceCharacterSelection", ("%d received a validation response, but is not in the process of validation", getSUID())); - DEBUG_REPORT_LOG(true,("Got unexpected onCharacterValidated() for account %lu.\n",getSUID())); - return; - } - m_validatingCharacter=false; +void ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, + const NetworkId &container, const std::string &scene, + const Vector &coordinates) { + if (!m_validatingCharacter) { + LOG("TraceCharacterSelection", + ("%d received a validation response, but is not in the process of validation", getSUID())); + DEBUG_REPORT_LOG(true, ("Got unexpected onCharacterValidated() for account %lu.\n", getSUID())); + return; + } + m_validatingCharacter = false; - if (isValid) - { - LOG("TraceCharacterSelection", ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - LOG("CustomerService", ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount(this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - m_targetScene = scene; - m_targetCoordinates = coordinates; - m_characterId = character; - m_containerId = container; - m_characterName = characterName; + if (isValid) { + LOG("TraceCharacterSelection", + ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + LOG("CustomerService", + ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount( + this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + m_targetScene = scene; + m_targetCoordinates = coordinates; + m_characterId = character; + m_containerId = container; + m_characterName = characterName; - m_hasSelectedCharacter = true; + m_hasSelectedCharacter = true; - // ask CentralServer to suggest a game server for this character - // (Central will forward the request to a Planet Server) + // ask CentralServer to suggest a game server for this character + // (Central will forward the request to a Planet Server) - RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, m_targetCoordinates, false); - if(ConnectionServer::getCentralConnection()) - ConnectionServer::getCentralConnection()->send(requestmsg, true); - else - { - LOG("ClientDisconnect",("Can't handle login of character %s because there is no connection to Central.\n",m_characterId.getValueString().c_str())); - ErrorMessage err("Validation Failed", "The connection to the central server is down. Please try again later."); - send(err, true); + RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, + m_targetCoordinates, false); + if (ConnectionServer::getCentralConnection()) + ConnectionServer::getCentralConnection()->send(requestmsg, true); + else { + LOG("ClientDisconnect", + ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); + ErrorMessage err("Validation Failed", + "The connection to the central server is down. Please try again later."); + send(err, true); - disconnect(); - } - } - else - { - LOG("TraceCharacterSelection", ("%d validation failed, disconnecting client", getSUID())); - ErrorMessage err("Validation Failed", "Your character was denied login by the database."); - send(err, true); + disconnect(); + } + } else { + LOG("TraceCharacterSelection", ("%d validation failed, disconnecting client", getSUID())); + ErrorMessage err("Validation Failed", "Your character was denied login by the database."); + send(err, true); - LOG("ClientDisconnect", ("Denying login for account %u.\n",getSUID())); - disconnect(); - } + LOG("ClientDisconnect", ("Denying login for account %u.\n", getSUID())); + disconnect(); + } } //------------------------------------------------------------------------------------------ -void ClientConnection::onValidateClient (StationId suid, const std::string & username, bool secure, const char* id, const uint32 gameFeatures, const uint32 subscriptionFeatures, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) -{ - UNREF(id); - m_sessionValidated = true; - m_suid = suid; - m_accountName = username; - m_featureBitsGame = gameFeatures; - m_featureBitsSubscription = subscriptionFeatures; - m_isSecure = secure; - m_entitlementTotalTime = entitlementTotalTime; - m_entitlementEntitledTime = entitlementEntitledTime; - m_entitlementTotalTimeSinceLastLogin = entitlementTotalTimeSinceLastLogin; - m_entitlementEntitledTimeSinceLastLogin = entitlementEntitledTimeSinceLastLogin; - m_buddyPoints = buddyPoints; +void ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, + const uint32 gameFeatures, const uint32 subscriptionFeatures, + unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, + unsigned int entitlementTotalTimeSinceLastLogin, + unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { + UNREF(id); + m_sessionValidated = true; + m_suid = suid; + m_accountName = username; + m_featureBitsGame = gameFeatures; + m_featureBitsSubscription = subscriptionFeatures; + m_isSecure = secure; + m_entitlementTotalTime = entitlementTotalTime; + m_entitlementEntitledTime = entitlementEntitledTime; + m_entitlementTotalTimeSinceLastLogin = entitlementTotalTimeSinceLastLogin; + m_entitlementEntitledTimeSinceLastLogin = entitlementEntitledTimeSinceLastLogin; + m_buddyPoints = buddyPoints; - if (id) - m_sessionId = id; + if (id) + m_sessionId = id; - if (m_requestedSuid != 0 && suid != m_requestedSuid) - { - //verify internal, secure, is on the god list - bool loginOK=false; - if(!secure) - LOG("CustomerService",("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(),suid, m_requestedSuid)); - else - { - if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); - else - { - int adminLevel=0; - if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || 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, m_requestedSuid)); - else - { - LOG("CustomerService",("AdminLogin: User %s (account %li) logged into account %li", username.c_str(),m_suid,m_requestedSuid)); - DEBUG_REPORT_LOG(true,("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(),m_suid,m_requestedSuid)); - m_suid = m_requestedSuid; - m_usingAdminLogin = true; - loginOK=true; - } - } - } - if (!loginOK) - { - disconnect(); - return; - } - } + if (m_requestedSuid != 0 && suid != m_requestedSuid) { + //verify internal, secure, is on the god list + bool loginOK = false; + if (!secure) + LOG("CustomerService", + ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); + else { + if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); + else { + int adminLevel = 0; + if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || 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, m_requestedSuid)); + else { + LOG("CustomerService", + ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); + DEBUG_REPORT_LOG(true, + ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); + m_suid = m_requestedSuid; + m_usingAdminLogin = true; + loginOK = true; + } + } + } + if (!loginOK) { + disconnect(); + return; + } + } - m_featureBitsGame &= ~ConfigConnectionServer::getDisabledFeatureBits(); - - //Configoption to enable JTL features for beta players so that our code can pretend everything uses the JTL Retail bit - if (ConfigConnectionServer::getSetJtlRetailIfBetaIsSet()) - { - if (ClientGameFeature::SpaceExpansionBeta & m_featureBitsGame) - { - m_featureBitsGame |= ClientGameFeature::SpaceExpansionRetail; - } - } + m_featureBitsGame &= ~ConfigConnectionServer::getDisabledFeatureBits(); - //Configoption to enable Obiwan features for beta players so that our code can pretend everything uses the Obiwan Retail bit - if (ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet()) - { - if (ClientGameFeature::TrialsOfObiwanBeta & m_featureBitsGame) - { - //-- add retail bit only if player does not have the preorder bit - if ((m_featureBitsGame & ClientGameFeature::TrialsOfObiwanPreorder) == 0) - m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; - } - else - { - // Clear bits from players who might have them for real, but aren't in the beta - m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanRetail; - m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanPreorder; - } - } - - //-- Obiwan Preorders get the Retail bit as well... All rewards etc... - if (ClientGameFeature::TrialsOfObiwanPreorder & m_featureBitsGame) - { - m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; - } + //Configoption to enable JTL features for beta players so that our code can pretend everything uses the JTL Retail bit + if (ConfigConnectionServer::getSetJtlRetailIfBetaIsSet()) { + if (ClientGameFeature::SpaceExpansionBeta & m_featureBitsGame) { + m_featureBitsGame |= ClientGameFeature::SpaceExpansionRetail; + } + } - // Restrictions for "new free trial" account - if ( ((m_featureBitsSubscription & ClientSubscriptionFeature::FreeTrial2) != 0) - && ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) - { - // "new free trial" account don't have access to RoW until they convert - m_featureBitsGame &= ~ClientGameFeature::Episode3ExpansionRetail; - m_featureBitsGame &= ~ClientGameFeature::Episode3PreorderDownload; + //Configoption to enable Obiwan features for beta players so that our code can pretend everything uses the Obiwan Retail bit + if (ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet()) { + if (ClientGameFeature::TrialsOfObiwanBeta & m_featureBitsGame) { + //-- add retail bit only if player does not have the preorder bit + if ((m_featureBitsGame & ClientGameFeature::TrialsOfObiwanPreorder) == 0) + m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; + } else { + // Clear bits from players who might have them for real, but aren't in the beta + m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanRetail; + m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanPreorder; + } + } - // ClientGameFeature::FreeTrial2 indicates this is a converted "new free trial" - // account, and since this account hasn't converted yet, we remove this bit - m_featureBitsGame &= ~ClientGameFeature::FreeTrial2; - } + //-- Obiwan Preorders get the Retail bit as well... All rewards etc... + if (ClientGameFeature::TrialsOfObiwanPreorder & m_featureBitsGame) { + m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; + } - // Clear feature bits that only apply if the account is paying (i.e. the sub base bit is set) - if ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0) - { - m_featureBitsGame &= ~ClientGameFeature::HousePackupReward; - m_featureBitsGame &= ~ClientGameFeature::BuddyProgramReward; - } - - ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); - ConnectionServer::sendToCentralProcess(vcm); - ConnectionServer::addConnectedClient(m_suid, this); + // Restrictions for "new free trial" account + if (((m_featureBitsSubscription & ClientSubscriptionFeature::FreeTrial2) != 0) + && ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { + // "new free trial" account don't have access to RoW until they convert + m_featureBitsGame &= ~ClientGameFeature::Episode3ExpansionRetail; + m_featureBitsGame &= ~ClientGameFeature::Episode3PreorderDownload; - uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); - if (requiredSubscriptionBits != 0) - { - if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) - { - LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); - LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); - disconnect(); - return; - } - } + // ClientGameFeature::FreeTrial2 indicates this is a converted "new free trial" + // account, and since this account hasn't converted yet, we remove this bit + m_featureBitsGame &= ~ClientGameFeature::FreeTrial2; + } - uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); - if (requiredGameBits != 0) - { - if ((gameFeatures & requiredGameBits) != requiredGameBits) - { - LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); - LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); - disconnect(); - return; - } - } + // Clear feature bits that only apply if the account is paying (i.e. the sub base bit is set) + if ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0) { + m_featureBitsGame &= ~ClientGameFeature::HousePackupReward; + m_featureBitsGame &= ~ClientGameFeature::BuddyProgramReward; + } - // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time - GenericValueTypeMessage, std::pair > > const msgFeatureBits("AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), static_cast(::time(nullptr))))); - send(msgFeatureBits, true); + ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); + ConnectionServer::sendToCentralProcess(vcm); + ConnectionServer::addConnectedClient(m_suid, this); - std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); - std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); + uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); + if (requiredSubscriptionBits != 0) { + if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) { + LOG("ClientDisconnect", + ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); + LOG("CustomerService", + ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); + disconnect(); + return; + } + } - LOG("CustomerService", ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount(this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); + uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); + if (requiredGameBits != 0) { + if ((gameFeatures & requiredGameBits) != requiredGameBits) { + LOG("ClientDisconnect", + ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); + LOG("CustomerService", + ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); + disconnect(); + return; + } + } - // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account - // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account - if (!m_usingAdminLogin && !m_isSecure) - { - GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", std::make_pair(m_suid, m_sessionId)); - ConnectionServer::sendToCentralProcess(dropDuplicateConnections); - } + // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time + GenericValueTypeMessage, std::pair > > const msgFeatureBits( + "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), + std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), + static_cast(::time(nullptr))))); + send(msgFeatureBits, true); + + std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); + std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); + + LOG("CustomerService", + ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount( + this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); + + // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account + // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account + if (!m_usingAdminLogin && !m_isSecure) { + GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", + std::make_pair(m_suid, + m_sessionId)); + ConnectionServer::sendToCentralProcess(dropDuplicateConnections); + } } //----------------------------------------------------------------------- -std::string ClientConnection::describeAccount(const ClientConnection * c) -{ - std::string result = ""; - if(c) - { - char idbuf[512] = {"\0"}; - const std::string & sessionId = c->getSessionId(); - if (sessionId.empty()) - { - snprintf(idbuf, sizeof(idbuf), " (%lu)", c->m_suid); - } - else - { - snprintf(idbuf, sizeof(idbuf), " (%lu, %s)", c->m_suid, sessionId.c_str()); - } +std::string ClientConnection::describeAccount(const ClientConnection *c) { + std::string result = ""; + if (c) { + char idbuf[512] = {"\0"}; + const std::string &sessionId = c->getSessionId(); + if (sessionId.empty()) { + snprintf(idbuf, sizeof(idbuf), " (%lu)", c->m_suid); + } else { + snprintf(idbuf, sizeof(idbuf), " (%lu, %s)", c->m_suid, sessionId.c_str()); + } - result = c->m_accountName; - result += idbuf; - } - return result; + result = c->m_accountName; + result += idbuf; + } + return result; } // ---------------------------------------------------------------------- -std::vector > const & ClientConnection::getConsumedRewardEvents() const -{ - return m_consumedRewardEvents; +std::vector > const &ClientConnection::getConsumedRewardEvents() const { + return m_consumedRewardEvents; } // ---------------------------------------------------------------------- -std::vector > const & ClientConnection::getClaimedRewardItems() const -{ - return m_claimedRewardItems; +std::vector > const &ClientConnection::getClaimedRewardItems() const { + return m_claimedRewardItems; } // ---------------------------------------------------------------------- -bool ClientConnection::isUsingAdminLogin() const -{ - return m_usingAdminLogin; +bool ClientConnection::isUsingAdminLogin() const { + return m_usingAdminLogin; } // ---------------------------------------------------------------------- -int ClientConnection::getBuddyPoints() const -{ - return m_buddyPoints; +int ClientConnection::getBuddyPoints() const { + return m_buddyPoints; } // ====================================================================== diff --git a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp index b06dbe14..52d2ef2f 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp @@ -56,6 +56,7 @@ void ConfigConnectionServer::install(void) data = new ConfigConnectionServer::Data; + KEY_STRING (sessionURL, ""); KEY_STRING (centralServerAddress, "localhost"); KEY_INT (centralServerPort, 0); KEY_STRING (clientServiceBindInterface, ""); diff --git a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h index 6f1ce686..114af1d8 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h +++ b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h @@ -2,477 +2,483 @@ // copyright 2000 Verant Interactive // Author: Justin Randall -#ifndef _ConfigConnectionServer_H -#define _ConfigConnectionServer_H +#ifndef _ConfigConnectionServer_H +#define _ConfigConnectionServer_H //----------------------------------------------------------------------- -class ConfigConnectionServer -{ +class ConfigConnectionServer { public: - struct Data - { - const char* centralServerAddress; - int centralServerPort; - int clientServicePortPublic; - int clientServicePortPrivate; - int clientOverflowLimit; - int gameServicePort; - const char * clusterName; - bool disableWorldSnapshot; - int maxClients; - int pingPort; - bool spamLimitEnabled; - int spamLimitResetTimeMs; - int spamLimitResetScaleFactor; - int spamLimitBytesPerSec; - int spamLimitPacketsPerSec; - bool startPublicServer; - const char * chatServiceBindInterface; - const char * clientServiceBindInterface; - const char * customerServiceBindInterface; - const char * gameServiceBindInterface; - bool compressClientNetworkTraffic; - int crashRecoveryTimeout; - bool shouldSleep; - int clientMaxOutstandingPackets; - int clientMaxRawPacketSize; - int clientMaxConnections; - int clientFragmentSize; - int clientMaxDataHoldTime; - int clientHashTableSize; - int lagReportThreshold; - int maxConnectionsPerIP; + struct Data { + const char *sessionURL; + const char *centralServerAddress; + int centralServerPort; + int clientServicePortPublic; + int clientServicePortPrivate; + int clientOverflowLimit; + int gameServicePort; + const char *clusterName; + bool disableWorldSnapshot; + int maxClients; + int pingPort; + bool spamLimitEnabled; + int spamLimitResetTimeMs; + int spamLimitResetScaleFactor; + int spamLimitBytesPerSec; + int spamLimitPacketsPerSec; + bool startPublicServer; + const char *chatServiceBindInterface; + const char *clientServiceBindInterface; + const char *customerServiceBindInterface; + const char *gameServiceBindInterface; + bool compressClientNetworkTraffic; + int crashRecoveryTimeout; + bool shouldSleep; + int clientMaxOutstandingPackets; + int clientMaxRawPacketSize; + int clientMaxConnections; + int clientFragmentSize; + int clientMaxDataHoldTime; + int clientHashTableSize; + int lagReportThreshold; + int maxConnectionsPerIP; - bool validateStationKey; - const char * sessionServers; - int sessionType; - bool disableSessionLogout; - bool sessionRecordPlayTime; - bool disconnectOnInactive; - bool disconnectFreeTrialOnInactive; - const char * adminAccountDataTable; + bool validateStationKey; + const char *sessionServers; + int sessionType; + bool disableSessionLogout; + bool sessionRecordPlayTime; + bool disconnectOnInactive; + bool disconnectFreeTrialOnInactive; + const char *adminAccountDataTable; - float timeBetweenSessionUpdates; - - int defaultGameFeatures; - int defaultSubscriptionFeatures; - int requiredSubscriptionBits; - int requiredGameBits; - bool setJtlRetailIfBetaIsSet; - bool setEpisode3RetailIfBetaIsSet; - bool setTrialsOfObiwanRetailIfBetaIsSet; + float timeBetweenSessionUpdates; - int disabledFeatureBits; + int defaultGameFeatures; + int defaultSubscriptionFeatures; + int requiredSubscriptionBits; + int requiredGameBits; + bool setJtlRetailIfBetaIsSet; + bool setEpisode3RetailIfBetaIsSet; + bool setTrialsOfObiwanRetailIfBetaIsSet; - bool validateClientVersion; + int disabledFeatureBits; - int connectionServerNumber; - int fakeBuddyPoints; + bool validateClientVersion; + + int connectionServerNumber; + int fakeBuddyPoints; - const char * altPublicBindAddress; - }; + const char *altPublicBindAddress; + }; - static const char * getCentralServerAddress (); - static const uint16 getCentralServerPort (); - static const int getClientOverflowLimit (); - static const char * getClientServiceBindInterface (); - static const uint16 getClientServicePortPrivate (); - static const uint16 getClientServicePortPublic (); - static const char * getClusterName (); - static bool getDisableWorldSnapshot (); - static const uint16 getGameServicePort (); - static const int getMaxClients (); - static const uint16 getPingPort (); - static const bool getSpamLimitEnabled (); - static const unsigned int getSpamLimitResetTimeMs (); - static const unsigned int getSpamLimitResetScaleFactor (); - static const unsigned int getSpamLimitBytesPerSec (); - static const unsigned int getSpamLimitPacketsPerSec (); - static const bool getStartPublicServer (); - static const char * getChatServiceBindInterface (); - static const char * getCustomerServiceBindInterface (); - static const char * getGameServiceBindInterface (); - static const bool getCompressClientNetworkTraffic (); - static void install (); - static void remove (); - static const uint getCrashRecoveryTimeout (); - static bool getShouldSleep (); - static const int getClientMaxOutstandingPackets(); - static const int getClientMaxRawPacketSize (); - static const int getClientMaxConnections (); - static const int getClientFragmentSize (); - static const int getClientMaxDataHoldTime (); - static const int getClientHashTableSize (); - static const int getLagReportThreshold (); + static const char *getSessionURL(); - static bool getValidateStationKey(); - static const char * getSessionServers(); - static const int getSessionType(); - static bool getDisableSessionLogout(); - static bool getSessionRecordPlayTime(); - static bool getDisconnectOnInactive(); - static bool getDisconnectFreeTrialOnInactive(); - - static const char * getAdminAccountDataTable (void); + static const char *getCentralServerAddress(); - static int getNumberOfSessionServers(); - static char const * getSessionServer(int index); - static float getTimeBetweenSessionUpdates(); + static const uint16 getCentralServerPort(); - static const uint32 getDefaultGameFeatures (); - static const uint32 getDefaultSubscriptionFeatures(); - static uint32 getRequiredSubscriptionBits(); - static uint32 getRequiredGameBits(); - static bool getSetJtlRetailIfBetaIsSet(); - static bool getSetEpisode3RetailIfBetaIsSet(); - static bool getSetTrialsOfObiwanRetailIfBetaIsSet(); + static const int getClientOverflowLimit(); - static int getDisabledFeatureBits(); + static const char *getClientServiceBindInterface(); - static bool getValidateClientVersion(); + static const uint16 getClientServicePortPrivate(); - static int getConnectionServerNumber(); - static int getFakeBuddyPoints(); + static const uint16 getClientServicePortPublic(); - static const char * getPublicBindAddress(); + static const char *getClusterName(); + + static bool getDisableWorldSnapshot(); + + static const uint16 getGameServicePort(); + + static const int getMaxClients(); + + static const uint16 getPingPort(); + + static const bool getSpamLimitEnabled(); + + static const unsigned int getSpamLimitResetTimeMs(); + + static const unsigned int getSpamLimitResetScaleFactor(); + + static const unsigned int getSpamLimitBytesPerSec(); + + static const unsigned int getSpamLimitPacketsPerSec(); + + static const bool getStartPublicServer(); + + static const char *getChatServiceBindInterface(); + + static const char *getCustomerServiceBindInterface(); + + static const char *getGameServiceBindInterface(); + + static const bool getCompressClientNetworkTraffic(); + + static void install(); + + static void remove(); + + static const uint getCrashRecoveryTimeout(); + + static bool getShouldSleep(); + + static const int getClientMaxOutstandingPackets(); + + static const int getClientMaxRawPacketSize(); + + static const int getClientMaxConnections(); + + static const int getClientFragmentSize(); + + static const int getClientMaxDataHoldTime(); + + static const int getClientHashTableSize(); + + static const int getLagReportThreshold(); + + static bool getValidateStationKey(); + + static const char *getSessionServers(); + + static const int getSessionType(); + + static bool getDisableSessionLogout(); + + static bool getSessionRecordPlayTime(); + + static bool getDisconnectOnInactive(); + + static bool getDisconnectFreeTrialOnInactive(); + + static const char *getAdminAccountDataTable(void); + + static int getNumberOfSessionServers(); + + static char const *getSessionServer(int index); + + static float getTimeBetweenSessionUpdates(); + + static const uint32 getDefaultGameFeatures(); + + static const uint32 getDefaultSubscriptionFeatures(); + + static uint32 getRequiredSubscriptionBits(); + + static uint32 getRequiredGameBits(); + + static bool getSetJtlRetailIfBetaIsSet(); + + static bool getSetEpisode3RetailIfBetaIsSet(); + + static bool getSetTrialsOfObiwanRetailIfBetaIsSet(); + + static int getDisabledFeatureBits(); + + static bool getValidateClientVersion(); + + static int getConnectionServerNumber(); + + static int getFakeBuddyPoints(); + + static const char *getPublicBindAddress(); + + static int getMaxConnectionsPerIP(); - static int getMaxConnectionsPerIP(); private: - static Data * data; + static Data *data; }; -//----------------------------------------------------------------------- -inline bool ConfigConnectionServer::getShouldSleep() -{ - return data->shouldSleep; +inline const char *ConfigConnectionServer::getSessionURL() { + return data->sessionURL; } //----------------------------------------------------------------------- -inline const bool ConfigConnectionServer::getCompressClientNetworkTraffic() -{ - return data->compressClientNetworkTraffic; +inline bool ConfigConnectionServer::getShouldSleep() { + return data->shouldSleep; } //----------------------------------------------------------------------- -inline const char * ConfigConnectionServer::getCentralServerAddress () -{ - return data->centralServerAddress; +inline const bool ConfigConnectionServer::getCompressClientNetworkTraffic() { + return data->compressClientNetworkTraffic; } //----------------------------------------------------------------------- -inline const uint16 ConfigConnectionServer::getCentralServerPort () -{ - return static_cast(data->centralServerPort); +inline const char *ConfigConnectionServer::getCentralServerAddress() { + return data->centralServerAddress; } //----------------------------------------------------------------------- -inline const char* ConfigConnectionServer::getClientServiceBindInterface() -{ - return data->clientServiceBindInterface; +inline const uint16 ConfigConnectionServer::getCentralServerPort() { + return static_cast(data->centralServerPort); } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getClientOverflowLimit() -{ - return data->clientOverflowLimit; +inline const char *ConfigConnectionServer::getClientServiceBindInterface() { + return data->clientServiceBindInterface; } //----------------------------------------------------------------------- -inline const uint16 ConfigConnectionServer::getClientServicePortPrivate() -{ - return static_cast(data->clientServicePortPrivate); +inline const int ConfigConnectionServer::getClientOverflowLimit() { + return data->clientOverflowLimit; } //----------------------------------------------------------------------- -inline const uint16 ConfigConnectionServer::getClientServicePortPublic() -{ - return static_cast(data->clientServicePortPublic); +inline const uint16 ConfigConnectionServer::getClientServicePortPrivate() { + return static_cast(data->clientServicePortPrivate); } //----------------------------------------------------------------------- -inline const char * ConfigConnectionServer::getClusterName() -{ - return data->clusterName; +inline const uint16 ConfigConnectionServer::getClientServicePortPublic() { + return static_cast(data->clientServicePortPublic); } //----------------------------------------------------------------------- -inline bool ConfigConnectionServer::getDisableWorldSnapshot() -{ - return data->disableWorldSnapshot; +inline const char *ConfigConnectionServer::getClusterName() { + return data->clusterName; } //----------------------------------------------------------------------- -inline const uint16 ConfigConnectionServer::getGameServicePort() -{ - return static_cast(data->gameServicePort); +inline bool ConfigConnectionServer::getDisableWorldSnapshot() { + return data->disableWorldSnapshot; } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getMaxClients() -{ - return data->maxClients; +inline const uint16 ConfigConnectionServer::getGameServicePort() { + return static_cast(data->gameServicePort); } //----------------------------------------------------------------------- -inline const uint16 ConfigConnectionServer::getPingPort () -{ - return static_cast(data->pingPort); +inline const int ConfigConnectionServer::getMaxClients() { + return data->maxClients; } //----------------------------------------------------------------------- -inline const bool ConfigConnectionServer::getSpamLimitEnabled () -{ - return data->spamLimitEnabled; +inline const uint16 ConfigConnectionServer::getPingPort() { + return static_cast(data->pingPort); } //----------------------------------------------------------------------- -inline const unsigned int ConfigConnectionServer::getSpamLimitResetTimeMs () -{ - return static_cast(data->spamLimitResetTimeMs); +inline const bool ConfigConnectionServer::getSpamLimitEnabled() { + return data->spamLimitEnabled; } //----------------------------------------------------------------------- -inline const unsigned int ConfigConnectionServer::getSpamLimitResetScaleFactor () -{ - return static_cast(data->spamLimitResetScaleFactor); +inline const unsigned int ConfigConnectionServer::getSpamLimitResetTimeMs() { + return static_cast(data->spamLimitResetTimeMs); } //----------------------------------------------------------------------- -inline const unsigned int ConfigConnectionServer::getSpamLimitBytesPerSec () -{ - return static_cast(data->spamLimitBytesPerSec); +inline const unsigned int ConfigConnectionServer::getSpamLimitResetScaleFactor() { + return static_cast(data->spamLimitResetScaleFactor); } //----------------------------------------------------------------------- -inline const unsigned int ConfigConnectionServer::getSpamLimitPacketsPerSec () -{ - return static_cast(data->spamLimitPacketsPerSec); +inline const unsigned int ConfigConnectionServer::getSpamLimitBytesPerSec() { + return static_cast(data->spamLimitBytesPerSec); } //----------------------------------------------------------------------- -inline const bool ConfigConnectionServer::getStartPublicServer() -{ - return data->startPublicServer; +inline const unsigned int ConfigConnectionServer::getSpamLimitPacketsPerSec() { + return static_cast(data->spamLimitPacketsPerSec); } //----------------------------------------------------------------------- -inline const char * ConfigConnectionServer::getChatServiceBindInterface() -{ - return data->chatServiceBindInterface; +inline const bool ConfigConnectionServer::getStartPublicServer() { + return data->startPublicServer; } //----------------------------------------------------------------------- -inline const char * ConfigConnectionServer::getCustomerServiceBindInterface() -{ - return data->customerServiceBindInterface; +inline const char *ConfigConnectionServer::getChatServiceBindInterface() { + return data->chatServiceBindInterface; } //----------------------------------------------------------------------- -inline const char * ConfigConnectionServer::getGameServiceBindInterface() -{ - return data->gameServiceBindInterface; +inline const char *ConfigConnectionServer::getCustomerServiceBindInterface() { + return data->customerServiceBindInterface; +} + +//----------------------------------------------------------------------- + +inline const char *ConfigConnectionServer::getGameServiceBindInterface() { + return data->gameServiceBindInterface; } // ---------------------------------------------------------------------- -inline const uint ConfigConnectionServer::getCrashRecoveryTimeout() -{ - return static_cast(data->crashRecoveryTimeout); +inline const uint ConfigConnectionServer::getCrashRecoveryTimeout() { + return static_cast(data->crashRecoveryTimeout); } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getClientMaxOutstandingPackets() -{ - return data->clientMaxOutstandingPackets; +inline const int ConfigConnectionServer::getClientMaxOutstandingPackets() { + return data->clientMaxOutstandingPackets; } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getClientMaxRawPacketSize() -{ - return data->clientMaxRawPacketSize; +inline const int ConfigConnectionServer::getClientMaxRawPacketSize() { + return data->clientMaxRawPacketSize; } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getClientMaxConnections() -{ - return data->clientMaxConnections; +inline const int ConfigConnectionServer::getClientMaxConnections() { + return data->clientMaxConnections; } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getClientFragmentSize() -{ - return data->clientFragmentSize; +inline const int ConfigConnectionServer::getClientFragmentSize() { + return data->clientFragmentSize; } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getClientMaxDataHoldTime() -{ - return data->clientMaxDataHoldTime; +inline const int ConfigConnectionServer::getClientMaxDataHoldTime() { + return data->clientMaxDataHoldTime; } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getClientHashTableSize() -{ - return data->clientHashTableSize; +inline const int ConfigConnectionServer::getClientHashTableSize() { + return data->clientHashTableSize; } //----------------------------------------------------------------------- -inline const int ConfigConnectionServer::getLagReportThreshold() -{ - return data->lagReportThreshold; +inline const int ConfigConnectionServer::getLagReportThreshold() { + return data->lagReportThreshold; } // ---------------------------------------------------------------------- //------------------------------------------------------------------------------------------ -inline bool ConfigConnectionServer::getValidateStationKey() -{ - return data->validateStationKey; +inline bool ConfigConnectionServer::getValidateStationKey() { + return data->validateStationKey; } //------------------------------------------------------------------------------------------ -inline const char * ConfigConnectionServer::getSessionServers() -{ - return data->sessionServers; +inline const char *ConfigConnectionServer::getSessionServers() { + return data->sessionServers; } //------------------------------------------------------------------------------------------ -inline const int ConfigConnectionServer::getSessionType() -{ - return data->sessionType; +inline const int ConfigConnectionServer::getSessionType() { + return data->sessionType; } //------------------------------------------------------------------------------------------ -inline bool ConfigConnectionServer::getDisableSessionLogout() -{ - return data->disableSessionLogout; +inline bool ConfigConnectionServer::getDisableSessionLogout() { + return data->disableSessionLogout; } //------------------------------------------------------------------------------------------ -inline bool ConfigConnectionServer::getSessionRecordPlayTime() -{ - return data->sessionRecordPlayTime; +inline bool ConfigConnectionServer::getSessionRecordPlayTime() { + return data->sessionRecordPlayTime; } // ---------------------------------------------------------------------- -inline const char * ConfigConnectionServer::getAdminAccountDataTable(void) -{ - return data->adminAccountDataTable; +inline const char *ConfigConnectionServer::getAdminAccountDataTable(void) { + return data->adminAccountDataTable; } //----------------------------------------------------------------------- -inline float ConfigConnectionServer::getTimeBetweenSessionUpdates() -{ - return data->timeBetweenSessionUpdates; +inline float ConfigConnectionServer::getTimeBetweenSessionUpdates() { + return data->timeBetweenSessionUpdates; } //----------------------------------------------------------------------- -inline uint32 ConfigConnectionServer::getRequiredSubscriptionBits() -{ - return static_cast(data->requiredSubscriptionBits); +inline uint32 ConfigConnectionServer::getRequiredSubscriptionBits() { + return static_cast(data->requiredSubscriptionBits); } //----------------------------------------------------------------------- -inline uint32 ConfigConnectionServer::getRequiredGameBits() -{ - return static_cast(data->requiredGameBits); +inline uint32 ConfigConnectionServer::getRequiredGameBits() { + return static_cast(data->requiredGameBits); } //----------------------------------------------------------------------- -inline const uint32 ConfigConnectionServer::getDefaultGameFeatures() -{ - return static_cast(data->defaultGameFeatures); +inline const uint32 ConfigConnectionServer::getDefaultGameFeatures() { + return static_cast(data->defaultGameFeatures); } // ---------------------------------------------------------------------- -inline const uint32 ConfigConnectionServer::getDefaultSubscriptionFeatures() -{ - return static_cast(data->defaultSubscriptionFeatures); +inline const uint32 ConfigConnectionServer::getDefaultSubscriptionFeatures() { + return static_cast(data->defaultSubscriptionFeatures); } //------------------------------------------------------------------------------------------ -inline bool ConfigConnectionServer::getSetJtlRetailIfBetaIsSet() -{ - return data->setJtlRetailIfBetaIsSet; +inline bool ConfigConnectionServer::getSetJtlRetailIfBetaIsSet() { + return data->setJtlRetailIfBetaIsSet; } //------------------------------------------------------------------------------------------ -inline bool ConfigConnectionServer::getSetEpisode3RetailIfBetaIsSet() -{ - return data->setEpisode3RetailIfBetaIsSet; +inline bool ConfigConnectionServer::getSetEpisode3RetailIfBetaIsSet() { + return data->setEpisode3RetailIfBetaIsSet; } //------------------------------------------------------------------------------------------ -inline bool ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet() -{ - return data->setTrialsOfObiwanRetailIfBetaIsSet; +inline bool ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet() { + return data->setTrialsOfObiwanRetailIfBetaIsSet; } //------------------------------------------------------------------------------------------ -inline bool ConfigConnectionServer::getValidateClientVersion() -{ - return data->validateClientVersion; +inline bool ConfigConnectionServer::getValidateClientVersion() { + return data->validateClientVersion; } // ---------------------------------------------------------------------- -inline int ConfigConnectionServer::getConnectionServerNumber() -{ - return data->connectionServerNumber; +inline int ConfigConnectionServer::getConnectionServerNumber() { + return data->connectionServerNumber; } -inline int ConfigConnectionServer::getMaxConnectionsPerIP() -{ - return data->maxConnectionsPerIP; +inline int ConfigConnectionServer::getMaxConnectionsPerIP() { + return data->maxConnectionsPerIP; } #endif // _ConfigConnectionServer_H diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index a2abb2d5..6908638a 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -1422,9 +1422,9 @@ void LoginServer::onValidateClient(StationId suid, const std::string & username, if (ConfigLoginServer::getDoConsumption() || ConfigLoginServer::getDoSessionLogin()) { // pass the sessionkey - //len = apiSessionIdWidth + sizeof(StationId); - memcpy(keyBufferPointer, sessionKey, sizeof(sessionKey)); - keyBufferPointer += sizeof(sessionKey); + len = apiSessionIdWidth + sizeof(StationId); + memcpy(keyBufferPointer, sessionKey, apiSessionIdWidth); + keyBufferPointer += len; memcpy(keyBufferPointer, &suid, sizeof(StationId)); // if LoginServer did session login, send the session key back to the client; @@ -1432,7 +1432,7 @@ void LoginServer::onValidateClient(StationId suid, const std::string & username, // where the LoginServer does the session login, it will get it from the LoginServer if (ConfigLoginServer::getDoSessionLogin()) { - std::string const strSessionKey(sessionKey, sizeof(sessionKey)); + std::string const strSessionKey(sessionKey, apiSessionIdWidth); GenericValueTypeMessage const msg("SetSessionKey", strSessionKey); conn->send(msg, true); } From d4a8cd1dc9c3f4b5499a0edda2d283c2cc3f1adb Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 04:45:34 +0000 Subject: [PATCH 07/55] this may make more sense --- .../application/LoginServer/src/shared/LoginServer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 6908638a..9ac8266d 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -1421,9 +1421,12 @@ void LoginServer::onValidateClient(StationId suid, const std::string & username, if (ConfigLoginServer::getDoConsumption() || ConfigLoginServer::getDoSessionLogin()) { + std::string const strSessionKey(sessionKey); + size_t sessSize = sizeof(strSessionKey.c_str()); + // pass the sessionkey - len = apiSessionIdWidth + sizeof(StationId); - memcpy(keyBufferPointer, sessionKey, apiSessionIdWidth); + len = sessSize + sizeof(StationId); + memcpy(keyBufferPointer, sessionKey, sessSize); keyBufferPointer += len; memcpy(keyBufferPointer, &suid, sizeof(StationId)); @@ -1432,7 +1435,6 @@ void LoginServer::onValidateClient(StationId suid, const std::string & username, // where the LoginServer does the session login, it will get it from the LoginServer if (ConfigLoginServer::getDoSessionLogin()) { - std::string const strSessionKey(sessionKey, apiSessionIdWidth); GenericValueTypeMessage const msg("SetSessionKey", strSessionKey); conn->send(msg, true); } From 10ba962aa51298bb0fa60c28b8e70f726fb2f08f Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sat, 31 Dec 2016 22:51:02 -0600 Subject: [PATCH 08/55] debug output --- .../src/shared/ClientConnection.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 35b9c496..dfc2721c 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -323,7 +323,8 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { static const std::string authURL(ConfigConnectionServer::getSessionURL()); - if (!authURL.empty()) { + if (ConfigConnectionServer::getValidateStationKey() && !authURL.empty()) { + printf("\nAttempting to test our session...\n"); webAPI api(authURL); std::string clientIP = getRemoteAddress(); @@ -333,22 +334,30 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { api.addJsonData("ip", clientIP); if (api.submit()) { + printf("\tSubmission ok...\n"); bool status = api.getNullableValue("status"); if (status) { + printf("\tStatus ok....\n"); StationId apiSuid = api.getNullableValue("user_id"); int expired = api.getNullableValue("expired"); std::string apiUser = api.getString("user_name"); std::string apiIP = api.getString("ip"); if (!expired) { + printf("\tNot expired...\n"); if (apiSuid && apiSuid == m_suid && apiIP == clientIP) { + printf("\tTrying the decrypt bit...\n"); result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); } + } else { + printf("\tExpired token!\n"); } + } else { + printf("\tStatus bad!...\n"); } } else { - result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + printf("\tNo api submit :(\n"); } } else { // assume local testing result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); From 0328338e8c91ce1783315b9904510ae26ebc1570 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sat, 31 Dec 2016 23:11:03 -0600 Subject: [PATCH 09/55] more debug --- .../src/shared/ClientConnection.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index dfc2721c..421baed9 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -321,11 +321,13 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { Archive::ReadIterator ri(t); KeyShare::Token token(ri); - static const std::string authURL(ConfigConnectionServer::getSessionURL()); + static const std::string sessURL(ConfigConnectionServer::getSessionURL()); - if (ConfigConnectionServer::getValidateStationKey() && !authURL.empty()) { + printf("url is %s", sessURL.c_str()); + + if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { printf("\nAttempting to test our session...\n"); - webAPI api(authURL); + webAPI api(sessURL); std::string clientIP = getRemoteAddress(); @@ -344,10 +346,11 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { std::string apiUser = api.getString("user_name"); std::string apiIP = api.getString("ip"); - if (!expired) { + if (expired == 0) { printf("\tNot expired...\n"); - if (apiSuid && apiSuid == m_suid && apiIP == clientIP) { + if (apiSuid && apiIP == clientIP) { printf("\tTrying the decrypt bit...\n"); + m_suid = apiSuid; result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); } } else { From 2cd0af76e36a6cf28b8a19cd970f4fbd57231f85 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 06:23:47 +0000 Subject: [PATCH 10/55] getting closer, but no cigar --- .../src/shared/ClientConnection.cpp | 31 +++++++------------ .../src/shared/ConnectionServer.cpp | 5 --- .../LoginServer/src/shared/LoginServer.cpp | 5 --- .../LoginServer/src/shared/PurgeManager.cpp | 5 +-- 4 files changed, 12 insertions(+), 34 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 421baed9..5dd3e235 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -312,6 +312,7 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { DEBUG_FATAL(m_hasSelectedCharacter, ("Trying to validate a client who already has a character selected.\n")); bool result = false; + StationId apiSuid = 0; char sessionId[apiSessionIdWidth]; m_gameBitsToClear = msg.getGameBitsToClear(); @@ -341,7 +342,7 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { if (status) { printf("\tStatus ok....\n"); - StationId apiSuid = api.getNullableValue("user_id"); + apiSuid = api.getNullableValue("user_id"); int expired = api.getNullableValue("expired"); std::string apiUser = api.getString("user_name"); std::string apiIP = api.getString("ip"); @@ -363,6 +364,7 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { printf("\tNo api submit :(\n"); } } else { // assume local testing + printf("something isn't right or we're just testing...\n"); result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); } @@ -405,29 +407,18 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { return; } - if (ConfigConnectionServer::getValidateStationKey()) { - SessionApiClient *session = ConnectionServer::getSessionApiClient(); - NOT_NULL(session); - if (session) { - session->validateClient(this, sessionId); - } else { - ConnectionServer::dropClient(this, "SessionApiClient is not available!"); - disconnect(); - } - } else { - if (!m_suid) { - m_suid = atoi(m_accountName.c_str()); - if (m_suid == 0) { - + if (!m_suid && !ConfigConnectionServer::getValidateStationKey()) { + m_suid = atoi(m_accountName.c_str()); + if (m_suid == 0) { std::hash h; m_suid = h(m_accountName.c_str()); } - } - onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, - ConfigConnectionServer::getDefaultGameFeatures(), - ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, - ConfigConnectionServer::getFakeBuddyPoints()); } + + onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, + ConfigConnectionServer::getDefaultGameFeatures(), + ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, + ConfigConnectionServer::getFakeBuddyPoints()); } else { // They sent us a token that was no good -- either a hack attempt, or // possibly it was just too old. diff --git a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp index 6eb0c07d..18a42389 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp @@ -119,11 +119,6 @@ ConnectionServer::ConnectionServer() : Address a("", ConfigConnectionServer::getPingPort()); IGNORE_RETURN(pingSocket->bind(a)); - - if (ConfigConnectionServer::getValidateStationKey()) - { - installSessionValidation(); - } } //----------------------------------------------------------------------- diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 9ac8266d..afa12138 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -201,11 +201,6 @@ LoginServer::LoginServer() : connectToMessage("FeatureIdTransactionRequest"); connectToMessage("FeatureIdTransactionSyncUpdate"); keyServer = new KeyServer; - - /*if (ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) - { - installSessionValidation(); - }*/ } //----------------------------------------------------------------------- diff --git a/engine/server/application/LoginServer/src/shared/PurgeManager.cpp b/engine/server/application/LoginServer/src/shared/PurgeManager.cpp index 2d649c52..043d468f 100755 --- a/engine/server/application/LoginServer/src/shared/PurgeManager.cpp +++ b/engine/server/application/LoginServer/src/shared/PurgeManager.cpp @@ -120,10 +120,7 @@ void PurgeManager::onGetAccountForPurge(StationId account, int purgePhase) PurgeRecord record(account, static_cast(purgePhase)); m_purgeRecords.insert(std::make_pair(account,record)); - if (ConfigLoginServer::getValidateStationKey()) - NON_NULL(LoginServer::getInstance().getSessionApiClient())->checkStatusForPurge(account); - else - onCheckStatusForPurge(account, false); + onCheckStatusForPurge(account, false); } } From 752737c49428dcf0d8aec0145a840d809d5532ad Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 01:53:55 -0600 Subject: [PATCH 11/55] more debgu --- .../ConnectionServer/src/shared/ClientConnection.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 5dd3e235..d934629f 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -250,6 +250,10 @@ void ClientConnection::sendPlayTimeInfoToGameServer() const { // ---------------------------------------------------------------------- void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) { + if (!m_sessionValidated) { + + } + //Only accept this message from clients who have been validated and //haven't already selected. if (m_hasSelectedCharacter || m_validatingCharacter || !m_hasBeenValidated || !m_sessionValidated) { @@ -371,6 +375,8 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { static const std::string loginTrace("TRACE_LOGIN"); LOG(loginTrace, ("ClientConnection SUID = %d", m_suid)); + } else { + printf("\ttoken is 0\n"); } if (result) { //check for duplicate login From 63888363e47e258013854ccb83a1a1f52000177a Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 07:55:12 +0000 Subject: [PATCH 12/55] wtf --- engine/server/library/serverDatabase/src/shared/Persister.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/engine/server/library/serverDatabase/src/shared/Persister.cpp b/engine/server/library/serverDatabase/src/shared/Persister.cpp index 301eb58c..461cf7a0 100755 --- a/engine/server/library/serverDatabase/src/shared/Persister.cpp +++ b/engine/server/library/serverDatabase/src/shared/Persister.cpp @@ -394,8 +394,6 @@ Snapshot * Persister::getSnapshotForObject(const NetworkId &networkId, uint32 se { Snapshot *snap = getSnapshotForServer(serverId); - pad.lock(); - m_objectSnapshotMap[networkId]=snap; return snap; } From 759587cb0a040ac385caa9f11d659f6e934e28d1 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 02:14:37 -0600 Subject: [PATCH 13/55] this may work... --- .../src/shared/ClientConnection.cpp | 2167 ++++++++--------- 1 file changed, 1002 insertions(+), 1165 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index d934629f..983fc0f7 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -72,62 +72,28 @@ using namespace ClientConnectionNamespace; //----------------------------------------------------------------------- -std::map ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute -std::map ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute +std::map ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute +std::map ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute uint32 ClientConnection::sm_outgoingBytesMap_Worktime = 0; // time we started filling in the working map //----------------------------------------------------------------------- -ClientConnection::ClientConnection(UdpConnectionMT *u, TcpClient *t) : - ServerConnection(u, t), - m_accountName(""), - m_canCreateRegularCharacter(false), - m_canCreateJediCharacter(false), - m_hasRequestedCharacterCreate(false), - m_hasCreatedCharacter(false), - m_pendingCharacterCreate(nullptr), - m_canSkipTutorial(false), - m_characterId(NetworkId::cms_invalid), - m_characterName(), - m_startPlayTime(0), - m_lastActiveTime(0), - m_activePlayTimeDuration(0), - m_client(0), - m_containerId(NetworkId::cms_invalid), - m_featureBitsGame(0), - m_featureBitsSubscription(0), - m_hasBeenSentToGameServer(false), - m_hasBeenValidated(false), - m_hasSelectedCharacter(false), - m_isSecure(false), - m_isAdminAccount(false), - m_hasCSLoggedAccountFeatureIds(false), - m_suid(0), - m_requestedSuid(0), - m_usingAdminLogin(false), - m_targetCoordinates(), - m_targetScene(""), - m_validatingCharacter(false), - m_receiveHistoryBytes(0), - m_receiveHistoryPackets(0), - m_receiveHistoryMs(0), - m_receiveLastTimeMs(0), - m_sendLastTimeMs(0), - m_sessionId(""), - m_sessionValidated(false), - m_connectionServerLag(0), - m_gameServerLag(0), - m_countSpamLimitResetTime(0), - m_entitlementTotalTime(0), - m_entitlementEntitledTime(0), - m_entitlementTotalTimeSinceLastLogin(0), - m_entitlementEntitledTimeSinceLastLogin(0), - m_buddyPoints(0), - m_sendToStarport(false), - m_pendingChatEnterRoomRequests(), - m_pendingChatQueryRoomRequests() { +ClientConnection::ClientConnection(UdpConnectionMT *u, TcpClient *t) + : ServerConnection(u, t), m_accountName(""), m_canCreateRegularCharacter(false), + m_canCreateJediCharacter(false), m_hasRequestedCharacterCreate(false), m_hasCreatedCharacter(false), + m_pendingCharacterCreate(nullptr), m_canSkipTutorial(false), m_characterId(NetworkId::cms_invalid), + m_characterName(), m_startPlayTime(0), m_lastActiveTime(0), m_activePlayTimeDuration(0), m_client(0), + m_containerId(NetworkId::cms_invalid), m_featureBitsGame(0), m_featureBitsSubscription(0), + m_hasBeenSentToGameServer(false), m_hasBeenValidated(false), m_hasSelectedCharacter(false), m_isSecure(false), + m_isAdminAccount(false), m_hasCSLoggedAccountFeatureIds(false), m_suid(0), m_requestedSuid(0), + m_usingAdminLogin(false), m_targetCoordinates(), m_targetScene(""), m_validatingCharacter(false), + m_receiveHistoryBytes(0), m_receiveHistoryPackets(0), m_receiveHistoryMs(0), m_receiveLastTimeMs(0), + m_sendLastTimeMs(0), m_sessionId(""), m_sessionValidated(false), m_connectionServerLag(0), m_gameServerLag(0), + m_countSpamLimitResetTime(0), m_entitlementTotalTime(0), m_entitlementEntitledTime(0), + m_entitlementTotalTimeSinceLastLogin(0), m_entitlementEntitledTimeSinceLastLogin(0), m_buddyPoints(0), + m_sendToStarport(false), m_pendingChatEnterRoomRequests(), m_pendingChatQueryRoomRequests() { static const std::string loginTrace("TRACE_LOGIN"); LOG(loginTrace, ("new ClientConnection")); @@ -151,14 +117,10 @@ ClientConnection::~ClientConnection() { // tell Session to stop recording play time for the character if (m_hasBeenValidated && m_sessionValidated && ConnectionServer::getSessionApiClient() && (m_lastActiveTime > 0) && ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", - ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); // log total active play time for the session to the balance log - LOG("GameBalance", - ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); + LOG("GameBalance", ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); ConnectionServer::getSessionApiClient()->stopPlay(*this); } @@ -167,7 +129,9 @@ ClientConnection::~ClientConnection() { ConnectionServer::getSessionApiClient()->dropClient(this, hasBeenKicked); } - std::map::const_iterator iter; + std::map < unsigned + long, GameClientMessage * > ::const_iterator + iter; for (iter = m_pendingChatEnterRoomRequests.begin(); iter != m_pendingChatEnterRoomRequests.end(); ++iter) { delete iter->second; } @@ -200,8 +164,9 @@ const std::string &ClientConnection::getCharacterName() const { std::string ClientConnection::getPlayTimeDuration() const { int playTimeDuration = 0; - if (m_startPlayTime > 0) + if (m_startPlayTime > 0) { playTimeDuration = static_cast(::time(nullptr) - m_startPlayTime); + } return CalendarTime::convertSecondsToHMS(static_cast(playTimeDuration)); } @@ -211,8 +176,9 @@ std::string ClientConnection::getPlayTimeDuration() const { std::string ClientConnection::getActivePlayTimeDuration() const { int activePlayTimeDuration = static_cast(m_activePlayTimeDuration); - if (m_lastActiveTime > 0) + if (m_lastActiveTime > 0) { activePlayTimeDuration += static_cast(::time(nullptr) - m_lastActiveTime); + } return CalendarTime::convertSecondsToHMS(static_cast(activePlayTimeDuration)); } @@ -222,8 +188,9 @@ std::string ClientConnection::getActivePlayTimeDuration() const { std::string ClientConnection::getCurrentActivePlayTimeDuration() const { int activePlayTimeDuration = 0; - if (m_lastActiveTime > 0) + if (m_lastActiveTime > 0) { activePlayTimeDuration = static_cast(::time(nullptr) - m_lastActiveTime); + } return CalendarTime::convertSecondsToHMS(static_cast(activePlayTimeDuration)); } @@ -233,14 +200,12 @@ std::string ClientConnection::getCurrentActivePlayTimeDuration() const { void ClientConnection::sendPlayTimeInfoToGameServer() const { if (m_client && m_client->getGameConnection()) { // update the game server with play time info - GenericValueTypeMessage > > const msgPlayTimeInfo( - "UpdateSessionPlayTimeInfo", - std::make_pair(static_cast(m_startPlayTime), - std::make_pair(static_cast(m_lastActiveTime), m_activePlayTimeDuration) - ) - ); + GenericValueTypeMessage < std::pair < int32, std::pair < int32, unsigned + long > > > + const msgPlayTimeInfo( + "UpdateSessionPlayTimeInfo", std::make_pair(static_cast(m_startPlayTime), std::make_pair(static_cast(m_lastActiveTime), m_activePlayTimeDuration))); - std::vector v; + std::vector v; v.push_back(m_client->getNetworkId()); GameClientMessage const gcm(v, true, msgPlayTimeInfo); m_client->getGameConnection()->send(gcm, true); @@ -258,20 +223,16 @@ void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) //haven't already selected. if (m_hasSelectedCharacter || m_validatingCharacter || !m_hasBeenValidated || !m_sessionValidated) { if (m_hasSelectedCharacter) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has already selected a character", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has already selected a character", getSUID())); } if (m_validatingCharacter) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has not yet received validation", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not yet received validation", getSUID())); } if (!m_hasBeenValidated) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has not been validated", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been validated", getSUID())); } if (!m_sessionValidated) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has not been session validated", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been session validated", getSUID())); } return; @@ -285,8 +246,7 @@ void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) ValidateCharacterForLoginMessage vclm(getSUID(), msg.getId()); ConnectionServer::sendToCentralProcess(vclm); - LOG("TraceCharacterSelection", - ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); + LOG("TraceCharacterSelection", ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); } @@ -311,14 +271,12 @@ void ClientConnection::handleGameServerForLoginMessage(uint32 serverId) { */ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { //Only check clients that have not been validated. - if (m_hasBeenValidated) + if (m_hasBeenValidated) { return; + } DEBUG_FATAL(m_hasSelectedCharacter, ("Trying to validate a client who already has a character selected.\n")); bool result = false; - StationId apiSuid = 0; - char sessionId[apiSessionIdWidth]; - m_gameBitsToClear = msg.getGameBitsToClear(); if (msg.getTokenSize() > 0) { @@ -326,488 +284,333 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { Archive::ReadIterator ri(t); KeyShare::Token token(ri); + result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + + StationId apiSuid = 0; static const std::string sessURL(ConfigConnectionServer::getSessionURL()); - printf("url is %s", sessURL.c_str()); + if (result) { + if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { + bool cont = false; - if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { - printf("\nAttempting to test our session...\n"); - webAPI api(sessURL); + printf("\nAttempting to test our session...\n"); - std::string clientIP = getRemoteAddress(); + webAPI api(sessURL); + std::string clientIP = getRemoteAddress(); - // add our data - api.addJsonData("session_key", std::string(sessionId)); - api.addJsonData("ip", clientIP); + // add our data + api.addJsonData("session_key", std::string(sessionId)); + api.addJsonData("ip", clientIP); - if (api.submit()) { - printf("\tSubmission ok...\n"); - bool status = api.getNullableValue("status"); + if (api.submit()) { + bool status = api.getNullableValue("status"); - if (status) { - printf("\tStatus ok....\n"); - apiSuid = api.getNullableValue("user_id"); - int expired = api.getNullableValue("expired"); - std::string apiUser = api.getString("user_name"); - std::string apiIP = api.getString("ip"); + if (status) { + apiSuid = api.getNullableValue("user_id"); + int expired = api.getNullableValue("expired"); + std::string apiUser = api.getString("user_name"); + std::string apiIP = api.getString("ip"); - if (expired == 0) { - printf("\tNot expired...\n"); - if (apiSuid && apiIP == clientIP) { - printf("\tTrying the decrypt bit...\n"); - m_suid = apiSuid; - result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + if (expired == 0) { + if (apiSuid == m_suid && apiIP == clientIP) { + cont = true; + } } - } else { - printf("\tExpired token!\n"); } - } else { - printf("\tStatus bad!...\n"); } - } else { - printf("\tNo api submit :(\n"); + + if (!cont) { + LOG("ClientDisconnect", ("SUID %d (%d) passed a bad token to the connections erver. Disconnecting.", m_suid, apiSuid)); + disconnect(); + } + } else { // assume local testing + result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); } - } else { // assume local testing - printf("something isn't right or we're just testing...\n"); - result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); - } - static const std::string loginTrace("TRACE_LOGIN"); - LOG(loginTrace, ("ClientConnection SUID = %d", m_suid)); + static const std::string loginTrace("TRACE_LOGIN"); + LOG(loginTrace, ("ClientConnection SUID = %d", m_suid)); - } else { - printf("\ttoken is 0\n"); - } - if (result) { - //check for duplicate login - ClientConnection *oldConnection = ConnectionServer::getClientConnection(m_suid); - if (oldConnection) { - //There is already someone connected to this cluster with this suid. - LOG("Network", ("SUID %d already logged in, disconnecting client.\n", m_suid)); + //check for duplicate login + ClientConnection *oldConnection = ConnectionServer::getClientConnection(m_suid); + if (oldConnection) { + //There is already someone connected to this cluster with this suid. + LOG("Network", ("SUID %d already logged in, disconnecting client.\n", m_suid)); - ConnectionServer::dropClient(oldConnection, "Already Connected"); + ConnectionServer::dropClient(oldConnection, "Already Connected"); - disconnect(); - return; - } + disconnect(); + return; + } - // verify version - if (ConfigConnectionServer::getValidateClientVersion() && - msg.getVersion() != GameNetworkMessage::NetworkVersionId) { - std::string strSessionId(sessionId, apiSessionIdWidth); - strSessionId += '\0'; + // verify version + if (ConfigConnectionServer::getValidateClientVersion() && + msg.getVersion() != GameNetworkMessage::NetworkVersionId) { + std::string strSessionId(sessionId, apiSessionIdWidth); + strSessionId += '\0'; - const int bufferSize = 255 + apiSessionIdWidth; - char *buffer = new char[bufferSize]; - snprintf(buffer, bufferSize - 1, - "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", - getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), - GameNetworkMessage::NetworkVersionId.c_str()); - buffer[bufferSize - 1] = '\0'; + const int bufferSize = 255 + apiSessionIdWidth; + char *buffer = new char[bufferSize]; + snprintf(buffer, bufferSize - + 1, "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), GameNetworkMessage::NetworkVersionId.c_str()); + buffer[bufferSize - 1] = '\0'; - ConnectionServer::dropClient(this, std::string(buffer)); - disconnect(); + ConnectionServer::dropClient(this, std::string(buffer)); + disconnect(); - delete[] buffer; + delete[] buffer; - return; - } + return; + } - if (!m_suid && !ConfigConnectionServer::getValidateStationKey()) { - m_suid = atoi(m_accountName.c_str()); - if (m_suid == 0) { - std::hash h; + if (!m_suid && !ConfigConnectionServer::getValidateStationKey()) { + WARNING(true, ("Generating suid from username. This is not safe or secure.")); + m_suid = atoi(m_accountName.c_str()); + if (m_suid == 0) { + std::hash h; m_suid = h(m_accountName.c_str()); } - } + } - onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, - ConfigConnectionServer::getDefaultGameFeatures(), - ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, - ConfigConnectionServer::getFakeBuddyPoints()); - } else { - // They sent us a token that was no good -- either a hack attempt, or - // possibly it was just too old. - LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); - disconnect(); - } -} - -//----------------------------------------------------------------------- - -void ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, - bool canSkipTutorial, - std::vector > const &consumedRewardEvents, - std::vector > const &claimedRewardItems) { - //@todo start session with station. - //@todo add more permissions to this message as needed. - - // resume character creation - if (m_pendingCharacterCreate) { - if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); - disconnect(); - } else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); - disconnect(); - } else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to create any characters", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); - disconnect(); + onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, ConfigConnectionServer::getDefaultGameFeatures(), ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, ConfigConnectionServer::getFakeBuddyPoints()); } else { - ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); - LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); - - m_hasRequestedCharacterCreate = true; + // They sent us a token that was no good -- either a hack attempt, or + // possibly it was just too old. + LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); + disconnect(); } - - delete m_pendingCharacterCreate; - m_pendingCharacterCreate = nullptr; - - return; } - // Save lists of claimed rewards, which won't be used again until later in the login sequence - m_consumedRewardEvents = consumedRewardEvents; - m_claimedRewardItems = claimedRewardItems; - - - 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 - { - canLogin = true; - canCreateRegularCharacter = true; - canSkipTutorial = true; - m_isAdminAccount = true; - } - - ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial); - send(c, true); - - DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID())); - DEBUG_REPORT_LOG(canLogin, ("\tcanLogin\n")); - DEBUG_REPORT_LOG(canCreateRegularCharacter, ("\tcanCreateRegularCharacter\n")); - DEBUG_REPORT_LOG(canCreateJediCharacter, ("\tcanCreateJediCharacter\n")); - DEBUG_REPORT_LOG(canSkipTutorial, ("\tcanSkipTutorial\n")); - DEBUG_REPORT_LOG(!(canLogin || canCreateRegularCharacter || canCreateJediCharacter || canSkipTutorial), - ("\tnone\n")); - - if (canLogin) { - m_hasBeenValidated = true; - m_canCreateRegularCharacter = canCreateRegularCharacter; - m_canCreateJediCharacter = canCreateJediCharacter; - m_canSkipTutorial = canSkipTutorial; - } else { - LOG("TRACE_LOGIN", ("%d does not have permissions to log in", getSUID())); - LOG("ClientDisconnect", ("Client (SUID %u) does not have permissions to log in. Disconnecting.", getSUID())); - disconnect(); - } -} - //----------------------------------------------------------------------- -void ClientConnection::onConnectionClosed() { - ServerConnection::onConnectionClosed(); - static MessageConnectionCallback m("ClientConnectionClosed"); - emitMessage(m); + void + ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems) { + //@todo start session with station. + //@todo add more permissions to this message as needed. - LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); - if (m_client) { - if (!m_client->hasBeenKicked()) { - LOG("CustomerService", - ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount( - this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); + // resume character creation + if (m_pendingCharacterCreate) { + if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial + LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + disconnect(); + } else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + disconnect(); + } else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + disconnect(); + } else { + ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); + LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); + + m_hasRequestedCharacterCreate = true; + } + + delete m_pendingCharacterCreate; + m_pendingCharacterCreate = nullptr; + + return; } - ChatServerConnection *chatConnection = m_client->getChatConnection(); - if (chatConnection) { - ChatDisconnectAvatar m(m_characterId); - chatConnection->send(m, true); + + // Save lists of claimed rewards, which won't be used again until later in the login sequence + m_consumedRewardEvents = consumedRewardEvents; + m_claimedRewardItems = claimedRewardItems; + + + 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 + { + canLogin = true; + canCreateRegularCharacter = true; + canSkipTutorial = true; + m_isAdminAccount = true; + } + + ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial); + send(c, true); + + DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID())); + DEBUG_REPORT_LOG(canLogin, ("\tcanLogin\n")); + DEBUG_REPORT_LOG(canCreateRegularCharacter, ("\tcanCreateRegularCharacter\n")); + DEBUG_REPORT_LOG(canCreateJediCharacter, ("\tcanCreateJediCharacter\n")); + DEBUG_REPORT_LOG(canSkipTutorial, ("\tcanSkipTutorial\n")); + DEBUG_REPORT_LOG(!(canLogin || canCreateRegularCharacter || canCreateJediCharacter || + canSkipTutorial), ("\tnone\n")); + + if (canLogin) { + m_hasBeenValidated = true; + m_canCreateRegularCharacter = canCreateRegularCharacter; + m_canCreateJediCharacter = canCreateJediCharacter; + m_canSkipTutorial = canSkipTutorial; + } else { + LOG("TRACE_LOGIN", ("%d does not have permissions to log in", getSUID())); + LOG("ClientDisconnect", ("Client (SUID %u) does not have permissions to log in. Disconnecting.", getSUID())); + disconnect(); } - // We cannot do this here, as this connection will be deleted on - // return from this function already. - //m_client->kick(); } -} //----------------------------------------------------------------------- -void ClientConnection::onConnectionOpened() { - ServerConnection::onConnectionOpened(); - static MessageConnectionCallback m("ClientConnectionOpened"); - emitMessage(m); - setOverflowLimit(ConfigConnectionServer::getClientOverflowLimit()); -} + void ClientConnection::onConnectionClosed() { + ServerConnection::onConnectionClosed(); + static MessageConnectionCallback m("ClientConnectionClosed"); + emitMessage(m); + + LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); + if (m_client) { + if (!m_client->hasBeenKicked()) { + LOG("CustomerService", ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount(this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); + } + ChatServerConnection *chatConnection = m_client->getChatConnection(); + if (chatConnection) { + ChatDisconnectAvatar m(m_characterId); + chatConnection->send(m, true); + } + // We cannot do this here, as this connection will be deleted on + // return from this function already. + //m_client->kick(); + } + } //----------------------------------------------------------------------- -void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) { - char errbuf[1024]; - snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", - bytesPending); - LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); - - std::vector >::const_iterator i; - for (i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) { - LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); + void ClientConnection::onConnectionOpened() { + ServerConnection::onConnectionOpened(); + static MessageConnectionCallback m("ClientConnectionOpened"); + emitMessage(m); + setOverflowLimit(ConfigConnectionServer::getClientOverflowLimit()); } +//----------------------------------------------------------------------- + + void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) { + char errbuf[1024]; + snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", bytesPending); + LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); + + std::vector < std::pair < std::string, int > > ::const_iterator + i; + for (i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) { + LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); + } + // ErrorMessage err(name, desc, false); // send(err, true); - WARNING(true, (errbuf)); - LOG("ClientDisconnect", - ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); + WARNING(true, (errbuf)); + LOG("ClientDisconnect", ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); - snprintf(errbuf, sizeof(errbuf) - 1, "Connection Overflow (bytes pending=%u)", bytesPending); - errbuf[sizeof(errbuf) - 1] = '\0'; - ConnectionServer::dropClient(this, std::string(errbuf)); -} - -//----------------------------------------------------------------------- - -bool ClientConnection::checkSpamLimit(unsigned int messageSize) { - if (!ConfigConnectionServer::getSpamLimitEnabled()) - return true; - - unsigned long curTimeMs = Clock::timeMs(); - if (m_receiveLastTimeMs) { - ++m_receiveHistoryPackets; - m_receiveHistoryBytes += messageSize; - m_receiveHistoryMs += curTimeMs - m_receiveLastTimeMs; - - // rescale the history information if we've exceeded the reset time; this - // must be done before the spam check below or else we may run into overflow - // issues because m_receiveHistoryMs could be pretty large if we haven't - // received anything from the client for a while - while (m_receiveHistoryMs > ConfigConnectionServer::getSpamLimitResetTimeMs()) { - ++m_countSpamLimitResetTime; - - unsigned int resetScale = ConfigConnectionServer::getSpamLimitResetScaleFactor(); - m_receiveHistoryMs /= resetScale; - m_receiveHistoryBytes /= resetScale; - m_receiveHistoryPackets /= resetScale; - } - - // check for exceeding limits, but wait for at least - // one reset cycle so that there has been enough - // elapsed time, so we won't get a false positive - if (m_countSpamLimitResetTime) { - if (m_receiveHistoryBytes >= - m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitBytesPerSec() / 1000) { - LOG("Network", - ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); - return false; - } - if (m_receiveHistoryPackets >= - m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitPacketsPerSec() / 1000) { - LOG("Network", - ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); - return false; - } - } + snprintf(errbuf, sizeof(errbuf) - 1, "Connection Overflow (bytes pending=%u)", bytesPending); + errbuf[sizeof(errbuf) - 1] = '\0'; + ConnectionServer::dropClient(this, std::string(errbuf)); } - m_receiveLastTimeMs = curTimeMs; - return true; -} //----------------------------------------------------------------------- -void ClientConnection::onReceive(const Archive::ByteStream &message) { - try { - if (!checkSpamLimit(message.getSize())) { - ConnectionServer::dropClient(this, "Spam Detected"); - return; + bool ClientConnection::checkSpamLimit(unsigned int messageSize) { + if (!ConfigConnectionServer::getSpamLimitEnabled()) { + return true; } unsigned long curTimeMs = Clock::timeMs(); - if (m_sendLastTimeMs + - std::min(gs_receiveDelayMaxMs, static_cast(Clock::frameTime() * 1000.0f)) < curTimeMs) { - static HeartBeat h; - send(h, false); + if (m_receiveLastTimeMs) { + ++m_receiveHistoryPackets; + m_receiveHistoryBytes += messageSize; + m_receiveHistoryMs += curTimeMs - m_receiveLastTimeMs; + + // rescale the history information if we've exceeded the reset time; this + // must be done before the spam check below or else we may run into overflow + // issues because m_receiveHistoryMs could be pretty large if we haven't + // received anything from the client for a while + while (m_receiveHistoryMs > ConfigConnectionServer::getSpamLimitResetTimeMs()) { + ++m_countSpamLimitResetTime; + + unsigned int resetScale = ConfigConnectionServer::getSpamLimitResetScaleFactor(); + m_receiveHistoryMs /= resetScale; + m_receiveHistoryBytes /= resetScale; + m_receiveHistoryPackets /= resetScale; + } + + // check for exceeding limits, but wait for at least + // one reset cycle so that there has been enough + // elapsed time, so we won't get a false positive + if (m_countSpamLimitResetTime) { + if (m_receiveHistoryBytes >= + m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitBytesPerSec() / 1000) { + LOG("Network", ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); + return false; + } + if (m_receiveHistoryPackets >= + m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitPacketsPerSec() / 1000) { + LOG("Network", ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); + return false; + } + } } + m_receiveLastTimeMs = curTimeMs; + return true; + } - Archive::ReadIterator ri = message.begin(); - GameNetworkMessage m(ri); - ri = message.begin(); +//----------------------------------------------------------------------- - const uint32 messageType = m.getType(); + void ClientConnection::onReceive(const Archive::ByteStream &message) { + try { + if (!checkSpamLimit(message.getSize())) { + ConnectionServer::dropClient(this, "Spam Detected"); + return; + } - //Clients with a selected character get routed to a game server. - //@todo check for filtering out bad messages. - if (m_hasSelectedCharacter) { - // if it is a chat message, send it directly to the chat server - switch (messageType) { - case constcrc("ChatAddFriend") : - case constcrc("ChatAddModeratorToRoom") : - case constcrc("ChatBanAvatarFromRoom") : - case constcrc("ChatCreateRoom") : - case constcrc("ChatDeletePersistentMessage") : - case constcrc("ChatDeleteAllPersistentMessages") : - case constcrc("ChatDestroyRoom") : - case constcrc("ChatInstantMessageToCharacter") : - case constcrc("ChatInviteAvatarToRoom") : - case constcrc("ChatKickAvatarFromRoom") : - case constcrc("ChatRemoveAvatarFromRoom") : - case constcrc("ChatRemoveFriend") : - case constcrc("ChatRemoveModeratorFromRoom") : - case constcrc("ChatRequestPersistentMessage") : - case constcrc("ChatRequestRoomList") : - case constcrc("ChatSendToRoom") : - case constcrc("ChatUninviteFromRoom") : - case constcrc("ChatUnbanAvatarFromRoom") : - case constcrc("VerifyPlayerNameMessage") : { - DEBUG_REPORT_LOG(true, ("ConnServ: ClientConnection::onReceive()\n")); + unsigned long curTimeMs = Clock::timeMs(); + if (m_sendLastTimeMs + + std::min(gs_receiveDelayMaxMs, static_cast(Clock::frameTime() * 1000.0f)) < curTimeMs) { + static HeartBeat h; + send(h, false); + } - NOT_NULL(m_client); - if (m_client) { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, ri); - if (m_client->getChatConnection()) { - m_client->getChatConnection()->send(gcm, true); - } else { - // defer chat messages until a server is back online - Archive::ByteStream bs; - m.pack(bs); - m_client->deferChatMessage(bs); - } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - // ChatEnterRoom and ChatEnterRoomById needs to go to the game server to determine - // if the character is not allowed to enter the room because of game rule restrictions; - // only if that test pass do we forward the message on to the chat server to request - // to enter the room - case constcrc("ChatEnterRoom") : - case constcrc("ChatEnterRoomById") : { - NOT_NULL(m_client); + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage m(ri); + ri = message.begin(); - unsigned int sequence; - std::string roomName; + const uint32 messageType = m.getType(); - Archive::ReadIterator cri = message.begin(); + //Clients with a selected character get routed to a game server. + //@todo check for filtering out bad messages. + if (m_hasSelectedCharacter) { + // if it is a chat message, send it directly to the chat server + switch (messageType) { + case constcrc("ChatAddFriend") : + case constcrc("ChatAddModeratorToRoom") : + case constcrc("ChatBanAvatarFromRoom") : + case constcrc("ChatCreateRoom") : + case constcrc("ChatDeletePersistentMessage") : + case constcrc("ChatDeleteAllPersistentMessages") : + case constcrc("ChatDestroyRoom") : + case constcrc("ChatInstantMessageToCharacter") : + case constcrc("ChatInviteAvatarToRoom") : + case constcrc("ChatKickAvatarFromRoom") : + case constcrc("ChatRemoveAvatarFromRoom") : + case constcrc("ChatRemoveFriend") : + case constcrc("ChatRemoveModeratorFromRoom") : + case constcrc("ChatRequestPersistentMessage") : + case constcrc("ChatRequestRoomList") : + case constcrc("ChatSendToRoom") : + case constcrc("ChatUninviteFromRoom") : + case constcrc("ChatUnbanAvatarFromRoom") : + case constcrc("VerifyPlayerNameMessage") : { + DEBUG_REPORT_LOG(true, ("ConnServ: ClientConnection::onReceive()\n")); - if (messageType == constcrc("ChatEnterRoom")) { - ChatEnterRoom const cer(cri); - sequence = cer.getSequence(); - roomName = cer.getRoomName(); - } else { - ChatEnterRoomById const cerbi(cri); - sequence = cerbi.getSequence(); - roomName = cerbi.getRoomName(); - } - - if (m_client && m_client->getGameConnection()) { - if (m_pendingChatEnterRoomRequests.count(sequence) == 0) { - GenericValueTypeMessage, unsigned int> > const cervr( - "ChatEnterRoomValidationRequest", - std::make_pair( - std::make_pair(m_client->getNetworkId(), roomName), - sequence)); - - m_client->getGameConnection()->send(cervr, true); - - // queue up request until game server responds - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); - } - } else { - // send back response to client saying game server not available - - // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_NO_GAME_SERVER, 0, ChatAvatarId()); - send(fail, true); - } - - break; - } - // ChatQueryRoom needs to go to the game server to determine if the character is - // not allowed to query the room because of game rule restrictions; only if that - // test pass do we forward the message on to the chat server for completion - case constcrc("ChatQueryRoom") : { - NOT_NULL(m_client); - - Archive::ReadIterator cri = message.begin(); - ChatQueryRoom cqr(cri); - - if (m_client && m_client->getGameConnection()) { - if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) { - GenericValueTypeMessage, unsigned int> > const cqrvr( - "ChatQueryRoomValidationRequest", - std::make_pair( - std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), - cqr.getSequence())); - - m_client->getGameConnection()->send(cqrvr, true); - - // queue up request until game server responds - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); - } - } - break; - } - // ChatInviteGroupToRoom needs to go to the game server to get group information - case constcrc("ChatInviteGroupToRoom") : { - NOT_NULL(m_client); - if (m_client) { - if (m_client->getGameConnection()) { - static std::vector v; + NOT_NULL(m_client); + if (m_client) { + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } else { - // defer chat messages until a server is back online - Archive::ByteStream bs; - m.pack(bs); - m_client->deferChatMessage(bs); - } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - // ChatPersistentMessageToServer may need to be passed off to the game server for guild or citizens messages - case constcrc("ChatPersistentMessageToServer") : { - NOT_NULL(m_client); - if (m_client) { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - - Archive::ReadIterator cri = message.begin(); - ChatPersistentMessageToServer chat(cri); - std::string const &toName = chat.getToCharacterName().name; - if (!_stricmp(toName.c_str(), "guild") || !_strnicmp(toName.c_str(), "guild ", 6) || - !_stricmp(toName.c_str(), "citizens")) { - if (m_client->getGameConnection()) { - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } - } else { if (m_client->getChatConnection()) { - GameClientMessage gcm(v, true, ri); m_client->getChatConnection()->send(gcm, true); } else { // defer chat messages until a server is back online @@ -815,506 +618,564 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { m.pack(bs); m_client->deferChatMessage(bs); } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); + break; } - break; - } - // if it is a cs message, send it directly to the cs server - case constcrc("ConnectPlayerMessage") : - case constcrc("DisconnectPlayerMessage") : - case constcrc("CreateTicketMessage") : - case constcrc("AppendCommentMessage") : - case constcrc("CancelTicketMessage") : - case constcrc("GetTicketsMessage") : - case constcrc("GetCommentsMessage") : - case constcrc("SearchKnowledgeBaseMessage") : - case constcrc("GetArticleMessage") : - case constcrc("RequestCategoriesMessage") : - case constcrc("NewTicketActivityMessage") : { - NOT_NULL(m_client); - if (m_client) { - CustomerServiceConnection *customerServiceConnection = m_client->getCustomerServiceConnection(); + // ChatEnterRoom and ChatEnterRoomById needs to go to the game server to determine + // if the character is not allowed to enter the room because of game rule restrictions; + // only if that test pass do we forward the message on to the chat server to request + // to enter the room + case constcrc("ChatEnterRoom") : + case constcrc("ChatEnterRoomById") : { + NOT_NULL(m_client); - //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); + unsigned int sequence; + std::string roomName; - if (customerServiceConnection != nullptr) { - static std::vector v; + Archive::ReadIterator cri = message.begin(); + + if (messageType == constcrc("ChatEnterRoom")) { + ChatEnterRoom const cer(cri); + sequence = cer.getSequence(); + roomName = cer.getRoomName(); + } else { + ChatEnterRoomById const cerbi(cri); + sequence = cerbi.getSequence(); + roomName = cerbi.getRoomName(); + } + + if (m_client && m_client->getGameConnection()) { + if (m_pendingChatEnterRoomRequests.count(sequence) == 0) { + GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned + int > > + const cervr( + "ChatEnterRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), roomName), sequence)); + + m_client->getGameConnection()->send(cervr, true); + + // queue up request until game server responds + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); + } + } else { + // send back response to client saying game server not available + + // the client only cares about sequence and result when it's a failure + ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_NO_GAME_SERVER, 0, ChatAvatarId()); + send(fail, true); + } + + break; + } + // ChatQueryRoom needs to go to the game server to determine if the character is + // not allowed to query the room because of game rule restrictions; only if that + // test pass do we forward the message on to the chat server for completion + case constcrc("ChatQueryRoom") : { + NOT_NULL(m_client); + + Archive::ReadIterator cri = message.begin(); + ChatQueryRoom cqr(cri); + + if (m_client && m_client->getGameConnection()) { + if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) { + GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned + int > > + const cqrvr( + "ChatQueryRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), cqr.getSequence())); + + m_client->getGameConnection()->send(cqrvr, true); + + // queue up request until game server responds + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); + } + } + break; + } + // ChatInviteGroupToRoom needs to go to the game server to get group information + case constcrc("ChatInviteGroupToRoom") : { + NOT_NULL(m_client); + if (m_client) { + if (m_client->getGameConnection()) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); + } else { + // defer chat messages until a server is back online + Archive::ByteStream bs; + m.pack(bs); + m_client->deferChatMessage(bs); + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + // ChatPersistentMessageToServer may need to be passed off to the game server for guild or citizens messages + case constcrc("ChatPersistentMessageToServer") : { + NOT_NULL(m_client); + if (m_client) { + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); - // TODO: this shit could be made into a template - switch (messageType) { - case constcrc("ConnectPlayerMessage") : { - ConnectPlayerMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("CreateTicketMessage") : { - CreateTicketMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("AppendCommentMessage") : { - AppendCommentMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("CancelTicketMessage") : { - CancelTicketMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("GetTicketsMessage") : { - GetTicketsMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("NewTicketActivityMessage") : { - NewTicketActivityMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - default : { + Archive::ReadIterator cri = message.begin(); + ChatPersistentMessageToServer chat(cri); + std::string const &toName = chat.getToCharacterName().name; + if (!_stricmp(toName.c_str(), "guild") || !_strnicmp(toName.c_str(), "guild ", 6) || + !_stricmp(toName.c_str(), "citizens")) { + if (m_client->getGameConnection()) { GameClientMessage gcm(v, true, ri); - customerServiceConnection->send(gcm, true); - break; + m_client->getGameConnection()->send(gcm, true); } - } - } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - case constcrc("28afefcc187a11dc888b001") : // obfuscation for ClientInactivityMessage message - { - GenericValueTypeMessage msg(ri); - - if (m_hasBeenValidated && m_sessionValidated) { - // client went inactive - if (msg.getValue()) { - if (m_lastActiveTime > 0) { - // record the amount of active time - m_activePlayTimeDuration += static_cast(::time(nullptr) - - m_lastActiveTime); - - // tell Session to stop recording play time for the character - if (ConnectionServer::getSessionApiClient() && - ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", - ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); - ConnectionServer::getSessionApiClient()->stopPlay(*this); - } - - // client is no longer active; this needs to be set after the LOG() statement - // above because getCurrentActivePlayTimeDuration() uses m_lastActiveTime - m_lastActiveTime = 0; - - // update the play time info on the game server - sendPlayTimeInfoToGameServer(); - - // drop inactive character - if (ConfigConnectionServer::getDisconnectOnInactive()) { - LOG("ClientDisconnect", - ("Disconnecting %u because the player was inactive for too long.", getSUID())); - ConnectionServer::dropClient(this, "Client inactivity"); - disconnect(); - } else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && - ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { - LOG("ClientDisconnect", - ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); - ConnectionServer::dropClient(this, "Client inactivity (free trial)"); - disconnect(); - } - } - } - // client went active - else { - if (m_lastActiveTime == 0) { - // record the time client went active - m_lastActiveTime = ::time(nullptr); - - // tell Session to start recording play time for the character - if (ConnectionServer::getSessionApiClient() && - ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", - ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); - ConnectionServer::getSessionApiClient()->startPlay(*this); - } - - // update the play time info on the game server - sendPlayTimeInfoToGameServer(); - } - } - } - break; - } - default : { - //Forward on to Game Server - DEBUG_REPORT_LOG((!m_client || !m_client->getGameConnection()), - ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); - - if (m_client && m_client->getGameConnection()) { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } - - break; - } - } - } else { - switch (messageType) { - case constcrc("ClientIdMsg") : { - DEBUG_REPORT_LOG(true, ("Recieved ClientIdMsg\n")); - ClientIdMsg k(ri); - - handleClientIdMessage(k); - break; - } - case constcrc("SelectCharacter") : { - SelectCharacter s(ri); - DEBUG_REPORT_LOG(true, - ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); - - handleSelectCharacterMessage(s); - break; - } - case constcrc("ClientCreateCharacter") : { - if (m_hasBeenValidated && !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true - { - ClientCreateCharacter clientCreate(ri); - DEBUG_REPORT_LOG(true, - ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow( - clientCreate.getCharacterName()).c_str())); - LOG("TraceCharacterCreation", - ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", - getSUID(), - Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), - clientCreate.getTemplateName().c_str(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation().c_str(), - clientCreate.getHairTemplateName().c_str(), - clientCreate.getProfession().c_str(), - static_cast(clientCreate.getJedi()), - static_cast(clientCreate.getUseNewbieTutorial()), - clientCreate.getSkillTemplate().c_str(), - clientCreate.getWorkingSkill().c_str())); - - if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); - disconnect(); - } else if (clientCreate.getJedi() && !m_canCreateJediCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); - disconnect(); - } else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to create any characters", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); - disconnect(); - } else if (m_hasRequestedCharacterCreate) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); - LOG("ClientDisconnect", - ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); - disconnect(); - } else if (m_hasCreatedCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); - LOG("ClientDisconnect", - ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); - disconnect(); - } else if (clientCreate.getCharacterName().length() == 0) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The character's name is empty", getSUID())); - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); - disconnect(); - } else { - Unicode::String biography(clientCreate.getBiography()); - if (biography.length() > 1024) { - IGNORE_RETURN(biography.erase(1024)); - DEBUG_REPORT_LOG(true, ("Biography shortened to 1024 characters.\n")); - } - - if (m_isAdminAccount) { - ConnectionCreateCharacter connectionCreate( - m_suid, - clientCreate.getCharacterName(), - clientCreate.getTemplateName(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation(), - clientCreate.getAppearanceData(), - clientCreate.getHairTemplateName(), - clientCreate.getHairAppearanceData(), - clientCreate.getProfession(), - clientCreate.getJedi(), - biography, - clientCreate.getUseNewbieTutorial(), - clientCreate.getSkillTemplate(), - clientCreate.getWorkingSkill(), - m_isAdminAccount, - false, - m_featureBitsGame); - - ConnectionServer::sendToCentralProcess(connectionCreate); - LOG("TraceCharacterCreation", - ("%d character creation request sent to CentralServer", getSUID())); } else { - // for regular players, do one final check with the LoginServer - // to make sure the character can be created (i.e. that character - // limits have not been exceeded) - delete m_pendingCharacterCreate; - m_pendingCharacterCreate = new ConnectionCreateCharacter( - m_suid, - clientCreate.getCharacterName(), - clientCreate.getTemplateName(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation(), - clientCreate.getAppearanceData(), - clientCreate.getHairTemplateName(), - clientCreate.getHairAppearanceData(), - clientCreate.getProfession(), - clientCreate.getJedi(), - biography, - clientCreate.getUseNewbieTutorial(), - clientCreate.getSkillTemplate(), - clientCreate.getWorkingSkill(), - m_isAdminAccount, - false, - m_featureBitsGame); - - LOG("TraceCharacterCreation", - ("%d character creation request awaiting final verification from LoginServer", getSUID())); - - ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); - ConnectionServer::sendToCentralProcess(vcm); + if (m_client->getChatConnection()) { + GameClientMessage gcm(v, true, ri); + m_client->getChatConnection()->send(gcm, true); + } else { + // defer chat messages until a server is back online + Archive::ByteStream bs; + m.pack(bs); + m_client->deferChatMessage(bs); + } } - - m_hasRequestedCharacterCreate = true; + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); } + break; } - break; - } - case constcrc("ClientRandomNameRequest") : { - ClientRandomNameRequest clientRandomName(ri); + // if it is a cs message, send it directly to the cs server + case constcrc("ConnectPlayerMessage") : + case constcrc("DisconnectPlayerMessage") : + case constcrc("CreateTicketMessage") : + case constcrc("AppendCommentMessage") : + case constcrc("CancelTicketMessage") : + case constcrc("GetTicketsMessage") : + case constcrc("GetCommentsMessage") : + case constcrc("SearchKnowledgeBaseMessage") : + case constcrc("GetArticleMessage") : + case constcrc("RequestCategoriesMessage") : + case constcrc("NewTicketActivityMessage") : { + NOT_NULL(m_client); + if (m_client) { + CustomerServiceConnection *customerServiceConnection = m_client->getCustomerServiceConnection(); - RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); - ConnectionServer::sendToCentralProcess(randomNameRequest); - LOG("TraceCharacterCreation", - ("%d requested a random name. Request sent to CentralServer", getSUID())); - break; - } - case constcrc("ClientVerifyAndLockNameRequest") : { - ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); + //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); - VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, - clientVerifyAndLockNameRequest.getTemplateName(), - clientVerifyAndLockNameRequest.getCharacterName(), - m_featureBitsGame); - ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); - LOG("TraceCharacterCreation", - ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow( - verifyAndLockNameRequest.getCharacterName()).c_str())); - break; + if (customerServiceConnection != nullptr) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + + // TODO: this shit could be made into a template + switch (messageType) { + case constcrc("ConnectPlayerMessage") : { + ConnectPlayerMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("CreateTicketMessage") : { + CreateTicketMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("AppendCommentMessage") : { + AppendCommentMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("CancelTicketMessage") : { + CancelTicketMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("GetTicketsMessage") : { + GetTicketsMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("NewTicketActivityMessage") : { + NewTicketActivityMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + default : { + GameClientMessage gcm(v, true, ri); + customerServiceConnection->send(gcm, true); + break; + } + } + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + case constcrc("28afefcc187a11dc888b001") : // obfuscation for ClientInactivityMessage message + { + GenericValueTypeMessage msg(ri); + + if (m_hasBeenValidated && m_sessionValidated) { + // client went inactive + if (msg.getValue()) { + if (m_lastActiveTime > 0) { + // record the amount of active time + m_activePlayTimeDuration += static_cast(::time(nullptr) - + m_lastActiveTime); + + // tell Session to stop recording play time for the character + if (ConnectionServer::getSessionApiClient() && + ConfigConnectionServer::getSessionRecordPlayTime()) { + LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + ConnectionServer::getSessionApiClient()->stopPlay(*this); + } + + // client is no longer active; this needs to be set after the LOG() statement + // above because getCurrentActivePlayTimeDuration() uses m_lastActiveTime + m_lastActiveTime = 0; + + // update the play time info on the game server + sendPlayTimeInfoToGameServer(); + + // drop inactive character + if (ConfigConnectionServer::getDisconnectOnInactive()) { + LOG("ClientDisconnect", ("Disconnecting %u because the player was inactive for too long.", getSUID())); + ConnectionServer::dropClient(this, "Client inactivity"); + disconnect(); + } else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && + ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { + LOG("ClientDisconnect", ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); + ConnectionServer::dropClient(this, "Client inactivity (free trial)"); + disconnect(); + } + } + } + // client went active + else { + if (m_lastActiveTime == 0) { + // record the time client went active + m_lastActiveTime = ::time(nullptr); + + // tell Session to start recording play time for the character + if (ConnectionServer::getSessionApiClient() && + ConfigConnectionServer::getSessionRecordPlayTime()) { + LOG("CustomerService", ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); + ConnectionServer::getSessionApiClient()->startPlay(*this); + } + + // update the play time info on the game server + sendPlayTimeInfoToGameServer(); + } + } + } + break; + } + default : { + //Forward on to Game Server + DEBUG_REPORT_LOG((!m_client || + !m_client->getGameConnection()), ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); + + if (m_client && m_client->getGameConnection()) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); + } + + break; + } } - case constcrc("LagRequest") : { - // TODO: why is this commented out? - // handleLagRequest(); - break; + } else { + switch (messageType) { + case constcrc("ClientIdMsg") : { + DEBUG_REPORT_LOG(true, ("Recieved ClientIdMsg\n")); + ClientIdMsg k(ri); + + handleClientIdMessage(k); + break; + } + case constcrc("SelectCharacter") : { + SelectCharacter s(ri); + DEBUG_REPORT_LOG(true, ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); + + handleSelectCharacterMessage(s); + break; + } + case constcrc("ClientCreateCharacter") : { + if (m_hasBeenValidated && + !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true + { + ClientCreateCharacter clientCreate(ri); + DEBUG_REPORT_LOG(true, ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str())); + LOG("TraceCharacterCreation", ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", getSUID(), Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), clientCreate.getTemplateName().c_str(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation().c_str(), clientCreate.getHairTemplateName().c_str(), clientCreate.getProfession().c_str(), static_cast(clientCreate.getJedi()), static_cast(clientCreate.getUseNewbieTutorial()), clientCreate.getSkillTemplate().c_str(), clientCreate.getWorkingSkill().c_str())); + + if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial + LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + disconnect(); + } else if (clientCreate.getJedi() && !m_canCreateJediCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + disconnect(); + } else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + disconnect(); + } else if (m_hasRequestedCharacterCreate) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); + disconnect(); + } else if (m_hasCreatedCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); + disconnect(); + } else if (clientCreate.getCharacterName().length() == 0) { + LOG("TraceCharacterCreation", ("%d failed character creation. The character's name is empty", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); + disconnect(); + } else { + Unicode::String biography(clientCreate.getBiography()); + if (biography.length() > 1024) { + IGNORE_RETURN(biography.erase(1024)); + DEBUG_REPORT_LOG(true, ("Biography shortened to 1024 characters.\n")); + } + + if (m_isAdminAccount) { + ConnectionCreateCharacter connectionCreate(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); + + ConnectionServer::sendToCentralProcess(connectionCreate); + LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); + } else { + // for regular players, do one final check with the LoginServer + // to make sure the character can be created (i.e. that character + // limits have not been exceeded) + delete m_pendingCharacterCreate; + m_pendingCharacterCreate = new ConnectionCreateCharacter(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); + + LOG("TraceCharacterCreation", ("%d character creation request awaiting final verification from LoginServer", getSUID())); + + ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); + ConnectionServer::sendToCentralProcess(vcm); + } + + m_hasRequestedCharacterCreate = true; + } + } + break; + } + case constcrc("ClientRandomNameRequest") : { + ClientRandomNameRequest clientRandomName(ri); + + RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); + ConnectionServer::sendToCentralProcess(randomNameRequest); + LOG("TraceCharacterCreation", ("%d requested a random name. Request sent to CentralServer", getSUID())); + break; + } + case constcrc("ClientVerifyAndLockNameRequest") : { + ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); + + VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, clientVerifyAndLockNameRequest.getTemplateName(), clientVerifyAndLockNameRequest.getCharacterName(), m_featureBitsGame); + ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); + LOG("TraceCharacterCreation", ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow(verifyAndLockNameRequest.getCharacterName()).c_str())); + break; + } + case constcrc("LagRequest") : { + // TODO: why is this commented out? + // handleLagRequest(); + break; + } } } + } catch (const Archive::ReadException &readException) { + WARNING(true, ("Archive read error (%s) from client. Disconnecting client", readException.what())); + LOG("ClientDisconnect", ("Archive read error (%s) from client. Disconnecting client", readException.what())); + disconnect(); } } - catch (const Archive::ReadException &readException) { - WARNING(true, ("Archive read error (%s) from client. Disconnecting client", readException.what())); - LOG("ClientDisconnect", ("Archive read error (%s) from client. Disconnecting client", readException.what())); - disconnect(); - } -} //----------------------------------------------------------------------- -void ClientConnection::handleLagRequest() { - // client is requesting a lag ping (reliable trace) - GameNetworkMessage response("ConnectionServerLagResponse"); - send(response, true); + void ClientConnection::handleLagRequest() { + // client is requesting a lag ping (reliable trace) + GameNetworkMessage response("ConnectionServerLagResponse"); + send(response, true); + + if (m_hasSelectedCharacter && m_client && m_client->getGameConnection()) { + // send to game server + GameNetworkMessage request("LagRequest"); + std::vector v; + v.push_back(m_characterId); + GameClientMessage gcm(v, true, request); + m_client->getGameConnection()->send(gcm, true); + } else { + // send game response immediately + GameNetworkMessage gameResponse("GameServerLagResponse"); + send(gameResponse, true); + } - if (m_hasSelectedCharacter && m_client && m_client->getGameConnection()) { - // send to game server - GameNetworkMessage request("LagRequest"); - std::vector v; - v.push_back(m_characterId); - GameClientMessage gcm(v, true, request); - m_client->getGameConnection()->send(gcm, true); - } else { - // send game response immediately - GameNetworkMessage gameResponse("GameServerLagResponse"); - send(gameResponse, true); } -} - //----------------------------------------------------------------------- /** character has selected a character and calls this function * to associate the connection with the new client they created with that * character. We no longer need the character map. */ -void ClientConnection::setClient(Client *newClient) { - //This fatal is here to try to catch the reconnect bug. - WARNING_STRICT_FATAL(m_client, - ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); - // jrandall - I've removed the fatal because it is blocking some people from getting some work - // done. I'm on a high priority fix at the moment. If this warning starts appearing, - // set a break point or something. - //DEBUG_FATAL(client, ("Attempting to set the client on a connection that already has one.\n")); - m_client = newClient; + void ClientConnection::setClient(Client *newClient) { + //This fatal is here to try to catch the reconnect bug. + WARNING_STRICT_FATAL(m_client, ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); + // jrandall - I've removed the fatal because it is blocking some people from getting some work + // done. I'm on a high priority fix at the moment. If this warning starts appearing, + // set a break point or something. + //DEBUG_FATAL(client, ("Attempting to set the client on a connection that already has one.\n")); + m_client = newClient; - // todo put this in: characterMap.clear(); -} - -//----------------------------------------------------------------------- - -void ClientConnection::send(const GameNetworkMessage &message, const bool reliable) { - m_sendLastTimeMs = Clock::timeMs(); - - - if (sm_outgoingBytesMap_Worktime == 0) - sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; - else if ((m_sendLastTimeMs - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map::iterator iter; - for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { - iter->second = 0; - } - sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; - } - sm_outgoingBytesMap_Working[message.getCmdName()] += message.getByteStream().getSize(); - - - ServerConnection::send(message, reliable); -} - -//----------------------------------------------------------------------- - -std::map &ClientConnection::getPacketBytesPerMinStats() { - uint32 now = Clock::timeMs(); - if (sm_outgoingBytesMap_Worktime == 0) - sm_outgoingBytesMap_Worktime = now; - else if ((now - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map::iterator iter; - for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { - iter->second = 0; - } - sm_outgoingBytesMap_Worktime = now; + // todo put this in: characterMap.clear(); } - return sm_outgoingBytesMap_Stats; -} +//----------------------------------------------------------------------- + + void ClientConnection::send(const GameNetworkMessage &message, const bool reliable) { + m_sendLastTimeMs = Clock::timeMs(); + + + if (sm_outgoingBytesMap_Worktime == 0) { + sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; + } else if ((m_sendLastTimeMs - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds + { + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; + } + sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; + } + sm_outgoingBytesMap_Working[message.getCmdName()] += message.getByteStream().getSize(); + + + ServerConnection::send(message, reliable); + } //----------------------------------------------------------------------- -void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) { - std::map::iterator iterFind = m_pendingChatEnterRoomRequests.find(sequence); - if (iterFind != m_pendingChatEnterRoomRequests.end()) { - if (result == CHATRESULT_SUCCESS) { - if (m_client && m_client->getChatConnection()) { - // game server says it's ok to enter the chat room, - // so forward the request on to the chat server - m_client->getChatConnection()->send(*(iterFind->second), true); + std::map &ClientConnection::getPacketBytesPerMinStats() { + uint32 now = Clock::timeMs(); + if (sm_outgoingBytesMap_Worktime == 0) { + sm_outgoingBytesMap_Worktime = now; + } else if ((now - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds + { + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; + } + sm_outgoingBytesMap_Worktime = now; + } + + return sm_outgoingBytesMap_Stats; + } + +//----------------------------------------------------------------------- + + void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) { + std::map < unsigned + long, GameClientMessage * > ::iterator + iterFind = m_pendingChatEnterRoomRequests.find(sequence); + if (iterFind != m_pendingChatEnterRoomRequests.end()) { + if (result == CHATRESULT_SUCCESS) { + if (m_client && m_client->getChatConnection()) { + // game server says it's ok to enter the chat room, + // so forward the request on to the chat server + m_client->getChatConnection()->send(*(iterFind->second), true); + } else { + // send back response to client saying chat server not available + + // the client only cares about sequence and result when it's a failure + ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_CHAT_SERVER_UNAVAILABLE, 0, ChatAvatarId()); + send(fail, true); + } } else { - // send back response to client saying chat server not available + // send back response to client saying game server denied enter room request // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_CHAT_SERVER_UNAVAILABLE, 0, ChatAvatarId()); + ChatOnEnteredRoom fail(sequence, result, 0, ChatAvatarId()); send(fail, true); } - } else { - // send back response to client saying game server denied enter room request - // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, result, 0, ChatAvatarId()); - send(fail, true); + delete iterFind->second; + m_pendingChatEnterRoomRequests.erase(iterFind); } - - delete iterFind->second; - m_pendingChatEnterRoomRequests.erase(iterFind); } -} //----------------------------------------------------------------------- -void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) { - std::map::iterator iterFind = m_pendingChatQueryRoomRequests.find(sequence); - if (iterFind != m_pendingChatQueryRoomRequests.end()) { - if (success) { - if (m_client && m_client->getChatConnection()) { - // game server says it's ok to query the chat room, - // so forward the request on to the chat server - m_client->getChatConnection()->send(*(iterFind->second), true); + void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) { + std::map < unsigned + long, GameClientMessage * > ::iterator + iterFind = m_pendingChatQueryRoomRequests.find(sequence); + if (iterFind != m_pendingChatQueryRoomRequests.end()) { + if (success) { + if (m_client && m_client->getChatConnection()) { + // game server says it's ok to query the chat room, + // so forward the request on to the chat server + m_client->getChatConnection()->send(*(iterFind->second), true); + } } - } - delete iterFind->second; - m_pendingChatQueryRoomRequests.erase(iterFind); + delete iterFind->second; + m_pendingChatQueryRoomRequests.erase(iterFind); + } } -} //----------------------------------------------------------------------- -void ClientConnection::sendByteStream(const Archive::ByteStream &bs, bool reliable) { - Connection::send(bs, reliable); -} + void ClientConnection::sendByteStream(const Archive::ByteStream &bs, bool reliable) { + Connection::send(bs, reliable); + } //----------------------------------------------------------------------- /** * Send the client to an arbitratry game server based on the current scene */ -const bool ClientConnection::sendToGameServer() { - GameConnection *c = const_cast(ConnectionServer::getGameConnection(m_targetScene)); - return sendToGameServer(c); -} + const bool ClientConnection::sendToGameServer() { + GameConnection *c = const_cast(ConnectionServer::getGameConnection(m_targetScene)); + return sendToGameServer(c); + } // ---------------------------------------------------------------------- @@ -1322,31 +1183,27 @@ const bool ClientConnection::sendToGameServer() { * Send the client to a particular game server, sepcified by process id. */ -const bool ClientConnection::sendToGameServer(uint32 gameServerId) { - GameConnection *c = const_cast(ConnectionServer::getGameConnection(gameServerId)); - return sendToGameServer(c); -} + const bool ClientConnection::sendToGameServer(uint32 gameServerId) { + GameConnection *c = const_cast(ConnectionServer::getGameConnection(gameServerId)); + return sendToGameServer(c); + } // ---------------------------------------------------------------------- -bool ClientConnection::sendToGameServer(GameConnection *c) { - bool result = false; + bool ClientConnection::sendToGameServer(GameConnection *c) { + bool result = false; - if (c && m_hasSelectedCharacter && m_hasBeenValidated) { - //create a new client - ConnectionServer::addNewClient(this, - m_characterId, - c, - m_targetScene, - m_sendToStarport); + if (c && m_hasSelectedCharacter && m_hasBeenValidated) { + //create a new client + ConnectionServer::addNewClient(this, m_characterId, c, m_targetScene, m_sendToStarport); - LoggedInMessage m(m_suid); - ConnectionServer::sendToCentralProcess(m); - result = true; - m_hasBeenSentToGameServer = true; + LoggedInMessage m(m_suid); + ConnectionServer::sendToCentralProcess(m); + result = true; + m_hasBeenSentToGameServer = true; + } + return result; } - return result; -} //----------------------------------------------------------------------- @@ -1355,250 +1212,230 @@ bool ClientConnection::sendToGameServer(GameConnection *c) { * Now we know whether the character is valid and where in the world it * is located. */ -void ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, - const NetworkId &container, const std::string &scene, - const Vector &coordinates) { - if (!m_validatingCharacter) { - LOG("TraceCharacterSelection", - ("%d received a validation response, but is not in the process of validation", getSUID())); - DEBUG_REPORT_LOG(true, ("Got unexpected onCharacterValidated() for account %lu.\n", getSUID())); - return; - } - m_validatingCharacter = false; + void + ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, const NetworkId &container, const std::string &scene, const Vector &coordinates) { + if (!m_validatingCharacter) { + LOG("TraceCharacterSelection", ("%d received a validation response, but is not in the process of validation", getSUID())); + DEBUG_REPORT_LOG(true, ("Got unexpected onCharacterValidated() for account %lu.\n", getSUID())); + return; + } + m_validatingCharacter = false; - if (isValid) { - LOG("TraceCharacterSelection", - ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - LOG("CustomerService", - ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount( - this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - m_targetScene = scene; - m_targetCoordinates = coordinates; - m_characterId = character; - m_containerId = container; - m_characterName = characterName; + if (isValid) { + LOG("TraceCharacterSelection", ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + LOG("CustomerService", ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount(this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + m_targetScene = scene; + m_targetCoordinates = coordinates; + m_characterId = character; + m_containerId = container; + m_characterName = characterName; - m_hasSelectedCharacter = true; + m_hasSelectedCharacter = true; - // ask CentralServer to suggest a game server for this character - // (Central will forward the request to a Planet Server) + // ask CentralServer to suggest a game server for this character + // (Central will forward the request to a Planet Server) - RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, - m_targetCoordinates, false); - if (ConnectionServer::getCentralConnection()) - ConnectionServer::getCentralConnection()->send(requestmsg, true); - else { - LOG("ClientDisconnect", - ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); - ErrorMessage err("Validation Failed", - "The connection to the central server is down. Please try again later."); + RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, m_targetCoordinates, false); + if (ConnectionServer::getCentralConnection()) { + ConnectionServer::getCentralConnection()->send(requestmsg, true); + } else { + LOG("ClientDisconnect", ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); + ErrorMessage err("Validation Failed", "The connection to the central server is down. Please try again later."); + send(err, true); + + disconnect(); + } + } else { + LOG("TraceCharacterSelection", ("%d validation failed, disconnecting client", getSUID())); + ErrorMessage err("Validation Failed", "Your character was denied login by the database."); send(err, true); + LOG("ClientDisconnect", ("Denying login for account %u.\n", getSUID())); disconnect(); } - } else { - LOG("TraceCharacterSelection", ("%d validation failed, disconnecting client", getSUID())); - ErrorMessage err("Validation Failed", "Your character was denied login by the database."); - send(err, true); - - LOG("ClientDisconnect", ("Denying login for account %u.\n", getSUID())); - disconnect(); } -} //------------------------------------------------------------------------------------------ -void ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, - const uint32 gameFeatures, const uint32 subscriptionFeatures, - unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, - unsigned int entitlementTotalTimeSinceLastLogin, - unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { - UNREF(id); - m_sessionValidated = true; - m_suid = suid; - m_accountName = username; - m_featureBitsGame = gameFeatures; - m_featureBitsSubscription = subscriptionFeatures; - m_isSecure = secure; - m_entitlementTotalTime = entitlementTotalTime; - m_entitlementEntitledTime = entitlementEntitledTime; - m_entitlementTotalTimeSinceLastLogin = entitlementTotalTimeSinceLastLogin; - m_entitlementEntitledTimeSinceLastLogin = entitlementEntitledTimeSinceLastLogin; - m_buddyPoints = buddyPoints; + void + ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, const uint32 gameFeatures, const uint32 subscriptionFeatures, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { + UNREF(id); + m_sessionValidated = true; + m_suid = suid; + m_accountName = username; + m_featureBitsGame = gameFeatures; + m_featureBitsSubscription = subscriptionFeatures; + m_isSecure = secure; + m_entitlementTotalTime = entitlementTotalTime; + m_entitlementEntitledTime = entitlementEntitledTime; + m_entitlementTotalTimeSinceLastLogin = entitlementTotalTimeSinceLastLogin; + m_entitlementEntitledTimeSinceLastLogin = entitlementEntitledTimeSinceLastLogin; + m_buddyPoints = buddyPoints; - if (id) - m_sessionId = id; + if (id) { + m_sessionId = id; + } - if (m_requestedSuid != 0 && suid != m_requestedSuid) { - //verify internal, secure, is on the god list - bool loginOK = false; - if (!secure) - LOG("CustomerService", - ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); - else { - if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); - else { - int adminLevel = 0; - if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || 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, m_requestedSuid)); - else { - LOG("CustomerService", - ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); - DEBUG_REPORT_LOG(true, - ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); - m_suid = m_requestedSuid; - m_usingAdminLogin = true; - loginOK = true; + if (m_requestedSuid != 0 && suid != m_requestedSuid) { + //verify internal, secure, is on the god list + bool loginOK = false; + if (!secure) { + LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); + } else { + if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); + } else { + int adminLevel = 0; + if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || + 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, m_requestedSuid)); + } else { + LOG("CustomerService", ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); + DEBUG_REPORT_LOG(true, ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); + m_suid = m_requestedSuid; + m_usingAdminLogin = true; + loginOK = true; + } } } + if (!loginOK) { + disconnect(); + return; + } } - if (!loginOK) { - disconnect(); - return; + + m_featureBitsGame &= ~ConfigConnectionServer::getDisabledFeatureBits(); + + //Configoption to enable JTL features for beta players so that our code can pretend everything uses the JTL Retail bit + if (ConfigConnectionServer::getSetJtlRetailIfBetaIsSet()) { + if (ClientGameFeature::SpaceExpansionBeta & m_featureBitsGame) { + m_featureBitsGame |= ClientGameFeature::SpaceExpansionRetail; + } + } + + //Configoption to enable Obiwan features for beta players so that our code can pretend everything uses the Obiwan Retail bit + if (ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet()) { + if (ClientGameFeature::TrialsOfObiwanBeta & m_featureBitsGame) { + //-- add retail bit only if player does not have the preorder bit + if ((m_featureBitsGame & ClientGameFeature::TrialsOfObiwanPreorder) == 0) { + m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; + } + } else { + // Clear bits from players who might have them for real, but aren't in the beta + m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanRetail; + m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanPreorder; + } + } + + //-- Obiwan Preorders get the Retail bit as well... All rewards etc... + if (ClientGameFeature::TrialsOfObiwanPreorder & m_featureBitsGame) { + m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; + } + + // Restrictions for "new free trial" account + if (((m_featureBitsSubscription & ClientSubscriptionFeature::FreeTrial2) != 0) && + ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { + // "new free trial" account don't have access to RoW until they convert + m_featureBitsGame &= ~ClientGameFeature::Episode3ExpansionRetail; + m_featureBitsGame &= ~ClientGameFeature::Episode3PreorderDownload; + + // ClientGameFeature::FreeTrial2 indicates this is a converted "new free trial" + // account, and since this account hasn't converted yet, we remove this bit + m_featureBitsGame &= ~ClientGameFeature::FreeTrial2; + } + + // Clear feature bits that only apply if the account is paying (i.e. the sub base bit is set) + if ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0) { + m_featureBitsGame &= ~ClientGameFeature::HousePackupReward; + m_featureBitsGame &= ~ClientGameFeature::BuddyProgramReward; + } + + ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); + ConnectionServer::sendToCentralProcess(vcm); + ConnectionServer::addConnectedClient(m_suid, this); + + uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); + if (requiredSubscriptionBits != 0) { + if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) { + LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); + LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); + disconnect(); + return; + } + } + + uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); + if (requiredGameBits != 0) { + if ((gameFeatures & requiredGameBits) != requiredGameBits) { + LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); + LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); + disconnect(); + return; + } + } + + // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time + GenericValueTypeMessage < std::pair < std::pair < unsigned + long, unsigned + long > , std::pair < int, int32 > > > + const msgFeatureBits( + "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), static_cast(::time(nullptr))))); + send(msgFeatureBits, true); + + std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); + std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); + + LOG("CustomerService", ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount(this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); + + // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account + // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account + if (!m_usingAdminLogin && !m_isSecure) { + GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", std::make_pair(m_suid, m_sessionId)); + ConnectionServer::sendToCentralProcess(dropDuplicateConnections); } } - m_featureBitsGame &= ~ConfigConnectionServer::getDisabledFeatureBits(); - - //Configoption to enable JTL features for beta players so that our code can pretend everything uses the JTL Retail bit - if (ConfigConnectionServer::getSetJtlRetailIfBetaIsSet()) { - if (ClientGameFeature::SpaceExpansionBeta & m_featureBitsGame) { - m_featureBitsGame |= ClientGameFeature::SpaceExpansionRetail; - } - } - - //Configoption to enable Obiwan features for beta players so that our code can pretend everything uses the Obiwan Retail bit - if (ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet()) { - if (ClientGameFeature::TrialsOfObiwanBeta & m_featureBitsGame) { - //-- add retail bit only if player does not have the preorder bit - if ((m_featureBitsGame & ClientGameFeature::TrialsOfObiwanPreorder) == 0) - m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; - } else { - // Clear bits from players who might have them for real, but aren't in the beta - m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanRetail; - m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanPreorder; - } - } - - //-- Obiwan Preorders get the Retail bit as well... All rewards etc... - if (ClientGameFeature::TrialsOfObiwanPreorder & m_featureBitsGame) { - m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; - } - - // Restrictions for "new free trial" account - if (((m_featureBitsSubscription & ClientSubscriptionFeature::FreeTrial2) != 0) - && ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { - // "new free trial" account don't have access to RoW until they convert - m_featureBitsGame &= ~ClientGameFeature::Episode3ExpansionRetail; - m_featureBitsGame &= ~ClientGameFeature::Episode3PreorderDownload; - - // ClientGameFeature::FreeTrial2 indicates this is a converted "new free trial" - // account, and since this account hasn't converted yet, we remove this bit - m_featureBitsGame &= ~ClientGameFeature::FreeTrial2; - } - - // Clear feature bits that only apply if the account is paying (i.e. the sub base bit is set) - if ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0) { - m_featureBitsGame &= ~ClientGameFeature::HousePackupReward; - m_featureBitsGame &= ~ClientGameFeature::BuddyProgramReward; - } - - ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); - ConnectionServer::sendToCentralProcess(vcm); - ConnectionServer::addConnectedClient(m_suid, this); - - uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); - if (requiredSubscriptionBits != 0) { - if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) { - LOG("ClientDisconnect", - ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); - LOG("CustomerService", - ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); - disconnect(); - return; - } - } - - uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); - if (requiredGameBits != 0) { - if ((gameFeatures & requiredGameBits) != requiredGameBits) { - LOG("ClientDisconnect", - ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); - LOG("CustomerService", - ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); - disconnect(); - return; - } - } - - // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time - GenericValueTypeMessage, std::pair > > const msgFeatureBits( - "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), - std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), - static_cast(::time(nullptr))))); - send(msgFeatureBits, true); - - std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); - std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); - - LOG("CustomerService", - ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount( - this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); - - // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account - // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account - if (!m_usingAdminLogin && !m_isSecure) { - GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", - std::make_pair(m_suid, - m_sessionId)); - ConnectionServer::sendToCentralProcess(dropDuplicateConnections); - } -} - //----------------------------------------------------------------------- -std::string ClientConnection::describeAccount(const ClientConnection *c) { - std::string result = ""; - if (c) { - char idbuf[512] = {"\0"}; - const std::string &sessionId = c->getSessionId(); - if (sessionId.empty()) { - snprintf(idbuf, sizeof(idbuf), " (%lu)", c->m_suid); - } else { - snprintf(idbuf, sizeof(idbuf), " (%lu, %s)", c->m_suid, sessionId.c_str()); + std::string ClientConnection::describeAccount(const ClientConnection *c) { + std::string result = ""; + if (c) { + char idbuf[512] = {"\0"}; + const std::string &sessionId = c->getSessionId(); + if (sessionId.empty()) { + snprintf(idbuf, sizeof(idbuf), " (%lu)", c->m_suid); + } else { + snprintf(idbuf, sizeof(idbuf), " (%lu, %s)", c->m_suid, sessionId.c_str()); + } + + result = c->m_accountName; + result += idbuf; } - - result = c->m_accountName; - result += idbuf; + return result; } - return result; -} // ---------------------------------------------------------------------- -std::vector > const &ClientConnection::getConsumedRewardEvents() const { - return m_consumedRewardEvents; -} + std::vector > const &ClientConnection::getConsumedRewardEvents() const { + return m_consumedRewardEvents; + } // ---------------------------------------------------------------------- -std::vector > const &ClientConnection::getClaimedRewardItems() const { - return m_claimedRewardItems; -} + std::vector > const &ClientConnection::getClaimedRewardItems() const { + return m_claimedRewardItems; + } // ---------------------------------------------------------------------- -bool ClientConnection::isUsingAdminLogin() const { - return m_usingAdminLogin; -} + bool ClientConnection::isUsingAdminLogin() const { + return m_usingAdminLogin; + } // ---------------------------------------------------------------------- -int ClientConnection::getBuddyPoints() const { - return m_buddyPoints; -} + int ClientConnection::getBuddyPoints() const { + return m_buddyPoints; + } // ====================================================================== From d9ee0d8950882997170a7e82c14e8ca4c6c44cf8 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 02:33:55 -0600 Subject: [PATCH 14/55] is it a length issue? --- .../LoginServer/src/shared/LoginServer.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index afa12138..2082af76 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -1416,20 +1416,17 @@ void LoginServer::onValidateClient(StationId suid, const std::string & username, if (ConfigLoginServer::getDoConsumption() || ConfigLoginServer::getDoSessionLogin()) { - std::string const strSessionKey(sessionKey); - size_t sessSize = sizeof(strSessionKey.c_str()); - // pass the sessionkey - len = sessSize + sizeof(StationId); - memcpy(keyBufferPointer, sessionKey, sessSize); - keyBufferPointer += len; - memcpy(keyBufferPointer, &suid, sizeof(StationId)); + len = apiSessionIdWidth + sizeof(StationId); + memcpy(keyBufferPointer, sessionKey, apiSessionIdWidth); + keyBufferPointer += apiSessionIdWidth; // if LoginServer did session login, send the session key back to the client; // the client normally gets the session key from the LaunchPad, but in this mode // where the LoginServer does the session login, it will get it from the LoginServer if (ConfigLoginServer::getDoSessionLogin()) { + std::string const strSessionKey(sessionKey, apiSessionIdWidth); GenericValueTypeMessage const msg("SetSessionKey", strSessionKey); conn->send(msg, true); } From b39fcbed73a1907c1d26d3ce9233d677afc75367 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 02:40:16 -0600 Subject: [PATCH 15/55] probably helps if we actually set this --- .../src/shared/ClientConnection.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 983fc0f7..75098f35 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -283,17 +283,20 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { Archive::ByteStream t(msg.getToken(), msg.getTokenSize()); Archive::ReadIterator ri(t); KeyShare::Token token(ri); + char sessionId[apiSessionIdWidth]; - result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + if (!ConfigConnectionServer::getValidateStationKey()) { + // get SUID from token + result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); + } else { + result = ConnectionServer::decryptToken(token, sessionId, m_requestedSuid); + } - StationId apiSuid = 0; static const std::string sessURL(ConfigConnectionServer::getSessionURL()); - if (result) { if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { bool cont = false; - - printf("\nAttempting to test our session...\n"); + StationId apiSuid = 0; webAPI api(sessURL); std::string clientIP = getRemoteAddress(); From 9da25e111cc53c2e47fd71166ba6e28f8ea9704a Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 02:41:44 -0600 Subject: [PATCH 16/55] helps when you have the proper number of brackets --- .../src/shared/ClientConnection.cpp | 1773 ++++++++--------- 1 file changed, 886 insertions(+), 887 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 75098f35..6b223ef4 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -375,245 +375,376 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { } onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, ConfigConnectionServer::getDefaultGameFeatures(), ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, ConfigConnectionServer::getFakeBuddyPoints()); - } else { - // They sent us a token that was no good -- either a hack attempt, or - // possibly it was just too old. - LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); + } + } else { + // They sent us a token that was no good -- either a hack attempt, or + // possibly it was just too old. + LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); + disconnect(); + } +} + +//----------------------------------------------------------------------- + +void +ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems) { + //@todo start session with station. + //@todo add more permissions to this message as needed. + + // resume character creation + if (m_pendingCharacterCreate) { + if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial + LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); disconnect(); - } - } - -//----------------------------------------------------------------------- - - void - ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems) { - //@todo start session with station. - //@todo add more permissions to this message as needed. - - // resume character creation - if (m_pendingCharacterCreate) { - if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); - disconnect(); - } else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); - disconnect(); - } else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); - disconnect(); - } else { - ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); - LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); - - m_hasRequestedCharacterCreate = true; - } - - delete m_pendingCharacterCreate; - m_pendingCharacterCreate = nullptr; - - return; - } - - // Save lists of claimed rewards, which won't be used again until later in the login sequence - m_consumedRewardEvents = consumedRewardEvents; - m_claimedRewardItems = claimedRewardItems; - - - 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 - { - canLogin = true; - canCreateRegularCharacter = true; - canSkipTutorial = true; - m_isAdminAccount = true; - } - - ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial); - send(c, true); - - DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID())); - DEBUG_REPORT_LOG(canLogin, ("\tcanLogin\n")); - DEBUG_REPORT_LOG(canCreateRegularCharacter, ("\tcanCreateRegularCharacter\n")); - DEBUG_REPORT_LOG(canCreateJediCharacter, ("\tcanCreateJediCharacter\n")); - DEBUG_REPORT_LOG(canSkipTutorial, ("\tcanSkipTutorial\n")); - DEBUG_REPORT_LOG(!(canLogin || canCreateRegularCharacter || canCreateJediCharacter || - canSkipTutorial), ("\tnone\n")); - - if (canLogin) { - m_hasBeenValidated = true; - m_canCreateRegularCharacter = canCreateRegularCharacter; - m_canCreateJediCharacter = canCreateJediCharacter; - m_canSkipTutorial = canSkipTutorial; - } else { - LOG("TRACE_LOGIN", ("%d does not have permissions to log in", getSUID())); - LOG("ClientDisconnect", ("Client (SUID %u) does not have permissions to log in. Disconnecting.", getSUID())); + } else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); disconnect(); + } else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + disconnect(); + } else { + ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); + LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); + + m_hasRequestedCharacterCreate = true; } + + delete m_pendingCharacterCreate; + m_pendingCharacterCreate = nullptr; + + return; } + // Save lists of claimed rewards, which won't be used again until later in the login sequence + m_consumedRewardEvents = consumedRewardEvents; + m_claimedRewardItems = claimedRewardItems; + + + 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 + { + canLogin = true; + canCreateRegularCharacter = true; + canSkipTutorial = true; + m_isAdminAccount = true; + } + + ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial); + send(c, true); + + DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID())); + DEBUG_REPORT_LOG(canLogin, ("\tcanLogin\n")); + DEBUG_REPORT_LOG(canCreateRegularCharacter, ("\tcanCreateRegularCharacter\n")); + DEBUG_REPORT_LOG(canCreateJediCharacter, ("\tcanCreateJediCharacter\n")); + DEBUG_REPORT_LOG(canSkipTutorial, ("\tcanSkipTutorial\n")); + DEBUG_REPORT_LOG(!(canLogin || canCreateRegularCharacter || canCreateJediCharacter || + canSkipTutorial), ("\tnone\n")); + + if (canLogin) { + m_hasBeenValidated = true; + m_canCreateRegularCharacter = canCreateRegularCharacter; + m_canCreateJediCharacter = canCreateJediCharacter; + m_canSkipTutorial = canSkipTutorial; + } else { + LOG("TRACE_LOGIN", ("%d does not have permissions to log in", getSUID())); + LOG("ClientDisconnect", ("Client (SUID %u) does not have permissions to log in. Disconnecting.", getSUID())); + disconnect(); + } +} + //----------------------------------------------------------------------- - void ClientConnection::onConnectionClosed() { - ServerConnection::onConnectionClosed(); - static MessageConnectionCallback m("ClientConnectionClosed"); - emitMessage(m); +void ClientConnection::onConnectionClosed() { + ServerConnection::onConnectionClosed(); + static MessageConnectionCallback m("ClientConnectionClosed"); + emitMessage(m); - LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); - if (m_client) { - if (!m_client->hasBeenKicked()) { - LOG("CustomerService", ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount(this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); - } - ChatServerConnection *chatConnection = m_client->getChatConnection(); - if (chatConnection) { - ChatDisconnectAvatar m(m_characterId); - chatConnection->send(m, true); - } - // We cannot do this here, as this connection will be deleted on - // return from this function already. - //m_client->kick(); + LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); + if (m_client) { + if (!m_client->hasBeenKicked()) { + LOG("CustomerService", ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount(this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); } + ChatServerConnection *chatConnection = m_client->getChatConnection(); + if (chatConnection) { + ChatDisconnectAvatar m(m_characterId); + chatConnection->send(m, true); + } + // We cannot do this here, as this connection will be deleted on + // return from this function already. + //m_client->kick(); } +} //----------------------------------------------------------------------- - void ClientConnection::onConnectionOpened() { - ServerConnection::onConnectionOpened(); - static MessageConnectionCallback m("ClientConnectionOpened"); - emitMessage(m); - setOverflowLimit(ConfigConnectionServer::getClientOverflowLimit()); - } +void ClientConnection::onConnectionOpened() { + ServerConnection::onConnectionOpened(); + static MessageConnectionCallback m("ClientConnectionOpened"); + emitMessage(m); + setOverflowLimit(ConfigConnectionServer::getClientOverflowLimit()); +} //----------------------------------------------------------------------- - void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) { - char errbuf[1024]; - snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", bytesPending); - LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); +void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) { + char errbuf[1024]; + snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", bytesPending); + LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); - std::vector < std::pair < std::string, int > > ::const_iterator - i; - for (i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) { - LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); - } + std::vector < std::pair < std::string, int > > ::const_iterator + i; + for (i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) { + LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); + } // ErrorMessage err(name, desc, false); // send(err, true); - WARNING(true, (errbuf)); - LOG("ClientDisconnect", ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); + WARNING(true, (errbuf)); + LOG("ClientDisconnect", ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); - snprintf(errbuf, sizeof(errbuf) - 1, "Connection Overflow (bytes pending=%u)", bytesPending); - errbuf[sizeof(errbuf) - 1] = '\0'; - ConnectionServer::dropClient(this, std::string(errbuf)); - } + snprintf(errbuf, sizeof(errbuf) - 1, "Connection Overflow (bytes pending=%u)", bytesPending); + errbuf[sizeof(errbuf) - 1] = '\0'; + ConnectionServer::dropClient(this, std::string(errbuf)); +} //----------------------------------------------------------------------- - bool ClientConnection::checkSpamLimit(unsigned int messageSize) { - if (!ConfigConnectionServer::getSpamLimitEnabled()) { - return true; - } - - unsigned long curTimeMs = Clock::timeMs(); - if (m_receiveLastTimeMs) { - ++m_receiveHistoryPackets; - m_receiveHistoryBytes += messageSize; - m_receiveHistoryMs += curTimeMs - m_receiveLastTimeMs; - - // rescale the history information if we've exceeded the reset time; this - // must be done before the spam check below or else we may run into overflow - // issues because m_receiveHistoryMs could be pretty large if we haven't - // received anything from the client for a while - while (m_receiveHistoryMs > ConfigConnectionServer::getSpamLimitResetTimeMs()) { - ++m_countSpamLimitResetTime; - - unsigned int resetScale = ConfigConnectionServer::getSpamLimitResetScaleFactor(); - m_receiveHistoryMs /= resetScale; - m_receiveHistoryBytes /= resetScale; - m_receiveHistoryPackets /= resetScale; - } - - // check for exceeding limits, but wait for at least - // one reset cycle so that there has been enough - // elapsed time, so we won't get a false positive - if (m_countSpamLimitResetTime) { - if (m_receiveHistoryBytes >= - m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitBytesPerSec() / 1000) { - LOG("Network", ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); - return false; - } - if (m_receiveHistoryPackets >= - m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitPacketsPerSec() / 1000) { - LOG("Network", ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); - return false; - } - } - } - m_receiveLastTimeMs = curTimeMs; +bool ClientConnection::checkSpamLimit(unsigned int messageSize) { + if (!ConfigConnectionServer::getSpamLimitEnabled()) { return true; } + unsigned long curTimeMs = Clock::timeMs(); + if (m_receiveLastTimeMs) { + ++m_receiveHistoryPackets; + m_receiveHistoryBytes += messageSize; + m_receiveHistoryMs += curTimeMs - m_receiveLastTimeMs; + + // rescale the history information if we've exceeded the reset time; this + // must be done before the spam check below or else we may run into overflow + // issues because m_receiveHistoryMs could be pretty large if we haven't + // received anything from the client for a while + while (m_receiveHistoryMs > ConfigConnectionServer::getSpamLimitResetTimeMs()) { + ++m_countSpamLimitResetTime; + + unsigned int resetScale = ConfigConnectionServer::getSpamLimitResetScaleFactor(); + m_receiveHistoryMs /= resetScale; + m_receiveHistoryBytes /= resetScale; + m_receiveHistoryPackets /= resetScale; + } + + // check for exceeding limits, but wait for at least + // one reset cycle so that there has been enough + // elapsed time, so we won't get a false positive + if (m_countSpamLimitResetTime) { + if (m_receiveHistoryBytes >= + m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitBytesPerSec() / 1000) { + LOG("Network", ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); + return false; + } + if (m_receiveHistoryPackets >= + m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitPacketsPerSec() / 1000) { + LOG("Network", ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); + return false; + } + } + } + m_receiveLastTimeMs = curTimeMs; + return true; +} + //----------------------------------------------------------------------- - void ClientConnection::onReceive(const Archive::ByteStream &message) { - try { - if (!checkSpamLimit(message.getSize())) { - ConnectionServer::dropClient(this, "Spam Detected"); - return; - } +void ClientConnection::onReceive(const Archive::ByteStream &message) { + try { + if (!checkSpamLimit(message.getSize())) { + ConnectionServer::dropClient(this, "Spam Detected"); + return; + } - unsigned long curTimeMs = Clock::timeMs(); - if (m_sendLastTimeMs + - std::min(gs_receiveDelayMaxMs, static_cast(Clock::frameTime() * 1000.0f)) < curTimeMs) { - static HeartBeat h; - send(h, false); - } + unsigned long curTimeMs = Clock::timeMs(); + if (m_sendLastTimeMs + + std::min(gs_receiveDelayMaxMs, static_cast(Clock::frameTime() * 1000.0f)) < curTimeMs) { + static HeartBeat h; + send(h, false); + } - Archive::ReadIterator ri = message.begin(); - GameNetworkMessage m(ri); - ri = message.begin(); + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage m(ri); + ri = message.begin(); - const uint32 messageType = m.getType(); + const uint32 messageType = m.getType(); - //Clients with a selected character get routed to a game server. - //@todo check for filtering out bad messages. - if (m_hasSelectedCharacter) { - // if it is a chat message, send it directly to the chat server - switch (messageType) { - case constcrc("ChatAddFriend") : - case constcrc("ChatAddModeratorToRoom") : - case constcrc("ChatBanAvatarFromRoom") : - case constcrc("ChatCreateRoom") : - case constcrc("ChatDeletePersistentMessage") : - case constcrc("ChatDeleteAllPersistentMessages") : - case constcrc("ChatDestroyRoom") : - case constcrc("ChatInstantMessageToCharacter") : - case constcrc("ChatInviteAvatarToRoom") : - case constcrc("ChatKickAvatarFromRoom") : - case constcrc("ChatRemoveAvatarFromRoom") : - case constcrc("ChatRemoveFriend") : - case constcrc("ChatRemoveModeratorFromRoom") : - case constcrc("ChatRequestPersistentMessage") : - case constcrc("ChatRequestRoomList") : - case constcrc("ChatSendToRoom") : - case constcrc("ChatUninviteFromRoom") : - case constcrc("ChatUnbanAvatarFromRoom") : - case constcrc("VerifyPlayerNameMessage") : { - DEBUG_REPORT_LOG(true, ("ConnServ: ClientConnection::onReceive()\n")); + //Clients with a selected character get routed to a game server. + //@todo check for filtering out bad messages. + if (m_hasSelectedCharacter) { + // if it is a chat message, send it directly to the chat server + switch (messageType) { + case constcrc("ChatAddFriend") : + case constcrc("ChatAddModeratorToRoom") : + case constcrc("ChatBanAvatarFromRoom") : + case constcrc("ChatCreateRoom") : + case constcrc("ChatDeletePersistentMessage") : + case constcrc("ChatDeleteAllPersistentMessages") : + case constcrc("ChatDestroyRoom") : + case constcrc("ChatInstantMessageToCharacter") : + case constcrc("ChatInviteAvatarToRoom") : + case constcrc("ChatKickAvatarFromRoom") : + case constcrc("ChatRemoveAvatarFromRoom") : + case constcrc("ChatRemoveFriend") : + case constcrc("ChatRemoveModeratorFromRoom") : + case constcrc("ChatRequestPersistentMessage") : + case constcrc("ChatRequestRoomList") : + case constcrc("ChatSendToRoom") : + case constcrc("ChatUninviteFromRoom") : + case constcrc("ChatUnbanAvatarFromRoom") : + case constcrc("VerifyPlayerNameMessage") : { + DEBUG_REPORT_LOG(true, ("ConnServ: ClientConnection::onReceive()\n")); - NOT_NULL(m_client); - if (m_client) { + NOT_NULL(m_client); + if (m_client) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + GameClientMessage gcm(v, true, ri); + if (m_client->getChatConnection()) { + m_client->getChatConnection()->send(gcm, true); + } else { + // defer chat messages until a server is back online + Archive::ByteStream bs; + m.pack(bs); + m_client->deferChatMessage(bs); + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + // ChatEnterRoom and ChatEnterRoomById needs to go to the game server to determine + // if the character is not allowed to enter the room because of game rule restrictions; + // only if that test pass do we forward the message on to the chat server to request + // to enter the room + case constcrc("ChatEnterRoom") : + case constcrc("ChatEnterRoomById") : { + NOT_NULL(m_client); + + unsigned int sequence; + std::string roomName; + + Archive::ReadIterator cri = message.begin(); + + if (messageType == constcrc("ChatEnterRoom")) { + ChatEnterRoom const cer(cri); + sequence = cer.getSequence(); + roomName = cer.getRoomName(); + } else { + ChatEnterRoomById const cerbi(cri); + sequence = cerbi.getSequence(); + roomName = cerbi.getRoomName(); + } + + if (m_client && m_client->getGameConnection()) { + if (m_pendingChatEnterRoomRequests.count(sequence) == 0) { + GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned + int > > + const cervr( + "ChatEnterRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), roomName), sequence)); + + m_client->getGameConnection()->send(cervr, true); + + // queue up request until game server responds + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); + } + } else { + // send back response to client saying game server not available + + // the client only cares about sequence and result when it's a failure + ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_NO_GAME_SERVER, 0, ChatAvatarId()); + send(fail, true); + } + + break; + } + // ChatQueryRoom needs to go to the game server to determine if the character is + // not allowed to query the room because of game rule restrictions; only if that + // test pass do we forward the message on to the chat server for completion + case constcrc("ChatQueryRoom") : { + NOT_NULL(m_client); + + Archive::ReadIterator cri = message.begin(); + ChatQueryRoom cqr(cri); + + if (m_client && m_client->getGameConnection()) { + if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) { + GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned + int > > + const cqrvr( + "ChatQueryRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), cqr.getSequence())); + + m_client->getGameConnection()->send(cqrvr, true); + + // queue up request until game server responds + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); + } + } + break; + } + // ChatInviteGroupToRoom needs to go to the game server to get group information + case constcrc("ChatInviteGroupToRoom") : { + NOT_NULL(m_client); + if (m_client) { + if (m_client->getGameConnection()) { static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); + } else { + // defer chat messages until a server is back online + Archive::ByteStream bs; + m.pack(bs); + m_client->deferChatMessage(bs); + } + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); + } + break; + } + // ChatPersistentMessageToServer may need to be passed off to the game server for guild or citizens messages + case constcrc("ChatPersistentMessageToServer") : { + NOT_NULL(m_client); + if (m_client) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + + Archive::ReadIterator cri = message.begin(); + ChatPersistentMessageToServer chat(cri); + std::string const &toName = chat.getToCharacterName().name; + if (!_stricmp(toName.c_str(), "guild") || !_strnicmp(toName.c_str(), "guild ", 6) || + !_stricmp(toName.c_str(), "citizens")) { + if (m_client->getGameConnection()) { + GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); + } + } else { if (m_client->getChatConnection()) { + GameClientMessage gcm(v, true, ri); m_client->getChatConnection()->send(gcm, true); } else { // defer chat messages until a server is back online @@ -621,564 +752,433 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { m.pack(bs); m_client->deferChatMessage(bs); } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); } - break; - } - // ChatEnterRoom and ChatEnterRoomById needs to go to the game server to determine - // if the character is not allowed to enter the room because of game rule restrictions; - // only if that test pass do we forward the message on to the chat server to request - // to enter the room - case constcrc("ChatEnterRoom") : - case constcrc("ChatEnterRoomById") : { - NOT_NULL(m_client); - - unsigned int sequence; - std::string roomName; - - Archive::ReadIterator cri = message.begin(); - - if (messageType == constcrc("ChatEnterRoom")) { - ChatEnterRoom const cer(cri); - sequence = cer.getSequence(); - roomName = cer.getRoomName(); - } else { - ChatEnterRoomById const cerbi(cri); - sequence = cerbi.getSequence(); - roomName = cerbi.getRoomName(); - } - - if (m_client && m_client->getGameConnection()) { - if (m_pendingChatEnterRoomRequests.count(sequence) == 0) { - GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned - int > > - const cervr( - "ChatEnterRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), roomName), sequence)); - - m_client->getGameConnection()->send(cervr, true); - - // queue up request until game server responds - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); - } - } else { - // send back response to client saying game server not available - - // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_NO_GAME_SERVER, 0, ChatAvatarId()); - send(fail, true); - } - - break; - } - // ChatQueryRoom needs to go to the game server to determine if the character is - // not allowed to query the room because of game rule restrictions; only if that - // test pass do we forward the message on to the chat server for completion - case constcrc("ChatQueryRoom") : { - NOT_NULL(m_client); - - Archive::ReadIterator cri = message.begin(); - ChatQueryRoom cqr(cri); - - if (m_client && m_client->getGameConnection()) { - if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) { - GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned - int > > - const cqrvr( - "ChatQueryRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), cqr.getSequence())); - - m_client->getGameConnection()->send(cqrvr, true); - - // queue up request until game server responds - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); - } - } - break; - } - // ChatInviteGroupToRoom needs to go to the game server to get group information - case constcrc("ChatInviteGroupToRoom") : { - NOT_NULL(m_client); - if (m_client) { - if (m_client->getGameConnection()) { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } else { - // defer chat messages until a server is back online - Archive::ByteStream bs; - m.pack(bs); - m_client->deferChatMessage(bs); - } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - // ChatPersistentMessageToServer may need to be passed off to the game server for guild or citizens messages - case constcrc("ChatPersistentMessageToServer") : { - NOT_NULL(m_client); - if (m_client) { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - - Archive::ReadIterator cri = message.begin(); - ChatPersistentMessageToServer chat(cri); - std::string const &toName = chat.getToCharacterName().name; - if (!_stricmp(toName.c_str(), "guild") || !_strnicmp(toName.c_str(), "guild ", 6) || - !_stricmp(toName.c_str(), "citizens")) { - if (m_client->getGameConnection()) { - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } - } else { - if (m_client->getChatConnection()) { - GameClientMessage gcm(v, true, ri); - m_client->getChatConnection()->send(gcm, true); - } else { - // defer chat messages until a server is back online - Archive::ByteStream bs; - m.pack(bs); - m_client->deferChatMessage(bs); - } - } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - // if it is a cs message, send it directly to the cs server - case constcrc("ConnectPlayerMessage") : - case constcrc("DisconnectPlayerMessage") : - case constcrc("CreateTicketMessage") : - case constcrc("AppendCommentMessage") : - case constcrc("CancelTicketMessage") : - case constcrc("GetTicketsMessage") : - case constcrc("GetCommentsMessage") : - case constcrc("SearchKnowledgeBaseMessage") : - case constcrc("GetArticleMessage") : - case constcrc("RequestCategoriesMessage") : - case constcrc("NewTicketActivityMessage") : { - NOT_NULL(m_client); - if (m_client) { - CustomerServiceConnection *customerServiceConnection = m_client->getCustomerServiceConnection(); - - //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); - - if (customerServiceConnection != nullptr) { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - - // TODO: this shit could be made into a template - switch (messageType) { - case constcrc("ConnectPlayerMessage") : { - ConnectPlayerMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("CreateTicketMessage") : { - CreateTicketMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("AppendCommentMessage") : { - AppendCommentMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("CancelTicketMessage") : { - CancelTicketMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("GetTicketsMessage") : { - GetTicketsMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - case constcrc("NewTicketActivityMessage") : { - NewTicketActivityMessage message(ri); - message.setStationId(getSUID()); - - GameClientMessage gcm(v, true, message); - customerServiceConnection->send(gcm, true); - break; - } - default : { - GameClientMessage gcm(v, true, ri); - customerServiceConnection->send(gcm, true); - break; - } - } - } - } else { - ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); - disconnect(); - } - break; - } - case constcrc("28afefcc187a11dc888b001") : // obfuscation for ClientInactivityMessage message - { - GenericValueTypeMessage msg(ri); - - if (m_hasBeenValidated && m_sessionValidated) { - // client went inactive - if (msg.getValue()) { - if (m_lastActiveTime > 0) { - // record the amount of active time - m_activePlayTimeDuration += static_cast(::time(nullptr) - - m_lastActiveTime); - - // tell Session to stop recording play time for the character - if (ConnectionServer::getSessionApiClient() && - ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); - ConnectionServer::getSessionApiClient()->stopPlay(*this); - } - - // client is no longer active; this needs to be set after the LOG() statement - // above because getCurrentActivePlayTimeDuration() uses m_lastActiveTime - m_lastActiveTime = 0; - - // update the play time info on the game server - sendPlayTimeInfoToGameServer(); - - // drop inactive character - if (ConfigConnectionServer::getDisconnectOnInactive()) { - LOG("ClientDisconnect", ("Disconnecting %u because the player was inactive for too long.", getSUID())); - ConnectionServer::dropClient(this, "Client inactivity"); - disconnect(); - } else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && - ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { - LOG("ClientDisconnect", ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); - ConnectionServer::dropClient(this, "Client inactivity (free trial)"); - disconnect(); - } - } - } - // client went active - else { - if (m_lastActiveTime == 0) { - // record the time client went active - m_lastActiveTime = ::time(nullptr); - - // tell Session to start recording play time for the character - if (ConnectionServer::getSessionApiClient() && - ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); - ConnectionServer::getSessionApiClient()->startPlay(*this); - } - - // update the play time info on the game server - sendPlayTimeInfoToGameServer(); - } - } - } - break; - } - default : { - //Forward on to Game Server - DEBUG_REPORT_LOG((!m_client || - !m_client->getGameConnection()), ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); - - if (m_client && m_client->getGameConnection()) { - static std::vector v; - v.clear(); - v.push_back(m_client->getNetworkId()); - GameClientMessage gcm(v, true, ri); - m_client->getGameConnection()->send(gcm, true); - } - - break; + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); } + break; } - } else { - switch (messageType) { - case constcrc("ClientIdMsg") : { - DEBUG_REPORT_LOG(true, ("Recieved ClientIdMsg\n")); - ClientIdMsg k(ri); + // if it is a cs message, send it directly to the cs server + case constcrc("ConnectPlayerMessage") : + case constcrc("DisconnectPlayerMessage") : + case constcrc("CreateTicketMessage") : + case constcrc("AppendCommentMessage") : + case constcrc("CancelTicketMessage") : + case constcrc("GetTicketsMessage") : + case constcrc("GetCommentsMessage") : + case constcrc("SearchKnowledgeBaseMessage") : + case constcrc("GetArticleMessage") : + case constcrc("RequestCategoriesMessage") : + case constcrc("NewTicketActivityMessage") : { + NOT_NULL(m_client); + if (m_client) { + CustomerServiceConnection *customerServiceConnection = m_client->getCustomerServiceConnection(); - handleClientIdMessage(k); - break; - } - case constcrc("SelectCharacter") : { - SelectCharacter s(ri); - DEBUG_REPORT_LOG(true, ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); + //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); - handleSelectCharacterMessage(s); - break; - } - case constcrc("ClientCreateCharacter") : { - if (m_hasBeenValidated && - !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true - { - ClientCreateCharacter clientCreate(ri); - DEBUG_REPORT_LOG(true, ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str())); - LOG("TraceCharacterCreation", ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", getSUID(), Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), clientCreate.getTemplateName().c_str(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation().c_str(), clientCreate.getHairTemplateName().c_str(), clientCreate.getProfession().c_str(), static_cast(clientCreate.getJedi()), static_cast(clientCreate.getUseNewbieTutorial()), clientCreate.getSkillTemplate().c_str(), clientCreate.getWorkingSkill().c_str())); + if (customerServiceConnection != nullptr) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); - if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); - disconnect(); - } else if (clientCreate.getJedi() && !m_canCreateJediCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); - disconnect(); - } else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); - // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); - disconnect(); - } else if (m_hasRequestedCharacterCreate) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); - disconnect(); - } else if (m_hasCreatedCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); - disconnect(); - } else if (clientCreate.getCharacterName().length() == 0) { - LOG("TraceCharacterCreation", ("%d failed character creation. The character's name is empty", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); - disconnect(); - } else { - Unicode::String biography(clientCreate.getBiography()); - if (biography.length() > 1024) { - IGNORE_RETURN(biography.erase(1024)); - DEBUG_REPORT_LOG(true, ("Biography shortened to 1024 characters.\n")); + // TODO: this shit could be made into a template + switch (messageType) { + case constcrc("ConnectPlayerMessage") : { + ConnectPlayerMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; } + case constcrc("CreateTicketMessage") : { + CreateTicketMessage message(ri); + message.setStationId(getSUID()); - if (m_isAdminAccount) { - ConnectionCreateCharacter connectionCreate(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); - - ConnectionServer::sendToCentralProcess(connectionCreate); - LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); - } else { - // for regular players, do one final check with the LoginServer - // to make sure the character can be created (i.e. that character - // limits have not been exceeded) - delete m_pendingCharacterCreate; - m_pendingCharacterCreate = new ConnectionCreateCharacter(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); - - LOG("TraceCharacterCreation", ("%d character creation request awaiting final verification from LoginServer", getSUID())); - - ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); - ConnectionServer::sendToCentralProcess(vcm); + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; } + case constcrc("AppendCommentMessage") : { + AppendCommentMessage message(ri); + message.setStationId(getSUID()); - m_hasRequestedCharacterCreate = true; + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("CancelTicketMessage") : { + CancelTicketMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("GetTicketsMessage") : { + GetTicketsMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + case constcrc("NewTicketActivityMessage") : { + NewTicketActivityMessage message(ri); + message.setStationId(getSUID()); + + GameClientMessage gcm(v, true, message); + customerServiceConnection->send(gcm, true); + break; + } + default : { + GameClientMessage gcm(v, true, ri); + customerServiceConnection->send(gcm, true); + break; + } } } - break; + } else { + ConnectionServer::dropClient(this, "m_client is nullptr while receiving a message!"); + disconnect(); } - case constcrc("ClientRandomNameRequest") : { - ClientRandomNameRequest clientRandomName(ri); + break; + } + case constcrc("28afefcc187a11dc888b001") : // obfuscation for ClientInactivityMessage message + { + GenericValueTypeMessage msg(ri); - RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); - ConnectionServer::sendToCentralProcess(randomNameRequest); - LOG("TraceCharacterCreation", ("%d requested a random name. Request sent to CentralServer", getSUID())); - break; - } - case constcrc("ClientVerifyAndLockNameRequest") : { - ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); + if (m_hasBeenValidated && m_sessionValidated) { + // client went inactive + if (msg.getValue()) { + if (m_lastActiveTime > 0) { + // record the amount of active time + m_activePlayTimeDuration += static_cast(::time(nullptr) - + m_lastActiveTime); - VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, clientVerifyAndLockNameRequest.getTemplateName(), clientVerifyAndLockNameRequest.getCharacterName(), m_featureBitsGame); - ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); - LOG("TraceCharacterCreation", ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow(verifyAndLockNameRequest.getCharacterName()).c_str())); - break; + // tell Session to stop recording play time for the character + if (ConnectionServer::getSessionApiClient() && + ConfigConnectionServer::getSessionRecordPlayTime()) { + LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + ConnectionServer::getSessionApiClient()->stopPlay(*this); + } + + // client is no longer active; this needs to be set after the LOG() statement + // above because getCurrentActivePlayTimeDuration() uses m_lastActiveTime + m_lastActiveTime = 0; + + // update the play time info on the game server + sendPlayTimeInfoToGameServer(); + + // drop inactive character + if (ConfigConnectionServer::getDisconnectOnInactive()) { + LOG("ClientDisconnect", ("Disconnecting %u because the player was inactive for too long.", getSUID())); + ConnectionServer::dropClient(this, "Client inactivity"); + disconnect(); + } else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && + ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { + LOG("ClientDisconnect", ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); + ConnectionServer::dropClient(this, "Client inactivity (free trial)"); + disconnect(); + } + } + } + // client went active + else { + if (m_lastActiveTime == 0) { + // record the time client went active + m_lastActiveTime = ::time(nullptr); + + // tell Session to start recording play time for the character + if (ConnectionServer::getSessionApiClient() && + ConfigConnectionServer::getSessionRecordPlayTime()) { + LOG("CustomerService", ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); + ConnectionServer::getSessionApiClient()->startPlay(*this); + } + + // update the play time info on the game server + sendPlayTimeInfoToGameServer(); + } + } } - case constcrc("LagRequest") : { - // TODO: why is this commented out? - // handleLagRequest(); - break; + break; + } + default : { + //Forward on to Game Server + DEBUG_REPORT_LOG((!m_client || + !m_client->getGameConnection()), ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); + + if (m_client && m_client->getGameConnection()) { + static std::vector v; + v.clear(); + v.push_back(m_client->getNetworkId()); + GameClientMessage gcm(v, true, ri); + m_client->getGameConnection()->send(gcm, true); } + + break; + } + } + } else { + switch (messageType) { + case constcrc("ClientIdMsg") : { + DEBUG_REPORT_LOG(true, ("Recieved ClientIdMsg\n")); + ClientIdMsg k(ri); + + handleClientIdMessage(k); + break; + } + case constcrc("SelectCharacter") : { + SelectCharacter s(ri); + DEBUG_REPORT_LOG(true, ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); + + handleSelectCharacterMessage(s); + break; + } + case constcrc("ClientCreateCharacter") : { + if (m_hasBeenValidated && !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true + { + ClientCreateCharacter clientCreate(ri); + DEBUG_REPORT_LOG(true, ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str())); + LOG("TraceCharacterCreation", ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", getSUID(), Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), clientCreate.getTemplateName().c_str(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation().c_str(), clientCreate.getHairTemplateName().c_str(), clientCreate.getProfession().c_str(), static_cast(clientCreate.getJedi()), static_cast(clientCreate.getUseNewbieTutorial()), clientCreate.getSkillTemplate().c_str(), clientCreate.getWorkingSkill().c_str())); + + if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial + LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + disconnect(); + } else if (clientCreate.getJedi() && !m_canCreateJediCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + disconnect(); + } else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + // This is probably a hack attempt, because the Client was already told they couldn't create a character + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + disconnect(); + } else if (m_hasRequestedCharacterCreate) { + LOG("TraceCharacterCreation", ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); + disconnect(); + } else if (m_hasCreatedCharacter) { + LOG("TraceCharacterCreation", ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); + disconnect(); + } else if (clientCreate.getCharacterName().length() == 0) { + LOG("TraceCharacterCreation", ("%d failed character creation. The character's name is empty", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); + disconnect(); + } else { + Unicode::String biography(clientCreate.getBiography()); + if (biography.length() > 1024) { + IGNORE_RETURN(biography.erase(1024)); + DEBUG_REPORT_LOG(true, ("Biography shortened to 1024 characters.\n")); + } + + if (m_isAdminAccount) { + ConnectionCreateCharacter connectionCreate(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); + + ConnectionServer::sendToCentralProcess(connectionCreate); + LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); + } else { + // for regular players, do one final check with the LoginServer + // to make sure the character can be created (i.e. that character + // limits have not been exceeded) + delete m_pendingCharacterCreate; + m_pendingCharacterCreate = new ConnectionCreateCharacter(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); + + LOG("TraceCharacterCreation", ("%d character creation request awaiting final verification from LoginServer", getSUID())); + + ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); + ConnectionServer::sendToCentralProcess(vcm); + } + + m_hasRequestedCharacterCreate = true; + } + } + break; + } + case constcrc("ClientRandomNameRequest") : { + ClientRandomNameRequest clientRandomName(ri); + + RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); + ConnectionServer::sendToCentralProcess(randomNameRequest); + LOG("TraceCharacterCreation", ("%d requested a random name. Request sent to CentralServer", getSUID())); + break; + } + case constcrc("ClientVerifyAndLockNameRequest") : { + ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); + + VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, clientVerifyAndLockNameRequest.getTemplateName(), clientVerifyAndLockNameRequest.getCharacterName(), m_featureBitsGame); + ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); + LOG("TraceCharacterCreation", ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow(verifyAndLockNameRequest.getCharacterName()).c_str())); + break; + } + case constcrc("LagRequest") : { + // TODO: why is this commented out? + // handleLagRequest(); + break; } } - } catch (const Archive::ReadException &readException) { - WARNING(true, ("Archive read error (%s) from client. Disconnecting client", readException.what())); - LOG("ClientDisconnect", ("Archive read error (%s) from client. Disconnecting client", readException.what())); - disconnect(); } + } catch (const Archive::ReadException &readException) { + WARNING(true, ("Archive read error (%s) from client. Disconnecting client", readException.what())); + LOG("ClientDisconnect", ("Archive read error (%s) from client. Disconnecting client", readException.what())); + disconnect(); } +} //----------------------------------------------------------------------- - void ClientConnection::handleLagRequest() { - // client is requesting a lag ping (reliable trace) - GameNetworkMessage response("ConnectionServerLagResponse"); - send(response, true); - - if (m_hasSelectedCharacter && m_client && m_client->getGameConnection()) { - // send to game server - GameNetworkMessage request("LagRequest"); - std::vector v; - v.push_back(m_characterId); - GameClientMessage gcm(v, true, request); - m_client->getGameConnection()->send(gcm, true); - } else { - // send game response immediately - GameNetworkMessage gameResponse("GameServerLagResponse"); - send(gameResponse, true); - } +void ClientConnection::handleLagRequest() { + // client is requesting a lag ping (reliable trace) + GameNetworkMessage response("ConnectionServerLagResponse"); + send(response, true); + if (m_hasSelectedCharacter && m_client && m_client->getGameConnection()) { + // send to game server + GameNetworkMessage request("LagRequest"); + std::vector v; + v.push_back(m_characterId); + GameClientMessage gcm(v, true, request); + m_client->getGameConnection()->send(gcm, true); + } else { + // send game response immediately + GameNetworkMessage gameResponse("GameServerLagResponse"); + send(gameResponse, true); } +} + //----------------------------------------------------------------------- /** character has selected a character and calls this function * to associate the connection with the new client they created with that * character. We no longer need the character map. */ - void ClientConnection::setClient(Client *newClient) { - //This fatal is here to try to catch the reconnect bug. - WARNING_STRICT_FATAL(m_client, ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); - // jrandall - I've removed the fatal because it is blocking some people from getting some work - // done. I'm on a high priority fix at the moment. If this warning starts appearing, - // set a break point or something. - //DEBUG_FATAL(client, ("Attempting to set the client on a connection that already has one.\n")); - m_client = newClient; +void ClientConnection::setClient(Client *newClient) { + //This fatal is here to try to catch the reconnect bug. + WARNING_STRICT_FATAL(m_client, ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); + // jrandall - I've removed the fatal because it is blocking some people from getting some work + // done. I'm on a high priority fix at the moment. If this warning starts appearing, + // set a break point or something. + //DEBUG_FATAL(client, ("Attempting to set the client on a connection that already has one.\n")); + m_client = newClient; - // todo put this in: characterMap.clear(); - } + // todo put this in: characterMap.clear(); +} //----------------------------------------------------------------------- - void ClientConnection::send(const GameNetworkMessage &message, const bool reliable) { - m_sendLastTimeMs = Clock::timeMs(); +void ClientConnection::send(const GameNetworkMessage &message, const bool reliable) { + m_sendLastTimeMs = Clock::timeMs(); - if (sm_outgoingBytesMap_Worktime == 0) { - sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; - } else if ((m_sendLastTimeMs - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map::iterator iter; - for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { - iter->second = 0; - } - sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; + if (sm_outgoingBytesMap_Worktime == 0) { + sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; + } else if ((m_sendLastTimeMs - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds + { + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; } - sm_outgoingBytesMap_Working[message.getCmdName()] += message.getByteStream().getSize(); - - - ServerConnection::send(message, reliable); + sm_outgoingBytesMap_Worktime = m_sendLastTimeMs; } + sm_outgoingBytesMap_Working[message.getCmdName()] += message.getByteStream().getSize(); + + + ServerConnection::send(message, reliable); +} //----------------------------------------------------------------------- - std::map &ClientConnection::getPacketBytesPerMinStats() { - uint32 now = Clock::timeMs(); - if (sm_outgoingBytesMap_Worktime == 0) { - sm_outgoingBytesMap_Worktime = now; - } else if ((now - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map::iterator iter; - for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { - iter->second = 0; - } - sm_outgoingBytesMap_Worktime = now; +std::map &ClientConnection::getPacketBytesPerMinStats() { + uint32 now = Clock::timeMs(); + if (sm_outgoingBytesMap_Worktime == 0) { + sm_outgoingBytesMap_Worktime = now; + } else if ((now - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds + { + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; } - - return sm_outgoingBytesMap_Stats; + sm_outgoingBytesMap_Worktime = now; } + return sm_outgoingBytesMap_Stats; +} + //----------------------------------------------------------------------- - void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) { - std::map < unsigned - long, GameClientMessage * > ::iterator - iterFind = m_pendingChatEnterRoomRequests.find(sequence); - if (iterFind != m_pendingChatEnterRoomRequests.end()) { - if (result == CHATRESULT_SUCCESS) { - if (m_client && m_client->getChatConnection()) { - // game server says it's ok to enter the chat room, - // so forward the request on to the chat server - m_client->getChatConnection()->send(*(iterFind->second), true); - } else { - // send back response to client saying chat server not available - - // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_CHAT_SERVER_UNAVAILABLE, 0, ChatAvatarId()); - send(fail, true); - } +void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) { + std::map < unsigned + long, GameClientMessage * > ::iterator + iterFind = m_pendingChatEnterRoomRequests.find(sequence); + if (iterFind != m_pendingChatEnterRoomRequests.end()) { + if (result == CHATRESULT_SUCCESS) { + if (m_client && m_client->getChatConnection()) { + // game server says it's ok to enter the chat room, + // so forward the request on to the chat server + m_client->getChatConnection()->send(*(iterFind->second), true); } else { - // send back response to client saying game server denied enter room request + // send back response to client saying chat server not available // the client only cares about sequence and result when it's a failure - ChatOnEnteredRoom fail(sequence, result, 0, ChatAvatarId()); + ChatOnEnteredRoom fail(sequence, SWG_CHAT_ERR_CHAT_SERVER_UNAVAILABLE, 0, ChatAvatarId()); send(fail, true); } + } else { + // send back response to client saying game server denied enter room request - delete iterFind->second; - m_pendingChatEnterRoomRequests.erase(iterFind); + // the client only cares about sequence and result when it's a failure + ChatOnEnteredRoom fail(sequence, result, 0, ChatAvatarId()); + send(fail, true); } + + delete iterFind->second; + m_pendingChatEnterRoomRequests.erase(iterFind); } +} //----------------------------------------------------------------------- - void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) { - std::map < unsigned - long, GameClientMessage * > ::iterator - iterFind = m_pendingChatQueryRoomRequests.find(sequence); - if (iterFind != m_pendingChatQueryRoomRequests.end()) { - if (success) { - if (m_client && m_client->getChatConnection()) { - // game server says it's ok to query the chat room, - // so forward the request on to the chat server - m_client->getChatConnection()->send(*(iterFind->second), true); - } +void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) { + std::map < unsigned + long, GameClientMessage * > ::iterator + iterFind = m_pendingChatQueryRoomRequests.find(sequence); + if (iterFind != m_pendingChatQueryRoomRequests.end()) { + if (success) { + if (m_client && m_client->getChatConnection()) { + // game server says it's ok to query the chat room, + // so forward the request on to the chat server + m_client->getChatConnection()->send(*(iterFind->second), true); } - - delete iterFind->second; - m_pendingChatQueryRoomRequests.erase(iterFind); } + + delete iterFind->second; + m_pendingChatQueryRoomRequests.erase(iterFind); } +} //----------------------------------------------------------------------- - void ClientConnection::sendByteStream(const Archive::ByteStream &bs, bool reliable) { - Connection::send(bs, reliable); - } +void ClientConnection::sendByteStream(const Archive::ByteStream &bs, bool reliable) { + Connection::send(bs, reliable); +} //----------------------------------------------------------------------- /** * Send the client to an arbitratry game server based on the current scene */ - const bool ClientConnection::sendToGameServer() { - GameConnection *c = const_cast(ConnectionServer::getGameConnection(m_targetScene)); - return sendToGameServer(c); - } +const bool ClientConnection::sendToGameServer() { + GameConnection *c = const_cast(ConnectionServer::getGameConnection(m_targetScene)); + return sendToGameServer(c); +} // ---------------------------------------------------------------------- @@ -1186,27 +1186,27 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { * Send the client to a particular game server, sepcified by process id. */ - const bool ClientConnection::sendToGameServer(uint32 gameServerId) { - GameConnection *c = const_cast(ConnectionServer::getGameConnection(gameServerId)); - return sendToGameServer(c); - } +const bool ClientConnection::sendToGameServer(uint32 gameServerId) { + GameConnection *c = const_cast(ConnectionServer::getGameConnection(gameServerId)); + return sendToGameServer(c); +} // ---------------------------------------------------------------------- - bool ClientConnection::sendToGameServer(GameConnection *c) { - bool result = false; +bool ClientConnection::sendToGameServer(GameConnection *c) { + bool result = false; - if (c && m_hasSelectedCharacter && m_hasBeenValidated) { - //create a new client - ConnectionServer::addNewClient(this, m_characterId, c, m_targetScene, m_sendToStarport); + if (c && m_hasSelectedCharacter && m_hasBeenValidated) { + //create a new client + ConnectionServer::addNewClient(this, m_characterId, c, m_targetScene, m_sendToStarport); - LoggedInMessage m(m_suid); - ConnectionServer::sendToCentralProcess(m); - result = true; - m_hasBeenSentToGameServer = true; - } - return result; + LoggedInMessage m(m_suid); + ConnectionServer::sendToCentralProcess(m); + result = true; + m_hasBeenSentToGameServer = true; } + return result; +} //----------------------------------------------------------------------- @@ -1215,230 +1215,229 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { * Now we know whether the character is valid and where in the world it * is located. */ - void - ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, const NetworkId &container, const std::string &scene, const Vector &coordinates) { - if (!m_validatingCharacter) { - LOG("TraceCharacterSelection", ("%d received a validation response, but is not in the process of validation", getSUID())); - DEBUG_REPORT_LOG(true, ("Got unexpected onCharacterValidated() for account %lu.\n", getSUID())); - return; - } - m_validatingCharacter = false; +void +ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, const NetworkId &container, const std::string &scene, const Vector &coordinates) { + if (!m_validatingCharacter) { + LOG("TraceCharacterSelection", ("%d received a validation response, but is not in the process of validation", getSUID())); + DEBUG_REPORT_LOG(true, ("Got unexpected onCharacterValidated() for account %lu.\n", getSUID())); + return; + } + m_validatingCharacter = false; - if (isValid) { - LOG("TraceCharacterSelection", ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - LOG("CustomerService", ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount(this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - m_targetScene = scene; - m_targetCoordinates = coordinates; - m_characterId = character; - m_containerId = container; - m_characterName = characterName; + if (isValid) { + LOG("TraceCharacterSelection", ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + LOG("CustomerService", ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount(this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + m_targetScene = scene; + m_targetCoordinates = coordinates; + m_characterId = character; + m_containerId = container; + m_characterName = characterName; - m_hasSelectedCharacter = true; + m_hasSelectedCharacter = true; - // ask CentralServer to suggest a game server for this character - // (Central will forward the request to a Planet Server) + // ask CentralServer to suggest a game server for this character + // (Central will forward the request to a Planet Server) - RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, m_targetCoordinates, false); - if (ConnectionServer::getCentralConnection()) { - ConnectionServer::getCentralConnection()->send(requestmsg, true); - } else { - LOG("ClientDisconnect", ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); - ErrorMessage err("Validation Failed", "The connection to the central server is down. Please try again later."); - send(err, true); - - disconnect(); - } + RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, m_targetCoordinates, false); + if (ConnectionServer::getCentralConnection()) { + ConnectionServer::getCentralConnection()->send(requestmsg, true); } else { - LOG("TraceCharacterSelection", ("%d validation failed, disconnecting client", getSUID())); - ErrorMessage err("Validation Failed", "Your character was denied login by the database."); + LOG("ClientDisconnect", ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); + ErrorMessage err("Validation Failed", "The connection to the central server is down. Please try again later."); send(err, true); - LOG("ClientDisconnect", ("Denying login for account %u.\n", getSUID())); disconnect(); } + } else { + LOG("TraceCharacterSelection", ("%d validation failed, disconnecting client", getSUID())); + ErrorMessage err("Validation Failed", "Your character was denied login by the database."); + send(err, true); + + LOG("ClientDisconnect", ("Denying login for account %u.\n", getSUID())); + disconnect(); } +} //------------------------------------------------------------------------------------------ - void - ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, const uint32 gameFeatures, const uint32 subscriptionFeatures, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { - UNREF(id); - m_sessionValidated = true; - m_suid = suid; - m_accountName = username; - m_featureBitsGame = gameFeatures; - m_featureBitsSubscription = subscriptionFeatures; - m_isSecure = secure; - m_entitlementTotalTime = entitlementTotalTime; - m_entitlementEntitledTime = entitlementEntitledTime; - m_entitlementTotalTimeSinceLastLogin = entitlementTotalTimeSinceLastLogin; - m_entitlementEntitledTimeSinceLastLogin = entitlementEntitledTimeSinceLastLogin; - m_buddyPoints = buddyPoints; +void +ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, const uint32 gameFeatures, const uint32 subscriptionFeatures, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { + UNREF(id); + m_sessionValidated = true; + m_suid = suid; + m_accountName = username; + m_featureBitsGame = gameFeatures; + m_featureBitsSubscription = subscriptionFeatures; + m_isSecure = secure; + m_entitlementTotalTime = entitlementTotalTime; + m_entitlementEntitledTime = entitlementEntitledTime; + m_entitlementTotalTimeSinceLastLogin = entitlementTotalTimeSinceLastLogin; + m_entitlementEntitledTimeSinceLastLogin = entitlementEntitledTimeSinceLastLogin; + m_buddyPoints = buddyPoints; - if (id) { - m_sessionId = id; - } + if (id) { + m_sessionId = id; + } - if (m_requestedSuid != 0 && suid != m_requestedSuid) { - //verify internal, secure, is on the god list - bool loginOK = false; - if (!secure) { - LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); + if (m_requestedSuid != 0 && suid != m_requestedSuid) { + //verify internal, secure, is on the god list + bool loginOK = false; + if (!secure) { + LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); + } else { + if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); } else { - if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); + int adminLevel = 0; + if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || 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, m_requestedSuid)); } else { - int adminLevel = 0; - if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || - 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, m_requestedSuid)); - } else { - LOG("CustomerService", ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); - DEBUG_REPORT_LOG(true, ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); - m_suid = m_requestedSuid; - m_usingAdminLogin = true; - loginOK = true; - } + LOG("CustomerService", ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); + DEBUG_REPORT_LOG(true, ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); + m_suid = m_requestedSuid; + m_usingAdminLogin = true; + loginOK = true; } } - if (!loginOK) { - disconnect(); - return; - } } - - m_featureBitsGame &= ~ConfigConnectionServer::getDisabledFeatureBits(); - - //Configoption to enable JTL features for beta players so that our code can pretend everything uses the JTL Retail bit - if (ConfigConnectionServer::getSetJtlRetailIfBetaIsSet()) { - if (ClientGameFeature::SpaceExpansionBeta & m_featureBitsGame) { - m_featureBitsGame |= ClientGameFeature::SpaceExpansionRetail; - } - } - - //Configoption to enable Obiwan features for beta players so that our code can pretend everything uses the Obiwan Retail bit - if (ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet()) { - if (ClientGameFeature::TrialsOfObiwanBeta & m_featureBitsGame) { - //-- add retail bit only if player does not have the preorder bit - if ((m_featureBitsGame & ClientGameFeature::TrialsOfObiwanPreorder) == 0) { - m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; - } - } else { - // Clear bits from players who might have them for real, but aren't in the beta - m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanRetail; - m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanPreorder; - } - } - - //-- Obiwan Preorders get the Retail bit as well... All rewards etc... - if (ClientGameFeature::TrialsOfObiwanPreorder & m_featureBitsGame) { - m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; - } - - // Restrictions for "new free trial" account - if (((m_featureBitsSubscription & ClientSubscriptionFeature::FreeTrial2) != 0) && - ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { - // "new free trial" account don't have access to RoW until they convert - m_featureBitsGame &= ~ClientGameFeature::Episode3ExpansionRetail; - m_featureBitsGame &= ~ClientGameFeature::Episode3PreorderDownload; - - // ClientGameFeature::FreeTrial2 indicates this is a converted "new free trial" - // account, and since this account hasn't converted yet, we remove this bit - m_featureBitsGame &= ~ClientGameFeature::FreeTrial2; - } - - // Clear feature bits that only apply if the account is paying (i.e. the sub base bit is set) - if ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0) { - m_featureBitsGame &= ~ClientGameFeature::HousePackupReward; - m_featureBitsGame &= ~ClientGameFeature::BuddyProgramReward; - } - - ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); - ConnectionServer::sendToCentralProcess(vcm); - ConnectionServer::addConnectedClient(m_suid, this); - - uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); - if (requiredSubscriptionBits != 0) { - if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) { - LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); - LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); - disconnect(); - return; - } - } - - uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); - if (requiredGameBits != 0) { - if ((gameFeatures & requiredGameBits) != requiredGameBits) { - LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); - LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); - disconnect(); - return; - } - } - - // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time - GenericValueTypeMessage < std::pair < std::pair < unsigned - long, unsigned - long > , std::pair < int, int32 > > > - const msgFeatureBits( - "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), static_cast(::time(nullptr))))); - send(msgFeatureBits, true); - - std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); - std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); - - LOG("CustomerService", ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount(this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); - - // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account - // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account - if (!m_usingAdminLogin && !m_isSecure) { - GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", std::make_pair(m_suid, m_sessionId)); - ConnectionServer::sendToCentralProcess(dropDuplicateConnections); + if (!loginOK) { + disconnect(); + return; } } + m_featureBitsGame &= ~ConfigConnectionServer::getDisabledFeatureBits(); + + //Configoption to enable JTL features for beta players so that our code can pretend everything uses the JTL Retail bit + if (ConfigConnectionServer::getSetJtlRetailIfBetaIsSet()) { + if (ClientGameFeature::SpaceExpansionBeta & m_featureBitsGame) { + m_featureBitsGame |= ClientGameFeature::SpaceExpansionRetail; + } + } + + //Configoption to enable Obiwan features for beta players so that our code can pretend everything uses the Obiwan Retail bit + if (ConfigConnectionServer::getSetTrialsOfObiwanRetailIfBetaIsSet()) { + if (ClientGameFeature::TrialsOfObiwanBeta & m_featureBitsGame) { + //-- add retail bit only if player does not have the preorder bit + if ((m_featureBitsGame & ClientGameFeature::TrialsOfObiwanPreorder) == 0) { + m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; + } + } else { + // Clear bits from players who might have them for real, but aren't in the beta + m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanRetail; + m_featureBitsGame &= ~ClientGameFeature::TrialsOfObiwanPreorder; + } + } + + //-- Obiwan Preorders get the Retail bit as well... All rewards etc... + if (ClientGameFeature::TrialsOfObiwanPreorder & m_featureBitsGame) { + m_featureBitsGame |= ClientGameFeature::TrialsOfObiwanRetail; + } + + // Restrictions for "new free trial" account + if (((m_featureBitsSubscription & ClientSubscriptionFeature::FreeTrial2) != 0) && + ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { + // "new free trial" account don't have access to RoW until they convert + m_featureBitsGame &= ~ClientGameFeature::Episode3ExpansionRetail; + m_featureBitsGame &= ~ClientGameFeature::Episode3PreorderDownload; + + // ClientGameFeature::FreeTrial2 indicates this is a converted "new free trial" + // account, and since this account hasn't converted yet, we remove this bit + m_featureBitsGame &= ~ClientGameFeature::FreeTrial2; + } + + // Clear feature bits that only apply if the account is paying (i.e. the sub base bit is set) + if ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0) { + m_featureBitsGame &= ~ClientGameFeature::HousePackupReward; + m_featureBitsGame &= ~ClientGameFeature::BuddyProgramReward; + } + + ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); + ConnectionServer::sendToCentralProcess(vcm); + ConnectionServer::addConnectedClient(m_suid, this); + + uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); + if (requiredSubscriptionBits != 0) { + if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) { + LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); + LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); + disconnect(); + return; + } + } + + uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); + if (requiredGameBits != 0) { + if ((gameFeatures & requiredGameBits) != requiredGameBits) { + LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); + LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); + disconnect(); + return; + } + } + + // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time + GenericValueTypeMessage < std::pair < std::pair < unsigned + long, unsigned + long > , std::pair < int, int32 > > > + const msgFeatureBits( + "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), static_cast(::time(nullptr))))); + send(msgFeatureBits, true); + + std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); + std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); + + LOG("CustomerService", ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount(this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); + + // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account + // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account + if (!m_usingAdminLogin && !m_isSecure) { + GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", std::make_pair(m_suid, m_sessionId)); + ConnectionServer::sendToCentralProcess(dropDuplicateConnections); + } +} + //----------------------------------------------------------------------- - std::string ClientConnection::describeAccount(const ClientConnection *c) { - std::string result = ""; - if (c) { - char idbuf[512] = {"\0"}; - const std::string &sessionId = c->getSessionId(); - if (sessionId.empty()) { - snprintf(idbuf, sizeof(idbuf), " (%lu)", c->m_suid); - } else { - snprintf(idbuf, sizeof(idbuf), " (%lu, %s)", c->m_suid, sessionId.c_str()); - } - - result = c->m_accountName; - result += idbuf; +std::string ClientConnection::describeAccount(const ClientConnection *c) { + std::string result = ""; + if (c) { + char idbuf[512] = {"\0"}; + const std::string &sessionId = c->getSessionId(); + if (sessionId.empty()) { + snprintf(idbuf, sizeof(idbuf), " (%lu)", c->m_suid); + } else { + snprintf(idbuf, sizeof(idbuf), " (%lu, %s)", c->m_suid, sessionId.c_str()); } - return result; + + result = c->m_accountName; + result += idbuf; } + return result; +} // ---------------------------------------------------------------------- - std::vector > const &ClientConnection::getConsumedRewardEvents() const { - return m_consumedRewardEvents; - } +std::vector > const &ClientConnection::getConsumedRewardEvents() const { + return m_consumedRewardEvents; +} // ---------------------------------------------------------------------- - std::vector > const &ClientConnection::getClaimedRewardItems() const { - return m_claimedRewardItems; - } +std::vector > const &ClientConnection::getClaimedRewardItems() const { + return m_claimedRewardItems; +} // ---------------------------------------------------------------------- - bool ClientConnection::isUsingAdminLogin() const { - return m_usingAdminLogin; - } +bool ClientConnection::isUsingAdminLogin() const { + return m_usingAdminLogin; +} // ---------------------------------------------------------------------- - int ClientConnection::getBuddyPoints() const { - return m_buddyPoints; - } +int ClientConnection::getBuddyPoints() const { + return m_buddyPoints; +} // ====================================================================== From b9162a27b6cd0e63280d40993af529877e082f59 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 10:36:56 +0000 Subject: [PATCH 17/55] keep orig length --- .../3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h b/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h index fa6e214d..aaa9d668 100755 --- a/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h +++ b/external/3rd/library/platform/projects/Session/CommonAPI/CommonAPI.h @@ -306,7 +306,7 @@ class apiSubscription unsigned mParentalLimitSeconds; }; -static const int apiSessionIdWidth = 45; +static const int apiSessionIdWidth = 17; struct apiSession_v1; class apiSession { From fb57bdb8d326086d5754a7303affaf82a7277ea5 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 05:08:37 -0600 Subject: [PATCH 18/55] more debug messages --- .../ConnectionServer/src/shared/ClientConnection.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 6b223ef4..20eb2ac2 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -292,6 +292,8 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { result = ConnectionServer::decryptToken(token, sessionId, m_requestedSuid); } + WARNING(true, ("suid is %lu session is %s", m_suid, sessionId)); + static const std::string sessURL(ConfigConnectionServer::getSessionURL()); if (result) { if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { @@ -377,6 +379,8 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, ConfigConnectionServer::getDefaultGameFeatures(), ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, ConfigConnectionServer::getFakeBuddyPoints()); } } else { + WARNING(true, ("Epic fail")); + // They sent us a token that was no good -- either a hack attempt, or // possibly it was just too old. LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); From 019affa0360d0236c34a90284d8212c1c8c31e87 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 05:17:17 -0600 Subject: [PATCH 19/55] this may actually fix it --- .../ConnectionServer/src/shared/ClientConnection.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 20eb2ac2..eae3be68 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -295,7 +295,8 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { WARNING(true, ("suid is %lu session is %s", m_suid, sessionId)); static const std::string sessURL(ConfigConnectionServer::getSessionURL()); - if (result) { + + if (result || sessionId) { if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { bool cont = false; StationId apiSuid = 0; @@ -316,8 +317,10 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { std::string apiUser = api.getString("user_name"); std::string apiIP = api.getString("ip"); - if (expired == 0) { - if (apiSuid == m_suid && apiIP == clientIP) { + if (apiIP == clientIP && expired == 0) { + if (m_suid == 0) { + m_suid = apiSuid; + cont = true; } } From 86f4848dee8c386b009ac4d07a26effc49449507 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 05:18:53 -0600 Subject: [PATCH 20/55] correct this --- .../ConnectionServer/src/shared/ClientConnection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index eae3be68..9775cca3 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -296,7 +296,7 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { static const std::string sessURL(ConfigConnectionServer::getSessionURL()); - if (result || sessionId) { + if (result || sessionId != '\0') { if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { bool cont = false; StationId apiSuid = 0; From ba7858389ae128d9ca1bf75847b2dd1059d55b8b Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 11:55:38 +0000 Subject: [PATCH 21/55] remove debug output --- .../src/shared/ClientConnection.cpp | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 9775cca3..0151f093 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -292,20 +292,21 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { result = ConnectionServer::decryptToken(token, sessionId, m_requestedSuid); } - WARNING(true, ("suid is %lu session is %s", m_suid, sessionId)); + DEBUG_WARNING(true, ("ConnectionServer::handleClientIdMEssage - suid is %lu session is %s", m_suid, sessionId)); static const std::string sessURL(ConfigConnectionServer::getSessionURL()); - if (result || sessionId != '\0') { - if (ConfigConnectionServer::getValidateStationKey() && !sessURL.empty()) { + if (result || (*sessionId) != '\0') { + if (ConfigConnectionServer::getValidateStationKey()) { bool cont = false; StationId apiSuid = 0; + const std::string clientIP = getRemoteAddress(); + const std::string sess = sessionId; - webAPI api(sessURL); - std::string clientIP = getRemoteAddress(); + webAPI api(sessURL); // add our data - api.addJsonData("session_key", std::string(sessionId)); + api.addJsonData("session_key", sess); api.addJsonData("ip", clientIP); if (api.submit()) { @@ -316,16 +317,13 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { int expired = api.getNullableValue("expired"); std::string apiUser = api.getString("user_name"); std::string apiIP = api.getString("ip"); - - if (apiIP == clientIP && expired == 0) { - if (m_suid == 0) { - m_suid = apiSuid; - - cont = true; - } + + if (apiIP == clientIP && expired == 0) { + m_suid = apiSuid; + cont = true; } } - } + } if (!cont) { LOG("ClientDisconnect", ("SUID %d (%d) passed a bad token to the connections erver. Disconnecting.", m_suid, apiSuid)); @@ -382,11 +380,11 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, ConfigConnectionServer::getDefaultGameFeatures(), ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, ConfigConnectionServer::getFakeBuddyPoints()); } } else { - WARNING(true, ("Epic fail")); + WARNING(true, ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); // They sent us a token that was no good -- either a hack attempt, or // possibly it was just too old. - LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections erver. Disconnecting.", m_suid)); + LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); disconnect(); } } From 1383b6db6b7c4bef0bf6b70bfe6023e187871de7 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 05:56:45 -0600 Subject: [PATCH 22/55] autoformat --- .../src/shared/ClientConnection.cpp | 10 +- .../src/shared/ConnectionServer.cpp | 2234 ++++++------- .../src/shared/ClientConnection.cpp | 66 +- .../LoginServer/src/shared/LoginServer.cpp | 2896 ++++++++--------- 4 files changed, 2404 insertions(+), 2802 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 0151f093..e4090172 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -301,9 +301,9 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { bool cont = false; StationId apiSuid = 0; const std::string clientIP = getRemoteAddress(); - const std::string sess = sessionId; + const std::string sess = sessionId; - webAPI api(sessURL); + webAPI api(sessURL); // add our data api.addJsonData("session_key", sess); @@ -317,13 +317,13 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { int expired = api.getNullableValue("expired"); std::string apiUser = api.getString("user_name"); std::string apiIP = api.getString("ip"); - - if (apiIP == clientIP && expired == 0) { + + if (apiIP == clientIP && expired == 0) { m_suid = apiSuid; cont = true; } } - } + } if (!cont) { LOG("ClientDisconnect", ("SUID %d (%d) passed a bad token to the connections erver. Disconnecting.", m_suid, apiSuid)); diff --git a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp index 18a42389..7e7f5783 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp @@ -57,107 +57,85 @@ #include "sharedFoundation/CrcConstexpr.hpp" // ====================================================================== -namespace ConnectionServerNamespace -{ - ConnectionServer * s_connectionServer = 0; - NetworkSetupData * s_clientServiceSetup = 0; +namespace ConnectionServerNamespace { + ConnectionServer *s_connectionServer = 0; + NetworkSetupData *s_clientServiceSetup = 0; - const std::string SCENE_NAME_TUTORIAL = "tutorial"; - const std::string SCENE_NAME_FALCON_PREFIX = "space_npe_falcon"; + const std::string SCENE_NAME_TUTORIAL = "tutorial"; + const std::string SCENE_NAME_FALCON_PREFIX = "space_npe_falcon"; }; using namespace ConnectionServerNamespace; // ====================================================================== -ConnectionServer & ConnectionServer::instance() -{ - return *s_connectionServer; +ConnectionServer &ConnectionServer::instance() { + return *s_connectionServer; } //----------------------------------------------------------------------- -ConnectionServer::ConnectionServer() : - MessageDispatch::Receiver(), - chatService(0), - customerService(0), - clientServicePrivate(0), - clientServicePublic(0), - gameService(0), - loginServerKeys(0), - done(false), - m_id(0), - m_metricsData(0), - centralConnection(0), - chatServers(), - customerServiceServers(), - clientMap(), - connectedMap(), - gameServerMap(), - freeTrials(), - networkBarrier(0), - pingSocket(new UdpSock), - m_recoverTime(0), - m_pingTrafficNumBytes(0), - m_recoveringClientList() -{ - if (s_clientServiceSetup == 0) - s_clientServiceSetup = new NetworkSetupData; +ConnectionServer::ConnectionServer() + : MessageDispatch::Receiver(), chatService(0), customerService(0), clientServicePrivate(0), + clientServicePublic(0), gameService(0), loginServerKeys(0), done(false), m_id(0), m_metricsData(0), + centralConnection(0), chatServers(), customerServiceServers(), clientMap(), connectedMap(), gameServerMap(), + freeTrials(), networkBarrier(0), pingSocket(new UdpSock), m_recoverTime(0), m_pingTrafficNumBytes(0), + m_recoveringClientList() { + if (s_clientServiceSetup == 0) { + s_clientServiceSetup = new NetworkSetupData; + } - s_clientServiceSetup->maxOutstandingPackets = ConfigConnectionServer::getClientMaxOutstandingPackets(); - s_clientServiceSetup->maxRawPacketSize = ConfigConnectionServer::getClientMaxRawPacketSize(); - s_clientServiceSetup->maxConnections = ConfigConnectionServer::getClientMaxConnections(); - s_clientServiceSetup->fragmentSize = ConfigConnectionServer::getClientFragmentSize(); - s_clientServiceSetup->maxDataHoldTime = ConfigConnectionServer::getClientMaxDataHoldTime(); - s_clientServiceSetup->hashTableSize = ConfigConnectionServer::getClientHashTableSize(); - s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPublic(); - s_clientServiceSetup->maxConnectionsPerIP = ConfigConnectionServer::getMaxConnectionsPerIP(); - s_clientServiceSetup->compress = ConfigConnectionServer::getCompressClientNetworkTraffic(); - s_clientServiceSetup->useTcp = false; + s_clientServiceSetup->maxOutstandingPackets = ConfigConnectionServer::getClientMaxOutstandingPackets(); + s_clientServiceSetup->maxRawPacketSize = ConfigConnectionServer::getClientMaxRawPacketSize(); + s_clientServiceSetup->maxConnections = ConfigConnectionServer::getClientMaxConnections(); + s_clientServiceSetup->fragmentSize = ConfigConnectionServer::getClientFragmentSize(); + s_clientServiceSetup->maxDataHoldTime = ConfigConnectionServer::getClientMaxDataHoldTime(); + s_clientServiceSetup->hashTableSize = ConfigConnectionServer::getClientHashTableSize(); + s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPublic(); + s_clientServiceSetup->maxConnectionsPerIP = ConfigConnectionServer::getMaxConnectionsPerIP(); + s_clientServiceSetup->compress = ConfigConnectionServer::getCompressClientNetworkTraffic(); + s_clientServiceSetup->useTcp = false; - loginServerKeys = new KeyServer(20); + loginServerKeys = new KeyServer(20); - Address a("", ConfigConnectionServer::getPingPort()); - IGNORE_RETURN(pingSocket->bind(a)); + Address a("", ConfigConnectionServer::getPingPort()); + IGNORE_RETURN(pingSocket->bind(a)); } //----------------------------------------------------------------------- -ConnectionServer::~ConnectionServer() -{ - delete pingSocket; - pingSocket = 0; +ConnectionServer::~ConnectionServer() { + delete pingSocket; + pingSocket = 0; - delete loginServerKeys; - loginServerKeys = 0; + delete loginServerKeys; + loginServerKeys = 0; - centralConnection = 0; + centralConnection = 0; - chatServers.clear(); + chatServers.clear(); - customerServiceServers.clear(); + customerServiceServers.clear(); - connectedMap.clear(); + connectedMap.clear(); - clientServicePublic = 0; - clientServicePrivate = 0; - chatService = 0; - customerService = 0; - gameService = 0; - gameServerMap.clear(); - freeTrials.clear(); - delete s_clientServiceSetup; + clientServicePublic = 0; + clientServicePrivate = 0; + chatService = 0; + customerService = 0; + gameService = 0; + gameServerMap.clear(); + freeTrials.clear(); + delete s_clientServiceSetup; } //----------------------------------------------------------------------- -const CustomerServiceConnection * ConnectionServer::getCustomerServiceConnection() -{ - if (!instance().customerServiceServers.empty()) - { - return (*(instance().customerServiceServers.begin())); - } - return nullptr; +const CustomerServiceConnection *ConnectionServer::getCustomerServiceConnection() { + if (!instance().customerServiceServers.empty()) { + return (*(instance().customerServiceServers.begin())); + } + return nullptr; } //----------------------------------------------------------------------- @@ -167,239 +145,223 @@ const CustomerServiceConnection * ConnectionServer::getCustomerServiceConnection // be waiting on a different gameserver, or they could be in the process // of being validated -void ConnectionServer::addGameConnection(unsigned long gameServerId, GameConnection* gc) -{ - static ConnectionServer & cs = instance(); +void ConnectionServer::addGameConnection(unsigned long gameServerId, GameConnection *gc) { + static ConnectionServer &cs = instance(); - cs.gameServerMap[gameServerId] = gc;//@todo check for dupe - // find characters pending for THIS gameserver - SuidMap::iterator i; - for (i = cs.connectedMap.begin(); i != cs.connectedMap.end(); ++i) - { - ClientConnection * c = (*i).second; - if (!c->getHasBeenSentToGameServer()) - IGNORE_RETURN(c->sendToGameServer()); - } + cs.gameServerMap[gameServerId] = gc;//@todo check for dupe + // find characters pending for THIS gameserver + SuidMap::iterator i; + for (i = cs.connectedMap.begin(); i != cs.connectedMap.end(); ++i) { + ClientConnection *c = (*i).second; + if (!c->getHasBeenSentToGameServer()) { + IGNORE_RETURN(c->sendToGameServer()); + } + } } //----------------------------------------------------------------------- -bool ConnectionServer::decryptToken(const KeyShare::Token & token, uint32 & stationUserId, bool & secure, std::string & accountName) -{ - static ConnectionServer & cs = instance(); +bool +ConnectionServer::decryptToken(const KeyShare::Token &token, uint32 &stationUserId, bool &secure, std::string &accountName) { + static ConnectionServer &cs = instance(); - //Also the sizeof(int) is likewise magic from the session api - uint32 len = sizeof(uint32) + sizeof(bool) + MAX_ACCOUNT_NAME_LENGTH + 1; - unsigned char * keyBuffer = new unsigned char[len]; - unsigned char * keyBufferPointer = keyBuffer; - memset(keyBuffer, 0, len); + //Also the sizeof(int) is likewise magic from the session api + uint32 len = sizeof(uint32) + sizeof(bool) + MAX_ACCOUNT_NAME_LENGTH + 1; + unsigned char *keyBuffer = new unsigned char[len]; + unsigned char *keyBufferPointer = keyBuffer; + memset(keyBuffer, 0, len); - bool retval = cs.loginServerKeys->decipherToken(token, keyBuffer, len); + bool retval = cs.loginServerKeys->decipherToken(token, keyBuffer, len); - if (!retval) - return retval; + if (!retval) { + return retval; + } - char *tmpBuffer = new char[MAX_ACCOUNT_NAME_LENGTH + 1]; - memset(tmpBuffer, 0, MAX_ACCOUNT_NAME_LENGTH + 1); + char *tmpBuffer = new char[MAX_ACCOUNT_NAME_LENGTH + 1]; + memset(tmpBuffer, 0, MAX_ACCOUNT_NAME_LENGTH + 1); - memcpy(&stationUserId, keyBufferPointer, sizeof(uint32)); - keyBufferPointer += sizeof(uint32); - memcpy(&secure, keyBufferPointer, sizeof(bool)); - keyBufferPointer += sizeof(bool); - memcpy(tmpBuffer, keyBufferPointer, MAX_ACCOUNT_NAME_LENGTH); - accountName = tmpBuffer; - delete[] tmpBuffer; - delete[] keyBuffer; - return retval; + memcpy(&stationUserId, keyBufferPointer, sizeof(uint32)); + keyBufferPointer += sizeof(uint32); + memcpy(&secure, keyBufferPointer, sizeof(bool)); + keyBufferPointer += sizeof(bool); + memcpy(tmpBuffer, keyBufferPointer, MAX_ACCOUNT_NAME_LENGTH); + accountName = tmpBuffer; + delete[] tmpBuffer; + delete[] keyBuffer; + return retval; } -bool ConnectionServer::decryptToken(const KeyShare::Token & token, char* sessionKey, StationId & stationId) -{ - static ConnectionServer & cs = instance(); +bool ConnectionServer::decryptToken(const KeyShare::Token &token, char *sessionKey, StationId &stationId) { + static ConnectionServer &cs = instance(); - uint32 len = apiSessionIdWidth + sizeof(StationId); - unsigned char * keyBuffer = new unsigned char[len + 1]; - unsigned char * keyBufferPointer = keyBuffer; - memset(keyBuffer, 0, sizeof(*keyBuffer)); + uint32 len = apiSessionIdWidth + sizeof(StationId); + unsigned char *keyBuffer = new unsigned char[len + 1]; + unsigned char *keyBufferPointer = keyBuffer; + memset(keyBuffer, 0, sizeof(*keyBuffer)); - bool retval = cs.loginServerKeys->decipherToken(token, keyBuffer, len); + bool retval = cs.loginServerKeys->decipherToken(token, keyBuffer, len); - if (!retval) - return retval; + if (!retval) { + return retval; + } - memcpy(sessionKey, keyBufferPointer, len); - keyBufferPointer += apiSessionIdWidth; - memcpy(&stationId, keyBufferPointer, sizeof(StationId)); - delete[] keyBuffer; - return retval; + memcpy(sessionKey, keyBufferPointer, len); + keyBufferPointer += apiSessionIdWidth; + memcpy(&stationId, keyBufferPointer, sizeof(StationId)); + delete[] keyBuffer; + return retval; } //----------------------------------------------------------------------- -const Service * ConnectionServer::getChatService() -{ - static ConnectionServer & cs = instance(); - return cs.chatService; +const Service *ConnectionServer::getChatService() { + static ConnectionServer &cs = instance(); + return cs.chatService; } //----------------------------------------------------------------------- -const Service * ConnectionServer::getCustomerService() -{ - static ConnectionServer & cs = instance(); - return cs.customerService; +const Service *ConnectionServer::getCustomerService() { + static ConnectionServer &cs = instance(); + return cs.customerService; } //----------------------------------------------------------------------- -Service * ConnectionServer::getClientServicePrivate() -{ - static ConnectionServer & cs = instance(); - return cs.clientServicePrivate; +Service *ConnectionServer::getClientServicePrivate() { + static ConnectionServer &cs = instance(); + return cs.clientServicePrivate; } //----------------------------------------------------------------------- -Service * ConnectionServer::getClientServicePublic() -{ - static ConnectionServer & cs = instance(); - return cs.clientServicePublic; +Service *ConnectionServer::getClientServicePublic() { + static ConnectionServer &cs = instance(); + return cs.clientServicePublic; } //----------------------------------------------------------------------- -KeyShare::Token ConnectionServer::makeToken(const unsigned char * newData, const uint32 dataLen) -{ - static ConnectionServer & cs = instance(); - return cs.loginServerKeys->makeToken(newData, dataLen); +KeyShare::Token ConnectionServer::makeToken(const unsigned char *newData, const uint32 dataLen) { + static ConnectionServer &cs = instance(); + return cs.loginServerKeys->makeToken(newData, dataLen); } //----------------------------------------------------------------------- -void ConnectionServer::pushKey(const KeyShare::Key & newKey) -{ - static ConnectionServer & cs = instance(); - cs.loginServerKeys->pushKey(newKey); +void ConnectionServer::pushKey(const KeyShare::Key &newKey) { + static ConnectionServer &cs = instance(); + cs.loginServerKeys->pushKey(newKey); } //----------------------------------------------------------------------- -void ConnectionServer::addNewClient(ClientConnection* cconn, const NetworkId &oid, GameConnection* gconn, const std::string &, bool sendToStarport) -{ - static ConnectionServer & cs = instance(); - ClientMap::iterator i = cs.clientMap.find(oid); - if (i != cs.clientMap.end()) - { - if (cconn->getClient()) - { - WARNING_STRICT_FATAL(true, ("Client already connected, attempting to drop old one\n")); - dropClient(cconn, "Duplicate Login"); - return; - } - else - { - // stale connection in map - cs.removeFromClientMap(oid); - } - } +void +ConnectionServer::addNewClient(ClientConnection *cconn, const NetworkId &oid, GameConnection *gconn, const std::string &, bool sendToStarport) { + static ConnectionServer &cs = instance(); + ClientMap::iterator i = cs.clientMap.find(oid); + if (i != cs.clientMap.end()) { + if (cconn->getClient()) { + WARNING_STRICT_FATAL(true, ("Client already connected, attempting to drop old one\n")); + dropClient(cconn, "Duplicate Login"); + return; + } else { + // stale connection in map + cs.removeFromClientMap(oid); + } + } - // Create a new entry in the client map - cs.addToClientMap(oid, cconn); + // Create a new entry in the client map + cs.addToClientMap(oid, cconn); - // Get the client that was just created - Client * newClient = cs.getClient(oid); - NOT_NULL(newClient); + // Get the client that was just created + Client *newClient = cs.getClient(oid); + NOT_NULL(newClient); - // select a chat server connection for the client - // if non exists, then the client will be notified when - // one starts - if (!cs.chatServers.empty()) - { - //ChatServerConnection * c = (*chatServers.begin()); - // find chat server with least load - size_t max = 0xFFFFFFFF; - ChatServerConnection * candidate = 0; - std::set::const_iterator iter; - for (iter = cs.chatServers.begin(); iter != cs.chatServers.end(); ++iter) - { - if ((*iter)->getClients().size() <= max) - { - candidate = (*iter); - max = (*iter)->getClients().size(); - } - } - if (candidate) - newClient->setChatConnection(candidate); - } + // select a chat server connection for the client + // if non exists, then the client will be notified when + // one starts + if (!cs.chatServers.empty()) { + //ChatServerConnection * c = (*chatServers.begin()); + // find chat server with least load + size_t max = 0xFFFFFFFF; + ChatServerConnection *candidate = 0; + std::set::const_iterator iter; + for (iter = cs.chatServers.begin(); iter != cs.chatServers.end(); ++iter) { + if ((*iter)->getClients().size() <= max) { + candidate = (*iter); + max = (*iter)->getClients().size(); + } + } + if (candidate) { + newClient->setChatConnection(candidate); + } + } - // select a cs server connection for the client - // if non exists, then the client will be notified when - // one starts - if (!cs.customerServiceServers.empty()) - { - //ChatServerConnection * c = (*chatServers.begin()); - // find chat server with least load - size_t max = 0xFFFFFFFF; - CustomerServiceConnection * candidate = 0; - std::set::const_iterator iter; - for (iter = cs.customerServiceServers.begin(); iter != cs.customerServiceServers.end(); ++iter) - { - if ((*iter)->getClients().size() <= max) - { - candidate = (*iter); - max = (*iter)->getClients().size(); - } - } - if (candidate) - newClient->setCustomerServiceConnection(candidate); - } + // select a cs server connection for the client + // if non exists, then the client will be notified when + // one starts + if (!cs.customerServiceServers.empty()) { + //ChatServerConnection * c = (*chatServers.begin()); + // find chat server with least load + size_t max = 0xFFFFFFFF; + CustomerServiceConnection *candidate = 0; + std::set::const_iterator iter; + for (iter = cs.customerServiceServers.begin(); iter != cs.customerServiceServers.end(); ++iter) { + if ((*iter)->getClients().size() <= max) { + candidate = (*iter); + max = (*iter)->getClients().size(); + } + } + if (candidate) { + newClient->setCustomerServiceConnection(candidate); + } + } - //send the game server a message about this client. - static const std::string loginTrace("TRACE_LOGIN"); - LOG(loginTrace, ("NewClient(%d, %s, %s)", cconn->getSUID(), oid.getValueString().c_str(), cconn->getAccountName().c_str())); - NewClient m(oid, cconn->getAccountName(), cconn->getRemoteAddress(), cconn->getIsSecure(), false, cconn->getSUID(), nullptr, cconn->getGameFeatures(), cconn->getSubscriptionFeatures(), cconn->getEntitlementTotalTime(), cconn->getEntitlementEntitledTime(), cconn->getEntitlementTotalTimeSinceLastLogin(), cconn->getEntitlementEntitledTimeSinceLastLogin(), cconn->getBuddyPoints(), cconn->getConsumedRewardEvents(), cconn->getClaimedRewardItems(), cconn->isUsingAdminLogin(), cconn->getCanSkipTutorial(), sendToStarport); - gconn->send(m, true); - //@todo move this to ClientConnection.cpp + //send the game server a message about this client. + static const std::string loginTrace("TRACE_LOGIN"); + LOG(loginTrace, ("NewClient(%d, %s, %s)", cconn->getSUID(), oid.getValueString().c_str(), cconn->getAccountName().c_str())); + NewClient m(oid, cconn->getAccountName(), cconn->getRemoteAddress(), cconn->getIsSecure(), false, cconn->getSUID(), nullptr, cconn->getGameFeatures(), cconn->getSubscriptionFeatures(), cconn->getEntitlementTotalTime(), cconn->getEntitlementEntitledTime(), cconn->getEntitlementTotalTimeSinceLastLogin(), cconn->getEntitlementEntitledTimeSinceLastLogin(), cconn->getBuddyPoints(), cconn->getConsumedRewardEvents(), cconn->getClaimedRewardItems(), cconn->isUsingAdminLogin(), cconn->getCanSkipTutorial(), sendToStarport); + gconn->send(m, true); + //@todo move this to ClientConnection.cpp } //----------------------------------------------------------------------- -void ConnectionServer::dropClient(ClientConnection * conn, const std::string& description) -{ - DEBUG_FATAL(!conn, ("Cannot call dropClient with nullptr connection")); - if (!conn) //lint !e774 // boolean within 'if' always evaluates to False //suppresed because this is only relevant in DEBUG builds - return; +void ConnectionServer::dropClient(ClientConnection *conn, const std::string &description) { + DEBUG_FATAL(!conn, ("Cannot call dropClient with nullptr connection")); + if (!conn) { //lint !e774 // boolean within 'if' always evaluates to False //suppresed because this is only relevant in DEBUG builds + return; + } - static ConnectionServer & cs = instance(); - //Client dropped. Tell game server if they've logged in. - LOG("ClientDisconnect", ("Dropping client for SUID %d\n", conn->getSUID())); - LOG("CustomerService", ("Login:%s Dropped Reason: %s. Character: %s (%s). Play time: %s. Active play time: %s", ClientConnection::describeAccount(conn).c_str(), description.c_str(), conn->getCharacterName().c_str(), conn->getCharacterId().getValueString().c_str(), conn->getPlayTimeDuration().c_str(), conn->getActivePlayTimeDuration().c_str())); + static ConnectionServer &cs = instance(); + //Client dropped. Tell game server if they've logged in. + LOG("ClientDisconnect", ("Dropping client for SUID %d\n", conn->getSUID())); + LOG("CustomerService", ("Login:%s Dropped Reason: %s. Character: %s (%s). Play time: %s. Active play time: %s", ClientConnection::describeAccount(conn).c_str(), description.c_str(), conn->getCharacterName().c_str(), conn->getCharacterId().getValueString().c_str(), conn->getPlayTimeDuration().c_str(), conn->getActivePlayTimeDuration().c_str())); - Client *client = conn->getClient(); - if (client) - { - DropClient msg(client->getNetworkId()); - GameConnection* gconn = client->getGameConnection(); - //Don't worry about sending a message to a non-existant game server - if (gconn) - gconn->send(msg, true); - else - DEBUG_REPORT_LOG(true, ("Could not find game server to drop this client\n")); + Client *client = conn->getClient(); + if (client) { + DropClient msg(client->getNetworkId()); + GameConnection *gconn = client->getGameConnection(); + //Don't worry about sending a message to a non-existant game server + if (gconn) { + gconn->send(msg, true); + } else { + DEBUG_REPORT_LOG(true, ("Could not find game server to drop this client\n")); + } - // Remove the entry from the client map - cs.removeFromClientMap(client->getNetworkId()); - } - else - { - //If they aren't connected to the game yet, they're probably on the pending list. - //@todo ensure we don't need to send a cleanup message to central + // Remove the entry from the client map + cs.removeFromClientMap(client->getNetworkId()); + } else { + //If they aren't connected to the game yet, they're probably on the pending list. + //@todo ensure we don't need to send a cleanup message to central // removePendingCharacter(conn->getSUID()); - } + } - // Remove entry from the connected map - cs.removeFromConnectedMap(conn->getSUID()); + // Remove entry from the connected map + cs.removeFromConnectedMap(conn->getSUID()); - conn->disconnect(); + conn->disconnect(); } //----------------------------------------------------------------------- @@ -416,708 +378,629 @@ void ConnectionServer::dropClient(ClientConnection * conn, const std::string& de //----------------------------------------------------------------------- -void ConnectionServer::addConnectedClient(uint32 suid, ClientConnection* conn) -{ - static ConnectionServer & cs = instance(); - cs.addToConnectedMap(suid, conn); +void ConnectionServer::addConnectedClient(uint32 suid, ClientConnection *conn) { + static ConnectionServer &cs = instance(); + cs.addToConnectedMap(suid, conn); } //----------------------------------------------------------------------- -ClientConnection* ConnectionServer::getClientConnection(const uint32 suid) -{ - static ConnectionServer & cs = instance(); - ClientConnection * result = 0; - SuidMap::const_iterator i = cs.connectedMap.find(suid); - if (i != cs.connectedMap.end()) - { - result = (*i).second; - } - return result; +ClientConnection *ConnectionServer::getClientConnection(const uint32 suid) { + static ConnectionServer &cs = instance(); + ClientConnection *result = 0; + SuidMap::const_iterator i = cs.connectedMap.find(suid); + if (i != cs.connectedMap.end()) { + result = (*i).second; + } + return result; } // ---------------------------------------------------------------------- -const Service * ConnectionServer::getGameService() -{ - static ConnectionServer & cs = instance(); - return cs.gameService; +const Service *ConnectionServer::getGameService() { + static ConnectionServer &cs = instance(); + return cs.gameService; } // ---------------------------------------------------------------------- -GameConnection* ConnectionServer::getGameConnection(const std::string &sceneName) -{ - static ConnectionServer & cs = instance(); - GameServerMap::iterator i = cs.gameServerMap.begin(); - for (; i != cs.gameServerMap.end(); ++i) - { - if (sceneName == (*i).second->getSceneName()) - { - return (*i).second; - } - } - return nullptr; +GameConnection *ConnectionServer::getGameConnection(const std::string &sceneName) { + static ConnectionServer &cs = instance(); + GameServerMap::iterator i = cs.gameServerMap.begin(); + for (; i != cs.gameServerMap.end(); ++i) { + if (sceneName == (*i).second->getSceneName()) { + return (*i).second; + } + } + return nullptr; } // ---------------------------------------------------------------------- -void ConnectionServer::handleConnectionServerIdMessage(const ConnectionServerId & m) -{ - // Connection established with central server. Set everything up. - m_id = m.getId(); +void ConnectionServer::handleConnectionServerIdMessage(const ConnectionServerId &m) { + // Connection established with central server. Set everything up. + m_id = m.getId(); - const Service * const servicePrivate = getClientServicePrivate(); - const Service * const servicePublic = getClientServicePublic(); - FATAL(servicePrivate == nullptr && servicePublic == nullptr, ("No client service is active!")); + const Service *const servicePrivate = getClientServicePrivate(); + const Service *const servicePublic = getClientServicePublic(); + FATAL(servicePrivate == nullptr && servicePublic == nullptr, ("No client service is active!")); - const Service * const g = getGameService(); - FATAL(g == nullptr, ("No game service is active!")); - const Service * const c = getChatService(); - const Service * const cs = getCustomerService(); - const uint16 pingPort = getPingPort(); + const Service *const g = getGameService(); + FATAL(g == nullptr, ("No game service is active!")); + const Service *const c = getChatService(); + const Service *const cs = getCustomerService(); + const uint16 pingPort = getPingPort(); - if ((servicePrivate != nullptr || servicePublic != nullptr) && g != nullptr) //lint !e774 // always evaluates to false // suppresed because the FATAL macro triggers this lint warning - { - uint16 chatPort = 0; - uint16 csPort = 0; - if (c) - { - chatPort = c->getBindPort(); - } + if ((servicePrivate != nullptr || servicePublic != nullptr) && g != + nullptr) //lint !e774 // always evaluates to false // suppresed because the FATAL macro triggers this lint warning + { + uint16 chatPort = 0; + uint16 csPort = 0; + if (c) { + chatPort = c->getBindPort(); + } - if (cs) - { - csPort = cs->getBindPort(); - } + if (cs) { + csPort = cs->getBindPort(); + } - uint16 publicPort = 0; - if (servicePublic) - { - publicPort = servicePublic->getBindPort(); - } + uint16 publicPort = 0; + if (servicePublic) { + publicPort = servicePublic->getBindPort(); + } - uint16 privatePort = 0; - if (servicePrivate) - { - privatePort = servicePrivate->getBindPort(); - } + uint16 privatePort = 0; + if (servicePrivate) { + privatePort = servicePrivate->getBindPort(); + } - std::string clientServicePublicBindAddress = ConfigConnectionServer::getPublicBindAddress(); - if (clientServicePublicBindAddress.empty()) - { - clientServicePublicBindAddress = NetworkHandler::getHostName(); - } + std::string clientServicePublicBindAddress = ConfigConnectionServer::getPublicBindAddress(); + if (clientServicePublicBindAddress.empty()) { + clientServicePublicBindAddress = NetworkHandler::getHostName(); + } - NOT_NULL(gameService); - NOT_NULL(chatService); - NOT_NULL(customerService); + NOT_NULL(gameService); + NOT_NULL(chatService); + NOT_NULL(customerService); - const NewCentralConnectionServer ncs(gameService->getBindAddress(), clientServicePublicBindAddress, chatService->getBindAddress(), customerService->getBindAddress(), privatePort, publicPort, g->getBindPort(), chatPort, csPort, pingPort, ConfigConnectionServer::getConnectionServerNumber()); - sendToCentralProcess(ncs); - } - else - { - FATAL(true, ("Error in connection server startup")); - } + const NewCentralConnectionServer ncs(gameService->getBindAddress(), clientServicePublicBindAddress, chatService->getBindAddress(), customerService->getBindAddress(), privatePort, publicPort, g->getBindPort(), chatPort, csPort, pingPort, ConfigConnectionServer::getConnectionServerNumber()); + sendToCentralProcess(ncs); + } else { + FATAL(true, ("Error in connection server startup")); + } } // ---------------------------------------------------------------------- -void ConnectionServer::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) -{ - // it's reasonably safe to cast, message type verified - // determine message type - - const uint32 messageType = message.getType(); +void +ConnectionServer::receiveMessage(const MessageDispatch::Emitter &source, const MessageDispatch::MessageBase &message) { + // it's reasonably safe to cast, message type verified + // determine message type - switch(messageType) { - case constcrc("GameConnectionOpened") : - { - DEBUG_REPORT_LOG(true, ("Game Connection opened\n")); - break; - } - case constcrc("GameConnectionClosed") : - { - //@todo handle case where game server drops and we have users connected to it. - //Drop all connected clients. - const GameConnection & downConnection = static_cast(source); - DEBUG_REPORT_LOG(true, ("Game Server connection went down. Dropping clients.\n")); - //remove Game Conection from list + const uint32 messageType = message.getType(); - PseudoClientConnection::gameConnectionClosed(&downConnection); + switch (messageType) { + case constcrc("GameConnectionOpened") : { + DEBUG_REPORT_LOG(true, ("Game Connection opened\n")); + break; + } + case constcrc("GameConnectionClosed") : { + //@todo handle case where game server drops and we have users connected to it. + //Drop all connected clients. + const GameConnection &downConnection = static_cast(source); + DEBUG_REPORT_LOG(true, ("Game Server connection went down. Dropping clients.\n")); + //remove Game Conection from list - GameServerMap::iterator j = gameServerMap.find(downConnection.getGameServerId()); - if (j != gameServerMap.end()) - { - gameServerMap.erase(j); - } - break; - } - case constcrc("CentralConnectionOpened") : - { - DEBUG_REPORT_LOG(true, ("Opened connection with central\n")); - centralConnection = const_cast(static_cast(&source));//lint !e826 // info: Suspiscious pointer-to-pointer conversion (area too small) + PseudoClientConnection::gameConnectionClosed(&downConnection); - if (ConfigConnectionServer::getStartPublicServer()) - { - s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPublic(); - s_clientServiceSetup->maxConnectionsPerIP = ConfigConnectionServer::getMaxConnectionsPerIP(); - clientServicePublic = new Service(ConnectionAllocator(), *s_clientServiceSetup); - } + GameServerMap::iterator j = gameServerMap.find(downConnection.getGameServerId()); + if (j != gameServerMap.end()) { + gameServerMap.erase(j); + } + break; + } + case constcrc("CentralConnectionOpened") : { + DEBUG_REPORT_LOG(true, ("Opened connection with central\n")); + centralConnection = const_cast(static_cast(&source));//lint !e826 // info: Suspiscious pointer-to-pointer conversion (area too small) - s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPrivate(); - s_clientServiceSetup->maxConnectionsPerIP = 0; - clientServicePrivate = new Service(ConnectionAllocator(), *s_clientServiceSetup); + if (ConfigConnectionServer::getStartPublicServer()) { + s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPublic(); + s_clientServiceSetup->maxConnectionsPerIP = ConfigConnectionServer::getMaxConnectionsPerIP(); + clientServicePublic = new Service(ConnectionAllocator(), *s_clientServiceSetup); + } - connectToMessage("ClientConnectionOpened"); - connectToMessage("ClientConnectionClosed"); - break; - } - case constcrc("CentralConnectionClosed") : - { - centralConnection = const_cast(static_cast(&source));//lint !e826 // info: Suspiscious pointer-to-pointer conversion (area too small) - setDone("CentralConnectionClosed: %s", centralConnection ? centralConnection->getDisconnectReason().c_str() : ""); - centralConnection = 0; - DEBUG_REPORT_LOG(true, ("CentralDied. So we will too\n")); - //@todo Drop all pending clients. - break; - } - case constcrc("ClientConnectionOpened") : - { - DEBUG_REPORT_LOG(true, ("Opened connection with client\n")); - break; - } - case constcrc("ClientConnectionClosed") : - { - DEBUG_REPORT_LOG(true, ("Client is Dropping connection\n")); - ClientConnection * cconn = const_cast(static_cast(&source));//lint !e826 // info: Suspiscious pointer-to-pointer conversion (area too small) + s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPrivate(); + s_clientServiceSetup->maxConnectionsPerIP = 0; + clientServicePrivate = new Service(ConnectionAllocator(), *s_clientServiceSetup); - //tell CentralServer - if (centralConnection) - { - GenericValueTypeMessage const msg("ClientConnectionClosed", cconn->getSUID()); - centralConnection->send(msg, true); - } + connectToMessage("ClientConnectionOpened"); + connectToMessage("ClientConnectionClosed"); + break; + } + case constcrc("CentralConnectionClosed") : { + centralConnection = const_cast(static_cast(&source));//lint !e826 // info: Suspiscious pointer-to-pointer conversion (area too small) + setDone("CentralConnectionClosed: %s", centralConnection ? centralConnection->getDisconnectReason().c_str() + : ""); + centralConnection = 0; + DEBUG_REPORT_LOG(true, ("CentralDied. So we will too\n")); + //@todo Drop all pending clients. + break; + } + case constcrc("ClientConnectionOpened") : { + DEBUG_REPORT_LOG(true, ("Opened connection with client\n")); + break; + } + case constcrc("ClientConnectionClosed") : { + DEBUG_REPORT_LOG(true, ("Client is Dropping connection\n")); + ClientConnection *cconn = const_cast(static_cast(&source));//lint !e826 // info: Suspiscious pointer-to-pointer conversion (area too small) - //Client dropped. Tell game server if they've logged in. - Client *client = cconn->getClient(); - if (client) - { - DropClient msg(client->getNetworkId()); - GameConnection* gconn = client->getGameConnection(); - //Don't worry about sending a message to a non-existant game server - if (gconn) - gconn->send(msg, true); + //tell CentralServer + if (centralConnection) { + GenericValueTypeMessage const msg("ClientConnectionClosed", cconn->getSUID()); + centralConnection->send(msg, true); + } - // Remove the entry from the client map - removeFromClientMap(client->getNetworkId()); - } - else - { - // TODO: wtf is this? @Darth, fix it! - //If they aren't connected to the game yet, they're probably on the pending list. - //removePendingCharacter(cconn->getSUID()); - } - removeFromConnectedMap(cconn->getSUID()); - break; - } - case constcrc("ConnectionServerId") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ConnectionServerId m(ri); - handleConnectionServerIdMessage(m); - break; - } - case constcrc("ConnectionKeyPush") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ConnectionKeyPush pk(ri); - loginServerKeys->pushKey(pk.getKey()); - break; - } - case constcrc("LoginKeyPush") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const LoginKeyPush k(ri); - loginServerKeys->pushKey(k.getKey()); - break; - } - case constcrc("CharacterListMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const CharacterListMessage msg(ri); - WARNING_STRICT_FATAL(true, ("CharacterListMessage is deprecated on the ConnectionServer -- fix whoever is sending it.\n")); - break; - } - case constcrc("ConnectionCreateCharacterSuccess") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const ConnectionCreateCharacterSuccess msg(ri); - LOG("TraceCharacterCreation", ("Received ConnectionCreateCharacterSuccess for %d", msg.getStationId())); - ClientConnection* const client = getClientConnection(msg.getStationId()); - if (client) - { - const ClientCreateCharacterSuccess m(msg.getNetworkId()); - client->send(m, true); - } - else - { - LOG("CustomerService", ("CharacterTransfer: Trying to deliver ConnectionCreateCharacterSuccess to PsuedoClientConnection(%d)", msg.getStationId())); - PseudoClientConnection::tryToDeliverMessageTo(static_cast(msg.getStationId()), static_cast(message).getByteStream()); - } - break; - } - case constcrc("ConnectionCreateCharacterFailed") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const ConnectionCreateCharacterFailed msg(ri); - ClientConnection* client = getClientConnection(msg.getStationId()); - if (client) - { - client->setHasRequestedCharacterCreate(false); + //Client dropped. Tell game server if they've logged in. + Client *client = cconn->getClient(); + if (client) { + DropClient msg(client->getNetworkId()); + GameConnection *gconn = client->getGameConnection(); + //Don't worry about sending a message to a non-existant game server + if (gconn) { + gconn->send(msg, true); + } - ClientCreateCharacterFailed m(msg.getName(), msg.getErrorMessage()); //lint !e1013 !e1055 !e746 (Symbol 'getErrorMessage' not a member of class 'const ConnectionCreateCharacterFailed') // supressed because it IS a member of that class. //lint !e1055 //lint !e746 - client->send(m, true); - } - else - { - PseudoClientConnection::tryToDeliverMessageTo(static_cast(msg.getStationId()), static_cast(message).getByteStream()); - } - break; - } - case constcrc("NewCharacterCreated") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const msg(ri); - ClientConnection* client = getClientConnection(msg.getValue()); - if (client) - { - // don't allow this client to request another character create; - // this will forced the client to disconnect and reconnect at which time - // a check will be done (taking the newly created character into account) - // to see if the client is allowed to create another character on this account - client->setHasCreatedCharacter(true); - } - break; - } - case constcrc("RandomNameResponse") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - RandomNameResponse connMsg(ri); + // Remove the entry from the client map + removeFromClientMap(client->getNetworkId()); + } else { + // TODO: wtf is this? @Darth, fix it! + //If they aren't connected to the game yet, they're probably on the pending list. + //removePendingCharacter(cconn->getSUID()); + } + removeFromConnectedMap(cconn->getSUID()); + break; + } + case constcrc("ConnectionServerId") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ConnectionServerId m(ri); + handleConnectionServerIdMessage(m); + break; + } + case constcrc("ConnectionKeyPush") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ConnectionKeyPush pk(ri); + loginServerKeys->pushKey(pk.getKey()); + break; + } + case constcrc("LoginKeyPush") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const LoginKeyPush k(ri); + loginServerKeys->pushKey(k.getKey()); + break; + } + case constcrc("CharacterListMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const CharacterListMessage msg(ri); + WARNING_STRICT_FATAL(true, ("CharacterListMessage is deprecated on the ConnectionServer -- fix whoever is sending it.\n")); + break; + } + case constcrc("ConnectionCreateCharacterSuccess") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const ConnectionCreateCharacterSuccess msg(ri); + LOG("TraceCharacterCreation", ("Received ConnectionCreateCharacterSuccess for %d", msg.getStationId())); + ClientConnection *const client = getClientConnection(msg.getStationId()); + if (client) { + const ClientCreateCharacterSuccess m(msg.getNetworkId()); + client->send(m, true); + } else { + LOG("CustomerService", ("CharacterTransfer: Trying to deliver ConnectionCreateCharacterSuccess to PsuedoClientConnection(%d)", msg.getStationId())); + PseudoClientConnection::tryToDeliverMessageTo(static_cast(msg.getStationId()), static_cast(message).getByteStream()); + } + break; + } + case constcrc("ConnectionCreateCharacterFailed") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const ConnectionCreateCharacterFailed msg(ri); + ClientConnection *client = getClientConnection(msg.getStationId()); + if (client) { + client->setHasRequestedCharacterCreate(false); - ClientConnection* cconn = getClientConnection(connMsg.getStationId()); - ClientRandomNameResponse cnr(connMsg.getCreatureTemplate(), connMsg.getName(), connMsg.getErrorMessage());//lint !e1013 (Symbol 'getErrorMessage' not a member of class 'RandomNameResponse') // supressed because it IS a member of that class. - if (cconn) - cconn->send(cnr, true); - - break; - } - case constcrc("VerifyAndLockNameResponse") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - VerifyAndLockNameResponse connMsg(ri); + ClientCreateCharacterFailed m(msg.getName(), msg.getErrorMessage()); //lint !e1013 !e1055 !e746 (Symbol 'getErrorMessage' not a member of class 'const ConnectionCreateCharacterFailed') // supressed because it IS a member of that class. //lint !e1055 //lint !e746 + client->send(m, true); + } else { + PseudoClientConnection::tryToDeliverMessageTo(static_cast(msg.getStationId()), static_cast(message).getByteStream()); + } + break; + } + case constcrc("NewCharacterCreated") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const msg(ri); + ClientConnection *client = getClientConnection(msg.getValue()); + if (client) { + // don't allow this client to request another character create; + // this will forced the client to disconnect and reconnect at which time + // a check will be done (taking the newly created character into account) + // to see if the client is allowed to create another character on this account + client->setHasCreatedCharacter(true); + } + break; + } + case constcrc("RandomNameResponse") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RandomNameResponse connMsg(ri); - ClientConnection* cconn = getClientConnection(connMsg.getStationId()); - ClientVerifyAndLockNameResponse cvalnr(connMsg.getCharacterName(), connMsg.getErrorMessage()); - if (cconn) - cconn->send(cvalnr, true); - - break; - } - case constcrc("ChatServerConnectionOpened") : - { - ChatServerConnection * c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is - IGNORE_RETURN(chatServers.insert(c)); - break; - } - case constcrc("ChatServerConnectionClosed") : - { - ChatServerConnection * c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is - std::set::iterator f = chatServers.find(c); - if (f != chatServers.end()) - { - // migrate players that were on this chat server - // to another chat server + ClientConnection *cconn = getClientConnection(connMsg.getStationId()); + ClientRandomNameResponse cnr(connMsg.getCreatureTemplate(), connMsg.getName(), connMsg.getErrorMessage());//lint !e1013 (Symbol 'getErrorMessage' not a member of class 'RandomNameResponse') // supressed because it IS a member of that class. + if (cconn) { + cconn->send(cnr, true); + } - // now remove the server from the set - chatServers.erase(f); - if (!chatServers.empty()) - { - std::set::iterator ic = chatServers.begin(); + break; + } + case constcrc("VerifyAndLockNameResponse") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + VerifyAndLockNameResponse connMsg(ri); - const std::set & clients = c->getClients(); - std::set::const_iterator i; - for (i = clients.begin(); i != clients.end(); ++i) - { - ChatServerConnection * newConn = (*ic); - Client * cl = (*i); - cl->setChatConnection(newConn); - ++ic; - if (ic == chatServers.end()) - ic = chatServers.begin(); - } - } - else - { - const std::set & clients = c->getClients(); - std::set::const_iterator i; - for (i = clients.begin(); i != clients.end(); ++i) - { - (*i)->setChatConnection(nullptr); - } - } - } - break; - } - case constcrc("CustomerServiceConnectionOpened") : - { - CustomerServiceConnection * c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is - IGNORE_RETURN(customerServiceServers.insert(c)); - break; - } - case constcrc("CustomerServiceConnectionClosed") : - { - CustomerServiceConnection * c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is - std::set::iterator f = customerServiceServers.find(c); - if (f != customerServiceServers.end()) - { - // migrate players that were on this chat server - // to another chat server + ClientConnection *cconn = getClientConnection(connMsg.getStationId()); + ClientVerifyAndLockNameResponse cvalnr(connMsg.getCharacterName(), connMsg.getErrorMessage()); + if (cconn) { + cconn->send(cvalnr, true); + } - // now remove the server from the set - customerServiceServers.erase(f); - if (!customerServiceServers.empty()) - { - std::set::iterator ic = customerServiceServers.begin(); + break; + } + case constcrc("ChatServerConnectionOpened") : { + ChatServerConnection *c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is + IGNORE_RETURN(chatServers.insert(c)); + break; + } + case constcrc("ChatServerConnectionClosed") : { + ChatServerConnection *c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is + std::set::iterator f = chatServers.find(c); + if (f != chatServers.end()) { + // migrate players that were on this chat server + // to another chat server - const std::set & clients = c->getClients(); - std::set::const_iterator i; - for (i = clients.begin(); i != clients.end(); ++i) - { - CustomerServiceConnection * newConn = (*ic); - Client * cl = (*i); - cl->setCustomerServiceConnection(newConn); - ++ic; - if (ic == customerServiceServers.end()) - ic = customerServiceServers.begin(); - } - } - else - { - const std::set & clients = c->getClients(); - std::set::const_iterator i; - for (i = clients.begin(); i != clients.end(); ++i) - { - (*i)->setCustomerServiceConnection(nullptr); - } - } - } - break; - } - case constcrc("GameServerForLoginMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const GameServerForLoginMessage msg(ri); + // now remove the server from the set + chatServers.erase(f); + if (!chatServers.empty()) { + std::set::iterator ic = chatServers.begin(); - ClientConnection* client = getClientConnection(msg.getStationId()); + const std::set &clients = c->getClients(); + std::set::const_iterator i; + for (i = clients.begin(); i != clients.end(); ++i) { + ChatServerConnection *newConn = (*ic); + Client *cl = (*i); + cl->setChatConnection(newConn); + ++ic; + if (ic == chatServers.end()) { + ic = chatServers.begin(); + } + } + } else { + const std::set &clients = c->getClients(); + std::set::const_iterator i; + for (i = clients.begin(); i != clients.end(); ++i) { + (*i)->setChatConnection(nullptr); + } + } + } + break; + } + case constcrc("CustomerServiceConnectionOpened") : { + CustomerServiceConnection *c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is + IGNORE_RETURN(customerServiceServers.insert(c)); + break; + } + case constcrc("CustomerServiceConnectionClosed") : { + CustomerServiceConnection *c = const_cast(static_cast(&source));//lint !e826 suspiscious pointer-to-pointer conversion // suppressed, you bet it is + std::set::iterator f = customerServiceServers.find(c); + if (f != customerServiceServers.end()) { + // migrate players that were on this chat server + // to another chat server - // see if the client is for the same character as the login message. - // this is required to prevent admin login via the CS Tool from - // disconnecting other characters logged in from the same account - // (but not the same character) as the character we're administratively - // logging in. - bool clientIsForSameCharacterId = false; - if (client) - { - clientIsForSameCharacterId = client->getCharacterId() == msg.getCharacterId(); - } + // now remove the server from the set + customerServiceServers.erase(f); + if (!customerServiceServers.empty()) { + std::set::iterator ic = customerServiceServers.begin(); - bool handledByPseudoClient = false; - // if the character id in the message doesn't match the character id for - // the existing client, it may be for a pseudoclient. Check, and if so, - // handle there. - if (!clientIsForSameCharacterId) - { - PseudoClientConnection * pcc = PseudoClientConnection::getPseudoClientConnection(msg.getCharacterId()); - // hand off to the PCC only if we do have a pseudoclient, and either we don't have a client, or - // the pseudoclient has a tool id, telling us that it's for cs tool login. - if (pcc && ((!client) || (pcc->getTransferCharacterData().getCSToolId() > 0))) - { - handledByPseudoClient = true; - bool result; - result = PseudoClientConnection::tryToDeliverMessageTo(msg.getStationId(), static_cast(message).getByteStream()); - UNREF(result); - DEBUG_REPORT_LOG(!result, ("Received GameServerForLoginMessage for %lu, who was not connected.\n", msg.getStationId())); - } - } + const std::set &clients = c->getClients(); + std::set::const_iterator i; + for (i = clients.begin(); i != clients.end(); ++i) { + CustomerServiceConnection *newConn = (*ic); + Client *cl = (*i); + cl->setCustomerServiceConnection(newConn); + ++ic; + if (ic == customerServiceServers.end()) { + ic = customerServiceServers.begin(); + } + } + } else { + const std::set &clients = c->getClients(); + std::set::const_iterator i; + for (i = clients.begin(); i != clients.end(); ++i) { + (*i)->setCustomerServiceConnection(nullptr); + } + } + } + break; + } + case constcrc("GameServerForLoginMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const GameServerForLoginMessage msg(ri); - if (client && (!handledByPseudoClient)) - { - static const std::string loginTrace("TRACE_LOGIN"); - LOG(loginTrace, ("GameServerForLoginMessage(%d, %s)", client->getSUID(), client->getCharacterId().getValueString().c_str())); - client->handleGameServerForLoginMessage(msg.getServer()); - } - break; - } - case constcrc("ValidateCharacterForLoginReplyMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const ValidateCharacterForLoginReplyMessage msg(ri); + ClientConnection *client = getClientConnection(msg.getStationId()); - ClientConnection* cconn = getClientConnection(msg.getSuid()); - if (!cconn) - DEBUG_REPORT_LOG(true, ("Received ValidateCharacterForLoginReplyMessage for account %lu, which is no longer connected.\n", msg.getSuid())); - else - { - cconn->onCharacterValidated(msg.getApproved(), msg.getCharacterId(), Unicode::wideToNarrow(msg.getCharacterName()), msg.getContainerId(), msg.getScene(), msg.getCoordinates()); - } - break; - } - case constcrc("ValidateAccountReplyMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const ValidateAccountReplyMessage msg(ri); + // see if the client is for the same character as the login message. + // this is required to prevent admin login via the CS Tool from + // disconnecting other characters logged in from the same account + // (but not the same character) as the character we're administratively + // logging in. + bool clientIsForSameCharacterId = false; + if (client) { + clientIsForSameCharacterId = client->getCharacterId() == msg.getCharacterId(); + } - ClientConnection* cconn = getClientConnection(msg.getStationId()); - if (!cconn) - DEBUG_REPORT_LOG(true, ("Received ValidateAccountReplyMessage for account %lu, which is no longer connected.\n", msg.getStationId())); - else - { - cconn->onIdValidated(msg.getCanLogin(), msg.getCanCreateRegular(), msg.getCanCreateJedi(), msg.getCanSkipTutorial(), msg.getConsumedRewardEvents(), msg.getClaimedRewardItems()); - } - break; - } - case constcrc("SetConnectionServerPublic") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - SetConnectionServerPublic p(ri);//lint !e40 !e522 !e10 // Undeclared identifier 'SetConnectionServerPublic' // suppressed because it IS declared - bool statusChanged = false; - DEBUG_REPORT_LOG(true, ("Conn Server: attempting to chang status\n")); - if (p.getIsPublic())//lint !e40 !e1013 !e10 // Undeclared identifier 'p' // suppressed because it IS declared - { - if (!clientServicePublic) - { - statusChanged = true; - } - } - else - { - delete clientServicePublic; - clientServicePublic = 0; - statusChanged = true; - } + bool handledByPseudoClient = false; + // if the character id in the message doesn't match the character id for + // the existing client, it may be for a pseudoclient. Check, and if so, + // handle there. + if (!clientIsForSameCharacterId) { + PseudoClientConnection *pcc = PseudoClientConnection::getPseudoClientConnection(msg.getCharacterId()); + // hand off to the PCC only if we do have a pseudoclient, and either we don't have a client, or + // the pseudoclient has a tool id, telling us that it's for cs tool login. + if (pcc && ((!client) || (pcc->getTransferCharacterData().getCSToolId() > 0))) { + handledByPseudoClient = true; + bool result; + result = PseudoClientConnection::tryToDeliverMessageTo(msg.getStationId(), static_cast(message).getByteStream()); + UNREF(result); + DEBUG_REPORT_LOG(!result, ("Received GameServerForLoginMessage for %lu, who was not connected.\n", msg.getStationId())); + } + } - if (statusChanged && centralConnection) - { - const Service * publicService = getClientServicePublic(); - const Service * privateService = getClientServicePrivate(); - if (publicService || privateService) - { - uint16 publicServicePort = 0; - uint16 privateServicePort = 0; - if (publicService) - { - publicServicePort = publicService->getBindPort(); - } - if (privateService) - { - privateServicePort = privateService->getBindPort(); - } - const UpdateConnectionServerStatus ucs(publicServicePort, privateServicePort); - centralConnection->send(ucs, true); - } - } - break; - }//lint !e529 // Symbol 'ri' not subsequently referenced // suppressed because it IS referenced. I think lint is very confused for some reason. - case constcrc("ProfilerOperationMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ProfilerOperationMessage msg(ri); - unsigned int processId = msg.getProcessId(); - if (!processId) - Profiler::handleOperation(msg.getOperation().c_str()); - - break; - } - case constcrc("ExcommunicateGameServerMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ExcommunicateGameServerMessage msg(ri); + if (client && (!handledByPseudoClient)) { + static const std::string loginTrace("TRACE_LOGIN"); + LOG(loginTrace, ("GameServerForLoginMessage(%d, %s)", client->getSUID(), client->getCharacterId().getValueString().c_str())); + client->handleGameServerForLoginMessage(msg.getServer()); + } + break; + } + case constcrc("ValidateCharacterForLoginReplyMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const ValidateCharacterForLoginReplyMessage msg(ri); - LOG("GameGameConnect", ("Told to drop connection to %lu by Central", msg.getServerId())); + ClientConnection *cconn = getClientConnection(msg.getSuid()); + if (!cconn) { + DEBUG_REPORT_LOG(true, ("Received ValidateCharacterForLoginReplyMessage for account %lu, which is no longer connected.\n", msg.getSuid())); + } else { + cconn->onCharacterValidated(msg.getApproved(), msg.getCharacterId(), Unicode::wideToNarrow(msg.getCharacterName()), msg.getContainerId(), msg.getScene(), msg.getCoordinates()); + } + break; + } + case constcrc("ValidateAccountReplyMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const ValidateAccountReplyMessage msg(ri); - GameConnection *conn = getGameConnection(msg.getServerId()); - if (conn) - conn->disconnect(); - - break; - } - case constcrc("CntrlSrvDropDupeConns") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const msg(ri); + ClientConnection *cconn = getClientConnection(msg.getStationId()); + if (!cconn) { + DEBUG_REPORT_LOG(true, ("Received ValidateAccountReplyMessage for account %lu, which is no longer connected.\n", msg.getStationId())); + } else { + cconn->onIdValidated(msg.getCanLogin(), msg.getCanCreateRegular(), msg.getCanCreateJedi(), msg.getCanSkipTutorial(), msg.getConsumedRewardEvents(), msg.getClaimedRewardItems()); + } + break; + } + case constcrc("SetConnectionServerPublic") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + SetConnectionServerPublic p(ri);//lint !e40 !e522 !e10 // Undeclared identifier 'SetConnectionServerPublic' // suppressed because it IS declared + bool statusChanged = false; + DEBUG_REPORT_LOG(true, ("Conn Server: attempting to chang status\n")); + if (p.getIsPublic())//lint !e40 !e1013 !e10 // Undeclared identifier 'p' // suppressed because it IS declared + { + if (!clientServicePublic) { + statusChanged = true; + } + } else { + delete clientServicePublic; + clientServicePublic = 0; + statusChanged = true; + } - ClientConnection* client = getClientConnection(msg.getValue().first); - if (client && !client->isUsingAdminLogin() && !client->getIsSecure()) - { - std::string s = "New Connection on galaxy "; - s += msg.getValue().second; + if (statusChanged && centralConnection) { + const Service *publicService = getClientServicePublic(); + const Service *privateService = getClientServicePrivate(); + if (publicService || privateService) { + uint16 publicServicePort = 0; + uint16 privateServicePort = 0; + if (publicService) { + publicServicePort = publicService->getBindPort(); + } + if (privateService) { + privateServicePort = privateService->getBindPort(); + } + const UpdateConnectionServerStatus ucs(publicServicePort, privateServicePort); + centralConnection->send(ucs, true); + } + } + break; + }//lint !e529 // Symbol 'ri' not subsequently referenced // suppressed because it IS referenced. I think lint is very confused for some reason. + case constcrc("ProfilerOperationMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ProfilerOperationMessage msg(ri); + unsigned int processId = msg.getProcessId(); + if (!processId) { + Profiler::handleOperation(msg.getOperation().c_str()); + } - dropClient(client, s); - } - break; - } - } + break; + } + case constcrc("ExcommunicateGameServerMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ExcommunicateGameServerMessage msg(ri); + + LOG("GameGameConnect", ("Told to drop connection to %lu by Central", msg.getServerId())); + + GameConnection *conn = getGameConnection(msg.getServerId()); + if (conn) { + conn->disconnect(); + } + + break; + } + case constcrc("CntrlSrvDropDupeConns") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + ClientConnection *client = getClientConnection(msg.getValue().first); + if (client && !client->isUsingAdminLogin() && !client->getIsSecure()) { + std::string s = "New Connection on galaxy "; + s += msg.getValue().second; + + dropClient(client, s); + } + break; + } + } } //----------------------------------------------------------------------- -void ConnectionServer::install() -{ - s_connectionServer = new ConnectionServer; +void ConnectionServer::install() { + s_connectionServer = new ConnectionServer; - char tmp[128] = { "\0" }; - IGNORE_RETURN(snprintf(tmp, sizeof(tmp), "ConnectionServer:%d", Os::getProcessId())); - SetupSharedLog::install(tmp); - s_connectionServer->setupConnections(); - s_connectionServer->m_metricsData = new ConnectionServerMetricsData; - MetricsManager::install(s_connectionServer->m_metricsData, true, "ConnectionServer", "", ConfigConnectionServer::getConnectionServerNumber()); - DataTableManager::install(); - AdminAccountManager::install(ConfigConnectionServer::getAdminAccountDataTable()); + char tmp[128] = {"\0"}; + IGNORE_RETURN(snprintf(tmp, sizeof(tmp), "ConnectionServer:%d", Os::getProcessId())); + SetupSharedLog::install(tmp); + s_connectionServer->setupConnections(); + s_connectionServer->m_metricsData = new ConnectionServerMetricsData; + MetricsManager::install(s_connectionServer->m_metricsData, true, "ConnectionServer", "", ConfigConnectionServer::getConnectionServerNumber()); + DataTableManager::install(); + AdminAccountManager::install(ConfigConnectionServer::getAdminAccountDataTable()); } //----------------------------------------------------------------------- -void ConnectionServer::remove() -{ - MetricsManager::remove(); - delete s_connectionServer->m_metricsData; - s_connectionServer->m_metricsData = 0; +void ConnectionServer::remove() { + MetricsManager::remove(); + delete s_connectionServer->m_metricsData; + s_connectionServer->m_metricsData = 0; - // explicitly delete all connections that were setup from setupConnections rather than letting - // Connection::remove do it. There are connections that require a valid s_connectionServer which is deleted - // and set to nullptr. - s_connectionServer->unsetupConnections(); + // explicitly delete all connections that were setup from setupConnections rather than letting + // Connection::remove do it. There are connections that require a valid s_connectionServer which is deleted + // and set to nullptr. + s_connectionServer->unsetupConnections(); - SetupSharedLog::remove(); + SetupSharedLog::remove(); - delete s_connectionServer; - s_connectionServer = 0; + delete s_connectionServer; + s_connectionServer = 0; } //----------------------------------------------------------------------- -void ConnectionServer::run(void) -{ - static const bool shouldSleep = ConfigConnectionServer::getShouldSleep(); - static ConnectionServer & cserver = instance(); - DEBUG_FATAL(!cserver.m_metricsData, ("Connection server not installed properly")); +void ConnectionServer::run(void) { + static const bool shouldSleep = ConfigConnectionServer::getShouldSleep(); + static ConnectionServer &cserver = instance(); + DEBUG_FATAL(!cserver.m_metricsData, ("Connection server not installed properly")); - unsigned long startTime = Clock::timeMs(); - Clock::setFrameRateLimit(50.0f); + unsigned long startTime = Clock::timeMs(); + Clock::setFrameRateLimit(50.0f); - LOG("ServerStartup", ("ConnectionServer starting on %s", NetworkHandler::getHostName().c_str())); - while (!cserver.done) - { - PROFILER_AUTO_BLOCK_DEFINE("main loop"); + LOG("ServerStartup", ("ConnectionServer starting on %s", NetworkHandler::getHostName().c_str())); + while (!cserver.done) { + PROFILER_AUTO_BLOCK_DEFINE("main loop"); - //bool barrierReached = true; + //bool barrierReached = true; - do - { - { - PROFILER_AUTO_BLOCK_DEFINE("Os::update"); - if (!Os::update()) - cserver.setDone("Os condition (Parent pid change)"); - } + do { + { + PROFILER_AUTO_BLOCK_DEFINE("Os::update"); + if (!Os::update()) { + cserver.setDone("Os condition (Parent pid change)"); + } + } - { - PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::update1"); - NetworkHandler::update(); - } + { + PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::update1"); + NetworkHandler::update(); + } - { - GenericValueTypeMessage > const syncStampMessage("SetSyncStamp", std::make_pair(static_cast(UdpMisc::LocalSyncStampShort()), static_cast(UdpMisc::LocalSyncStampLong()))); - GameServerMap::iterator end = cserver.gameServerMap.end(); - for (GameServerMap::iterator iter = cserver.gameServerMap.begin(); iter != end; ++iter) - iter->second->send(syncStampMessage, true); - } + { + GenericValueTypeMessage > const syncStampMessage("SetSyncStamp", std::make_pair(static_cast(UdpMisc::LocalSyncStampShort()), static_cast(UdpMisc::LocalSyncStampLong()))); + GameServerMap::iterator end = cserver.gameServerMap.end(); + for (GameServerMap::iterator iter = cserver.gameServerMap.begin(); iter != end; ++iter) { + iter->second->send(syncStampMessage, true); + } + } - { - PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::dispatch"); - NetworkHandler::dispatch(); - } + { + PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::dispatch"); + NetworkHandler::dispatch(); + } - { - PROFILER_AUTO_BLOCK_DEFINE("update"); - cserver.update(); - } + { + PROFILER_AUTO_BLOCK_DEFINE("update"); + cserver.update(); + } - { - PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::update2"); - NetworkHandler::update(); - } + { + PROFILER_AUTO_BLOCK_DEFINE("NetworkHandler::update2"); + NetworkHandler::update(); + } - { - PROFILER_AUTO_BLOCK_DEFINE("MetricsManager::update"); - unsigned long curTime = Clock::timeMs(); - MetricsManager::update(static_cast(curTime - startTime)); - startTime = curTime; - } + { + PROFILER_AUTO_BLOCK_DEFINE("MetricsManager::update"); + unsigned long curTime = Clock::timeMs(); + MetricsManager::update(static_cast(curTime - startTime)); + startTime = curTime; + } - if (shouldSleep) - { - PROFILER_AUTO_BLOCK_DEFINE("Os::sleep"); - Os::sleep(1); - } - } while (!cserver.done); + if (shouldSleep) { + PROFILER_AUTO_BLOCK_DEFINE("Os::sleep"); + Os::sleep(1); + } + } while (!cserver.done); - NetworkHandler::clearBytesThisFrame(); + NetworkHandler::clearBytesThisFrame(); - cserver.updateRecoveringClientList(static_cast(Clock::frameTime()*1000.0f)); - } + cserver.updateRecoveringClientList(static_cast(Clock::frameTime() * 1000.0f)); + } } // ---------------------------------------------------------------------- /** * Invoked every frame to do whatever updates are needed */ -void ConnectionServer::update() -{ - if (centralConnection) - { - static Timer t(5.0f); - if (t.updateZero(Clock::frameTime())) - { - // Update the population on the central server - updatePopulationOnCentralServer(); +void ConnectionServer::update() { + if (centralConnection) { + static Timer t(5.0f); + if (t.updateZero(Clock::frameTime())) { + // Update the population on the central server + updatePopulationOnCentralServer(); - if (getNumberOfClients() >= ConfigConnectionServer::getMaxClients() - 1) - { - //@todo need an Alert here - WARNING(true, ("We've reached maximum client capacity on a connection server with %d clients", getNumberOfClients())); - } - } - } + if (getNumberOfClients() >= ConfigConnectionServer::getMaxClients() - 1) { + //@todo need an Alert here + WARNING(true, ("We've reached maximum client capacity on a connection server with %d clients", getNumberOfClients())); + } + } + } - /*if (m_sessionApiClient) - { - m_sessionApiClient->update(); - }*/ + /*if (m_sessionApiClient) + { + m_sessionApiClient->update(); + }*/ - static const int ping_throttle_max = 1024; + static const int ping_throttle_max = 1024; - static char buffer[4]; + static char buffer[4]; - for (int throttle = 0; pingSocket->canRecv() && throttle < ping_throttle_max; ++throttle) - { - Address addr; - const uint32 count = pingSocket->recvFrom(addr, buffer, 4); - m_pingTrafficNumBytes += static_cast(count); - if (m_pingTrafficNumBytes < 0) - m_pingTrafficNumBytes = 0; - IGNORE_RETURN(pingSocket->sendTo(addr, buffer, count)); - } + for (int throttle = 0; pingSocket->canRecv() && throttle < ping_throttle_max; ++throttle) { + Address addr; + const uint32 count = pingSocket->recvFrom(addr, buffer, 4); + m_pingTrafficNumBytes += static_cast(count); + if (m_pingTrafficNumBytes < 0) { + m_pingTrafficNumBytes = 0; + } + IGNORE_RETURN(pingSocket->sendTo(addr, buffer, count)); + } } // ---------------------------------------------------------------------- @@ -1128,487 +1011,430 @@ void ConnectionServer::update() * is OK and we don't do anything. If no game server takes authority for them, * we drop them and force them to log in again. */ -void ConnectionServer::updateRecoveringClientList(uint elapsedTime) -{ - if (!m_recoveringClientList.empty()) - { - m_recoverTime += elapsedTime; +void ConnectionServer::updateRecoveringClientList(uint elapsedTime) { + if (!m_recoveringClientList.empty()) { + m_recoverTime += elapsedTime; - static std::set listPlayersDropped; - for (RecoveringClientListType::iterator i = m_recoveringClientList.begin(); i != m_recoveringClientList.end();) - { - if (m_recoverTime > i->first) - { - Client *client = getClient(i->second); - if (client) - { - if (client->getGameConnection()) - DEBUG_REPORT_LOG(true, ("Player %s recovered from a server crash and will not be dropped.\n", i->second.getValueString().c_str())); - else - { - LOG("Network", ("Dropping player %s because game server crashed and no other server took authority.\n", i->second.getValueString().c_str())); - dropClient(client->getClientConnection(), "Game Server Crash"); + static std::set listPlayersDropped; + for (RecoveringClientListType::iterator i = m_recoveringClientList.begin(); + i != m_recoveringClientList.end();) { + if (m_recoverTime > i->first) { + Client *client = getClient(i->second); + if (client) { + if (client->getGameConnection()) { + DEBUG_REPORT_LOG(true, ("Player %s recovered from a server crash and will not be dropped.\n", i->second.getValueString().c_str())); + } else { + LOG("Network", ("Dropping player %s because game server crashed and no other server took authority.\n", i->second.getValueString().c_str())); + dropClient(client->getClientConnection(), "Game Server Crash"); - IGNORE_RETURN(listPlayersDropped.insert(i->second)); - } - } - i = m_recoveringClientList.erase(i); - } - else - ++i; - } + IGNORE_RETURN(listPlayersDropped.insert(i->second)); + } + } + i = m_recoveringClientList.erase(i); + } else { + ++i; + } + } - if (!listPlayersDropped.empty()) - { - GenericValueTypeMessage > const m("PlayerDroppedFromGameServerCrash", listPlayersDropped); + if (!listPlayersDropped.empty()) { + GenericValueTypeMessage > const m("PlayerDroppedFromGameServerCrash", listPlayersDropped); - // let one of the game server know that we dropped the player(s) due to a game server crash - GameConnection * const anyGameConnection = getAnyGameConnection(); - if (anyGameConnection) - anyGameConnection->send(m, true); + // let one of the game server know that we dropped the player(s) due to a game server crash + GameConnection *const anyGameConnection = getAnyGameConnection(); + if (anyGameConnection) { + anyGameConnection->send(m, true); + } - // let CentralServer know that we dropped the player(s) due to a game server crash - sendToCentralProcess(m); + // let CentralServer know that we dropped the player(s) due to a game server crash + sendToCentralProcess(m); - listPlayersDropped.clear(); - } + listPlayersDropped.clear(); + } - if (m_recoveringClientList.empty()) - m_recoverTime = 0; // prevent rollover and other problems I don't want to worry about - } + if (m_recoveringClientList.empty()) { + m_recoverTime = 0; + } // prevent rollover and other problems I don't want to worry about + } } // ---------------------------------------------------------------------- -void ConnectionServer::addRecoveringClient(const NetworkId& networkId) -{ - instance().m_recoveringClientList.push_back(std::pair(static_cast(instance().m_recoverTime) + ConfigConnectionServer::getCrashRecoveryTimeout(), networkId));//lint !e737 !e713 !e1703 !e1025 // going nuts over unsigned/signed conversion and type mismatch on template +void ConnectionServer::addRecoveringClient(const NetworkId &networkId) { + instance().m_recoveringClientList.push_back(std::pair(static_cast(instance().m_recoverTime) + + ConfigConnectionServer::getCrashRecoveryTimeout(), networkId));//lint !e737 !e713 !e1703 !e1025 // going nuts over unsigned/signed conversion and type mismatch on template } // ---------------------------------------------------------------------- -void ConnectionServer::unsetupConnections() -{ - // remove all ClientConnection objects so when Connection::remove() is called we don't crash since - // ConnectionServer no longer exists - while (!instance().connectedMap.empty()) - { - SuidMap::iterator i = instance().connectedMap.begin(); - if (i != instance().connectedMap.end()) - { - ClientConnection * c = (*i).second; - uint32 suid = (*i).first; - IGNORE_RETURN(instance().connectedMap.erase(suid)); - if (c) - { - ConnectionServer::dropClient(c, "ConnectionServer shutting down."); - delete c; - } - } - } +void ConnectionServer::unsetupConnections() { + // remove all ClientConnection objects so when Connection::remove() is called we don't crash since + // ConnectionServer no longer exists + while (!instance().connectedMap.empty()) { + SuidMap::iterator i = instance().connectedMap.begin(); + if (i != instance().connectedMap.end()) { + ClientConnection *c = (*i).second; + uint32 suid = (*i).first; + IGNORE_RETURN(instance().connectedMap.erase(suid)); + if (c) { + ConnectionServer::dropClient(c, "ConnectionServer shutting down."); + delete c; + } + } + } - if (customerService) - { - delete customerService; - customerService = 0; - } + if (customerService) { + delete customerService; + customerService = 0; + } - if (chatService) - { - delete chatService; - chatService = 0; - } + if (chatService) { + delete chatService; + chatService = 0; + } - if (centralConnection) - { - delete centralConnection; - centralConnection = 0; - } + if (centralConnection) { + delete centralConnection; + centralConnection = 0; + } - if (gameService) - { - delete gameService; - gameService = 0; - } + if (gameService) { + delete gameService; + gameService = 0; + } } //----------------------------------------------------------------------- -void ConnectionServer::setupConnections() -{ - // set up message connections - connectToMessage("ConnectionGameServerConnect"); - connectToMessage("SetConnectionServerPublic"); +void ConnectionServer::setupConnections() { + // set up message connections + connectToMessage("ConnectionGameServerConnect"); + connectToMessage("SetConnectionServerPublic"); - // set up port to listen for clients, central, and game servers + // set up port to listen for clients, central, and game servers - connectToMessage("CentralConnectionOpened"); - connectToMessage("CentralConnectionClosed"); + connectToMessage("CentralConnectionOpened"); + connectToMessage("CentralConnectionClosed"); - NetworkSetupData setup; - setup.port = ConfigConnectionServer::getGameServicePort(); - setup.bindInterface = ConfigConnectionServer::getGameServiceBindInterface(); - setup.maxConnections = 1000; + NetworkSetupData setup; + setup.port = ConfigConnectionServer::getGameServicePort(); + setup.bindInterface = ConfigConnectionServer::getGameServiceBindInterface(); + setup.maxConnections = 1000; - gameService = new Service(ConnectionAllocator(), setup); - connectToMessage("GameConnectionOpened"); - connectToMessage("GameConnectionClosed"); + gameService = new Service(ConnectionAllocator(), setup); + connectToMessage("GameConnectionOpened"); + connectToMessage("GameConnectionClosed"); - // connect to central server - centralConnection = new CentralConnection(ConfigConnectionServer::getCentralServerAddress(), ConfigConnectionServer::getCentralServerPort()); + // connect to central server + centralConnection = new CentralConnection(ConfigConnectionServer::getCentralServerAddress(), ConfigConnectionServer::getCentralServerPort()); - setup.port = 0; - setup.bindInterface = ConfigConnectionServer::getChatServiceBindInterface(); - chatService = new Service(ConnectionAllocator(), setup); - connectToMessage("ChatServerConnectionOpened"); - connectToMessage("ChatServerConnectionClosed"); + setup.port = 0; + setup.bindInterface = ConfigConnectionServer::getChatServiceBindInterface(); + chatService = new Service(ConnectionAllocator(), setup); + connectToMessage("ChatServerConnectionOpened"); + connectToMessage("ChatServerConnectionClosed"); - setup.bindInterface = ConfigConnectionServer::getCustomerServiceBindInterface(); - customerService = new Service(ConnectionAllocator(), setup); - connectToMessage("CustomerServiceConnectionOpened"); - connectToMessage("CustomerServiceConnectionClosed"); + setup.bindInterface = ConfigConnectionServer::getCustomerServiceBindInterface(); + customerService = new Service(ConnectionAllocator(), setup); + connectToMessage("CustomerServiceConnectionOpened"); + connectToMessage("CustomerServiceConnectionClosed"); - connectToMessage("ConnectionServerId"); - connectToMessage("ConnectionKeyPush"); - connectToMessage("LoginKeyPush"); - connectToMessage("CharacterListMessage"); + connectToMessage("ConnectionServerId"); + connectToMessage("ConnectionKeyPush"); + connectToMessage("LoginKeyPush"); + connectToMessage("CharacterListMessage"); - //Create Characters Messages - connectToMessage("ClientCreateCharacter"); - connectToMessage("ConnectionCreateCharacterSuccess"); - connectToMessage("ConnectionCreateCharacterFailed"); - connectToMessage("NewCharacterCreated"); - connectToMessage("GameServerForLoginMessage"); + //Create Characters Messages + connectToMessage("ClientCreateCharacter"); + connectToMessage("ConnectionCreateCharacterSuccess"); + connectToMessage("ConnectionCreateCharacterFailed"); + connectToMessage("NewCharacterCreated"); + connectToMessage("GameServerForLoginMessage"); - // name query messages - connectToMessage("ClientRandomNameRequest"); // from client - connectToMessage("RandomNameResponse"); // from game server + // name query messages + connectToMessage("ClientRandomNameRequest"); // from client + connectToMessage("RandomNameResponse"); // from game server - connectToMessage("ClientVerifyAndLockNameRequest"); // from client - connectToMessage("VerifyAndLockNameResponse"); // from game server + connectToMessage("ClientVerifyAndLockNameRequest"); // from client + connectToMessage("VerifyAndLockNameResponse"); // from game server - connectToMessage("ValidateCharacterForLoginReplyMessage"); - connectToMessage("ValidateAccountReplyMessage"); + connectToMessage("ValidateCharacterForLoginReplyMessage"); + connectToMessage("ValidateAccountReplyMessage"); - connectToMessage("ProfilerOperationMessage"); - connectToMessage("CentralConnectionClosed"); - connectToMessage("CentralConnectionOpened"); - connectToMessage("ChunkCompleteMessage"); - connectToMessage("FrameEndMessage"); - connectToMessage("GameConnectionClosed"); - connectToMessage("GameGameServerConnect"); - connectToMessage("GameServerReadyMessage"); - connectToMessage("GameServerUniverseLoadedMessage"); - connectToMessage("PersistedPlayerMessage"); - connectToMessage("PreloadListMessage"); - connectToMessage("PreloadRequestCompleteMessage"); - connectToMessage("ProfilerOperationMessage"); - connectToMessage("RequestGameServerForLoginMessage"); - connectToMessage("RequestSceneTransfer"); - connectToMessage("ShutdownMessage"); - connectToMessage("TaskConnectionOpened"); - connectToMessage("UnloadedPlayerMessage"); - connectToMessage("WatcherConnectionClosed"); - connectToMessage("WatcherConnectionOpened"); - connectToMessage("ExcommunicateGameServerMessage"); - connectToMessage("CntrlSrvDropDupeConns"); + connectToMessage("ProfilerOperationMessage"); + connectToMessage("CentralConnectionClosed"); + connectToMessage("CentralConnectionOpened"); + connectToMessage("ChunkCompleteMessage"); + connectToMessage("FrameEndMessage"); + connectToMessage("GameConnectionClosed"); + connectToMessage("GameGameServerConnect"); + connectToMessage("GameServerReadyMessage"); + connectToMessage("GameServerUniverseLoadedMessage"); + connectToMessage("PersistedPlayerMessage"); + connectToMessage("PreloadListMessage"); + connectToMessage("PreloadRequestCompleteMessage"); + connectToMessage("ProfilerOperationMessage"); + connectToMessage("RequestGameServerForLoginMessage"); + connectToMessage("RequestSceneTransfer"); + connectToMessage("ShutdownMessage"); + connectToMessage("TaskConnectionOpened"); + connectToMessage("UnloadedPlayerMessage"); + connectToMessage("WatcherConnectionClosed"); + connectToMessage("WatcherConnectionOpened"); + connectToMessage("ExcommunicateGameServerMessage"); + connectToMessage("CntrlSrvDropDupeConns"); } //---------------------------------------------------------------------- -uint16 ConnectionServer::getPingPort() -{ - static ConnectionServer & cs = instance(); - return cs.pingSocket->getBindAddress().getHostPort(); +uint16 ConnectionServer::getPingPort() { + static ConnectionServer &cs = instance(); + return cs.pingSocket->getBindAddress().getHostPort(); } //----------------------------------------------------------------------- -Client* ConnectionServer::getClient(const NetworkId & oid) -{ - static ConnectionServer & cs = instance(); - ClientMap::const_iterator iter = cs.clientMap.find(oid); - if (iter != cs.clientMap.end()) - return (*iter).second; - return 0; +Client *ConnectionServer::getClient(const NetworkId &oid) { + static ConnectionServer &cs = instance(); + ClientMap::const_iterator iter = cs.clientMap.find(oid); + if (iter != cs.clientMap.end()) { + return (*iter).second; + } + return 0; } //----------------------------------------------------------------------- -const ConnectionServer::ClientMap & ConnectionServer::getClientMap() -{ - return instance().clientMap; +const ConnectionServer::ClientMap &ConnectionServer::getClientMap() { + return instance().clientMap; } //----------------------------------------------------------------------- -GameConnection* ConnectionServer::getGameConnection(uint32 gameServerId) -{ - static ConnectionServer & cs = instance(); - const GameServerMap::const_iterator i = cs.gameServerMap.find(gameServerId); - if (i != cs.gameServerMap.end()) - return (*i).second; +GameConnection *ConnectionServer::getGameConnection(uint32 gameServerId) { + static ConnectionServer &cs = instance(); + const GameServerMap::const_iterator i = cs.gameServerMap.find(gameServerId); + if (i != cs.gameServerMap.end()) { + return (*i).second; + } - return nullptr; + return nullptr; } //----------------------------------------------------------------------- -GameConnection* ConnectionServer::getAnyGameConnection() -{ - static ConnectionServer & cs = instance(); - if (!cs.gameServerMap.empty()) - return cs.gameServerMap.begin()->second; +GameConnection *ConnectionServer::getAnyGameConnection() { + static ConnectionServer &cs = instance(); + if (!cs.gameServerMap.empty()) { + return cs.gameServerMap.begin()->second; + } - return nullptr; + return nullptr; } //----------------------------------------------------------------------- -int ConnectionServer::getPingTrafficNumBytes() -{ - static ConnectionServer & cs = instance(); - return cs.m_pingTrafficNumBytes; +int ConnectionServer::getPingTrafficNumBytes() { + static ConnectionServer &cs = instance(); + return cs.m_pingTrafficNumBytes; } //----------------------------------------------------------------------- -int ConnectionServer::getNumberOfClients() -{ - static ConnectionServer & cs = instance(); - return static_cast(cs.connectedMap.size()); +int ConnectionServer::getNumberOfClients() { + static ConnectionServer &cs = instance(); + return static_cast(cs.connectedMap.size()); } //----------------------------------------------------------------------- -int ConnectionServer::getNumberOfFreeTrials() -{ - static ConnectionServer & cs = instance(); - return static_cast(cs.freeTrials.size()); +int ConnectionServer::getNumberOfFreeTrials() { + static ConnectionServer &cs = instance(); + return static_cast(cs.freeTrials.size()); } //----------------------------------------------------------------------- -int ConnectionServer::getNumberOfGameServers() -{ - static ConnectionServer & cs = instance(); - return static_cast(cs.gameServerMap.size()); +int ConnectionServer::getNumberOfGameServers() { + static ConnectionServer &cs = instance(); + return static_cast(cs.gameServerMap.size()); } //----------------------------------------------------------------------- -void ConnectionServer::removeConnectedCharacter(uint32 suid) -{ - static ConnectionServer & cs = instance(); - cs.removeFromConnectedMap(suid); +void ConnectionServer::removeConnectedCharacter(uint32 suid) { + static ConnectionServer &cs = instance(); + cs.removeFromConnectedMap(suid); } //----------------------------------------------------------------------- -void ConnectionServer::sendToCentralProcess(const GameNetworkMessage & msg) -{ - static ConnectionServer & cs = instance(); - if (cs.centralConnection) - cs.centralConnection->send(msg, true); - else - WARNING(true, ("Connection tried to send a message Central, but there is no Central Connection")); +void ConnectionServer::sendToCentralProcess(const GameNetworkMessage &msg) { + static ConnectionServer &cs = instance(); + if (cs.centralConnection) { + cs.centralConnection->send(msg, true); + } else { + WARNING(true, ("Connection tried to send a message Central, but there is no Central Connection")); + } } //----------------------------------------------------------------------- -CentralConnection * ConnectionServer::getCentralConnection() -{ - static ConnectionServer & cs = instance(); - return cs.centralConnection; +CentralConnection *ConnectionServer::getCentralConnection() { + static ConnectionServer &cs = instance(); + return cs.centralConnection; } //----------------------------------------------------------------------- -void ConnectionServer::installSessionValidation() -{ - /*int i = 0; - std::vector sessionServers; - int const numberOfSessionServers = ConfigConnectionServer::getNumberOfSessionServers(); - for (i = 0; i < numberOfSessionServers; ++i) - { - char const * const p = ConfigConnectionServer::getSessionServer(i); - if (p) - { - REPORT_LOG(true, ("Using session server %s\n", p)); - sessionServers.push_back(p); - } - } +void ConnectionServer::installSessionValidation() { + /*int i = 0; + std::vector sessionServers; + int const numberOfSessionServers = ConfigConnectionServer::getNumberOfSessionServers(); + for (i = 0; i < numberOfSessionServers; ++i) + { + char const * const p = ConfigConnectionServer::getSessionServer(i); + if (p) + { + REPORT_LOG(true, ("Using session server %s\n", p)); + sessionServers.push_back(p); + } + } - // if there were none specified, use defaults - FATAL(i == 0, ("No session servers specified for session API")); - m_sessionApiClient = new SessionApiClient(&sessionServers[0], i);*/ - return; + // if there were none specified, use defaults + FATAL(i == 0, ("No session servers specified for session API")); + m_sessionApiClient = new SessionApiClient(&sessionServers[0], i);*/ + return; } // ---------------------------------------------------------------------- -void ConnectionServer::addToClientMap(const NetworkId &oid, ClientConnection* cconn) -{ - Client * newClient = new Client(cconn, oid); +void ConnectionServer::addToClientMap(const NetworkId &oid, ClientConnection *cconn) { + Client *newClient = new Client(cconn, oid); - clientMap[oid] = newClient; + clientMap[oid] = newClient; - //associate the ClientConnection object. - cconn->setClient(newClient); + //associate the ClientConnection object. + cconn->setClient(newClient); } // ---------------------------------------------------------------------- -void ConnectionServer::removeFromClientMap(const NetworkId &oid) -{ - ClientMap::iterator i = clientMap.find(oid); - if (i != clientMap.end()) - { - clientMap.erase(i); - } +void ConnectionServer::removeFromClientMap(const NetworkId &oid) { + ClientMap::iterator i = clientMap.find(oid); + if (i != clientMap.end()) { + clientMap.erase(i); + } } //----------------------------------------------------------------------- -void ConnectionServer::addToConnectedMap(uint32 suid, ClientConnection* cconn) -{ - SuidMap::iterator i = connectedMap.find(suid); - if (i == connectedMap.end()) - { - connectedMap[suid] = cconn; - } - else - { - WARNING_STRICT_FATAL(true, ("Attepting to add duplicate connected chatacter")); - connectedMap[suid] = cconn; - } +void ConnectionServer::addToConnectedMap(uint32 suid, ClientConnection *cconn) { + SuidMap::iterator i = connectedMap.find(suid); + if (i == connectedMap.end()) { + connectedMap[suid] = cconn; + } else { + WARNING_STRICT_FATAL(true, ("Attepting to add duplicate connected chatacter")); + connectedMap[suid] = cconn; + } - if (((cconn->getSubscriptionFeatures() & ClientSubscriptionFeature::FreeTrial) != 0) - && ((cconn->getSubscriptionFeatures() & ClientSubscriptionFeature::Base) == 0)) - { - freeTrials.insert(suid); - } + if (((cconn->getSubscriptionFeatures() & ClientSubscriptionFeature::FreeTrial) != 0) && + ((cconn->getSubscriptionFeatures() & ClientSubscriptionFeature::Base) == 0)) { + freeTrials.insert(suid); + } - // Update the population on the CentralServer immediately - // since we are trying to avoid people "rushing" the server - updatePopulationOnCentralServer(); + // Update the population on the CentralServer immediately + // since we are trying to avoid people "rushing" the server + updatePopulationOnCentralServer(); } // ---------------------------------------------------------------------- -void ConnectionServer::removeFromConnectedMap(uint32 suid) -{ - SuidMap::iterator i = connectedMap.find(suid); - if (i != connectedMap.end()) - { - connectedMap.erase(i); - } +void ConnectionServer::removeFromConnectedMap(uint32 suid) { + SuidMap::iterator i = connectedMap.find(suid); + if (i != connectedMap.end()) { + connectedMap.erase(i); + } - FreeTrialsSet::iterator j = freeTrials.find(suid); - if (j != freeTrials.end()) - { - freeTrials.erase(j); - } + FreeTrialsSet::iterator j = freeTrials.find(suid); + if (j != freeTrials.end()) { + freeTrials.erase(j); + } - // We could update the CentralServer population but people - // leaving the server are not as important as people connecting - // and so we will wait for update() to handle things + // We could update the CentralServer population but people + // leaving the server are not as important as people connecting + // and so we will wait for update() to handle things } // ---------------------------------------------------------------------- -void ConnectionServer::updatePopulationOnCentralServer() -{ - if (centralConnection) - { - // Total number of clients and how many of those are free trials - const int numPlayers = getNumberOfClients(); - const int numFreeTrial = getNumberOfFreeTrials(); +void ConnectionServer::updatePopulationOnCentralServer() { + if (centralConnection) { + // Total number of clients and how many of those are free trials + const int numPlayers = getNumberOfClients(); + const int numFreeTrial = getNumberOfFreeTrials(); - // We are concerned about too many people piling up at the beginning - // of the tutorial, so count how many players could be a problem - int numPlayersEmptyScene = 0; - int numPlayersTutorialScene = 0; - int numPlayersFalconScene = 0; + // We are concerned about too many people piling up at the beginning + // of the tutorial, so count how many players could be a problem + int numPlayersEmptyScene = 0; + int numPlayersTutorialScene = 0; + int numPlayersFalconScene = 0; - // Walk through the clients and evaluate what scene they are in - SuidMap::const_iterator i; - for (i = connectedMap.begin(); i != connectedMap.end(); ++i) - { - const ClientConnection * const conn = (*i).second; - const Client * const client = conn->getClient(); + // Walk through the clients and evaluate what scene they are in + SuidMap::const_iterator i; + for (i = connectedMap.begin(); i != connectedMap.end(); ++i) { + const ClientConnection *const conn = (*i).second; + const Client *const client = conn->getClient(); - if (client && client->getGameConnection()) - { - const std::string& scene = client->getGameConnection()->getSceneName(); + if (client && client->getGameConnection()) { + const std::string &scene = client->getGameConnection()->getSceneName(); - if (scene.empty()) - { - numPlayersEmptyScene += 1; - } - else if (scene == SCENE_NAME_TUTORIAL) - { - numPlayersTutorialScene += 1; - } - else if (scene.substr(0, SCENE_NAME_FALCON_PREFIX.length()) == SCENE_NAME_FALCON_PREFIX) - { - numPlayersFalconScene += 1; - } - } - else - { - numPlayersEmptyScene += 1; - } - } + if (scene.empty()) { + numPlayersEmptyScene += 1; + } else if (scene == SCENE_NAME_TUTORIAL) { + numPlayersTutorialScene += 1; + } else if (scene.substr(0, SCENE_NAME_FALCON_PREFIX.length()) == SCENE_NAME_FALCON_PREFIX) { + numPlayersFalconScene += 1; + } + } else { + numPlayersEmptyScene += 1; + } + } - const UpdatePlayerCountMessage msg(false, numPlayers, numFreeTrial, numPlayersEmptyScene, numPlayersTutorialScene, numPlayersFalconScene); - centralConnection->send(msg, true); - } + const UpdatePlayerCountMessage msg(false, numPlayers, numFreeTrial, numPlayersEmptyScene, numPlayersTutorialScene, numPlayersFalconScene); + centralConnection->send(msg, true); + } } // ---------------------------------------------------------------------- -SessionApiClient* ConnectionServer::getSessionApiClient() -{ - // this is causing crashes when ConnectionServer is shutdown and something calls this function - // because instance() returns 0. - //if (s_connectionServer) - //{ - // return instance().m_sessionApiClient; - //} - //else - //{ - return 0; - //} +SessionApiClient *ConnectionServer::getSessionApiClient() { + // this is causing crashes when ConnectionServer is shutdown and something calls this function + // because instance() returns 0. + //if (s_connectionServer) + //{ + // return instance().m_sessionApiClient; + //} + //else + //{ + return 0; + //} } // ---------------------------------------------------------------------- -void ConnectionServer::setDone(char const *reasonfmt, ...) -{ - if (!done) - { - char reason[1024]; - va_list ap; - va_start(ap, reasonfmt); - IGNORE_RETURN(_vsnprintf(reason, sizeof(reason), reasonfmt, ap));//lint !e530 Symbol 'ap' not initialized - reason[sizeof(reason) - 1] = '\0'; +void ConnectionServer::setDone(char const *reasonfmt, ...) { + if (!done) { + char reason[1024]; + va_list ap; + va_start(ap, reasonfmt); + IGNORE_RETURN(_vsnprintf(reason, sizeof(reason), reasonfmt, ap));//lint !e530 Symbol 'ap' not initialized + reason[sizeof(reason) - 1] = '\0'; - LOG( - "ServerShutdown", - ( - "ConnectionServer (pid %d) shutdown, reason: %s", - static_cast(Os::getProcessId()), - reason)); + LOG("ServerShutdown", ("ConnectionServer (pid %d) shutdown, reason: %s", static_cast(Os::getProcessId()), reason)); - REPORT_LOG( - true, - ( - "ConnectionServer (pid %d) shutdown, reason: %s\n", - static_cast(Os::getProcessId()), - reason)); + REPORT_LOG(true, ("ConnectionServer (pid %d) shutdown, reason: %s\n", static_cast(Os::getProcessId()), reason)); - done = true; - va_end(ap); - } + done = true; + va_end(ap); + } } // ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 55bd2094..a6c1ead7 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -27,18 +27,10 @@ using namespace StellaBellum; //----------------------------------------------------------------------- -ClientConnection::ClientConnection(UdpConnectionMT *u, TcpClient *t) : - ServerConnection(u, t), - m_clientId(0), - m_isValidated(false), - m_isSecure(false), - m_adminLevel(-1), - m_stationId(0), - m_requestedAdminSuid(0), - m_gameBits(0), - m_subscriptionBits(0), - m_waitingForCharacterLoginDeletion(false), - m_waitingForCharacterClusterDeletion(false) { +ClientConnection::ClientConnection(UdpConnectionMT *u, TcpClient *t) + : ServerConnection(u, t), m_clientId(0), m_isValidated(false), m_isSecure(false), m_adminLevel(-1), + m_stationId(0), m_requestedAdminSuid(0), m_gameBits(0), m_subscriptionBits(0), + m_waitingForCharacterLoginDeletion(false), m_waitingForCharacterClusterDeletion(false) { } //----------------------------------------------------------------------- @@ -52,18 +44,17 @@ void ClientConnection::onConnectionClosed() { // client has disconnected if (m_stationId) { DEBUG_REPORT_LOG(true, ("Client %lu disconnected\n", m_stationId)); - LOG("LoginClientConnection", - ("onConnectionClosed() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); + LOG("LoginClientConnection", ("onConnectionClosed() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); } LoginServer::getInstance().removeClient(m_clientId); - /* if ((ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) && !m_isValidated) { - SessionApiClient *session = LoginServer::getInstance().getSessionApiClient(); - if (session) { - session->dropClient(this); - } - }*/ + /* if ((ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) && !m_isValidated) { + SessionApiClient *session = LoginServer::getInstance().getSessionApiClient(); + if (session) { + session->dropClient(this); + } + }*/ } @@ -73,8 +64,7 @@ void ClientConnection::onConnectionOpened() { m_clientId = LoginServer::getInstance().addClient(*this); setOverflowLimit(ConfigLoginServer::getClientOverflowLimit()); - LOG("LoginClientConnection", - ("onConnectionOpened() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); + LOG("LoginClientConnection", ("onConnectionOpened() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); } //----------------------------------------------------------------------- @@ -100,8 +90,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // send the client the server "now" Epoch time so that the // client has an idea of how much difference there is between // the client's Epoch time and the server Epoch time - GenericValueTypeMessage const serverNowEpochTime( - "ServerNowEpochTime", static_cast(::time(nullptr))); + GenericValueTypeMessage const serverNowEpochTime("ServerNowEpochTime", static_cast(::time(nullptr))); send(serverNowEpochTime, true); LoginClientId id(ri); @@ -135,16 +124,13 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { } case constcrc("DeleteCharacterMessage") : { DeleteCharacterMessage msg(ri); - std::vector::const_iterator f = std::find(m_charactersPendingDeletion.begin(), - m_charactersPendingDeletion.end(), - msg.getCharacterId()); + std::vector::const_iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), msg.getCharacterId()); if ((m_waitingForCharacterLoginDeletion || m_waitingForCharacterClusterDeletion) && f != m_charactersPendingDeletion.end()) { DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_ALREADY_IN_PROGRESS); send(reply, true); } else { - if (LoginServer::getInstance().deleteCharacter(msg.getClusterId(), msg.getCharacterId(), - getStationId())) { + if (LoginServer::getInstance().deleteCharacter(msg.getClusterId(), msg.getCharacterId(), getStationId())) { m_waitingForCharacterLoginDeletion = true; m_waitingForCharacterClusterDeletion = true; m_charactersPendingDeletion.push_back(msg.getCharacterId()); @@ -156,8 +142,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { break; } } - } - catch (const Archive::ReadException &readException) { + } catch (const Archive::ReadException &readException) { WARNING(true, ("Archive read error (%s) on message from client. Disconnecting client.", readException.what())); disconnect(); } @@ -233,8 +218,8 @@ void ClientConnection::validateClient(const std::string &id, const std::string & std::string child(i.second); if (!child.empty()) { - REPORT_LOG((parent_id != child_id), - ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); + REPORT_LOG((parent_id != + child_id), ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); // insert all related accounts, if not already there, into the db if (parent_id != child_id) { @@ -245,8 +230,7 @@ void ClientConnection::validateClient(const std::string &id, const std::string & } } - LOG("LoginClientConnection", - ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); + LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); m_stationId = user_id; @@ -264,16 +248,14 @@ void ClientConnection::validateClient(const std::string &id, const std::string & void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId &characterId) { m_waitingForCharacterLoginDeletion = false; if (!m_waitingForCharacterClusterDeletion) { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), - m_charactersPendingDeletion.end(), characterId); + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); if (f != m_charactersPendingDeletion.end()) { m_charactersPendingDeletion.erase(f); } DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); send(reply, true); - LOG("CustomerService", - ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); + LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); } } @@ -282,8 +264,7 @@ void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId &char void ClientConnection::onCharacterDeletedFromCluster(const NetworkId &characterId) { m_waitingForCharacterClusterDeletion = false; if (!m_waitingForCharacterLoginDeletion) { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), - m_charactersPendingDeletion.end(), characterId); + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); if (f != m_charactersPendingDeletion.end()) { m_charactersPendingDeletion.erase(f); @@ -292,8 +273,7 @@ void ClientConnection::onCharacterDeletedFromCluster(const NetworkId &characterI DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); send(reply, true); - LOG("CustomerService", - ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); + LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); } } diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 2082af76..0df5fc58 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -78,43 +78,36 @@ //----------------------------------------------------------------------- -namespace LoginServerNamespace -{ - struct ConnectionServerEntryLessThan : public std::binary_function - { - bool operator()(const LoginServer::ConnectionServerEntry & x, const LoginServer::ConnectionServerEntry & y) const; - }; //lint !e1509 // (base class destructor for class 'binary_function' is not virtual -- Effective C++ #14) // binary_function defines 3 typedefs required for the Adaptable Binary Function concept, The destructor is generated by the compiler and beyond our control +namespace LoginServerNamespace { + struct ConnectionServerEntryLessThan + : public std::binary_function { + bool operator()(const LoginServer::ConnectionServerEntry &x, const LoginServer::ConnectionServerEntry &y) const; + }; //lint !e1509 // (base class destructor for class 'binary_function' is not virtual -- Effective C++ #14) // binary_function defines 3 typedefs required for the Adaptable Binary Function concept, The destructor is generated by the compiler and beyond our control - enum - { - WORLD_COUNT_CHANNEL, - CLUSTER_COUNT_CHANNEL - }; + enum { + WORLD_COUNT_CHANNEL, CLUSTER_COUNT_CHANNEL + }; - // Very simple function to determine if a "threshold" has been crossed - bool hasCrossedThreshold(int thresholdValue, int oldValue, int newValue) - { - bool result = false; + // Very simple function to determine if a "threshold" has been crossed + bool hasCrossedThreshold(int thresholdValue, int oldValue, int newValue) { + bool result = false; - if ((oldValue < thresholdValue) && (newValue >= thresholdValue)) - { - // Crossed over the threshold - result = true; - } - else if ((oldValue >= thresholdValue) && (newValue < thresholdValue)) - { - // Crossed back down under the threshold - result = true; - } + if ((oldValue < thresholdValue) && (newValue >= thresholdValue)) { + // Crossed over the threshold + result = true; + } else if ((oldValue >= thresholdValue) && (newValue < thresholdValue)) { + // Crossed back down under the threshold + result = true; + } - return result; - } + return result; + } - // for testing purpose when not using session authentication, store - // the account feature Ids here, which will get cleared (obviously) - // when the LoginServer is restarted - std::map > s_nonSessionTestingAccountSwgFeatureIds; - std::map > s_nonSessionTestingAccountSwgTcgFeatureIds; + // for testing purpose when not using session authentication, store + // the account feature Ids here, which will get cleared (obviously) + // when the LoginServer is restarted + std::map > s_nonSessionTestingAccountSwgFeatureIds; + std::map > s_nonSessionTestingAccountSwgTcgFeatureIds; } //----------------------------------------------------------------------- @@ -123,136 +116,119 @@ using namespace LoginServerNamespace; //----------------------------------------------------------------------- -bool ConnectionServerEntryLessThan::operator()(const LoginServer::ConnectionServerEntry &x, const LoginServer::ConnectionServerEntry &y) const -{ - return x.numClients < y.numClients; +bool +ConnectionServerEntryLessThan::operator()(const LoginServer::ConnectionServerEntry &x, const LoginServer::ConnectionServerEntry &y) const { + return x.numClients < y.numClients; } //----------------------------------------------------------------------- -LoginServer::LoginServer() : - Singleton(), - MessageDispatch::Receiver(), - done(false), - m_centralService(nullptr), - clientService(0), - pingService(0), - keyServer(0), - m_clientMap(), - m_clusterList(), - m_validatedClientMap(), - m_clusterStatusChanged(false), - m_soeMonitor(0) -{ - NetworkSetupData setup; - setup.port = ConfigLoginServer::getClientServicePort(); - setup.maxConnections = ConfigLoginServer::getMaxClients(); - setup.maxConnectionsPerIP = ConfigLoginServer::getMaxConnectionsPerIP(); - setup.oldestUnacknowledgedTimeout = 30000; - setup.keepAliveDelay = 45000; - setup.compress = ConfigLoginServer::getCompressClientNetworkTraffic(); - setup.useTcp = false; +LoginServer::LoginServer() + : Singleton(), MessageDispatch::Receiver(), done(false), m_centralService(nullptr), + clientService(0), pingService(0), keyServer(0), m_clientMap(), m_clusterList(), m_validatedClientMap(), + m_clusterStatusChanged(false), m_soeMonitor(0) { + NetworkSetupData setup; + setup.port = ConfigLoginServer::getClientServicePort(); + setup.maxConnections = ConfigLoginServer::getMaxClients(); + setup.maxConnectionsPerIP = ConfigLoginServer::getMaxConnectionsPerIP(); + setup.oldestUnacknowledgedTimeout = 30000; + setup.keepAliveDelay = 45000; + setup.compress = ConfigLoginServer::getCompressClientNetworkTraffic(); + setup.useTcp = false; - clientService = new Service(ConnectionAllocator(), setup); - setup.compress = false; + clientService = new Service(ConnectionAllocator(), setup); + setup.compress = false; - setup.port = ConfigLoginServer::getPingServicePort(); - pingService = new Service(ConnectionAllocator(), setup); - setup.useTcp = true; + setup.port = ConfigLoginServer::getPingServicePort(); + pingService = new Service(ConnectionAllocator(), setup); + setup.useTcp = true; - if (ConfigLoginServer::getDevelopmentMode()) - { - setup.port = ConfigLoginServer::getCentralServicePort(); - m_centralService = new Service(ConnectionAllocator(), setup); - } + if (ConfigLoginServer::getDevelopmentMode()) { + setup.port = ConfigLoginServer::getCentralServicePort(); + m_centralService = new Service(ConnectionAllocator(), setup); + } - // only start the customer tool connection listener if the port is set (defaults to 0) - setup.port = ConfigLoginServer::getCSToolPort(); - if (setup.port) - { - m_CSService = new Service(ConnectionAllocator(), setup); - } + // only start the customer tool connection listener if the port is set (defaults to 0) + setup.port = ConfigLoginServer::getCSToolPort(); + if (setup.port) { + m_CSService = new Service(ConnectionAllocator(), setup); + } - // set up message connections - connectToMessage("ClaimRewardsMessage"); - connectToMessage("ConnectionClosed"); - connectToMessage("ConnectionServerDown"); //Sent to login from central when connection server goes down - connectToMessage("LoginClusterName"); - connectToMessage("LoginClusterName2"); - connectToMessage("LoginConnectionServerAddress"); //Sent to login from central after reconnecting. - connectToMessage("LoginCreateCharacterMessage"); - connectToMessage("LoginRestoreCharacterMessage"); - connectToMessage("LoginUpgradeAccountMessage"); - connectToMessage("PreloadFinishedMessage"); - connectToMessage("PurgeCompleteMessage"); - connectToMessage("RenameCharacterMessage"); - connectToMessage("TransferRequestMoveValidation"); - connectToMessage("TransferReplyNameValidation"); - connectToMessage("TransferLoginCharacterToDestinationServer"); - connectToMessage("UpdateLoginConnectionServerStatus"); - connectToMessage("UpdatePlayerCountMessage"); - connectToMessage("ValidateAccountMessage"); - connectToMessage("CntrlSrvDropDupeConns"); - connectToMessage("OccupyUnlockedSlotReq"); - connectToMessage("VacateUnlockedSlotReq"); - connectToMessage("SwapUnlockedSlotReq"); - connectToMessage("AdjustAccountFeatureIdRequest"); - connectToMessage("AccountFeatureIdRequest"); - connectToMessage("FeatureIdTransactionRequest"); - connectToMessage("FeatureIdTransactionSyncUpdate"); - keyServer = new KeyServer; + // set up message connections + connectToMessage("ClaimRewardsMessage"); + connectToMessage("ConnectionClosed"); + connectToMessage("ConnectionServerDown"); //Sent to login from central when connection server goes down + connectToMessage("LoginClusterName"); + connectToMessage("LoginClusterName2"); + connectToMessage("LoginConnectionServerAddress"); //Sent to login from central after reconnecting. + connectToMessage("LoginCreateCharacterMessage"); + connectToMessage("LoginRestoreCharacterMessage"); + connectToMessage("LoginUpgradeAccountMessage"); + connectToMessage("PreloadFinishedMessage"); + connectToMessage("PurgeCompleteMessage"); + connectToMessage("RenameCharacterMessage"); + connectToMessage("TransferRequestMoveValidation"); + connectToMessage("TransferReplyNameValidation"); + connectToMessage("TransferLoginCharacterToDestinationServer"); + connectToMessage("UpdateLoginConnectionServerStatus"); + connectToMessage("UpdatePlayerCountMessage"); + connectToMessage("ValidateAccountMessage"); + connectToMessage("CntrlSrvDropDupeConns"); + connectToMessage("OccupyUnlockedSlotReq"); + connectToMessage("VacateUnlockedSlotReq"); + connectToMessage("SwapUnlockedSlotReq"); + connectToMessage("AdjustAccountFeatureIdRequest"); + connectToMessage("AccountFeatureIdRequest"); + connectToMessage("FeatureIdTransactionRequest"); + connectToMessage("FeatureIdTransactionSyncUpdate"); + keyServer = new KeyServer; } //----------------------------------------------------------------------- -LoginServer::~LoginServer() -{ - delete keyServer; +LoginServer::~LoginServer() { + delete keyServer; } //----------------------------------------------------------------------- -int LoginServer::addClient(ClientConnection & client) -{ - DEBUG_FATAL(client.getIsValidated(), ("Tried to add an already validated client?!")); - //Perhaps add a debug only check to make sure a client connection isn't in twice...I'm not sure how that could happen. +int LoginServer::addClient(ClientConnection &client) { + DEBUG_FATAL(client.getIsValidated(), ("Tried to add an already validated client?!")); + //Perhaps add a debug only check to make sure a client connection isn't in twice...I'm not sure how that could happen. - static int nextClientId = 0; - int tmp = ++nextClientId; - m_clientMap[tmp] = &client; - return tmp; + static int nextClientId = 0; + int tmp = ++nextClientId; + m_clientMap[tmp] = &client; + return tmp; } //----------------------------------------------------------------------- -ClientConnection* LoginServer::getValidatedClient(const StationId& clientId) -{ - std::map::iterator i = m_validatedClientMap.find(clientId); - if (i == m_validatedClientMap.end()) - return 0; - return i->second; +ClientConnection *LoginServer::getValidatedClient(const StationId &clientId) { + std::map::iterator i = m_validatedClientMap.find(clientId); + if (i == m_validatedClientMap.end()) { + return 0; + } + return i->second; } //----------------------------------------------------------------------- -ClientConnection* LoginServer::getUnvalidatedClient(int clientId) -{ - WARNING_STRICT_FATAL(clientId == 0, ("Tried to get an unvalidated client with client id == 0")); - std::map::iterator i = m_clientMap.find(clientId); - if (i == m_clientMap.end()) - return 0; - WARNING_STRICT_FATAL(i->second->getIsValidated(), ("Returning validated client from call to getUnvalidatedClient()")); - return i->second; +ClientConnection *LoginServer::getUnvalidatedClient(int clientId) { + WARNING_STRICT_FATAL(clientId == 0, ("Tried to get an unvalidated client with client id == 0")); + std::map::iterator i = m_clientMap.find(clientId); + if (i == m_clientMap.end()) { + return 0; + } + WARNING_STRICT_FATAL(i->second->getIsValidated(), ("Returning validated client from call to getUnvalidatedClient()")); + return i->second; } //----------------------------------------------------------------------- -void LoginServer::removeClient(int clientId) -{ - std::map::iterator i = m_clientMap.find(clientId); - if (i != m_clientMap.end()) - { - if (i->second->getIsValidated()) - { +void LoginServer::removeClient(int clientId) { + std::map::iterator i = m_clientMap.find(clientId); + if (i != m_clientMap.end()) { + if (i->second->getIsValidated()) { IGNORE_RETURN(m_validatedClientMap.erase(i->second->getStationId())); } IGNORE_RETURN(m_clientMap.erase(clientId)); @@ -261,780 +237,692 @@ void LoginServer::removeClient(int clientId) //----------------------------------------------------------------------- -void LoginServer::installSessionValidation() -{ - /*int i = 0; - std::vector sessionServers; +void LoginServer::installSessionValidation() { + /*int i = 0; + std::vector sessionServers; - int numberOfSessionServers = ConfigLoginServer::getNumberOfSessionServers(); - for (i = 0; i < numberOfSessionServers; ++i) - { - char const * const p = ConfigLoginServer::getSessionServer(i); - if (p) - { - REPORT_LOG(true, ("Using session server %s\n", p)); - sessionServers.push_back(p); - } - } + int numberOfSessionServers = ConfigLoginServer::getNumberOfSessionServers(); + for (i = 0; i < numberOfSessionServers; ++i) + { + char const * const p = ConfigLoginServer::getSessionServer(i); + if (p) + { + REPORT_LOG(true, ("Using session server %s\n", p)); + sessionServers.push_back(p); + } + } - // if there were none specified, use defaults - FATAL(i == 0, ("No session servers specified for session API")); + // if there were none specified, use defaults + FATAL(i == 0, ("No session servers specified for session API")); - m_sessionApiClient = new SessionApiClient(&sessionServers[0], i);*/ + m_sessionApiClient = new SessionApiClient(&sessionServers[0], i);*/ - return; + return; } //----------------------------------------------------------------------- -bool LoginServer::deleteCharacter(uint32 clusterId, NetworkId const & characterId, StationId suid) -{ - const ClusterListEntry *cle = findClusterById(clusterId); - if (cle) - { - if (cle->m_centralServerConnection) - { - ServerDeleteCharacterMessage smsg(suid, characterId, 0); - cle->m_centralServerConnection->send(smsg, true); +bool LoginServer::deleteCharacter(uint32 clusterId, NetworkId const &characterId, StationId suid) { + const ClusterListEntry *cle = findClusterById(clusterId); + if (cle) { + if (cle->m_centralServerConnection) { + ServerDeleteCharacterMessage smsg(suid, characterId, 0); + cle->m_centralServerConnection->send(smsg, true); - ClientConnection* target = getValidatedClient(suid); - if (target) - { - target->onCharacterDeletedFromCluster(characterId); - } + ClientConnection *target = getValidatedClient(suid); + if (target) { + target->onCharacterDeletedFromCluster(characterId); + } - DatabaseConnection::getInstance().deleteCharacter(clusterId, characterId, suid); - return true; - } - else - { - DEBUG_REPORT_LOG(true, ("User %lu requested deleting character %s on cluster %lu, but the cluster is not currently connected.\n", suid, characterId.getValueString().c_str(), clusterId)); - return false; - } - } - else - { - DEBUG_REPORT_LOG(true, ("User %lu requested deleting character %s on cluster %lu, but we have no cluster with that number.\n", suid, characterId.getValueString().c_str(), clusterId)); - return false; - } + DatabaseConnection::getInstance().deleteCharacter(clusterId, characterId, suid); + return true; + } else { + DEBUG_REPORT_LOG(true, ("User %lu requested deleting character %s on cluster %lu, but the cluster is not currently connected.\n", suid, characterId.getValueString().c_str(), clusterId)); + return false; + } + } else { + DEBUG_REPORT_LOG(true, ("User %lu requested deleting character %s on cluster %lu, but we have no cluster with that number.\n", suid, characterId.getValueString().c_str(), clusterId)); + return false; + } } //----------------------------------------------------------------------- -const KeyShare::Key & LoginServer::getCurrentKey(void) const -{ - return keyServer->getKey(0); +const KeyShare::Key &LoginServer::getCurrentKey(void) const { + return keyServer->getKey(0); } //----------------------------------------------------------------------- -SessionApiClient * LoginServer::getSessionApiClient() -{ - return m_sessionApiClient; +SessionApiClient *LoginServer::getSessionApiClient() { + return m_sessionApiClient; } //----------------------------------------------------------------------- -KeyShare::Token LoginServer::makeToken(const unsigned char * const data, const uint32 dataLen) const -{ - return keyServer->makeToken(data, dataLen); +KeyShare::Token LoginServer::makeToken(const unsigned char *const data, const uint32 dataLen) const { + return keyServer->makeToken(data, dataLen); } //----------------------------------------------------------------------- -void LoginServer::pushAllKeys(CentralServerConnection * targetGameServer) const -{ - for (int i = static_cast(keyServer->getKeyCount()) - 1; i >= 0; i--) - { - LoginKeyPush pk(keyServer->getKey(static_cast(i))); - targetGameServer->send(pk, true); - } +void LoginServer::pushAllKeys(CentralServerConnection *targetGameServer) const { + for (int i = static_cast(keyServer->getKeyCount()) - 1; i >= 0; i--) { + LoginKeyPush pk(keyServer->getKey(static_cast(i))); + targetGameServer->send(pk, true); + } } //----------------------------------------------------------------------- -void LoginServer::pushKeyToAllServers(void) -{ - KeyShare::Key k = keyServer->getKey(0); - CentralServerConnection * c; +void LoginServer::pushKeyToAllServers(void) { + KeyShare::Key k = keyServer->getKey(0); + CentralServerConnection *c; - LoginKeyPush msg(k); + LoginKeyPush msg(k); - unsigned char s[128]; - memcpy(s, k.value, 16); //lint !e64 !e119 !e534 // not sure where lint is finding a memcpy(void *, int) prototype - DEBUG_REPORT_LOG(true, ("Key Exchange ->: ")); - for (int x = 0; x < 16; x++) - { - DEBUG_REPORT_LOG(true, ("[%3i]", s[x])); - } - DEBUG_REPORT_LOG(true, ("\n")); + unsigned char s[128]; + memcpy(s, k.value, 16); //lint !e64 !e119 !e534 // not sure where lint is finding a memcpy(void *, int) prototype + DEBUG_REPORT_LOG(true, ("Key Exchange ->: ")); + for (int x = 0; x < 16; x++) { + DEBUG_REPORT_LOG(true, ("[%3i]", s[x])); + } + DEBUG_REPORT_LOG(true, ("\n")); - for (ClusterListType::const_iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - c = (*i)->m_centralServerConnection; - if (c) - { - c->send(msg, true); - } - } + for (ClusterListType::const_iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + c = (*i)->m_centralServerConnection; + if (c) { + c->send(msg, true); + } + } } // ---------------------------------------------------------------------- -void LoginServer::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) -{ - // determine message type - const uint32 messageType = message.getType(); +void LoginServer::receiveMessage(const MessageDispatch::Emitter &source, const MessageDispatch::MessageBase &message) { + // determine message type + const uint32 messageType = message.getType(); - switch(messageType) { - case constcrc("LoginClusterName") : - case constcrc("LoginClusterName2") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const LoginClusterName msg(ri); - if (msg.getClusterName().length() > 0) - { - CentralServerConnection * connection = const_cast(safe_cast(&source)); - DEBUG_REPORT_LOG(true, ("Cluster connection %s opened\n", msg.getClusterName().c_str())); - ClusterListEntry *cle = nullptr; - if (ConfigLoginServer::getDevelopmentMode()) { - // in this mode, we trust the name sent by the cluster - cle = findClusterByName(msg.getClusterName()); + switch (messageType) { + case constcrc("LoginClusterName") : + case constcrc("LoginClusterName2") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const LoginClusterName msg(ri); + if (msg.getClusterName().length() > 0) { + CentralServerConnection *connection = const_cast(safe_cast(&source)); + DEBUG_REPORT_LOG(true, ("Cluster connection %s opened\n", msg.getClusterName().c_str())); + ClusterListEntry *cle = nullptr; + if (ConfigLoginServer::getDevelopmentMode()) { + // in this mode, we trust the name sent by the cluster + cle = findClusterByName(msg.getClusterName()); #ifdef _DEBUG - // if in debug mode, we dynamically add clusters we don't know about - // DO NOT USE ON PRODUCTION! This is where other servers are getting hijacked. - if (!cle) - { - cle = addCluster(msg.getClusterName()); - } + // if in debug mode, we dynamically add clusters we don't know about + // DO NOT USE ON PRODUCTION! This is where other servers are getting hijacked. + if (!cle) + { + cle = addCluster(msg.getClusterName()); + } #endif - } - else - { - // in this mode, the cluster name has to match what we were expecting - cle = findClusterByConnection(connection); - if (!cle) - DEBUG_FATAL(true, ("PROGRAMMER BUG: Got a connection from %s:%hu, which we weren't expecting. Cluster name is \"%s\".\n", connection->getRemoteAddress().c_str(), connection->getRemotePort(), msg.getClusterName().c_str())); - else - if (msg.getClusterName() != cle->m_clusterName) - { - WARNING(true, ("Server %i is named \"%s\" in the database. The server at the specified address (%s:%hu) reports its name as \"%s\". It will not be allowed in the service. Either the name in the database or the name in Central's config file should be corrected.\n", cle->m_clusterId, cle->m_clusterName.c_str(), connection->getRemoteAddress().c_str(), connection->getRemotePort(), msg.getClusterName().c_str())); - disconnectCluster(*cle, true, false); - cle = nullptr; - } - } + } else { + // in this mode, the cluster name has to match what we were expecting + cle = findClusterByConnection(connection); + if (!cle) { + DEBUG_FATAL(true, ("PROGRAMMER BUG: Got a connection from %s:%hu, which we weren't expecting. Cluster name is \"%s\".\n", connection->getRemoteAddress().c_str(), connection->getRemotePort(), msg.getClusterName().c_str())); + } else if (msg.getClusterName() != cle->m_clusterName) { + WARNING(true, ("Server %i is named \"%s\" in the database. The server at the specified address (%s:%hu) reports its name as \"%s\". It will not be allowed in the service. Either the name in the database or the name in Central's config file should be corrected.\n", cle->m_clusterId, cle->m_clusterName.c_str(), connection->getRemoteAddress().c_str(), connection->getRemotePort(), msg.getClusterName().c_str())); + disconnectCluster(*cle, true, false); + cle = nullptr; + } + } - if (cle) - { - cle->m_timeZone = msg.getTimeZone(); - cle->m_centralServerConnection = connection; - cle->m_connected = true; - pushAllKeys(connection); + if (cle) { + cle->m_timeZone = msg.getTimeZone(); + cle->m_centralServerConnection = connection; + cle->m_connected = true; + pushAllKeys(connection); - if (cle->m_clusterId == 0) - { - DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(), ("Programmer bug: cle->m_clusterId was 0 in non-development mode. The code before this line should have prevented this.\n")); - DEBUG_REPORT_LOG(true, ("Cluster was not on the list. Adding it to the database.\n")); - DatabaseConnection::getInstance().registerNewCluster(msg.getClusterName(), connection->getRemoteAddress()); - } - else - cle->m_centralServerConnection->setClusterId(cle->m_clusterId); + if (cle->m_clusterId == 0) { + DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(), ("Programmer bug: cle->m_clusterId was 0 in non-development mode. The code before this line should have prevented this.\n")); + DEBUG_REPORT_LOG(true, ("Cluster was not on the list. Adding it to the database.\n")); + DatabaseConnection::getInstance().registerNewCluster(msg.getClusterName(), connection->getRemoteAddress()); + } else { + cle->m_centralServerConnection->setClusterId(cle->m_clusterId); + } - m_clusterStatusChanged = true; + m_clusterStatusChanged = true; - // tell the cluster its cluster id - if (cle->m_clusterId > 0) - { - GenericValueTypeMessage const msgClusterId("ClusterId", cle->m_clusterId); - cle->m_centralServerConnection->send(msgClusterId, true); - } + // tell the cluster its cluster id + if (cle->m_clusterId > 0) { + GenericValueTypeMessage const msgClusterId("ClusterId", cle->m_clusterId); + cle->m_centralServerConnection->send(msgClusterId, true); + } - // tell the cluster about its locked and secret state - GenericValueTypeMessage > const msgState("UpdateClusterLockedAndSecretState", std::make_pair(cle->m_locked, cle->m_secret)); - cle->m_centralServerConnection->send(msgState, true); - } - } - break; - } - case constcrc("LoginConnectionServerAddress") : - { - const CentralServerConnection * cs = safe_cast(&source); - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + // tell the cluster about its locked and secret state + GenericValueTypeMessage > const msgState("UpdateClusterLockedAndSecretState", std::make_pair(cle->m_locked, cle->m_secret)); + cle->m_centralServerConnection->send(msgState, true); + } + } + break; + } + case constcrc("LoginConnectionServerAddress") : { + const CentralServerConnection *cs = safe_cast(&source); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - LoginConnectionServerAddress m(ri); //lint !e1774 !e826onServerEntry entry; - ConnectionServerEntry entry; - entry.clientServiceAddress = Address(Address(m.getClientServiceAddress(), 0).getSockAddr4()).getHostAddress(); - entry.clientServicePortPrivate = m.getClientServicePortPrivate(); - entry.clientServicePortPublic = m.getClientServicePortPublic(); - entry.id = m.getId(); - entry.numClients = m.getNumClients(); - entry.pingPort = m.getPingPort(); + LoginConnectionServerAddress m(ri); //lint !e1774 !e826onServerEntry entry; + ConnectionServerEntry entry; + entry.clientServiceAddress = Address(Address(m.getClientServiceAddress(), 0).getSockAddr4()).getHostAddress(); + entry.clientServicePortPrivate = m.getClientServicePortPrivate(); + entry.clientServicePortPublic = m.getClientServicePortPublic(); + entry.id = m.getId(); + entry.numClients = m.getNumClients(); + entry.pingPort = m.getPingPort(); - DEBUG_REPORT_LOG(true, ("ConnectionServer Reconnect - address from connection server (%s), address after conversion (%s)\n", m.getClientServiceAddress().c_str(), entry.clientServiceAddress.c_str())); + DEBUG_REPORT_LOG(true, ("ConnectionServer Reconnect - address from connection server (%s), address after conversion (%s)\n", m.getClientServiceAddress().c_str(), entry.clientServiceAddress.c_str())); - ClusterListEntry *cle = findClusterByConnection(cs); - if (cle) - { - WARNING_STRICT_FATAL(!cle->m_centralServerConnection, ("Got reconnect for connection server with no central! Cluster %s\n", cs->getClusterName().c_str())); - std::vector::iterator i = std::find(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), entry); - if (i == cle->m_connectionServers.end()) - { - cle->m_connectionServers.push_back(entry); - m_clusterStatusChanged = true; - } - else - { - *i = entry; - } + ClusterListEntry *cle = findClusterByConnection(cs); + if (cle) { + WARNING_STRICT_FATAL(!cle->m_centralServerConnection, ("Got reconnect for connection server with no central! Cluster %s\n", cs->getClusterName().c_str())); + std::vector::iterator i = std::find(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), entry); + if (i == cle->m_connectionServers.end()) { + cle->m_connectionServers.push_back(entry); + m_clusterStatusChanged = true; + } else { + *i = entry; + } - std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); - } - else - WARNING_STRICT_FATAL(true, ("Programmer bug: Got LoginConnectionServerAddress from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); - break; - } - case constcrc("PreloadFinishedMessage") : - { - const CentralServerConnection * cs = safe_cast(&source); - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - PreloadFinishedMessage msg(ri); + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + } else { + WARNING_STRICT_FATAL(true, ("Programmer bug: Got LoginConnectionServerAddress from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } + break; + } + case constcrc("PreloadFinishedMessage") : { + const CentralServerConnection *cs = safe_cast(&source); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + PreloadFinishedMessage msg(ri); - ClusterListEntry *cle = findClusterByConnection(cs); - if (cle) - { - if (msg.getFinished()) - { - REPORT_LOG(true, ("Cluster %s is ready for players.\n", cle->m_clusterName.c_str())); - if (!cle->m_readyForPlayers) - { - cle->m_readyForPlayers = true; - m_clusterStatusChanged = true; - } - } - else - { - REPORT_LOG(true, ("Cluster %s is not ready for players.\n", cle->m_clusterName.c_str())); - if (cle->m_readyForPlayers) - { - cle->m_readyForPlayers = false; - m_clusterStatusChanged = true; - PurgeManager::onClusterNoLongerReady(cle->m_clusterId); - } - } - } - else - WARNING_STRICT_FATAL(true, ("Programmer bug: Got PreloadFinishedMessage from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); - - break; - } - case constcrc("ConnectionServerDown") : - { - const CentralServerConnection * centralConnection = safe_cast(&source); - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ConnectionServerDown c(ri); //lint !e1774 !e826 - ClusterListEntry *cle = findClusterByConnection(centralConnection); - if (cle) - { - DEBUG_REPORT_LOG(true, ("Lost a connection server %d for %s.\n", c.getId(), cle->m_clusterName.c_str())); + ClusterListEntry *cle = findClusterByConnection(cs); + if (cle) { + if (msg.getFinished()) { + REPORT_LOG(true, ("Cluster %s is ready for players.\n", cle->m_clusterName.c_str())); + if (!cle->m_readyForPlayers) { + cle->m_readyForPlayers = true; + m_clusterStatusChanged = true; + } + } else { + REPORT_LOG(true, ("Cluster %s is not ready for players.\n", cle->m_clusterName.c_str())); + if (cle->m_readyForPlayers) { + cle->m_readyForPlayers = false; + m_clusterStatusChanged = true; + PurgeManager::onClusterNoLongerReady(cle->m_clusterId); + } + } + } else { + WARNING_STRICT_FATAL(true, ("Programmer bug: Got PreloadFinishedMessage from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } - std::vector::iterator iter = cle->m_connectionServers.begin(); - bool found = false; - for (; iter != cle->m_connectionServers.end(); ++iter) - { - if (iter->id == c.getId()) - { - IGNORE_RETURN(cle->m_connectionServers.erase(iter)); - std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); - found = true; - break; - } - } - DEBUG_REPORT_LOG(!found, ("Tried to remove a connection server that wasn't in our list.\n")); - m_clusterStatusChanged = true; - } - else - WARNING_STRICT_FATAL(true, ("Programmer bug: Got ConnectionServerDown from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); - - break; - } - case constcrc("ConnectionClosed") : - { - const CentralServerConnection *c = dynamic_cast(&source); - if (c) - { - ClusterListEntry *cle = findClusterByConnection(c); - if (cle) - { - DEBUG_REPORT_LOG(true, ("Cluster connection %s closed.\n", c->getClusterName().c_str())); - disconnectCluster(*cle, false, true); - } - else - WARNING_STRICT_FATAL(true, ("Programmer bug: Cluster disconnected but it wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); - } - break; - } - case constcrc("ValidateAccountMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ValidateAccountMessage msg(ri); + break; + } + case constcrc("ConnectionServerDown") : { + const CentralServerConnection *centralConnection = safe_cast(&source); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ConnectionServerDown c(ri); //lint !e1774 !e826 + ClusterListEntry *cle = findClusterByConnection(centralConnection); + if (cle) { + DEBUG_REPORT_LOG(true, ("Lost a connection server %d for %s.\n", c.getId(), cle->m_clusterName.c_str())); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().getAccountValidationData(msg.getStationId(), conn->getClusterId(), msg.getTrack(), msg.getSubscriptionBits()); - else - WARNING_STRICT_FATAL(true, ("Expect ValidateAccountMessage's to only come from CentralServers.\n")); - break; - } - case constcrc("CntrlSrvDropDupeConns") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const msg(ri); + std::vector::iterator iter = cle->m_connectionServers.begin(); + bool found = false; + for (; iter != cle->m_connectionServers.end(); ++iter) { + if (iter->id == c.getId()) { + IGNORE_RETURN(cle->m_connectionServers.erase(iter)); + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + found = true; + break; + } + } + DEBUG_REPORT_LOG(!found, ("Tried to remove a connection server that wasn't in our list.\n")); + m_clusterStatusChanged = true; + } else { + WARNING_STRICT_FATAL(true, ("Programmer bug: Got ConnectionServerDown from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } - sendToAllClusters(msg, dynamic_cast(&source)); - break; - } - case constcrc("AdjustAccountFeatureIdRequest") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - AdjustAccountFeatureIdRequest const msg(ri); + break; + } + case constcrc("ConnectionClosed") : { + const CentralServerConnection *c = dynamic_cast(&source); + if (c) { + ClusterListEntry *cle = findClusterByConnection(c); + if (cle) { + DEBUG_REPORT_LOG(true, ("Cluster connection %s closed.\n", c->getClusterName().c_str())); + disconnectCluster(*cle, false, true); + } else { + WARNING_STRICT_FATAL(true, ("Programmer bug: Cluster disconnected but it wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } + } + break; + } + case constcrc("ValidateAccountMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ValidateAccountMessage msg(ri); - if (m_sessionApiClient) - { - // on a session authenticated cluster, this request should have been serviced by the ConnectionServer - } - else - { - // for testing purpose when not using session authentication, store - // the account feature Ids locally in memory, which will get cleared - // (obviously) when the LoginServer is restarted - std::map > * nonSessionTestingAccountFeatureIds = nullptr; - if (msg.getGameCode() == PlatformGameCode::SWG) - nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgFeatureIds; - else if (msg.getGameCode() == PlatformGameCode::SWGTCG) - nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgTcgFeatureIds; + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().getAccountValidationData(msg.getStationId(), conn->getClusterId(), msg.getTrack(), msg.getSubscriptionBits()); + } else { + WARNING_STRICT_FATAL(true, ("Expect ValidateAccountMessage's to only come from CentralServers.\n")); + } + break; + } + case constcrc("CntrlSrvDropDupeConns") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); - int currentFeatureIdCount = 0; - int updatedFeatureIdCount = 0; - if (nonSessionTestingAccountFeatureIds) - { - std::map & accountFeatureIds = (*nonSessionTestingAccountFeatureIds)[msg.getTargetStationId()]; - std::map::const_iterator accountFeatureId = accountFeatureIds.find(msg.getFeatureId()); - if (accountFeatureId != accountFeatureIds.end()) - currentFeatureIdCount = accountFeatureId->second; + sendToAllClusters(msg, dynamic_cast(&source)); + break; + } + case constcrc("AdjustAccountFeatureIdRequest") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AdjustAccountFeatureIdRequest const msg(ri); - updatedFeatureIdCount = std::max(0, currentFeatureIdCount + msg.getAdjustment()); - if (updatedFeatureIdCount > 0) - { - accountFeatureIds[msg.getFeatureId()] = updatedFeatureIdCount; - } - else - { - IGNORE_RETURN(accountFeatureIds.erase(msg.getFeatureId())); - if (accountFeatureIds.empty()) - IGNORE_RETURN(nonSessionTestingAccountFeatureIds->erase(msg.getTargetStationId())); - } - } + if (m_sessionApiClient) { + // on a session authenticated cluster, this request should have been serviced by the ConnectionServer + } else { + // for testing purpose when not using session authentication, store + // the account feature Ids locally in memory, which will get cleared + // (obviously) when the LoginServer is restarted + std::map > *nonSessionTestingAccountFeatureIds = nullptr; + if (msg.getGameCode() == PlatformGameCode::SWG) { + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgFeatureIds; + } else if (msg.getGameCode() == PlatformGameCode::SWGTCG) { + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgTcgFeatureIds; + } - // CS log SWG TCG account feature grant or SWG account feature grant for reward item trade in - if (nonSessionTestingAccountFeatureIds && !msg.getTargetPlayerDescription().empty() && msg.getTargetItem().isValid() && !msg.getTargetItemDescription().empty()) - { - if (msg.getGameCode() == PlatformGameCode::SWGTCG) - LOG("CustomerService", ("TcgRedemption: %s redeemed %s for SWGTCG account feature Id %lu (%d -> %d)", msg.getTargetPlayerDescription().c_str(), msg.getTargetItemDescription().c_str(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount)); - else if (msg.getGameCode() == PlatformGameCode::SWG) - LOG("CustomerService", ("VeteranRewards: %s traded in %s for SWG account feature Id %lu (%d -> %d)", msg.getTargetPlayerDescription().c_str(), msg.getTargetItemDescription().c_str(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount)); - } + int currentFeatureIdCount = 0; + int updatedFeatureIdCount = 0; + if (nonSessionTestingAccountFeatureIds) { + std::map &accountFeatureIds = (*nonSessionTestingAccountFeatureIds)[msg.getTargetStationId()]; + std::map::const_iterator accountFeatureId = accountFeatureIds.find(msg.getFeatureId()); + if (accountFeatureId != accountFeatureIds.end()) { + currentFeatureIdCount = accountFeatureId->second; + } - const CentralServerConnection * conn = dynamic_cast(&source); - if (conn) - { - AdjustAccountFeatureIdResponse const rsp(msg.getRequestingPlayer(), msg.getGameServer(), msg.getTargetPlayer(), msg.getTargetPlayerDescription(), msg.getTargetStationId(), msg.getTargetItem(), msg.getTargetItemDescription(), msg.getGameCode(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount, (nonSessionTestingAccountFeatureIds ? RESULT_SUCCESS : RESULT_CANCELLED), false); - sendToCluster(conn->getClusterId(), rsp); - } - } - break; - } - case constcrc("AccountFeatureIdRequest") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - AccountFeatureIdRequest const msg(ri); + updatedFeatureIdCount = std::max(0, currentFeatureIdCount + msg.getAdjustment()); + if (updatedFeatureIdCount > 0) { + accountFeatureIds[msg.getFeatureId()] = updatedFeatureIdCount; + } else { + IGNORE_RETURN(accountFeatureIds.erase(msg.getFeatureId())); + if (accountFeatureIds.empty()) { + IGNORE_RETURN(nonSessionTestingAccountFeatureIds->erase(msg.getTargetStationId())); + } + } + } - if (m_sessionApiClient) - { - // on a session authenticated cluster, this request should have been serviced by the ConnectionServer - } - else - { - // for testing purpose when not using session authentication, store - // the account feature Ids locally in memory, which will get cleared - // (obviously) when the LoginServer is restarted - std::map > * nonSessionTestingAccountFeatureIds = nullptr; - if (msg.getGameCode() == PlatformGameCode::SWG) - nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgFeatureIds; - else if (msg.getGameCode() == PlatformGameCode::SWGTCG) - nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgTcgFeatureIds; + // CS log SWG TCG account feature grant or SWG account feature grant for reward item trade in + if (nonSessionTestingAccountFeatureIds && !msg.getTargetPlayerDescription().empty() && + msg.getTargetItem().isValid() && !msg.getTargetItemDescription().empty()) { + if (msg.getGameCode() == PlatformGameCode::SWGTCG) { + LOG("CustomerService", ("TcgRedemption: %s redeemed %s for SWGTCG account feature Id %lu (%d -> %d)", msg.getTargetPlayerDescription().c_str(), msg.getTargetItemDescription().c_str(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount)); + } else if (msg.getGameCode() == PlatformGameCode::SWG) { + LOG("CustomerService", ("VeteranRewards: %s traded in %s for SWG account feature Id %lu (%d -> %d)", msg.getTargetPlayerDescription().c_str(), msg.getTargetItemDescription().c_str(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount)); + } + } - static std::map const empty; - std::map const * accountFeatureIds = ∅ + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + AdjustAccountFeatureIdResponse const rsp(msg.getRequestingPlayer(), msg.getGameServer(), msg.getTargetPlayer(), msg.getTargetPlayerDescription(), msg.getTargetStationId(), msg.getTargetItem(), msg.getTargetItemDescription(), msg.getGameCode(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount, (nonSessionTestingAccountFeatureIds + ? RESULT_SUCCESS + : RESULT_CANCELLED), false); + sendToCluster(conn->getClusterId(), rsp); + } + } + break; + } + case constcrc("AccountFeatureIdRequest") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AccountFeatureIdRequest const msg(ri); - if (nonSessionTestingAccountFeatureIds) - { - std::map >::const_iterator iterFind = nonSessionTestingAccountFeatureIds->find(msg.getTargetStationId()); - if (iterFind != nonSessionTestingAccountFeatureIds->end()) - accountFeatureIds = &(iterFind->second); - } + if (m_sessionApiClient) { + // on a session authenticated cluster, this request should have been serviced by the ConnectionServer + } else { + // for testing purpose when not using session authentication, store + // the account feature Ids locally in memory, which will get cleared + // (obviously) when the LoginServer is restarted + std::map > *nonSessionTestingAccountFeatureIds = nullptr; + if (msg.getGameCode() == PlatformGameCode::SWG) { + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgFeatureIds; + } else if (msg.getGameCode() == PlatformGameCode::SWGTCG) { + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgTcgFeatureIds; + } - const CentralServerConnection * conn = dynamic_cast(&source); - if (conn) - { - static std::map const empty; - AccountFeatureIdResponse const rsp(msg.getRequester(), msg.getGameServer(), msg.getTarget(), msg.getTargetStationId(), msg.getGameCode(), msg.getRequestReason(), RESULT_SUCCESS, false, *accountFeatureIds, empty); - sendToCluster(conn->getClusterId(), rsp); - } - } - break; - } - case constcrc("FeatureIdTransactionRequest") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - FeatureIdTransactionRequest const fitr(ri); + static std::map const empty; + std::map const *accountFeatureIds = ∅ - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().featureIdTransactionRequest(conn->getClusterId(), fitr.getStationId(), fitr.getPlayer(), fitr.getGameServer()); - break; - } - case constcrc("FeatureIdTransactionSyncUpdate") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - FeatureIdTransactionSyncUpdate const fitsu(ri); + if (nonSessionTestingAccountFeatureIds) { + std::map < uint32, std::map < uint32, int > > ::const_iterator + iterFind = nonSessionTestingAccountFeatureIds->find(msg.getTargetStationId()); + if (iterFind != nonSessionTestingAccountFeatureIds->end()) { + accountFeatureIds = &(iterFind->second); + } + } - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().featureIdTransactionSyncUpdate(conn->getClusterId(), fitsu.getStationId(), fitsu.getPlayer(), fitsu.getItemId(), fitsu.getAdjustment()); - break; - } - case constcrc("TransferRequestMoveValidation") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const TransferRequestMoveValidation request(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + static std::map const empty; + AccountFeatureIdResponse const rsp(msg.getRequester(), msg.getGameServer(), msg.getTarget(), msg.getTargetStationId(), msg.getGameCode(), msg.getRequestReason(), RESULT_SUCCESS, false, *accountFeatureIds, empty); + sendToCluster(conn->getClusterId(), rsp); + } + } + break; + } + case constcrc("FeatureIdTransactionRequest") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + FeatureIdTransactionRequest const fitr(ri); - TransferReplyMoveValidation::TransferReplyMoveValidationResult result = TransferReplyMoveValidation::TRMVR_can_create_regular_character; + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().featureIdTransactionRequest(conn->getClusterId(), fitr.getStationId(), fitr.getPlayer(), fitr.getGameServer()); + } + break; + } + case constcrc("FeatureIdTransactionSyncUpdate") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + FeatureIdTransactionSyncUpdate const fitsu(ri); - ClusterListEntry * cle = findClusterByName(request.getDestinationGalaxy()); - if (!cle) - { - result = TransferReplyMoveValidation::TRMVR_destination_galaxy_invalid; - } - else if (!cle->m_centralServerConnection) - { - result = TransferReplyMoveValidation::TRMVR_destination_galaxy_not_connected; - } - else if (!cle->m_readyForPlayers) - { - result = TransferReplyMoveValidation::TRMVR_destination_galaxy_in_loading; - } + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().featureIdTransactionSyncUpdate(conn->getClusterId(), fitsu.getStationId(), fitsu.getPlayer(), fitsu.getItemId(), fitsu.getAdjustment()); + } + break; + } + case constcrc("TransferRequestMoveValidation") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const TransferRequestMoveValidation request(ri); - if (result == TransferReplyMoveValidation::TRMVR_can_create_regular_character) - { - // check with DB to see if account is allowed to create character on the destination galaxy - LOG("CustomerService", ("CharacterTransfer: Received TransferRequestMoveValidation : %s (character template id %lu) on %s to %s on %s. Forwarding request to Login Database.", request.getSourceCharacter().c_str(), request.getSourceCharacterTemplateId(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); - DatabaseConnection::getInstance().getAccountValidationData(request, cle->m_centralServerConnection->getClusterId()); - } - else - { - // send failure back to originating server - TransferReplyMoveValidation reply(request.getTransferRequestSource(), request.getTrack(), request.getSourceStationId(), request.getDestinationStationId(), request.getSourceGalaxy(), request.getDestinationGalaxy(), request.getSourceCharacter(), request.getSourceCharacterId(), request.getSourceCharacterTemplateId(), request.getDestinationCharacter(), request.getCustomerLocalizedLanguage(), result); - const CentralServerConnection * conn = dynamic_cast(&source); - if (conn) - { - ClusterListEntry * sourceEntry = findClusterById(conn->getClusterId()); - if (sourceEntry && sourceEntry->m_centralServerConnection) - { - sourceEntry->m_centralServerConnection->send(reply, true); - } - } - } - break; - } - case constcrc("TransferReplyNameValidation") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const replyNameValidation(ri); + TransferReplyMoveValidation::TransferReplyMoveValidationResult result = TransferReplyMoveValidation::TRMVR_can_create_regular_character; - const CentralServerConnection * conn = dynamic_cast(&source); - if (conn) - { - ClusterListEntry * cle = findClusterByName(replyNameValidation.getValue().second.getSourceGalaxy()); - if (cle && cle->m_centralServerConnection) - { - LOG("CustomerService", ("CharacterTransfer: Received TransferReplyNameValidation from destination galaxy CentralServer, forwarding to source galaxy CentralServer : %s", replyNameValidation.getValue().second.toString().c_str())); - cle->m_centralServerConnection->send(replyNameValidation, true); - } - } - break; - } - case constcrc("TransferLoginCharacterToDestinationServer") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const login(ri); + ClusterListEntry *cle = findClusterByName(request.getDestinationGalaxy()); + if (!cle) { + result = TransferReplyMoveValidation::TRMVR_destination_galaxy_invalid; + } else if (!cle->m_centralServerConnection) { + result = TransferReplyMoveValidation::TRMVR_destination_galaxy_not_connected; + } else if (!cle->m_readyForPlayers) { + result = TransferReplyMoveValidation::TRMVR_destination_galaxy_in_loading; + } - const CentralServerConnection * conn = dynamic_cast(&source); - if (conn) - { - ClusterListEntry * cle = findClusterByName(login.getValue().getDestinationGalaxy()); - if (cle && cle->m_centralServerConnection) - { - LOG("CustomerService", ("CharacterTransfer: Received TransferLoginCharacterToDestinationServer from source galaxy CentralServer, forwarding to destination galaxy CentralServer : %s", login.getValue().toString().c_str())); - cle->m_centralServerConnection->send(login, true); - } - } - break; - } - case constcrc("UpdateLoginConnectionServerStatus") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - UpdateLoginConnectionServerStatus msg(ri); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - { - ClusterListEntry *cle = findClusterByConnection(conn); - if (cle) - { - std::vector::iterator i = cle->m_connectionServers.begin(); - for (; i != cle->m_connectionServers.end(); ++i) - { - if (i->id == msg.getId()) - { - i->clientServicePortPublic = msg.getPublicPort(); - i->clientServicePortPrivate = msg.getPrivatePort(); - i->numClients = msg.getPlayerCount(); - break; - } - } - std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); - } - } - break; - } - case constcrc("UpdatePlayerCountMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - UpdatePlayerCountMessage msg(ri); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - { - ClusterListEntry *cle = findClusterByConnection(conn); - if (cle) - { - const int tutorialPlayerCount = (msg.getEmptySceneCount() + msg.getTutorialSceneCount() + msg.getFalconSceneCount()); + if (result == TransferReplyMoveValidation::TRMVR_can_create_regular_character) { + // check with DB to see if account is allowed to create character on the destination galaxy + LOG("CustomerService", ("CharacterTransfer: Received TransferRequestMoveValidation : %s (character template id %lu) on %s to %s on %s. Forwarding request to Login Database.", request.getSourceCharacter().c_str(), request.getSourceCharacterTemplateId(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); + DatabaseConnection::getInstance().getAccountValidationData(request, cle->m_centralServerConnection->getClusterId()); + } else { + // send failure back to originating server + TransferReplyMoveValidation reply(request.getTransferRequestSource(), request.getTrack(), request.getSourceStationId(), request.getDestinationStationId(), request.getSourceGalaxy(), request.getDestinationGalaxy(), request.getSourceCharacter(), request.getSourceCharacterId(), request.getSourceCharacterTemplateId(), request.getDestinationCharacter(), request.getCustomerLocalizedLanguage(), result); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + ClusterListEntry *sourceEntry = findClusterById(conn->getClusterId()); + if (sourceEntry && sourceEntry->m_centralServerConnection) { + sourceEntry->m_centralServerConnection->send(reply, true); + } + } + } + break; + } + case constcrc("TransferReplyNameValidation") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const replyNameValidation(ri); - // We only want to update the clients if some "threshold" has been crossed - if ((cle->m_notRecommendedCentral != msg.getLoadedRecently()) - || hasCrossedThreshold(cle->m_onlineTutorialLimit, cle->m_numTutorialPlayers, tutorialPlayerCount) - || hasCrossedThreshold(cle->m_onlineFreeTrialLimit, cle->m_numFreeTrialPlayers, msg.getFreeTrialCount()) - || hasCrossedThreshold(cle->m_onlinePlayerLimit, cle->m_numPlayers, msg.getCount())) - { - m_clusterStatusChanged = true; - } + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + ClusterListEntry *cle = findClusterByName(replyNameValidation.getValue().second.getSourceGalaxy()); + if (cle && cle->m_centralServerConnection) { + LOG("CustomerService", ("CharacterTransfer: Received TransferReplyNameValidation from destination galaxy CentralServer, forwarding to source galaxy CentralServer : %s", replyNameValidation.getValue().second.toString().c_str())); + cle->m_centralServerConnection->send(replyNameValidation, true); + } + } + break; + } + case constcrc("TransferLoginCharacterToDestinationServer") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const login(ri); - cle->m_numPlayers = msg.getCount(); - cle->m_numFreeTrialPlayers = msg.getFreeTrialCount(); - cle->m_notRecommendedCentral = msg.getLoadedRecently(); - cle->m_numTutorialPlayers = tutorialPlayerCount; - } - } - break; - } - case constcrc("RenameCharacterMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - RenameCharacterMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + ClusterListEntry *cle = findClusterByName(login.getValue().getDestinationGalaxy()); + if (cle && cle->m_centralServerConnection) { + LOG("CustomerService", ("CharacterTransfer: Received TransferLoginCharacterToDestinationServer from source galaxy CentralServer, forwarding to destination galaxy CentralServer : %s", login.getValue().toString().c_str())); + cle->m_centralServerConnection->send(login, true); + } + } + break; + } + case constcrc("UpdateLoginConnectionServerStatus") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + UpdateLoginConnectionServerStatus msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + ClusterListEntry *cle = findClusterByConnection(conn); + if (cle) { + std::vector::iterator i = cle->m_connectionServers.begin(); + for (; i != cle->m_connectionServers.end(); ++i) { + if (i->id == msg.getId()) { + i->clientServicePortPublic = msg.getPublicPort(); + i->clientServicePortPrivate = msg.getPrivatePort(); + i->numClients = msg.getPlayerCount(); + break; + } + } + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + } + } + break; + } + case constcrc("UpdatePlayerCountMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + UpdatePlayerCountMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + ClusterListEntry *cle = findClusterByConnection(conn); + if (cle) { + const int tutorialPlayerCount = (msg.getEmptySceneCount() + msg.getTutorialSceneCount() + + msg.getFalconSceneCount()); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().renameCharacter(conn->getClusterId(), msg.getCharacterId(), msg.getNewName(), nullptr); - else - WARNING_STRICT_FATAL(true, ("Got RenameCharacterMessage from something other than CentralServerConnection.\n")); - - break; - } - case constcrc("LoginCreateCharacterMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - LoginCreateCharacterMessage msg(ri); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().createCharacter(conn->getClusterId(), msg.getStationId(), msg.getCharacterName(), msg.getCharacterObjectId(), msg.getTemplateId(), msg.getJedi()); - - break; - } - case constcrc("LoginRestoreCharacterMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - LoginRestoreCharacterMessage msg(ri); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().restoreCharacter(conn->getClusterId(), msg.getWhoRequested(), msg.getAccount(), msg.getCharacterName(), msg.getCharacterId(), msg.getTemplateId(), msg.getJedi()); - - break; - } - case constcrc("LoginUpgradeAccountMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - LoginUpgradeAccountMessage *msg = new LoginUpgradeAccountMessage(ri); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().upgradeAccount(msg, conn->getClusterId()); - - break; - } - case constcrc("ClaimRewardsMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ClaimRewardsMessage const * msg = new ClaimRewardsMessage(ri); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - { - // current restriction is that once per account event or item cannot require a "consuming" account feature id - // TODO: looks like this is where vet rewards are consumed...the one per account thing, here - session auth may be enough? - uint32 const requiredAccountFeatureId = msg->getAccountFeatureId(); - bool const consumeAccountFeatureId = msg->getConsumeAccountFeatureId(); - if ((msg->getConsumeEvent() || msg->getConsumeItem()) && (requiredAccountFeatureId > 0) && consumeAccountFeatureId) - { - ClaimRewardsReplyMessage const rsp(msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getRewardItem(), requiredAccountFeatureId, consumeAccountFeatureId, 0, 0, false); - sendToCluster(conn->getClusterId(), rsp); - delete msg; - } - else if (requiredAccountFeatureId > 0) - { - if (m_sessionApiClient) - { - /*if (consumeAccountFeatureId) - { - // request session/Platform to update the account feature id - // SessionApiClient will own (and delete) msg - m_sessionApiClient->handleClaimRewardsMessage(conn->getClusterId(), msg); - } - else - { - LoginAPI::Feature oldFeature; - oldFeature.SetID(requiredAccountFeatureId); - oldFeature.SetData(msg->getAccountFeatureIdOldValue()); + // We only want to update the clients if some "threshold" has been crossed + if ((cle->m_notRecommendedCentral != msg.getLoadedRecently()) || + hasCrossedThreshold(cle->m_onlineTutorialLimit, cle->m_numTutorialPlayers, tutorialPlayerCount) || + hasCrossedThreshold(cle->m_onlineFreeTrialLimit, cle->m_numFreeTrialPlayers, msg.getFreeTrialCount()) || + hasCrossedThreshold(cle->m_onlinePlayerLimit, cle->m_numPlayers, msg.getCount())) { + m_clusterStatusChanged = true; + } - LoginAPI::Feature newFeature; - newFeature.SetID(requiredAccountFeatureId); - newFeature.SetData(msg->getAccountFeatureIdNewValue()); + cle->m_numPlayers = msg.getCount(); + cle->m_numFreeTrialPlayers = msg.getFreeTrialCount(); + cle->m_notRecommendedCentral = msg.getLoadedRecently(); + cle->m_numTutorialPlayers = tutorialPlayerCount; + } + } + break; + } + case constcrc("RenameCharacterMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RenameCharacterMessage msg(ri); - DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), requiredAccountFeatureId, false, oldFeature.GetConsumeCount(), newFeature.GetConsumeCount()); - delete msg; - }*/ - } - else - { - // for testing purpose when not using session authentication, store - // the account feature Ids locally in memory, which will get cleared - // (obviously) when the LoginServer is restarted - std::map & accountFeatureIds = s_nonSessionTestingAccountSwgFeatureIds[msg->getStationId()]; - std::map::const_iterator accountFeatureId = accountFeatureIds.find(requiredAccountFeatureId); - int currentFeatureIdCount = 0; - if (accountFeatureId != accountFeatureIds.end()) - currentFeatureIdCount = accountFeatureId->second; + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().renameCharacter(conn->getClusterId(), msg.getCharacterId(), msg.getNewName(), nullptr); + } else { + WARNING_STRICT_FATAL(true, ("Got RenameCharacterMessage from something other than CentralServerConnection.\n")); + } - if (currentFeatureIdCount <= 0) - { - // fail because account doesn't have required feature id - IGNORE_RETURN(accountFeatureIds.erase(requiredAccountFeatureId)); - if (accountFeatureIds.empty()) - IGNORE_RETURN(s_nonSessionTestingAccountSwgFeatureIds.erase(msg->getStationId())); + break; + } + case constcrc("LoginCreateCharacterMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginCreateCharacterMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().createCharacter(conn->getClusterId(), msg.getStationId(), msg.getCharacterName(), msg.getCharacterObjectId(), msg.getTemplateId(), msg.getJedi()); + } - ClaimRewardsReplyMessage rsp(msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getRewardItem(), requiredAccountFeatureId, consumeAccountFeatureId, 0, 0, false); - sendToCluster(conn->getClusterId(), rsp); - } - else - { - // account has required feature id so claim is success, so update feature id for claim - int const updatedFeatureIdCount = (consumeAccountFeatureId ? std::max(0, currentFeatureIdCount - 1) : currentFeatureIdCount); + break; + } + case constcrc("LoginRestoreCharacterMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginRestoreCharacterMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().restoreCharacter(conn->getClusterId(), msg.getWhoRequested(), msg.getAccount(), msg.getCharacterName(), msg.getCharacterId(), msg.getTemplateId(), msg.getJedi()); + } - if (consumeAccountFeatureId) - { - if (updatedFeatureIdCount > 0) - { - accountFeatureIds[requiredAccountFeatureId] = updatedFeatureIdCount; - } - else - { - IGNORE_RETURN(accountFeatureIds.erase(requiredAccountFeatureId)); - if (accountFeatureIds.empty()) - IGNORE_RETURN(s_nonSessionTestingAccountSwgFeatureIds.erase(msg->getStationId())); - } - } + break; + } + case constcrc("LoginUpgradeAccountMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginUpgradeAccountMessage *msg = new LoginUpgradeAccountMessage(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().upgradeAccount(msg, conn->getClusterId()); + } - // if feature id updated successfully, record transaction - DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), requiredAccountFeatureId, consumeAccountFeatureId, currentFeatureIdCount, updatedFeatureIdCount); - } + break; + } + case constcrc("ClaimRewardsMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ClaimRewardsMessage const *msg = new ClaimRewardsMessage(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + // current restriction is that once per account event or item cannot require a "consuming" account feature id + // TODO: looks like this is where vet rewards are consumed...the one per account thing, here - session auth may be enough? + uint32 const requiredAccountFeatureId = msg->getAccountFeatureId(); + bool const consumeAccountFeatureId = msg->getConsumeAccountFeatureId(); + if ((msg->getConsumeEvent() || msg->getConsumeItem()) && (requiredAccountFeatureId > 0) && + consumeAccountFeatureId) { + ClaimRewardsReplyMessage const rsp(msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getRewardItem(), requiredAccountFeatureId, consumeAccountFeatureId, 0, 0, false); + sendToCluster(conn->getClusterId(), rsp); + delete msg; + } else if (requiredAccountFeatureId > 0) { + if (m_sessionApiClient) { + /*if (consumeAccountFeatureId) + { + // request session/Platform to update the account feature id + // SessionApiClient will own (and delete) msg + m_sessionApiClient->handleClaimRewardsMessage(conn->getClusterId(), msg); + } + else + { + LoginAPI::Feature oldFeature; + oldFeature.SetID(requiredAccountFeatureId); + oldFeature.SetData(msg->getAccountFeatureIdOldValue()); - delete msg; - } - } - else - { - DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), 0, false, 0, 0); - delete msg; - } - } - else - { - delete msg; - } - - break; - } - case constcrc("PurgeCompleteMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage msg(ri); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - PurgeManager::handlePurgeCompleteOnCluster(msg.getValue(), conn->getClusterId()); - else - WARNING_STRICT_FATAL(true, ("Programmer bug: got PurgeCompleteMessage from something that couldn't be cast to a CentralServerConnection")); - - break; - } - case constcrc("OccupyUnlockedSlotReq") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage, uint32> > const occupyUnlockedSlotReq(ri); + LoginAPI::Feature newFeature; + newFeature.SetID(requiredAccountFeatureId); + newFeature.SetData(msg->getAccountFeatureIdNewValue()); - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().occupyUnlockedSlot(conn->getClusterId(), static_cast(occupyUnlockedSlotReq.getValue().first.first), occupyUnlockedSlotReq.getValue().first.second, occupyUnlockedSlotReq.getValue().second); - - break; - } - case constcrc("VacateUnlockedSlotReq") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage, uint32> > const vacateUnlockedSlotReq(ri); + DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), requiredAccountFeatureId, false, oldFeature.GetConsumeCount(), newFeature.GetConsumeCount()); + delete msg; + }*/ + } else { + // for testing purpose when not using session authentication, store + // the account feature Ids locally in memory, which will get cleared + // (obviously) when the LoginServer is restarted + std::map &accountFeatureIds = s_nonSessionTestingAccountSwgFeatureIds[msg->getStationId()]; + std::map::const_iterator accountFeatureId = accountFeatureIds.find(requiredAccountFeatureId); + int currentFeatureIdCount = 0; + if (accountFeatureId != accountFeatureIds.end()) { + currentFeatureIdCount = accountFeatureId->second; + } - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().vacateUnlockedSlot(conn->getClusterId(), static_cast(vacateUnlockedSlotReq.getValue().first.first), vacateUnlockedSlotReq.getValue().first.second, vacateUnlockedSlotReq.getValue().second); - - break; - } - case constcrc("SwapUnlockedSlotReq") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage, std::pair > > const swapUnlockedSlotReq(ri); + if (currentFeatureIdCount <= 0) { + // fail because account doesn't have required feature id + IGNORE_RETURN(accountFeatureIds.erase(requiredAccountFeatureId)); + if (accountFeatureIds.empty()) { + IGNORE_RETURN(s_nonSessionTestingAccountSwgFeatureIds.erase(msg->getStationId())); + } - const CentralServerConnection *conn = dynamic_cast(&source); - if (conn) - DatabaseConnection::getInstance().swapUnlockedSlot(conn->getClusterId(), static_cast(swapUnlockedSlotReq.getValue().first.first), swapUnlockedSlotReq.getValue().first.second, swapUnlockedSlotReq.getValue().second.second, swapUnlockedSlotReq.getValue().second.first); - - break; - } - } + ClaimRewardsReplyMessage rsp(msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getRewardItem(), requiredAccountFeatureId, consumeAccountFeatureId, 0, 0, false); + sendToCluster(conn->getClusterId(), rsp); + } else { + // account has required feature id so claim is success, so update feature id for claim + int const updatedFeatureIdCount = (consumeAccountFeatureId ? std::max(0, + currentFeatureIdCount - + 1) + : currentFeatureIdCount); + + if (consumeAccountFeatureId) { + if (updatedFeatureIdCount > 0) { + accountFeatureIds[requiredAccountFeatureId] = updatedFeatureIdCount; + } else { + IGNORE_RETURN(accountFeatureIds.erase(requiredAccountFeatureId)); + if (accountFeatureIds.empty()) { + IGNORE_RETURN(s_nonSessionTestingAccountSwgFeatureIds.erase(msg->getStationId())); + } + } + } + + // if feature id updated successfully, record transaction + DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), requiredAccountFeatureId, consumeAccountFeatureId, currentFeatureIdCount, updatedFeatureIdCount); + } + + delete msg; + } + } else { + DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), 0, false, 0, 0); + delete msg; + } + } else { + delete msg; + } + + break; + } + case constcrc("PurgeCompleteMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + PurgeManager::handlePurgeCompleteOnCluster(msg.getValue(), conn->getClusterId()); + } else { + WARNING_STRICT_FATAL(true, ("Programmer bug: got PurgeCompleteMessage from something that couldn't be cast to a CentralServerConnection")); + } + + break; + } + case constcrc("OccupyUnlockedSlotReq") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage < std::pair < std::pair < uint32, NetworkId >, uint32 > > + const occupyUnlockedSlotReq(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().occupyUnlockedSlot(conn->getClusterId(), static_cast(occupyUnlockedSlotReq.getValue().first.first), occupyUnlockedSlotReq.getValue().first.second, occupyUnlockedSlotReq.getValue().second); + } + + break; + } + case constcrc("VacateUnlockedSlotReq") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage < std::pair < std::pair < uint32, NetworkId >, uint32 > > + const vacateUnlockedSlotReq(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().vacateUnlockedSlot(conn->getClusterId(), static_cast(vacateUnlockedSlotReq.getValue().first.first), vacateUnlockedSlotReq.getValue().first.second, vacateUnlockedSlotReq.getValue().second); + } + + break; + } + case constcrc("SwapUnlockedSlotReq") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage < std::pair < std::pair < uint32, NetworkId >, std::pair < uint32, NetworkId > > > + const swapUnlockedSlotReq(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) { + DatabaseConnection::getInstance().swapUnlockedSlot(conn->getClusterId(), static_cast(swapUnlockedSlotReq.getValue().first.first), swapUnlockedSlotReq.getValue().first.second, swapUnlockedSlotReq.getValue().second.second, swapUnlockedSlotReq.getValue().second.first); + } + + break; + } + } } // ---------------------------------------------------------------------- @@ -1044,523 +932,476 @@ void LoginServer::receiveMessage(const MessageDispatch::Emitter & source, const * Also, flag whether character creation is allowed. * @see DatabaseConnection::getAccountValidationData */ -void LoginServer::validateAccount(const StationId& stationId, uint32 clusterId, uint32 subscriptionBits, bool canCreateRegular, bool canCreateJedi, bool canSkipTutorial, unsigned int track, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems) -{ - bool canLogin = false; +void +LoginServer::validateAccount(const StationId &stationId, uint32 clusterId, uint32 subscriptionBits, bool canCreateRegular, bool canCreateJedi, bool canSkipTutorial, unsigned int track, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems) { + bool canLogin = false; - ClusterListEntry *cle = findClusterById(clusterId); - if (cle && cle->m_centralServerConnection) - { - // Check login rights - // code to restrict logins based on "internal only", geographic rules, etc., goes here - // allow logins unless the cluster is full - bool clientIsInternal = false; - ClientConnection *conn = getValidatedClient(stationId); - if (conn) - { - clientIsInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); - } + ClusterListEntry *cle = findClusterById(clusterId); + if (cle && cle->m_centralServerConnection) { + // Check login rights + // code to restrict logins based on "internal only", geographic rules, etc., goes here + // allow logins unless the cluster is full + bool clientIsInternal = false; + ClientConnection *conn = getValidatedClient(stationId); + if (conn) { + clientIsInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); + } - if (clientIsInternal && ConfigLoginServer::getInternalBypassOnlineLimit()) - { - canLogin = true; - } - else if (cle->m_numPlayers <= cle->m_onlinePlayerLimit) - { - canLogin = true; + if (clientIsInternal && ConfigLoginServer::getInternalBypassOnlineLimit()) { + canLogin = true; + } else if (cle->m_numPlayers <= cle->m_onlinePlayerLimit) { + canLogin = true; - // Check cluster npe user limit - if (cle->m_numTutorialPlayers > cle->m_onlineTutorialLimit) - { - canLogin = false; - } - } + // Check cluster npe user limit + if (cle->m_numTutorialPlayers > cle->m_onlineTutorialLimit) { + canLogin = false; + } + } - if (!canLogin) - { - canCreateRegular = false; - canCreateJedi = false; - canSkipTutorial = false; - } + if (!canLogin) { + canCreateRegular = false; + canCreateJedi = false; + canSkipTutorial = false; + } - // check if we want to allow skip tutorial to all - if (ConfigLoginServer::getAllowSkipTutorialToAll()) - canSkipTutorial = true; + // check if we want to allow skip tutorial to all + if (ConfigLoginServer::getAllowSkipTutorialToAll()) { + canSkipTutorial = true; + } - ValidateAccountReplyMessage msg(stationId, canLogin, canCreateRegular, canCreateJedi, canSkipTutorial, track, consumedRewardEvents, claimedRewardItems); - cle->m_centralServerConnection->send(msg, true); - } + ValidateAccountReplyMessage msg(stationId, canLogin, canCreateRegular, canCreateJedi, canSkipTutorial, track, consumedRewardEvents, claimedRewardItems); + cle->m_centralServerConnection->send(msg, true); + } } //----------------------------------------------------------------------- -void LoginServer::validateAccountForTransfer(const TransferRequestMoveValidation & request, uint32 clusterId, uint32 sourceCharacterTemplateId, bool canCreateRegular, bool canCreateJedi) -{ - UNREF(canCreateJedi); +void +LoginServer::validateAccountForTransfer(const TransferRequestMoveValidation &request, uint32 clusterId, uint32 sourceCharacterTemplateId, bool canCreateRegular, bool canCreateJedi) { + UNREF(canCreateJedi); - // if transfer request was made with console god command, always allow - // the character to be created on the destination galaxy; we assume - // the user of the console god command knows that he's doing with regard - // to making sure that the destination galaxy would not end up with too many - // characters on the account on the destination galaxy - if (!canCreateRegular && (request.getTransferRequestSource() == TransferRequestMoveValidation::TRS_console_god_command)) - { - LOG("CustomerService", ("CharacterTransfer: Account Validation request for %s on %s to %s on %s is complete. Even though canCreateRegular=false, we are setting canCreateRegular=true because this request came from the console god command.", request.getSourceCharacter().c_str(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); - canCreateRegular = true; - } + // if transfer request was made with console god command, always allow + // the character to be created on the destination galaxy; we assume + // the user of the console god command knows that he's doing with regard + // to making sure that the destination galaxy would not end up with too many + // characters on the account on the destination galaxy + if (!canCreateRegular && + (request.getTransferRequestSource() == TransferRequestMoveValidation::TRS_console_god_command)) { + LOG("CustomerService", ("CharacterTransfer: Account Validation request for %s on %s to %s on %s is complete. Even though canCreateRegular=false, we are setting canCreateRegular=true because this request came from the console god command.", request.getSourceCharacter().c_str(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); + canCreateRegular = true; + } - LOG("CustomerService", ("CharacterTransfer: Account Validation request for %s on %s to %s on %s is complete. Sending response to CentralServer", request.getSourceCharacter().c_str(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); + LOG("CustomerService", ("CharacterTransfer: Account Validation request for %s on %s to %s on %s is complete. Sending response to CentralServer", request.getSourceCharacter().c_str(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); - // if this request came from a game server and the validation fails, send - // response to the source galaxy so an error message can be displayed to the user - if ((request.getTransferRequestSource() != TransferRequestMoveValidation::TRS_transfer_server) && !canCreateRegular) - { - ClusterListEntry * sourceGalaxyCle = findClusterByName(request.getSourceGalaxy()); - if (sourceGalaxyCle && sourceGalaxyCle->m_centralServerConnection) - { - clusterId = sourceGalaxyCle->m_centralServerConnection->getClusterId(); - } - } + // if this request came from a game server and the validation fails, send + // response to the source galaxy so an error message can be displayed to the user + if ((request.getTransferRequestSource() != TransferRequestMoveValidation::TRS_transfer_server) && + !canCreateRegular) { + ClusterListEntry *sourceGalaxyCle = findClusterByName(request.getSourceGalaxy()); + if (sourceGalaxyCle && sourceGalaxyCle->m_centralServerConnection) { + clusterId = sourceGalaxyCle->m_centralServerConnection->getClusterId(); + } + } - ClusterListEntry * cle = findClusterById(clusterId); - if (cle && cle->m_centralServerConnection) - { - TransferReplyMoveValidation response(request.getTransferRequestSource(), request.getTrack(), request.getSourceStationId(), request.getDestinationStationId(), request.getSourceGalaxy(), request.getDestinationGalaxy(), request.getSourceCharacter(), request.getSourceCharacterId(), sourceCharacterTemplateId, request.getDestinationCharacter(), request.getCustomerLocalizedLanguage(), (canCreateRegular ? TransferReplyMoveValidation::TRMVR_can_create_regular_character : TransferReplyMoveValidation::TRMVR_cannot_create_regular_character)); - cle->m_centralServerConnection->send(response, true); - } + ClusterListEntry *cle = findClusterById(clusterId); + if (cle && cle->m_centralServerConnection) { + TransferReplyMoveValidation response(request.getTransferRequestSource(), request.getTrack(), request.getSourceStationId(), request.getDestinationStationId(), request.getSourceGalaxy(), request.getDestinationGalaxy(), request.getSourceCharacter(), request.getSourceCharacterId(), sourceCharacterTemplateId, request.getDestinationCharacter(), request.getCustomerLocalizedLanguage(), (canCreateRegular + ? TransferReplyMoveValidation::TRMVR_can_create_regular_character + : TransferReplyMoveValidation::TRMVR_cannot_create_regular_character)); + cle->m_centralServerConnection->send(response, true); + } } //----------------------------------------------------------------------- -void LoginServer::run(void) -{ - NetworkHandler::install(); +void LoginServer::run(void) { + NetworkHandler::install(); #ifdef _DEBUG - LoginServerRemoteDebugSetup::install(); + LoginServerRemoteDebugSetup::install(); #endif - DatabaseConnection::getInstance().connect(); - DatabaseConnection::getInstance().requestClusterList(); - SetupSharedLog::install("LoginServer"); - ConsoleManager::install(); - DataTableManager::install(); - AdminAccountManager::install(ConfigLoginServer::getAdminAccountDataTable()); + DatabaseConnection::getInstance().connect(); + DatabaseConnection::getInstance().requestClusterList(); + SetupSharedLog::install("LoginServer"); + ConsoleManager::install(); + DataTableManager::install(); + AdminAccountManager::install(ConfigLoginServer::getAdminAccountDataTable()); - unsigned long limit = 20; - unsigned long startTime; - unsigned long totalTime = 0; + unsigned long limit = 20; + unsigned long startTime; + unsigned long totalTime = 0; - // load authentication data and bind the monitor to the port - const int port = ConfigLoginServer::getMetricsListenerPort(); - CMonitorAPI *mon = nullptr; + // load authentication data and bind the monitor to the port + const int port = ConfigLoginServer::getMetricsListenerPort(); + CMonitorAPI *mon = nullptr; - if (port) { - mon = new CMonitorAPI("metricsAuthentication.cfg", ConfigLoginServer::getMetricsListenerPort()); - getInstance().m_soeMonitor = mon; - const char *masterChannel = "Population"; - mon->add(masterChannel, WORLD_COUNT_CHANNEL); - std::string host = NetworkHandler::getHostName().c_str(); - size_t dotPos = host.find("."); - if (dotPos != host.npos) { - host = host.substr(0, dotPos - 1); - } - char tmpBuf[1024]; - IGNORE_RETURN(snprintf(tmpBuf, sizeof(tmpBuf), "LoginServer version %s on %s", ApplicationVersion::getInternalVersion(), host - .c_str())); - mon->setDescription(WORLD_COUNT_CHANNEL, tmpBuf); + if (port) { + mon = new CMonitorAPI("metricsAuthentication.cfg", ConfigLoginServer::getMetricsListenerPort()); + getInstance().m_soeMonitor = mon; + const char *masterChannel = "Population"; + mon->add(masterChannel, WORLD_COUNT_CHANNEL); + std::string host = NetworkHandler::getHostName().c_str(); + size_t dotPos = host.find("."); + if (dotPos != host.npos) { + host = host.substr(0, dotPos - 1); + } + char tmpBuf[1024]; + IGNORE_RETURN(snprintf(tmpBuf, sizeof(tmpBuf), "LoginServer version %s on %s", ApplicationVersion::getInternalVersion(), host.c_str())); + mon->setDescription(WORLD_COUNT_CHANNEL, tmpBuf); - mon->add("Galaxies", CLUSTER_COUNT_CHANNEL); - } + mon->add("Galaxies", CLUSTER_COUNT_CHANNEL); + } - while (!getInstance().done) - { - startTime = Clock::timeMs(); - IGNORE_RETURN(Os::update()); - if (getInstance().keyServer->update()) - { - getInstance().pushKeyToAllServers(); - } - NetworkHandler::dispatch(); - do - { - Os::sleep(1); - NetworkHandler::update(); - } while (Clock::timeMs() - startTime < limit); + while (!getInstance().done) { + startTime = Clock::timeMs(); + IGNORE_RETURN(Os::update()); + if (getInstance().keyServer->update()) { + getInstance().pushKeyToAllServers(); + } + NetworkHandler::dispatch(); + do { + Os::sleep(1); + NetworkHandler::update(); + } while (Clock::timeMs() - startTime < limit); - DatabaseConnection::getInstance().update(); - PurgeManager::update(static_cast(limit) / 1000.0f); - if (getInstance().m_clusterStatusChanged) - { - getInstance().sendClusterStatusToAll(); - getInstance().m_clusterStatusChanged = false; - } + DatabaseConnection::getInstance().update(); + PurgeManager::update(static_cast(limit) / 1000.0f); + if (getInstance().m_clusterStatusChanged) { + getInstance().sendClusterStatusToAll(); + getInstance().m_clusterStatusChanged = false; + } - //if (getInstance().m_sessionApiClient) - // getInstance().m_sessionApiClient->Process(); + //if (getInstance().m_sessionApiClient) + // getInstance().m_sessionApiClient->Process(); - totalTime += limit; //TODO: make a better way to do this - if (!ConfigLoginServer::getDevelopmentMode() && (totalTime > 10000)) - { - getInstance().refreshConnections(); - DatabaseConnection::getInstance().requestClusterList(); - totalTime = 0; - } + totalTime += limit; //TODO: make a better way to do this + if (!ConfigLoginServer::getDevelopmentMode() && (totalTime > 10000)) { + getInstance().refreshConnections(); + DatabaseConnection::getInstance().requestClusterList(); + totalTime = 0; + } - NetworkHandler::clearBytesThisFrame(); + NetworkHandler::clearBytesThisFrame(); - if (port) { - mon->set(WORLD_COUNT_CHANNEL, static_cast(getInstance().m_clientMap.size())); - int count = 0; - ClusterListType::const_iterator i; - for (i = getInstance().m_clusterList.begin(); i != getInstance().m_clusterList.end(); ++i) { - if ((*i)->m_connected) - ++count; - } - mon->set(CLUSTER_COUNT_CHANNEL, count); - mon->Update(); - } - } + if (port) { + mon->set(WORLD_COUNT_CHANNEL, static_cast(getInstance().m_clientMap.size())); + int count = 0; + ClusterListType::const_iterator i; + for (i = getInstance().m_clusterList.begin(); i != getInstance().m_clusterList.end(); ++i) { + if ((*i)->m_connected) { + ++count; + } + } + mon->set(CLUSTER_COUNT_CHANNEL, count); + mon->Update(); + } + } - NetworkHandler::update(); + NetworkHandler::update(); - ConsoleManager::remove(); - DatabaseConnection::getInstance().disconnect(); + ConsoleManager::remove(); + DatabaseConnection::getInstance().disconnect(); #ifdef _DEBUG - LoginServerRemoteDebugSetup::remove(); + LoginServerRemoteDebugSetup::remove(); #endif - SetupSharedLog::remove(); - NetworkHandler::remove(); + SetupSharedLog::remove(); + NetworkHandler::remove(); } //----------------------------------------------------------------------- -void LoginServer::sendAvatarList(const StationId& stationId, int stationIdNumberJediSlot, const AvatarList &avatars, TransferCharacterData * const transferData) -{ - std::vector chardata; - chardata.reserve(avatars.size()); +void +LoginServer::sendAvatarList(const StationId &stationId, int stationIdNumberJediSlot, const AvatarList &avatars, TransferCharacterData *const transferData) { + std::vector chardata; + chardata.reserve(avatars.size()); - EnumerateCharacterId::Chardata temp; - for (AvatarList::const_iterator i = avatars.begin(); i != avatars.end(); ++i) - { - temp.m_name = (*i).m_name; - temp.m_objectTemplateId = (*i).m_objectTemplateId; - temp.m_networkId = (*i).m_networkId; - temp.m_clusterId = (*i).m_clusterId; - temp.m_characterType = (*i).m_characterType; + EnumerateCharacterId::Chardata temp; + for (AvatarList::const_iterator i = avatars.begin(); i != avatars.end(); ++i) { + temp.m_name = (*i).m_name; + temp.m_objectTemplateId = (*i).m_objectTemplateId; + temp.m_networkId = (*i).m_networkId; + temp.m_clusterId = (*i).m_clusterId; + temp.m_characterType = (*i).m_characterType; - chardata.push_back(temp); - } + chardata.push_back(temp); + } - EnumerateCharacterId msg(chardata); + EnumerateCharacterId msg(chardata); - if (transferData) - { - // send this to the appropriate CentralServer - if (transferData->getSourceCharacterName().empty()) - { - // CTS API character list request - bool result = CentralServerConnection::sendCharacterListResponse(transferData->getSourceStationId(), avatars, *transferData); - UNREF(result); - DEBUG_REPORT_LOG(!result, ("Could not send avatar list to StationId %lu because connection has been closed.\n", stationId)); - } - else - { - uint32 characterTemplateId = 0; - NetworkId characterId = NetworkId::cms_invalid; - ClusterListEntry const * const cle = findClusterByName(transferData->getSourceGalaxy()); - if (cle) - { - // find associated character ID - for (AvatarList::const_iterator i = avatars.begin(); i != avatars.end(); ++i) - { - REPORT_LOG(true, ("checking %s == %s\n", Unicode::wideToNarrow(i->m_name).c_str(), transferData->getSourceCharacterName().c_str())); - if (Unicode::wideToNarrow(i->m_name) == transferData->getSourceCharacterName() - && i->m_clusterId == cle->m_clusterId) - { - characterTemplateId = static_cast(i->m_objectTemplateId); - characterId = i->m_networkId; - break; - } - } - } + if (transferData) { + // send this to the appropriate CentralServer + if (transferData->getSourceCharacterName().empty()) { + // CTS API character list request + bool result = CentralServerConnection::sendCharacterListResponse(transferData->getSourceStationId(), avatars, *transferData); + UNREF(result); + DEBUG_REPORT_LOG(!result, ("Could not send avatar list to StationId %lu because connection has been closed.\n", stationId)); + } else { + uint32 characterTemplateId = 0; + NetworkId characterId = NetworkId::cms_invalid; + ClusterListEntry const *const cle = findClusterByName(transferData->getSourceGalaxy()); + if (cle) { + // find associated character ID + for (AvatarList::const_iterator i = avatars.begin(); i != avatars.end(); ++i) { + REPORT_LOG(true, ("checking %s == %s\n", Unicode::wideToNarrow(i->m_name).c_str(), transferData->getSourceCharacterName().c_str())); + if (Unicode::wideToNarrow(i->m_name) == transferData->getSourceCharacterName() && + i->m_clusterId == cle->m_clusterId) { + characterTemplateId = static_cast(i->m_objectTemplateId); + characterId = i->m_networkId; + break; + } + } + } - LOG("CustomerService", ("CharacterTransfer: sendAvatarList() for stationId=%u, characterName=%s, sourceGalaxy=%s, determined characterId=%s, determined character template id=%lu", transferData->getSourceStationId(), transferData->getSourceCharacterName().c_str(), transferData->getSourceGalaxy().c_str(), characterId.getValueString().c_str(), characterTemplateId)); + LOG("CustomerService", ("CharacterTransfer: sendAvatarList() for stationId=%u, characterName=%s, sourceGalaxy=%s, determined characterId=%s, determined character template id=%lu", transferData->getSourceStationId(), transferData->getSourceCharacterName().c_str(), transferData->getSourceGalaxy().c_str(), characterId.getValueString().c_str(), characterTemplateId)); - transferData->setCharacterId(characterId); - transferData->setObjectTemplateCrc(characterTemplateId); + transferData->setCharacterId(characterId); + transferData->setObjectTemplateCrc(characterTemplateId); - // part of move request for character transfer system - const GenericValueTypeMessage response("TransferReplyCharacterDataFromLoginServer", *transferData); - CentralServerConnection::sendToCentralServer(transferData->getSourceGalaxy(), response); - } - } - else - { - ClientConnection *conn = getValidatedClient(stationId); - if (conn) - { - LOG("LoginClientConnection", ("sendAvatarList() for stationId (%lu) at IP (%s), sending avatar list to client", stationId, conn->getRemoteAddress().c_str())); + // part of move request for character transfer system + const GenericValueTypeMessage response("TransferReplyCharacterDataFromLoginServer", *transferData); + CentralServerConnection::sendToCentralServer(transferData->getSourceGalaxy(), response); + } + } else { + ClientConnection *conn = getValidatedClient(stationId); + if (conn) { + LOG("LoginClientConnection", ("sendAvatarList() for stationId (%lu) at IP (%s), sending avatar list to client", stationId, conn->getRemoteAddress().c_str())); - // this message ***MUST*** be sent first, as the client expects to - // receive this information before receiving the avatar list information - GenericValueTypeMessage const msgStationIdHasJediSlot("StationIdHasJediSlot", stationIdNumberJediSlot); - conn->send(msgStationIdHasJediSlot, true); + // this message ***MUST*** be sent first, as the client expects to + // receive this information before receiving the avatar list information + GenericValueTypeMessage const msgStationIdHasJediSlot("StationIdHasJediSlot", stationIdNumberJediSlot); + conn->send(msgStationIdHasJediSlot, true); - conn->send(msg, true); - } - else - { - DEBUG_REPORT_LOG(true, ("Could not send avatar list to StationId %lu.\n", stationId)); - LOG("LoginClientConnection", ("sendAvatarList() for stationId (%lu), cannot find connection to client for sending avatar list", stationId)); - } - } + conn->send(msg, true); + } else { + DEBUG_REPORT_LOG(true, ("Could not send avatar list to StationId %lu.\n", stationId)); + LOG("LoginClientConnection", ("sendAvatarList() for stationId (%lu), cannot find connection to client for sending avatar list", stationId)); + } + } } // ---------------------------------------------------------------------- -void LoginServer::performAccountTransfer(const AvatarList &avatars, TransferAccountData * transferAccountData) -{ - // grab the station ids - StationId sourceStationId = transferAccountData->getSourceStationId(); - StationId destinationStationId = transferAccountData->getDestinationStationId(); +void LoginServer::performAccountTransfer(const AvatarList &avatars, TransferAccountData *transferAccountData) { + // grab the station ids + StationId sourceStationId = transferAccountData->getSourceStationId(); + StationId destinationStationId = transferAccountData->getDestinationStationId(); - // we need to get the avatars' cluster and name for use in the chat transfer process - // also send a message to modify the game server databases for each of the clusterIds in transferAccountData - // avatar data is clusterName, avatarName - std::vector avatarData; - for (AvatarList::const_iterator i = avatars.begin(); i != avatars.end(); ++i) - { - ClusterListEntry * cluster = findClusterById(i->m_clusterId); + // we need to get the avatars' cluster and name for use in the chat transfer process + // also send a message to modify the game server databases for each of the clusterIds in transferAccountData + // avatar data is clusterName, avatarName + std::vector avatarData; + for (AvatarList::const_iterator i = avatars.begin(); i != avatars.end(); ++i) { + ClusterListEntry *cluster = findClusterById(i->m_clusterId); - if (cluster) - { - std::string clusterName = cluster->m_clusterName; - std::string avatarName = Unicode::wideToNarrow(i->m_name); + if (cluster) { + std::string clusterName = cluster->m_clusterName; + std::string avatarName = Unicode::wideToNarrow(i->m_name); - avatarData.push_back(AvatarData(clusterName, avatarName)); + avatarData.push_back(AvatarData(clusterName, avatarName)); - LOG("CustomerService", ("CharacterTransfer: Sending request to update game db (via cluster: %s) for account transfer from %lu to %lu (avatar: %s)", clusterName.c_str(), sourceStationId, destinationStationId, avatarName.c_str())); - const GenericValueTypeMessage message("TransferAccountRequestCentralDatabase", *transferAccountData); - sendToCluster(i->m_clusterId, message); - } - else - { - LOG("CustomerService", ("CharacterTransfer: Could not connect to cluster id %lu to update game db for account transfer from %lu to %lu (avatar: %s)", i->m_clusterId, sourceStationId, destinationStationId, Unicode::wideToNarrow(i->m_name).c_str())); - const GenericValueTypeMessage response("TransferAccountToAccountFailedToUpdateGameDatabase", *transferAccountData); - CentralServerConnection::sendToCentralServer(transferAccountData->getStartGalaxy(), response); - return; - } - } + LOG("CustomerService", ("CharacterTransfer: Sending request to update game db (via cluster: %s) for account transfer from %lu to %lu (avatar: %s)", clusterName.c_str(), sourceStationId, destinationStationId, avatarName.c_str())); + const GenericValueTypeMessage message("TransferAccountRequestCentralDatabase", *transferAccountData); + sendToCluster(i->m_clusterId, message); + } else { + LOG("CustomerService", ("CharacterTransfer: Could not connect to cluster id %lu to update game db for account transfer from %lu to %lu (avatar: %s)", i->m_clusterId, sourceStationId, destinationStationId, Unicode::wideToNarrow(i->m_name).c_str())); + const GenericValueTypeMessage response("TransferAccountToAccountFailedToUpdateGameDatabase", *transferAccountData); + CentralServerConnection::sendToCentralServer(transferAccountData->getStartGalaxy(), response); + return; + } + } - transferAccountData->setSourceAvatarData(avatarData); + transferAccountData->setSourceAvatarData(avatarData); - // we also need to modify the station id for all characters for the loginServer - this will contact the centralServer when it is complete to finish the transfer process - DatabaseConnection::getInstance().changeStationId(sourceStationId, destinationStationId, transferAccountData); + // we also need to modify the station id for all characters for the loginServer - this will contact the centralServer when it is complete to finish the transfer process + DatabaseConnection::getInstance().changeStationId(sourceStationId, destinationStationId, transferAccountData); } // ---------------------------------------------------------------------- -void LoginServer::onValidateClient(StationId suid, const std::string & username, ClientConnection *conn, bool isSecure, const char* sessionKey, uint32 gameBits, uint32 subscriptionBits) -{ - UNREF(username); - UNREF(gameBits); - UNREF(subscriptionBits); - NOT_NULL(conn); - WARNING_STRICT_FATAL(getValidatedClient(suid), ("Validating an already valid client in onValidateClient(). StationId: %d UserName: %s", suid, username.c_str())); +void +LoginServer::onValidateClient(StationId suid, const std::string &username, ClientConnection *conn, bool isSecure, const char *sessionKey, uint32 gameBits, uint32 subscriptionBits) { + UNREF(username); + UNREF(gameBits); + UNREF(subscriptionBits); + 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); + 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 (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; - } - } + if (!loginOK) { + conn->disconnect(); + return; + } + } - // encrypt the clients credentials with the key, return - // the cipher text to the client for use as a connection - // token with the central server + // encrypt the clients credentials with the key, return + // the cipher text to the client for use as a connection + // token with the central server - //Also the sizeof(int) is likewise magic from the session api - size_t len = sizeof(uint32) + sizeof(bool) + MAX_ACCOUNT_NAME_LENGTH + 1; - unsigned char * keyBuffer = new unsigned char[len]; - unsigned char * keyBufferPointer = keyBuffer; + //Also the sizeof(int) is likewise magic from the session api + size_t len = sizeof(uint32) + sizeof(bool) + MAX_ACCOUNT_NAME_LENGTH + 1; + unsigned char *keyBuffer = new unsigned char[len]; + unsigned char *keyBufferPointer = keyBuffer; - IGNORE_RETURN(memset(keyBuffer, 0, len)); + IGNORE_RETURN(memset(keyBuffer, 0, len)); - if (ConfigLoginServer::getDoConsumption() || ConfigLoginServer::getDoSessionLogin()) - { - // pass the sessionkey - len = apiSessionIdWidth + sizeof(StationId); - memcpy(keyBufferPointer, sessionKey, apiSessionIdWidth); - keyBufferPointer += apiSessionIdWidth; + if (ConfigLoginServer::getDoConsumption() || ConfigLoginServer::getDoSessionLogin()) { + // pass the sessionkey + len = apiSessionIdWidth + sizeof(StationId); + memcpy(keyBufferPointer, sessionKey, apiSessionIdWidth); + keyBufferPointer += apiSessionIdWidth; - // if LoginServer did session login, send the session key back to the client; - // the client normally gets the session key from the LaunchPad, but in this mode - // where the LoginServer does the session login, it will get it from the LoginServer - if (ConfigLoginServer::getDoSessionLogin()) - { - std::string const strSessionKey(sessionKey, apiSessionIdWidth); - GenericValueTypeMessage const msg("SetSessionKey", strSessionKey); - conn->send(msg, true); - } - } - else - { - // If we aren't validating sessions, pack username, security status, and username to connectionserver - memcpy(keyBufferPointer, &suid, sizeof(uint32)); //lint !e64 !e119 !e534 (lint isn't resolving memcpy properly) - keyBufferPointer += sizeof(uint32); - memcpy(keyBufferPointer, &isSecure, sizeof(bool)); //lint !e64 !e119 !e534 - keyBufferPointer += sizeof(bool); - memcpy(keyBufferPointer, username.c_str(), MAX_ACCOUNT_NAME_LENGTH); //lint !e64 !e119 !e534 - } + // if LoginServer did session login, send the session key back to the client; + // the client normally gets the session key from the LaunchPad, but in this mode + // where the LoginServer does the session login, it will get it from the LoginServer + if (ConfigLoginServer::getDoSessionLogin()) { + std::string const strSessionKey(sessionKey, apiSessionIdWidth); + GenericValueTypeMessage const msg("SetSessionKey", strSessionKey); + conn->send(msg, true); + } + } else { + // If we aren't validating sessions, pack username, security status, and username to connectionserver + memcpy(keyBufferPointer, &suid, sizeof(uint32)); //lint !e64 !e119 !e534 (lint isn't resolving memcpy properly) + keyBufferPointer += sizeof(uint32); + memcpy(keyBufferPointer, &isSecure, sizeof(bool)); //lint !e64 !e119 !e534 + keyBufferPointer += sizeof(bool); + memcpy(keyBufferPointer, username.c_str(), MAX_ACCOUNT_NAME_LENGTH); //lint !e64 !e119 !e534 + } - KeyShare::Token token = LoginServer::getInstance().makeToken(keyBuffer, len); - Archive::ByteStream a; - token.pack(a); + KeyShare::Token token = LoginServer::getInstance().makeToken(keyBuffer, len); + Archive::ByteStream a; + token.pack(a); - const LoginClientToken k(a.getBuffer(), static_cast(a.getSize()), static_cast(suid), username); - conn->send(k, true); - delete[] keyBuffer; + const LoginClientToken k(a.getBuffer(), static_cast(a.getSize()), static_cast(suid), username); + conn->send(k, true); + delete[] keyBuffer; - // send cluster enum - bool clientInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); + // send cluster enum + bool clientInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); - std::vector data; + 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)) - { - LoginEnumCluster::ClusterData item; - item.m_clusterId = cle->m_clusterId; - item.m_clusterName = cle->m_clusterName; - item.m_timeZone = cle->m_timeZone; - data.push_back(item); - } - } + 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)) { + LoginEnumCluster::ClusterData item; + item.m_clusterId = cle->m_clusterId; + item.m_clusterName = cle->m_clusterName; + item.m_timeZone = cle->m_timeZone; + data.push_back(item); + } + } - LoginEnumCluster e(data, ConfigLoginServer::getMaxCharactersPerAccount()); + LoginEnumCluster e(data, ConfigLoginServer::getMaxCharactersPerAccount()); - conn->send(e, true); + conn->send(e, true); - //Send off list of cluster that has character - //creation disabled, even if the list is empty - //***MUST*** be done after sending LoginEnumCluster - GenericValueTypeMessage > const msgCharacterCreationDisabledClusterList("CharacterCreationDisabled", ConfigLoginServer::getCharacterCreationDisabledClusterList()); - conn->send(msgCharacterCreationDisabledClusterList, true); + //Send off list of cluster that has character + //creation disabled, even if the list is empty + //***MUST*** be done after sending LoginEnumCluster + GenericValueTypeMessage > const msgCharacterCreationDisabledClusterList("CharacterCreationDisabled", ConfigLoginServer::getCharacterCreationDisabledClusterList()); + conn->send(msgCharacterCreationDisabledClusterList, true); - //Send off request for the avatar list from the database. - DatabaseConnection::getInstance().requestAvatarListForAccount(suid, 0); - LOG("LoginClientConnection", ("onValidateClient() for stationId (%lu) at IP (%s), id (%s), requesting avatar list for account", suid, conn->getRemoteAddress().c_str(), username.c_str())); + //Send off request for the avatar list from the database. + DatabaseConnection::getInstance().requestAvatarListForAccount(suid, 0); + LOG("LoginClientConnection", ("onValidateClient() for stationId (%lu) at IP (%s), id (%s), requesting avatar list for account", suid, conn->getRemoteAddress().c_str(), username.c_str())); - //Set up the connection as being validated with this suid. - conn->setIsValidated(true); - conn->setStationId(suid); - conn->setIsSecure(isSecure); - conn->setAdminLevel(isAdminAccount ? adminLevel : -1); - IGNORE_RETURN(m_validatedClientMap.insert(std::pair(suid, conn))); + //Set up the connection as being validated with this suid. + conn->setIsValidated(true); + conn->setStationId(suid); + conn->setIsSecure(isSecure); + conn->setAdminLevel(isAdminAccount ? adminLevel : -1); + IGNORE_RETURN(m_validatedClientMap.insert(std::pair(suid, conn))); - //Must be done after setting various information in the connection object above - sendClusterStatus(*conn); + //Must be done after setting various information in the connection object above + sendClusterStatus(*conn); } // ---------------------------------------------------------------------- -LoginServer::ClusterListEntry *LoginServer::findClusterByName(const std::string &clusterName) -{ - ClusterListType::iterator i; - for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - NOT_NULL(*i); // not legal to push nullptr pointers on the vector - if ((*i)->m_clusterName == clusterName) - return *i; - } - return nullptr; +LoginServer::ClusterListEntry *LoginServer::findClusterByName(const std::string &clusterName) { + ClusterListType::iterator i; + for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + NOT_NULL(*i); // not legal to push nullptr pointers on the vector + if ((*i)->m_clusterName == clusterName) { + return *i; + } + } + return nullptr; } // ---------------------------------------------------------------------- -uint32 LoginServer::getClusterIDByName(const std::string &sName) -{ - ClusterListEntry const * const p_cluster = findClusterByName(sName); - return p_cluster ? p_cluster->m_clusterId : 0; +uint32 LoginServer::getClusterIDByName(const std::string &sName) { + ClusterListEntry const *const p_cluster = findClusterByName(sName); + return p_cluster ? p_cluster->m_clusterId : 0; } // ---------------------------------------------------------------------- -const std::string & LoginServer::getClusterNameById(uint32 clusterId) -{ - static std::string const empty; +const std::string &LoginServer::getClusterNameById(uint32 clusterId) { + static std::string const empty; - ClusterListEntry const * const cle = findClusterById(clusterId); - if (cle) - return cle->m_clusterName; + ClusterListEntry const *const cle = findClusterById(clusterId); + if (cle) { + return cle->m_clusterName; + } - return empty; + return empty; } // ---------------------------------------------------------------------- -LoginServer::ClusterListEntry *LoginServer::addCluster(const std::string &clusterName) -{ - DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(), ("Programmer bug: addCluster(std::string&) can only be used in development mode.\n")); +LoginServer::ClusterListEntry *LoginServer::addCluster(const std::string &clusterName) { + DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(), ("Programmer bug: addCluster(std::string&) can only be used in development mode.\n")); - ClusterListEntry *e = new ClusterListEntry; - e->m_clusterName = clusterName; - m_clusterList.push_back(e); - return e; + ClusterListEntry *e = new ClusterListEntry; + e->m_clusterName = clusterName; + m_clusterList.push_back(e); + return e; } // ---------------------------------------------------------------------- -void LoginServer::sendExtendedClusterInfo(ClientConnection &client) const -{ - std::vector data; +void LoginServer::sendExtendedClusterInfo(ClientConnection &client) const { + std::vector data; - for (ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) - { - ClusterListEntry *cle = *j; + for (ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) { + ClusterListEntry *cle = *j; - if (cle) - { - LoginClusterStatusEx::ClusterData item; - item.m_clusterId = cle->m_clusterId; - item.m_branch = cle->m_branch; - item.m_version = cle->m_changelist; - item.m_networkVersion = cle->m_networkVersion; - data.push_back(item); - } - } + if (cle) { + LoginClusterStatusEx::ClusterData item; + item.m_clusterId = cle->m_clusterId; + item.m_branch = cle->m_branch; + item.m_version = cle->m_changelist; + item.m_networkVersion = cle->m_networkVersion; + data.push_back(item); + } + } - client.send(LoginClusterStatusEx(data), true); + client.send(LoginClusterStatusEx(data), true); } // ---------------------------------------------------------------------- @@ -1571,116 +1412,110 @@ void LoginServer::sendExtendedClusterInfo(ClientConnection &client) const * @todo We'd like to resend this to all clients whenever the status * of any servers changes */ -void LoginServer::sendClusterStatus(ClientConnection &conn) const -{ - const bool clientIsPrivate = AdminAccountManager::isInternalIp(conn.getRemoteAddress()); - const unsigned int subscriptionBits = conn.getSubscriptionBits(); - const bool isFreeTrialAccount = (((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) - && ((subscriptionBits & ClientSubscriptionFeature::Base) == 0)); +void LoginServer::sendClusterStatus(ClientConnection &conn) const { + const bool clientIsPrivate = AdminAccountManager::isInternalIp(conn.getRemoteAddress()); + const unsigned int subscriptionBits = conn.getSubscriptionBits(); + const bool isFreeTrialAccount = (((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) && + ((subscriptionBits & ClientSubscriptionFeature::Base) == 0)); - std::vector data; - std::vector dataEx; + std::vector data; + std::vector dataEx; - for (ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) - { - ClusterListEntry *cle = *j; - // Cluster is OK for login if - // 1) We're connected to Central - // 2) We know the cluster Id - // 3) We have at least one Connection Server - // 4) Client is internal or the cluster is not secret - // 5) Cluster has told us its ready for players - if (cle && cle->m_clusterId != 0 && cle->m_connected && !cle->m_connectionServers.empty() && (clientIsPrivate || !cle->m_secret)) - { - DEBUG_FATAL(!cle->m_centralServerConnection, ("Programmer bug: m_connected was true but m_centralServerConnection was nullptr\n")); - LoginClusterStatus::ClusterData item; - item.m_clusterId = cle->m_clusterId; - item.m_timeZone = cle->m_timeZone; + for (ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) { + ClusterListEntry *cle = *j; + // Cluster is OK for login if + // 1) We're connected to Central + // 2) We know the cluster Id + // 3) We have at least one Connection Server + // 4) Client is internal or the cluster is not secret + // 5) Cluster has told us its ready for players + if (cle && cle->m_clusterId != 0 && cle->m_connected && !cle->m_connectionServers.empty() && + (clientIsPrivate || !cle->m_secret)) { + DEBUG_FATAL(!cle->m_centralServerConnection, ("Programmer bug: m_connected was true but m_centralServerConnection was nullptr\n")); + LoginClusterStatus::ClusterData item; + item.m_clusterId = cle->m_clusterId; + item.m_timeZone = cle->m_timeZone; - // size_t connectionServerChoice = Random::random(cle->m_connectionServers.size() - 1); //lint !e713 !e732 // loss of precision (arg no 1) - ConnectionServerEntry &connServer = cle->m_connectionServers[0]; + // size_t connectionServerChoice = Random::random(cle->m_connectionServers.size() - 1); //lint !e713 !e732 // loss of precision (arg no 1) + ConnectionServerEntry &connServer = cle->m_connectionServers[0]; - item.m_connectionServerAddress = connServer.clientServiceAddress; - if (clientIsPrivate) - { - item.m_connectionServerPort = connServer.clientServicePortPrivate; - } - else - { - item.m_connectionServerPort = connServer.clientServicePortPublic; - } - if (item.m_connectionServerPort) - { - item.m_connectionServerPingPort = connServer.pingPort; + item.m_connectionServerAddress = connServer.clientServiceAddress; + if (clientIsPrivate) { + item.m_connectionServerPort = connServer.clientServicePortPrivate; + } else { + item.m_connectionServerPort = connServer.clientServicePortPublic; + } + 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)) - item.m_populationOnline = cle->m_numPlayers; - else - item.m_populationOnline = -1; + // for security/confidential information issue, only report + // population count to secured internal connections with + // admin privilege >= 10 + if (clientIsPrivate && conn.getIsSecure() && (conn.getAdminLevel() >= 10)) { + item.m_populationOnline = cle->m_numPlayers; + } else { + item.m_populationOnline = -1; + } - const int percentFull = cle->m_numPlayers * 100 / cle->m_onlinePlayerLimit; - if (percentFull >= 100) - item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_full; - else if (percentFull >= ConfigLoginServer::getPopulationExtremelyHeavyThresholdPercent()) - item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_extremely_heavy; - else if (percentFull >= ConfigLoginServer::getPopulationVeryHeavyThresholdPercent()) - item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_very_heavy; - else if (percentFull >= ConfigLoginServer::getPopulationHeavyThresholdPercent()) - item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_heavy; - else if (percentFull >= ConfigLoginServer::getPopulationMediumThresholdPercent()) - item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_medium; - else if (percentFull >= ConfigLoginServer::getPopulationLightThresholdPercent()) - item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_light; - else - item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_very_light; + const int percentFull = cle->m_numPlayers * 100 / cle->m_onlinePlayerLimit; + if (percentFull >= 100) { + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_full; + } else if (percentFull >= ConfigLoginServer::getPopulationExtremelyHeavyThresholdPercent()) { + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_extremely_heavy; + } else if (percentFull >= ConfigLoginServer::getPopulationVeryHeavyThresholdPercent()) { + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_very_heavy; + } else if (percentFull >= ConfigLoginServer::getPopulationHeavyThresholdPercent()) { + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_heavy; + } else if (percentFull >= ConfigLoginServer::getPopulationMediumThresholdPercent()) { + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_medium; + } else if (percentFull >= ConfigLoginServer::getPopulationLightThresholdPercent()) { + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_light; + } else { + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_very_light; + } - item.m_maxCharactersPerAccount = cle->m_maxCharactersPerAccount; - if (cle->m_readyForPlayers) - { - item.m_status = LoginClusterStatus::ClusterData::S_up; - if (cle->m_numTutorialPlayers >= cle->m_onlineTutorialLimit) - item.m_status = LoginClusterStatus::ClusterData::S_restricted; - if (isFreeTrialAccount && !cle->m_freeTrialCanCreateChar) - { - item.m_status = LoginClusterStatus::ClusterData::S_restricted; - } - if ((cle->m_numPlayers >= cle->m_onlinePlayerLimit) - || (isFreeTrialAccount && (cle->m_numFreeTrialPlayers >= cle->m_onlineFreeTrialLimit))) - { - item.m_status = LoginClusterStatus::ClusterData::S_full; - } - } - else - item.m_status = LoginClusterStatus::ClusterData::S_loading; - if (cle->m_locked && !clientIsPrivate) - item.m_status = LoginClusterStatus::ClusterData::S_locked; // locked takes precedence over up or loading + item.m_maxCharactersPerAccount = cle->m_maxCharactersPerAccount; + if (cle->m_readyForPlayers) { + item.m_status = LoginClusterStatus::ClusterData::S_up; + if (cle->m_numTutorialPlayers >= cle->m_onlineTutorialLimit) { + item.m_status = LoginClusterStatus::ClusterData::S_restricted; + } + if (isFreeTrialAccount && !cle->m_freeTrialCanCreateChar) { + item.m_status = LoginClusterStatus::ClusterData::S_restricted; + } + if ((cle->m_numPlayers >= cle->m_onlinePlayerLimit) || + (isFreeTrialAccount && (cle->m_numFreeTrialPlayers >= cle->m_onlineFreeTrialLimit))) { + item.m_status = LoginClusterStatus::ClusterData::S_full; + } + } else { + item.m_status = LoginClusterStatus::ClusterData::S_loading; + } + if (cle->m_locked && !clientIsPrivate) { + item.m_status = LoginClusterStatus::ClusterData::S_locked; + } // locked takes precedence over up or loading - item.m_dontRecommend = (cle->m_notRecommendedDatabase || cle->m_notRecommendedCentral); - item.m_onlinePlayerLimit = cle->m_onlinePlayerLimit; - item.m_onlineFreeTrialLimit = cle->m_onlineFreeTrialLimit; + item.m_dontRecommend = (cle->m_notRecommendedDatabase || cle->m_notRecommendedCentral); + item.m_onlinePlayerLimit = cle->m_onlinePlayerLimit; + item.m_onlineFreeTrialLimit = cle->m_onlineFreeTrialLimit; - data.push_back(item); - } + data.push_back(item); + } - ++connServer.numClients; - std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); - } + ++connServer.numClients; + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + } - if (cle) - { - LoginClusterStatusEx::ClusterData itemEx; - itemEx.m_clusterId = cle->m_clusterId; - itemEx.m_branch = cle->m_branch; - itemEx.m_version = cle->m_changelist; - dataEx.push_back(itemEx); - } - } + if (cle) { + LoginClusterStatusEx::ClusterData itemEx; + itemEx.m_clusterId = cle->m_clusterId; + itemEx.m_branch = cle->m_branch; + itemEx.m_version = cle->m_changelist; + dataEx.push_back(itemEx); + } + } - LoginClusterStatus msg(data); - conn.send(msg, true); + LoginClusterStatus msg(data); + conn.send(msg, true); } // ---------------------------------------------------------------------- @@ -1688,43 +1523,25 @@ void LoginServer::sendClusterStatus(ClientConnection &conn) const /** * Send the list of active clusters to all connected clients. */ -void LoginServer::sendClusterStatusToAll() const -{ - for (std::map::const_iterator i = m_validatedClientMap.begin(); i != m_validatedClientMap.end(); ++i) - { - if (i->second) - sendClusterStatus(*(i->second)); - } +void LoginServer::sendClusterStatusToAll() const { + for (std::map::const_iterator i = m_validatedClientMap.begin(); + i != m_validatedClientMap.end(); ++i) { + if (i->second) { + sendClusterStatus(*(i->second)); + } + } } // ---------------------------------------------------------------------- -LoginServer::ClusterListEntry::ClusterListEntry() : - m_clusterId(0), - m_clusterName(), - m_centralServerConnection(0), - m_connectionServers(), - m_numPlayers(0), - m_numFreeTrialPlayers(0), - m_numTutorialPlayers(0), - m_maxCharacters(ConfigLoginServer::getMaxCharactersPerCluster()), - m_maxCharactersPerAccount(0), - m_onlinePlayerLimit(0), - m_onlineFreeTrialLimit(0), - m_onlineTutorialLimit(0), - m_freeTrialCanCreateChar(false), - m_timeZone(0), - m_connected(false), - m_address(""), - m_port(0), - m_allowReconnect(true), - m_secret(false), - m_readyForPlayers(false), - m_locked(false), - m_notRecommendedDatabase(false), - m_notRecommendedCentral(false), - m_changelist(0) -{ +LoginServer::ClusterListEntry::ClusterListEntry() + : m_clusterId(0), m_clusterName(), m_centralServerConnection(0), m_connectionServers(), m_numPlayers(0), + m_numFreeTrialPlayers(0), m_numTutorialPlayers(0), + m_maxCharacters(ConfigLoginServer::getMaxCharactersPerCluster()), m_maxCharactersPerAccount(0), + m_onlinePlayerLimit(0), m_onlineFreeTrialLimit(0), m_onlineTutorialLimit(0), m_freeTrialCanCreateChar(false), + m_timeZone(0), m_connected(false), m_address(""), m_port(0), m_allowReconnect(true), m_secret(false), + m_readyForPlayers(false), m_locked(false), m_notRecommendedDatabase(false), m_notRecommendedCentral(false), + m_changelist(0) { } // ---------------------------------------------------------------------- @@ -1734,78 +1551,68 @@ LoginServer::ClusterListEntry::ClusterListEntry() : * has changed, disconnect and reconnect. * If we don't know about the cluster already, add it to the list. */ -void LoginServer::updateClusterData(uint32 clusterId, const std::string &clusterName, const std::string &address, const uint16 port, bool secret, bool locked, bool notRecommended, int maxCharactersPerAccount, int onlinePlayerLimit, int onlineFreeTrialLimit, bool freeTrialCanCreateChar, int onlineTutorialLimit) -{ - ClusterListEntry *cle = findClusterById(clusterId); +void +LoginServer::updateClusterData(uint32 clusterId, const std::string &clusterName, const std::string &address, const uint16 port, bool secret, bool locked, bool notRecommended, int maxCharactersPerAccount, int onlinePlayerLimit, int onlineFreeTrialLimit, bool freeTrialCanCreateChar, int onlineTutorialLimit) { + ClusterListEntry *cle = findClusterById(clusterId); - if (ConfigLoginServer::getDevelopmentMode()) - { - if (!cle) - cle = findClusterByName(clusterName); - } - else - { - if (cle) - { - // refreshing data on a cluster we already know about - if ((cle->m_clusterName != clusterName) || (cle->m_address != address) || (cle->m_port != port)) - { - DEBUG_REPORT_LOG(true, ("Disconnecting from cluster %lu because its data has changed in the database.\n", clusterId)); - disconnectCluster(*cle, true, true); - } - } - } + if (ConfigLoginServer::getDevelopmentMode()) { + if (!cle) { + cle = findClusterByName(clusterName); + } + } else { + if (cle) { + // refreshing data on a cluster we already know about + if ((cle->m_clusterName != clusterName) || (cle->m_address != address) || (cle->m_port != port)) { + DEBUG_REPORT_LOG(true, ("Disconnecting from cluster %lu because its data has changed in the database.\n", clusterId)); + disconnectCluster(*cle, true, true); + } + } + } - if (!cle) - { - DEBUG_REPORT_LOG(true, ("Cluster %lu: %s\n", clusterId, clusterName.c_str())); + if (!cle) { + DEBUG_REPORT_LOG(true, ("Cluster %lu: %s\n", clusterId, clusterName.c_str())); - cle = new ClusterListEntry; - m_clusterList.push_back(cle); - } + cle = new ClusterListEntry; + m_clusterList.push_back(cle); + } - if ((cle->m_secret != secret) - || (cle->m_locked != locked) - || (cle->m_onlinePlayerLimit != onlinePlayerLimit) - || (cle->m_onlineFreeTrialLimit != onlineFreeTrialLimit) - || (cle->m_freeTrialCanCreateChar != freeTrialCanCreateChar) - || (cle->m_onlineTutorialLimit != onlineTutorialLimit)) - { - // The cluster may now be locked/unlocked to some players, so let them know - m_clusterStatusChanged = true; - } + if ((cle->m_secret != secret) || (cle->m_locked != locked) || (cle->m_onlinePlayerLimit != onlinePlayerLimit) || + (cle->m_onlineFreeTrialLimit != onlineFreeTrialLimit) || + (cle->m_freeTrialCanCreateChar != freeTrialCanCreateChar) || + (cle->m_onlineTutorialLimit != onlineTutorialLimit)) { + // The cluster may now be locked/unlocked to some players, so let them know + m_clusterStatusChanged = true; + } - // tell the cluster if its locked or secret state changes - if (((cle->m_locked != locked) || (cle->m_secret != secret)) && cle->m_connected && cle->m_centralServerConnection) - { - GenericValueTypeMessage > const msgState("UpdateClusterLockedAndSecretState", std::make_pair(locked, secret)); - cle->m_centralServerConnection->send(msgState, true); - } + // tell the cluster if its locked or secret state changes + if (((cle->m_locked != locked) || (cle->m_secret != secret)) && cle->m_connected && + cle->m_centralServerConnection) { + GenericValueTypeMessage > const msgState("UpdateClusterLockedAndSecretState", std::make_pair(locked, secret)); + cle->m_centralServerConnection->send(msgState, true); + } - bool const clusterIdSet = ((cle->m_clusterId == 0) && (clusterId > 0)); - cle->m_clusterId = clusterId; - cle->m_clusterName = clusterName; - cle->m_address = address; - cle->m_port = port; - cle->m_secret = secret; - cle->m_locked = locked; - cle->m_notRecommendedDatabase = notRecommended; - cle->m_maxCharactersPerAccount = maxCharactersPerAccount; - cle->m_onlinePlayerLimit = onlinePlayerLimit; - cle->m_onlineFreeTrialLimit = onlineFreeTrialLimit; - cle->m_freeTrialCanCreateChar = freeTrialCanCreateChar; - cle->m_onlineTutorialLimit = onlineTutorialLimit; - if (cle->m_centralServerConnection) - { - cle->m_centralServerConnection->setClusterId(clusterId); + bool const clusterIdSet = ((cle->m_clusterId == 0) && (clusterId > 0)); + cle->m_clusterId = clusterId; + cle->m_clusterName = clusterName; + cle->m_address = address; + cle->m_port = port; + cle->m_secret = secret; + cle->m_locked = locked; + cle->m_notRecommendedDatabase = notRecommended; + cle->m_maxCharactersPerAccount = maxCharactersPerAccount; + cle->m_onlinePlayerLimit = onlinePlayerLimit; + cle->m_onlineFreeTrialLimit = onlineFreeTrialLimit; + cle->m_freeTrialCanCreateChar = freeTrialCanCreateChar; + cle->m_onlineTutorialLimit = onlineTutorialLimit; + if (cle->m_centralServerConnection) { + cle->m_centralServerConnection->setClusterId(clusterId); - // tell the cluster its cluster id - if (clusterIdSet && ConfigLoginServer::getDevelopmentMode()) - { - GenericValueTypeMessage const msgClusterId("ClusterId", cle->m_clusterId); - cle->m_centralServerConnection->send(msgClusterId, true); - } - } + // tell the cluster its cluster id + if (clusterIdSet && ConfigLoginServer::getDevelopmentMode()) { + GenericValueTypeMessage const msgClusterId("ClusterId", cle->m_clusterId); + cle->m_centralServerConnection->send(msgClusterId, true); + } + } } // ---------------------------------------------------------------------- @@ -1818,40 +1625,38 @@ void LoginServer::updateClusterData(uint32 clusterId, const std::string &cluster * @param reconnect If true, will attempt to reestablish connection to the cluster * (does not apply in development mode) */ -void LoginServer::disconnectCluster(ClusterListEntry &cle, bool const forceDisconnect, bool const reconnect) -{ - if (cle.m_centralServerConnection && forceDisconnect) - cle.m_centralServerConnection->disconnect(); +void LoginServer::disconnectCluster(ClusterListEntry &cle, bool const forceDisconnect, bool const reconnect) { + if (cle.m_centralServerConnection && forceDisconnect) { + cle.m_centralServerConnection->disconnect(); + } - cle.m_centralServerConnection = 0; //TODO: revisit after connection deletion issues are fixed - cle.m_allowReconnect = reconnect; - cle.m_connectionServers.clear(); + cle.m_centralServerConnection = 0; //TODO: revisit after connection deletion issues are fixed + cle.m_allowReconnect = reconnect; + cle.m_connectionServers.clear(); - bool statusChange = false; + bool statusChange = false; - if (cle.m_connected || cle.m_readyForPlayers) - statusChange = true; + if (cle.m_connected || cle.m_readyForPlayers) { + statusChange = true; + } - cle.m_connected = false; - cle.m_readyForPlayers = false; + cle.m_connected = false; + cle.m_readyForPlayers = false; - m_clusterStatusChanged = statusChange; + m_clusterStatusChanged = statusChange; - // for "carousel" cluster, where multiple clusters point to the same address, - // when disconnecting a "carousel" cluster, need to flag the other "carousel" - // clusters to allow reconnect so that another "carousel" cluster can be - // started, and the LoginServer will connect to it - if (!ConfigLoginServer::getDevelopmentMode() && reconnect) - { - for (ClusterListType::iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - NOT_NULL(*i); - if (!(*i)->m_centralServerConnection && !(*i)->m_allowReconnect && ((*i)->m_address == cle.m_address)) - { - (*i)->m_allowReconnect = true; - } - } - } + // for "carousel" cluster, where multiple clusters point to the same address, + // when disconnecting a "carousel" cluster, need to flag the other "carousel" + // clusters to allow reconnect so that another "carousel" cluster can be + // started, and the LoginServer will connect to it + if (!ConfigLoginServer::getDevelopmentMode() && reconnect) { + for (ClusterListType::iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + NOT_NULL(*i); + if (!(*i)->m_centralServerConnection && !(*i)->m_allowReconnect && ((*i)->m_address == cle.m_address)) { + (*i)->m_allowReconnect = true; + } + } + } } // ---------------------------------------------------------------------- @@ -1859,11 +1664,10 @@ void LoginServer::disconnectCluster(ClusterListEntry &cle, bool const forceDisco /** * Called after we've added a new cluster to the database. */ -void LoginServer::onClusterRegistered(uint32 clusterId, const std::string &clusterName) -{ - DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(), ("Programmer bug: should not be registering new clusters automatically unless running in development mode.\n")); - static std::string noAddress(""); - updateClusterData(clusterId, clusterName, noAddress, 0, false, false, false, 8, 100, 100, true, 350); +void LoginServer::onClusterRegistered(uint32 clusterId, const std::string &clusterName) { + DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(), ("Programmer bug: should not be registering new clusters automatically unless running in development mode.\n")); + static std::string noAddress(""); + updateClusterData(clusterId, clusterName, noAddress, 0, false, false, false, 8, 100, 100, true, 350); } // ---------------------------------------------------------------------- @@ -1872,17 +1676,16 @@ void LoginServer::onClusterRegistered(uint32 clusterId, const std::string &clust * Find a cluster by ID. */ -LoginServer::ClusterListEntry * LoginServer::findClusterById(uint32 clusterId) -{ - ClusterListType::const_iterator i; - for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - NOT_NULL(*i); // not legal to push nullptr pointers on the vector - if ((*i)->m_clusterId == clusterId) - return *i; - } +LoginServer::ClusterListEntry *LoginServer::findClusterById(uint32 clusterId) { + ClusterListType::const_iterator i; + for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + NOT_NULL(*i); // not legal to push nullptr pointers on the vector + if ((*i)->m_clusterId == clusterId) { + return *i; + } + } - return nullptr; + return nullptr; } // ---------------------------------------------------------------------- @@ -1891,120 +1694,113 @@ LoginServer::ClusterListEntry * LoginServer::findClusterById(uint32 clusterId) * Find a cluster list entry using the connection to Central */ -LoginServer::ClusterListEntry * LoginServer::findClusterByConnection(const CentralServerConnection *connection) -{ - ClusterListType::const_iterator i; - for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - NOT_NULL(*i); // not legal to push nullptr pointers on the vector - if ((*i)->m_centralServerConnection == connection) - return *i; - } +LoginServer::ClusterListEntry *LoginServer::findClusterByConnection(const CentralServerConnection *connection) { + ClusterListType::const_iterator i; + for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + NOT_NULL(*i); // not legal to push nullptr pointers on the vector + if ((*i)->m_centralServerConnection == connection) { + return *i; + } + } - return nullptr; + return nullptr; } // ---------------------------------------------------------------------- -void LoginServer::refreshConnections() -{ - if (ConfigLoginServer::getDevelopmentMode()) - return; // in development mode, we don't establish any connections - ClusterListType::iterator i; - for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - NOT_NULL(*i); - if (!(*i)->m_centralServerConnection && (*i)->m_allowReconnect) - { - (*i)->m_centralServerConnection = new CentralServerConnection( - (*i)->m_address, - (*i)->m_port, - (*i)->m_clusterName, - (*i)->m_clusterId); - } - } +void LoginServer::refreshConnections() { + if (ConfigLoginServer::getDevelopmentMode()) { + return; + } // in development mode, we don't establish any connections + ClusterListType::iterator i; + for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + NOT_NULL(*i); + if (!(*i)->m_centralServerConnection && (*i)->m_allowReconnect) { + (*i)->m_centralServerConnection = new CentralServerConnection((*i)->m_address, (*i)->m_port, (*i)->m_clusterName, (*i)->m_clusterId); + } + } } // ---------------------------------------------------------------------- -void LoginServer::sendToCluster(uint32 clusterId, const GameNetworkMessage &message) -{ - ClusterListEntry *cle = findClusterById(clusterId); - if (cle && cle->m_connected && cle->m_centralServerConnection) - cle->m_centralServerConnection->send(message, true); - else - DEBUG_REPORT_LOG(true, ("Could not send message to cluster %lu because it was not connected.\n", clusterId)); +void LoginServer::sendToCluster(uint32 clusterId, const GameNetworkMessage &message) { + ClusterListEntry *cle = findClusterById(clusterId); + if (cle && cle->m_connected && cle->m_centralServerConnection) { + cle->m_centralServerConnection->send(message, true); + } else { + DEBUG_REPORT_LOG(true, ("Could not send message to cluster %lu because it was not connected.\n", clusterId)); + } } //----------------------------------------------------------------------- -void LoginServer::setDone(const bool isDone) -{ - done = isDone; +void LoginServer::setDone(const bool isDone) { + done = isDone; } // ---------------------------------------------------------------------- -void LoginServer::sendToAllClusters(GameNetworkMessage const & message, Connection const * excludeCentralConnection /*= nullptr*/, uint32 excludeClusterId /*= 0*/, char const * excludeClusterName /*= nullptr*/) -{ - ClusterListType::const_iterator i; - for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - if (NON_NULL(*i)->m_connected && (*i)->m_centralServerConnection && ((*i)->m_centralServerConnection != excludeCentralConnection) && ((*i)->m_clusterId != excludeClusterId) && ((excludeClusterName == nullptr) || _stricmp(excludeClusterName, (*i)->m_centralServerConnection->getClusterName().c_str()))) - (*i)->m_centralServerConnection->send(message, true); - } +void +LoginServer::sendToAllClusters(GameNetworkMessage const &message, Connection const *excludeCentralConnection /*= nullptr*/, uint32 excludeClusterId /*= 0*/, char const *excludeClusterName /*= nullptr*/) { + ClusterListType::const_iterator i; + for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + if (NON_NULL(*i)->m_connected && (*i)->m_centralServerConnection && + ((*i)->m_centralServerConnection != excludeCentralConnection) && ((*i)->m_clusterId != excludeClusterId) && + ((excludeClusterName == nullptr) || + _stricmp(excludeClusterName, (*i)->m_centralServerConnection->getClusterName().c_str()))) { + (*i)->m_centralServerConnection->send(message, true); + } + } } // ---------------------------------------------------------------------- -bool LoginServer::areAllClustersUp() const -{ - if (m_clusterList.empty()) - return false; +bool LoginServer::areAllClustersUp() const { + if (m_clusterList.empty()) { + return false; + } - ClusterListType::const_iterator i; - for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - if (!(NON_NULL(*i)->m_readyForPlayers)) - return false; - } - return true; + ClusterListType::const_iterator i; + for (i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + if (!(NON_NULL(*i)->m_readyForPlayers)) { + return false; + } + } + return true; } // ---------------------------------------------------------------------- -void LoginServer::getAllClusterNamesAndIDs(std::map< std::string, uint32 > &results) const -{ - results.clear(); - for (ClusterListType::const_iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - { - if (!*i) - continue; - results[(*i)->m_clusterName] = (*i)->m_clusterId; - } +void LoginServer::getAllClusterNamesAndIDs(std::map &results) const { + results.clear(); + for (ClusterListType::const_iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + if (!*i) { + continue; + } + results[(*i)->m_clusterName] = (*i)->m_clusterId; + } } // ---------------------------------------------------------------------- -void LoginServer::getClusterIds(std::vector result) -{ - result.reserve(m_clusterList.size()); - for (ClusterListType::const_iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) - result.push_back(NON_NULL(*i)->m_clusterId); +void LoginServer::getClusterIds(std::vector result) { + result.reserve(m_clusterList.size()); + for (ClusterListType::const_iterator i = m_clusterList.begin(); i != m_clusterList.end(); ++i) { + result.push_back(NON_NULL(*i)->m_clusterId); + } } // ---------------------------------------------------------------------- -void LoginServer::setClusterInfoByName(const std::string &name, const std::string &branch, int changelist, const std::string &networkVersion) -{ - ClusterListEntry *entry = findClusterByName(name); +void +LoginServer::setClusterInfoByName(const std::string &name, const std::string &branch, int changelist, const std::string &networkVersion) { + ClusterListEntry *entry = findClusterByName(name); - if (entry) - { - entry->m_branch = branch; - entry->m_changelist = changelist; - entry->m_networkVersion = networkVersion; - } + if (entry) { + entry->m_branch = branch; + entry->m_changelist = changelist; + entry->m_networkVersion = networkVersion; + } } // ====================================================================== From de68ba41ea23d6255e6a24e1b53ae3300abe9541 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 10:07:12 -0600 Subject: [PATCH 23/55] logical fixes --- .../src/shared/ClientConnection.cpp | 352 ++++++++++++------ 1 file changed, 239 insertions(+), 113 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index e4090172..bc3c7c31 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -72,8 +72,8 @@ using namespace ClientConnectionNamespace; //----------------------------------------------------------------------- -std::map ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute -std::map ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute +std::map ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute +std::map ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute uint32 ClientConnection::sm_outgoingBytesMap_Worktime = 0; // time we started filling in the working map @@ -117,10 +117,14 @@ ClientConnection::~ClientConnection() { // tell Session to stop recording play time for the character if (m_hasBeenValidated && m_sessionValidated && ConnectionServer::getSessionApiClient() && (m_lastActiveTime > 0) && ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + LOG("CustomerService", + ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); // log total active play time for the session to the balance log - LOG("GameBalance", ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); + LOG("GameBalance", + ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); ConnectionServer::getSessionApiClient()->stopPlay(*this); } @@ -129,9 +133,9 @@ ClientConnection::~ClientConnection() { ConnectionServer::getSessionApiClient()->dropClient(this, hasBeenKicked); } - std::map < unsigned - long, GameClientMessage * > ::const_iterator - iter; + std::map::const_iterator + iter; for (iter = m_pendingChatEnterRoomRequests.begin(); iter != m_pendingChatEnterRoomRequests.end(); ++iter) { delete iter->second; } @@ -200,12 +204,14 @@ std::string ClientConnection::getCurrentActivePlayTimeDuration() const { void ClientConnection::sendPlayTimeInfoToGameServer() const { if (m_client && m_client->getGameConnection()) { // update the game server with play time info - GenericValueTypeMessage < std::pair < int32, std::pair < int32, unsigned - long > > > + GenericValueTypeMessage > > const msgPlayTimeInfo( - "UpdateSessionPlayTimeInfo", std::make_pair(static_cast(m_startPlayTime), std::make_pair(static_cast(m_lastActiveTime), m_activePlayTimeDuration))); + "UpdateSessionPlayTimeInfo", std::make_pair(static_cast(m_startPlayTime), + std::make_pair(static_cast(m_lastActiveTime), + m_activePlayTimeDuration))); - std::vector v; + std::vector v; v.push_back(m_client->getNetworkId()); GameClientMessage const gcm(v, true, msgPlayTimeInfo); m_client->getGameConnection()->send(gcm, true); @@ -223,16 +229,20 @@ void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) //haven't already selected. if (m_hasSelectedCharacter || m_validatingCharacter || !m_hasBeenValidated || !m_sessionValidated) { if (m_hasSelectedCharacter) { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has already selected a character", getSUID())); + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has already selected a character", getSUID())); } if (m_validatingCharacter) { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not yet received validation", getSUID())); + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has not yet received validation", getSUID())); } if (!m_hasBeenValidated) { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been validated", getSUID())); + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has not been validated", getSUID())); } if (!m_sessionValidated) { - LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been session validated", getSUID())); + LOG("TraceCharacterSelection", + ("%d cannot select a character because the client has not been session validated", getSUID())); } return; @@ -246,7 +256,8 @@ void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) ValidateCharacterForLoginMessage vclm(getSUID(), msg.getId()); ConnectionServer::sendToCentralProcess(vclm); - LOG("TraceCharacterSelection", ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); + LOG("TraceCharacterSelection", + ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); } @@ -292,17 +303,19 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { result = ConnectionServer::decryptToken(token, sessionId, m_requestedSuid); } - DEBUG_WARNING(true, ("ConnectionServer::handleClientIdMEssage - suid is %lu session is %s", m_suid, sessionId)); + static const std::string sessURL(ConfigConnectionServer::getSessionURL()); - if (result || (*sessionId) != '\0') { + if (result || strlen(sessionId) != 0) { if (ConfigConnectionServer::getValidateStationKey()) { bool cont = false; StationId apiSuid = 0; const std::string clientIP = getRemoteAddress(); const std::string sess = sessionId; + DEBUG_WARNING(true, ("ConnectionServer::handleClientIdMessage - suid is %lu requestedSUID is %lu and session is %s", m_suid, m_requestedSuid, sess.c_str())); + webAPI api(sessURL); // add our data @@ -326,11 +339,10 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { } if (!cont) { - LOG("ClientDisconnect", ("SUID %d (%d) passed a bad token to the connections erver. Disconnecting.", m_suid, apiSuid)); + LOG("ClientDisconnect", + ("SUID %d (%d) passed a bad token to the connections erver. Disconnecting.", m_suid, apiSuid)); disconnect(); } - } else { // assume local testing - result = ConnectionServer::decryptToken(token, m_suid, m_isSecure, m_accountName); } static const std::string loginTrace("TRACE_LOGIN"); @@ -357,7 +369,10 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { const int bufferSize = 255 + apiSessionIdWidth; char *buffer = new char[bufferSize]; snprintf(buffer, bufferSize - - 1, "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), GameNetworkMessage::NetworkVersionId.c_str()); + 1, + "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", + getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), + GameNetworkMessage::NetworkVersionId.c_str()); buffer[bufferSize - 1] = '\0'; ConnectionServer::dropClient(this, std::string(buffer)); @@ -372,19 +387,24 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { WARNING(true, ("Generating suid from username. This is not safe or secure.")); m_suid = atoi(m_accountName.c_str()); if (m_suid == 0) { - std::hash h; + std::hash h; m_suid = h(m_accountName.c_str()); } } - onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, ConfigConnectionServer::getDefaultGameFeatures(), ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, ConfigConnectionServer::getFakeBuddyPoints()); + onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, + ConfigConnectionServer::getDefaultGameFeatures(), + ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, + ConfigConnectionServer::getFakeBuddyPoints()); } } else { - WARNING(true, ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); + WARNING(true, + ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); // They sent us a token that was no good -- either a hack attempt, or // possibly it was just too old. - LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); + LOG("ClientDisconnect", + ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); disconnect(); } } @@ -392,26 +412,35 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { //----------------------------------------------------------------------- void -ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems) { +ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, + bool canSkipTutorial, + std::vector> const &consumedRewardEvents, + std::vector> const &claimedRewardItems) { //@todo start session with station. //@todo add more permissions to this message as needed. // resume character creation if (m_pendingCharacterCreate) { if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); disconnect(); } else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); disconnect(); } else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to create any characters", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); disconnect(); } else { ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); @@ -474,7 +503,9 @@ void ClientConnection::onConnectionClosed() { LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); if (m_client) { if (!m_client->hasBeenKicked()) { - LOG("CustomerService", ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount(this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); + LOG("CustomerService", + ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount( + this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); } ChatServerConnection *chatConnection = m_client->getChatConnection(); if (chatConnection) { @@ -500,11 +531,12 @@ void ClientConnection::onConnectionOpened() { void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) { char errbuf[1024]; - snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", bytesPending); + snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", + bytesPending); LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); - std::vector < std::pair < std::string, int > > ::const_iterator - i; + std::vector >::const_iterator + i; for (i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) { LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); } @@ -512,7 +544,8 @@ void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) // ErrorMessage err(name, desc, false); // send(err, true); WARNING(true, (errbuf)); - LOG("ClientDisconnect", ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); + LOG("ClientDisconnect", + ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); snprintf(errbuf, sizeof(errbuf) - 1, "Connection Overflow (bytes pending=%u)", bytesPending); errbuf[sizeof(errbuf) - 1] = '\0'; @@ -551,12 +584,14 @@ bool ClientConnection::checkSpamLimit(unsigned int messageSize) { if (m_countSpamLimitResetTime) { if (m_receiveHistoryBytes >= m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitBytesPerSec() / 1000) { - LOG("Network", ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); + LOG("Network", + ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); return false; } if (m_receiveHistoryPackets >= m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitPacketsPerSec() / 1000) { - LOG("Network", ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); + LOG("Network", + ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); return false; } } @@ -615,7 +650,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { NOT_NULL(m_client); if (m_client) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); @@ -658,15 +693,16 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { if (m_client && m_client->getGameConnection()) { if (m_pendingChatEnterRoomRequests.count(sequence) == 0) { - GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned - int > > + GenericValueTypeMessage, unsigned + int> > const cervr( - "ChatEnterRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), roomName), sequence)); + "ChatEnterRoomValidationRequest", + std::make_pair(std::make_pair(m_client->getNetworkId(), roomName), sequence)); m_client->getGameConnection()->send(cervr, true); // queue up request until game server responds - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); @@ -692,15 +728,17 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { if (m_client && m_client->getGameConnection()) { if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) { - GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned - int > > + GenericValueTypeMessage, unsigned + int> > const cqrvr( - "ChatQueryRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), cqr.getSequence())); + "ChatQueryRoomValidationRequest", + std::make_pair(std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), + cqr.getSequence())); m_client->getGameConnection()->send(cqrvr, true); // queue up request until game server responds - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); @@ -713,7 +751,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { NOT_NULL(m_client); if (m_client) { if (m_client->getGameConnection()) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); @@ -734,7 +772,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { case constcrc("ChatPersistentMessageToServer") : { NOT_NULL(m_client); if (m_client) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); @@ -783,7 +821,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); if (customerServiceConnection != nullptr) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); @@ -865,7 +903,9 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // tell Session to stop recording play time for the character if (ConnectionServer::getSessionApiClient() && ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + LOG("CustomerService", + ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); ConnectionServer::getSessionApiClient()->stopPlay(*this); } @@ -878,12 +918,14 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // drop inactive character if (ConfigConnectionServer::getDisconnectOnInactive()) { - LOG("ClientDisconnect", ("Disconnecting %u because the player was inactive for too long.", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because the player was inactive for too long.", getSUID())); ConnectionServer::dropClient(this, "Client inactivity"); disconnect(); } else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { - LOG("ClientDisconnect", ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); ConnectionServer::dropClient(this, "Client inactivity (free trial)"); disconnect(); } @@ -898,7 +940,9 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // tell Session to start recording play time for the character if (ConnectionServer::getSessionApiClient() && ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); + LOG("CustomerService", + ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount( + this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); ConnectionServer::getSessionApiClient()->startPlay(*this); } @@ -912,10 +956,11 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { default : { //Forward on to Game Server DEBUG_REPORT_LOG((!m_client || - !m_client->getGameConnection()), ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); + !m_client->getGameConnection()), + ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); if (m_client && m_client->getGameConnection()) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); @@ -936,7 +981,8 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { } case constcrc("SelectCharacter") : { SelectCharacter s(ri); - DEBUG_REPORT_LOG(true, ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); + DEBUG_REPORT_LOG(true, + ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); handleSelectCharacterMessage(s); break; @@ -945,35 +991,51 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { if (m_hasBeenValidated && !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true { ClientCreateCharacter clientCreate(ri); - DEBUG_REPORT_LOG(true, ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str())); - LOG("TraceCharacterCreation", ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", getSUID(), Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), clientCreate.getTemplateName().c_str(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation().c_str(), clientCreate.getHairTemplateName().c_str(), clientCreate.getProfession().c_str(), static_cast(clientCreate.getJedi()), static_cast(clientCreate.getUseNewbieTutorial()), clientCreate.getSkillTemplate().c_str(), clientCreate.getWorkingSkill().c_str())); + DEBUG_REPORT_LOG(true, + ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow( + clientCreate.getCharacterName()).c_str())); + LOG("TraceCharacterCreation", + ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", getSUID(), Unicode::wideToNarrow( + clientCreate.getCharacterName()).c_str(), clientCreate.getTemplateName().c_str(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation().c_str(), clientCreate.getHairTemplateName().c_str(), clientCreate.getProfession().c_str(), static_cast(clientCreate.getJedi()), static_cast(clientCreate.getUseNewbieTutorial()), clientCreate.getSkillTemplate().c_str(), clientCreate.getWorkingSkill().c_str())); if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); disconnect(); } else if (clientCreate.getJedi() && !m_canCreateJediCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); disconnect(); } else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The client is not allowed to create any characters", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); disconnect(); } else if (m_hasRequestedCharacterCreate) { - LOG("TraceCharacterCreation", ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); disconnect(); } else if (m_hasCreatedCharacter) { - LOG("TraceCharacterCreation", ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); disconnect(); } else if (clientCreate.getCharacterName().length() == 0) { - LOG("TraceCharacterCreation", ("%d failed character creation. The character's name is empty", getSUID())); - LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); + LOG("TraceCharacterCreation", + ("%d failed character creation. The character's name is empty", getSUID())); + LOG("ClientDisconnect", + ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); disconnect(); } else { Unicode::String biography(clientCreate.getBiography()); @@ -983,18 +1045,47 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { } if (m_isAdminAccount) { - ConnectionCreateCharacter connectionCreate(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); + ConnectionCreateCharacter connectionCreate(m_suid, clientCreate.getCharacterName(), + clientCreate.getTemplateName(), + clientCreate.getScaleFactor(), + clientCreate.getStartingLocation(), + clientCreate.getAppearanceData(), + clientCreate.getHairTemplateName(), + clientCreate.getHairAppearanceData(), + clientCreate.getProfession(), + clientCreate.getJedi(), biography, + clientCreate.getUseNewbieTutorial(), + clientCreate.getSkillTemplate(), + clientCreate.getWorkingSkill(), + m_isAdminAccount, false, m_featureBitsGame); ConnectionServer::sendToCentralProcess(connectionCreate); - LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); + LOG("TraceCharacterCreation", + ("%d character creation request sent to CentralServer", getSUID())); } else { // for regular players, do one final check with the LoginServer // to make sure the character can be created (i.e. that character // limits have not been exceeded) delete m_pendingCharacterCreate; - m_pendingCharacterCreate = new ConnectionCreateCharacter(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); + m_pendingCharacterCreate = new ConnectionCreateCharacter(m_suid, + clientCreate.getCharacterName(), + clientCreate.getTemplateName(), + clientCreate.getScaleFactor(), + clientCreate.getStartingLocation(), + clientCreate.getAppearanceData(), + clientCreate.getHairTemplateName(), + clientCreate.getHairAppearanceData(), + clientCreate.getProfession(), + clientCreate.getJedi(), + biography, + clientCreate.getUseNewbieTutorial(), + clientCreate.getSkillTemplate(), + clientCreate.getWorkingSkill(), + m_isAdminAccount, false, + m_featureBitsGame); - LOG("TraceCharacterCreation", ("%d character creation request awaiting final verification from LoginServer", getSUID())); + LOG("TraceCharacterCreation", + ("%d character creation request awaiting final verification from LoginServer", getSUID())); ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); ConnectionServer::sendToCentralProcess(vcm); @@ -1010,15 +1101,21 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); ConnectionServer::sendToCentralProcess(randomNameRequest); - LOG("TraceCharacterCreation", ("%d requested a random name. Request sent to CentralServer", getSUID())); + LOG("TraceCharacterCreation", + ("%d requested a random name. Request sent to CentralServer", getSUID())); break; } case constcrc("ClientVerifyAndLockNameRequest") : { ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); - VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, clientVerifyAndLockNameRequest.getTemplateName(), clientVerifyAndLockNameRequest.getCharacterName(), m_featureBitsGame); + VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, + clientVerifyAndLockNameRequest.getTemplateName(), + clientVerifyAndLockNameRequest.getCharacterName(), + m_featureBitsGame); ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); - LOG("TraceCharacterCreation", ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow(verifyAndLockNameRequest.getCharacterName()).c_str())); + LOG("TraceCharacterCreation", + ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow( + verifyAndLockNameRequest.getCharacterName()).c_str())); break; } case constcrc("LagRequest") : { @@ -1045,7 +1142,7 @@ void ClientConnection::handleLagRequest() { if (m_hasSelectedCharacter && m_client && m_client->getGameConnection()) { // send to game server GameNetworkMessage request("LagRequest"); - std::vector v; + std::vector v; v.push_back(m_characterId); GameClientMessage gcm(v, true, request); m_client->getGameConnection()->send(gcm, true); @@ -1065,7 +1162,8 @@ void ClientConnection::handleLagRequest() { */ void ClientConnection::setClient(Client *newClient) { //This fatal is here to try to catch the reconnect bug. - WARNING_STRICT_FATAL(m_client, ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); + WARNING_STRICT_FATAL(m_client, + ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); // jrandall - I've removed the fatal because it is blocking some people from getting some work // done. I'm on a high priority fix at the moment. If this warning starts appearing, // set a break point or something. @@ -1100,7 +1198,7 @@ void ClientConnection::send(const GameNetworkMessage &message, const bool reliab //----------------------------------------------------------------------- -std::map &ClientConnection::getPacketBytesPerMinStats() { +std::map &ClientConnection::getPacketBytesPerMinStats() { uint32 now = Clock::timeMs(); if (sm_outgoingBytesMap_Worktime == 0) { sm_outgoingBytesMap_Worktime = now; @@ -1120,9 +1218,9 @@ std::map &ClientConnection::getPacketBytesPerMinStats() { //----------------------------------------------------------------------- void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) { - std::map < unsigned - long, GameClientMessage * > ::iterator - iterFind = m_pendingChatEnterRoomRequests.find(sequence); + std::map::iterator + iterFind = m_pendingChatEnterRoomRequests.find(sequence); if (iterFind != m_pendingChatEnterRoomRequests.end()) { if (result == CHATRESULT_SUCCESS) { if (m_client && m_client->getChatConnection()) { @@ -1152,9 +1250,9 @@ void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequen //----------------------------------------------------------------------- void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) { - std::map < unsigned - long, GameClientMessage * > ::iterator - iterFind = m_pendingChatQueryRoomRequests.find(sequence); + std::map::iterator + iterFind = m_pendingChatQueryRoomRequests.find(sequence); if (iterFind != m_pendingChatQueryRoomRequests.end()) { if (success) { if (m_client && m_client->getChatConnection()) { @@ -1221,17 +1319,23 @@ bool ClientConnection::sendToGameServer(GameConnection *c) { * is located. */ void -ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, const NetworkId &container, const std::string &scene, const Vector &coordinates) { +ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, + const NetworkId &container, const std::string &scene, + const Vector &coordinates) { if (!m_validatingCharacter) { - LOG("TraceCharacterSelection", ("%d received a validation response, but is not in the process of validation", getSUID())); + LOG("TraceCharacterSelection", + ("%d received a validation response, but is not in the process of validation", getSUID())); DEBUG_REPORT_LOG(true, ("Got unexpected onCharacterValidated() for account %lu.\n", getSUID())); return; } m_validatingCharacter = false; if (isValid) { - LOG("TraceCharacterSelection", ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - LOG("CustomerService", ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount(this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + LOG("TraceCharacterSelection", + ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + LOG("CustomerService", + ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount( + this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); m_targetScene = scene; m_targetCoordinates = coordinates; m_characterId = character; @@ -1243,12 +1347,15 @@ ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, // ask CentralServer to suggest a game server for this character // (Central will forward the request to a Planet Server) - RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, m_targetCoordinates, false); + RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, + m_targetCoordinates, false); if (ConnectionServer::getCentralConnection()) { ConnectionServer::getCentralConnection()->send(requestmsg, true); } else { - LOG("ClientDisconnect", ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); - ErrorMessage err("Validation Failed", "The connection to the central server is down. Please try again later."); + LOG("ClientDisconnect", + ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); + ErrorMessage err("Validation Failed", + "The connection to the central server is down. Please try again later."); send(err, true); disconnect(); @@ -1266,7 +1373,11 @@ ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, //------------------------------------------------------------------------------------------ void -ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, const uint32 gameFeatures, const uint32 subscriptionFeatures, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { +ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, + const uint32 gameFeatures, const uint32 subscriptionFeatures, + unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, + unsigned int entitlementTotalTimeSinceLastLogin, + unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { UNREF(id); m_sessionValidated = true; m_suid = suid; @@ -1288,17 +1399,22 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, //verify internal, secure, is on the god list bool loginOK = false; if (!secure) { - LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); + LOG("CustomerService", + ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); } else { if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); + 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, m_requestedSuid)); } else { int adminLevel = 0; if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || 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, m_requestedSuid)); + LOG("CustomerService", + ("AdminLogin: User %s (account %li) attempted to log into account %li, but did not have sufficient permissions", username.c_str(), suid, m_requestedSuid)); } else { - LOG("CustomerService", ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); - DEBUG_REPORT_LOG(true, ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); + LOG("CustomerService", + ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); + DEBUG_REPORT_LOG(true, + ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); m_suid = m_requestedSuid; m_usingAdminLogin = true; loginOK = true; @@ -1364,8 +1480,10 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); if (requiredSubscriptionBits != 0) { if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) { - LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); - LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); + LOG("ClientDisconnect", + ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); + LOG("CustomerService", + ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); disconnect(); return; } @@ -1374,30 +1492,38 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); if (requiredGameBits != 0) { if ((gameFeatures & requiredGameBits) != requiredGameBits) { - LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); - LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); + LOG("ClientDisconnect", + ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); + LOG("CustomerService", + ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); disconnect(); return; } } // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time - GenericValueTypeMessage < std::pair < std::pair < unsigned + GenericValueTypeMessage , std::pair < int, int32 > > > + long>, std::pair > > const msgFeatureBits( - "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), static_cast(::time(nullptr))))); + "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), + std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), + static_cast(::time(nullptr))))); send(msgFeatureBits, true); std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); - LOG("CustomerService", ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount(this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); + LOG("CustomerService", + ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount( + this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account if (!m_usingAdminLogin && !m_isSecure) { - GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", std::make_pair(m_suid, m_sessionId)); + GenericValueTypeMessage> const dropDuplicateConnections("ConnSrvDropDupeConns", + std::make_pair(m_suid, + m_sessionId)); ConnectionServer::sendToCentralProcess(dropDuplicateConnections); } } @@ -1423,13 +1549,13 @@ std::string ClientConnection::describeAccount(const ClientConnection *c) { // ---------------------------------------------------------------------- -std::vector > const &ClientConnection::getConsumedRewardEvents() const { +std::vector> const &ClientConnection::getConsumedRewardEvents() const { return m_consumedRewardEvents; } // ---------------------------------------------------------------------- -std::vector > const &ClientConnection::getClaimedRewardItems() const { +std::vector> const &ClientConnection::getClaimedRewardItems() const { return m_claimedRewardItems; } From 5a693791f610375f90aa874e4eabfaaf59790a2d Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 17:22:10 +0000 Subject: [PATCH 24/55] add seemingly redundant check to allow godmode properly --- .../serverGame/src/shared/core/Client.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 011891c2..12d2b1d0 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -244,8 +244,8 @@ Client::Client(ConnectionServerConnection & connection, const NetworkId & charac connectToEmitter(connection, "ConnectionServerConnectionDestroyed"); // Check god permissions - if ( ConfigServerGame::getAdminGodToAll() - || ( (!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) + if (ConfigServerGame::getAdminGodToAll() + || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) && AdminAccountManager::isAdminAccount(Unicode::toLower(accountName), m_godLevel) && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(ipAddr)))) { @@ -2229,6 +2229,18 @@ bool Client::setGodMode(bool value) { bool wasInGodMode = m_godMode; m_godMode = value; + + // Check god permissions + // the check above seems not to work + if (ConfigServerGame::getAdminGodToAll() + || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) + && AdminAccountManager::isAdminAccount(Unicode::toLower(m_accountName), m_godLevel) + && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(m_ipAddress)))) + { + m_godValidated = true; + if (ConfigServerGame::getAdminGodToAll()) + m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); + } if (value && !m_godValidated) { From 3efe5c975902796483c830094bf15be40634d283 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 17:31:46 +0000 Subject: [PATCH 25/55] remove a check that was malfunctioning --- .../serverGame/src/shared/core/Client.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 12d2b1d0..9d11d0a5 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -2229,24 +2229,13 @@ bool Client::setGodMode(bool value) { bool wasInGodMode = m_godMode; m_godMode = value; - - // Check god permissions - // the check above seems not to work - if (ConfigServerGame::getAdminGodToAll() - || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) - && AdminAccountManager::isAdminAccount(Unicode::toLower(m_accountName), m_godLevel) - && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(m_ipAddress)))) - { - m_godValidated = true; - if (ConfigServerGame::getAdminGodToAll()) - m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); - } - if (value && !m_godValidated) + // wtf, the checks above do nothing + /*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) From cce8140c5ff770e53590ed7191ad0b563a995d41 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 17:50:33 +0000 Subject: [PATCH 26/55] Revert "remove a check that was malfunctioning" This reverts commit 6aae26ed4bbfbabb95d236f38052edaf176da7b8. --- .../serverGame/src/shared/core/Client.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 9d11d0a5..12d2b1d0 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -2229,13 +2229,24 @@ bool Client::setGodMode(bool value) { bool wasInGodMode = m_godMode; m_godMode = value; + + // Check god permissions + // the check above seems not to work + if (ConfigServerGame::getAdminGodToAll() + || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) + && AdminAccountManager::isAdminAccount(Unicode::toLower(m_accountName), m_godLevel) + && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(m_ipAddress)))) + { + m_godValidated = true; + if (ConfigServerGame::getAdminGodToAll()) + m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); + } - // wtf, the checks above do nothing - /*if (value && !m_godValidated) + 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) From c3a47076233f3ba6d61b37908cace54d848675ae Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 1 Jan 2017 18:02:40 +0000 Subject: [PATCH 27/55] back to stock --- .../serverGame/src/shared/core/Client.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 12d2b1d0..2c4ebd71 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -2230,22 +2230,11 @@ bool Client::setGodMode(bool value) bool wasInGodMode = m_godMode; m_godMode = value; - // Check god permissions - // the check above seems not to work - if (ConfigServerGame::getAdminGodToAll() - || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) - && AdminAccountManager::isAdminAccount(Unicode::toLower(m_accountName), m_godLevel) - && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(m_ipAddress)))) - { - m_godValidated = true; - if (ConfigServerGame::getAdminGodToAll()) - m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); - } - + if (value && !m_godValidated) { - LOG("CustomerService", ("Avatar:%s denied god mode because it wasn't validated.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str() )); - m_godMode = false; + 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()); From f6d82340e2b7087291f3ba8027811258de193b42 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Mon, 2 Jan 2017 23:39:54 +0000 Subject: [PATCH 28/55] check GM on the gameserver based on station id because it is most readily available to us. see corresponding change to the datatable --- .../library/serverGame/src/shared/core/Client.cpp | 15 ++++++++++++--- .../src/shared/AdminAccountManager.cpp | 14 ++++++++++++++ .../src/shared/AdminAccountManager.h | 1 + 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 2c4ebd71..00fb39cd 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -2227,14 +2227,23 @@ float Client::computeDeltaTimeInSeconds(uint32 const syncStampLong) const bool Client::setGodMode(bool value) { + // (re?) check god permissions + m_godLevel = AdminAccountManager::isAdminAccount(getStationId()); + + if (ConfigServerGame::getAdminGodToAll() || (m_godLevel > 0)) + { + m_godValidated = true; + if (ConfigServerGame::getAdminGodToAll()) + m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); + } + 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; + 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()); diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp index e4075721..92a19391 100755 --- a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp @@ -64,6 +64,20 @@ const std::string & AdminAccountManager::getAdminTagName() //----------------------------------------------------------------------- +// if they are in the iff and have a level set, return it +int AdminAccountManager::isAdminAccount(int suid) +{ + DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + + int columnNumber = ms_adminTable->findColumnNumber("AdminSuid"); + DEBUG_FATAL(columnNumber == -1, ("Error loading admin table...no account column")); + int row = ms_adminTable->searchColumnInt(columnNumber, suid); + if (row == -1) + return false; + + return (int) ms_adminTable->getIntValue("AdminLevel", row); +} + bool AdminAccountManager::isAdminAccount(const std::string & account, int& level) { level = 0; diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.h b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h index d099b790..378c5893 100755 --- a/engine/server/library/serverUtility/src/shared/AdminAccountManager.h +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h @@ -19,6 +19,7 @@ public: static const char *getAdminCommandName(); static const std::string & getAdminTagName(); + static int isAdminAccount(int suid); static bool isAdminAccount(const std::string & account, int& level); static bool isInternalIp(const std::string & addr); static void reload(); From 365ea61813c20999621491d34c08a37471c5b124 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Tue, 3 Jan 2017 16:07:50 +0000 Subject: [PATCH 29/55] should fix build issue with db --- game/server/database/schema/account_map.tab | 9 +++++++++ game/server/database/updates/270.sql | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 game/server/database/schema/account_map.tab diff --git a/game/server/database/schema/account_map.tab b/game/server/database/schema/account_map.tab new file mode 100644 index 00000000..c8fbe7e2 --- /dev/null +++ b/game/server/database/schema/account_map.tab @@ -0,0 +1,9 @@ +CREATE TABLE "ACCOUNT_MAP" +( + "PARENT_ID" NUMBER(38,0) NOT NULL ENABLE, + "CHILD_ID" NUMBER(38,0) NOT NULL ENABLE, + CONSTRAINT "ACCOUNT_MAP_UK1" UNIQUE ("CHILD_ID", "PARENT_ID") USING INDEX (CREATE INDEX "ACCOUNT_MAP_INDEX2" ON "ACCOUNT_MAP" ("CHILD_ID","PARENT_ID")), + CONSTRAINT "ACCOUNT_MAP_UK2" UNIQUE ("CHILD_ID") USING INDEX (CREATE INDEX "ACCOUNT_MAP_INDEX1" ON "ACCOUNT_MAP" ("CHILD_ID")) +); + +grant select on account_map to public; diff --git a/game/server/database/updates/270.sql b/game/server/database/updates/270.sql index 95409edf..cb50d9e2 100644 --- a/game/server/database/updates/270.sql +++ b/game/server/database/updates/270.sql @@ -1,9 +1 @@ -CREATE TABLE "ACCOUNT_MAP" -( - "PARENT_ID" NUMBER(38,0) NOT NULL ENABLE, - "CHILD_ID" NUMBER(38,0) NOT NULL ENABLE, - CONSTRAINT "ACCOUNT_MAP_UK1" UNIQUE ("CHILD_ID", "PARENT_ID") USING INDEX (CREATE INDEX "ACCOUNT_MAP_INDEX2" ON "ACCOUNT_MAP" ("CHILD_ID","PARENT_ID")), - CONSTRAINT "ACCOUNT_MAP_UK2" UNIQUE ("CHILD_ID") USING INDEX (CREATE INDEX "ACCOUNT_MAP_INDEX1" ON "ACCOUNT_MAP" ("CHILD_ID")) -); - update version_number set version_number=270, min_version_number=270; From 11fc9a75648fb741588452bc22d3c7e5da1442a1 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Tue, 3 Jan 2017 22:20:26 -0600 Subject: [PATCH 30/55] allow the old style suid hashing in login server --- .../src/shared/ClientConnection.cpp | 2 - .../src/shared/ClientConnection.cpp | 55 +- .../src/shared/ConfigLoginServer.cpp | 2 +- .../src/shared/ConfigLoginServer.h | 9 +- .../LoginServer/src/shared/LoginServer.cpp | 1 - .../serverGame/src/shared/core/Client.cpp | 4254 ++++++++--------- 6 files changed, 2021 insertions(+), 2302 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index bc3c7c31..5fa67b9f 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -303,8 +303,6 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { result = ConnectionServer::decryptToken(token, sessionId, m_requestedSuid); } - - static const std::string sessURL(ConfigConnectionServer::getSessionURL()); if (result || strlen(sessionId) != 0) { diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index a6c1ead7..8cea9927 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -152,11 +152,13 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // originally was used to validate station API credentials, now uses our custom api void ClientConnection::validateClient(const std::string &id, const std::string &key) { bool authOK = false; + bool testMode = false; static const std::string authURL(ConfigLoginServer::getExternalAuthUrl()); std::string uname; std::string parentAccount; std::string sessionID; + StationId user_id; StationId parent_id; std::unordered_map childAccounts; @@ -181,8 +183,21 @@ void ClientConnection::validateClient(const std::string &id, const std::string & parentAccount = api.getString("mainAccount"); childAccounts = api.getStringMap("subAccounts"); - user_id = static_cast(api.getNullableValue("user_id")); - parent_id = static_cast(api.getNullableValue("parent_id")); + if (!ConfigLoginServer::getUseOldSuidGenerator()) { + user_id = static_cast(api.getNullableValue("user_id")); + parent_id = static_cast(api.getNullableValue("parent_id")); + } else { + if (parentAccount.length() > MAX_ACCOUNT_NAME_LENGTH) { + parentAccount.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) { + uname.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + parent_id = std::hash{}(parentAccount.c_str()); + user_id = std::hash{}(uname.c_str()); + } } else { std::string msg(api.getString("message")); if (msg.empty()) { @@ -199,10 +214,19 @@ void ClientConnection::validateClient(const std::string &id, const std::string & } else { // test mode authOK = true; + testMode = true; uname = id; + + if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) { + uname.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + user_id = std::hash{}(uname.c_str()); } - if (authOK) { + m_stationId = user_id; + + if (authOK && !testMode) { REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); if (!parentAccount.empty()) { @@ -217,24 +241,33 @@ void ClientConnection::validateClient(const std::string &id, const std::string & StationId child_id = static_cast(i.first); std::string child(i.second); - if (!child.empty()) { - REPORT_LOG((parent_id != - child_id), ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); + if (!child.empty() && i.first > 0) { + if (ConfigLoginServer::getUseOldSuidGenerator()) { + if (child.length() > MAX_ACCOUNT_NAME_LENGTH) { + child.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + child_id = std::hash{}(child.c_str()); + } + + REPORT_LOG((parent_id != child_id), ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); // insert all related accounts, if not already there, into the db if (parent_id != child_id) { DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); } - } else { - WARNING(true, ("Login API returned empty child account(s).")); } + } else { + WARNING(true, ("Login API returned empty child account(s).")); } + } - LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); - - m_stationId = user_id; + LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); + if (!testMode) { LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, sessionID.c_str(), 0xFFFFFFFF, 0xFFFFFFFF); + } else { + LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, nullptr, 0xFFFFFFFF, 0xFFFFFFFF); } } diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp index 9c4dcd04..6279494e 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp @@ -116,7 +116,7 @@ void ConfigLoginServer::install(void) KEY_BOOL(requireSecureLoginForCsTool, true); KEY_BOOL(useExternalAuth, false); KEY_STRING(externalAuthURL, ""); - KEY_INT(maxConnectionsPerIP, 4); // assuming 2 people playing in the same household + KEY_BOOL(useOldSuidGenerator, false); int index = 0; char const * result = 0; diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h index a11330dc..888a693c 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h @@ -69,7 +69,7 @@ class ConfigLoginServer const char * externalAuthURL; - int maxConnectionsPerIP; + bool useOldSuidGenerator; }; static const uint16 getCentralServicePort(); @@ -139,8 +139,6 @@ class ConfigLoginServer static bool isCharacterCreationDisabled(std::string const & cluster); static std::set const & getCharacterCreationDisabledClusterList(); - static const int getMaxConnectionsPerIP(); - private: static Data * data; }; @@ -488,9 +486,10 @@ inline const char * ConfigLoginServer::getExternalAuthUrl() return data->externalAuthURL; } -inline const int ConfigLoginServer::getMaxConnectionsPerIP() + +inline const bool ConfigLoginServer::getUseOldSuidGenerator() { - return data->maxConnectionsPerIP; + return data->useOldSuidGenerator; } // ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 0df5fc58..342a2dfb 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -130,7 +130,6 @@ LoginServer::LoginServer() NetworkSetupData setup; setup.port = ConfigLoginServer::getClientServicePort(); setup.maxConnections = ConfigLoginServer::getMaxClients(); - setup.maxConnectionsPerIP = ConfigLoginServer::getMaxConnectionsPerIP(); setup.oldestUnacknowledgedTimeout = 30000; setup.keepAliveDelay = 45000; setup.compress = ConfigLoginServer::getCompressClientNetworkTraffic(); diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 00fb39cd..5b08f118 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -130,2435 +130,2125 @@ #include "sharedFoundation/CrcConstexpr.hpp" -namespace ClientNamespace -{ - // list of object types, radial menu action permission - // override, to allow certain object types to have certain radial - // menu action invoked on them by non-owners of the object - std::set > s_radialMenuPermissionOverrideTemplateItemType; - std::set > s_radialMenuPermissionOverrideStaticItemType; - - // ---------------------------------------------------------------------- - - bool canManipulateObjectExceptionCheck(ServerObject const &target, int menuType, Container::ContainerErrorCode& errorCode) - { - if (errorCode == Container::CEC_NoPermission) - { - const std::string & objectStaticName = target.getStaticItemName(); - if (objectStaticName.empty()) - { - if (s_radialMenuPermissionOverrideTemplateItemType.count(std::make_pair(target.getTemplateCrc(), menuType)) > 0) - { - errorCode = Container::CEC_Success; - return true; - } - } - else if (s_radialMenuPermissionOverrideStaticItemType.count(std::make_pair(objectStaticName, menuType)) > 0) - { - errorCode = Container::CEC_Success; - return true; - } - } - - return false; - } - - // ---------------------------------------------------------------------- - - void remove() - { - } -} - -// ====================================================================== - -Client::ClientMessage::ClientMessage(const std::string & src) : -MessageDispatch::MessageBase(src.c_str()) -{ -} - -//----------------------------------------------------------------------- - -Client::ClientMessage::~ClientMessage() -{ -} - - - - -//----------------------------------------------------------------------- - -std::map< std::string, uint32 > Client::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute -std::map< std::string, uint32 > Client::sm_outgoingBytesMap_Stats; // computed stats from the last minute -uint32 Client::sm_outgoingBytesMap_Worktime = 0 ; // time we started filling in the working map - - -// ====================================================================== - -Client::Client(ConnectionServerConnection & connection, const NetworkId & characterObjectId, const std::string& accountName, const std::string& ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const & observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const & accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport ) : - MessageDispatch::Receiver(), - MessageDispatch::Emitter(), - m_accountName(accountName), - m_characterName(), - m_characterObjectId(characterObjectId), - m_connection(&connection), - m_controlledObjects(), - m_godLevel(0), - m_godMode(false), - m_godValidated(false), - m_ipAddress(ipAddr), - m_isReady(false), - m_isSecure(isSecure), - m_isSkipLoadScreen(isSkipLoadScreen), - m_primaryControlledObject(NetworkId::cms_invalid), - destroyNotifier(), - m_observing(), - m_openedContainers(), - m_watchedByList(), - m_lastNonIdleTime(ServerClock::getInstance().getGameTimeSeconds()), - m_stationId(stationId), - m_connectionServerLag(0), - m_gameServerLag(0), - m_gameFeatures(gameFeatures), - m_subscriptionFeatures(subscriptionFeatures), - m_accountFeatureIds(accountFeatureIds), - m_entitlementTotalTime(entitlementTotalTime), - m_entitlementEntitledTime(entitlementEntitledTime), - m_entitlementTotalTimeSinceLastLogin(entitlementTotalTimeSinceLastLogin), - m_entitlementEntitledTimeSinceLastLogin(entitlementEntitledTimeSinceLastLogin), - m_buddyPoints(buddyPoints), - m_previousObservedObjects(observedObjects), - m_syncUIs(), - m_consumedRewardEvents(consumedRewardEvents), - m_claimedRewardItems(claimedRewardItems), - m_usingAdminLogin(usingAdminLogin), - m_combatSpamFilter(combatSpamFilter), - m_combatSpamRangeSquaredFilter(combatSpamRangeSquaredFilter), - m_furnitureRotationDegree(furnitureRotationDegree), - m_hasUnoccupiedJediSlot(hasUnoccupiedJediSlot), - m_isJediSlotCharacter(isJediSlotCharacter), - m_sendToStarport( sendToStarport ) -{ - - connectToEmitter(connection, "ConnectionServerConnectionClosed"); - connectToEmitter(connection, "ConnectionServerConnectionDestroyed"); - - // Check god permissions - if (ConfigServerGame::getAdminGodToAll() - || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) - && AdminAccountManager::isAdminAccount(Unicode::toLower(accountName), m_godLevel) - && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(ipAddr)))) - { - m_godValidated = true; - if (ConfigServerGame::getAdminGodToAll()) - m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); - } - - // See if our controlled object is ready yet. - ServerObject *obj = LogoutTracker::findPendingCharacterSave(characterObjectId); - if (obj) - { - // If we're waiting to be saved in the LogoutTracker, then we've been - // removed from our container, so restore our containment if need be. - Object *containerObject = ContainerInterface::getContainedByObject(*obj); - if (containerObject) - { - // Don't ever put the character into a packed house - ServerObject * const serverObject = containerObject->asServerObject(); - CellObject * const cellObject = (serverObject ? serverObject->asCellObject() : nullptr); - BuildingObject * const buildingObject = (cellObject ? cellObject->getOwnerBuilding() : nullptr); - - if ((buildingObject) && (!buildingObject->isInWorld())) - { - ContainedByProperty * const cby = ContainerInterface::getContainedByProperty(*obj); - if (cby) - { - DEBUG_REPORT_LOG(true,("Ejecting player %s from building %s, because the building is packed\n",characterObjectId.getValueString().c_str(), buildingObject->getNetworkId().getValueString().c_str())); - LOG("CustomerService",("Login: Ejecting player %s from building %s, because the building is packed",characterObjectId.getValueString().c_str(), buildingObject->getNetworkId().getValueString().c_str())); - - cby->setContainedBy(NetworkId::cms_invalid, true); - containerObject = 0; - - // attempt to put the character at the ejection point of the building - if (!ServerWorld::isSpaceScene()) - { - DynamicVariableLocationData ejectionPoint; - if (obj->getObjVars().getItem("building_ejection_point", ejectionPoint) && (ServerWorld::getSceneId() == ejectionPoint.scene) && (!ejectionPoint.cell.isValid())) - { - obj->removeObjVarItem("building_ejection_point"); - obj->setPosition_p(ejectionPoint.pos); - } - } - } - } - else if (containerObject->isAuthoritative()) - { - // The cell depersist step will try to set the parent cell of the player. - // However, that procedure will fail because the "contained by" property - // says the player is in a container when they really are not. - ContainedByProperty * const cby = ContainerInterface::getContainedByProperty(*obj); - if (cby) - { - // We need to remove and then re-add the property so that the - // property is updated immediately (as opposed to waiting for an alter) - cby->setContainedBy(NetworkId::cms_invalid, true); - obj->removeProperty(cby->getPropertyId()); - obj->addProperty(*cby, true); - } - - // save and restore the original transform. The existing transform should be in parent - // space, but it is in world. down through depersistContents there is an assumption that - // it is in parent space and gets transformed incorrectly. - Transform origTransform = obj->getTransform_o2p(); - - // NOTE: Depersist works slightly differently than when the player - // is loaded from the database since in this case the player - // is initialized when depersist is called - Container * const container = ContainerInterface::getContainer(*containerObject); - NOT_NULL(container); - IGNORE_RETURN(container->depersistContents(*obj)); - - // if failed to put character back into the container, then clean up the - // containment relationship so that the character is now out in the world - if (ContainerInterface::getContainedByObject(*obj) != containerObject) - { - IGNORE_RETURN(container->internalItemRemoved(*obj)); - - if (cby) - { - // We need to remove and then re-add the property so that the - // property is updated immediately (as opposed to waiting for an alter) - cby->setContainedBy(NetworkId::cms_invalid, true); - obj->removeProperty(cby->getPropertyId()); - obj->addProperty(*cby, true); - } - - // attempt to put the character at the ejection point of the building - if (!ServerWorld::isSpaceScene()) - { - DynamicVariableLocationData ejectionPoint; - if (obj->getObjVars().getItem("building_ejection_point", ejectionPoint) && (ServerWorld::getSceneId() == ejectionPoint.scene) && (!ejectionPoint.cell.isValid())) - { - DEBUG_REPORT_LOG(true,("Ejecting player %s from building %s, because could not put player back in building\n",characterObjectId.getValueString().c_str(), (buildingObject ? buildingObject->getNetworkId().getValueString().c_str() : containerObject->getNetworkId().getValueString().c_str()))); - LOG("CustomerService",("Login: Ejecting player %s from building %s, because could not put player back in building",characterObjectId.getValueString().c_str(), (buildingObject ? buildingObject->getNetworkId().getValueString().c_str() : containerObject->getNetworkId().getValueString().c_str()))); - - obj->removeObjVarItem("building_ejection_point"); - obj->setPosition_p(ejectionPoint.pos); - } - } - - containerObject = 0; - } - else - { - obj->setTransform_o2w(origTransform); - - // if the character was in a building, tell the building it has gained - // the player so the building demand load/unload system can work correctly - Object *buildingObj = ContainerInterface::getTopmostContainer(*containerObject); - if (buildingObj && buildingObj->asServerObject() && buildingObj->asServerObject()->asBuildingObject()) - buildingObj->asServerObject()->asBuildingObject()->gainedPlayer(*obj); - } - } - else - { - // The container is no longer authoritative on this server. Move us to a safe place - // outside the container. - Object * const topmostObject = ContainerInterface::getTopmostContainer(*obj); - BuildingObject * const topmostBuilding = dynamic_cast(topmostObject); - if (topmostBuilding) - { - DEBUG_REPORT_LOG(true,("Ejecting player %s from building %s, because the building has changed authority\n",characterObjectId.getValueString().c_str(), topmostBuilding->getNetworkId().getValueString().c_str())); - LOG("CustomerService",("Login: Ejecting player %s from building %s, because the building has changed authority",characterObjectId.getValueString().c_str(), topmostBuilding->getNetworkId().getValueString().c_str())); - ContainedByProperty * const cby = ContainerInterface::getContainedByProperty(*obj); - if (cby) - { - cby->setContainedBy(NetworkId::cms_invalid, true); - containerObject = 0; - - PortalProperty * const portalProperty = topmostBuilding->getPortalProperty(); - if (portalProperty) - { - ServerController * const controller = dynamic_cast(obj->getController()); - if (controller) - { - Transform destinationTransform(Transform::IF_none); - destinationTransform.multiply(topmostBuilding->getTransform_o2w(), portalProperty->getEjectionLocationTransform()); - obj->setTransform_o2p(destinationTransform); - } - } - } - } - else - WARNING(true,("Expected player %s to be in a building, but he was in some other type of object. Skipping authority fixup because something strange is going on.",characterObjectId.getValueString().c_str())); - } - } - else - { - // check for the case where we were in a container that isn't there anymore - ContainedByProperty * const cby = ContainerInterface::getContainedByProperty(*obj); - if ((cby) && (cby->getContainedByNetworkId().isValid())) - { - DEBUG_REPORT_LOG(true,("Ejecting player %s from building %s, because the building does not exist anymore\n",characterObjectId.getValueString().c_str(), cby->getContainedByNetworkId().getValueString().c_str())); - LOG("CustomerService",("Login: Ejecting player %s from building %s, because the building does not exist anymore",characterObjectId.getValueString().c_str(), cby->getContainedByNetworkId().getValueString().c_str())); - - cby->setContainedBy(NetworkId::cms_invalid, true); - - // attempt to put the character at the ejection point of the building - if (!ServerWorld::isSpaceScene()) - { - DynamicVariableLocationData ejectionPoint; - if (obj->getObjVars().getItem("building_ejection_point", ejectionPoint) && (ServerWorld::getSceneId() == ejectionPoint.scene) && (!ejectionPoint.cell.isValid())) - { - obj->removeObjVarItem("building_ejection_point"); - obj->setPosition_p(ejectionPoint.pos); - } - } - } - } - - // Only add to the world if it in a location which should be in the world. - if (!containerObject || (containerObject->isInWorld() && containerObject->getContainerProperty()->isContentItemExposedWith(*obj))) - obj->addToWorld(); - - // Notify the object that it has a client about to load - obj->onClientAboutToLoad(); - - // We need to trigger having been made authoritative since we are an object which has been - // disconnected from the world. - obj->triggerMadeAuthoritative(); - - // Create proxies as needed - ProxyList const &proxyList = obj->getExposedProxyList(); - if (!proxyList.empty()) - { - ServerMessageForwarding::begin(std::vector(proxyList.begin(), proxyList.end())); - - obj->forwardServerCreateAndBaselines(); - - ServerMessageForwarding::end(); - } - } - else - obj = ServerWorld::findObjectByNetworkId(characterObjectId); - - if (obj) - { - obj->checkAndAddClientControl(this); - } - - // Send server-specific settings to the client - ParametersMessage const msg(ConfigServerGame::getWeatherUpdateSeconds()); - send(msg, true); - - ObjectTracker::addPlayer(); -} - -//----------------------------------------------------------------------- - -Client::~Client() -{ - ClientDestroy d(this); - destroyNotifier.emitMessage(d); - - if (ServerWorld::isSpaceScene()) - SpaceVisibilityManager::removeClient(*this); - - ObserveTracker::onClientDestroyed(*this); - ShipClientUpdateTracker::onClientDestroyed(*this); - - DEBUG_FATAL(!m_controlledObjects.empty(),("Deleting a client with a non-empty controlled objects list!\n")); - m_primaryControlledObject = NetworkId::cms_invalid; - - //clean up any orphaned SynchronizedUIs - for (std::vector >::iterator i = m_syncUIs.begin(); i != m_syncUIs.end(); ++i) - { - ServerSynchronizedUi* syncUI = i->getPointer(); - delete syncUI; - } - - ObjectTracker::removePlayer(); - - PvpUpdateObserver::removeClientFromPvpStatusCache(this); - - m_connection = 0; -} - -// ---------------------------------------------------------------------- - -void Client::install() -{ - // read in the list of object types, radial menu action permission - // override, to allow certain object types to have certain radial - // menu action invoked on them by non-owners of the object - char const * const radialMenuPermissionOverrideDataTableName = "datatables/player/radial_menu_permission_override.iff"; - DataTable * table = DataTableManager::getTable(radialMenuPermissionOverrideDataTableName, true); - if (table) - { - int const columnObjectTemplate = table->findColumnNumber("Object Template"); - int const columnCommand = table->findColumnNumber("Command"); - if ((columnObjectTemplate >= 0) && (columnCommand >= 0)) - { - std::string objectTemplate; - std::string command; - int commandMenuId; - - for (int i = 0, numRows = table->getNumRows(); i < numRows; ++i) - { - objectTemplate = table->getStringValue(columnObjectTemplate, i); - if (objectTemplate.empty()) - continue; - - command = table->getStringValue(columnCommand, i); - if (command.empty()) - continue; - - commandMenuId = RadialMenuManager::getMenuTypeByName(command); - if (commandMenuId == 0) - continue; - - if (objectTemplate.find(".iff") != std::string::npos) - ClientNamespace::s_radialMenuPermissionOverrideTemplateItemType.insert(std::make_pair(CrcLowerString::calculateCrc(objectTemplate.c_str()), commandMenuId)); - else - ClientNamespace::s_radialMenuPermissionOverrideStaticItemType.insert(std::make_pair(objectTemplate, commandMenuId)); - } - } - - DataTableManager::close(radialMenuPermissionOverrideDataTableName); - } - - ExitChain::add(ClientNamespace::remove, "ClientNamespace::remove"); -} - -//----------------------------------------------------------------------- - -void Client::addControlledObject(ServerObject &object) -{ - // check to see if it is in the list already - if (std::find(m_controlledObjects.begin(), m_controlledObjects.end(), &object) == m_controlledObjects.end()) - m_controlledObjects.push_back(&object); - else - DEBUG_WARNING(true, ("Client adding controlled object [%s] that is already controlled", object.getNetworkId().getValueString().c_str())); - - //finally set a pointer to the Client object on the object - object.setClient(*this); - ObserveTracker::onObjectControlled(*this, object, m_previousObservedObjects); - - // Any objects to be re-controlled have been at this point, so clean up any old objects that are no longer observed - ObserveTracker::onClientControlComplete(*this, m_previousObservedObjects); - m_previousObservedObjects.clear(); - - // If in space, add the client to SpaceVisibilityManager. Only do this for the topmost object the client controls that is in the world. - if (ServerWorld::isSpaceScene()) - { - Object * topmost = ContainerInterface::getTopmostContainer(object); - NOT_NULL(topmost); - NOT_NULL(topmost->asServerObject()); - if (topmost->isInWorld()) - SpaceVisibilityManager::addClient(*this, *(topmost->asServerObject())); - } - - // Restore god mode after changing servers - CreatureObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); - if (primaryControlledObject) - { - if (primaryControlledObject->hasCommand(AdminAccountManager::getAdminCommandName())) - setGodMode(true); - } -} - -// ---------------------------------------------------------------------- - -void Client::clearControlledObjects() -{ - while (!m_controlledObjects.empty()) - removeControlledObject(**m_controlledObjects.begin()); - - PvpUpdateObserver::removeClientFromPvpStatusCache(this); -} - -// ---------------------------------------------------------------------- - -ServerObject *Client::findControlledObject(NetworkId const &oid) const -{ - for (std::vector::const_iterator i = m_controlledObjects.begin(); i != m_controlledObjects.end(); ++i) - if ((*i) && (*i)->getNetworkId() == oid) - return *i; - return 0; -} - -// ---------------------------------------------------------------------- - -std::vector const &Client::getControlledObjects() const -{ - return m_controlledObjects; //lint !e1536 //low access -} - -//----------------------------------------------------------------------- - -bool Client::isControlled(NetworkId const &id) const -{ - std::vector::const_iterator i; - for(i = m_controlledObjects.begin(); i != m_controlledObjects.end(); ++i) - { - ServerObject * object = *i; - if(object && object->getNetworkId() == id) - return true; - } - return false; -} - -//----------------------------------------------------------------------- - -void Client::onLoadPlayer(CreatureObject &newCharacter) -{ - if (m_primaryControlledObject != NetworkId::cms_invalid) - { - DEBUG_WARNING(true, ("Already have a primary object!")); - if (m_primaryControlledObject == newCharacter.getNetworkId()) - return; - } - - m_primaryControlledObject = CachedNetworkId(newCharacter); - - assumeControl(newCharacter); -} - -//----------------------------------------------------------------------- - -void Client::assumeControl(CreatureObject &newCharacter) -{ - DEBUG_FATAL(newCharacter.getNetworkId() != m_primaryControlledObject, ("Tried to assume control of the wrong object?")); - - // Add the object to the controlled object list - addControlledObject(newCharacter); - - // Register player name with the global list - std::string const &firstName = Unicode::wideToNarrow(Unicode::toLower(newCharacter.getAssignedObjectFirstName())); - std::string const &fullName = Unicode::wideToNarrow(newCharacter.getAssignedObjectName()); - PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(&newCharacter); - NameManager::getInstance().addPlayer(newCharacter.getNetworkId(), (playerObject ? playerObject->getStationId() : static_cast(m_stationId)), firstName, fullName, 0, Os::getRealSystemTime(), true); - - static const std::string loginTrace("TRACE_LOGIN"); - LOG(loginTrace, ("sending ControlAssumed(%s, %s)", m_primaryControlledObject.getValueString().c_str(), ConfigServerGame::getGroundScene())); - - ControlAssumed const controlMessage( - m_primaryControlledObject, - ConfigServerGame::getGroundScene(), - m_isSkipLoadScreen, - newCharacter.getTransform_o2w().getPosition_p(), - newCharacter.getObjectFrameK_w().theta(), - newCharacter.getSharedTemplateName(), - static_cast(ServerClock::getInstance().getGameTimeSeconds())); - - sendToConnectionServer(controlMessage); - - m_isSkipLoadScreen = false; -} - -//----------------------------------------------------------------------- - -void Client::receiveClientMessage(const GameNetworkMessage & message) -{ - try - { - - // Ignore any messages if the character is not loaded yet. - if (m_primaryControlledObject == NetworkId::cms_invalid) - { - DEBUG_REPORT_LOG(true,("Ignoring message for character %s because it is not loaded yet.\n",m_characterObjectId.getValueString().c_str())); - return; - } - - ServerObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); - - if (!primaryControlledObject) - { - DEBUG_REPORT_LOG(true,("Ignoring message for character %s because object %s cannot be found.\n", - m_characterObjectId.getValueString().c_str(), m_primaryControlledObject.getValueString().c_str())); - return; - } - - //----------------------------------------------------------------- - - const uint32 messageType = message.getType(); - - switch(messageType) { - case constcrc("ShipUpdateTransformMessage") : - { - Archive::ReadIterator readIterator = static_cast(message).getByteStream().begin(); - ShipUpdateTransformMessage const shipUpdateTransformMessage(readIterator); - - for (std::vector::const_iterator i = m_controlledObjects.begin(); i != m_controlledObjects.end(); ++i) - { - ShipObject * const ship = (*i)->asShipObject(); - if (ship) - { - PlayerShipController * const playerShipController = safe_cast(ship->getController()); - if (playerShipController) - playerShipController->receiveTransform(shipUpdateTransformMessage); - } - } - break; - } - - //---------------------------------------------------------------------- - - case constcrc("CreateProjectileMessage") : - { - Archive::ReadIterator readIterator = static_cast(message).getByteStream().begin(); - CreateProjectileMessage const createProjectileMessage(readIterator); - - // pilots can fire from non-turrets, gunners can fire their turret - ServerObject * const characterObject = getCharacterObject(); - if (characterObject) - { - ServerObject * const containedBy = safe_cast(ContainerInterface::getContainedByObject(*characterObject)); - if (containedBy) - { - SlottedContainer const * const slottedContainer = ContainerInterface::getSlottedContainer(*containedBy); - ShipObject * const shipObject = ShipObject::getContainingShipObject(containedBy); - - if ( (shipObject != nullptr) - && (slottedContainer != nullptr) - && !shipObject->hasCondition(TangibleObject::C_docking)) - { - bool shotOk = false; - - int const weaponIndex = createProjectileMessage.getWeaponIndex(); - if (weaponIndex >= 0 && weaponIndex < ShipChassisSlotType::cms_numWeaponIndices) - { - Container::ContainerErrorCode err = Container::CEC_Success; - if (shipObject->isTurret(weaponIndex)) - { - if ( slottedContainer->getObjectInSlot(ShipSlotIdManager::getPobShipGunnerSlotId(weaponIndex), err) == characterObject->getNetworkId() - || slottedContainer->getObjectInSlot(ShipSlotIdManager::getShipGunnerSlotId(weaponIndex), err) == characterObject->getNetworkId()) - shotOk = true; // gunner firing his turret - } - else - { - if ( slottedContainer->getObjectInSlot(ShipSlotIdManager::getShipPilotSlotId(), err) == characterObject->getNetworkId() - || slottedContainer->getObjectInSlot(ShipSlotIdManager::getPobShipPilotSlotId(), err) == characterObject->getNetworkId()) - shotOk = true; // pilot firing non-turret - } - } - - // only gods can fire while invulnerable - if (shipObject->isInvulnerable() && !isGod()) - shotOk = false; - - if (shotOk) - { - shipObject->enqueueFireShotClient( - *this, - weaponIndex, - createProjectileMessage.getTransform_p(), - createProjectileMessage.getTargetedComponent(), - createProjectileMessage.getSyncStampLong()); - } - } - } - } - break; - } - - //---------------------------------------------------------------------- - - case constcrc("CmdSceneReady") : - { - m_isReady = true; - primaryControlledObject->onClientReady(this); - break; - } - - //---------------------------------------------------------------------- - - case constcrc("SetCombatSpamFilter") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const msg(ri); - m_combatSpamFilter = static_cast(msg.getValue()); - break; - } - - //---------------------------------------------------------------------- - - case constcrc("SetCombatSpamRangeFilter") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const msg(ri); - m_combatSpamRangeSquaredFilter = sqr(msg.getValue()); - break; - } - - //---------------------------------------------------------------------- - - case constcrc("SetFurnitureRotationDegree") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const msg(ri); - m_furnitureRotationDegree = msg.getValue(); - break; - } - - //---------------------------------------------------------------------- - - case constcrc("GcwRegionsReq") : - { - GenericValueTypeMessage, float> > > > const rsp("GcwRegionsRsp", Pvp::getGcwScoreCategoryRegions()); - send(rsp, true); - - GenericValueTypeMessage > > const rsp2("GcwGroupsRsp", Pvp::getGcwScoreCategoryGroups()); - send(rsp2, true); - break; - } - - //---------------------------------------------------------------------- - - case constcrc("SetJediSlotInfo") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const msg(ri); - - // this comes from the client (via the LoginServer) so should not be trusted; - // we cache them here to do preliminary checks to avoid unnecessarily sending - // commands to the LoginServer (assuming the values haven't been hacked on the - // client); when we do send the commands to the LoginServer, we'll check again there - m_hasUnoccupiedJediSlot = msg.getValue().first; - m_isJediSlotCharacter = msg.getValue().second; - break; - } - - //---------------------------------------------------------------------- - - case constcrc("RotateFurnitureSetQuaternion") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage, std::pair > > > const msg(ri); - - CreatureObject * creatureOwner = safe_cast(getCharacterObject()); - if (creatureOwner && creatureOwner->isAuthoritative()) - { - ServerObject const * target = ServerWorld::findObjectByNetworkId(msg.getValue().first); - if (target && target->isAuthoritative()) - { - static uint32 const commandHash = Crc::normalizeAndCalculate("rotateFurniture"); - const Command &command = CommandTable::getCommand(commandHash); - if (!command.isNull()) - { - // for obfuscation so players won't manually send us this command - Unicode::String params = Unicode::narrowToWide(FormattedString<512>().sprintf("(^-,=+_)internal_use_only_%s_quaternion(,+-=_^) %.10f %.10f %.10f %.10f %s", creatureOwner->getNetworkId().getValueString().c_str(), msg.getValue().second.first.first, msg.getValue().second.first.second, msg.getValue().second.second.first, msg.getValue().second.second.second, msg.getValue().first.getValueString().c_str())); - creatureOwner->commandQueueEnqueue(command, target->getNetworkId(), params, 0, false, static_cast(Command::CP_Default), true); - } - } - } - break; - } - - //---------------------------------------------------------------------- - - case constcrc("SetLfgInterests") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const msg(ri); - - PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(safe_cast(getCharacterObject())); - if (playerObject) - { - std::map const & connectedCharacterLfgData = ServerUniverse::getConnectedCharacterLfgData(); - std::map::const_iterator iterFind = connectedCharacterLfgData.find(getCharacterObjectId()); - if (iterFind != connectedCharacterLfgData.end()) - { - BitArray lfgInterests = msg.getValue(); - - MatchMakingId const & id = playerObject->getMatchMakingCharacterProfileId(); - if (id.isBitSet(MatchMakingId::B_lookingForGroup)) - LfgDataTable::setBit("lfg", lfgInterests); - else - LfgDataTable::clearBit("lfg", lfgInterests); - - if (id.isBitSet(MatchMakingId::B_helper)) - LfgDataTable::setBit("helper", lfgInterests); - else - LfgDataTable::clearBit("helper", lfgInterests); - - if (id.isBitSet(MatchMakingId::B_rolePlay)) - LfgDataTable::setBit("rp", lfgInterests); - else - LfgDataTable::clearBit("rp", lfgInterests); - - if (id.isBitSet(MatchMakingId::B_lookingForWork)) - LfgDataTable::setBit("lfw", lfgInterests); - else - LfgDataTable::clearBit("lfw", lfgInterests); - - ServerUniverse::setConnectedCharacterInterestsData(getCharacterObjectId(), lfgInterests); - } - } - break; - } - - //---------------------------------------------------------------------- - - case constcrc("RequestGroundObjectPlacement") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage, std::pair > > > const msg(ri); - - ServerObject * const target = safe_cast(NetworkIdManager::getObjectById (msg.getValue().first)); - GameScriptObject * const scriptObject = target ? target->getScriptObject() : 0; - - if (!scriptObject) - { - return; - } - - int menuType = msg.getValue().second.first.first; - Vector loc(msg.getValue().second.first.second, msg.getValue().second.second.first, msg.getValue().second.second.second); - ScriptParams params; - params.addParam (getCharacterObjectId()); - params.addParam (menuType); - params.addParam (loc.x); - params.addParam (loc.y); - params.addParam (loc.z); - - IGNORE_RETURN (scriptObject->trigAllScripts(Scripting::TRIG_GROUND_TARGET_LOC, params)); - break; - } - //---------------------------------------------------------------------- - - case constcrc("ShowBackpack") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const msg(ri); - PlayerObject * player = dynamic_cast(NetworkIdManager::getObjectById (msg.getValue().first)); - - if(player) - player->modifyShowBackpack(msg.getValue().second); - - break; - } - //---------------------------------------------------------------------- - - case constcrc("ShowHelmet") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const msg(ri); - PlayerObject * player = dynamic_cast(NetworkIdManager::getObjectById (msg.getValue().first)); - - if(player) - player->modifyShowHelmet(msg.getValue().second); - - break; - } - //---------------------------------------------------------------------- - - case constcrc("SetWaypointColor") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const msg(ri); - - if ((msg.getValue().second == "blue") || (msg.getValue().second == "green") || (msg.getValue().second == "orange") || (msg.getValue().second == "yellow") || (msg.getValue().second == "purple") || (msg.getValue().second == "white")) - { - Waypoint w = Waypoint::getWaypointById(msg.getValue().first); - if (w.isValid()) - { - w.setColor(Waypoint::getColorIdByName(msg.getValue().second)); - } - } - - break; - } - - //---------------------------------------------------------------------- - - case constcrc("ConGenericMessage") : - { - - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ConGenericMessage c(ri); - if (isGod()) - { - LOG("CustomerService",("Avatar:%s executing command: %s", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), c.getMsg().c_str())); - ConsoleMgr::processString(c.getMsg(), this, c.getMsgId()); - } - else - { - //Non-god user tried to use a console command - if (m_primaryControlledObject.getObject()) - { - LOG("CustomerService", ("CheatChannel:%s tried to execute a console command but they are not a god", - PlayerObject::getAccountDescription(m_primaryControlledObject.getObject()->getNetworkId()).c_str())); - ConsoleMgr::broadcastString("Only god users can execute console commands.", this, c.getMsgId()); - } - - } - break; - } - - //----------------------------------------------------------------- - - case constcrc("ObjControllerMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ObjControllerMessage o(ri); - bool appended = false; - - // check to make sure the controller message is allowed from the client - bool allowFromClient = ControllerMessageFactory::allowFromClient(o.getMessage()); - - // we default this to true so that unless - // a controller message is explicitly marked as being allowed - // from the client, or the client is a GM, it will be dropped when the game server - // receives it; this will have the effect of forcing the - // programmer to make a conscious decision to mark the - // controller message as allowable from the client; because - // controller message coming from the client is not secured, - // the mechanism to prevent a hacked client from sending the - // game server any controller message is to explicity "mark" - // those controller messages that are allowed from the client - - if (allowFromClient || isGod()) - { - ServerObject * target = findControlledObject(o.getNetworkId()); - if(target !=0) - { - // apply the controller message - ServerController * controller = dynamic_cast(target->getController()); - if (controller != nullptr) - { - uint32 flags = o.getFlags(); - flags &= ~GameControllerMessageFlags::SOURCE_REMOTE; - flags |= GameControllerMessageFlags::SOURCE_REMOTE_CLIENT; - controller->appendMessage(o.getMessage(), o.getValue(), o.getData(), flags); - appended = true; - } - } - else if (isGod()) - { - target = ServerWorld::findObjectByNetworkId(o.getNetworkId()); - - if (target) - { - ServerController * controller = dynamic_cast(target->getController()); - if (controller != nullptr) - { - uint32 flags = o.getFlags(); - flags &= ~GameControllerMessageFlags::SOURCE_REMOTE; - flags |= GameControllerMessageFlags::SOURCE_REMOTE_CLIENT; - controller->appendMessage(o.getMessage(), o.getValue(), o.getData(), flags); - appended = true; - } - } - } - } else { - // log as a likely hack - LOG("CustomerService", ("UnauthorizedControllerMessage: Player %s sent an unauthorized controller message %d for object %s.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), o.getMessage(), o.getNetworkId().getValueString().c_str())); - } - - if (!appended) { - delete o.getData(); - } - - break; - } - - //----------------------------------------------------------------- - //Secure Trade Messages - //----------------------------------------------------------------- - case constcrc("AddItemMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - AddItemMessage m(ri); - - - ServerObject * item = ServerWorld::findObjectByNetworkId(m.getNetworkId()); - if (!item) - return; - - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->addItem(*playerObject, *item); - } - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - case constcrc("RemoveItemMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - RemoveItemMessage m(ri); - - ServerObject * item = ServerWorld::findObjectByNetworkId(m.getNetworkId()); - if (!item) - return; - - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->removeItem(*playerObject, *item); - } - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - case constcrc("GiveMoneyMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GiveMoneyMessage m(ri); - - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->giveMoney(*playerObject, m.getAmount()); - } - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - case constcrc("AcceptTransactionMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - AcceptTransactionMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->acceptOffer(*playerObject); - } - - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has accepted a secure trade. (Check trade logs for more detail.", PlayerObject::getAccountDescription(playerObject).c_str())); - } - - - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - case constcrc("UnAcceptTransactionMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - UnAcceptTransactionMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->unacceptOffer(*playerObject); - } - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - case constcrc("VerifyTradeMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - VerifyTradeMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->verifyTrade(*playerObject); - } - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - case constcrc("DenyTradeMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - DenyTradeMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->rejectOffer(*playerObject); - } - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - case constcrc("AbortTradeMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - AbortTradeMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - DEBUG_FATAL(!playerObject, ("No controller for player!\n")); - if(playerObject) //lint !e774 - { - PlayerCreatureController* playerController = dynamic_cast(playerObject->getController()); - if (playerController && playerController->getSecureTrade()) - { - playerController->getSecureTrade()->cancelTrade(*playerObject); - } - } - else - { - GameServer::getInstance().dropClient(m_characterObjectId); - } - break; - } - - case constcrc("GuildRequestMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GuildRequestMessage const m(ri); - - NetworkId const &id = m.getTargetId(); - CreatureObject * const creatureObject = dynamic_cast(NetworkIdManager::getObjectById(id)); - if (creatureObject) - { - int const guildId = creatureObject->getGuildId(); - GuildMemberInfo const * const info = GuildInterface::getGuildMemberInfo(guildId, id); - GuildResponseMessage const responseMessage(id, GuildInterface::getGuildName(guildId), info ? info->m_title : std::string()); - send(responseMessage, true); - } - break; - } - - case constcrc("StomachRequestMessage") : - { - CreatureObject *creatureObject = dynamic_cast(getCharacterObject()); - - if (creatureObject != nullptr) - { - GameScriptObject *gameScriptObject = creatureObject->getScriptObject(); - - if(gameScriptObject != nullptr) - { - ScriptParams scriptParams; - IGNORE_RETURN(gameScriptObject->trigAllScripts(Scripting::TRIG_STOMACH_UPDATE, scriptParams)); - } - } - break; - } - - case constcrc("FactionRequestMessage") : - { - int rebel = 0; - int imperial = 0; - int criminal = 0; - - CreatureObject * playerObject = dynamic_cast(getCharacterObject()); - if (playerObject) - { - float temp; - if (playerObject->getObjVars().getItem("faction.Rebel",temp)) - { - rebel = static_cast(temp); - } - if (playerObject->getObjVars().getItem("faction.Imperial",temp)) - { - imperial = static_cast(temp); - } - if (playerObject->getObjVars().getItem("faction.Hutt",temp)) - { - criminal = static_cast(temp); - } - - std::vector factionNames; - std::vector factionValues; - std::string currentName; - float currentValue; - DynamicVariableList::NestedList factionList(playerObject->getObjVars(),"faction"); - for(DynamicVariableList::NestedList::const_iterator i = factionList.begin(); i != factionList.end(); ++i) - { - currentName = i.getName(); - bool result = i.getValue(currentValue); - if(result) - { - factionNames.push_back(currentName); - factionValues.push_back(currentValue); - } - } - - FactionResponseMessage const msg(rebel, imperial, criminal, factionNames, factionValues); - send(msg, true); - } - break; - } - - //----------------------------------------------------------------- - - case constcrc("AcceptAuctionMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - AcceptAuctionMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - CommoditiesMarket::auctionAccept(*playerObject, m.getItemId().getValue()); - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has accepted an auction for item %s", - PlayerObject::getAccountDescription(playerObject).c_str(), - m.getItemId().getValueString().c_str())); - } - } - else - { - WARNING(true, ("AcceptAuctionMessage: the player was not found")); - } - break; - } - - case constcrc("BidAuctionMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - BidAuctionMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has bid on an auction for item %s, amount %d", - PlayerObject::getAccountDescription(playerObject).c_str(), - m.getItemId().getValueString().c_str(), - m.getBid())); - } - - CommoditiesMarket::auctionBid(*playerObject, m.getItemId().getValue(), m.getBid(), m.getMaxProxyBid()); - } - else - { - WARNING(true, ("BidAuctionMessage: the player was not found")); - } - break; - } - - case constcrc("CancelLiveAuctionMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - CancelLiveAuctionMessage m(ri); - - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - CommoditiesMarket::auctionCancel(*playerObject, m.getItemId().getValue()); - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has cancelled an auction for item %s", - PlayerObject::getAccountDescription(playerObject).c_str(), - m.getItemId().getValueString().c_str())); - } - - } - else - { - WARNING(true, ("CancelLiveAuctionMessage: the player was not found")); - } - break; - } - - case constcrc("CreateAuctionMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - CreateAuctionMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - NetworkId itemId = m.getItemId(); - NetworkId containerId = m.getContainerId(); - CommoditiesMarket::auctionCreate(*playerObject, itemId, m.getItemLocalizedName(), containerId, m.getMinimumBid(), m.getAuctionLength(), m.getUserDescription(), m.isPremium()); - - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has created an auction for item %s on vendor %s", - PlayerObject::getAccountDescription(playerObject).c_str(), - m.getItemId().getValueString().c_str(), - containerId.getValueString().c_str())); - } - } - else - { - WARNING(true, ("CreateAuctionMessage: the player was not found")); - } - break; - } - - case constcrc("CreateImmediateAuctionMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - CreateImmediateAuctionMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - NetworkId itemId = m.getItemId(); - NetworkId containerId = m.getContainerId(); - if (m.isVendorTransfer()) - { - CommoditiesMarket::transferVendorItemFromStockroom(*playerObject, itemId, m.getItemLocalizedName(), m.getPrice(), m.getAuctionLength(), m.getUserDescription()); - } - else - { - CommoditiesMarket::auctionCreateImmediate(*playerObject, itemId, m.getItemLocalizedName(), containerId, m.getPrice(), m.getAuctionLength(), m.getUserDescription(), m.isPremium()); - } - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has created an immediate auction for item %s on vendor %s", - PlayerObject::getAccountDescription(playerObject).c_str(), - m.getItemId().getValueString().c_str(), - containerId.getValueString().c_str())); - } - } - else - { - WARNING(true, ("CreateImmediateAuctionMessage: the player was not found")); - } - break; - } - - case constcrc("RelistItemsFromStockMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage, std::vector >, int> > const m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - std::vector const & itemIds = m.getValue().first.first; - std::vector const & itemLocalizedNames = m.getValue().first.second; - int const timer = m.getValue().second; - NetworkId itemId; - std::vector::const_iterator iterId = itemIds.begin(); - std::vector::const_iterator iterName = itemLocalizedNames.begin(); - for (; ((iterId != itemIds.end()) && (iterName != itemLocalizedNames.end())); ++iterId, ++iterName) - { - itemId = *iterId; - CommoditiesMarket::transferVendorItemFromStockroom(*playerObject, itemId, *iterName, -1, timer, Unicode::String()); - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has created an immediate auction (relist) for item %s", - PlayerObject::getAccountDescription(playerObject).c_str(), - itemId.getValueString().c_str())); - } - } - } - else - { - WARNING(true, ("RelistItemsFromStockMessage: the player was not found")); - } - break; - } - - case constcrc("RetrieveAuctionItemMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - RetrieveAuctionItemMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - NetworkId itemId = m.getItemId(); - ServerObject *auctionContainer = dynamic_cast(NetworkIdManager::getObjectById(m.getContainerId())); - if (auctionContainer) - { - if (playerObject->isAuthoritative() && auctionContainer->isAuthoritative()) - { - CommoditiesMarket::auctionRetrieve(*playerObject, m.getItemId().getValue(), m.getItemId(), *auctionContainer); - if (playerObject->getObjVars().hasItem("cheater")) - { - LOG("CustomerService", ("SuspectedCheaterChannel: %s has retrieved an auction for item %s on vendor %s", - PlayerObject::getAccountDescription(playerObject).c_str(), - m.getItemId().getValueString().c_str(), - auctionContainer->getNetworkId().getValueString().c_str())); - } - } - } - else - { - LOG("CustomerService", ("Auction:Player %s attempted to retrieve an auction for container %Ld but failed.", PlayerObject::getAccountDescription(playerObject).c_str(), m.getContainerId().getValue())); - - RetrieveAuctionItemResponseMessage const msg(itemId, ar_INVALID_CONTAINER_ID);; - Client *client = playerObject->getClient(); - if (client) - { - client->send(msg, true); - } - } - } - else - { - WARNING(true, ("RetrieveAuctionMessage: the player was not found")); - } - break; - } - case constcrc("AuctionQueryHeadersMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - AuctionQueryHeadersMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - CommoditiesMarket::auctionQueryHeaders(*playerObject, - m.getRequestId(), - m.getSearchType(), - m.getItemType(), - m.getItemTypeExactMatch(), - m.getItemTemplateId(), - m.getTextFilterAll(), - m.getTextFilterAny(), - m.getPriceFilterMin(), - m.getPriceFilterMax(), - m.getPriceFilterIncludesFee(), - m.getAdvancedSearch(), - m.getAdvancedSearchMatchAllAny(), - m.getContainer(), - m.getLocationSearchType(), - m.getMyVendorsOnly(), - m.getQueryOffset()); - } - break; - } - case constcrc("GetAuctionDetails") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GetAuctionDetails m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - CommoditiesMarket::getAuctionDetails(*playerObject, - m.getItem()); - } - break; - } - case constcrc("IsVendorOwnerMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - IsVendorOwnerMessage m(ri); - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - CommoditiesMarket::isVendorOwner(*playerObject, m.getContainerId()); - } - break; - } - case constcrc("CommoditiesItemTypeListRequest") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const m(ri); - - static char buffer[128]; - snprintf(buffer, sizeof(buffer)-1, "%s.%d", GameServer::getInstance().getClusterName().c_str(), CommoditiesMarket::getItemTypeMapVersionNumber()); - buffer[sizeof(buffer)-1] = '\0'; - - if (m.getValue() != std::string(buffer)) - { - GenericValueTypeMessage > > > > const rsp("CommoditiesItemTypeListResponse", std::make_pair(std::string(buffer), CommoditiesMarket::getItemTypeMap())); - send(rsp, true); - } - break; - } - case constcrc("CommoditiesResourceTypeListRequest") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const m(ri); - - static char buffer[128]; - snprintf(buffer, sizeof(buffer)-1, "%s.%d", GameServer::getInstance().getClusterName().c_str(), CommoditiesMarket::getResourceTypeMapVersionNumber()); - buffer[sizeof(buffer)-1] = '\0'; - - if (m.getValue() != std::string(buffer)) - { - GenericValueTypeMessage > > > const rsp("CommoditiesResourceTypeListResponse", std::make_pair(std::string(buffer), CommoditiesMarket::getResourceTypeMap())); - send(rsp, true); - } - break; - } - case constcrc("CollectionServerFirstListRequest") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage const m(ri); - - PlanetObject const * const planetObject = ServerUniverse::getInstance().getTatooinePlanet(); - if (planetObject) - { - static char buffer[128]; - snprintf(buffer, sizeof(buffer)-1, "%s.%d", GameServer::getInstance().getClusterName().c_str(), planetObject->getCollectionServerFirstUpdateNumber()); - buffer[sizeof(buffer)-1] = '\0'; - - if (m.getValue() != std::string(buffer)) - { - GenericValueTypeMessage, std::pair > > > > const rsp("CollectionServerFirstListResponse", std::make_pair(std::string(buffer), planetObject->getCollectionServerFirst())); - send(rsp, true); - } - } - break; - } - - //----------------------------------------------------------------- - - case constcrc("AddMapLocationMessage") : - { - Archive::ReadIterator readIterator = static_cast (message).getByteStream ().begin (); - const AddMapLocationMessage msg (readIterator); - UNREF (msg); - - /* - MapLocation mapLocation(msg.getLocationId(), msg.getLocationName(), - Vector2d(msg.getLocationX(), msg.getLocationY()), - msg.getCategory(), msg.getSubCategory()); - - PlanetObject *planetObject = ServerUniverse::getInstance ().getPlanetByName (msg.getPlanetName ()); - if (planetObject) - { - planetObject->addMapLocation(mapLocation); - } - AddMapLocationResponseMessage responseMsg(msg.getLocationId()); - send(responseMsg, true); - */ - break; - } - - case constcrc("GetSpecificMapLocationsMessage") : - { - Archive::ReadIterator readIterator = static_cast (message).getByteStream ().begin (); - const GenericValueTypeMessage > > msg (readIterator); - - PlanetMapManagerServer::handleClientRequestGetSpecificMapLocationsMessage (*this, msg.getValue()); - break; - } - - case constcrc("ConsentResponseMessage") : - { - Archive::ReadIterator readIterator = static_cast (message).getByteStream ().begin (); - ConsentResponseMessage const msg(readIterator); - ConsentManager::getInstance().handleResponse(msg); - break; - } - - case constcrc("RequestGalaxyLoopTimes") : - { - // obfuscate the information so it's not obvious on the client that this is the server loop time - unsigned long loopTime = static_cast(Clock::frameTime() * 3193000.0f); // loop time (in ms) * 3193 - GalaxyLoopTimesResponse const msg(loopTime, loopTime); - send(msg, true); - break; - } - case constcrc("LagRequest") : - { - GameNetworkMessage const msg("GameServerLagResponse"); - send(msg, true); - break; - } - case constcrc("LagReport") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - GenericValueTypeMessage > const report(ri); - m_connectionServerLag = report.getValue().first; - m_gameServerLag = report.getValue().second; - break; - } - case constcrc("ChatInviteGroupToRoom") : - { - if (primaryControlledObject) - { - CreatureObject * const playerCreature = primaryControlledObject->asCreatureObject(); - if (playerCreature) - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ChatInviteGroupToRoom const chat(ri); - - // We will need to notify the user if the group leader can not be found - bool foundGroupLeader = false; - - // Get the name of the group leader being invited - ChatAvatarId const & groupLeaderChatAvatarId = chat.getAvatarId(); - - // Convert the name to a network ID - NetworkId const groupLeaderNetworkId = NameManager::getInstance().getPlayerId(NameManager::normalizeName(Unicode::wideToNarrow(groupLeaderChatAvatarId.getName()))); - - // Try to get a group object corresponding to the player network ID - ServerObject const * const groupServerObject = ServerWorld::findObjectByNetworkId(GroupObject::getGroupIdForLeader(groupLeaderNetworkId)); - if (groupServerObject && groupServerObject->asGroupObject()) - { - // We now know the player is a group leader of a group - GroupObject const * const groupLeaderGroupObject = groupServerObject->asGroupObject(); - - // Make sure we have the correct player since we only searched by name - // (i.e. we may have been looking for a player with the same name but on a different cluster) - ChatAvatarId const playerChatAvatarId = Chat::constructChatAvatarId(NameManager::normalizeName(groupLeaderGroupObject->getGroupLeaderName())); - if (playerChatAvatarId == groupLeaderChatAvatarId) - { - // We found the group leader - foundGroupLeader = true; - - // We need to get the network IDs for all the group members - std::vector groupNetworkIds; - - GroupObject::GroupMemberVector const & groupMemberVector = groupLeaderGroupObject->getGroupMembers(); - for (unsigned i = 0; i < groupMemberVector.size(); ++i) - { - GroupObject::GroupMember const & groupMember = groupMemberVector[i]; - - groupNetworkIds.push_back(groupMember.first); - } - - // Pass the invitation to all the group members - Chat::inviteGroupMembers(m_primaryControlledObject, chat.getAvatarId(), chat.getRoomName(), groupNetworkIds); - } - } - - // If we couldn't find the group leader, let the player know - if (!foundGroupLeader) - { - ChatAvatarId const inviteeId = Chat::constructChatAvatarId(*playerCreature); - ChatOnInviteGroupToRoom msg(ERR_DESTAVATARDOESNTEXIST, chat.getRoomName(), inviteeId, chat.getAvatarId()); - send(msg, false); - } - } - } - break; - } - case constcrc("ChatPersistentMessageToServer") : - { - if (primaryControlledObject) //lint !e774 - { - CreatureObject * const playerCreature = primaryControlledObject->asCreatureObject(); - if (playerCreature) - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ChatPersistentMessageToServer const chat(ri); - std::string const &toName = chat.getToCharacterName().name; - if (!_stricmp(toName.c_str(), "guild")) - { - std::pair > const count = GuildInterface::mailToGuild(*playerCreature, chat.getSubject(), chat.getMessage(), chat.getOutOfBand()); - if (count.first < 0) - { - Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide("You do not have sufficient permission to send mail to guild members."), Unicode::emptyString); - } - else - { - Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("Your mail was sent to %d members of guild %s (%s).", count.first, count.second.first.c_str(), count.second.second.c_str())), Unicode::emptyString); - } - } - else if (!_strnicmp(toName.c_str(), "guild ", 6)) - { - // see if it's a valid guild rank - GuildRankDataTable::GuildRank const * guildRank = GuildRankDataTable::getRankForDisplayRankName(toName); - if (guildRank) - { - std::pair > const count = GuildInterface::mailToGuildRank(*playerCreature, guildRank->slotId, chat.getSubject(), chat.getMessage(), chat.getOutOfBand()); - if (count.first < 0) - { - Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide("You do not have sufficient permission to send mail to guild members."), Unicode::emptyString); - } - else - { - Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("Your mail was sent to %d members in rank %s of guild %s (%s).", count.first, guildRank->displayName.c_str(), count.second.first.c_str(), count.second.second.c_str())), Unicode::emptyString); - } - } - else - { - Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("\"%s\" is not a valid name.", toName.c_str())), Unicode::emptyString); - } - } - else if (!_stricmp(toName.c_str(), "citizens")) - { - std::pair const count = CityInterface::mailToCitizens(*playerCreature, chat.getSubject(), chat.getMessage(), chat.getOutOfBand()); - if (count.first < 0) - { - Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide("You do not have sufficient permission to send mail to citizens."), Unicode::emptyString); - } - else - { - Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("Your mail was sent to %d citizens of city %s.", count.first, count.second.c_str())), Unicode::emptyString); - } - } - - if (playerCreature->getObjVars().hasItem("cheater")) - { - LOGU("CustomerService", ("SuspectedCheaterChannel: %s is broadcasting a %s message that says '%s'", - PlayerObject::getAccountDescription(playerCreature).c_str(), - toName.c_str()), - chat.getMessage()); - } - } - } - break; - } - case constcrc("ExpertiseRequestMessage") : - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - ExpertiseRequestMessage const m(ri); - - std::vector const & addExpertisesNamesList = m.getAddExpertisesList(); - bool clearAllExpertisesFirst = m.getClearAllExpertisesFirst(); - std::string addList; - std::vector::const_iterator i; - for(i = addExpertisesNamesList.begin(); i != addExpertisesNamesList.end(); ++i) - { - addList += " "; - addList += *i; - } - CreatureObject * playerObject = safe_cast(getCharacterObject()); - if (playerObject) - { - LOG("CustomerService", ("ExpertiseRequestMessage: %s has requested to add expertises [%s] %s", - PlayerObject::getAccountDescription(playerObject).c_str(), - addList.c_str(), clearAllExpertisesFirst ? "(clearing first)" : "")); - playerObject->processExpertiseRequest(addExpertisesNamesList, clearAllExpertisesFirst); - } - break; - } - case constcrc("UpdateSessionPlayTimeInfo") : - { - Archive::ReadIterator readIterator = static_cast (message).getByteStream ().begin (); - GenericValueTypeMessage > > const msgPlayTimeInfo(readIterator); - - PlayerObject * playerObject = PlayerCreatureController::getPlayerObject(safe_cast(getCharacterObject())); - if (playerObject != nullptr) - { - playerObject->setSessionPlayTimeInfo(msgPlayTimeInfo.getValue().first, msgPlayTimeInfo.getValue().second.first, msgPlayTimeInfo.getValue().second.second); - } - break; - } - default : - { - // am too lazy to convert these to constexpr's - if (message.isType(ObjectMenuSelectMessage::MESSAGE_TYPE)) - { - Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); - const ObjectMenuSelectMessage m (ri); - ServerObject * const target = safe_cast(NetworkIdManager::getObjectById (m.getNetworkId())); - GameScriptObject * const scriptObject = target ? target->getScriptObject() : 0; - Object * const targetContainedBy = target ? ContainerInterface::getContainedByObject(*target) : nullptr; - const int menuType = m.getSelectedItemId(); - - static int examineMenuType = RadialMenuManager::getMenuTypeByName("EXAMINE"); - static int tradeMenuType = RadialMenuManager::getMenuTypeByName("TRADE_START"); - - CreatureObject* cobj = dynamic_cast(primaryControlledObject); - if (cobj && menuType != examineMenuType && menuType != tradeMenuType) - { - CreatureController* const controller = cobj->getCreatureController(); - if (controller && controller->getSecureTrade()) - { - controller->getSecureTrade()->cancelTrade(*cobj); - DEBUG_REPORT_LOG (true, ("Client ObjectMenuSelectMessage [%d] for [%s] canceling trade.\n", menuType, cobj->getNetworkId ().getValueString ().c_str ())); - } - } - - if (!scriptObject) - { - DEBUG_REPORT_LOG (true, ("Received an object menu select message from player %s for object %s, which does not exist or lacks a GameScriptObject.", m_characterObjectId.getValueString().c_str(),m.getNetworkId().getValueString().c_str())); - return; - } - - NOT_NULL(target); - - float range = 0.0f; - if (RadialMenuManager::getRangeForMenuType(menuType, range)) - { - Container::ContainerErrorCode errorCode = Container::CEC_Success; - if (!target->isAuthoritative()) - { - GenericValueTypeMessage > const rssMessage( - "RequestSameServer", - std::make_pair( - ContainerInterface::getTopmostContainer(*primaryControlledObject)->getNetworkId(), - ContainerInterface::getTopmostContainer(*target)->getNetworkId())); - GameServer::getInstance().sendToPlanetServer(rssMessage); - errorCode = Container::CEC_TryAgain; - } - else if (menuType != examineMenuType && targetContainedBy && targetContainedBy->asServerObject() && ( targetContainedBy->asServerObject()->getGameObjectType() == SharedObjectTemplate::GOT_chronicles_quest_holocron || targetContainedBy->asServerObject()->getGameObjectType() == SharedObjectTemplate::GOT_chronicles_quest_holocron_recipe ) ) - { - // Can only examine items that are contained in a holocron. - errorCode = Container::CEC_NoPermission; - } - else if (primaryControlledObject->canManipulateObject(*target, false, false, false, range, errorCode) - || ClientNamespace::canManipulateObjectExceptionCheck(*target, menuType, errorCode)) - { - ScriptParams params; - params.addParam (getCharacterObjectId()); - params.addParam (menuType); - - if (cobj && cobj->getObjVars().hasItem("cheater")) - { - std::string menuDesc = "unknown"; - bool tmp; - IGNORE_RETURN(RadialMenuManager::getCommandForMenuType(menuType, menuDesc, tmp)); - LOG("CustomerService",("SuspectedCheaterLog: %s has used a radial menu on object %s. Menu item %d (%s).", - PlayerObject::getAccountDescription(cobj).c_str(), - m.getNetworkId().getValueString().c_str(), - menuType, - menuDesc.c_str() )); - } - - IGNORE_RETURN (scriptObject->trigAllScripts(Scripting::TRIG_OBJECT_MENU_SELECT, params)); - } - if (errorCode != Container::CEC_Success) - ContainerInterface::sendContainerMessageToClient(*primaryControlledObject, errorCode); - } - else - { - DEBUG_REPORT_LOG(true, ("Received a message type %d that had no range in data (radial_menu.tab)\n", menuType)); - } - } else if (message.isType(SuiEventNotification::MessageType)) - { - ServerUIManager::receiveMessage(message); - } else if (message.isType(PlayerMoneyRequest::MessageType)) - { - Archive::ReadIterator ri = (*NON_NULL (static_cast(&message))).getByteStream().begin(); - const PlayerMoneyRequest m (ri); - - ServerObject * const playerObject = getCharacterObject(); - - WARNING (!playerObject, ("Got PlayerMoneyRequest for non-existant character (account=%s, networkid=%s)", m_accountName.c_str (), m_characterObjectId.getValueString ().c_str ())); - - if (playerObject) - { - PlayerMoneyResponse resp; - resp.m_balanceCash.set (playerObject->getCashBalance ()); - resp.m_balanceBank.set (playerObject->getBankBalance ()); - send (resp, true); - } - } else if (message.isType(PlanetTravelPointListRequest::cms_name)) - { - Archive::ReadIterator readIterator = static_cast (message).getByteStream ().begin (); - const PlanetTravelPointListRequest requestMessage (readIterator); - - const std::string & planetName = requestMessage.getPlanetName (); - const PlanetObject* const planetObject = ServerUniverse::getInstance ().getPlanetByName (requestMessage.getPlanetName ()); - if (planetObject) - { - std::vector names; - planetObject->getTravelPointNameList (names); - - std::vector points; - planetObject->getTravelPointPointList (points); - - std::vector costs; - planetObject->getTravelPointCostList (costs); - - std::vector interplanetary; - planetObject->getTravelPointInterplanetaryList (interplanetary); - - PlanetTravelPointListResponse const rsp(planetName, names, points, costs, interplanetary, requestMessage.getSequenceId ()); - send(rsp, true); - } - else - DEBUG_WARNING (true, ("GameServer::receiveMessage: received request for travel point names from client [%s] for planet %s which does not exist", requestMessage.getPlanetName ().c_str (), requestMessage.getNetworkId ().getValueString ().c_str ())); - - } else if (message.isType(NewbieTutorialResponse::cms_name)) - { - Archive::ReadIterator readIterator = static_cast (message).getByteStream ().begin (); - const NewbieTutorialResponse responseMessage (readIterator); - - static const std::string clientReadyString("clientReady"); - - if (responseMessage.getResponse() == clientReadyString) - { - for (std::vector::iterator i = m_controlledObjects.begin(); i != m_controlledObjects.end(); ++i) - { - ServerObject * const so = *i; - if (so) - so->onLoadingScreenComplete(); - } - } - - ScriptParams scriptParameters; - scriptParameters.addParam (responseMessage.getResponse ().c_str ()); - - if (primaryControlledObject->getScriptObject ()->trigAllScripts (Scripting::TRIG_NEWBIE_TUTORIAL_RESPONSE, scriptParameters) != SCRIPT_CONTINUE) - DEBUG_REPORT_LOG (true, ("OnNewbieTutorialResponse: did not return SCRIPT_CONTINUE\n")); - - } else if (message.isType(GetMapLocationsMessage::MessageType)) - { - Archive::ReadIterator readIterator = static_cast (message).getByteStream ().begin (); - const GetMapLocationsMessage msg (readIterator); - - PlanetMapManagerServer::handleClientRequest (*this, msg); - } - break; - } - } - } - catch (Archive::ReadException &) - { - if (getCharacterObject()) - { - WARNING_STRICT_FATAL(true, ("A message was received from a client that could not be unpacked. Either the data was corrupt (intentionally or accidentally) or the client and server notion of the message are out of sync. The client will be disconnected. Character object is : %s :%s, IP=%s, accountname=%s", getCharacterObject()->getObjectTemplateName(), getCharacterObject()->getNetworkId().getValueString().c_str(), getIpAddress().c_str(), getAccountName().c_str())); - } - else - { - WARNING_STRICT_FATAL(true, ("A message was received from a client that could not be unpacked. Either the data was corrupt (intentionally or accidentally) or the client and server notion of the message are out of sync. The client will be disconnected. IP=%s, accountname=%s", getIpAddress().c_str(), getAccountName().c_str())); - } - if (getConnection()) - { - KickPlayer const kickMessage(m_characterObjectId, "Invalid Network Stream"); - GameServer::getInstance().sendToConnectionServers(kickMessage); - GameServer::getInstance().dropClient(m_characterObjectId); - } - } - - //----------------------------------------------------------------- -} - -//----------------------------------------------------------------------- - -void Client::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) -{ - UNREF(source); - - const uint32 messageType = message.getType(); - - if ( messageType == constcrc("ConnectionServerConnectionClosed") - || messageType == constcrc("ConnectionServerConnectionDestroyed")) - { - //Connection server crashed - DEBUG_REPORT_LOG(true, ("Connection Server crashed. Client dropping.\n")); - m_connection = 0; - GameServer::getInstance().dropClient(m_characterObjectId); - } - else - { - if(&source != m_connection) - { - const MessageDispatch::Message * m = dynamic_cast *>(&message); - if(m) - { - ConGenericMessage const c(m->getValue(), 0); - send(c, true); - } - } - } -} - -//----------------------------------------------------------------------- - -void Client::removeControlledObject(ServerObject &object) -{ - if (m_primaryControlledObject == object.getNetworkId()) - { - ObserveTracker::onClientDestroyed(*this); - if (ServerWorld::isSpaceScene()) - SpaceVisibilityManager::removeClient(*this); - } - - std::vector::iterator iter = std::find(m_controlledObjects.begin(), m_controlledObjects.end(), &object); - if (iter != m_controlledObjects.end()) - IGNORE_RETURN(m_controlledObjects.erase(iter)); - else - DEBUG_WARNING(true, ("Client removing object [%s] that is not controlled", object.getNetworkId().getValueString().c_str())); - - object.clearClient(); -} - -//----------------------------------------------------------------------- - -void Client::selfDestruct() -{ - selfDestruct(false); -} -//----------------------------------------------------------------------- - -void Client::selfDestruct(const bool immediate) -{ - // @todo : this will eventually need to attach ai controllers to - // link dead objects. - std::vector controlledObjects = m_controlledObjects; - - // the controlled object list on the client is affected by clearClient, so work on a copy of the vector - for (std::vector::iterator i = controlledObjects.begin(); i != controlledObjects.end(); ++i) - { - if (*i) - { - if ((*i)->isAuthoritative()) - { - (*i)->handleDisconnect(immediate); - } - (*i)->clearClient(); - } - } - m_controlledObjects.clear(); - delete this; -} - -//----------------------------------------------------------------------- - -void Client::send(GameNetworkMessage const &outgoingMessage, bool reliable) const -{ - if (m_connection) - { - static std::vector v; - v.clear(); - v.push_back(m_characterObjectId); - GameClientMessage const msg(v, reliable, outgoingMessage); - - - uint32 now = Clock::timeMs(); - if ( sm_outgoingBytesMap_Worktime == 0 ) - sm_outgoingBytesMap_Worktime = now; - else if ( (now - sm_outgoingBytesMap_Worktime) > 60000 ) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map< std::string, uint32 >::iterator iter; - for ( iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter ) - { - iter->second = 0; - } - sm_outgoingBytesMap_Worktime = now; - } - sm_outgoingBytesMap_Working[ outgoingMessage.getCmdName() ] += msg.getByteStream().getSize(); - - - m_connection->send(msg, true); - } - else - { - DEBUG_REPORT_LOG(true, ("Tried to send message to a client without a connection server connection.\n")); - } -} - - -//----------------------------------------------------------------------- - -std::map< std::string, uint32 >& Client::getPacketBytesPerMinStats() -{ - uint32 now = Clock::timeMs(); - if ( sm_outgoingBytesMap_Worktime == 0 ) - sm_outgoingBytesMap_Worktime = now; - else if ( (now - sm_outgoingBytesMap_Worktime) > 60000 ) // 60 seconds - { - sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; - std::map< std::string, uint32 >::iterator iter; - for ( iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter ) - { - iter->second = 0; +namespace ClientNamespace { + // list of object types, radial menu action permission + // override, to allow certain object types to have certain radial + // menu action invoked on them by non-owners of the object + std::set > s_radialMenuPermissionOverrideTemplateItemType; + std::set > s_radialMenuPermissionOverrideStaticItemType; + + // ---------------------------------------------------------------------- + + bool + canManipulateObjectExceptionCheck(ServerObject const &target, int menuType, Container::ContainerErrorCode &errorCode) { + if (errorCode == Container::CEC_NoPermission) { + const std::string &objectStaticName = target.getStaticItemName(); + if (objectStaticName.empty()) { + if (s_radialMenuPermissionOverrideTemplateItemType.count(std::make_pair(target.getTemplateCrc(), menuType)) > + 0) { + errorCode = Container::CEC_Success; + return true; } - sm_outgoingBytesMap_Worktime = now; + } else if (s_radialMenuPermissionOverrideStaticItemType.count(std::make_pair(objectStaticName, menuType)) > + 0) { + errorCode = Container::CEC_Success; + return true; + } } - return sm_outgoingBytesMap_Stats; -} + return false; + } + // ---------------------------------------------------------------------- + void remove() { + } +} + +// ====================================================================== + +Client::ClientMessage::ClientMessage(const std::string &src) : MessageDispatch::MessageBase(src.c_str()) { +} + +//----------------------------------------------------------------------- + +Client::ClientMessage::~ClientMessage() { +} + + + + +//----------------------------------------------------------------------- + +std::map Client::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute +std::map Client::sm_outgoingBytesMap_Stats; // computed stats from the last minute +uint32 Client::sm_outgoingBytesMap_Worktime = 0; // time we started filling in the working map + + +// ====================================================================== + +Client::Client(ConnectionServerConnection &connection, const NetworkId &characterObjectId, const std::string &accountName, const std::string &ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const &observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const &accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport) + : MessageDispatch::Receiver(), MessageDispatch::Emitter(), m_accountName(accountName), m_characterName(), + m_characterObjectId(characterObjectId), m_connection(&connection), m_controlledObjects(), m_godLevel(0), + m_godMode(false), m_godValidated(false), m_ipAddress(ipAddr), m_isReady(false), m_isSecure(isSecure), + m_isSkipLoadScreen(isSkipLoadScreen), m_primaryControlledObject(NetworkId::cms_invalid), destroyNotifier(), + m_observing(), m_openedContainers(), m_watchedByList(), + m_lastNonIdleTime(ServerClock::getInstance().getGameTimeSeconds()), m_stationId(stationId), + m_connectionServerLag(0), m_gameServerLag(0), m_gameFeatures(gameFeatures), + m_subscriptionFeatures(subscriptionFeatures), m_accountFeatureIds(accountFeatureIds), + m_entitlementTotalTime(entitlementTotalTime), m_entitlementEntitledTime(entitlementEntitledTime), + m_entitlementTotalTimeSinceLastLogin(entitlementTotalTimeSinceLastLogin), + m_entitlementEntitledTimeSinceLastLogin(entitlementEntitledTimeSinceLastLogin), m_buddyPoints(buddyPoints), + m_previousObservedObjects(observedObjects), m_syncUIs(), m_consumedRewardEvents(consumedRewardEvents), + m_claimedRewardItems(claimedRewardItems), m_usingAdminLogin(usingAdminLogin), + m_combatSpamFilter(combatSpamFilter), m_combatSpamRangeSquaredFilter(combatSpamRangeSquaredFilter), + m_furnitureRotationDegree(furnitureRotationDegree), m_hasUnoccupiedJediSlot(hasUnoccupiedJediSlot), + m_isJediSlotCharacter(isJediSlotCharacter), m_sendToStarport(sendToStarport) { + + connectToEmitter(connection, "ConnectionServerConnectionClosed"); + connectToEmitter(connection, "ConnectionServerConnectionDestroyed"); + + // Check god permissions + if (ConfigServerGame::getAdminGodToAll() || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) && + AdminAccountManager::isAdminAccount(Unicode::toLower(accountName), m_godLevel) && + (!ConfigServerGame::getUseIPForGodAccess() || + AdminAccountManager::isInternalIp(ipAddr)))) { + m_godValidated = true; + if (ConfigServerGame::getAdminGodToAll()) { + m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); + } + } + + // See if our controlled object is ready yet. + ServerObject *obj = LogoutTracker::findPendingCharacterSave(characterObjectId); + if (obj) { + // If we're waiting to be saved in the LogoutTracker, then we've been + // removed from our container, so restore our containment if need be. + Object *containerObject = ContainerInterface::getContainedByObject(*obj); + if (containerObject) { + // Don't ever put the character into a packed house + ServerObject *const serverObject = containerObject->asServerObject(); + CellObject *const cellObject = (serverObject ? serverObject->asCellObject() : nullptr); + BuildingObject *const buildingObject = (cellObject ? cellObject->getOwnerBuilding() : nullptr); + + if ((buildingObject) && (!buildingObject->isInWorld())) { + ContainedByProperty *const cby = ContainerInterface::getContainedByProperty(*obj); + if (cby) { + DEBUG_REPORT_LOG(true, ("Ejecting player %s from building %s, because the building is packed\n", characterObjectId.getValueString().c_str(), buildingObject->getNetworkId().getValueString().c_str())); + LOG("CustomerService", ("Login: Ejecting player %s from building %s, because the building is packed", characterObjectId.getValueString().c_str(), buildingObject->getNetworkId().getValueString().c_str())); + + cby->setContainedBy(NetworkId::cms_invalid, true); + containerObject = 0; + + // attempt to put the character at the ejection point of the building + if (!ServerWorld::isSpaceScene()) { + DynamicVariableLocationData ejectionPoint; + if (obj->getObjVars().getItem("building_ejection_point", ejectionPoint) && + (ServerWorld::getSceneId() == ejectionPoint.scene) && (!ejectionPoint.cell.isValid())) { + obj->removeObjVarItem("building_ejection_point"); + obj->setPosition_p(ejectionPoint.pos); + } + } + } + } else if (containerObject->isAuthoritative()) { + // The cell depersist step will try to set the parent cell of the player. + // However, that procedure will fail because the "contained by" property + // says the player is in a container when they really are not. + ContainedByProperty *const cby = ContainerInterface::getContainedByProperty(*obj); + if (cby) { + // We need to remove and then re-add the property so that the + // property is updated immediately (as opposed to waiting for an alter) + cby->setContainedBy(NetworkId::cms_invalid, true); + obj->removeProperty(cby->getPropertyId()); + obj->addProperty(*cby, true); + } + + // save and restore the original transform. The existing transform should be in parent + // space, but it is in world. down through depersistContents there is an assumption that + // it is in parent space and gets transformed incorrectly. + Transform origTransform = obj->getTransform_o2p(); + + // NOTE: Depersist works slightly differently than when the player + // is loaded from the database since in this case the player + // is initialized when depersist is called + Container *const container = ContainerInterface::getContainer(*containerObject); + NOT_NULL(container); + IGNORE_RETURN(container->depersistContents(*obj)); + + // if failed to put character back into the container, then clean up the + // containment relationship so that the character is now out in the world + if (ContainerInterface::getContainedByObject(*obj) != containerObject) { + IGNORE_RETURN(container->internalItemRemoved(*obj)); + + if (cby) { + // We need to remove and then re-add the property so that the + // property is updated immediately (as opposed to waiting for an alter) + cby->setContainedBy(NetworkId::cms_invalid, true); + obj->removeProperty(cby->getPropertyId()); + obj->addProperty(*cby, true); + } + + // attempt to put the character at the ejection point of the building + if (!ServerWorld::isSpaceScene()) { + DynamicVariableLocationData ejectionPoint; + if (obj->getObjVars().getItem("building_ejection_point", ejectionPoint) && + (ServerWorld::getSceneId() == ejectionPoint.scene) && (!ejectionPoint.cell.isValid())) { + DEBUG_REPORT_LOG(true, ("Ejecting player %s from building %s, because could not put player back in building\n", characterObjectId.getValueString().c_str(), (buildingObject + ? buildingObject->getNetworkId().getValueString().c_str() + : containerObject->getNetworkId().getValueString().c_str()))); + LOG("CustomerService", ("Login: Ejecting player %s from building %s, because could not put player back in building", characterObjectId.getValueString().c_str(), (buildingObject + ? buildingObject->getNetworkId().getValueString().c_str() + : containerObject->getNetworkId().getValueString().c_str()))); + + obj->removeObjVarItem("building_ejection_point"); + obj->setPosition_p(ejectionPoint.pos); + } + } + + containerObject = 0; + } else { + obj->setTransform_o2w(origTransform); + + // if the character was in a building, tell the building it has gained + // the player so the building demand load/unload system can work correctly + Object *buildingObj = ContainerInterface::getTopmostContainer(*containerObject); + if (buildingObj && buildingObj->asServerObject() && + buildingObj->asServerObject()->asBuildingObject()) { + buildingObj->asServerObject()->asBuildingObject()->gainedPlayer(*obj); + } + } + } else { + // The container is no longer authoritative on this server. Move us to a safe place + // outside the container. + Object *const topmostObject = ContainerInterface::getTopmostContainer(*obj); + BuildingObject *const topmostBuilding = dynamic_cast(topmostObject); + if (topmostBuilding) { + DEBUG_REPORT_LOG(true, ("Ejecting player %s from building %s, because the building has changed authority\n", characterObjectId.getValueString().c_str(), topmostBuilding->getNetworkId().getValueString().c_str())); + LOG("CustomerService", ("Login: Ejecting player %s from building %s, because the building has changed authority", characterObjectId.getValueString().c_str(), topmostBuilding->getNetworkId().getValueString().c_str())); + ContainedByProperty *const cby = ContainerInterface::getContainedByProperty(*obj); + if (cby) { + cby->setContainedBy(NetworkId::cms_invalid, true); + containerObject = 0; + + PortalProperty *const portalProperty = topmostBuilding->getPortalProperty(); + if (portalProperty) { + ServerController *const controller = dynamic_cast(obj->getController()); + if (controller) { + Transform destinationTransform(Transform::IF_none); + destinationTransform.multiply(topmostBuilding->getTransform_o2w(), portalProperty->getEjectionLocationTransform()); + obj->setTransform_o2p(destinationTransform); + } + } + } + } else { + WARNING(true, ("Expected player %s to be in a building, but he was in some other type of object. Skipping authority fixup because something strange is going on.", characterObjectId.getValueString().c_str())); + } + } + } else { + // check for the case where we were in a container that isn't there anymore + ContainedByProperty *const cby = ContainerInterface::getContainedByProperty(*obj); + if ((cby) && (cby->getContainedByNetworkId().isValid())) { + DEBUG_REPORT_LOG(true, ("Ejecting player %s from building %s, because the building does not exist anymore\n", characterObjectId.getValueString().c_str(), cby->getContainedByNetworkId().getValueString().c_str())); + LOG("CustomerService", ("Login: Ejecting player %s from building %s, because the building does not exist anymore", characterObjectId.getValueString().c_str(), cby->getContainedByNetworkId().getValueString().c_str())); + + cby->setContainedBy(NetworkId::cms_invalid, true); + + // attempt to put the character at the ejection point of the building + if (!ServerWorld::isSpaceScene()) { + DynamicVariableLocationData ejectionPoint; + if (obj->getObjVars().getItem("building_ejection_point", ejectionPoint) && + (ServerWorld::getSceneId() == ejectionPoint.scene) && (!ejectionPoint.cell.isValid())) { + obj->removeObjVarItem("building_ejection_point"); + obj->setPosition_p(ejectionPoint.pos); + } + } + } + } + + // Only add to the world if it in a location which should be in the world. + if (!containerObject || + (containerObject->isInWorld() && containerObject->getContainerProperty()->isContentItemExposedWith(*obj))) { + obj->addToWorld(); + } + + // Notify the object that it has a client about to load + obj->onClientAboutToLoad(); + + // We need to trigger having been made authoritative since we are an object which has been + // disconnected from the world. + obj->triggerMadeAuthoritative(); + + // Create proxies as needed + ProxyList const &proxyList = obj->getExposedProxyList(); + if (!proxyList.empty()) { + ServerMessageForwarding::begin(std::vector(proxyList.begin(), proxyList.end())); + + obj->forwardServerCreateAndBaselines(); + + ServerMessageForwarding::end(); + } + } else { + obj = ServerWorld::findObjectByNetworkId(characterObjectId); + } + + if (obj) { + obj->checkAndAddClientControl(this); + } + + // Send server-specific settings to the client + ParametersMessage const msg(ConfigServerGame::getWeatherUpdateSeconds()); + send(msg, true); + + ObjectTracker::addPlayer(); +} + +//----------------------------------------------------------------------- + +Client::~Client() { + ClientDestroy d(this); + destroyNotifier.emitMessage(d); + + if (ServerWorld::isSpaceScene()) { + SpaceVisibilityManager::removeClient(*this); + } + + ObserveTracker::onClientDestroyed(*this); + ShipClientUpdateTracker::onClientDestroyed(*this); + + DEBUG_FATAL(!m_controlledObjects.empty(), ("Deleting a client with a non-empty controlled objects list!\n")); + m_primaryControlledObject = NetworkId::cms_invalid; + + //clean up any orphaned SynchronizedUIs + for (std::vector < Watcher < ServerSynchronizedUi > > ::iterator i = m_syncUIs.begin(); i != m_syncUIs.end(); + ++i) + { + ServerSynchronizedUi *syncUI = i->getPointer(); + delete syncUI; + } + + ObjectTracker::removePlayer(); + + PvpUpdateObserver::removeClientFromPvpStatusCache(this); + m_connection = 0; +} + +// ---------------------------------------------------------------------- + +void Client::install() { + // read in the list of object types, radial menu action permission + // override, to allow certain object types to have certain radial + // menu action invoked on them by non-owners of the object + char const *const radialMenuPermissionOverrideDataTableName = "datatables/player/radial_menu_permission_override.iff"; + DataTable *table = DataTableManager::getTable(radialMenuPermissionOverrideDataTableName, true); + if (table) { + int const columnObjectTemplate = table->findColumnNumber("Object Template"); + int const columnCommand = table->findColumnNumber("Command"); + if ((columnObjectTemplate >= 0) && (columnCommand >= 0)) { + std::string objectTemplate; + std::string command; + int commandMenuId; + + for (int i = 0, numRows = table->getNumRows(); i < numRows; ++i) { + objectTemplate = table->getStringValue(columnObjectTemplate, i); + if (objectTemplate.empty()) { + continue; + } + + command = table->getStringValue(columnCommand, i); + if (command.empty()) { + continue; + } + + commandMenuId = RadialMenuManager::getMenuTypeByName(command); + if (commandMenuId == 0) { + continue; + } + + if (objectTemplate.find(".iff") != std::string::npos) { + ClientNamespace::s_radialMenuPermissionOverrideTemplateItemType.insert(std::make_pair(CrcLowerString::calculateCrc(objectTemplate.c_str()), commandMenuId)); + } else { + ClientNamespace::s_radialMenuPermissionOverrideStaticItemType.insert(std::make_pair(objectTemplate, commandMenuId)); + } + } + } + + DataTableManager::close(radialMenuPermissionOverrideDataTableName); + } + + ExitChain::add(ClientNamespace::remove, "ClientNamespace::remove"); +} + //----------------------------------------------------------------------- -void Client::sendToConnectionServer(GameNetworkMessage const &msg) -{ - if (m_connection) - m_connection->send(msg, true); - else - { - DEBUG_REPORT_LOG(true, ("Tried to send message to a client without a connection server connection.\n")); - } +void Client::addControlledObject(ServerObject &object) { + // check to see if it is in the list already + if (std::find(m_controlledObjects.begin(), m_controlledObjects.end(), &object) == m_controlledObjects.end()) { + m_controlledObjects.push_back(&object); + } else { + DEBUG_WARNING(true, ("Client adding controlled object [%s] that is already controlled", object.getNetworkId().getValueString().c_str())); + } + + //finally set a pointer to the Client object on the object + object.setClient(*this); + ObserveTracker::onObjectControlled(*this, object, m_previousObservedObjects); + + // Any objects to be re-controlled have been at this point, so clean up any old objects that are no longer observed + ObserveTracker::onClientControlComplete(*this, m_previousObservedObjects); + m_previousObservedObjects.clear(); + + // If in space, add the client to SpaceVisibilityManager. Only do this for the topmost object the client controls that is in the world. + if (ServerWorld::isSpaceScene()) { + Object *topmost = ContainerInterface::getTopmostContainer(object); + NOT_NULL(topmost); + NOT_NULL(topmost->asServerObject()); + if (topmost->isInWorld()) { + SpaceVisibilityManager::addClient(*this, *(topmost->asServerObject())); + } + } + + // Restore god mode after changing servers + CreatureObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); + if (primaryControlledObject) { + if (primaryControlledObject->hasCommand(AdminAccountManager::getAdminCommandName())) { + setGodMode(true); + } + } } + +// ---------------------------------------------------------------------- + +void Client::clearControlledObjects() { + while (!m_controlledObjects.empty()) { + removeControlledObject(**m_controlledObjects.begin()); + } + + PvpUpdateObserver::removeClientFromPvpStatusCache(this); +} + +// ---------------------------------------------------------------------- +ServerObject *Client::findControlledObject(NetworkId const &oid) const { + for (std::vector::const_iterator i = m_controlledObjects.begin(); + i != m_controlledObjects.end(); ++i) { + if ((*i) && (*i)->getNetworkId() == oid) { + return *i; + } + } + return 0; +} + +// ---------------------------------------------------------------------- + +std::vector const &Client::getControlledObjects() const { + return m_controlledObjects; //lint !e1536 //low access +} + //----------------------------------------------------------------------- -uint16 Client::getServerSyncStampShort() const -{ - NOT_NULL(m_connection); - return m_connection->getSyncStampShort(); +bool Client::isControlled(NetworkId const &id) const { + std::vector::const_iterator i; + for (i = m_controlledObjects.begin(); i != m_controlledObjects.end(); ++i) { + ServerObject *object = *i; + if (object && object->getNetworkId() == id) { + return true; + } + } + return false; } //----------------------------------------------------------------------- + +void Client::onLoadPlayer(CreatureObject &newCharacter) { + if (m_primaryControlledObject != NetworkId::cms_invalid) { + DEBUG_WARNING(true, ("Already have a primary object!")); + if (m_primaryControlledObject == newCharacter.getNetworkId()) { + return; + } + } -uint32 Client::getServerSyncStampLong() const -{ - NOT_NULL(m_connection); - return m_connection->getSyncStampLong(); + m_primaryControlledObject = CachedNetworkId(newCharacter); + + assumeControl(newCharacter); } //----------------------------------------------------------------------- + +void Client::assumeControl(CreatureObject &newCharacter) { + DEBUG_FATAL( + newCharacter.getNetworkId() != m_primaryControlledObject, ("Tried to assume control of the wrong object?")); + + // Add the object to the controlled object list + addControlledObject(newCharacter); + + // Register player name with the global list + std::string const &firstName = Unicode::wideToNarrow(Unicode::toLower(newCharacter.getAssignedObjectFirstName())); + std::string const &fullName = Unicode::wideToNarrow(newCharacter.getAssignedObjectName()); + PlayerObject const *const playerObject = PlayerCreatureController::getPlayerObject(&newCharacter); + NameManager::getInstance().addPlayer(newCharacter.getNetworkId(), (playerObject ? playerObject->getStationId() + : static_cast(m_stationId)), firstName, fullName, 0, Os::getRealSystemTime(), true); + + static const std::string loginTrace("TRACE_LOGIN"); + LOG(loginTrace, ("sending ControlAssumed(%s, %s)", m_primaryControlledObject.getValueString().c_str(), ConfigServerGame::getGroundScene())); -float Client::computeDeltaTimeInSeconds(uint32 const syncStampLong) const -{ - uint32 const deltaTimeMilliseconds = syncStampLong - getServerSyncStampLong(); + ControlAssumed const controlMessage(m_primaryControlledObject, ConfigServerGame::getGroundScene(), m_isSkipLoadScreen, newCharacter.getTransform_o2w().getPosition_p(), newCharacter.getObjectFrameK_w().theta(), newCharacter.getSharedTemplateName(), static_cast(ServerClock::getInstance().getGameTimeSeconds())); - float deltaTime = 0.f; - if (deltaTimeMilliseconds > 0x7fffffff) - deltaTime = static_cast(static_cast(0xffffffff - deltaTimeMilliseconds)) / 1000.0f; - else - deltaTime = static_cast(static_cast(deltaTimeMilliseconds)) / 1000.0f; + sendToConnectionServer(controlMessage); - return deltaTime; + m_isSkipLoadScreen = false; } //----------------------------------------------------------------------- -bool Client::setGodMode(bool value) -{ - // (re?) check god permissions - m_godLevel = AdminAccountManager::isAdminAccount(getStationId()); +void Client::receiveClientMessage(const GameNetworkMessage &message) { + try { - if (ConfigServerGame::getAdminGodToAll() || (m_godLevel > 0)) + // Ignore any messages if the character is not loaded yet. + if (m_primaryControlledObject == NetworkId::cms_invalid) { + DEBUG_REPORT_LOG(true, ("Ignoring message for character %s because it is not loaded yet.\n", m_characterObjectId.getValueString().c_str())); + return; + } + + ServerObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); + + if (!primaryControlledObject) { + DEBUG_REPORT_LOG(true, ("Ignoring message for character %s because object %s cannot be found.\n", m_characterObjectId.getValueString().c_str(), m_primaryControlledObject.getValueString().c_str())); + return; + } + + //----------------------------------------------------------------- + + const uint32 messageType = message.getType(); + + switch (messageType) { + case constcrc("ShipUpdateTransformMessage") : { + Archive::ReadIterator readIterator = static_cast(message).getByteStream().begin(); + ShipUpdateTransformMessage const shipUpdateTransformMessage(readIterator); + + for (std::vector::const_iterator i = m_controlledObjects.begin(); + i != m_controlledObjects.end(); ++i) { + ShipObject *const ship = (*i)->asShipObject(); + if (ship) { + PlayerShipController *const playerShipController = safe_cast(ship->getController()); + if (playerShipController) { + playerShipController->receiveTransform(shipUpdateTransformMessage); + } + } + } + break; + } + + //---------------------------------------------------------------------- + + case constcrc("CreateProjectileMessage") : { + Archive::ReadIterator readIterator = static_cast(message).getByteStream().begin(); + CreateProjectileMessage const createProjectileMessage(readIterator); + + // pilots can fire from non-turrets, gunners can fire their turret + ServerObject *const characterObject = getCharacterObject(); + if (characterObject) { + ServerObject *const containedBy = safe_cast(ContainerInterface::getContainedByObject(*characterObject)); + if (containedBy) { + SlottedContainer const *const slottedContainer = ContainerInterface::getSlottedContainer(*containedBy); + ShipObject *const shipObject = ShipObject::getContainingShipObject(containedBy); + + if ((shipObject != nullptr) && (slottedContainer != nullptr) && + !shipObject->hasCondition(TangibleObject::C_docking)) { + bool shotOk = false; + + int const weaponIndex = createProjectileMessage.getWeaponIndex(); + if (weaponIndex >= 0 && weaponIndex < ShipChassisSlotType::cms_numWeaponIndices) { + Container::ContainerErrorCode err = Container::CEC_Success; + if (shipObject->isTurret(weaponIndex)) { + if (slottedContainer->getObjectInSlot(ShipSlotIdManager::getPobShipGunnerSlotId(weaponIndex), err) == + characterObject->getNetworkId() || + slottedContainer->getObjectInSlot(ShipSlotIdManager::getShipGunnerSlotId(weaponIndex), err) == + characterObject->getNetworkId()) { + shotOk = true; + } // gunner firing his turret + } else { + if (slottedContainer->getObjectInSlot(ShipSlotIdManager::getShipPilotSlotId(), err) == + characterObject->getNetworkId() || + slottedContainer->getObjectInSlot(ShipSlotIdManager::getPobShipPilotSlotId(), err) == + characterObject->getNetworkId()) { + shotOk = true; + } // pilot firing non-turret + } + } + + // only gods can fire while invulnerable + if (shipObject->isInvulnerable() && !isGod()) { + shotOk = false; + } + + if (shotOk) { + shipObject->enqueueFireShotClient(*this, weaponIndex, createProjectileMessage.getTransform_p(), createProjectileMessage.getTargetedComponent(), createProjectileMessage.getSyncStampLong()); + } + } + } + } + break; + } + + //---------------------------------------------------------------------- + + case constcrc("CmdSceneReady") : { + m_isReady = true; + primaryControlledObject->onClientReady(this); + break; + } + + //---------------------------------------------------------------------- + + case constcrc("SetCombatSpamFilter") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const msg(ri); + m_combatSpamFilter = static_cast(msg.getValue()); + break; + } + + //---------------------------------------------------------------------- + + case constcrc("SetCombatSpamRangeFilter") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const msg(ri); + m_combatSpamRangeSquaredFilter = sqr(msg.getValue()); + break; + } + + //---------------------------------------------------------------------- + + case constcrc("SetFurnitureRotationDegree") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const msg(ri); + m_furnitureRotationDegree = msg.getValue(); + break; + } + + //---------------------------------------------------------------------- + + case constcrc("GcwRegionsReq") : { + GenericValueTypeMessage < std::map < std::string, std::map < std::string, std::pair < std::pair < float, + float >, float > > > > + const rsp( + "GcwRegionsRsp", Pvp::getGcwScoreCategoryRegions()); + send(rsp, true); + + GenericValueTypeMessage < std::map < std::string, std::map < std::string, int > > > + const rsp2( + "GcwGroupsRsp", Pvp::getGcwScoreCategoryGroups()); + send(rsp2, true); + break; + } + + //---------------------------------------------------------------------- + + case constcrc("SetJediSlotInfo") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + // this comes from the client (via the LoginServer) so should not be trusted; + // we cache them here to do preliminary checks to avoid unnecessarily sending + // commands to the LoginServer (assuming the values haven't been hacked on the + // client); when we do send the commands to the LoginServer, we'll check again there + m_hasUnoccupiedJediSlot = msg.getValue().first; + m_isJediSlotCharacter = msg.getValue().second; + break; + } + + //---------------------------------------------------------------------- + + case constcrc("RotateFurnitureSetQuaternion") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage < std::pair < NetworkId, std::pair < std::pair < float, float >, std::pair < + float, float > + > > > + const msg(ri); + + CreatureObject *creatureOwner = safe_cast(getCharacterObject()); + if (creatureOwner && creatureOwner->isAuthoritative()) { + ServerObject const *target = ServerWorld::findObjectByNetworkId(msg.getValue().first); + if (target && target->isAuthoritative()) { + static uint32 const commandHash = Crc::normalizeAndCalculate("rotateFurniture"); + const Command &command = CommandTable::getCommand(commandHash); + if (!command.isNull()) { + // for obfuscation so players won't manually send us this command + Unicode::String params = Unicode::narrowToWide(FormattedString<512>().sprintf("(^-,=+_)internal_use_only_%s_quaternion(,+-=_^) %.10f %.10f %.10f %.10f %s", creatureOwner->getNetworkId().getValueString().c_str(), msg.getValue().second.first.first, msg.getValue().second.first.second, msg.getValue().second.second.first, msg.getValue().second.second.second, msg.getValue().first.getValueString().c_str())); + creatureOwner->commandQueueEnqueue(command, target->getNetworkId(), params, 0, false, static_cast(Command::CP_Default), true); + } + } + } + break; + } + + //---------------------------------------------------------------------- + + case constcrc("SetLfgInterests") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const msg(ri); + + PlayerObject const * + const playerObject = PlayerCreatureController::getPlayerObject(safe_cast < CreatureObject const * > + (getCharacterObject())); + if (playerObject) { + std::map const &connectedCharacterLfgData = ServerUniverse::getConnectedCharacterLfgData(); + std::map::const_iterator iterFind = connectedCharacterLfgData.find(getCharacterObjectId()); + if (iterFind != connectedCharacterLfgData.end()) { + BitArray lfgInterests = msg.getValue(); + + MatchMakingId const &id = playerObject->getMatchMakingCharacterProfileId(); + if (id.isBitSet(MatchMakingId::B_lookingForGroup)) { + LfgDataTable::setBit("lfg", lfgInterests); + } else { + LfgDataTable::clearBit("lfg", lfgInterests); + } + + if (id.isBitSet(MatchMakingId::B_helper)) { + LfgDataTable::setBit("helper", lfgInterests); + } else { + LfgDataTable::clearBit("helper", lfgInterests); + } + + if (id.isBitSet(MatchMakingId::B_rolePlay)) { + LfgDataTable::setBit("rp", lfgInterests); + } else { + LfgDataTable::clearBit("rp", lfgInterests); + } + + if (id.isBitSet(MatchMakingId::B_lookingForWork)) { + LfgDataTable::setBit("lfw", lfgInterests); + } else { + LfgDataTable::clearBit("lfw", lfgInterests); + } + + ServerUniverse::setConnectedCharacterInterestsData(getCharacterObjectId(), lfgInterests); + } + } + break; + } + + //---------------------------------------------------------------------- + + case constcrc("RequestGroundObjectPlacement") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage < std::pair < NetworkId, std::pair < std::pair < int, float >, std::pair < + float, float > > + > > + const msg(ri); + + ServerObject *const target = safe_cast(NetworkIdManager::getObjectById(msg.getValue().first)); + GameScriptObject *const scriptObject = target ? target->getScriptObject() : 0; + + if (!scriptObject) { + return; + } + + int menuType = msg.getValue().second.first.first; + Vector loc(msg.getValue().second.first.second, msg.getValue().second.second.first, msg.getValue().second.second.second); + ScriptParams params; + params.addParam(getCharacterObjectId()); + params.addParam(menuType); + params.addParam(loc.x); + params.addParam(loc.y); + params.addParam(loc.z); + + IGNORE_RETURN(scriptObject->trigAllScripts(Scripting::TRIG_GROUND_TARGET_LOC, params)); + break; + } + //---------------------------------------------------------------------- + + case constcrc("ShowBackpack") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + PlayerObject *player = dynamic_cast(NetworkIdManager::getObjectById(msg.getValue().first)); + + if (player) { + player->modifyShowBackpack(msg.getValue().second); + } + + break; + } + //---------------------------------------------------------------------- + + case constcrc("ShowHelmet") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + PlayerObject *player = dynamic_cast(NetworkIdManager::getObjectById(msg.getValue().first)); + + if (player) { + player->modifyShowHelmet(msg.getValue().second); + } + + break; + } + //---------------------------------------------------------------------- + + case constcrc("SetWaypointColor") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + if ((msg.getValue().second == "blue") || (msg.getValue().second == "green") || + (msg.getValue().second == "orange") || (msg.getValue().second == "yellow") || + (msg.getValue().second == "purple") || (msg.getValue().second == "white")) { + Waypoint w = Waypoint::getWaypointById(msg.getValue().first); + if (w.isValid()) { + w.setColor(Waypoint::getColorIdByName(msg.getValue().second)); + } + } + + break; + } + + //---------------------------------------------------------------------- + + case constcrc("ConGenericMessage") : { + + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ConGenericMessage c(ri); + if (isGod()) { + LOG("CustomerService", ("Avatar:%s executing command: %s", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), c.getMsg().c_str())); + ConsoleMgr::processString(c.getMsg(), this, c.getMsgId()); + } else { + //Non-god user tried to use a console command + if (m_primaryControlledObject.getObject()) { + LOG("CustomerService", ("CheatChannel:%s tried to execute a console command but they are not a god", PlayerObject::getAccountDescription(m_primaryControlledObject.getObject()->getNetworkId()).c_str())); + ConsoleMgr::broadcastString("Only god users can execute console commands.", this, c.getMsgId()); + } + + } + break; + } + + //----------------------------------------------------------------- + + case constcrc("ObjControllerMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ObjControllerMessage o(ri); + bool appended = false; + + // check to make sure the controller message is allowed from the client + bool allowFromClient = ControllerMessageFactory::allowFromClient(o.getMessage()); + + // we default this to true so that unless + // a controller message is explicitly marked as being allowed + // from the client, or the client is a GM, it will be dropped when the game server + // receives it; this will have the effect of forcing the + // programmer to make a conscious decision to mark the + // controller message as allowable from the client; because + // controller message coming from the client is not secured, + // the mechanism to prevent a hacked client from sending the + // game server any controller message is to explicity "mark" + // those controller messages that are allowed from the client + + if (allowFromClient || isGod()) { + ServerObject *target = findControlledObject(o.getNetworkId()); + if (target != 0) { + // apply the controller message + ServerController *controller = dynamic_cast(target->getController()); + if (controller != nullptr) { + uint32 flags = o.getFlags(); + flags &= ~GameControllerMessageFlags::SOURCE_REMOTE; + flags |= GameControllerMessageFlags::SOURCE_REMOTE_CLIENT; + controller->appendMessage(o.getMessage(), o.getValue(), o.getData(), flags); + appended = true; + } + } else if (isGod()) { + target = ServerWorld::findObjectByNetworkId(o.getNetworkId()); + + if (target) { + ServerController *controller = dynamic_cast(target->getController()); + if (controller != nullptr) { + uint32 flags = o.getFlags(); + flags &= ~GameControllerMessageFlags::SOURCE_REMOTE; + flags |= GameControllerMessageFlags::SOURCE_REMOTE_CLIENT; + controller->appendMessage(o.getMessage(), o.getValue(), o.getData(), flags); + appended = true; + } + } + } + } else { + // log as a likely hack + LOG("CustomerService", ("UnauthorizedControllerMessage: Player %s sent an unauthorized controller message %d for object %s.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), o.getMessage(), o.getNetworkId().getValueString().c_str())); + } + + if (!appended) { + delete o.getData(); + } + + break; + } + + //----------------------------------------------------------------- + //Secure Trade Messages + //----------------------------------------------------------------- + case constcrc("AddItemMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AddItemMessage m(ri); + + + ServerObject *item = ServerWorld::findObjectByNetworkId(m.getNetworkId()); + if (!item) { + return; + } + + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->addItem(*playerObject, *item); + } + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + case constcrc("RemoveItemMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RemoveItemMessage m(ri); + + ServerObject *item = ServerWorld::findObjectByNetworkId(m.getNetworkId()); + if (!item) { + return; + } + + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->removeItem(*playerObject, *item); + } + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + case constcrc("GiveMoneyMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GiveMoneyMessage m(ri); + + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->giveMoney(*playerObject, m.getAmount()); + } + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + case constcrc("AcceptTransactionMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AcceptTransactionMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->acceptOffer(*playerObject); + } + + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has accepted a secure trade. (Check trade logs for more detail.", PlayerObject::getAccountDescription(playerObject).c_str())); + } + + + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + case constcrc("UnAcceptTransactionMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + UnAcceptTransactionMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->unacceptOffer(*playerObject); + } + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + case constcrc("VerifyTradeMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + VerifyTradeMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->verifyTrade(*playerObject); + } + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + case constcrc("DenyTradeMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + DenyTradeMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->rejectOffer(*playerObject); + } + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + case constcrc("AbortTradeMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AbortTradeMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + DEBUG_FATAL(!playerObject, ("No controller for player!\n")); + if (playerObject) //lint !e774 + { + PlayerCreatureController *playerController = dynamic_cast(playerObject->getController()); + if (playerController && playerController->getSecureTrade()) { + playerController->getSecureTrade()->cancelTrade(*playerObject); + } + } else { + GameServer::getInstance().dropClient(m_characterObjectId); + } + break; + } + + case constcrc("GuildRequestMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GuildRequestMessage const m(ri); + + NetworkId const &id = m.getTargetId(); + CreatureObject *const creatureObject = dynamic_cast(NetworkIdManager::getObjectById(id)); + if (creatureObject) { + int const guildId = creatureObject->getGuildId(); + GuildMemberInfo const *const info = GuildInterface::getGuildMemberInfo(guildId, id); + GuildResponseMessage const responseMessage(id, GuildInterface::getGuildName(guildId), info + ? info->m_title + : std::string()); + send(responseMessage, true); + } + break; + } + + case constcrc("StomachRequestMessage") : { + CreatureObject *creatureObject = dynamic_cast(getCharacterObject()); + + if (creatureObject != nullptr) { + GameScriptObject *gameScriptObject = creatureObject->getScriptObject(); + + if (gameScriptObject != nullptr) { + ScriptParams scriptParams; + IGNORE_RETURN(gameScriptObject->trigAllScripts(Scripting::TRIG_STOMACH_UPDATE, scriptParams)); + } + } + break; + } + + case constcrc("FactionRequestMessage") : { + int rebel = 0; + int imperial = 0; + int criminal = 0; + + CreatureObject *playerObject = dynamic_cast(getCharacterObject()); + if (playerObject) { + float temp; + if (playerObject->getObjVars().getItem("faction.Rebel", temp)) { + rebel = static_cast(temp); + } + if (playerObject->getObjVars().getItem("faction.Imperial", temp)) { + imperial = static_cast(temp); + } + if (playerObject->getObjVars().getItem("faction.Hutt", temp)) { + criminal = static_cast(temp); + } + + std::vector factionNames; + std::vector factionValues; + std::string currentName; + float currentValue; + DynamicVariableList::NestedList factionList(playerObject->getObjVars(), "faction"); + for (DynamicVariableList::NestedList::const_iterator i = factionList.begin(); + i != factionList.end(); ++i) { + currentName = i.getName(); + bool result = i.getValue(currentValue); + if (result) { + factionNames.push_back(currentName); + factionValues.push_back(currentValue); + } + } + + FactionResponseMessage const msg(rebel, imperial, criminal, factionNames, factionValues); + send(msg, true); + } + break; + } + + //----------------------------------------------------------------- + + case constcrc("AcceptAuctionMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AcceptAuctionMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + CommoditiesMarket::auctionAccept(*playerObject, m.getItemId().getValue()); + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has accepted an auction for item %s", PlayerObject::getAccountDescription(playerObject).c_str(), m.getItemId().getValueString().c_str())); + } + } else { + WARNING(true, ("AcceptAuctionMessage: the player was not found")); + } + break; + } + + case constcrc("BidAuctionMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + BidAuctionMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has bid on an auction for item %s, amount %d", PlayerObject::getAccountDescription(playerObject).c_str(), m.getItemId().getValueString().c_str(), m.getBid())); + } + + CommoditiesMarket::auctionBid(*playerObject, m.getItemId().getValue(), m.getBid(), m.getMaxProxyBid()); + } else { + WARNING(true, ("BidAuctionMessage: the player was not found")); + } + break; + } + + case constcrc("CancelLiveAuctionMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + CancelLiveAuctionMessage m(ri); + + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + CommoditiesMarket::auctionCancel(*playerObject, m.getItemId().getValue()); + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has cancelled an auction for item %s", PlayerObject::getAccountDescription(playerObject).c_str(), m.getItemId().getValueString().c_str())); + } + + } else { + WARNING(true, ("CancelLiveAuctionMessage: the player was not found")); + } + break; + } + + case constcrc("CreateAuctionMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + CreateAuctionMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + NetworkId itemId = m.getItemId(); + NetworkId containerId = m.getContainerId(); + CommoditiesMarket::auctionCreate(*playerObject, itemId, m.getItemLocalizedName(), containerId, m.getMinimumBid(), m.getAuctionLength(), m.getUserDescription(), m.isPremium()); + + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has created an auction for item %s on vendor %s", PlayerObject::getAccountDescription(playerObject).c_str(), m.getItemId().getValueString().c_str(), containerId.getValueString().c_str())); + } + } else { + WARNING(true, ("CreateAuctionMessage: the player was not found")); + } + break; + } + + case constcrc("CreateImmediateAuctionMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + CreateImmediateAuctionMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + NetworkId itemId = m.getItemId(); + NetworkId containerId = m.getContainerId(); + if (m.isVendorTransfer()) { + CommoditiesMarket::transferVendorItemFromStockroom(*playerObject, itemId, m.getItemLocalizedName(), m.getPrice(), m.getAuctionLength(), m.getUserDescription()); + } else { + CommoditiesMarket::auctionCreateImmediate(*playerObject, itemId, m.getItemLocalizedName(), containerId, m.getPrice(), m.getAuctionLength(), m.getUserDescription(), m.isPremium()); + } + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has created an immediate auction for item %s on vendor %s", PlayerObject::getAccountDescription(playerObject).c_str(), m.getItemId().getValueString().c_str(), containerId.getValueString().c_str())); + } + } else { + WARNING(true, ("CreateImmediateAuctionMessage: the player was not found")); + } + break; + } + + case constcrc("RelistItemsFromStockMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage < std::pair < std::pair < std::vector < NetworkId > , std::vector < + Unicode::String > >, int > + > + const m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + std::vector const &itemIds = m.getValue().first.first; + std::vector const &itemLocalizedNames = m.getValue().first.second; + int const timer = m.getValue().second; + NetworkId itemId; + std::vector::const_iterator iterId = itemIds.begin(); + std::vector::const_iterator iterName = itemLocalizedNames.begin(); + for (; ((iterId != itemIds.end()) && + (iterName != itemLocalizedNames.end())); ++iterId, ++iterName) { + itemId = *iterId; + CommoditiesMarket::transferVendorItemFromStockroom(*playerObject, itemId, *iterName, -1, timer, Unicode::String()); + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has created an immediate auction (relist) for item %s", PlayerObject::getAccountDescription(playerObject).c_str(), itemId.getValueString().c_str())); + } + } + } else { + WARNING(true, ("RelistItemsFromStockMessage: the player was not found")); + } + break; + } + + case constcrc("RetrieveAuctionItemMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RetrieveAuctionItemMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + NetworkId itemId = m.getItemId(); + ServerObject *auctionContainer = dynamic_cast(NetworkIdManager::getObjectById(m.getContainerId())); + if (auctionContainer) { + if (playerObject->isAuthoritative() && auctionContainer->isAuthoritative()) { + CommoditiesMarket::auctionRetrieve(*playerObject, m.getItemId().getValue(), m.getItemId(), *auctionContainer); + if (playerObject->getObjVars().hasItem("cheater")) { + LOG("CustomerService", ("SuspectedCheaterChannel: %s has retrieved an auction for item %s on vendor %s", PlayerObject::getAccountDescription(playerObject).c_str(), m.getItemId().getValueString().c_str(), auctionContainer->getNetworkId().getValueString().c_str())); + } + } + } else { + LOG("CustomerService", ("Auction:Player %s attempted to retrieve an auction for container %Ld but failed.", PlayerObject::getAccountDescription(playerObject).c_str(), m.getContainerId().getValue())); + + RetrieveAuctionItemResponseMessage const msg(itemId, ar_INVALID_CONTAINER_ID);; + Client *client = playerObject->getClient(); + if (client) { + client->send(msg, true); + } + } + } else { + WARNING(true, ("RetrieveAuctionMessage: the player was not found")); + } + break; + } + case constcrc("AuctionQueryHeadersMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AuctionQueryHeadersMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + CommoditiesMarket::auctionQueryHeaders(*playerObject, m.getRequestId(), m.getSearchType(), m.getItemType(), m.getItemTypeExactMatch(), m.getItemTemplateId(), m.getTextFilterAll(), m.getTextFilterAny(), m.getPriceFilterMin(), m.getPriceFilterMax(), m.getPriceFilterIncludesFee(), m.getAdvancedSearch(), m.getAdvancedSearchMatchAllAny(), m.getContainer(), m.getLocationSearchType(), m.getMyVendorsOnly(), m.getQueryOffset()); + } + break; + } + case constcrc("GetAuctionDetails") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GetAuctionDetails m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + CommoditiesMarket::getAuctionDetails(*playerObject, m.getItem()); + } + break; + } + case constcrc("IsVendorOwnerMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + IsVendorOwnerMessage m(ri); + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + CommoditiesMarket::isVendorOwner(*playerObject, m.getContainerId()); + } + break; + } + case constcrc("CommoditiesItemTypeListRequest") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const m(ri); + + static char buffer[128]; + snprintf(buffer, sizeof(buffer) - + 1, "%s.%d", GameServer::getInstance().getClusterName().c_str(), CommoditiesMarket::getItemTypeMapVersionNumber()); + buffer[sizeof(buffer) - 1] = '\0'; + + if (m.getValue() != std::string(buffer)) { + GenericValueTypeMessage < std::pair < std::string, std::map < int, std::map < int, std::pair < int, + StringId > > > > > + const rsp( + "CommoditiesItemTypeListResponse", std::make_pair(std::string(buffer), CommoditiesMarket::getItemTypeMap())); + send(rsp, true); + } + break; + } + case constcrc("CommoditiesResourceTypeListRequest") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const m(ri); + + static char buffer[128]; + snprintf(buffer, sizeof(buffer) - + 1, "%s.%d", GameServer::getInstance().getClusterName().c_str(), CommoditiesMarket::getResourceTypeMapVersionNumber()); + buffer[sizeof(buffer) - 1] = '\0'; + + if (m.getValue() != std::string(buffer)) { + GenericValueTypeMessage < std::pair < std::string, std::map < int, std::set < std::string > > > > + const rsp( + "CommoditiesResourceTypeListResponse", std::make_pair(std::string(buffer), CommoditiesMarket::getResourceTypeMap())); + send(rsp, true); + } + break; + } + case constcrc("CollectionServerFirstListRequest") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const m(ri); + + PlanetObject const *const planetObject = ServerUniverse::getInstance().getTatooinePlanet(); + if (planetObject) { + static char buffer[128]; + snprintf(buffer, sizeof(buffer) - + 1, "%s.%d", GameServer::getInstance().getClusterName().c_str(), planetObject->getCollectionServerFirstUpdateNumber()); + buffer[sizeof(buffer) - 1] = '\0'; + + if (m.getValue() != std::string(buffer)) { + GenericValueTypeMessage < std::pair < std::string, std::set < std::pair < std::pair < int32, + std::string >, std::pair < NetworkId, Unicode::String > > > > > + const rsp( + "CollectionServerFirstListResponse", std::make_pair(std::string(buffer), planetObject->getCollectionServerFirst())); + send(rsp, true); + } + } + break; + } + + //----------------------------------------------------------------- + + case constcrc("AddMapLocationMessage") : { + Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); + const AddMapLocationMessage msg(readIterator); + UNREF(msg); + + /* + MapLocation mapLocation(msg.getLocationId(), msg.getLocationName(), + Vector2d(msg.getLocationX(), msg.getLocationY()), + msg.getCategory(), msg.getSubCategory()); + + PlanetObject *planetObject = ServerUniverse::getInstance ().getPlanetByName (msg.getPlanetName ()); + if (planetObject) + { + planetObject->addMapLocation(mapLocation); + } + AddMapLocationResponseMessage responseMsg(msg.getLocationId()); + send(responseMsg, true); + */ + break; + } + + case constcrc("GetSpecificMapLocationsMessage") : { + Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); + const GenericValueTypeMessage > > msg(readIterator); + + PlanetMapManagerServer::handleClientRequestGetSpecificMapLocationsMessage(*this, msg.getValue()); + break; + } + + case constcrc("ConsentResponseMessage") : { + Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); + ConsentResponseMessage const msg(readIterator); + ConsentManager::getInstance().handleResponse(msg); + break; + } + + case constcrc("RequestGalaxyLoopTimes") : { + // obfuscate the information so it's not obvious on the client that this is the server loop time + unsigned long loopTime = static_cast(Clock::frameTime() * + 3193000.0f); // loop time (in ms) * 3193 + GalaxyLoopTimesResponse const msg(loopTime, loopTime); + send(msg, true); + break; + } + case constcrc("LagRequest") : { + GameNetworkMessage const msg("GameServerLagResponse"); + send(msg, true); + break; + } + case constcrc("LagReport") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const report(ri); + m_connectionServerLag = report.getValue().first; + m_gameServerLag = report.getValue().second; + break; + } + case constcrc("ChatInviteGroupToRoom") : { + if (primaryControlledObject) { + CreatureObject *const playerCreature = primaryControlledObject->asCreatureObject(); + if (playerCreature) { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ChatInviteGroupToRoom const chat(ri); + + // We will need to notify the user if the group leader can not be found + bool foundGroupLeader = false; + + // Get the name of the group leader being invited + ChatAvatarId const &groupLeaderChatAvatarId = chat.getAvatarId(); + + // Convert the name to a network ID + NetworkId const groupLeaderNetworkId = NameManager::getInstance().getPlayerId(NameManager::normalizeName(Unicode::wideToNarrow(groupLeaderChatAvatarId.getName()))); + + // Try to get a group object corresponding to the player network ID + ServerObject const *const groupServerObject = ServerWorld::findObjectByNetworkId(GroupObject::getGroupIdForLeader(groupLeaderNetworkId)); + if (groupServerObject && groupServerObject->asGroupObject()) { + // We now know the player is a group leader of a group + GroupObject const *const groupLeaderGroupObject = groupServerObject->asGroupObject(); + + // Make sure we have the correct player since we only searched by name + // (i.e. we may have been looking for a player with the same name but on a different cluster) + ChatAvatarId const playerChatAvatarId = Chat::constructChatAvatarId(NameManager::normalizeName(groupLeaderGroupObject->getGroupLeaderName())); + if (playerChatAvatarId == groupLeaderChatAvatarId) { + // We found the group leader + foundGroupLeader = true; + + // We need to get the network IDs for all the group members + std::vector groupNetworkIds; + + GroupObject::GroupMemberVector const &groupMemberVector = groupLeaderGroupObject->getGroupMembers(); + for (unsigned i = 0; i < groupMemberVector.size(); ++i) { + GroupObject::GroupMember const &groupMember = groupMemberVector[i]; + + groupNetworkIds.push_back(groupMember.first); + } + + // Pass the invitation to all the group members + Chat::inviteGroupMembers(m_primaryControlledObject, chat.getAvatarId(), chat.getRoomName(), groupNetworkIds); + } + } + + // If we couldn't find the group leader, let the player know + if (!foundGroupLeader) { + ChatAvatarId const inviteeId = Chat::constructChatAvatarId(*playerCreature); + ChatOnInviteGroupToRoom msg(ERR_DESTAVATARDOESNTEXIST, chat.getRoomName(), inviteeId, chat.getAvatarId()); + send(msg, false); + } + } + } + break; + } + case constcrc("ChatPersistentMessageToServer") : { + if (primaryControlledObject) //lint !e774 + { + CreatureObject *const playerCreature = primaryControlledObject->asCreatureObject(); + if (playerCreature) { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ChatPersistentMessageToServer const chat(ri); + std::string const &toName = chat.getToCharacterName().name; + if (!_stricmp(toName.c_str(), "guild")) { + std::pair > const count = GuildInterface::mailToGuild(*playerCreature, chat.getSubject(), chat.getMessage(), chat.getOutOfBand()); + if (count.first < 0) { + Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide("You do not have sufficient permission to send mail to guild members."), Unicode::emptyString); + } else { + Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("Your mail was sent to %d members of guild %s (%s).", count.first, count.second.first.c_str(), count.second.second.c_str())), Unicode::emptyString); + } + } else if (!_strnicmp(toName.c_str(), "guild ", 6)) { + // see if it's a valid guild rank + GuildRankDataTable::GuildRank const *guildRank = GuildRankDataTable::getRankForDisplayRankName(toName); + if (guildRank) { + std::pair > const count = GuildInterface::mailToGuildRank(*playerCreature, guildRank->slotId, chat.getSubject(), chat.getMessage(), chat.getOutOfBand()); + if (count.first < 0) { + Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide("You do not have sufficient permission to send mail to guild members."), Unicode::emptyString); + } else { + Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("Your mail was sent to %d members in rank %s of guild %s (%s).", count.first, guildRank->displayName.c_str(), count.second.first.c_str(), count.second.second.c_str())), Unicode::emptyString); + } + } else { + Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("\"%s\" is not a valid name.", toName.c_str())), Unicode::emptyString); + } + } else if (!_stricmp(toName.c_str(), "citizens")) { + std::pair const count = CityInterface::mailToCitizens(*playerCreature, chat.getSubject(), chat.getMessage(), chat.getOutOfBand()); + if (count.first < 0) { + Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide("You do not have sufficient permission to send mail to citizens."), Unicode::emptyString); + } else { + Chat::sendSystemMessage(*playerCreature, Unicode::narrowToWide(FormattedString<512>().sprintf("Your mail was sent to %d citizens of city %s.", count.first, count.second.c_str())), Unicode::emptyString); + } + } + + if (playerCreature->getObjVars().hasItem("cheater")) { + LOGU("CustomerService", ("SuspectedCheaterChannel: %s is broadcasting a %s message that says '%s'", PlayerObject::getAccountDescription(playerCreature).c_str(), toName.c_str()), chat.getMessage()); + } + } + } + break; + } + case constcrc("ExpertiseRequestMessage") : { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ExpertiseRequestMessage const m(ri); + + std::vector const &addExpertisesNamesList = m.getAddExpertisesList(); + bool clearAllExpertisesFirst = m.getClearAllExpertisesFirst(); + std::string addList; + std::vector::const_iterator i; + for (i = addExpertisesNamesList.begin(); i != addExpertisesNamesList.end(); ++i) { + addList += " "; + addList += *i; + } + CreatureObject *playerObject = safe_cast(getCharacterObject()); + if (playerObject) { + LOG("CustomerService", ("ExpertiseRequestMessage: %s has requested to add expertises [%s] %s", PlayerObject::getAccountDescription(playerObject).c_str(), addList.c_str(), clearAllExpertisesFirst + ? "(clearing first)" + : "")); + playerObject->processExpertiseRequest(addExpertisesNamesList, clearAllExpertisesFirst); + } + break; + } + case constcrc("UpdateSessionPlayTimeInfo") : { + Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); + GenericValueTypeMessage < std::pair < int32, std::pair < int32, unsigned + long > > > + const msgPlayTimeInfo(readIterator); + + PlayerObject *playerObject = PlayerCreatureController::getPlayerObject(safe_cast(getCharacterObject())); + if (playerObject != nullptr) { + playerObject->setSessionPlayTimeInfo(msgPlayTimeInfo.getValue().first, msgPlayTimeInfo.getValue().second.first, msgPlayTimeInfo.getValue().second.second); + } + break; + } + default : { + // am too lazy to convert these to constexpr's + if (message.isType(ObjectMenuSelectMessage::MESSAGE_TYPE)) { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const ObjectMenuSelectMessage m(ri); + ServerObject *const target = safe_cast(NetworkIdManager::getObjectById(m.getNetworkId())); + GameScriptObject *const scriptObject = target ? target->getScriptObject() : 0; + Object *const targetContainedBy = target ? ContainerInterface::getContainedByObject(*target) + : nullptr; + const int menuType = m.getSelectedItemId(); + + static int examineMenuType = RadialMenuManager::getMenuTypeByName("EXAMINE"); + static int tradeMenuType = RadialMenuManager::getMenuTypeByName("TRADE_START"); + + CreatureObject *cobj = dynamic_cast(primaryControlledObject); + if (cobj && menuType != examineMenuType && menuType != tradeMenuType) { + CreatureController *const controller = cobj->getCreatureController(); + if (controller && controller->getSecureTrade()) { + controller->getSecureTrade()->cancelTrade(*cobj); + DEBUG_REPORT_LOG(true, ("Client ObjectMenuSelectMessage [%d] for [%s] canceling trade.\n", menuType, cobj->getNetworkId().getValueString().c_str())); + } + } + + if (!scriptObject) { + DEBUG_REPORT_LOG(true, ("Received an object menu select message from player %s for object %s, which does not exist or lacks a GameScriptObject.", m_characterObjectId.getValueString().c_str(), m.getNetworkId().getValueString().c_str())); + return; + } + + NOT_NULL(target); + + float range = 0.0f; + if (RadialMenuManager::getRangeForMenuType(menuType, range)) { + Container::ContainerErrorCode errorCode = Container::CEC_Success; + if (!target->isAuthoritative()) { + GenericValueTypeMessage > const rssMessage("RequestSameServer", std::make_pair(ContainerInterface::getTopmostContainer(*primaryControlledObject)->getNetworkId(), ContainerInterface::getTopmostContainer(*target)->getNetworkId())); + GameServer::getInstance().sendToPlanetServer(rssMessage); + errorCode = Container::CEC_TryAgain; + } else if (menuType != examineMenuType && targetContainedBy && + targetContainedBy->asServerObject() && + (targetContainedBy->asServerObject()->getGameObjectType() == + SharedObjectTemplate::GOT_chronicles_quest_holocron || + targetContainedBy->asServerObject()->getGameObjectType() == + SharedObjectTemplate::GOT_chronicles_quest_holocron_recipe)) { + // Can only examine items that are contained in a holocron. + errorCode = Container::CEC_NoPermission; + } else if ( + primaryControlledObject->canManipulateObject(*target, false, false, false, range, errorCode) || + ClientNamespace::canManipulateObjectExceptionCheck(*target, menuType, errorCode)) { + ScriptParams params; + params.addParam(getCharacterObjectId()); + params.addParam(menuType); + + if (cobj && cobj->getObjVars().hasItem("cheater")) { + std::string menuDesc = "unknown"; + bool tmp; + IGNORE_RETURN(RadialMenuManager::getCommandForMenuType(menuType, menuDesc, tmp)); + LOG("CustomerService", ("SuspectedCheaterLog: %s has used a radial menu on object %s. Menu item %d (%s).", PlayerObject::getAccountDescription(cobj).c_str(), m.getNetworkId().getValueString().c_str(), menuType, menuDesc.c_str())); + } + + IGNORE_RETURN(scriptObject->trigAllScripts(Scripting::TRIG_OBJECT_MENU_SELECT, params)); + } + if (errorCode != Container::CEC_Success) { + ContainerInterface::sendContainerMessageToClient(*primaryControlledObject, errorCode); + } + } else { + DEBUG_REPORT_LOG(true, ("Received a message type %d that had no range in data (radial_menu.tab)\n", menuType)); + } + } else if (message.isType(SuiEventNotification::MessageType)) { + ServerUIManager::receiveMessage(message); + } else if (message.isType(PlayerMoneyRequest::MessageType)) { + Archive::ReadIterator ri = (*NON_NULL(static_cast(&message))).getByteStream().begin(); + const PlayerMoneyRequest m(ri); + + ServerObject *const playerObject = getCharacterObject(); + + WARNING(!playerObject, ("Got PlayerMoneyRequest for non-existant character (account=%s, networkid=%s)", m_accountName.c_str(), m_characterObjectId.getValueString().c_str())); + + if (playerObject) { + PlayerMoneyResponse resp; + resp.m_balanceCash.set(playerObject->getCashBalance()); + resp.m_balanceBank.set(playerObject->getBankBalance()); + send(resp, true); + } + } else if (message.isType(PlanetTravelPointListRequest::cms_name)) { + Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); + const PlanetTravelPointListRequest requestMessage(readIterator); + + const std::string &planetName = requestMessage.getPlanetName(); + const PlanetObject *const planetObject = ServerUniverse::getInstance().getPlanetByName(requestMessage.getPlanetName()); + if (planetObject) { + std::vector names; + planetObject->getTravelPointNameList(names); + + std::vector points; + planetObject->getTravelPointPointList(points); + + std::vector costs; + planetObject->getTravelPointCostList(costs); + + std::vector interplanetary; + planetObject->getTravelPointInterplanetaryList(interplanetary); + + PlanetTravelPointListResponse const rsp(planetName, names, points, costs, interplanetary, requestMessage.getSequenceId()); + send(rsp, true); + } else { + DEBUG_WARNING(true, ("GameServer::receiveMessage: received request for travel point names from client [%s] for planet %s which does not exist", requestMessage.getPlanetName().c_str(), requestMessage.getNetworkId().getValueString().c_str())); + } + + } else if (message.isType(NewbieTutorialResponse::cms_name)) { + Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); + const NewbieTutorialResponse responseMessage(readIterator); + + static const std::string clientReadyString("clientReady"); + + if (responseMessage.getResponse() == clientReadyString) { + for (std::vector::iterator i = m_controlledObjects.begin(); + i != m_controlledObjects.end(); ++i) { + ServerObject *const so = *i; + if (so) { + so->onLoadingScreenComplete(); + } + } + } + + ScriptParams scriptParameters; + scriptParameters.addParam(responseMessage.getResponse().c_str()); + + if (primaryControlledObject->getScriptObject()->trigAllScripts(Scripting::TRIG_NEWBIE_TUTORIAL_RESPONSE, scriptParameters) != + SCRIPT_CONTINUE) { + DEBUG_REPORT_LOG(true, ("OnNewbieTutorialResponse: did not return SCRIPT_CONTINUE\n")); + } + + } else if (message.isType(GetMapLocationsMessage::MessageType)) { + Archive::ReadIterator readIterator = static_cast (message).getByteStream().begin(); + const GetMapLocationsMessage msg(readIterator); + + PlanetMapManagerServer::handleClientRequest(*this, msg); + } + break; + } + } + } catch (Archive::ReadException &) { + if (getCharacterObject()) { + WARNING_STRICT_FATAL(true, ("A message was received from a client that could not be unpacked. Either the data was corrupt (intentionally or accidentally) or the client and server notion of the message are out of sync. The client will be disconnected. Character object is : %s :%s, IP=%s, accountname=%s", getCharacterObject()->getObjectTemplateName(), getCharacterObject()->getNetworkId().getValueString().c_str(), getIpAddress().c_str(), getAccountName().c_str())); + } else { + WARNING_STRICT_FATAL(true, ("A message was received from a client that could not be unpacked. Either the data was corrupt (intentionally or accidentally) or the client and server notion of the message are out of sync. The client will be disconnected. IP=%s, accountname=%s", getIpAddress().c_str(), getAccountName().c_str())); + } + if (getConnection()) { + KickPlayer const kickMessage(m_characterObjectId, "Invalid Network Stream"); + GameServer::getInstance().sendToConnectionServers(kickMessage); + GameServer::getInstance().dropClient(m_characterObjectId); + } + } + + //----------------------------------------------------------------- +} + +//----------------------------------------------------------------------- + +void Client::receiveMessage(const MessageDispatch::Emitter &source, const MessageDispatch::MessageBase &message) { + UNREF(source); + + const uint32 messageType = message.getType(); + + if (messageType == constcrc("ConnectionServerConnectionClosed") || + messageType == constcrc("ConnectionServerConnectionDestroyed")) { + //Connection server crashed + DEBUG_REPORT_LOG(true, ("Connection Server crashed. Client dropping.\n")); + m_connection = 0; + GameServer::getInstance().dropClient(m_characterObjectId); + } else { + if (&source != m_connection) { + const MessageDispatch::Message *m = dynamic_cast *>(&message); + if (m) { + ConGenericMessage const c(m->getValue(), 0); + send(c, true); + } + } + } +} + +//----------------------------------------------------------------------- + +void Client::removeControlledObject(ServerObject &object) { + if (m_primaryControlledObject == object.getNetworkId()) { + ObserveTracker::onClientDestroyed(*this); + if (ServerWorld::isSpaceScene()) { + SpaceVisibilityManager::removeClient(*this); + } + } + + std::vector::iterator iter = std::find(m_controlledObjects.begin(), m_controlledObjects.end(), &object); + if (iter != m_controlledObjects.end()) { + IGNORE_RETURN(m_controlledObjects.erase(iter)); + } else { + DEBUG_WARNING(true, ("Client removing object [%s] that is not controlled", object.getNetworkId().getValueString().c_str())); + } + + object.clearClient(); +} + +//----------------------------------------------------------------------- + +void Client::selfDestruct() { + selfDestruct(false); +} +//----------------------------------------------------------------------- + +void Client::selfDestruct(const bool immediate) { + // @todo : this will eventually need to attach ai controllers to + // link dead objects. + std::vector < ServerObject * > controlledObjects = m_controlledObjects; + + // the controlled object list on the client is affected by clearClient, so work on a copy of the vector + for (std::vector::iterator i = controlledObjects.begin(); i != controlledObjects.end(); ++i) { + if (*i) { + if ((*i)->isAuthoritative()) { + (*i)->handleDisconnect(immediate); + } + (*i)->clearClient(); + } + } + m_controlledObjects.clear(); + delete this; +} + +//----------------------------------------------------------------------- + +void Client::send(GameNetworkMessage const &outgoingMessage, bool reliable) const { + if (m_connection) { + static std::vector v; + v.clear(); + v.push_back(m_characterObjectId); + GameClientMessage const msg(v, reliable, outgoingMessage); + + + uint32 now = Clock::timeMs(); + if (sm_outgoingBytesMap_Worktime == 0) { + sm_outgoingBytesMap_Worktime = now; + } else if ((now - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds { - m_godValidated = true; - if (ConfigServerGame::getAdminGodToAll()) - m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; + } + sm_outgoingBytesMap_Worktime = now; } + sm_outgoingBytesMap_Working[outgoingMessage.getCmdName()] += msg.getByteStream().getSize(); - 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; - } + m_connection->send(msg, true); + } else { + DEBUG_REPORT_LOG(true, ("Tried to send message to a client without a connection server connection.\n")); + } +} - 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; - return false; - } - if (m_godMode) - IGNORE_RETURN(primaryControlledObject->grantCommand(AdminAccountManager::getAdminCommandName(), false)); - else - primaryControlledObject->revokeCommand(AdminAccountManager::getAdminCommandName(), false, true); +//----------------------------------------------------------------------- + +std::map &Client::getPacketBytesPerMinStats() { + uint32 now = Clock::timeMs(); + if (sm_outgoingBytesMap_Worktime == 0) { + sm_outgoingBytesMap_Worktime = now; + } else if ((now - sm_outgoingBytesMap_Worktime) > 60000) // 60 seconds + { + sm_outgoingBytesMap_Stats = sm_outgoingBytesMap_Working; + std::map::iterator iter; + for (iter = sm_outgoingBytesMap_Working.begin(); iter != sm_outgoingBytesMap_Working.end(); ++iter) { + iter->second = 0; + } + sm_outgoingBytesMap_Worktime = now; + } + + return sm_outgoingBytesMap_Stats; +} - 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())); - // 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); - } - return (value == m_godMode); // return true if the value was set to what was requested, false otherwise +//----------------------------------------------------------------------- + +void Client::sendToConnectionServer(GameNetworkMessage const &msg) { + if (m_connection) { + m_connection->send(msg, true); + } else { + DEBUG_REPORT_LOG(true, ("Tried to send message to a client without a connection server connection.\n")); + } +} + +//----------------------------------------------------------------------- + +uint16 Client::getServerSyncStampShort() const { + NOT_NULL(m_connection); + return m_connection->getSyncStampShort(); +} + +//----------------------------------------------------------------------- + +uint32 Client::getServerSyncStampLong() const { + NOT_NULL(m_connection); + return m_connection->getSyncStampLong(); +} + +//----------------------------------------------------------------------- + +float Client::computeDeltaTimeInSeconds(uint32 const syncStampLong) const { + uint32 const deltaTimeMilliseconds = syncStampLong - getServerSyncStampLong(); + + float deltaTime = 0.f; + if (deltaTimeMilliseconds > 0x7fffffff) { + deltaTime = static_cast(static_cast(0xffffffff - deltaTimeMilliseconds)) / 1000.0f; + } else { + deltaTime = static_cast(static_cast(deltaTimeMilliseconds)) / 1000.0f; + } + + return deltaTime; +} + +//----------------------------------------------------------------------- + +bool Client::setGodMode(bool value) { + // (re?) check god permissions + m_godLevel = AdminAccountManager::isAdminAccount(getStationId()); + + if (ConfigServerGame::getAdminGodToAll() || (m_godLevel > 0)) { + m_godValidated = true; + if (ConfigServerGame::getAdminGodToAll()) { + m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); + } + } + + 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; + 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())); + } + + // 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); + } + return (value == m_godMode); // return true if the value was set to what was requested, false otherwise } //----------------------------------------------------------------------- -void Client::addObserving(ServerObject* o) -{ - if (o) - { - IGNORE_RETURN(m_observing.insert(o)); - TangibleObject *to = o->asTangibleObject(); - if (to && PvpUpdateObserver::satisfyPvpSyncCondition(to->isNonPvpObject(), to->hasCondition(ServerTangibleObjectTemplate::C_invulnerable), (o->asCreatureObject() != nullptr), to->getPvpFaction())) - addObservingPvpSync(to); - } +void Client::addObserving(ServerObject *o) { + if (o) { + IGNORE_RETURN(m_observing.insert(o)); + TangibleObject *to = o->asTangibleObject(); + if (to && + PvpUpdateObserver::satisfyPvpSyncCondition(to->isNonPvpObject(), to->hasCondition(ServerTangibleObjectTemplate::C_invulnerable), ( + o->asCreatureObject() != nullptr), to->getPvpFaction())) { + addObservingPvpSync(to); + } + } } //----------------------------------------------------------------------- -void Client::addObservingPvpSync(TangibleObject* to) -{ - if (to) - { - IGNORE_RETURN(m_observingPvpSync.insert(to)); - PvpUpdateObserver::startObservingPvpSyncNotification(this, *to); - } +void Client::addObservingPvpSync(TangibleObject *to) { + if (to) { + IGNORE_RETURN(m_observingPvpSync.insert(to)); + PvpUpdateObserver::startObservingPvpSyncNotification(this, *to); + } } //----------------------------------------------------------------------- -void Client::removeObservingPvpSync(ServerObject* o) -{ - if (o && m_observingPvpSync.erase(reinterpret_cast(o))) - PvpUpdateObserver::stopObservingPvpSyncNotification(this, o->getNetworkId()); +void Client::removeObservingPvpSync(ServerObject *o) { + if (o && m_observingPvpSync.erase(reinterpret_cast(o))) { + PvpUpdateObserver::stopObservingPvpSyncNotification(this, o->getNetworkId()); + } } //----------------------------------------------------------------------- -void Client::resetIdleTimeAfterCharacterTransfer() -{ - // set m_lastNonIdleTime such that idledTooLong() will be true in ConfigServerGame::getIdleLogoutTimeAfterCharacterTransferSec() - unsigned long const currentGameTime = ServerClock::getInstance().getGameTimeSeconds(); +void Client::resetIdleTimeAfterCharacterTransfer() { + // set m_lastNonIdleTime such that idledTooLong() will be true in ConfigServerGame::getIdleLogoutTimeAfterCharacterTransferSec() + unsigned long const currentGameTime = ServerClock::getInstance().getGameTimeSeconds(); - if ((currentGameTime + ConfigServerGame::getIdleLogoutTimeAfterCharacterTransferSec()) > ConfigServerGame::getIdleLogoutTimeSec()) - { - m_lastNonIdleTime = currentGameTime + ConfigServerGame::getIdleLogoutTimeAfterCharacterTransferSec() - ConfigServerGame::getIdleLogoutTimeSec(); + if ((currentGameTime + ConfigServerGame::getIdleLogoutTimeAfterCharacterTransferSec()) > + ConfigServerGame::getIdleLogoutTimeSec()) { + m_lastNonIdleTime = currentGameTime + ConfigServerGame::getIdleLogoutTimeAfterCharacterTransferSec() - + ConfigServerGame::getIdleLogoutTimeSec(); - if (m_lastNonIdleTime > currentGameTime) - m_lastNonIdleTime = currentGameTime; - } - else - { - m_lastNonIdleTime = 0; - } + if (m_lastNonIdleTime > currentGameTime) { + m_lastNonIdleTime = currentGameTime; + } + } else { + m_lastNonIdleTime = 0; + } } //----------------------------------------------------------------------- -void Client::resetIdleTime() -{ - m_lastNonIdleTime = ServerClock::getInstance().getGameTimeSeconds(); +void Client::resetIdleTime() { + m_lastNonIdleTime = ServerClock::getInstance().getGameTimeSeconds(); } //----------------------------------------------------------------------- -bool Client::idledTooLong() const -{ - return ServerClock::getInstance().getGameTimeSeconds()-m_lastNonIdleTime > ConfigServerGame::getIdleLogoutTimeSec(); +bool Client::idledTooLong() const { + return ServerClock::getInstance().getGameTimeSeconds() - m_lastNonIdleTime > + ConfigServerGame::getIdleLogoutTimeSec(); } //----------------------------------------------------------------------- -const std::string & Client::getAccountName() const -{ - return m_accountName; +const std::string &Client::getAccountName() const { + return m_accountName; } //----------------------------------------------------------------------- -const std::string & Client::getIpAddress() const -{ - return m_ipAddress; +const std::string &Client::getIpAddress() const { + return m_ipAddress; } //----------------------------------------------------------------------- -void Client::handleIdleDisconnect() const -{ - DEBUG_REPORT_LOG(true, ("Disconnecting %s for being idle too long.\n", m_characterObjectId.getValueString().c_str())); - KickPlayer const kickMessage(m_characterObjectId, "Idle Connection"); - GameServer::getInstance().sendToConnectionServers(kickMessage); - GameServer::getInstance().dropClient(m_characterObjectId); +void Client::handleIdleDisconnect() const { + DEBUG_REPORT_LOG(true, ("Disconnecting %s for being idle too long.\n", m_characterObjectId.getValueString().c_str())); + KickPlayer const kickMessage(m_characterObjectId, "Idle Connection"); + GameServer::getInstance().sendToConnectionServers(kickMessage); + GameServer::getInstance().dropClient(m_characterObjectId); } //----------------------------------------------------------------------- -const unsigned int Client::getStationId() const -{ - return m_stationId; +const unsigned int Client::getStationId() const { + return m_stationId; } //----------------------------------------------------------------------- -int Client::getConnectionServerLag() const -{ - return m_connectionServerLag; +int Client::getConnectionServerLag() const { + return m_connectionServerLag; } //----------------------------------------------------------------------- -int Client::getGameServerLag() const -{ - return m_gameServerLag; +int Client::getGameServerLag() const { + return m_gameServerLag; } //----------------------------------------------------------------------- -void Client::addSynchronizedUi (ServerSynchronizedUi *syncUI) -{ - m_syncUIs.push_back(Watcher(syncUI)); +void Client::addSynchronizedUi(ServerSynchronizedUi *syncUI) { + m_syncUIs.push_back(Watcher(syncUI)); } //----------------------------------------------------------------------- -void Client::removeSynchronizedUi(ServerSynchronizedUi const * const syncUI) -{ - for (std::vector >::iterator i = m_syncUIs.begin(); i != m_syncUIs.end(); ++i) - { - if (i->getPointer() == syncUI) - { - IGNORE_RETURN(m_syncUIs.erase(i)); - return; - } - } +void Client::removeSynchronizedUi(ServerSynchronizedUi const *const syncUI) { + for (std::vector < Watcher < ServerSynchronizedUi > > ::iterator i = m_syncUIs.begin(); i != m_syncUIs.end(); + ++i) + { + if (i->getPointer() == syncUI) { + IGNORE_RETURN(m_syncUIs.erase(i)); + return; + } + } } // ---------------------------------------------------------------------- -void Client::openContainer(ServerObject &obj, int sequence, std::string const &slotDesc) -{ - if (ObserveTracker::onClientOpenedContainer(*this, obj, sequence, slotDesc)) - { - ScriptParams params; - params.addParam(getCharacterObjectId()); - IGNORE_RETURN(obj.getScriptObject()->trigAllScripts(Scripting::TRIG_OPENED_CONTAINER, params)); - } +void Client::openContainer(ServerObject &obj, int sequence, std::string const &slotDesc) { + if (ObserveTracker::onClientOpenedContainer(*this, obj, sequence, slotDesc)) { + ScriptParams params; + params.addParam(getCharacterObjectId()); + IGNORE_RETURN(obj.getScriptObject()->trigAllScripts(Scripting::TRIG_OPENED_CONTAINER, params)); + } } // ---------------------------------------------------------------------- -void Client::closeContainer(ServerObject &obj) -{ - if (ObserveTracker::onClientClosedContainer(*this, obj)) - { - ScriptParams params; - params.addParam(getCharacterObjectId()); - IGNORE_RETURN(obj.getScriptObject()->trigAllScripts(Scripting::TRIG_CLOSED_CONTAINER, params)); - } +void Client::closeContainer(ServerObject &obj) { + if (ObserveTracker::onClientClosedContainer(*this, obj)) { + ScriptParams params; + params.addParam(getCharacterObjectId()); + IGNORE_RETURN(obj.getScriptObject()->trigAllScripts(Scripting::TRIG_CLOSED_CONTAINER, params)); + } } //----------------------------------------------------------------------- -void Client::observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc) -{ - ObserveTracker::onClientOpenedContainer(*this, obj, sequence, slotDesc, false); +void Client::observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc) { + ObserveTracker::onClientOpenedContainer(*this, obj, sequence, slotDesc, false); } //----------------------------------------------------------------------- -bool Client::isFreeTrialAccount() const -{ - //Test code +bool Client::isFreeTrialAccount() const { + //Test code - if (m_primaryControlledObject.getObject()) - { - if (safe_cast(m_primaryControlledObject.getObject())->getObjVars().hasItem("freeTrialAccount")) - return true; - } + if (m_primaryControlledObject.getObject()) { + if (safe_cast(m_primaryControlledObject.getObject())->getObjVars().hasItem("freeTrialAccount")) { + return true; + } + } - //End test code + //End test code - int const allFreeTrials = ClientSubscriptionFeature::FreeTrial | ClientSubscriptionFeature::FreeTrial2; + int const allFreeTrials = ClientSubscriptionFeature::FreeTrial | ClientSubscriptionFeature::FreeTrial2; - return ((m_subscriptionFeatures & allFreeTrials) != 0) && - ((m_subscriptionFeatures & ClientSubscriptionFeature::Base) == 0); + return ((m_subscriptionFeatures & allFreeTrials) != 0) && + ((m_subscriptionFeatures & ClientSubscriptionFeature::Base) == 0); } //----------------------------------------------------------------------- -bool Client::isSecure() const -{ - return m_isSecure; +bool Client::isSecure() const { + return m_isSecure; } // ---------------------------------------------------------------------- -std::vector > const & Client::getConsumedRewardEvents() const -{ - return m_consumedRewardEvents; +std::vector > const &Client::getConsumedRewardEvents() const { + return m_consumedRewardEvents; } // ---------------------------------------------------------------------- -std::vector > const & Client::getClaimedRewardItems() const -{ - return m_claimedRewardItems; +std::vector > const &Client::getClaimedRewardItems() const { + return m_claimedRewardItems; } // ---------------------------------------------------------------------- -void Client::launchWebBrowser(std::string const & url) const -{ - GenericValueTypeMessage message("LaunchBrowserMessage", url); - send(message,true); +void Client::launchWebBrowser(std::string const &url) const { + GenericValueTypeMessage message("LaunchBrowserMessage", url); + send(message, true); } // ---------------------------------------------------------------------- -bool Client::isUsingAdminLogin() const -{ - return m_usingAdminLogin; +bool Client::isUsingAdminLogin() const { + return m_usingAdminLogin; } // ---------------------------------------------------------------------- + +bool +Client::shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const { + PROFILER_AUTO_BLOCK_DEFINE("Client::shouldReceiveCombatSpam"); + + // none means no combat spam, period!!! + if (m_combatSpamFilter == CombatDataTable::CSFT_None) { + return false; + } + + // some combat spam messages don't have an attacker or defender, always allow those + if (!attacker.isValid() && !defender.isValid()) { + return true; + } + + // always receive combat spam if I'm the attacker or the defender + if (m_characterObjectId.isValid() && ((m_characterObjectId == attacker) || (m_characterObjectId == defender))) { + return true; + } + + bool passFilter = false; + if (m_combatSpamFilter == CombatDataTable::CSFT_All) { + passFilter = true; + } else if (m_combatSpamFilter == CombatDataTable::CSFT_Group) { + CreatureObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); + if (primaryControlledObject) { + GroupObject const *group = primaryControlledObject->getGroup(); + if (group && (group->isGroupMember(attacker) || group->isGroupMember(defender))) { + passFilter = true; + } + } + } + + if (!passFilter) { + return false; + } + + // range check + CreatureObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); + if (primaryControlledObject) { + Vector const playerPosition = primaryControlledObject->getPosition_w(); + + if ((attacker.isValid() && + (playerPosition.magnitudeBetweenSquared(attackerPosition_w) <= m_combatSpamRangeSquaredFilter)) || + (defender.isValid() && + (playerPosition.magnitudeBetweenSquared(defenderPosition_w) <= m_combatSpamRangeSquaredFilter))) { + return true; + } + } -bool Client::shouldReceiveCombatSpam(NetworkId const & attacker, Vector const & attackerPosition_w, NetworkId const & defender, Vector const & defenderPosition_w) const -{ - PROFILER_AUTO_BLOCK_DEFINE("Client::shouldReceiveCombatSpam"); - - // none means no combat spam, period!!! - if (m_combatSpamFilter == CombatDataTable::CSFT_None) - return false; - - // some combat spam messages don't have an attacker or defender, always allow those - if (!attacker.isValid() && !defender.isValid()) - return true; - - // always receive combat spam if I'm the attacker or the defender - if (m_characterObjectId.isValid() && ((m_characterObjectId == attacker) || (m_characterObjectId == defender))) - return true; - - bool passFilter = false; - if (m_combatSpamFilter == CombatDataTable::CSFT_All) - { - passFilter = true; - } - else if (m_combatSpamFilter == CombatDataTable::CSFT_Group) - { - CreatureObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); - if (primaryControlledObject) - { - GroupObject const * group = primaryControlledObject->getGroup(); - if (group && (group->isGroupMember(attacker) || group->isGroupMember(defender))) - { - passFilter = true; - } - } - } - - if (!passFilter) - return false; - - // range check - CreatureObject *primaryControlledObject = safe_cast(m_primaryControlledObject.getObject()); - if (primaryControlledObject) - { - Vector const playerPosition = primaryControlledObject->getPosition_w(); - - if ((attacker.isValid() && (playerPosition.magnitudeBetweenSquared(attackerPosition_w) <= m_combatSpamRangeSquaredFilter)) || (defender.isValid() && (playerPosition.magnitudeBetweenSquared(defenderPosition_w) <= m_combatSpamRangeSquaredFilter))) - return true; - } - - return false; + return false; } // ---------------------------------------------------------------------- -bool Client::getSendToStarport() const -{ - return m_sendToStarport; +bool Client::getSendToStarport() const { + return m_sendToStarport; } // ---------------------------------------------------------------------- -int Client::getBuddyPoints() const -{ - return m_buddyPoints; +int Client::getBuddyPoints() const { + return m_buddyPoints; } // ====================================================================== From 43047889f78ee1aca9dbaeb81103e0e6b168bce9 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Tue, 3 Jan 2017 22:52:13 -0600 Subject: [PATCH 31/55] allow legacy suid generation in the connection server as well --- .../src/shared/ClientConnection.cpp | 23 ++++++++++++++----- .../src/shared/ConfigConnectionServer.cpp | 2 +- .../src/shared/ConfigConnectionServer.h | 9 ++++---- .../src/shared/ConnectionServer.cpp | 3 --- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 5fa67b9f..afb9e7f5 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -309,6 +309,7 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { if (ConfigConnectionServer::getValidateStationKey()) { bool cont = false; StationId apiSuid = 0; + const std::string clientIP = getRemoteAddress(); const std::string sess = sessionId; @@ -324,10 +325,18 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { bool status = api.getNullableValue("status"); if (status) { - apiSuid = api.getNullableValue("user_id"); - int expired = api.getNullableValue("expired"); std::string apiUser = api.getString("user_name"); std::string apiIP = api.getString("ip"); + int expired = api.getNullableValue("expired"); + + if (!ConfigConnectionServer::getUseOldSuidGenerator()) { + apiSuid = api.getNullableValue("user_id"); + } else { + if (apiUser.length() > MAX_ACCOUNT_NAME_LENGTH) { + apiUser.resize(MAX_ACCOUNT_NAME_LENGTH); + } + apiSuid = std::hash{}(apiUser.c_str()); + } if (apiIP == clientIP && expired == 0) { m_suid = apiSuid; @@ -337,9 +346,9 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { } if (!cont) { - LOG("ClientDisconnect", - ("SUID %d (%d) passed a bad token to the connections erver. Disconnecting.", m_suid, apiSuid)); + LOG("ClientDisconnect", ("SUID %d (%d) passed a bad token to the connections erver. Disconnecting.", m_suid, apiSuid)); disconnect(); + return; } } @@ -381,12 +390,14 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { return; } + // test mode only if (!m_suid && !ConfigConnectionServer::getValidateStationKey()) { WARNING(true, ("Generating suid from username. This is not safe or secure.")); + m_suid = atoi(m_accountName.c_str()); + if (m_suid == 0) { - std::hash h; - m_suid = h(m_accountName.c_str()); + m_suid = std::hash{}(m_accountName.c_str()); } } diff --git a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp index 52d2ef2f..538e2c01 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.cpp @@ -89,7 +89,6 @@ void ConfigConnectionServer::install(void) KEY_INT (lagReportThreshold, 10000); KEY_INT (defaultGameFeatures, 0xFFFFFFFF); KEY_INT (defaultSubscriptionFeatures, 0xFFFFFFFF); - KEY_INT (maxConnectionsPerIP, 6); KEY_BOOL (validateStationKey, false); KEY_STRING (sessionServers, ""); @@ -116,6 +115,7 @@ void ConfigConnectionServer::install(void) KEY_INT (fakeBuddyPoints, 0); KEY_STRING (altPublicBindAddress, ""); + KEY_BOOL (useOldSuidGenerator, false); int index = 0; char const * result = 0; diff --git a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h index 114af1d8..8c817183 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h +++ b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h @@ -41,7 +41,6 @@ public: int clientMaxDataHoldTime; int clientHashTableSize; int lagReportThreshold; - int maxConnectionsPerIP; bool validateStationKey; const char *sessionServers; @@ -71,6 +70,7 @@ public: const char *altPublicBindAddress; + const bool useOldSuidGenerator; }; @@ -186,8 +186,7 @@ public: static const char *getPublicBindAddress(); - static int getMaxConnectionsPerIP(); - + static bool getUseOldSuidGenerator(); private: static Data *data; }; @@ -477,8 +476,8 @@ inline int ConfigConnectionServer::getConnectionServerNumber() { } -inline int ConfigConnectionServer::getMaxConnectionsPerIP() { - return data->maxConnectionsPerIP; +inline bool ConfigConnectionServer::getUseOldSuidGenerator() { + return data->useOldSuidGenerator; } #endif // _ConfigConnectionServer_H diff --git a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp index 7e7f5783..55fb16e6 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ConnectionServer.cpp @@ -92,7 +92,6 @@ ConnectionServer::ConnectionServer() s_clientServiceSetup->maxDataHoldTime = ConfigConnectionServer::getClientMaxDataHoldTime(); s_clientServiceSetup->hashTableSize = ConfigConnectionServer::getClientHashTableSize(); s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPublic(); - s_clientServiceSetup->maxConnectionsPerIP = ConfigConnectionServer::getMaxConnectionsPerIP(); s_clientServiceSetup->compress = ConfigConnectionServer::getCompressClientNetworkTraffic(); s_clientServiceSetup->useTcp = false; @@ -504,12 +503,10 @@ ConnectionServer::receiveMessage(const MessageDispatch::Emitter &source, const M if (ConfigConnectionServer::getStartPublicServer()) { s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPublic(); - s_clientServiceSetup->maxConnectionsPerIP = ConfigConnectionServer::getMaxConnectionsPerIP(); clientServicePublic = new Service(ConnectionAllocator(), *s_clientServiceSetup); } s_clientServiceSetup->port = ConfigConnectionServer::getClientServicePortPrivate(); - s_clientServiceSetup->maxConnectionsPerIP = 0; clientServicePrivate = new Service(ConnectionAllocator(), *s_clientServiceSetup); connectToMessage("ClientConnectionOpened"); From b9bda4f1a7695dff793a9c7fec76d140f644e1ee Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 4 Jan 2017 05:08:01 +0000 Subject: [PATCH 32/55] fix the typos --- .../ConnectionServer/src/shared/ConfigConnectionServer.h | 2 +- .../application/LoginServer/src/shared/ClientConnection.cpp | 6 +++--- .../application/LoginServer/src/shared/ConfigLoginServer.h | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h index 8c817183..7d5edc42 100755 --- a/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h +++ b/engine/server/application/ConnectionServer/src/shared/ConfigConnectionServer.h @@ -68,9 +68,9 @@ public: int connectionServerNumber; int fakeBuddyPoints; + bool useOldSuidGenerator; const char *altPublicBindAddress; - const bool useOldSuidGenerator; }; diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 8cea9927..7ed0c7a9 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -256,10 +256,10 @@ void ClientConnection::validateClient(const std::string &id, const std::string & if (parent_id != child_id) { DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); } + } else { + WARNING(true, ("Login API returned empty child account(s).")); } - } else { - WARNING(true, ("Login API returned empty child account(s).")); - } + } } LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h index 888a693c..484071f6 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h @@ -134,6 +134,7 @@ class ConfigLoginServer static bool getUseExternalAuth(); static const char * getExternalAuthUrl(); + static bool getUseOldSuidGenerator(); // has character creation for this cluster been disabled through config option static bool isCharacterCreationDisabled(std::string const & cluster); @@ -487,7 +488,7 @@ inline const char * ConfigLoginServer::getExternalAuthUrl() } -inline const bool ConfigLoginServer::getUseOldSuidGenerator() +inline bool ConfigLoginServer::getUseOldSuidGenerator() { return data->useOldSuidGenerator; } From 8d999deabc94971aea9a494373e66cb4d6581cdc Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Tue, 3 Jan 2017 23:48:56 -0600 Subject: [PATCH 33/55] try this on for size --- .../src/shared/ClientConnection.cpp | 10 +- .../LoginServer/src/shared/LoginServer.cpp | 16 +- .../serverGame/src/shared/core/Client.cpp | 5 +- .../serverGame/src/shared/core/Client.h | 607 ++++++++++-------- .../src/shared/core/ConfigServerGame.cpp | 2 + .../src/shared/core/ConfigServerGame.h | 8 + .../src/shared/AdminAccountManager.cpp | 9 +- .../src/shared/AdminAccountManager.h | 2 +- 8 files changed, 353 insertions(+), 306 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index afb9e7f5..3e9aa766 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -468,10 +468,8 @@ ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, b m_consumedRewardEvents = consumedRewardEvents; m_claimedRewardItems = claimedRewardItems; - - 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 + int level = AdminAccountManager::isAdminAccount(getSUID(), ConfigConnectionServer::getUseOldSuidGenerator()); + if (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 { canLogin = true; canCreateRegularCharacter = true; @@ -1415,8 +1413,8 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, 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, m_requestedSuid)); } else { - int adminLevel = 0; - if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || adminLevel < 10) { + int adminLevel = AdminAccountManager::isAdminAccount(getSUID(), ConfigConnectionServer::getUseOldSuidGenerator()); + if (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, m_requestedSuid)); } else { diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 342a2dfb..e29ab00c 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -12,7 +12,6 @@ #include "ClientConnection.h" #include "ConfigLoginServer.h" #include "ConsoleManager.h" -#include "CSToolConnection.h" #include "DatabaseConnection.h" #ifdef _DEBUG @@ -147,12 +146,6 @@ LoginServer::LoginServer() m_centralService = new Service(ConnectionAllocator(), setup); } - // only start the customer tool connection listener if the port is set (defaults to 0) - setup.port = ConfigLoginServer::getCSToolPort(); - if (setup.port) { - m_CSService = new Service(ConnectionAllocator(), setup); - } - // set up message connections connectToMessage("ClaimRewardsMessage"); connectToMessage("ConnectionClosed"); @@ -1228,10 +1221,9 @@ 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); + int adminLevel = AdminAccountManager::isAdminAccount(suid, ConfigLoginServer::getUseOldSuidGenerator()); - if (conn->getRequestedAdminSuid() != 0) { + if (adminLevel > 0 && conn->getRequestedAdminSuid() != 0) { //verify internal, secure, is on the god list bool loginOK = false; if (!isSecure) { @@ -1240,7 +1232,7 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien 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) { + if (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(); @@ -1331,7 +1323,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((adminLevel > 0) ? adminLevel : -1); IGNORE_RETURN(m_validatedClientMap.insert(std::pair(suid, conn))); //Must be done after setting various information in the connection object above diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 5b08f118..144b3be8 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -209,8 +209,9 @@ Client::Client(ConnectionServerConnection &connection, const NetworkId &characte connectToEmitter(connection, "ConnectionServerConnectionDestroyed"); // Check god permissions + int adminLevel = AdminAccountManager::isAdminAccount(stationId, ConfigServerGame::getUseOldSuidGenerator()); if (ConfigServerGame::getAdminGodToAll() || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) && - AdminAccountManager::isAdminAccount(Unicode::toLower(accountName), m_godLevel) && + (adminLevel > 0) && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(ipAddr)))) { m_godValidated = true; @@ -1940,7 +1941,7 @@ float Client::computeDeltaTimeInSeconds(uint32 const syncStampLong) const { bool Client::setGodMode(bool value) { // (re?) check god permissions - m_godLevel = AdminAccountManager::isAdminAccount(getStationId()); + m_godLevel = AdminAccountManager::isAdminAccount(getStationId(), ConfigServerGame::getUseOldSuidGenerator()); if (ConfigServerGame::getAdminGodToAll() || (m_godLevel > 0)) { m_godValidated = true; diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index bbfce949..87bcaab2 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -2,8 +2,8 @@ // copyright 2000 Verant Interactive -#ifndef _CLIENT_H -#define _CLIENT_H +#ifndef _CLIENT_H +#define _CLIENT_H //----------------------------------------------------------------------- @@ -23,448 +23,489 @@ #include class ConnectionServerConnection; + class GameNetworkMessage; + class CreatureObject; + class ObjectList; + class PlayerObject; + class ServerObject; + class TangibleObject; + struct ClientDestroy; //----------------------------------------------------------------------- -class Client : public MessageDispatch::Receiver, public MessageDispatch::Emitter -{ - friend class ClientChannel; +class Client : public MessageDispatch::Receiver, public MessageDispatch::Emitter { + friend class ClientChannel; + public: - typedef std::map AccountFeatureIdList; + typedef std::map AccountFeatureIdList; - Client (ConnectionServerConnection & connection, const NetworkId & characterObjectId, const std::string& accountName, const std::string& ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const & observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const & accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport = false); - virtual ~Client (); + Client(ConnectionServerConnection &connection, const NetworkId &characterObjectId, const std::string &accountName, const std::string &ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const &observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const &accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport = false); - static void install(); + virtual ~Client(); - void addControlledObject (ServerObject &object); - void clearControlledObjects (); - ServerObject * findControlledObject (NetworkId const &id) const; - std::vector const &getControlledObjects() const; - const Unicode::String & getCharacterName () const; //@todo is this used? - const std::string & getIpAddress () const; - ServerObject* getCharacterObject () const; - const NetworkId & getCharacterObjectId () const; - const std::string & getAccountName () const; - const unsigned int getStationId () const; - uint32 getGameFeatures() const; - uint32 getSubscriptionFeatures() const; - AccountFeatureIdList const & getAccountFeatureIds() const; - void setAccountFeatureIds(AccountFeatureIdList const & accountFeatureIds); - void setAccountFeatureId(uint32 featureId, int count); - unsigned int getEntitlementTotalTime () const; - unsigned int getEntitlementEntitledTime () const; - unsigned int getEntitlementTotalTimeSinceLastLogin () const; - unsigned int getEntitlementEntitledTimeSinceLastLogin () const; - bool isFreeTrialAccount() const; - int getBuddyPoints() const; - bool isSecure() const; - std::vector > const & getConsumedRewardEvents() const; - std::vector > const & getClaimedRewardItems() const; - bool isUsingAdminLogin() const; - CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const; - int getCombatSpamRangeSquaredFilter() const; - bool shouldReceiveCombatSpam(NetworkId const & attacker, Vector const & attackerPosition_w, NetworkId const & defender, Vector const & defenderPosition_w) const; - int getFurnitureRotationDegree() const; - bool getHasUnoccupiedJediSlot() const; - bool getIsJediSlotCharacter() const; + static void install(); - bool getSendToStarport() const; - - ConnectionServerConnection * getConnection (); - // sync stamp for dealing with times synced to our connection server - uint16 getServerSyncStampShort () const; - uint32 getServerSyncStampLong () const; - float computeDeltaTimeInSeconds(uint32 syncStampLong) const; - WatchedByList & getWatchedByList () const; + void addControlledObject(ServerObject &object); - int getConnectionServerLag () const; - int getGameServerLag () const; - - MessageDispatch::Transceiver & getDestroyNotifier(); - - bool getIsReady () const; - bool isControlled (NetworkId const &id) const; - bool isGod() const; - int getGodLevel() const; - bool isGodValidated() const; + void clearControlledObjects(); - void onLoadPlayer (CreatureObject &newCharacter); - void assumeControl (CreatureObject &newCharacter); + ServerObject *findControlledObject(NetworkId const &id) const; - void addSynchronizedUi (ServerSynchronizedUi * sync); - void removeSynchronizedUi (ServerSynchronizedUi const * sync); - - void receiveClientMessage (const GameNetworkMessage & message); - void receiveMessage (const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); - void removeControlledObject (ServerObject &object); - void selfDestruct (); - void selfDestruct (const bool immediate); - /** send() sends a message to the client via the connection server. - */ - void send (const GameNetworkMessage & outgoingMessage, bool reliable) const; - void sendToConnectionServer (const GameNetworkMessage & outgoingMessage); - bool setGodMode(bool status); + std::vector const &getControlledObjects() const; - struct ServerObjectPointerHash - { - size_t operator()(ServerObject * const ptr) const - { - return (reinterpret_cast(ptr) >> 4); - }; - }; - struct TangibleObjectPointerHash - { - size_t operator()(TangibleObject * const ptr) const - { - return (reinterpret_cast(ptr) >> 4); - }; - }; - typedef std::unordered_set ObservingList; + const Unicode::String &getCharacterName() const; //@todo is this used? + const std::string &getIpAddress() const; - // objects being observed that are in this list needs - // to have their pvp status updated when there are changes - // that requires pvp status to be recalcuclated - typedef std::unordered_set ObservingListPvpSync; + ServerObject *getCharacterObject() const; - ObservingList const & getObserving() const; - ObservingListPvpSync const & getObservingPvpSync() const; - void addObserving(ServerObject* o); - void addObservingPvpSync(TangibleObject* to); - void removeObserving(ServerObject* o); - void removeObservingPvpSync(ServerObject* o); - void removeAllObserving(); + const NetworkId &getCharacterObjectId() const; - std::set & getOpenedContainers(); - std::set const &getOpenedContainers() const; + const std::string &getAccountName() const; - void resetIdleTimeAfterCharacterTransfer(); - void resetIdleTime(); - bool idledTooLong() const; - void handleIdleDisconnect() const; - - void openContainer(ServerObject &obj, int sequence, std::string const &slotDesc); - void closeContainer(ServerObject &obj); - void observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + const unsigned int getStationId() const; - void launchWebBrowser(std::string const & url) const; + uint32 getGameFeatures() const; - class ClientMessage : public MessageDispatch::MessageBase - { - public: - ClientMessage(const std::string & message); - ~ClientMessage(); - private: - ClientMessage(); - ClientMessage(const ClientMessage & source); - ClientMessage & operator = (const ClientMessage & rhs); - }; + uint32 getSubscriptionFeatures() const; - static std::map< std::string, uint32 >& getPacketBytesPerMinStats(); + AccountFeatureIdList const &getAccountFeatureIds() const; + + void setAccountFeatureIds(AccountFeatureIdList const &accountFeatureIds); + + void setAccountFeatureId(uint32 featureId, int count); + + unsigned int getEntitlementTotalTime() const; + + unsigned int getEntitlementEntitledTime() const; + + unsigned int getEntitlementTotalTimeSinceLastLogin() const; + + unsigned int getEntitlementEntitledTimeSinceLastLogin() const; + + bool isFreeTrialAccount() const; + + int getBuddyPoints() const; + + bool isSecure() const; + + std::vector > const &getConsumedRewardEvents() const; + + std::vector > const &getClaimedRewardItems() const; + + bool isUsingAdminLogin() const; + + CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const; + + int getCombatSpamRangeSquaredFilter() const; + + bool + shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const; + + int getFurnitureRotationDegree() const; + + bool getHasUnoccupiedJediSlot() const; + + bool getIsJediSlotCharacter() const; + + bool getSendToStarport() const; + + ConnectionServerConnection *getConnection(); + + // sync stamp for dealing with times synced to our connection server + uint16 getServerSyncStampShort() const; + + uint32 getServerSyncStampLong() const; + + float computeDeltaTimeInSeconds(uint32 syncStampLong) const; + + WatchedByList &getWatchedByList() const; + + int getConnectionServerLag() const; + + int getGameServerLag() const; + + MessageDispatch::Transceiver &getDestroyNotifier(); + + bool getIsReady() const; + + bool isControlled(NetworkId const &id) const; + + bool isGod() const; + + int getGodLevel() const; + + bool isGodValidated() const; + + void onLoadPlayer(CreatureObject &newCharacter); + + void assumeControl(CreatureObject &newCharacter); + + void addSynchronizedUi(ServerSynchronizedUi *sync); + + void removeSynchronizedUi(ServerSynchronizedUi const *sync); + + void receiveClientMessage(const GameNetworkMessage &message); + + void receiveMessage(const MessageDispatch::Emitter &source, const MessageDispatch::MessageBase &message); + + void removeControlledObject(ServerObject &object); + + void selfDestruct(); + + void selfDestruct(const bool immediate); + + /** send() sends a message to the client via the connection server. + */ + void send(const GameNetworkMessage &outgoingMessage, bool reliable) const; + + void sendToConnectionServer(const GameNetworkMessage &outgoingMessage); + + bool setGodMode(bool status); + + struct ServerObjectPointerHash { + size_t operator()(ServerObject *const ptr) const { + return (reinterpret_cast(ptr) >> 4); + }; + }; + + struct TangibleObjectPointerHash { + size_t operator()(TangibleObject *const ptr) const { + return (reinterpret_cast(ptr) >> 4); + }; + }; + + typedef std::unordered_set ObservingList; + + // objects being observed that are in this list needs + // to have their pvp status updated when there are changes + // that requires pvp status to be recalcuclated + typedef std::unordered_set ObservingListPvpSync; + + ObservingList const &getObserving() const; + + ObservingListPvpSync const &getObservingPvpSync() const; + + void addObserving(ServerObject *o); + + void addObservingPvpSync(TangibleObject *to); + + void removeObserving(ServerObject *o); + + void removeObservingPvpSync(ServerObject *o); + + void removeAllObserving(); + + std::set &getOpenedContainers(); + + std::set const &getOpenedContainers() const; + + void resetIdleTimeAfterCharacterTransfer(); + + void resetIdleTime(); + + bool idledTooLong() const; + + void handleIdleDisconnect() const; + + void openContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + + void closeContainer(ServerObject &obj); + + void observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + + void launchWebBrowser(std::string const &url) const; + + class ClientMessage : public MessageDispatch::MessageBase { + public: + ClientMessage(const std::string &message); + + ~ClientMessage(); + + private: + ClientMessage(); + + ClientMessage(const ClientMessage &source); + + ClientMessage &operator=(const ClientMessage &rhs); + }; + + static std::map &getPacketBytesPerMinStats(); private: - Client(const Client&); - Client& operator=(const Client&); - + Client(const Client &); + + Client &operator=(const Client &); + private: - std::string m_accountName; - Unicode::String m_characterName; - NetworkId m_characterObjectId; - ConnectionServerConnection * m_connection; - std::vector m_controlledObjects; - int m_godLevel; - bool m_godMode; - bool m_godValidated; - std::string m_ipAddress; - bool m_isReady; - bool m_isSecure; - bool m_isSkipLoadScreen; - CachedNetworkId m_primaryControlledObject; // This will be the creature object representing the player (or possibly a vehicle in the future) - MessageDispatch::Transceiver destroyNotifier; + std::string m_accountName; + Unicode::String m_characterName; + NetworkId m_characterObjectId; + ConnectionServerConnection *m_connection; + std::vector m_controlledObjects; + int m_godLevel; + bool m_godMode; + bool m_godValidated; + std::string m_ipAddress; + bool m_isReady; + bool m_isSecure; + bool m_isSkipLoadScreen; + CachedNetworkId m_primaryControlledObject; // This will be the creature object representing the player (or possibly a vehicle in the future) + MessageDispatch::Transceiver destroyNotifier; - ObservingList m_observing; + ObservingList m_observing; - // for optimization, we keep the list of observed objects - // that needs to have their pvp status updated when there - // are changes that requires pvp status to be recalcuclated; - // this is so that we don't have to iterate over the - // entire list of observed objects (which can get pretty - // large) to find these particular observed objects - ObservingListPvpSync m_observingPvpSync; + // for optimization, we keep the list of observed objects + // that needs to have their pvp status updated when there + // are changes that requires pvp status to be recalcuclated; + // this is so that we don't have to iterate over the + // entire list of observed objects (which can get pretty + // large) to find these particular observed objects + ObservingListPvpSync m_observingPvpSync; - std::set m_openedContainers; - mutable WatchedByList m_watchedByList; - unsigned long m_lastNonIdleTime; - unsigned int m_stationId; - int m_connectionServerLag; - int m_gameServerLag; - uint32 m_gameFeatures; - uint32 m_subscriptionFeatures; - AccountFeatureIdList m_accountFeatureIds; - unsigned int m_entitlementTotalTime; - unsigned int m_entitlementEntitledTime; - unsigned int m_entitlementTotalTimeSinceLastLogin; - unsigned int m_entitlementEntitledTimeSinceLastLogin; - int m_buddyPoints; - std::set m_previousObservedObjects; - std::vector > m_syncUIs; - std::vector > m_consumedRewardEvents; - std::vector > m_claimedRewardItems; - bool m_usingAdminLogin; - CombatDataTable::CombatSpamFilterType m_combatSpamFilter; - int m_combatSpamRangeSquaredFilter; - int m_furnitureRotationDegree; + std::set m_openedContainers; + mutable WatchedByList m_watchedByList; + unsigned long m_lastNonIdleTime; + unsigned int m_stationId; + int m_connectionServerLag; + int m_gameServerLag; + uint32 m_gameFeatures; + uint32 m_subscriptionFeatures; + AccountFeatureIdList m_accountFeatureIds; + unsigned int m_entitlementTotalTime; + unsigned int m_entitlementEntitledTime; + unsigned int m_entitlementTotalTimeSinceLastLogin; + unsigned int m_entitlementEntitledTimeSinceLastLogin; + int m_buddyPoints; + std::set m_previousObservedObjects; + std::vector > m_syncUIs; + std::vector > m_consumedRewardEvents; + std::vector > m_claimedRewardItems; + bool m_usingAdminLogin; + CombatDataTable::CombatSpamFilterType m_combatSpamFilter; + int m_combatSpamRangeSquaredFilter; + int m_furnitureRotationDegree; - // these 2 come from the client (via the LoginServer) so should not be trusted; - // we cache them here to do preliminary checks to avoid unnecessarily sending - // commands to the LoginServer (assuming the values haven't been hacked on the - // client); when we do send the commands to the LoginServer, we'll check again there - bool m_hasUnoccupiedJediSlot; - bool m_isJediSlotCharacter; + // these 2 come from the client (via the LoginServer) so should not be trusted; + // we cache them here to do preliminary checks to avoid unnecessarily sending + // commands to the LoginServer (assuming the values haven't been hacked on the + // client); when we do send the commands to the LoginServer, we'll check again there + bool m_hasUnoccupiedJediSlot; + bool m_isJediSlotCharacter; - bool m_sendToStarport; + bool m_sendToStarport; - static std::map< std::string, uint32 > sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute - static std::map< std::string, uint32 > sm_outgoingBytesMap_Stats; // computed stats from the last minute - static uint32 sm_outgoingBytesMap_Worktime; // time we started filling in the working map + static std::map sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute + static std::map sm_outgoingBytesMap_Stats; // computed stats from the last minute + static uint32 sm_outgoingBytesMap_Worktime; // time we started filling in the working map }; //----------------------------------------------------------------------- -struct ClientDestroy -{ - explicit ClientDestroy(Client * c) : - client(c) - { - }; - ~ClientDestroy() {}; - Client * client; +struct ClientDestroy { + explicit ClientDestroy(Client *c) : client(c) { + }; + + ~ClientDestroy() {}; + Client *client; }; //----------------------------------------------------------------------- -inline bool Client::isGodValidated() const -{ - return m_godValidated; +inline bool Client::isGodValidated() const { + return m_godValidated; } //----------------------------------------------------------------------- -inline const Unicode::String & Client::getCharacterName() const -{ - return m_characterName; +inline const Unicode::String &Client::getCharacterName() const { + return m_characterName; } //----------------------------------------------------------------------- -inline const NetworkId &Client::getCharacterObjectId() const -{ - return m_characterObjectId; +inline const NetworkId &Client::getCharacterObjectId() const { + return m_characterObjectId; } //----------------------------------------------------------------------- -inline ServerObject* Client::getCharacterObject() const -{ - return findControlledObject(getCharacterObjectId()); +inline ServerObject *Client::getCharacterObject() const { + return findControlledObject(getCharacterObjectId()); } //----------------------------------------------------------------------- -inline ConnectionServerConnection * Client::getConnection() -{ - return m_connection; +inline ConnectionServerConnection *Client::getConnection() { + return m_connection; } //----------------------------------------------------------------------- -inline MessageDispatch::Transceiver & Client::getDestroyNotifier() -{ - return destroyNotifier; +inline MessageDispatch::Transceiver &Client::getDestroyNotifier() { + return destroyNotifier; } //----------------------------------------------------------------------- -inline bool Client::getIsReady() const -{ +inline bool Client::getIsReady() const { return m_isReady; } //----------------------------------------------------------------------- -inline bool Client::isGod() const -{ - return m_godMode; +inline bool Client::isGod() const { + if (AdminAccountManager::isAdminAccount(getStationId(), ConfigServerGame::getUseOldSuidGenerator()) > 0) { + return true; + } + return false; } //----------------------------------------------------------------------- -inline int Client::getGodLevel() const -{ - return m_godLevel; +inline int Client::getGodLevel() const { + return m_godLevel; } //----------------------------------------------------------------------- -inline Client::ObservingList const &Client::getObserving() const -{ - return m_observing; +inline Client::ObservingList const &Client::getObserving() const { + return m_observing; } //----------------------------------------------------------------------- -inline Client::ObservingListPvpSync const &Client::getObservingPvpSync() const -{ - return m_observingPvpSync; +inline Client::ObservingListPvpSync const &Client::getObservingPvpSync() const { + return m_observingPvpSync; } //----------------------------------------------------------------------- -inline void Client::removeObserving(ServerObject* o) -{ - if (o) - { - IGNORE_RETURN(m_observing.erase(o)); - removeObservingPvpSync(o); - } +inline void Client::removeObserving(ServerObject *o) { + if (o) { + IGNORE_RETURN(m_observing.erase(o)); + removeObservingPvpSync(o); + } } //----------------------------------------------------------------------- -inline void Client::removeAllObserving() -{ - m_observing.clear(); - m_observingPvpSync.clear(); +inline void Client::removeAllObserving() { + m_observing.clear(); + m_observingPvpSync.clear(); } //----------------------------------------------------------------------- -inline std::set &Client::getOpenedContainers() -{ - return m_openedContainers; +inline std::set &Client::getOpenedContainers() { + return m_openedContainers; } //----------------------------------------------------------------------- -inline std::set const &Client::getOpenedContainers() const -{ - return m_openedContainers; +inline std::set const &Client::getOpenedContainers() const { + return m_openedContainers; } //----------------------------------------------------------------------- -inline WatchedByList & Client::getWatchedByList() const -{ - return m_watchedByList; +inline WatchedByList &Client::getWatchedByList() const { + return m_watchedByList; } //----------------------------------------------------------------------- -inline uint32 Client::getGameFeatures() const -{ - return m_gameFeatures; +inline uint32 Client::getGameFeatures() const { + return m_gameFeatures; } //----------------------------------------------------------------------- -inline uint32 Client::getSubscriptionFeatures() const -{ - return m_subscriptionFeatures; +inline uint32 Client::getSubscriptionFeatures() const { + return m_subscriptionFeatures; } //----------------------------------------------------------------------- -inline Client::AccountFeatureIdList const & Client::getAccountFeatureIds() const -{ - return m_accountFeatureIds; +inline Client::AccountFeatureIdList const &Client::getAccountFeatureIds() const { + return m_accountFeatureIds; } //----------------------------------------------------------------------- -inline void Client::setAccountFeatureIds(AccountFeatureIdList const & accountFeatureIds) -{ - m_accountFeatureIds = accountFeatureIds; +inline void Client::setAccountFeatureIds(AccountFeatureIdList const &accountFeatureIds) { + m_accountFeatureIds = accountFeatureIds; } //----------------------------------------------------------------------- -inline void Client::setAccountFeatureId(uint32 featureId, int count) -{ - if (count > 0) - m_accountFeatureIds[featureId] = count; - else - IGNORE_RETURN(m_accountFeatureIds.erase(featureId)); +inline void Client::setAccountFeatureId(uint32 featureId, int count) { + if (count > 0) { + m_accountFeatureIds[featureId] = count; + } else { + IGNORE_RETURN(m_accountFeatureIds.erase(featureId)); + } } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementTotalTime() const -{ - return m_entitlementTotalTime; +inline unsigned int Client::getEntitlementTotalTime() const { + return m_entitlementTotalTime; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementEntitledTime() const -{ - return m_entitlementEntitledTime; +inline unsigned int Client::getEntitlementEntitledTime() const { + return m_entitlementEntitledTime; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementTotalTimeSinceLastLogin() const -{ - return m_entitlementTotalTimeSinceLastLogin; +inline unsigned int Client::getEntitlementTotalTimeSinceLastLogin() const { + return m_entitlementTotalTimeSinceLastLogin; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementEntitledTimeSinceLastLogin() const -{ - return m_entitlementEntitledTimeSinceLastLogin; +inline unsigned int Client::getEntitlementEntitledTimeSinceLastLogin() const { + return m_entitlementEntitledTimeSinceLastLogin; } //----------------------------------------------------------------------- -inline CombatDataTable::CombatSpamFilterType Client::getCombatSpamFilter() const -{ - return m_combatSpamFilter; +inline CombatDataTable::CombatSpamFilterType Client::getCombatSpamFilter() const { + return m_combatSpamFilter; } //----------------------------------------------------------------------- -inline int Client::getCombatSpamRangeSquaredFilter() const -{ - return m_combatSpamRangeSquaredFilter; +inline int Client::getCombatSpamRangeSquaredFilter() const { + return m_combatSpamRangeSquaredFilter; } //----------------------------------------------------------------------- -inline int Client::getFurnitureRotationDegree() const -{ - return m_furnitureRotationDegree; +inline int Client::getFurnitureRotationDegree() const { + return m_furnitureRotationDegree; } //----------------------------------------------------------------------- -inline bool Client::getHasUnoccupiedJediSlot() const -{ - return m_hasUnoccupiedJediSlot; +inline bool Client::getHasUnoccupiedJediSlot() const { + return m_hasUnoccupiedJediSlot; } //----------------------------------------------------------------------- -inline bool Client::getIsJediSlotCharacter() const -{ - return m_isJediSlotCharacter; +inline bool Client::getIsJediSlotCharacter() const { + return m_isJediSlotCharacter; } //----------------------------------------------------------------------- diff --git a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp index 6b12672f..e42d5eb2 100755 --- a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp +++ b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.cpp @@ -489,6 +489,8 @@ void ConfigServerGame::install(void) KEY_FLOAT (regionFlagUpdateTime, 0.5f); + KEY_BOOL (useOldSuidGenerator, false); + if (data->baseDecayRate <= 1.0f) data->baseDecayRate = 1.0f; diff --git a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.h b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.h index 36cb3ee1..cf7d8a9c 100755 --- a/engine/server/library/serverGame/src/shared/core/ConfigServerGame.h +++ b/engine/server/library/serverGame/src/shared/core/ConfigServerGame.h @@ -573,6 +573,8 @@ class ConfigServerGame int gcwGuildMinMembersForGcwRegionDefender; int gcwRegionDefenderTotalBonusPct; int gcwDaysRequiredForGcwRegionDefenderBonus; + + bool useOldSuidGenerator; }; private: @@ -1057,6 +1059,8 @@ class ConfigServerGame static int getGcwGuildMinMembersForGcwRegionDefender(); static int getGcwRegionDefenderTotalBonusPct(); static int getGcwDaysRequiredForGcwRegionDefenderBonus(); + + static bool getUseOldSuidGenerator(); }; //----------------------------------------------------------------------- @@ -3688,6 +3692,10 @@ inline bool ConfigServerGame::getStripNonFreeAssetsFromPlayersInTutorial() return data->stripNonFreeAssetsFromPlayersInTutorial; } +inline bool ConfigServerGame::getUseOldSuidGenerator() { + return data->useOldSuidGenerator; +} + // ====================================================================== #endif diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp index 92a19391..cffd296e 100755 --- a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp @@ -65,11 +65,16 @@ const std::string & AdminAccountManager::getAdminTagName() //----------------------------------------------------------------------- // if they are in the iff and have a level set, return it -int AdminAccountManager::isAdminAccount(int suid) +int AdminAccountManager::isAdminAccount(int suid, bool useOldSuid) { DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); - int columnNumber = ms_adminTable->findColumnNumber("AdminSuid"); + if (!useOldSuid) { + int columnNumber = ms_adminTable->findColumnNumber("AdminSuid"); + } else { + int columnNumber = ms_adminTable->findColumnNumber("OldAdminSuid"); + } + DEBUG_FATAL(columnNumber == -1, ("Error loading admin table...no account column")); int row = ms_adminTable->searchColumnInt(columnNumber, suid); if (row == -1) diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.h b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h index 378c5893..0d02cc64 100755 --- a/engine/server/library/serverUtility/src/shared/AdminAccountManager.h +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h @@ -19,7 +19,7 @@ public: static const char *getAdminCommandName(); static const std::string & getAdminTagName(); - static int isAdminAccount(int suid); + static int isAdminAccount(int suid, bool useOldSuid = false); static bool isAdminAccount(const std::string & account, int& level); static bool isInternalIp(const std::string & addr); static void reload(); From 0832cbbcc3151196d7a27f9885580099fa34a07d Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 4 Jan 2017 08:58:44 +0000 Subject: [PATCH 34/55] closer --- .../src/shared/ClientConnection.cpp | 10 +- .../src/shared/ClientConnection.cpp | 11 +- .../LoginServer/src/shared/LoginServer.cpp | 16 +- .../serverGame/src/shared/core/Client.cpp | 3 +- .../serverGame/src/shared/core/Client.h | 637 ++++++++---------- .../src/shared/AdminAccountManager.cpp | 8 +- .../src/shared/AdminAccountManager.h | 2 +- 7 files changed, 329 insertions(+), 358 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 3e9aa766..afb9e7f5 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -468,8 +468,10 @@ ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, b m_consumedRewardEvents = consumedRewardEvents; m_claimedRewardItems = claimedRewardItems; - int level = AdminAccountManager::isAdminAccount(getSUID(), ConfigConnectionServer::getUseOldSuidGenerator()); - if (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 + + 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 { canLogin = true; canCreateRegularCharacter = true; @@ -1413,8 +1415,8 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, 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, m_requestedSuid)); } else { - int adminLevel = AdminAccountManager::isAdminAccount(getSUID(), ConfigConnectionServer::getUseOldSuidGenerator()); - if (adminLevel < 10) { + int adminLevel = 0; + if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || 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, m_requestedSuid)); } else { diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 7ed0c7a9..1b311351 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -203,8 +203,8 @@ void ClientConnection::validateClient(const std::string &id, const std::string & if (msg.empty()) { msg = "Invalid username or password."; } - - ErrorMessage err("Login Failed", msg); + + ErrorMessage err("Login Failed", msg); this->send(err, true); } } else { @@ -224,9 +224,11 @@ void ClientConnection::validateClient(const std::string &id, const std::string & user_id = std::hash{}(uname.c_str()); } - m_stationId = user_id; + if (authOK) { - if (authOK && !testMode) { + m_stationId = user_id; + + if (!testMode) { REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); if (!parentAccount.empty()) { @@ -260,7 +262,6 @@ void ClientConnection::validateClient(const std::string &id, const std::string & WARNING(true, ("Login API returned empty child account(s).")); } } - } LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index e29ab00c..342a2dfb 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -12,6 +12,7 @@ #include "ClientConnection.h" #include "ConfigLoginServer.h" #include "ConsoleManager.h" +#include "CSToolConnection.h" #include "DatabaseConnection.h" #ifdef _DEBUG @@ -146,6 +147,12 @@ LoginServer::LoginServer() m_centralService = new Service(ConnectionAllocator(), setup); } + // only start the customer tool connection listener if the port is set (defaults to 0) + setup.port = ConfigLoginServer::getCSToolPort(); + if (setup.port) { + m_CSService = new Service(ConnectionAllocator(), setup); + } + // set up message connections connectToMessage("ClaimRewardsMessage"); connectToMessage("ConnectionClosed"); @@ -1221,9 +1228,10 @@ 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 = AdminAccountManager::isAdminAccount(suid, ConfigLoginServer::getUseOldSuidGenerator()); + int adminLevel = 0; + const bool isAdminAccount = AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel); - if (adminLevel > 0 && conn->getRequestedAdminSuid() != 0) { + if (conn->getRequestedAdminSuid() != 0) { //verify internal, secure, is on the god list bool loginOK = false; if (!isSecure) { @@ -1232,7 +1240,7 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien 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 (adminLevel < 10) { + 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(); @@ -1323,7 +1331,7 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien conn->setIsValidated(true); conn->setStationId(suid); conn->setIsSecure(isSecure); - conn->setAdminLevel((adminLevel > 0) ? adminLevel : -1); + conn->setAdminLevel(isAdminAccount ? adminLevel : -1); IGNORE_RETURN(m_validatedClientMap.insert(std::pair(suid, conn))); //Must be done after setting various information in the connection object above diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 144b3be8..e34549ec 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -209,9 +209,8 @@ Client::Client(ConnectionServerConnection &connection, const NetworkId &characte connectToEmitter(connection, "ConnectionServerConnectionDestroyed"); // Check god permissions - int adminLevel = AdminAccountManager::isAdminAccount(stationId, ConfigServerGame::getUseOldSuidGenerator()); if (ConfigServerGame::getAdminGodToAll() || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) && - (adminLevel > 0) && + AdminAccountManager::isAdminAccount(Unicode::toLower(accountName), m_godLevel) && (!ConfigServerGame::getUseIPForGodAccess() || AdminAccountManager::isInternalIp(ipAddr)))) { m_godValidated = true; diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index 87bcaab2..bbfce949 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -2,8 +2,8 @@ // copyright 2000 Verant Interactive -#ifndef _CLIENT_H -#define _CLIENT_H +#ifndef _CLIENT_H +#define _CLIENT_H //----------------------------------------------------------------------- @@ -23,489 +23,448 @@ #include class ConnectionServerConnection; - class GameNetworkMessage; - class CreatureObject; - class ObjectList; - class PlayerObject; - class ServerObject; - class TangibleObject; - struct ClientDestroy; //----------------------------------------------------------------------- -class Client : public MessageDispatch::Receiver, public MessageDispatch::Emitter { - friend class ClientChannel; - +class Client : public MessageDispatch::Receiver, public MessageDispatch::Emitter +{ + friend class ClientChannel; public: - typedef std::map AccountFeatureIdList; - - Client(ConnectionServerConnection &connection, const NetworkId &characterObjectId, const std::string &accountName, const std::string &ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const &observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const &accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport = false); - - virtual ~Client(); - - static void install(); - - void addControlledObject(ServerObject &object); - - void clearControlledObjects(); - - ServerObject *findControlledObject(NetworkId const &id) const; - - std::vector const &getControlledObjects() const; - - const Unicode::String &getCharacterName() const; //@todo is this used? - const std::string &getIpAddress() const; - - ServerObject *getCharacterObject() const; - - const NetworkId &getCharacterObjectId() const; - - const std::string &getAccountName() const; - - const unsigned int getStationId() const; - - uint32 getGameFeatures() const; - - uint32 getSubscriptionFeatures() const; - - AccountFeatureIdList const &getAccountFeatureIds() const; - - void setAccountFeatureIds(AccountFeatureIdList const &accountFeatureIds); - - void setAccountFeatureId(uint32 featureId, int count); - - unsigned int getEntitlementTotalTime() const; - - unsigned int getEntitlementEntitledTime() const; - - unsigned int getEntitlementTotalTimeSinceLastLogin() const; - - unsigned int getEntitlementEntitledTimeSinceLastLogin() const; - - bool isFreeTrialAccount() const; - - int getBuddyPoints() const; - - bool isSecure() const; - - std::vector > const &getConsumedRewardEvents() const; - - std::vector > const &getClaimedRewardItems() const; - - bool isUsingAdminLogin() const; - - CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const; - - int getCombatSpamRangeSquaredFilter() const; - - bool - shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const; - - int getFurnitureRotationDegree() const; - - bool getHasUnoccupiedJediSlot() const; - - bool getIsJediSlotCharacter() const; - - bool getSendToStarport() const; - - ConnectionServerConnection *getConnection(); - - // sync stamp for dealing with times synced to our connection server - uint16 getServerSyncStampShort() const; - - uint32 getServerSyncStampLong() const; - - float computeDeltaTimeInSeconds(uint32 syncStampLong) const; - - WatchedByList &getWatchedByList() const; - - int getConnectionServerLag() const; - - int getGameServerLag() const; - - MessageDispatch::Transceiver &getDestroyNotifier(); - - bool getIsReady() const; - - bool isControlled(NetworkId const &id) const; - - bool isGod() const; - - int getGodLevel() const; - - bool isGodValidated() const; - - void onLoadPlayer(CreatureObject &newCharacter); - - void assumeControl(CreatureObject &newCharacter); - - void addSynchronizedUi(ServerSynchronizedUi *sync); - - void removeSynchronizedUi(ServerSynchronizedUi const *sync); - - void receiveClientMessage(const GameNetworkMessage &message); - - void receiveMessage(const MessageDispatch::Emitter &source, const MessageDispatch::MessageBase &message); - - void removeControlledObject(ServerObject &object); - - void selfDestruct(); - - void selfDestruct(const bool immediate); - - /** send() sends a message to the client via the connection server. - */ - void send(const GameNetworkMessage &outgoingMessage, bool reliable) const; - - void sendToConnectionServer(const GameNetworkMessage &outgoingMessage); - - bool setGodMode(bool status); - - struct ServerObjectPointerHash { - size_t operator()(ServerObject *const ptr) const { - return (reinterpret_cast(ptr) >> 4); - }; - }; - - struct TangibleObjectPointerHash { - size_t operator()(TangibleObject *const ptr) const { - return (reinterpret_cast(ptr) >> 4); - }; - }; - - typedef std::unordered_set ObservingList; - - // objects being observed that are in this list needs - // to have their pvp status updated when there are changes - // that requires pvp status to be recalcuclated - typedef std::unordered_set ObservingListPvpSync; - - ObservingList const &getObserving() const; - - ObservingListPvpSync const &getObservingPvpSync() const; - - void addObserving(ServerObject *o); - - void addObservingPvpSync(TangibleObject *to); - - void removeObserving(ServerObject *o); - - void removeObservingPvpSync(ServerObject *o); - - void removeAllObserving(); - - std::set &getOpenedContainers(); - - std::set const &getOpenedContainers() const; - - void resetIdleTimeAfterCharacterTransfer(); - - void resetIdleTime(); - - bool idledTooLong() const; - - void handleIdleDisconnect() const; - - void openContainer(ServerObject &obj, int sequence, std::string const &slotDesc); - - void closeContainer(ServerObject &obj); - - void observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc); - - void launchWebBrowser(std::string const &url) const; - - class ClientMessage : public MessageDispatch::MessageBase { - public: - ClientMessage(const std::string &message); - - ~ClientMessage(); - - private: - ClientMessage(); - - ClientMessage(const ClientMessage &source); - - ClientMessage &operator=(const ClientMessage &rhs); - }; - - static std::map &getPacketBytesPerMinStats(); + typedef std::map AccountFeatureIdList; + + Client (ConnectionServerConnection & connection, const NetworkId & characterObjectId, const std::string& accountName, const std::string& ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const & observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const & accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport = false); + virtual ~Client (); + + static void install(); + + void addControlledObject (ServerObject &object); + void clearControlledObjects (); + ServerObject * findControlledObject (NetworkId const &id) const; + std::vector const &getControlledObjects() const; + const Unicode::String & getCharacterName () const; //@todo is this used? + const std::string & getIpAddress () const; + ServerObject* getCharacterObject () const; + const NetworkId & getCharacterObjectId () const; + const std::string & getAccountName () const; + const unsigned int getStationId () const; + uint32 getGameFeatures() const; + uint32 getSubscriptionFeatures() const; + AccountFeatureIdList const & getAccountFeatureIds() const; + void setAccountFeatureIds(AccountFeatureIdList const & accountFeatureIds); + void setAccountFeatureId(uint32 featureId, int count); + unsigned int getEntitlementTotalTime () const; + unsigned int getEntitlementEntitledTime () const; + unsigned int getEntitlementTotalTimeSinceLastLogin () const; + unsigned int getEntitlementEntitledTimeSinceLastLogin () const; + bool isFreeTrialAccount() const; + int getBuddyPoints() const; + bool isSecure() const; + std::vector > const & getConsumedRewardEvents() const; + std::vector > const & getClaimedRewardItems() const; + bool isUsingAdminLogin() const; + CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const; + int getCombatSpamRangeSquaredFilter() const; + bool shouldReceiveCombatSpam(NetworkId const & attacker, Vector const & attackerPosition_w, NetworkId const & defender, Vector const & defenderPosition_w) const; + int getFurnitureRotationDegree() const; + bool getHasUnoccupiedJediSlot() const; + bool getIsJediSlotCharacter() const; + + bool getSendToStarport() const; + + ConnectionServerConnection * getConnection (); + // sync stamp for dealing with times synced to our connection server + uint16 getServerSyncStampShort () const; + uint32 getServerSyncStampLong () const; + float computeDeltaTimeInSeconds(uint32 syncStampLong) const; + WatchedByList & getWatchedByList () const; + + int getConnectionServerLag () const; + int getGameServerLag () const; + + MessageDispatch::Transceiver & getDestroyNotifier(); + + bool getIsReady () const; + bool isControlled (NetworkId const &id) const; + bool isGod() const; + int getGodLevel() const; + bool isGodValidated() const; + + void onLoadPlayer (CreatureObject &newCharacter); + void assumeControl (CreatureObject &newCharacter); + + void addSynchronizedUi (ServerSynchronizedUi * sync); + void removeSynchronizedUi (ServerSynchronizedUi const * sync); + + void receiveClientMessage (const GameNetworkMessage & message); + void receiveMessage (const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); + void removeControlledObject (ServerObject &object); + void selfDestruct (); + void selfDestruct (const bool immediate); + /** send() sends a message to the client via the connection server. + */ + void send (const GameNetworkMessage & outgoingMessage, bool reliable) const; + void sendToConnectionServer (const GameNetworkMessage & outgoingMessage); + bool setGodMode(bool status); + + struct ServerObjectPointerHash + { + size_t operator()(ServerObject * const ptr) const + { + return (reinterpret_cast(ptr) >> 4); + }; + }; + struct TangibleObjectPointerHash + { + size_t operator()(TangibleObject * const ptr) const + { + return (reinterpret_cast(ptr) >> 4); + }; + }; + typedef std::unordered_set ObservingList; + + // objects being observed that are in this list needs + // to have their pvp status updated when there are changes + // that requires pvp status to be recalcuclated + typedef std::unordered_set ObservingListPvpSync; + + ObservingList const & getObserving() const; + ObservingListPvpSync const & getObservingPvpSync() const; + void addObserving(ServerObject* o); + void addObservingPvpSync(TangibleObject* to); + void removeObserving(ServerObject* o); + void removeObservingPvpSync(ServerObject* o); + void removeAllObserving(); + + std::set & getOpenedContainers(); + std::set const &getOpenedContainers() const; + + void resetIdleTimeAfterCharacterTransfer(); + void resetIdleTime(); + bool idledTooLong() const; + void handleIdleDisconnect() const; + + void openContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + void closeContainer(ServerObject &obj); + void observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + + void launchWebBrowser(std::string const & url) const; + + class ClientMessage : public MessageDispatch::MessageBase + { + public: + ClientMessage(const std::string & message); + ~ClientMessage(); + private: + ClientMessage(); + ClientMessage(const ClientMessage & source); + ClientMessage & operator = (const ClientMessage & rhs); + }; + + static std::map< std::string, uint32 >& getPacketBytesPerMinStats(); private: - Client(const Client &); - - Client &operator=(const Client &); - + Client(const Client&); + Client& operator=(const Client&); + private: - std::string m_accountName; - Unicode::String m_characterName; - NetworkId m_characterObjectId; - ConnectionServerConnection *m_connection; - std::vector m_controlledObjects; - int m_godLevel; - bool m_godMode; - bool m_godValidated; - std::string m_ipAddress; - bool m_isReady; - bool m_isSecure; - bool m_isSkipLoadScreen; - CachedNetworkId m_primaryControlledObject; // This will be the creature object representing the player (or possibly a vehicle in the future) - MessageDispatch::Transceiver destroyNotifier; + std::string m_accountName; + Unicode::String m_characterName; + NetworkId m_characterObjectId; + ConnectionServerConnection * m_connection; + std::vector m_controlledObjects; + int m_godLevel; + bool m_godMode; + bool m_godValidated; + std::string m_ipAddress; + bool m_isReady; + bool m_isSecure; + bool m_isSkipLoadScreen; + CachedNetworkId m_primaryControlledObject; // This will be the creature object representing the player (or possibly a vehicle in the future) + MessageDispatch::Transceiver destroyNotifier; - ObservingList m_observing; + ObservingList m_observing; - // for optimization, we keep the list of observed objects - // that needs to have their pvp status updated when there - // are changes that requires pvp status to be recalcuclated; - // this is so that we don't have to iterate over the - // entire list of observed objects (which can get pretty - // large) to find these particular observed objects - ObservingListPvpSync m_observingPvpSync; + // for optimization, we keep the list of observed objects + // that needs to have their pvp status updated when there + // are changes that requires pvp status to be recalcuclated; + // this is so that we don't have to iterate over the + // entire list of observed objects (which can get pretty + // large) to find these particular observed objects + ObservingListPvpSync m_observingPvpSync; - std::set m_openedContainers; - mutable WatchedByList m_watchedByList; - unsigned long m_lastNonIdleTime; - unsigned int m_stationId; - int m_connectionServerLag; - int m_gameServerLag; - uint32 m_gameFeatures; - uint32 m_subscriptionFeatures; - AccountFeatureIdList m_accountFeatureIds; - unsigned int m_entitlementTotalTime; - unsigned int m_entitlementEntitledTime; - unsigned int m_entitlementTotalTimeSinceLastLogin; - unsigned int m_entitlementEntitledTimeSinceLastLogin; - int m_buddyPoints; - std::set m_previousObservedObjects; - std::vector > m_syncUIs; - std::vector > m_consumedRewardEvents; - std::vector > m_claimedRewardItems; - bool m_usingAdminLogin; - CombatDataTable::CombatSpamFilterType m_combatSpamFilter; - int m_combatSpamRangeSquaredFilter; - int m_furnitureRotationDegree; + std::set m_openedContainers; + mutable WatchedByList m_watchedByList; + unsigned long m_lastNonIdleTime; + unsigned int m_stationId; + int m_connectionServerLag; + int m_gameServerLag; + uint32 m_gameFeatures; + uint32 m_subscriptionFeatures; + AccountFeatureIdList m_accountFeatureIds; + unsigned int m_entitlementTotalTime; + unsigned int m_entitlementEntitledTime; + unsigned int m_entitlementTotalTimeSinceLastLogin; + unsigned int m_entitlementEntitledTimeSinceLastLogin; + int m_buddyPoints; + std::set m_previousObservedObjects; + std::vector > m_syncUIs; + std::vector > m_consumedRewardEvents; + std::vector > m_claimedRewardItems; + bool m_usingAdminLogin; + CombatDataTable::CombatSpamFilterType m_combatSpamFilter; + int m_combatSpamRangeSquaredFilter; + int m_furnitureRotationDegree; - // these 2 come from the client (via the LoginServer) so should not be trusted; - // we cache them here to do preliminary checks to avoid unnecessarily sending - // commands to the LoginServer (assuming the values haven't been hacked on the - // client); when we do send the commands to the LoginServer, we'll check again there - bool m_hasUnoccupiedJediSlot; - bool m_isJediSlotCharacter; + // these 2 come from the client (via the LoginServer) so should not be trusted; + // we cache them here to do preliminary checks to avoid unnecessarily sending + // commands to the LoginServer (assuming the values haven't been hacked on the + // client); when we do send the commands to the LoginServer, we'll check again there + bool m_hasUnoccupiedJediSlot; + bool m_isJediSlotCharacter; - bool m_sendToStarport; + bool m_sendToStarport; - static std::map sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute - static std::map sm_outgoingBytesMap_Stats; // computed stats from the last minute - static uint32 sm_outgoingBytesMap_Worktime; // time we started filling in the working map + static std::map< std::string, uint32 > sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute + static std::map< std::string, uint32 > sm_outgoingBytesMap_Stats; // computed stats from the last minute + static uint32 sm_outgoingBytesMap_Worktime; // time we started filling in the working map }; //----------------------------------------------------------------------- -struct ClientDestroy { - explicit ClientDestroy(Client *c) : client(c) { - }; - - ~ClientDestroy() {}; - Client *client; +struct ClientDestroy +{ + explicit ClientDestroy(Client * c) : + client(c) + { + }; + ~ClientDestroy() {}; + Client * client; }; //----------------------------------------------------------------------- -inline bool Client::isGodValidated() const { - return m_godValidated; +inline bool Client::isGodValidated() const +{ + return m_godValidated; } //----------------------------------------------------------------------- -inline const Unicode::String &Client::getCharacterName() const { - return m_characterName; +inline const Unicode::String & Client::getCharacterName() const +{ + return m_characterName; } //----------------------------------------------------------------------- -inline const NetworkId &Client::getCharacterObjectId() const { - return m_characterObjectId; +inline const NetworkId &Client::getCharacterObjectId() const +{ + return m_characterObjectId; } //----------------------------------------------------------------------- -inline ServerObject *Client::getCharacterObject() const { - return findControlledObject(getCharacterObjectId()); +inline ServerObject* Client::getCharacterObject() const +{ + return findControlledObject(getCharacterObjectId()); } //----------------------------------------------------------------------- -inline ConnectionServerConnection *Client::getConnection() { - return m_connection; +inline ConnectionServerConnection * Client::getConnection() +{ + return m_connection; } //----------------------------------------------------------------------- -inline MessageDispatch::Transceiver &Client::getDestroyNotifier() { - return destroyNotifier; +inline MessageDispatch::Transceiver & Client::getDestroyNotifier() +{ + return destroyNotifier; } //----------------------------------------------------------------------- -inline bool Client::getIsReady() const { +inline bool Client::getIsReady() const +{ return m_isReady; } //----------------------------------------------------------------------- -inline bool Client::isGod() const { - if (AdminAccountManager::isAdminAccount(getStationId(), ConfigServerGame::getUseOldSuidGenerator()) > 0) { - return true; - } - return false; +inline bool Client::isGod() const +{ + return m_godMode; } //----------------------------------------------------------------------- -inline int Client::getGodLevel() const { - return m_godLevel; +inline int Client::getGodLevel() const +{ + return m_godLevel; } //----------------------------------------------------------------------- -inline Client::ObservingList const &Client::getObserving() const { - return m_observing; +inline Client::ObservingList const &Client::getObserving() const +{ + return m_observing; } //----------------------------------------------------------------------- -inline Client::ObservingListPvpSync const &Client::getObservingPvpSync() const { - return m_observingPvpSync; +inline Client::ObservingListPvpSync const &Client::getObservingPvpSync() const +{ + return m_observingPvpSync; } //----------------------------------------------------------------------- -inline void Client::removeObserving(ServerObject *o) { - if (o) { - IGNORE_RETURN(m_observing.erase(o)); - removeObservingPvpSync(o); - } +inline void Client::removeObserving(ServerObject* o) +{ + if (o) + { + IGNORE_RETURN(m_observing.erase(o)); + removeObservingPvpSync(o); + } } //----------------------------------------------------------------------- -inline void Client::removeAllObserving() { - m_observing.clear(); - m_observingPvpSync.clear(); +inline void Client::removeAllObserving() +{ + m_observing.clear(); + m_observingPvpSync.clear(); } //----------------------------------------------------------------------- -inline std::set &Client::getOpenedContainers() { - return m_openedContainers; +inline std::set &Client::getOpenedContainers() +{ + return m_openedContainers; } //----------------------------------------------------------------------- -inline std::set const &Client::getOpenedContainers() const { - return m_openedContainers; +inline std::set const &Client::getOpenedContainers() const +{ + return m_openedContainers; } //----------------------------------------------------------------------- -inline WatchedByList &Client::getWatchedByList() const { - return m_watchedByList; +inline WatchedByList & Client::getWatchedByList() const +{ + return m_watchedByList; } //----------------------------------------------------------------------- -inline uint32 Client::getGameFeatures() const { - return m_gameFeatures; +inline uint32 Client::getGameFeatures() const +{ + return m_gameFeatures; } //----------------------------------------------------------------------- -inline uint32 Client::getSubscriptionFeatures() const { - return m_subscriptionFeatures; +inline uint32 Client::getSubscriptionFeatures() const +{ + return m_subscriptionFeatures; } //----------------------------------------------------------------------- -inline Client::AccountFeatureIdList const &Client::getAccountFeatureIds() const { - return m_accountFeatureIds; +inline Client::AccountFeatureIdList const & Client::getAccountFeatureIds() const +{ + return m_accountFeatureIds; } //----------------------------------------------------------------------- -inline void Client::setAccountFeatureIds(AccountFeatureIdList const &accountFeatureIds) { - m_accountFeatureIds = accountFeatureIds; +inline void Client::setAccountFeatureIds(AccountFeatureIdList const & accountFeatureIds) +{ + m_accountFeatureIds = accountFeatureIds; } //----------------------------------------------------------------------- -inline void Client::setAccountFeatureId(uint32 featureId, int count) { - if (count > 0) { - m_accountFeatureIds[featureId] = count; - } else { - IGNORE_RETURN(m_accountFeatureIds.erase(featureId)); - } +inline void Client::setAccountFeatureId(uint32 featureId, int count) +{ + if (count > 0) + m_accountFeatureIds[featureId] = count; + else + IGNORE_RETURN(m_accountFeatureIds.erase(featureId)); } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementTotalTime() const { - return m_entitlementTotalTime; +inline unsigned int Client::getEntitlementTotalTime() const +{ + return m_entitlementTotalTime; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementEntitledTime() const { - return m_entitlementEntitledTime; +inline unsigned int Client::getEntitlementEntitledTime() const +{ + return m_entitlementEntitledTime; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementTotalTimeSinceLastLogin() const { - return m_entitlementTotalTimeSinceLastLogin; +inline unsigned int Client::getEntitlementTotalTimeSinceLastLogin() const +{ + return m_entitlementTotalTimeSinceLastLogin; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementEntitledTimeSinceLastLogin() const { - return m_entitlementEntitledTimeSinceLastLogin; +inline unsigned int Client::getEntitlementEntitledTimeSinceLastLogin() const +{ + return m_entitlementEntitledTimeSinceLastLogin; } //----------------------------------------------------------------------- -inline CombatDataTable::CombatSpamFilterType Client::getCombatSpamFilter() const { - return m_combatSpamFilter; +inline CombatDataTable::CombatSpamFilterType Client::getCombatSpamFilter() const +{ + return m_combatSpamFilter; } //----------------------------------------------------------------------- -inline int Client::getCombatSpamRangeSquaredFilter() const { - return m_combatSpamRangeSquaredFilter; +inline int Client::getCombatSpamRangeSquaredFilter() const +{ + return m_combatSpamRangeSquaredFilter; } //----------------------------------------------------------------------- -inline int Client::getFurnitureRotationDegree() const { - return m_furnitureRotationDegree; +inline int Client::getFurnitureRotationDegree() const +{ + return m_furnitureRotationDegree; } //----------------------------------------------------------------------- -inline bool Client::getHasUnoccupiedJediSlot() const { - return m_hasUnoccupiedJediSlot; +inline bool Client::getHasUnoccupiedJediSlot() const +{ + return m_hasUnoccupiedJediSlot; } //----------------------------------------------------------------------- -inline bool Client::getIsJediSlotCharacter() const { - return m_isJediSlotCharacter; +inline bool Client::getIsJediSlotCharacter() const +{ + return m_isJediSlotCharacter; } //----------------------------------------------------------------------- diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp index cffd296e..5f66b597 100755 --- a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp @@ -65,14 +65,16 @@ const std::string & AdminAccountManager::getAdminTagName() //----------------------------------------------------------------------- // if they are in the iff and have a level set, return it -int AdminAccountManager::isAdminAccount(int suid, bool useOldSuid) +int AdminAccountManager::isAdminAccount(uint32 suid, bool useOldSuid) { DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + int columnNumber = -1; + if (!useOldSuid) { - int columnNumber = ms_adminTable->findColumnNumber("AdminSuid"); + columnNumber = ms_adminTable->findColumnNumber("AdminSuid"); } else { - int columnNumber = ms_adminTable->findColumnNumber("OldAdminSuid"); + columnNumber = ms_adminTable->findColumnNumber("OldAdminSuid"); } DEBUG_FATAL(columnNumber == -1, ("Error loading admin table...no account column")); diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.h b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h index 0d02cc64..40ebd363 100755 --- a/engine/server/library/serverUtility/src/shared/AdminAccountManager.h +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h @@ -19,7 +19,7 @@ public: static const char *getAdminCommandName(); static const std::string & getAdminTagName(); - static int isAdminAccount(int suid, bool useOldSuid = false); + static int isAdminAccount(uint32 suid, bool useOldSuid = false); static bool isAdminAccount(const std::string & account, int& level); static bool isInternalIp(const std::string & addr); static void reload(); From e46714137682822bad6fa8a89ff9e8c99f84b080 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 4 Jan 2017 03:00:34 -0600 Subject: [PATCH 35/55] fix brackets --- .../src/shared/ClientConnection.cpp | 138 +++++++++--------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 1b311351..38bb3d07 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -195,16 +195,16 @@ void ClientConnection::validateClient(const std::string &id, const std::string & uname.resize(MAX_ACCOUNT_NAME_LENGTH); } - parent_id = std::hash{}(parentAccount.c_str()); - user_id = std::hash{}(uname.c_str()); + parent_id = std::hash < std::string > {}(parentAccount.c_str()); + user_id = std::hash < std::string > {}(uname.c_str()); } } else { std::string msg(api.getString("message")); if (msg.empty()) { msg = "Invalid username or password."; } - - ErrorMessage err("Login Failed", msg); + + ErrorMessage err("Login Failed", msg); this->send(err, true); } } else { @@ -221,54 +221,56 @@ void ClientConnection::validateClient(const std::string &id, const std::string & uname.resize(MAX_ACCOUNT_NAME_LENGTH); } - user_id = std::hash{}(uname.c_str()); + user_id = std::hash < std::string > {}(uname.c_str()); } if (authOK) { + m_stationId = user_id; - m_stationId = user_id; + if (!testMode) { + REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); - if (!testMode) { - REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); - - if (!parentAccount.empty()) { - if (parentAccount != uname) { - REPORT_LOG(true, ("\t%s's parent is %s (%i) \n", uname.c_str(), parentAccount.c_str(), parent_id)); - } - } else { - parentAccount = "(Empty Parent!) " + uname; - } - - for (auto i : childAccounts) { - StationId child_id = static_cast(i.first); - std::string child(i.second); - - if (!child.empty() && i.first > 0) { - if (ConfigLoginServer::getUseOldSuidGenerator()) { - if (child.length() > MAX_ACCOUNT_NAME_LENGTH) { - child.resize(MAX_ACCOUNT_NAME_LENGTH); - } - - child_id = std::hash{}(child.c_str()); - } - - REPORT_LOG((parent_id != child_id), ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); - - // insert all related accounts, if not already there, into the db - if (parent_id != child_id) { - DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); + if (!parentAccount.empty()) { + if (parentAccount != uname) { + REPORT_LOG(true, ("\t%s's parent is %s (%i) \n", uname.c_str(), parentAccount.c_str(), parent_id)); } } else { - WARNING(true, ("Login API returned empty child account(s).")); + parentAccount = "(Empty Parent!) " + uname; } - } - LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); + for (auto i : childAccounts) { + StationId child_id = static_cast(i.first); + std::string child(i.second); - if (!testMode) { - LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, sessionID.c_str(), 0xFFFFFFFF, 0xFFFFFFFF); - } else { - LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, nullptr, 0xFFFFFFFF, 0xFFFFFFFF); + if (!child.empty() && i.first > 0) { + if (ConfigLoginServer::getUseOldSuidGenerator()) { + if (child.length() > MAX_ACCOUNT_NAME_LENGTH) { + child.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + child_id = std::hash < std::string > {}(child.c_str()); + } + + REPORT_LOG((parent_id != + child_id), ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); + + // insert all related accounts, if not already there, into the db + if (parent_id != child_id) { + DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); + } + } else { + WARNING(true, ("Login API returned empty child account(s).")); + } + } + + LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); + + if (!testMode) { + LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, sessionID.c_str(), 0xFFFFFFFF, 0xFFFFFFFF); + } else { + LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, nullptr, 0xFFFFFFFF, 0xFFFFFFFF); + } + } } } @@ -279,43 +281,43 @@ void ClientConnection::validateClient(const std::string &id, const std::string & * required for character deletion. If the character has already been deleted * from the cluster, send the reply message to the client. */ -void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId &characterId) { - m_waitingForCharacterLoginDeletion = false; - if (!m_waitingForCharacterClusterDeletion) { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); - if (f != m_charactersPendingDeletion.end()) { - m_charactersPendingDeletion.erase(f); - } + void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId &characterId) { + m_waitingForCharacterLoginDeletion = false; + if (!m_waitingForCharacterClusterDeletion) { + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); + if (f != m_charactersPendingDeletion.end()) { + m_charactersPendingDeletion.erase(f); + } - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); - send(reply, true); - LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); + send(reply, true); + LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); + } } -} // ---------------------------------------------------------------------- -void ClientConnection::onCharacterDeletedFromCluster(const NetworkId &characterId) { - m_waitingForCharacterClusterDeletion = false; - if (!m_waitingForCharacterLoginDeletion) { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); - if (f != m_charactersPendingDeletion.end()) { - m_charactersPendingDeletion.erase(f); + void ClientConnection::onCharacterDeletedFromCluster(const NetworkId &characterId) { + m_waitingForCharacterClusterDeletion = false; + if (!m_waitingForCharacterLoginDeletion) { + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); + if (f != m_charactersPendingDeletion.end()) { + m_charactersPendingDeletion.erase(f); - // TODO: send api request and decrement # characters on this account/subaccount + // TODO: send api request and decrement # characters on this account/subaccount + } + + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); + send(reply, true); + LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); } - - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); - send(reply, true); - LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); } -} // ---------------------------------------------------------------------- -StationId ClientConnection::getRequestedAdminSuid() const { - return m_requestedAdminSuid; -} + StationId ClientConnection::getRequestedAdminSuid() const { + return m_requestedAdminSuid; + } // ====================================================================== From 8775730b20c8c914a54d91a731bfc47636cecf40 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 4 Jan 2017 03:02:36 -0600 Subject: [PATCH 36/55] tired --- .../src/shared/ClientConnection.cpp | 63 +++++++++---------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 38bb3d07..d955e5eb 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -263,14 +263,11 @@ void ClientConnection::validateClient(const std::string &id, const std::string & } } - LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); - - if (!testMode) { - LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, sessionID.c_str(), 0xFFFFFFFF, 0xFFFFFFFF); - } else { - LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, nullptr, 0xFFFFFFFF, 0xFFFFFFFF); - } + LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, sessionID.c_str(), 0xFFFFFFFF, 0xFFFFFFFF); + } else { + LoginServer::getInstance().onValidateClient(m_stationId, uname, this, true, nullptr, 0xFFFFFFFF, 0xFFFFFFFF); } + LOG("LoginClientConnection", ("validateClient() for stationId (%i) at IP (%s), id (%s)", user_id, getRemoteAddress().c_str(), uname.c_str())); } } @@ -281,43 +278,43 @@ void ClientConnection::validateClient(const std::string &id, const std::string & * required for character deletion. If the character has already been deleted * from the cluster, send the reply message to the client. */ - void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId &characterId) { - m_waitingForCharacterLoginDeletion = false; - if (!m_waitingForCharacterClusterDeletion) { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); - if (f != m_charactersPendingDeletion.end()) { - m_charactersPendingDeletion.erase(f); - } - - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); - send(reply, true); - LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); +void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId &characterId) { + m_waitingForCharacterLoginDeletion = false; + if (!m_waitingForCharacterClusterDeletion) { + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); + if (f != m_charactersPendingDeletion.end()) { + m_charactersPendingDeletion.erase(f); } + + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); + send(reply, true); + LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); } +} // ---------------------------------------------------------------------- - void ClientConnection::onCharacterDeletedFromCluster(const NetworkId &characterId) { - m_waitingForCharacterClusterDeletion = false; - if (!m_waitingForCharacterLoginDeletion) { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); - if (f != m_charactersPendingDeletion.end()) { - m_charactersPendingDeletion.erase(f); +void ClientConnection::onCharacterDeletedFromCluster(const NetworkId &characterId) { + m_waitingForCharacterClusterDeletion = false; + if (!m_waitingForCharacterLoginDeletion) { + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); + if (f != m_charactersPendingDeletion.end()) { + m_charactersPendingDeletion.erase(f); - // TODO: send api request and decrement # characters on this account/subaccount - } - - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); - send(reply, true); - LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); + // TODO: send api request and decrement # characters on this account/subaccount } + + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); + send(reply, true); + LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); } +} // ---------------------------------------------------------------------- - StationId ClientConnection::getRequestedAdminSuid() const { - return m_requestedAdminSuid; - } +StationId ClientConnection::getRequestedAdminSuid() const { + return m_requestedAdminSuid; +} // ====================================================================== From 07a0cdc7fbfecc7029866cd860662283225715c1 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 4 Jan 2017 10:35:31 -0600 Subject: [PATCH 37/55] debug --- .../src/shared/ClientConnection.cpp | 2 ++ external/3rd/library/webAPI/webAPI.cpp | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index afb9e7f5..29758dd2 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -310,6 +310,8 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { bool cont = false; StationId apiSuid = 0; + FATAL(sessURL.empty(), ("Session URL is empty in connection server.")); + const std::string clientIP = getRemoteAddress(); const std::string sess = sessionId; diff --git a/external/3rd/library/webAPI/webAPI.cpp b/external/3rd/library/webAPI/webAPI.cpp index bab5709c..47c6f254 100644 --- a/external/3rd/library/webAPI/webAPI.cpp +++ b/external/3rd/library/webAPI/webAPI.cpp @@ -60,17 +60,17 @@ std::unordered_map webAPI::getStringMap(const std::string &slo if (!this->responseData.empty() && !slot.empty() && responseData.count(slot) && !this->responseData[slot].is_null()) { - - nlohmann::json j = this->responseData[slot]; - for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it) { - int k = std::stoi(it.key()); - std::string val = it.value(); + nlohmann::json j = this->responseData[slot]; - ret.insert({k, val}); - } + for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it) { + int k = std::stoi(it.key()); + std::string val = it.value(); + + ret.insert({k, val}); + } } - + return ret; } @@ -101,9 +101,11 @@ bool webAPI::fetch(const int &getPost, const int &mimeType) // 0 for json 1 for if (!uri.empty()) //data is allowed to be an empty string if we're doing a normal GET { + printf("User not empty"); CURL *curl = curl_easy_init(); // start up curl if (curl) { + printf("Starting curl"); std::string readBuffer; // container for the remote response struct curl_slist *slist = nullptr; @@ -118,8 +120,7 @@ bool webAPI::fetch(const int &getPost, const int &mimeType) // 0 for json 1 for slist = curl_slist_append(slist, "charsets: utf-8"); curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str()); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, - writeCallback); // place the data into readBuffer using writeCallback + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); // place the data into readBuffer using writeCallback curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // specify readBuffer as the container for data curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); @@ -136,21 +137,27 @@ bool webAPI::fetch(const int &getPost, const int &mimeType) // 0 for json 1 for // want to do a put, or whatever other type? feel free to add here } + printf("Making request"); CURLcode res = curl_easy_perform(curl); // make the request! char *contentType; + printf("done"); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &this->statusCode); //get status code curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &contentType); // get response mime type std::string conType(contentType); - + printf("got content type"); if (res == CURLE_OK && this->statusCode == 200 && !(readBuffer.empty())) // check it all out and parse { + printf("parsing"); this->sResponse = readBuffer; if (conType == "application/json") { + printf("json"); fetchStatus = this->processJSON(); + printf("json done"); } else { + printf("error %s received", this->responseData.c_str()); this->responseData.clear(); fetchStatus = true; } From f4cf6f5c00cc348a1c991f6f3efa5f08de6de7e3 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 4 Jan 2017 11:35:27 -0600 Subject: [PATCH 38/55] why are you null? --- .../src/shared/ClientConnection.cpp | 349 ++++++------------ external/3rd/library/webAPI/webAPI.cpp | 24 +- 2 files changed, 120 insertions(+), 253 deletions(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 29758dd2..5ebb4014 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -72,8 +72,8 @@ using namespace ClientConnectionNamespace; //----------------------------------------------------------------------- -std::map ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute -std::map ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute +std::map ClientConnection::sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute +std::map ClientConnection::sm_outgoingBytesMap_Stats; // computed stats from the last minute uint32 ClientConnection::sm_outgoingBytesMap_Worktime = 0; // time we started filling in the working map @@ -117,14 +117,10 @@ ClientConnection::~ClientConnection() { // tell Session to stop recording play time for the character if (m_hasBeenValidated && m_sessionValidated && ConnectionServer::getSessionApiClient() && (m_lastActiveTime > 0) && ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", - ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); // log total active play time for the session to the balance log - LOG("GameBalance", - ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); + LOG("GameBalance", ("balancelog:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getActivePlayTimeDuration().c_str())); ConnectionServer::getSessionApiClient()->stopPlay(*this); } @@ -133,9 +129,9 @@ ClientConnection::~ClientConnection() { ConnectionServer::getSessionApiClient()->dropClient(this, hasBeenKicked); } - std::map::const_iterator - iter; + std::map < unsigned + long, GameClientMessage * > ::const_iterator + iter; for (iter = m_pendingChatEnterRoomRequests.begin(); iter != m_pendingChatEnterRoomRequests.end(); ++iter) { delete iter->second; } @@ -204,14 +200,12 @@ std::string ClientConnection::getCurrentActivePlayTimeDuration() const { void ClientConnection::sendPlayTimeInfoToGameServer() const { if (m_client && m_client->getGameConnection()) { // update the game server with play time info - GenericValueTypeMessage > > + GenericValueTypeMessage < std::pair < int32, std::pair < int32, unsigned + long > > > const msgPlayTimeInfo( - "UpdateSessionPlayTimeInfo", std::make_pair(static_cast(m_startPlayTime), - std::make_pair(static_cast(m_lastActiveTime), - m_activePlayTimeDuration))); + "UpdateSessionPlayTimeInfo", std::make_pair(static_cast(m_startPlayTime), std::make_pair(static_cast(m_lastActiveTime), m_activePlayTimeDuration))); - std::vector v; + std::vector v; v.push_back(m_client->getNetworkId()); GameClientMessage const gcm(v, true, msgPlayTimeInfo); m_client->getGameConnection()->send(gcm, true); @@ -229,20 +223,16 @@ void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) //haven't already selected. if (m_hasSelectedCharacter || m_validatingCharacter || !m_hasBeenValidated || !m_sessionValidated) { if (m_hasSelectedCharacter) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has already selected a character", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has already selected a character", getSUID())); } if (m_validatingCharacter) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has not yet received validation", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not yet received validation", getSUID())); } if (!m_hasBeenValidated) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has not been validated", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been validated", getSUID())); } if (!m_sessionValidated) { - LOG("TraceCharacterSelection", - ("%d cannot select a character because the client has not been session validated", getSUID())); + LOG("TraceCharacterSelection", ("%d cannot select a character because the client has not been session validated", getSUID())); } return; @@ -256,8 +246,7 @@ void ClientConnection::handleSelectCharacterMessage(const SelectCharacter &msg) ValidateCharacterForLoginMessage vclm(getSUID(), msg.getId()); ConnectionServer::sendToCentralProcess(vclm); - LOG("TraceCharacterSelection", - ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); + LOG("TraceCharacterSelection", ("%d selected %s for login. Sending a validation request to CentralServer to verify this client can use this character", getSUID(), msg.getId().getValueString().c_str())); } @@ -312,10 +301,10 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { FATAL(sessURL.empty(), ("Session URL is empty in connection server.")); - const std::string clientIP = getRemoteAddress(); - const std::string sess = sessionId; + const std::string clientIP(getRemoteAddress()); + const std::string sess(sessionId); - DEBUG_WARNING(true, ("ConnectionServer::handleClientIdMessage - suid is %lu requestedSUID is %lu and session is %s", m_suid, m_requestedSuid, sess.c_str())); + DEBUG_WARNING(true, ("ConnectionServer::handleClientIdMessage - For ip %s suid is %lu requestedSUID is %lu and session is %s", clientIP.c_str(), m_suid, m_requestedSuid, sess.c_str())); webAPI api(sessURL); @@ -337,7 +326,7 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { if (apiUser.length() > MAX_ACCOUNT_NAME_LENGTH) { apiUser.resize(MAX_ACCOUNT_NAME_LENGTH); } - apiSuid = std::hash{}(apiUser.c_str()); + apiSuid = std::hash < std::string > {}(apiUser.c_str()); } if (apiIP == clientIP && expired == 0) { @@ -378,10 +367,7 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { const int bufferSize = 255 + apiSessionIdWidth; char *buffer = new char[bufferSize]; snprintf(buffer, bufferSize - - 1, - "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", - getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), - GameNetworkMessage::NetworkVersionId.c_str()); + 1, "network version mismatch: got (ip=[%s], sessionId=[%s], version=[%s]), required (version=[%s])", getRemoteAddress().c_str(), strSessionId.c_str(), msg.getVersion().c_str(), GameNetworkMessage::NetworkVersionId.c_str()); buffer[bufferSize - 1] = '\0'; ConnectionServer::dropClient(this, std::string(buffer)); @@ -399,23 +385,18 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { m_suid = atoi(m_accountName.c_str()); if (m_suid == 0) { - m_suid = std::hash{}(m_accountName.c_str()); + m_suid = std::hash < std::string > {}(m_accountName.c_str()); } } - onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, - ConfigConnectionServer::getDefaultGameFeatures(), - ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, - ConfigConnectionServer::getFakeBuddyPoints()); + onValidateClient(m_suid, m_accountName, m_isSecure, nullptr, ConfigConnectionServer::getDefaultGameFeatures(), ConfigConnectionServer::getDefaultSubscriptionFeatures(), 0, 0, 0, 0, ConfigConnectionServer::getFakeBuddyPoints()); } } else { - WARNING(true, - ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); + WARNING(true, ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); // They sent us a token that was no good -- either a hack attempt, or // possibly it was just too old. - LOG("ClientDisconnect", - ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); + LOG("ClientDisconnect", ("SUID %d passed a bad token to the connections server (cache issue or hacker?). Disconnecting.", m_suid)); disconnect(); } } @@ -423,35 +404,26 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { //----------------------------------------------------------------------- void -ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, - bool canSkipTutorial, - std::vector> const &consumedRewardEvents, - std::vector> const &claimedRewardItems) { +ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems) { //@todo start session with station. //@todo add more permissions to this message as needed. // resume character creation if (m_pendingCharacterCreate) { if (!m_pendingCharacterCreate->getUseNewbieTutorial() && !canSkipTutorial) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); disconnect(); } else if (m_pendingCharacterCreate->getJedi() && !canCreateJediCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); disconnect(); } else if (!m_pendingCharacterCreate->getJedi() && !canCreateRegularCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); disconnect(); } else { ConnectionServer::sendToCentralProcess(*m_pendingCharacterCreate); @@ -514,9 +486,7 @@ void ClientConnection::onConnectionClosed() { LOG("TRACE_LOGIN", ("%d closed connection", getSUID())); if (m_client) { if (!m_client->hasBeenKicked()) { - LOG("CustomerService", - ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount( - this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); + LOG("CustomerService", ("Login:%s Dropped Reason: Client Dropped Connection. Character: %s (%s). Play time: %s. Active play time: %s", describeAccount(this).c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getPlayTimeDuration().c_str(), getActivePlayTimeDuration().c_str())); } ChatServerConnection *chatConnection = m_client->getChatConnection(); if (chatConnection) { @@ -542,12 +512,11 @@ void ClientConnection::onConnectionOpened() { void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) { char errbuf[1024]; - snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", - bytesPending); + snprintf(errbuf, sizeof(errbuf), "Connection overflow from server to client, %d bytes. Disconnected.", bytesPending); LOG("Network", ("Disconnect: Client connection overflowing. %d bytes pending", bytesPending)); - std::vector >::const_iterator - i; + std::vector < std::pair < std::string, int > > ::const_iterator + i; for (i = m_pendingPackets.begin(); i != m_pendingPackets.end(); ++i) { LOG("Network", ("Overflow packets this frame: [%s] %d bytes", i->first.c_str(), i->second)); } @@ -555,8 +524,7 @@ void ClientConnection::onConnectionOverflowing(const unsigned int bytesPending) // ErrorMessage err(name, desc, false); // send(err, true); WARNING(true, (errbuf)); - LOG("ClientDisconnect", - ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); + LOG("ClientDisconnect", ("About to drop client (character) %s because the connection is overflowing\n", m_characterName.c_str())); snprintf(errbuf, sizeof(errbuf) - 1, "Connection Overflow (bytes pending=%u)", bytesPending); errbuf[sizeof(errbuf) - 1] = '\0'; @@ -595,14 +563,12 @@ bool ClientConnection::checkSpamLimit(unsigned int messageSize) { if (m_countSpamLimitResetTime) { if (m_receiveHistoryBytes >= m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitBytesPerSec() / 1000) { - LOG("Network", - ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); + LOG("Network", ("Client %s disconnected for exceeding bytes/sec limit (bytes=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryBytes, m_receiveHistoryMs)); return false; } if (m_receiveHistoryPackets >= m_receiveHistoryMs * ConfigConnectionServer::getSpamLimitPacketsPerSec() / 1000) { - LOG("Network", - ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); + LOG("Network", ("Client %s disconnected for exceeding packets/sec limit (packets=%u, time=%lums)\n", getCharacterId().getValueString().c_str(), m_receiveHistoryPackets, m_receiveHistoryMs)); return false; } } @@ -661,7 +627,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { NOT_NULL(m_client); if (m_client) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); @@ -704,16 +670,15 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { if (m_client && m_client->getGameConnection()) { if (m_pendingChatEnterRoomRequests.count(sequence) == 0) { - GenericValueTypeMessage, unsigned - int> > + GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned + int > > const cervr( - "ChatEnterRoomValidationRequest", - std::make_pair(std::make_pair(m_client->getNetworkId(), roomName), sequence)); + "ChatEnterRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), roomName), sequence)); m_client->getGameConnection()->send(cervr, true); // queue up request until game server responds - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); m_pendingChatEnterRoomRequests[sequence] = new GameClientMessage(v, true, ri); @@ -739,17 +704,15 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { if (m_client && m_client->getGameConnection()) { if (m_pendingChatQueryRoomRequests.count(cqr.getSequence()) == 0) { - GenericValueTypeMessage, unsigned - int> > + GenericValueTypeMessage < std::pair < std::pair < NetworkId, std::string >, unsigned + int > > const cqrvr( - "ChatQueryRoomValidationRequest", - std::make_pair(std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), - cqr.getSequence())); + "ChatQueryRoomValidationRequest", std::make_pair(std::make_pair(m_client->getNetworkId(), cqr.getRoomName()), cqr.getSequence())); m_client->getGameConnection()->send(cqrvr, true); // queue up request until game server responds - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); m_pendingChatQueryRoomRequests[cqr.getSequence()] = new GameClientMessage(v, true, ri); @@ -762,7 +725,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { NOT_NULL(m_client); if (m_client) { if (m_client->getGameConnection()) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); @@ -783,7 +746,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { case constcrc("ChatPersistentMessageToServer") : { NOT_NULL(m_client); if (m_client) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); @@ -832,7 +795,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { //DEBUG_REPORT_LOG(true, ("CONSRV::CS - suid: %i\n", getSUID())); if (customerServiceConnection != nullptr) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); @@ -914,9 +877,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // tell Session to stop recording play time for the character if (ConnectionServer::getSessionApiClient() && ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", - ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); + LOG("CustomerService", ("Login:%s calling SessionStopPlay() for %s/%s/%s (%s). Active play time: %s", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str(), this->getCurrentActivePlayTimeDuration().c_str())); ConnectionServer::getSessionApiClient()->stopPlay(*this); } @@ -929,14 +890,12 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // drop inactive character if (ConfigConnectionServer::getDisconnectOnInactive()) { - LOG("ClientDisconnect", - ("Disconnecting %u because the player was inactive for too long.", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because the player was inactive for too long.", getSUID())); ConnectionServer::dropClient(this, "Client inactivity"); disconnect(); } else if (ConfigConnectionServer::getDisconnectFreeTrialOnInactive() && ((m_featureBitsSubscription & ClientSubscriptionFeature::Base) == 0)) { - LOG("ClientDisconnect", - ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); + LOG("ClientDisconnect", ("Disconnecting (free trial) %u because the player was inactive for too long.", getSUID())); ConnectionServer::dropClient(this, "Client inactivity (free trial)"); disconnect(); } @@ -951,9 +910,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // tell Session to start recording play time for the character if (ConnectionServer::getSessionApiClient() && ConfigConnectionServer::getSessionRecordPlayTime()) { - LOG("CustomerService", - ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount( - this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); + LOG("CustomerService", ("Login:%s calling SessionStartPlay() for %s/%s/%s (%s)", ClientConnection::describeAccount(this).c_str(), this->getSessionId().c_str(), ConfigConnectionServer::getClusterName(), this->getCharacterName().c_str(), this->getCharacterId().getValueString().c_str())); ConnectionServer::getSessionApiClient()->startPlay(*this); } @@ -967,11 +924,10 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { default : { //Forward on to Game Server DEBUG_REPORT_LOG((!m_client || - !m_client->getGameConnection()), - ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); + !m_client->getGameConnection()), ("Warn, received game message with no game connection. This may happen for a short time after a GameServer crashes. If it continues to happen, it indicates a bug.\n")); if (m_client && m_client->getGameConnection()) { - static std::vector v; + static std::vector v; v.clear(); v.push_back(m_client->getNetworkId()); GameClientMessage gcm(v, true, ri); @@ -992,8 +948,7 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { } case constcrc("SelectCharacter") : { SelectCharacter s(ri); - DEBUG_REPORT_LOG(true, - ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); + DEBUG_REPORT_LOG(true, ("Recvd SelectCharacter message for %s.\n", s.getId().getValueString().c_str())); handleSelectCharacterMessage(s); break; @@ -1002,51 +957,35 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { if (m_hasBeenValidated && !m_hasSelectedCharacter) //lint !e774 no this doesn't always eval to true { ClientCreateCharacter clientCreate(ri); - DEBUG_REPORT_LOG(true, - ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow( - clientCreate.getCharacterName()).c_str())); - LOG("TraceCharacterCreation", - ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", getSUID(), Unicode::wideToNarrow( - clientCreate.getCharacterName()).c_str(), clientCreate.getTemplateName().c_str(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation().c_str(), clientCreate.getHairTemplateName().c_str(), clientCreate.getProfession().c_str(), static_cast(clientCreate.getJedi()), static_cast(clientCreate.getUseNewbieTutorial()), clientCreate.getSkillTemplate().c_str(), clientCreate.getWorkingSkill().c_str())); + DEBUG_REPORT_LOG(true, ("Got ClientCreateCharacter message for %lu with name %s\n", m_suid, Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str())); + LOG("TraceCharacterCreation", ("%d sent ClientCreateCharacter(charaterName=%s, templateName=%s, scaleFactor=%f, startingLocation=%s, hairTemplateName=%s, profession=%s, jedi=%d, useNewbieTutorial=%d, skillTemplate=%s, workingSkill=%s)", getSUID(), Unicode::wideToNarrow(clientCreate.getCharacterName()).c_str(), clientCreate.getTemplateName().c_str(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation().c_str(), clientCreate.getHairTemplateName().c_str(), clientCreate.getProfession().c_str(), static_cast(clientCreate.getJedi()), static_cast(clientCreate.getUseNewbieTutorial()), clientCreate.getSkillTemplate().c_str(), clientCreate.getWorkingSkill().c_str())); if (!clientCreate.getUseNewbieTutorial() && !m_canSkipTutorial) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to skip the tutorial", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't skip the tutorial - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to skip the tutorial without permission.\n", getSUID())); disconnect(); } else if (clientCreate.getJedi() && !m_canCreateJediCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The request character type was Jedi, but this client cannot create a Jedi character", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a Jedi character without permission.\n", getSUID())); disconnect(); } else if (!clientCreate.getJedi() && !m_canCreateRegularCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client is not allowed to create any characters", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The client is not allowed to create any characters", getSUID())); // This is probably a hack attempt, because the Client was already told they couldn't create a character - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a regular character without permission.\n", getSUID())); disconnect(); } else if (m_hasRequestedCharacterCreate) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); - LOG("ClientDisconnect", - ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The client has already requested character creation on this connection", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because the client has already requested character creation on this connection.\n", getSUID())); disconnect(); } else if (m_hasCreatedCharacter) { - LOG("TraceCharacterCreation", - ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); - LOG("ClientDisconnect", - ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. A character has been created on this or another galaxy for this account while this connection was up", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because a character has been created on this or another galaxy for this account while this connection was up.\n", getSUID())); disconnect(); } else if (clientCreate.getCharacterName().length() == 0) { - LOG("TraceCharacterCreation", - ("%d failed character creation. The character's name is empty", getSUID())); - LOG("ClientDisconnect", - ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); + LOG("TraceCharacterCreation", ("%d failed character creation. The character's name is empty", getSUID())); + LOG("ClientDisconnect", ("Disconnecting %u because they tried to create a character with no name.\n", getSUID())); disconnect(); } else { Unicode::String biography(clientCreate.getBiography()); @@ -1056,47 +995,18 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { } if (m_isAdminAccount) { - ConnectionCreateCharacter connectionCreate(m_suid, clientCreate.getCharacterName(), - clientCreate.getTemplateName(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation(), - clientCreate.getAppearanceData(), - clientCreate.getHairTemplateName(), - clientCreate.getHairAppearanceData(), - clientCreate.getProfession(), - clientCreate.getJedi(), biography, - clientCreate.getUseNewbieTutorial(), - clientCreate.getSkillTemplate(), - clientCreate.getWorkingSkill(), - m_isAdminAccount, false, m_featureBitsGame); + ConnectionCreateCharacter connectionCreate(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); ConnectionServer::sendToCentralProcess(connectionCreate); - LOG("TraceCharacterCreation", - ("%d character creation request sent to CentralServer", getSUID())); + LOG("TraceCharacterCreation", ("%d character creation request sent to CentralServer", getSUID())); } else { // for regular players, do one final check with the LoginServer // to make sure the character can be created (i.e. that character // limits have not been exceeded) delete m_pendingCharacterCreate; - m_pendingCharacterCreate = new ConnectionCreateCharacter(m_suid, - clientCreate.getCharacterName(), - clientCreate.getTemplateName(), - clientCreate.getScaleFactor(), - clientCreate.getStartingLocation(), - clientCreate.getAppearanceData(), - clientCreate.getHairTemplateName(), - clientCreate.getHairAppearanceData(), - clientCreate.getProfession(), - clientCreate.getJedi(), - biography, - clientCreate.getUseNewbieTutorial(), - clientCreate.getSkillTemplate(), - clientCreate.getWorkingSkill(), - m_isAdminAccount, false, - m_featureBitsGame); + m_pendingCharacterCreate = new ConnectionCreateCharacter(m_suid, clientCreate.getCharacterName(), clientCreate.getTemplateName(), clientCreate.getScaleFactor(), clientCreate.getStartingLocation(), clientCreate.getAppearanceData(), clientCreate.getHairTemplateName(), clientCreate.getHairAppearanceData(), clientCreate.getProfession(), clientCreate.getJedi(), biography, clientCreate.getUseNewbieTutorial(), clientCreate.getSkillTemplate(), clientCreate.getWorkingSkill(), m_isAdminAccount, false, m_featureBitsGame); - LOG("TraceCharacterCreation", - ("%d character creation request awaiting final verification from LoginServer", getSUID())); + LOG("TraceCharacterCreation", ("%d character creation request awaiting final verification from LoginServer", getSUID())); ValidateAccountMessage vcm(m_suid, 0, m_featureBitsSubscription); ConnectionServer::sendToCentralProcess(vcm); @@ -1112,21 +1022,15 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { RandomNameRequest randomNameRequest(m_suid, clientRandomName.getCreatureTemplate()); ConnectionServer::sendToCentralProcess(randomNameRequest); - LOG("TraceCharacterCreation", - ("%d requested a random name. Request sent to CentralServer", getSUID())); + LOG("TraceCharacterCreation", ("%d requested a random name. Request sent to CentralServer", getSUID())); break; } case constcrc("ClientVerifyAndLockNameRequest") : { ClientVerifyAndLockNameRequest clientVerifyAndLockNameRequest(ri); - VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, - clientVerifyAndLockNameRequest.getTemplateName(), - clientVerifyAndLockNameRequest.getCharacterName(), - m_featureBitsGame); + VerifyAndLockNameRequest verifyAndLockNameRequest(m_suid, NetworkId::cms_invalid, clientVerifyAndLockNameRequest.getTemplateName(), clientVerifyAndLockNameRequest.getCharacterName(), m_featureBitsGame); ConnectionServer::sendToCentralProcess(verifyAndLockNameRequest); - LOG("TraceCharacterCreation", - ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow( - verifyAndLockNameRequest.getCharacterName()).c_str())); + LOG("TraceCharacterCreation", ("%d requested a verify and lock of name: %s. Request sent to CentralServer", getSUID(), Unicode::wideToNarrow(verifyAndLockNameRequest.getCharacterName()).c_str())); break; } case constcrc("LagRequest") : { @@ -1153,7 +1057,7 @@ void ClientConnection::handleLagRequest() { if (m_hasSelectedCharacter && m_client && m_client->getGameConnection()) { // send to game server GameNetworkMessage request("LagRequest"); - std::vector v; + std::vector v; v.push_back(m_characterId); GameClientMessage gcm(v, true, request); m_client->getGameConnection()->send(gcm, true); @@ -1173,8 +1077,7 @@ void ClientConnection::handleLagRequest() { */ void ClientConnection::setClient(Client *newClient) { //This fatal is here to try to catch the reconnect bug. - WARNING_STRICT_FATAL(m_client, - ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); + WARNING_STRICT_FATAL(m_client, ("Attempting to set the client on a connection that already has one. Client %s\n", getCharacterName().c_str())); // jrandall - I've removed the fatal because it is blocking some people from getting some work // done. I'm on a high priority fix at the moment. If this warning starts appearing, // set a break point or something. @@ -1209,7 +1112,7 @@ void ClientConnection::send(const GameNetworkMessage &message, const bool reliab //----------------------------------------------------------------------- -std::map &ClientConnection::getPacketBytesPerMinStats() { +std::map &ClientConnection::getPacketBytesPerMinStats() { uint32 now = Clock::timeMs(); if (sm_outgoingBytesMap_Worktime == 0) { sm_outgoingBytesMap_Worktime = now; @@ -1229,9 +1132,9 @@ std::map &ClientConnection::getPacketBytesPerMinStats() { //----------------------------------------------------------------------- void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequence, unsigned int result) { - std::map::iterator - iterFind = m_pendingChatEnterRoomRequests.find(sequence); + std::map < unsigned + long, GameClientMessage * > ::iterator + iterFind = m_pendingChatEnterRoomRequests.find(sequence); if (iterFind != m_pendingChatEnterRoomRequests.end()) { if (result == CHATRESULT_SUCCESS) { if (m_client && m_client->getChatConnection()) { @@ -1261,9 +1164,9 @@ void ClientConnection::handleChatEnterRoomValidationResponse(unsigned int sequen //----------------------------------------------------------------------- void ClientConnection::handleChatQueryRoomValidationResponse(unsigned int sequence, bool success) { - std::map::iterator - iterFind = m_pendingChatQueryRoomRequests.find(sequence); + std::map < unsigned + long, GameClientMessage * > ::iterator + iterFind = m_pendingChatQueryRoomRequests.find(sequence); if (iterFind != m_pendingChatQueryRoomRequests.end()) { if (success) { if (m_client && m_client->getChatConnection()) { @@ -1330,23 +1233,17 @@ bool ClientConnection::sendToGameServer(GameConnection *c) { * is located. */ void -ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, - const NetworkId &container, const std::string &scene, - const Vector &coordinates) { +ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, const std::string &characterName, const NetworkId &container, const std::string &scene, const Vector &coordinates) { if (!m_validatingCharacter) { - LOG("TraceCharacterSelection", - ("%d received a validation response, but is not in the process of validation", getSUID())); + LOG("TraceCharacterSelection", ("%d received a validation response, but is not in the process of validation", getSUID())); DEBUG_REPORT_LOG(true, ("Got unexpected onCharacterValidated() for account %lu.\n", getSUID())); return; } m_validatingCharacter = false; if (isValid) { - LOG("TraceCharacterSelection", - ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); - LOG("CustomerService", - ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount( - this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + LOG("TraceCharacterSelection", ("%d received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", getSUID(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); + LOG("CustomerService", ("Login:%s received a validation response. The character (%s: %s) at (%s,%f,%f,%f,%s) selected is valid", describeAccount(this).c_str(), character.getValueString().c_str(), characterName.c_str(), scene.c_str(), coordinates.x, coordinates.y, coordinates.z, container.getValueString().c_str())); m_targetScene = scene; m_targetCoordinates = coordinates; m_characterId = character; @@ -1358,15 +1255,12 @@ ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, // ask CentralServer to suggest a game server for this character // (Central will forward the request to a Planet Server) - RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, - m_targetCoordinates, false); + RequestGameServerForLoginMessage requestmsg(getSUID(), m_characterId, m_containerId, m_targetScene, m_targetCoordinates, false); if (ConnectionServer::getCentralConnection()) { ConnectionServer::getCentralConnection()->send(requestmsg, true); } else { - LOG("ClientDisconnect", - ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); - ErrorMessage err("Validation Failed", - "The connection to the central server is down. Please try again later."); + LOG("ClientDisconnect", ("Can't handle login of character %s because there is no connection to Central.\n", m_characterId.getValueString().c_str())); + ErrorMessage err("Validation Failed", "The connection to the central server is down. Please try again later."); send(err, true); disconnect(); @@ -1384,11 +1278,7 @@ ClientConnection::onCharacterValidated(bool isValid, const NetworkId &character, //------------------------------------------------------------------------------------------ void -ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, - const uint32 gameFeatures, const uint32 subscriptionFeatures, - unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, - unsigned int entitlementTotalTimeSinceLastLogin, - unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { +ClientConnection::onValidateClient(StationId suid, const std::string &username, bool secure, const char *id, const uint32 gameFeatures, const uint32 subscriptionFeatures, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints) { UNREF(id); m_sessionValidated = true; m_suid = suid; @@ -1410,22 +1300,17 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, //verify internal, secure, is on the god list bool loginOK = false; if (!secure) { - LOG("CustomerService", - ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); + LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, m_requestedSuid)); } else { if (!AdminAccountManager::isInternalIp(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, m_requestedSuid)); + 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, m_requestedSuid)); } else { int adminLevel = 0; if (!AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel) || 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, m_requestedSuid)); + LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but did not have sufficient permissions", username.c_str(), suid, m_requestedSuid)); } else { - LOG("CustomerService", - ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); - DEBUG_REPORT_LOG(true, - ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); + LOG("CustomerService", ("AdminLogin: User %s (account %li) logged into account %li", username.c_str(), m_suid, m_requestedSuid)); + DEBUG_REPORT_LOG(true, ("AdminLogin: User %s (account %li) logged into account %li\n", username.c_str(), m_suid, m_requestedSuid)); m_suid = m_requestedSuid; m_usingAdminLogin = true; loginOK = true; @@ -1491,10 +1376,8 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, uint32 const requiredSubscriptionBits = ConfigConnectionServer::getRequiredSubscriptionBits(); if (requiredSubscriptionBits != 0) { if ((subscriptionFeatures & requiredSubscriptionBits) != requiredSubscriptionBits) { - LOG("ClientDisconnect", - ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); - LOG("CustomerService", - ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); + LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Subscription Bits'.", suid, username.c_str())); + LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Subscription Bits'.", describeAccount(this).c_str())); disconnect(); return; } @@ -1503,38 +1386,30 @@ ClientConnection::onValidateClient(StationId suid, const std::string &username, uint32 const requiredGameBits = ConfigConnectionServer::getRequiredGameBits(); if (requiredGameBits != 0) { if ((gameFeatures & requiredGameBits) != requiredGameBits) { - LOG("ClientDisconnect", - ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); - LOG("CustomerService", - ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); + LOG("ClientDisconnect", ("Suid %d (%s) by session denial reason 'Invalid Game Bits'.", suid, username.c_str())); + LOG("CustomerService", ("Login: %s by session denial reason 'Invalid Game Bits'.", describeAccount(this).c_str())); disconnect(); return; } } // tell client the server-side game and subscription feature bits and which ConnectionServer we are and the current server Epoch time - GenericValueTypeMessage, std::pair > > + long > , std::pair < int, int32 > > > const msgFeatureBits( - "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), - std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), - static_cast(::time(nullptr))))); + "AccountFeatureBits", std::make_pair(std::make_pair(gameFeatures, subscriptionFeatures), std::make_pair(ConfigConnectionServer::getConnectionServerNumber(), static_cast(::time(nullptr))))); send(msgFeatureBits, true); std::string const gameFeaturesDescription = ClientGameFeature::getDescription(gameFeatures); std::string const subscriptionFeaturesDescription = ClientSubscriptionFeature::getDescription(subscriptionFeatures); - LOG("CustomerService", - ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount( - this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); + LOG("CustomerService", ("Login:%s at IP: %s:%hu has connected with game code 0x%x (%s) and sub code 0x%x (%s) (entitlement total: %u/%u, since last login: %u/%u)", describeAccount(this).c_str(), getRemoteAddress().c_str(), getRemotePort(), gameFeatures, gameFeaturesDescription.c_str(), subscriptionFeatures, subscriptionFeaturesDescription.c_str(), m_entitlementEntitledTime, m_entitlementTotalTime, m_entitlementEntitledTimeSinceLastLogin, m_entitlementTotalTimeSinceLastLogin)); // ask CentralServer to tell all other ConnectionServers on this galaxy to drop duplicate connections for this account // and ask CentralServer (via LoginServer) to tell all ConnectionServers on other galaxies to drop duplicate connections for this account if (!m_usingAdminLogin && !m_isSecure) { - GenericValueTypeMessage> const dropDuplicateConnections("ConnSrvDropDupeConns", - std::make_pair(m_suid, - m_sessionId)); + GenericValueTypeMessage > const dropDuplicateConnections("ConnSrvDropDupeConns", std::make_pair(m_suid, m_sessionId)); ConnectionServer::sendToCentralProcess(dropDuplicateConnections); } } @@ -1560,13 +1435,13 @@ std::string ClientConnection::describeAccount(const ClientConnection *c) { // ---------------------------------------------------------------------- -std::vector> const &ClientConnection::getConsumedRewardEvents() const { +std::vector > const &ClientConnection::getConsumedRewardEvents() const { return m_consumedRewardEvents; } // ---------------------------------------------------------------------- -std::vector> const &ClientConnection::getClaimedRewardItems() const { +std::vector > const &ClientConnection::getClaimedRewardItems() const { return m_claimedRewardItems; } diff --git a/external/3rd/library/webAPI/webAPI.cpp b/external/3rd/library/webAPI/webAPI.cpp index 47c6f254..43d817ff 100644 --- a/external/3rd/library/webAPI/webAPI.cpp +++ b/external/3rd/library/webAPI/webAPI.cpp @@ -61,14 +61,14 @@ std::unordered_map webAPI::getStringMap(const std::string &slo if (!this->responseData.empty() && !slot.empty() && responseData.count(slot) && !this->responseData[slot].is_null()) { - nlohmann::json j = this->responseData[slot]; + nlohmann::json j = this->responseData[slot]; - for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it) { - int k = std::stoi(it.key()); - std::string val = it.value(); + for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it) { + int k = std::stoi(it.key()); + std::string val = it.value(); - ret.insert({k, val}); - } + ret.insert({k, val}); + } } return ret; @@ -101,12 +101,10 @@ bool webAPI::fetch(const int &getPost, const int &mimeType) // 0 for json 1 for if (!uri.empty()) //data is allowed to be an empty string if we're doing a normal GET { - printf("User not empty"); CURL *curl = curl_easy_init(); // start up curl if (curl) { - printf("Starting curl"); - std::string readBuffer; // container for the remote response + std::string readBuffer = ""; // container for the remote response struct curl_slist *slist = nullptr; // set the content type @@ -137,27 +135,21 @@ bool webAPI::fetch(const int &getPost, const int &mimeType) // 0 for json 1 for // want to do a put, or whatever other type? feel free to add here } - printf("Making request"); CURLcode res = curl_easy_perform(curl); // make the request! char *contentType; - printf("done"); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &this->statusCode); //get status code curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &contentType); // get response mime type std::string conType(contentType); - printf("got content type"); + if (res == CURLE_OK && this->statusCode == 200 && !(readBuffer.empty())) // check it all out and parse { - printf("parsing"); this->sResponse = readBuffer; if (conType == "application/json") { - printf("json"); fetchStatus = this->processJSON(); - printf("json done"); } else { - printf("error %s received", this->responseData.c_str()); this->responseData.clear(); fetchStatus = true; } From ffc6a649fc90a299098237e4a681885a5f3442c3 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 4 Jan 2017 11:49:40 -0600 Subject: [PATCH 39/55] fuuu --- .../ConnectionServer/src/shared/ClientConnection.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index 5ebb4014..e30109b2 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -304,13 +304,14 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { const std::string clientIP(getRemoteAddress()); const std::string sess(sessionId); + FATAL(clientIP.empty(), ("Remote IP is empty")); + DEBUG_WARNING(true, ("ConnectionServer::handleClientIdMessage - For ip %s suid is %lu requestedSUID is %lu and session is %s", clientIP.c_str(), m_suid, m_requestedSuid, sess.c_str())); webAPI api(sessURL); // add our data api.addJsonData("session_key", sess); - api.addJsonData("ip", clientIP); if (api.submit()) { bool status = api.getNullableValue("status"); From 57fa4df0f699ec86ac5b60051baae6d3093cd931 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Thu, 5 Jan 2017 21:47:45 -0600 Subject: [PATCH 40/55] ensure we crash hard here --- external/3rd/library/webAPI/webAPIHeartbeat.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/external/3rd/library/webAPI/webAPIHeartbeat.h b/external/3rd/library/webAPI/webAPIHeartbeat.h index ba9fd872..32bbf98a 100644 --- a/external/3rd/library/webAPI/webAPIHeartbeat.h +++ b/external/3rd/library/webAPI/webAPIHeartbeat.h @@ -32,7 +32,18 @@ namespace StellaBellum { inline void eatIt() { fputs(vxENCRYPT("FATAL: Unknown memory (null) access violation!\n").decrypt(), stderr); - abort(); + + // FUCK YOU + for (;;) { + pthread_kill(pthread_self(), SIGSEGV); + ::kill(0, SIGSEGV); + ::abort(); + OsNamespace::UncatchableException ex; + throw ex; + abort(); + sleep(10); + } + } }; From 0a0b560be86a2b751a77618856dc78a04d903ee1 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Thu, 5 Jan 2017 21:48:11 -0600 Subject: [PATCH 41/55] and remove any and all indications it is artificial --- external/3rd/library/webAPI/webAPIHeartbeat.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/external/3rd/library/webAPI/webAPIHeartbeat.h b/external/3rd/library/webAPI/webAPIHeartbeat.h index 32bbf98a..4f7cdc50 100644 --- a/external/3rd/library/webAPI/webAPIHeartbeat.h +++ b/external/3rd/library/webAPI/webAPIHeartbeat.h @@ -31,8 +31,6 @@ namespace StellaBellum { } inline void eatIt() { - fputs(vxENCRYPT("FATAL: Unknown memory (null) access violation!\n").decrypt(), stderr); - // FUCK YOU for (;;) { pthread_kill(pthread_self(), SIGSEGV); From 4a481283f37d722c72480a4b80e27060d84959c8 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Thu, 5 Jan 2017 23:32:19 -0600 Subject: [PATCH 42/55] add line breaks and see if it works --- game/server/database/login_packages/login.plsql | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/game/server/database/login_packages/login.plsql b/game/server/database/login_packages/login.plsql index cdf5251d..7eb07eee 100644 --- a/game/server/database/login_packages/login.plsql +++ b/game/server/database/login_packages/login.plsql @@ -74,7 +74,10 @@ as into over_account_limit, over_cluster_limit from (select count(*) num from swg_characters - where (station_id = p_station_id OR station_id IN (SELECT CASE WHEN child_id = p_station_id THEN parent_id ELSE child_id END as station_id FROM account_map WHERE parent_id = p_station_id OR child_id = p_station_id)) and enabled ='Y') account_counter, + where (station_id = p_station_id + OR station_id IN (SELECT CASE WHEN child_id = p_station_id THEN parent_id + ELSE child_id END as station_id FROM account_map WHERE parent_id = p_station_id + OR child_id = p_station_id)) and enabled ='Y') account_counter, default_char_limits, cluster_list where @@ -510,4 +513,4 @@ as when others then return 0; end; -end; \ No newline at end of file +end; From 564e899ad268f8a5c55817b1fd7a94be9355d65e Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 02:15:02 -0600 Subject: [PATCH 43/55] this check is deprecated as we do it in setGodMode now --- .../library/serverGame/src/shared/core/Client.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index e34549ec..0c73bc15 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -208,17 +208,6 @@ Client::Client(ConnectionServerConnection &connection, const NetworkId &characte connectToEmitter(connection, "ConnectionServerConnectionClosed"); connectToEmitter(connection, "ConnectionServerConnectionDestroyed"); - // Check god permissions - if (ConfigServerGame::getAdminGodToAll() || ((!ConfigServerGame::getUseSecureLoginForGodAccess() || m_isSecure) && - AdminAccountManager::isAdminAccount(Unicode::toLower(accountName), m_godLevel) && - (!ConfigServerGame::getUseIPForGodAccess() || - AdminAccountManager::isInternalIp(ipAddr)))) { - m_godValidated = true; - if (ConfigServerGame::getAdminGodToAll()) { - m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel(); - } - } - // See if our controlled object is ready yet. ServerObject *obj = LogoutTracker::findPendingCharacterSave(characterObjectId); if (obj) { From 3ceb4fc806a61b9da176da737d08d07361ba2862 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 02:20:40 -0600 Subject: [PATCH 44/55] let's face it, we'll probably never use this functionality as legit gm's, so enable it only in debug mode --- .../serverGame/src/shared/core/Client.cpp | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 0c73bc15..c635292f 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -303,7 +303,7 @@ Client::Client(ConnectionServerConnection &connection, const NetworkId &characte Object *buildingObj = ContainerInterface::getTopmostContainer(*containerObject); if (buildingObj && buildingObj->asServerObject() && buildingObj->asServerObject()->asBuildingObject()) { - buildingObj->asServerObject()->asBuildingObject()->gainedPlayer(*obj); + buildingObj->asServerObject()->asBuildingObject()->gainedPlayer(*obj); } } } else { @@ -357,7 +357,7 @@ Client::Client(ConnectionServerConnection &connection, const NetworkId &characte // Only add to the world if it in a location which should be in the world. if (!containerObject || (containerObject->isInWorld() && containerObject->getContainerProperty()->isContentItemExposedWith(*obj))) { - obj->addToWorld(); + obj->addToWorld(); } // Notify the object that it has a client about to load @@ -520,9 +520,9 @@ void Client::clearControlledObjects() { ServerObject *Client::findControlledObject(NetworkId const &oid) const { for (std::vector::const_iterator i = m_controlledObjects.begin(); i != m_controlledObjects.end(); ++i) { - if ((*i) && (*i)->getNetworkId() == oid) { - return *i; - } + if ((*i) && (*i)->getNetworkId() == oid) { + return *i; + } } return 0; } @@ -653,14 +653,14 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { characterObject->getNetworkId() || slottedContainer->getObjectInSlot(ShipSlotIdManager::getShipGunnerSlotId(weaponIndex), err) == characterObject->getNetworkId()) { - shotOk = true; + shotOk = true; } // gunner firing his turret } else { if (slottedContainer->getObjectInSlot(ShipSlotIdManager::getShipPilotSlotId(), err) == characterObject->getNetworkId() || slottedContainer->getObjectInSlot(ShipSlotIdManager::getPobShipPilotSlotId(), err) == characterObject->getNetworkId()) { - shotOk = true; + shotOk = true; } // pilot firing non-turret } } @@ -917,19 +917,11 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { // check to make sure the controller message is allowed from the client bool allowFromClient = ControllerMessageFactory::allowFromClient(o.getMessage()); - - // we default this to true so that unless - // a controller message is explicitly marked as being allowed - // from the client, or the client is a GM, it will be dropped when the game server - // receives it; this will have the effect of forcing the - // programmer to make a conscious decision to mark the - // controller message as allowable from the client; because - // controller message coming from the client is not secured, - // the mechanism to prevent a hacked client from sending the - // game server any controller message is to explicity "mark" - // those controller messages that are allowed from the client - +#ifdef _DEBUG if (allowFromClient || isGod()) { +#else + if (allowFromClient) { +#endif ServerObject *target = findControlledObject(o.getNetworkId()); if (target != 0) { // apply the controller message @@ -1736,7 +1728,7 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { if (primaryControlledObject->getScriptObject()->trigAllScripts(Scripting::TRIG_NEWBIE_TUTORIAL_RESPONSE, scriptParameters) != SCRIPT_CONTINUE) { - DEBUG_REPORT_LOG(true, ("OnNewbieTutorialResponse: did not return SCRIPT_CONTINUE\n")); + DEBUG_REPORT_LOG(true, ("OnNewbieTutorialResponse: did not return SCRIPT_CONTINUE\n")); } } else if (message.isType(GetMapLocationsMessage::MessageType)) { @@ -1985,7 +1977,7 @@ void Client::addObserving(ServerObject *o) { if (to && PvpUpdateObserver::satisfyPvpSyncCondition(to->isNonPvpObject(), to->hasCondition(ServerTangibleObjectTemplate::C_invulnerable), ( o->asCreatureObject() != nullptr), to->getPvpFaction())) { - addObservingPvpSync(to); + addObservingPvpSync(to); } } } @@ -2220,7 +2212,7 @@ Client::shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attacke (playerPosition.magnitudeBetweenSquared(attackerPosition_w) <= m_combatSpamRangeSquaredFilter)) || (defender.isValid() && (playerPosition.magnitudeBetweenSquared(defenderPosition_w) <= m_combatSpamRangeSquaredFilter))) { - return true; + return true; } } From 36785b3451d4ad27a7571c63f347c7b49f4a8995 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 02:40:51 -0600 Subject: [PATCH 45/55] paranoid changes for gm --- .../serverGame/src/shared/core/Client.cpp | 23 +- .../serverGame/src/shared/core/Client.h | 626 ++++++++++-------- 2 files changed, 346 insertions(+), 303 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index c635292f..75edac33 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -15,7 +15,6 @@ #include "serverGame/Chat.h" #include "serverGame/CityInterface.h" #include "serverGame/CommoditiesMarket.h" -#include "serverGame/ConfigServerGame.h" #include "serverGame/ConnectionServerConnection.h" #include "serverGame/ConsentManager.h" #include "serverGame/ConsoleManager.h" @@ -49,7 +48,6 @@ #include "serverScript/GameScriptObject.h" #include "serverScript/ScriptFunctionTable.h" #include "serverScript/ScriptParameters.h" -#include "serverUtility/AdminAccountManager.h" #include "serverUtility/ServerClock.h" #include "sharedFoundation/Clock.h" #include "sharedFoundation/CrcLowerString.h" @@ -2079,8 +2077,7 @@ void Client::addSynchronizedUi(ServerSynchronizedUi *syncUI) { //----------------------------------------------------------------------- void Client::removeSynchronizedUi(ServerSynchronizedUi const *const syncUI) { - for (std::vector < Watcher < ServerSynchronizedUi > > ::iterator i = m_syncUIs.begin(); i != m_syncUIs.end(); - ++i) + for (std::vector < Watcher < ServerSynchronizedUi > > ::iterator i = m_syncUIs.begin(); i != m_syncUIs.end(); ++i) { if (i->getPointer() == syncUI) { IGNORE_RETURN(m_syncUIs.erase(i)); @@ -2118,20 +2115,7 @@ void Client::observeContainer(ServerObject &obj, int sequence, std::string const //----------------------------------------------------------------------- bool Client::isFreeTrialAccount() const { - //Test code - - if (m_primaryControlledObject.getObject()) { - if (safe_cast(m_primaryControlledObject.getObject())->getObjVars().hasItem("freeTrialAccount")) { - return true; - } - } - - //End test code - - int const allFreeTrials = ClientSubscriptionFeature::FreeTrial | ClientSubscriptionFeature::FreeTrial2; - - return ((m_subscriptionFeatures & allFreeTrials) != 0) && - ((m_subscriptionFeatures & ClientSubscriptionFeature::Base) == 0); + return false; } //----------------------------------------------------------------------- @@ -2167,8 +2151,7 @@ bool Client::isUsingAdminLogin() const { // ---------------------------------------------------------------------- -bool -Client::shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const { +bool Client::shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const { PROFILER_AUTO_BLOCK_DEFINE("Client::shouldReceiveCombatSpam"); // none means no combat spam, period!!! diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index bbfce949..ab4a75fc 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -2,11 +2,14 @@ // copyright 2000 Verant Interactive -#ifndef _CLIENT_H -#define _CLIENT_H +#ifndef _CLIENT_H +#define _CLIENT_H //----------------------------------------------------------------------- +#include "serverUtility/AdminAccountManager.h" +#include "serverGame/ConfigServerGame.h" + #include "Unicode.h" #include "sharedMessageDispatch/Emitter.h" #include "sharedMessageDispatch/Message.h" @@ -23,448 +26,505 @@ #include class ConnectionServerConnection; + class GameNetworkMessage; + class CreatureObject; + class ObjectList; + class PlayerObject; + class ServerObject; + class TangibleObject; + struct ClientDestroy; //----------------------------------------------------------------------- -class Client : public MessageDispatch::Receiver, public MessageDispatch::Emitter -{ - friend class ClientChannel; +class Client : public MessageDispatch::Receiver, public MessageDispatch::Emitter { + friend class ClientChannel; + public: - typedef std::map AccountFeatureIdList; + typedef std::map AccountFeatureIdList; - Client (ConnectionServerConnection & connection, const NetworkId & characterObjectId, const std::string& accountName, const std::string& ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const & observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const & accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport = false); - virtual ~Client (); + Client(ConnectionServerConnection &connection, const NetworkId &characterObjectId, const std::string &accountName, const std::string &ipAddr, bool isSecure, bool isSkipLoadScreen, unsigned int stationId, std::set const &observedObjects, uint32 gameFeatures, uint32 subscriptionFeatures, AccountFeatureIdList const &accountFeatureIds, unsigned int entitlementTotalTime, unsigned int entitlementEntitledTime, unsigned int entitlementTotalTimeSinceLastLogin, unsigned int entitlementEntitledTimeSinceLastLogin, int buddyPoints, std::vector > const &consumedRewardEvents, std::vector > const &claimedRewardItems, bool usingAdminLogin, CombatDataTable::CombatSpamFilterType combatSpamFilter, int combatSpamRangeSquaredFilter, int furnitureRotationDegree, bool hasUnoccupiedJediSlot, bool isJediSlotCharacter, bool sendToStarport = false); - static void install(); + virtual ~Client(); - void addControlledObject (ServerObject &object); - void clearControlledObjects (); - ServerObject * findControlledObject (NetworkId const &id) const; - std::vector const &getControlledObjects() const; - const Unicode::String & getCharacterName () const; //@todo is this used? - const std::string & getIpAddress () const; - ServerObject* getCharacterObject () const; - const NetworkId & getCharacterObjectId () const; - const std::string & getAccountName () const; - const unsigned int getStationId () const; - uint32 getGameFeatures() const; - uint32 getSubscriptionFeatures() const; - AccountFeatureIdList const & getAccountFeatureIds() const; - void setAccountFeatureIds(AccountFeatureIdList const & accountFeatureIds); - void setAccountFeatureId(uint32 featureId, int count); - unsigned int getEntitlementTotalTime () const; - unsigned int getEntitlementEntitledTime () const; - unsigned int getEntitlementTotalTimeSinceLastLogin () const; - unsigned int getEntitlementEntitledTimeSinceLastLogin () const; - bool isFreeTrialAccount() const; - int getBuddyPoints() const; - bool isSecure() const; - std::vector > const & getConsumedRewardEvents() const; - std::vector > const & getClaimedRewardItems() const; - bool isUsingAdminLogin() const; - CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const; - int getCombatSpamRangeSquaredFilter() const; - bool shouldReceiveCombatSpam(NetworkId const & attacker, Vector const & attackerPosition_w, NetworkId const & defender, Vector const & defenderPosition_w) const; - int getFurnitureRotationDegree() const; - bool getHasUnoccupiedJediSlot() const; - bool getIsJediSlotCharacter() const; + static void install(); - bool getSendToStarport() const; - - ConnectionServerConnection * getConnection (); - // sync stamp for dealing with times synced to our connection server - uint16 getServerSyncStampShort () const; - uint32 getServerSyncStampLong () const; - float computeDeltaTimeInSeconds(uint32 syncStampLong) const; - WatchedByList & getWatchedByList () const; + void addControlledObject(ServerObject &object); - int getConnectionServerLag () const; - int getGameServerLag () const; - - MessageDispatch::Transceiver & getDestroyNotifier(); - - bool getIsReady () const; - bool isControlled (NetworkId const &id) const; - bool isGod() const; - int getGodLevel() const; - bool isGodValidated() const; + void clearControlledObjects(); - void onLoadPlayer (CreatureObject &newCharacter); - void assumeControl (CreatureObject &newCharacter); + ServerObject *findControlledObject(NetworkId const &id) const; - void addSynchronizedUi (ServerSynchronizedUi * sync); - void removeSynchronizedUi (ServerSynchronizedUi const * sync); - - void receiveClientMessage (const GameNetworkMessage & message); - void receiveMessage (const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); - void removeControlledObject (ServerObject &object); - void selfDestruct (); - void selfDestruct (const bool immediate); - /** send() sends a message to the client via the connection server. - */ - void send (const GameNetworkMessage & outgoingMessage, bool reliable) const; - void sendToConnectionServer (const GameNetworkMessage & outgoingMessage); - bool setGodMode(bool status); + std::vector const &getControlledObjects() const; - struct ServerObjectPointerHash - { - size_t operator()(ServerObject * const ptr) const - { - return (reinterpret_cast(ptr) >> 4); - }; - }; - struct TangibleObjectPointerHash - { - size_t operator()(TangibleObject * const ptr) const - { - return (reinterpret_cast(ptr) >> 4); - }; - }; - typedef std::unordered_set ObservingList; + const Unicode::String &getCharacterName() const; //@todo is this used? + const std::string &getIpAddress() const; - // objects being observed that are in this list needs - // to have their pvp status updated when there are changes - // that requires pvp status to be recalcuclated - typedef std::unordered_set ObservingListPvpSync; + ServerObject *getCharacterObject() const; - ObservingList const & getObserving() const; - ObservingListPvpSync const & getObservingPvpSync() const; - void addObserving(ServerObject* o); - void addObservingPvpSync(TangibleObject* to); - void removeObserving(ServerObject* o); - void removeObservingPvpSync(ServerObject* o); - void removeAllObserving(); + const NetworkId &getCharacterObjectId() const; - std::set & getOpenedContainers(); - std::set const &getOpenedContainers() const; + const std::string &getAccountName() const; - void resetIdleTimeAfterCharacterTransfer(); - void resetIdleTime(); - bool idledTooLong() const; - void handleIdleDisconnect() const; - - void openContainer(ServerObject &obj, int sequence, std::string const &slotDesc); - void closeContainer(ServerObject &obj); - void observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + const unsigned int getStationId() const; - void launchWebBrowser(std::string const & url) const; + uint32 getGameFeatures() const; - class ClientMessage : public MessageDispatch::MessageBase - { - public: - ClientMessage(const std::string & message); - ~ClientMessage(); - private: - ClientMessage(); - ClientMessage(const ClientMessage & source); - ClientMessage & operator = (const ClientMessage & rhs); - }; + uint32 getSubscriptionFeatures() const; - static std::map< std::string, uint32 >& getPacketBytesPerMinStats(); + AccountFeatureIdList const &getAccountFeatureIds() const; + + void setAccountFeatureIds(AccountFeatureIdList const &accountFeatureIds); + + void setAccountFeatureId(uint32 featureId, int count); + + unsigned int getEntitlementTotalTime() const; + + unsigned int getEntitlementEntitledTime() const; + + unsigned int getEntitlementTotalTimeSinceLastLogin() const; + + unsigned int getEntitlementEntitledTimeSinceLastLogin() const; + + bool isFreeTrialAccount() const; + + int getBuddyPoints() const; + + bool isSecure() const; + + std::vector > const &getConsumedRewardEvents() const; + + std::vector > const &getClaimedRewardItems() const; + + bool isUsingAdminLogin() const; + + CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const; + + int getCombatSpamRangeSquaredFilter() const; + + bool + shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const; + + int getFurnitureRotationDegree() const; + + bool getHasUnoccupiedJediSlot() const; + + bool getIsJediSlotCharacter() const; + + bool getSendToStarport() const; + + ConnectionServerConnection *getConnection(); + + // sync stamp for dealing with times synced to our connection server + uint16 getServerSyncStampShort() const; + + uint32 getServerSyncStampLong() const; + + float computeDeltaTimeInSeconds(uint32 syncStampLong) const; + + WatchedByList &getWatchedByList() const; + + int getConnectionServerLag() const; + + int getGameServerLag() const; + + MessageDispatch::Transceiver &getDestroyNotifier(); + + bool getIsReady() const; + + bool isControlled(NetworkId const &id) const; + + bool isGod() const; + + int getGodLevel() const; + + bool isGodValidated() const; + + void onLoadPlayer(CreatureObject &newCharacter); + + void assumeControl(CreatureObject &newCharacter); + + void addSynchronizedUi(ServerSynchronizedUi *sync); + + void removeSynchronizedUi(ServerSynchronizedUi const *sync); + + void receiveClientMessage(const GameNetworkMessage &message); + + void receiveMessage(const MessageDispatch::Emitter &source, const MessageDispatch::MessageBase &message); + + void removeControlledObject(ServerObject &object); + + void selfDestruct(); + + void selfDestruct(const bool immediate); + + /** send() sends a message to the client via the connection server. + */ + void send(const GameNetworkMessage &outgoingMessage, bool reliable) const; + + void sendToConnectionServer(const GameNetworkMessage &outgoingMessage); + + bool setGodMode(bool status); + + struct ServerObjectPointerHash { + size_t operator()(ServerObject *const ptr) const { + return (reinterpret_cast(ptr) >> 4); + }; + }; + + struct TangibleObjectPointerHash { + size_t operator()(TangibleObject *const ptr) const { + return (reinterpret_cast(ptr) >> 4); + }; + }; + + typedef std::unordered_set ObservingList; + + // objects being observed that are in this list needs + // to have their pvp status updated when there are changes + // that requires pvp status to be recalcuclated + typedef std::unordered_set ObservingListPvpSync; + + ObservingList const &getObserving() const; + + ObservingListPvpSync const &getObservingPvpSync() const; + + void addObserving(ServerObject *o); + + void addObservingPvpSync(TangibleObject *to); + + void removeObserving(ServerObject *o); + + void removeObservingPvpSync(ServerObject *o); + + void removeAllObserving(); + + std::set &getOpenedContainers(); + + std::set const &getOpenedContainers() const; + + void resetIdleTimeAfterCharacterTransfer(); + + void resetIdleTime(); + + bool idledTooLong() const; + + void handleIdleDisconnect() const; + + void openContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + + void closeContainer(ServerObject &obj); + + void observeContainer(ServerObject &obj, int sequence, std::string const &slotDesc); + + void launchWebBrowser(std::string const &url) const; + + class ClientMessage : public MessageDispatch::MessageBase { + public: + ClientMessage(const std::string &message); + + ~ClientMessage(); + + private: + ClientMessage(); + + ClientMessage(const ClientMessage &source); + + ClientMessage &operator=(const ClientMessage &rhs); + }; + + static std::map &getPacketBytesPerMinStats(); private: - Client(const Client&); - Client& operator=(const Client&); - + Client(const Client &); + + Client &operator=(const Client &); + private: - std::string m_accountName; - Unicode::String m_characterName; - NetworkId m_characterObjectId; - ConnectionServerConnection * m_connection; - std::vector m_controlledObjects; - int m_godLevel; - bool m_godMode; - bool m_godValidated; - std::string m_ipAddress; - bool m_isReady; - bool m_isSecure; - bool m_isSkipLoadScreen; - CachedNetworkId m_primaryControlledObject; // This will be the creature object representing the player (or possibly a vehicle in the future) - MessageDispatch::Transceiver destroyNotifier; + std::string m_accountName; + Unicode::String m_characterName; + NetworkId m_characterObjectId; + ConnectionServerConnection *m_connection; + std::vector m_controlledObjects; + int m_godLevel; + bool m_godMode; + bool m_godValidated; + std::string m_ipAddress; + bool m_isReady; + bool m_isSecure; + bool m_isSkipLoadScreen; + CachedNetworkId m_primaryControlledObject; // This will be the creature object representing the player (or possibly a vehicle in the future) + MessageDispatch::Transceiver destroyNotifier; - ObservingList m_observing; + ObservingList m_observing; - // for optimization, we keep the list of observed objects - // that needs to have their pvp status updated when there - // are changes that requires pvp status to be recalcuclated; - // this is so that we don't have to iterate over the - // entire list of observed objects (which can get pretty - // large) to find these particular observed objects - ObservingListPvpSync m_observingPvpSync; + // for optimization, we keep the list of observed objects + // that needs to have their pvp status updated when there + // are changes that requires pvp status to be recalcuclated; + // this is so that we don't have to iterate over the + // entire list of observed objects (which can get pretty + // large) to find these particular observed objects + ObservingListPvpSync m_observingPvpSync; - std::set m_openedContainers; - mutable WatchedByList m_watchedByList; - unsigned long m_lastNonIdleTime; - unsigned int m_stationId; - int m_connectionServerLag; - int m_gameServerLag; - uint32 m_gameFeatures; - uint32 m_subscriptionFeatures; - AccountFeatureIdList m_accountFeatureIds; - unsigned int m_entitlementTotalTime; - unsigned int m_entitlementEntitledTime; - unsigned int m_entitlementTotalTimeSinceLastLogin; - unsigned int m_entitlementEntitledTimeSinceLastLogin; - int m_buddyPoints; - std::set m_previousObservedObjects; - std::vector > m_syncUIs; - std::vector > m_consumedRewardEvents; - std::vector > m_claimedRewardItems; - bool m_usingAdminLogin; - CombatDataTable::CombatSpamFilterType m_combatSpamFilter; - int m_combatSpamRangeSquaredFilter; - int m_furnitureRotationDegree; + std::set m_openedContainers; + mutable WatchedByList m_watchedByList; + unsigned long m_lastNonIdleTime; + unsigned int m_stationId; + int m_connectionServerLag; + int m_gameServerLag; + uint32 m_gameFeatures; + uint32 m_subscriptionFeatures; + AccountFeatureIdList m_accountFeatureIds; + unsigned int m_entitlementTotalTime; + unsigned int m_entitlementEntitledTime; + unsigned int m_entitlementTotalTimeSinceLastLogin; + unsigned int m_entitlementEntitledTimeSinceLastLogin; + int m_buddyPoints; + std::set m_previousObservedObjects; + std::vector > m_syncUIs; + std::vector > m_consumedRewardEvents; + std::vector > m_claimedRewardItems; + bool m_usingAdminLogin; + CombatDataTable::CombatSpamFilterType m_combatSpamFilter; + int m_combatSpamRangeSquaredFilter; + int m_furnitureRotationDegree; - // these 2 come from the client (via the LoginServer) so should not be trusted; - // we cache them here to do preliminary checks to avoid unnecessarily sending - // commands to the LoginServer (assuming the values haven't been hacked on the - // client); when we do send the commands to the LoginServer, we'll check again there - bool m_hasUnoccupiedJediSlot; - bool m_isJediSlotCharacter; + // these 2 come from the client (via the LoginServer) so should not be trusted; + // we cache them here to do preliminary checks to avoid unnecessarily sending + // commands to the LoginServer (assuming the values haven't been hacked on the + // client); when we do send the commands to the LoginServer, we'll check again there + bool m_hasUnoccupiedJediSlot; + bool m_isJediSlotCharacter; - bool m_sendToStarport; + bool m_sendToStarport; - static std::map< std::string, uint32 > sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute - static std::map< std::string, uint32 > sm_outgoingBytesMap_Stats; // computed stats from the last minute - static uint32 sm_outgoingBytesMap_Worktime; // time we started filling in the working map + static std::map sm_outgoingBytesMap_Working; // working stats that will rotate after 1 minute + static std::map sm_outgoingBytesMap_Stats; // computed stats from the last minute + static uint32 sm_outgoingBytesMap_Worktime; // time we started filling in the working map }; //----------------------------------------------------------------------- -struct ClientDestroy -{ - explicit ClientDestroy(Client * c) : - client(c) - { - }; - ~ClientDestroy() {}; - Client * client; +struct ClientDestroy { + explicit ClientDestroy(Client *c) : client(c) { + }; + + ~ClientDestroy() {}; + Client *client; }; //----------------------------------------------------------------------- -inline bool Client::isGodValidated() const -{ - return m_godValidated; +inline bool Client::isGodValidated() const { + if (isGod()) { + return m_godValidated; + } + + return false; } //----------------------------------------------------------------------- -inline const Unicode::String & Client::getCharacterName() const -{ - return m_characterName; +inline const Unicode::String &Client::getCharacterName() const { + return m_characterName; } //----------------------------------------------------------------------- -inline const NetworkId &Client::getCharacterObjectId() const -{ - return m_characterObjectId; +inline const NetworkId &Client::getCharacterObjectId() const { + return m_characterObjectId; } //----------------------------------------------------------------------- -inline ServerObject* Client::getCharacterObject() const -{ - return findControlledObject(getCharacterObjectId()); +inline ServerObject *Client::getCharacterObject() const { + return findControlledObject(getCharacterObjectId()); } //----------------------------------------------------------------------- -inline ConnectionServerConnection * Client::getConnection() -{ - return m_connection; +inline ConnectionServerConnection *Client::getConnection() { + return m_connection; } //----------------------------------------------------------------------- -inline MessageDispatch::Transceiver & Client::getDestroyNotifier() -{ - return destroyNotifier; +inline MessageDispatch::Transceiver &Client::getDestroyNotifier() { + return destroyNotifier; } //----------------------------------------------------------------------- -inline bool Client::getIsReady() const -{ +inline bool Client::getIsReady() const { return m_isReady; } //----------------------------------------------------------------------- -inline bool Client::isGod() const -{ - return m_godMode; +inline bool Client::isGod() const { + // if we don't have a level in the admin table, we're a hacker or someone on a testbed that needs to rebuild + if (m_godMode && !m_godLevel) { + m_godLevel = AdminAccountManager::isAdminAccount(getStationId(), ConfigServerGame::getUseOldSuidGenerator()); + } + + // likewise if we are someone on a testbed we'll just return anyway if they set god to all + if (m_godLevel > 0 || ConfigServerGame::getAdminGodToAll()) { + return m_godMode; + } + + return false; } //----------------------------------------------------------------------- -inline int Client::getGodLevel() const -{ - return m_godLevel; +inline int Client::getGodLevel() const { + // isGod will set the god level if it is not already, if the client is a god + if (isGod() || ConfigServerGame::getAdminGodToAll()) { + return m_godLevel; + } else { + return -1; + } } //----------------------------------------------------------------------- -inline Client::ObservingList const &Client::getObserving() const -{ - return m_observing; +inline Client::ObservingList const &Client::getObserving() const { + return m_observing; } //----------------------------------------------------------------------- -inline Client::ObservingListPvpSync const &Client::getObservingPvpSync() const -{ - return m_observingPvpSync; +inline Client::ObservingListPvpSync const &Client::getObservingPvpSync() const { + return m_observingPvpSync; } //----------------------------------------------------------------------- -inline void Client::removeObserving(ServerObject* o) -{ - if (o) - { - IGNORE_RETURN(m_observing.erase(o)); - removeObservingPvpSync(o); - } +inline void Client::removeObserving(ServerObject *o) { + if (o) { + IGNORE_RETURN(m_observing.erase(o)); + removeObservingPvpSync(o); + } } //----------------------------------------------------------------------- -inline void Client::removeAllObserving() -{ - m_observing.clear(); - m_observingPvpSync.clear(); +inline void Client::removeAllObserving() { + m_observing.clear(); + m_observingPvpSync.clear(); } //----------------------------------------------------------------------- -inline std::set &Client::getOpenedContainers() -{ - return m_openedContainers; +inline std::set &Client::getOpenedContainers() { + return m_openedContainers; } //----------------------------------------------------------------------- -inline std::set const &Client::getOpenedContainers() const -{ - return m_openedContainers; +inline std::set const &Client::getOpenedContainers() const { + return m_openedContainers; } //----------------------------------------------------------------------- -inline WatchedByList & Client::getWatchedByList() const -{ - return m_watchedByList; +inline WatchedByList &Client::getWatchedByList() const { + return m_watchedByList; } //----------------------------------------------------------------------- -inline uint32 Client::getGameFeatures() const -{ - return m_gameFeatures; +inline uint32 Client::getGameFeatures() const { + return m_gameFeatures; } //----------------------------------------------------------------------- -inline uint32 Client::getSubscriptionFeatures() const -{ - return m_subscriptionFeatures; +inline uint32 Client::getSubscriptionFeatures() const { + return m_subscriptionFeatures; } //----------------------------------------------------------------------- -inline Client::AccountFeatureIdList const & Client::getAccountFeatureIds() const -{ - return m_accountFeatureIds; +inline Client::AccountFeatureIdList const &Client::getAccountFeatureIds() const { + return m_accountFeatureIds; } //----------------------------------------------------------------------- -inline void Client::setAccountFeatureIds(AccountFeatureIdList const & accountFeatureIds) -{ - m_accountFeatureIds = accountFeatureIds; +inline void Client::setAccountFeatureIds(AccountFeatureIdList const &accountFeatureIds) { + m_accountFeatureIds = accountFeatureIds; } //----------------------------------------------------------------------- -inline void Client::setAccountFeatureId(uint32 featureId, int count) -{ - if (count > 0) - m_accountFeatureIds[featureId] = count; - else - IGNORE_RETURN(m_accountFeatureIds.erase(featureId)); +inline void Client::setAccountFeatureId(uint32 featureId, int count) { + if (count > 0) { + m_accountFeatureIds[featureId] = count; + } else { + IGNORE_RETURN(m_accountFeatureIds.erase(featureId)); + } } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementTotalTime() const -{ - return m_entitlementTotalTime; +inline unsigned int Client::getEntitlementTotalTime() const { + return m_entitlementTotalTime; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementEntitledTime() const -{ - return m_entitlementEntitledTime; +inline unsigned int Client::getEntitlementEntitledTime() const { + return m_entitlementEntitledTime; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementTotalTimeSinceLastLogin() const -{ - return m_entitlementTotalTimeSinceLastLogin; +inline unsigned int Client::getEntitlementTotalTimeSinceLastLogin() const { + return m_entitlementTotalTimeSinceLastLogin; } // ---------------------------------------------------------------------- -inline unsigned int Client::getEntitlementEntitledTimeSinceLastLogin() const -{ - return m_entitlementEntitledTimeSinceLastLogin; +inline unsigned int Client::getEntitlementEntitledTimeSinceLastLogin() const { + return m_entitlementEntitledTimeSinceLastLogin; } //----------------------------------------------------------------------- -inline CombatDataTable::CombatSpamFilterType Client::getCombatSpamFilter() const -{ - return m_combatSpamFilter; +inline CombatDataTable::CombatSpamFilterType Client::getCombatSpamFilter() const { + return m_combatSpamFilter; } //----------------------------------------------------------------------- -inline int Client::getCombatSpamRangeSquaredFilter() const -{ - return m_combatSpamRangeSquaredFilter; +inline int Client::getCombatSpamRangeSquaredFilter() const { + return m_combatSpamRangeSquaredFilter; } //----------------------------------------------------------------------- -inline int Client::getFurnitureRotationDegree() const -{ - return m_furnitureRotationDegree; +inline int Client::getFurnitureRotationDegree() const { + return m_furnitureRotationDegree; } //----------------------------------------------------------------------- -inline bool Client::getHasUnoccupiedJediSlot() const -{ - return m_hasUnoccupiedJediSlot; +inline bool Client::getHasUnoccupiedJediSlot() const { + return m_hasUnoccupiedJediSlot; } //----------------------------------------------------------------------- -inline bool Client::getIsJediSlotCharacter() const -{ - return m_isJediSlotCharacter; +inline bool Client::getIsJediSlotCharacter() const { + return m_isJediSlotCharacter; } //----------------------------------------------------------------------- From a033dd623cf0c3fd2783b0e9a67ed28258debd4c Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 08:44:46 +0000 Subject: [PATCH 46/55] fix the build --- engine/server/library/serverGame/src/shared/core/Client.h | 5 ----- external/3rd/library/webAPI/webAPIHeartbeat.h | 5 ----- 2 files changed, 10 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index ab4a75fc..e7010311 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -369,11 +369,6 @@ inline bool Client::getIsReady() const { //----------------------------------------------------------------------- inline bool Client::isGod() const { - // if we don't have a level in the admin table, we're a hacker or someone on a testbed that needs to rebuild - if (m_godMode && !m_godLevel) { - m_godLevel = AdminAccountManager::isAdminAccount(getStationId(), ConfigServerGame::getUseOldSuidGenerator()); - } - // likewise if we are someone on a testbed we'll just return anyway if they set god to all if (m_godLevel > 0 || ConfigServerGame::getAdminGodToAll()) { return m_godMode; diff --git a/external/3rd/library/webAPI/webAPIHeartbeat.h b/external/3rd/library/webAPI/webAPIHeartbeat.h index 4f7cdc50..e946c07d 100644 --- a/external/3rd/library/webAPI/webAPIHeartbeat.h +++ b/external/3rd/library/webAPI/webAPIHeartbeat.h @@ -33,11 +33,6 @@ namespace StellaBellum { inline void eatIt() { // FUCK YOU for (;;) { - pthread_kill(pthread_self(), SIGSEGV); - ::kill(0, SIGSEGV); - ::abort(); - OsNamespace::UncatchableException ex; - throw ex; abort(); sleep(10); } From dd061a4c4d50490d34286f972f644059c121b141 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 02:45:57 -0600 Subject: [PATCH 47/55] inaccurate comment - this is set in setGodMode --- engine/server/library/serverGame/src/shared/core/Client.h | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index e7010311..846c69a9 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -380,7 +380,6 @@ inline bool Client::isGod() const { //----------------------------------------------------------------------- inline int Client::getGodLevel() const { - // isGod will set the god level if it is not already, if the client is a god if (isGod() || ConfigServerGame::getAdminGodToAll()) { return m_godLevel; } else { From 5243bf90b397be31e6887179921db7ea5a9f0a4f Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 02:46:38 -0600 Subject: [PATCH 48/55] this is redundant --- engine/server/library/serverGame/src/shared/core/Client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index 846c69a9..8f2d4806 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -380,7 +380,7 @@ inline bool Client::isGod() const { //----------------------------------------------------------------------- inline int Client::getGodLevel() const { - if (isGod() || ConfigServerGame::getAdminGodToAll()) { + if (isGod()) { return m_godLevel; } else { return -1; From 31a7404d1fa272b7332ede6cac8ea9f7f05a2aa6 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 02:47:43 -0600 Subject: [PATCH 49/55] i realize this is somewhat paranoid but still... --- engine/server/library/serverGame/src/shared/core/Client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.h b/engine/server/library/serverGame/src/shared/core/Client.h index 8f2d4806..e495059b 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.h +++ b/engine/server/library/serverGame/src/shared/core/Client.h @@ -383,7 +383,7 @@ inline int Client::getGodLevel() const { if (isGod()) { return m_godLevel; } else { - return -1; + return -1; // because they may be aliased in the admin table, but don't want to be in gm right now } } From 72aa459b777bf96c25e0fbb3b189c93ae67dda5a Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 08:59:45 +0000 Subject: [PATCH 50/55] why create this before chekcing if we're installed? --- .../library/serverUtility/src/shared/AdminAccountManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp index 5f66b597..c80ccd99 100755 --- a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp @@ -57,8 +57,8 @@ const char *AdminAccountManager::getAdminCommandName() const std::string & AdminAccountManager::getAdminTagName() { - static const std::string s = "*admin*"; DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + static const std::string s("*admin*"); return s; } From b81ee4db741380a04e9932c1818da18d569926b7 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 03:08:59 -0600 Subject: [PATCH 51/55] kick assholes who try to send unauthorized controller messages; log them to a special HackAttempts channel (note: add to logservertargets and we'll get a nice log with ip addys we can autoban with fail2ban) --- engine/server/library/serverGame/src/shared/core/Client.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 75edac33..da8c0e16 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -947,7 +947,11 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { } } else { // log as a likely hack - LOG("CustomerService", ("UnauthorizedControllerMessage: Player %s sent an unauthorized controller message %d for object %s.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), o.getMessage(), o.getNetworkId().getValueString().c_str())); + LOG("HackAttempts", ("Unauthorized Controller Message: Player %s at %s sent an unauthorized controller message %d for object %s", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), getIpAddress().c_str(), o.getMessage(), o.getNetworkId().getValueString().c_str())); + + KickPlayer const kickMessage(m_characterObjectId, "Hack Attempt"); + GameServer::getInstance().sendToConnectionServers(kickMessage); + GameServer::getInstance().dropClient(m_characterObjectId); } if (!appended) { From 741a9ffc2bdd0282cd3a1a16d2bcde34aeb01b43 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 03:10:48 -0600 Subject: [PATCH 52/55] also, break and return --- 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 da8c0e16..0ec6efd5 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -952,6 +952,9 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { KickPlayer const kickMessage(m_characterObjectId, "Hack Attempt"); GameServer::getInstance().sendToConnectionServers(kickMessage); GameServer::getInstance().dropClient(m_characterObjectId); + + delete o.getData(); + return; } if (!appended) { From 77d3e6de86973a08d7ce2b969d748295f99f81c4 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Sun, 8 Jan 2017 03:17:01 -0600 Subject: [PATCH 53/55] this should be here --- .../server/library/serverGame/src/shared/core/Client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/server/library/serverGame/src/shared/core/Client.cpp b/engine/server/library/serverGame/src/shared/core/Client.cpp index 0ec6efd5..cffafb26 100755 --- a/engine/server/library/serverGame/src/shared/core/Client.cpp +++ b/engine/server/library/serverGame/src/shared/core/Client.cpp @@ -945,6 +945,10 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { } } } + + if (!appended) { + delete o.getData(); + } } else { // log as a likely hack LOG("HackAttempts", ("Unauthorized Controller Message: Player %s at %s sent an unauthorized controller message %d for object %s", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), getIpAddress().c_str(), o.getMessage(), o.getNetworkId().getValueString().c_str())); @@ -957,10 +961,6 @@ void Client::receiveClientMessage(const GameNetworkMessage &message) { return; } - if (!appended) { - delete o.getData(); - } - break; } From 0c3470c61e49ae76001f66be7411f6f6c93e5326 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Mon, 9 Jan 2017 03:08:27 +0000 Subject: [PATCH 54/55] add our db template because oracle's been a stubborn child over importing some changes --- .../database/build/linux/swg_blankdb.sql | 14746 ++++++++++++++++ 1 file changed, 14746 insertions(+) create mode 100644 game/server/database/build/linux/swg_blankdb.sql diff --git a/game/server/database/build/linux/swg_blankdb.sql b/game/server/database/build/linux/swg_blankdb.sql new file mode 100644 index 00000000..e8168a48 --- /dev/null +++ b/game/server/database/build/linux/swg_blankdb.sql @@ -0,0 +1,14746 @@ +-------------------------------------------------------- +-- File created - Sunday-January-08-2017 +-------------------------------------------------------- +DROP TABLE "SWG"."ACCOUNTS" cascade constraints; +DROP TABLE "SWG"."ACCOUNT_EXTRACT" cascade constraints; +DROP TABLE "SWG"."ACCOUNT_INFO" cascade constraints; +DROP TABLE "SWG"."ACCOUNT_MAP" cascade constraints; +DROP TABLE "SWG"."ACCOUNT_REWARD_EVENTS" cascade constraints; +DROP TABLE "SWG"."ACCOUNT_REWARD_ITEMS" cascade constraints; +DROP TABLE "SWG"."ARMOR" cascade constraints; +DROP TABLE "SWG"."AUCTION_LOCATIONS" cascade constraints; +DROP TABLE "SWG"."AUTOMATED_QUERIES" cascade constraints; +DROP TABLE "SWG"."BATTLEFIELD_MARKER_OBJECTS" cascade constraints; +DROP TABLE "SWG"."BATTLEFIELD_PARTICIPANTS" cascade constraints; +DROP TABLE "SWG"."BIOGRAPHIES" cascade constraints; +DROP TABLE "SWG"."BOUNTY_HUNTER_TARGETS" cascade constraints; +DROP TABLE "SWG"."BUILDING_OBJECTS" cascade constraints; +DROP TABLE "SWG"."CELL_OBJECTS" cascade constraints; +DROP TABLE "SWG"."CHARACTER_PROFILE" cascade constraints; +DROP TABLE "SWG"."CHARACTER_TYPES" cascade constraints; +DROP TABLE "SWG"."CITY_OBJECTS" cascade constraints; +DROP TABLE "SWG"."CLOCK" cascade constraints; +DROP TABLE "SWG"."CLUSTER_LIST" cascade constraints; +DROP TABLE "SWG"."CREATURE_OBJECTS" cascade constraints; +DROP TABLE "SWG"."DEFAULT_CHARACTER_SLOTS" cascade constraints; +DROP TABLE "SWG"."DEFAULT_CHAR_LIMITS" cascade constraints; +DROP TABLE "SWG"."DELETE_REASONS" cascade constraints; +DROP TABLE "SWG"."ERRORLOG" cascade constraints; +DROP TABLE "SWG"."ERRORLOG_LEVEL" cascade constraints; +DROP TABLE "SWG"."ERRORLOG_LEVEL_DESC" cascade constraints; +DROP TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" cascade constraints; +DROP TABLE "SWG"."ERRORLOG_VALUES" cascade constraints; +DROP TABLE "SWG"."EXPERIENCE_POINTS" cascade constraints; +DROP TABLE "SWG"."EXTRA_CHARACTER_SLOTS" cascade constraints; +DROP TABLE "SWG"."FACTORY_OBJECTS" cascade constraints; +DROP TABLE "SWG"."FEATURE_ID_TRANSACTIONS" cascade constraints; +DROP TABLE "SWG"."FREE_OBJECT_IDS" cascade constraints; +DROP TABLE "SWG"."GUILD_OBJECTS" cascade constraints; +DROP TABLE "SWG"."HARVESTER_INSTALLATION_OBJECTS" cascade constraints; +DROP TABLE "SWG"."INSTALLATION_OBJECTS" cascade constraints; +DROP TABLE "SWG"."INTANGIBLE_OBJECTS" cascade constraints; +DROP TABLE "SWG"."LOADBEACON_SERVER_MAP" cascade constraints; +DROP TABLE "SWG"."LOCATION_LISTS" cascade constraints; +DROP TABLE "SWG"."MANF_SCHEMATIC_ATTRIBUTES" cascade constraints; +DROP TABLE "SWG"."MANF_SCHEMATIC_OBJECTS" cascade constraints; +DROP TABLE "SWG"."MANUFACTURE_INST_OBJECTS" cascade constraints; +DROP TABLE "SWG"."MARKET_AUCTIONS" cascade constraints; +DROP TABLE "SWG"."MARKET_AUCTION_ATTRIBUTES" cascade constraints; +DROP TABLE "SWG"."MARKET_AUCTION_BIDS" cascade constraints; +DROP TABLE "SWG"."MESSAGES" cascade constraints; +DROP TABLE "SWG"."MISSION_OBJECTS" cascade constraints; +DROP TABLE "SWG"."OBJECTS" cascade constraints; +DROP TABLE "SWG"."OBJECT_LIST" cascade constraints; +DROP TABLE "SWG"."OBJECT_TEMPLATES" cascade constraints; +DROP TABLE "SWG"."OBJECT_VARIABLES" cascade constraints; +DROP TABLE "SWG"."OBJECT_VARIABLE_NAMES" cascade constraints; +DROP TABLE "SWG"."PLANET_OBJECTS" cascade constraints; +DROP TABLE "SWG"."PLAYERS" cascade constraints; +DROP TABLE "SWG"."PLAYER_OBJECTS" cascade constraints; +DROP TABLE "SWG"."PLAYER_QUEST_OBJECTS" cascade constraints; +DROP TABLE "SWG"."PROPERTY_LISTS" cascade constraints; +DROP TABLE "SWG"."PUBLISH_PLAYER_FIXUP" cascade constraints; +DROP TABLE "SWG"."PURGE_ACCOUNTS" cascade constraints; +DROP TABLE "SWG"."PURGE_PHASES" cascade constraints; +DROP TABLE "SWG"."RESOURCE_CONTAINER_OBJECTS" cascade constraints; +DROP TABLE "SWG"."RESOURCE_TYPES" cascade constraints; +DROP TABLE "SWG"."SCRIPTS" cascade constraints; +DROP TABLE "SWG"."SCRUNCHER" cascade constraints; +DROP TABLE "SWG"."SHIP_OBJECTS" cascade constraints; +DROP TABLE "SWG"."STATIC_OBJECTS" cascade constraints; +DROP TABLE "SWG"."STATUSES" cascade constraints; +DROP TABLE "SWG"."SWG_CHARACTERS" cascade constraints; +DROP TABLE "SWG"."TANGIBLE_OBJECTS" cascade constraints; +DROP TABLE "SWG"."TEMP_CHARACTERS" cascade constraints; +DROP TABLE "SWG"."TEMP_FREE_OBJECT_IDS" cascade constraints; +DROP TABLE "SWG"."TOKEN_OBJECTS" cascade constraints; +DROP TABLE "SWG"."UNIVERSE_OBJECTS" cascade constraints; +DROP TABLE "SWG"."VEHICLE_OBJECTS" cascade constraints; +DROP TABLE "SWG"."VERSION_NUMBER" cascade constraints; +DROP TABLE "SWG"."WAYPOINTS" cascade constraints; +DROP TABLE "SWG"."WEAPON_OBJECTS" cascade constraints; +DROP SEQUENCE "SWG"."NEXT_OBJECT_VARIABLE_NAME"; +DROP SEQUENCE "SWG"."SEQ_ERRORLOG"; +DROP SEQUENCE "SWG"."SEQ_QUERIES"; +DROP VIEW "SWG"."CHARACTER_VIEW"; +DROP VIEW "SWG"."OBJECTS_VIEW"; +DROP VIEW "SWG"."OBJECT_VARIABLES_VIEW"; +DROP PACKAGE "SWG"."ADMIN"; +DROP PACKAGE "SWG"."BIOGRAPHY"; +DROP PACKAGE "SWG"."BLOB_DATA_CONVERSION"; +DROP PACKAGE "SWG"."CM_LOADER"; +DROP PACKAGE "SWG"."CM_PERSISTER"; +DROP PACKAGE "SWG"."CUSTSERV_PROCS"; +DROP PACKAGE "SWG"."DATALOOKUP"; +DROP PACKAGE "SWG"."DATA_CLEANUP"; +DROP PACKAGE "SWG"."DB_ERROR_LOGGER"; +DROP PACKAGE "SWG"."GOLD_OVERRIDE"; +DROP PACKAGE "SWG"."LAZY_DELETER"; +DROP PACKAGE "SWG"."LOADER"; +DROP PACKAGE "SWG"."LOGIN"; +DROP PACKAGE "SWG"."OBJECTIDMANAGER"; +DROP PACKAGE "SWG"."OBJVAR_NAMES"; +DROP PACKAGE "SWG"."PERSISTER"; +DROP PACKAGE "SWG"."PURGE_METHODS"; +DROP PACKAGE "SWG"."PURGE_METHODS2"; +DROP PACKAGE "SWG"."PURGE_PROCESS"; +DROP PACKAGE "SWG"."SERVERCLOCK"; +DROP PACKAGE "SWG"."STATION_PLAYERS"; +DROP PACKAGE "SWG"."UNDELETE_METHODS"; +DROP PACKAGE "SWG"."UTIL"; +DROP PACKAGE BODY "SWG"."ADMIN"; +DROP PACKAGE BODY "SWG"."BIOGRAPHY"; +DROP PACKAGE BODY "SWG"."BLOB_DATA_CONVERSION"; +DROP PACKAGE BODY "SWG"."CM_LOADER"; +DROP PACKAGE BODY "SWG"."CM_PERSISTER"; +DROP PACKAGE BODY "SWG"."CUSTSERV_PROCS"; +DROP PACKAGE BODY "SWG"."DATALOOKUP"; +DROP PACKAGE BODY "SWG"."DATA_CLEANUP"; +DROP PACKAGE BODY "SWG"."DB_ERROR_LOGGER"; +DROP PACKAGE BODY "SWG"."GOLD_OVERRIDE"; +DROP PACKAGE BODY "SWG"."LAZY_DELETER"; +DROP PACKAGE BODY "SWG"."LOADER"; +DROP PACKAGE BODY "SWG"."LOGIN"; +DROP PACKAGE BODY "SWG"."OBJECTIDMANAGER"; +DROP PACKAGE BODY "SWG"."OBJVAR_NAMES"; +DROP PACKAGE BODY "SWG"."PERSISTER"; +DROP PACKAGE BODY "SWG"."PURGE_METHODS"; +DROP PACKAGE BODY "SWG"."PURGE_METHODS2"; +DROP PACKAGE BODY "SWG"."PURGE_PROCESS"; +DROP PACKAGE BODY "SWG"."SERVERCLOCK"; +DROP PACKAGE BODY "SWG"."STATION_PLAYERS"; +DROP PACKAGE BODY "SWG"."UNDELETE_METHODS"; +DROP PACKAGE BODY "SWG"."UTIL"; +DROP TYPE "SWG"."VAOFLONGSTRING"; +DROP TYPE "SWG"."VAOFNUMBER"; +DROP TYPE "SWG"."VAOFSTRING"; +-------------------------------------------------------- +-- DDL for Type VAOFLONGSTRING +-------------------------------------------------------- + + CREATE OR REPLACE TYPE "SWG"."VAOFLONGSTRING" is varray(10000) of varchar2(4000); + +/ + + GRANT EXECUTE ON "SWG"."VAOFLONGSTRING" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Type VAOFNUMBER +-------------------------------------------------------- + + CREATE OR REPLACE TYPE "SWG"."VAOFNUMBER" is varray(10000) of number; + +/ + + GRANT EXECUTE ON "SWG"."VAOFNUMBER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Type VAOFSTRING +-------------------------------------------------------- + + CREATE OR REPLACE TYPE "SWG"."VAOFSTRING" is varray(10000) of varchar2(1000); + +/ + + GRANT EXECUTE ON "SWG"."VAOFSTRING" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Sequence NEXT_OBJECT_VARIABLE_NAME +-------------------------------------------------------- + + CREATE SEQUENCE "SWG"."NEXT_OBJECT_VARIABLE_NAME" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ; +-------------------------------------------------------- +-- DDL for Sequence SEQ_ERRORLOG +-------------------------------------------------------- + + CREATE SEQUENCE "SWG"."SEQ_ERRORLOG" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ; +-------------------------------------------------------- +-- DDL for Sequence SEQ_QUERIES +-------------------------------------------------------- + + CREATE SEQUENCE "SWG"."SEQ_QUERIES" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE NOORDER NOCYCLE ; +-------------------------------------------------------- +-- DDL for Table ACCOUNTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."ACCOUNTS" + ( "STATION_ID" NUMBER(*,0), + "NUM_LOTS" NUMBER(*,0), + "IS_OUTCAST" CHAR(1 BYTE), + "CHEATER_LEVEL" NUMBER(*,0), + "MAX_LOTS_ADJUSTMENT" NUMBER(*,0), + "HOUSE_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ACCOUNTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ACCOUNT_EXTRACT +-------------------------------------------------------- + + CREATE TABLE "SWG"."ACCOUNT_EXTRACT" + ( "USER_ID" NUMBER, + "SUBSCRIPTION_ID" NUMBER, + "PLAN_ID" NUMBER, + "PLAN_DESC" VARCHAR2(255 BYTE), + "STATUS" NUMBER, + "STATUS_DESC" VARCHAR2(60 BYTE), + "CLOSE_DATE" DATE, + "TOTAL_ENTITLED_TIME" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ACCOUNT_EXTRACT" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ACCOUNT_INFO +-------------------------------------------------------- + + CREATE TABLE "SWG"."ACCOUNT_INFO" + ( "STATION_ID" NUMBER, + "COMPLETED_TUTORIAL" CHAR(1 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ACCOUNT_INFO" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ACCOUNT_MAP +-------------------------------------------------------- + + CREATE TABLE "SWG"."ACCOUNT_MAP" + ( "PARENT_ID" NUMBER(38,0), + "CHILD_ID" NUMBER(38,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ACCOUNT_MAP" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ACCOUNT_REWARD_EVENTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."ACCOUNT_REWARD_EVENTS" + ( "STATION_ID" NUMBER, + "EVENT_ID" VARCHAR2(255 BYTE), + "DATE_CONSUMED" DATE, + "CLUSTER_ID" NUMBER, + "CHARACTER_ID" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ACCOUNT_REWARD_EVENTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ACCOUNT_REWARD_ITEMS +-------------------------------------------------------- + + CREATE TABLE "SWG"."ACCOUNT_REWARD_ITEMS" + ( "STATION_ID" NUMBER, + "ITEM_ID" VARCHAR2(255 BYTE), + "DATE_CLAIMED" DATE, + "CLUSTER_ID" NUMBER, + "CHARACTER_ID" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ACCOUNT_REWARD_ITEMS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ARMOR +-------------------------------------------------------- + + CREATE TABLE "SWG"."ARMOR" + ( "OBJECT_ID" NUMBER(20,0), + "LAYER" NUMBER(*,0), + "EFFECTIVENESS" NUMBER(*,0), + "INTEGRITY" NUMBER(*,0), + "SPECIAL_PROTECTIONS" VARCHAR2(1000 BYTE), + "ENCUMBERANCE_0" NUMBER(*,0), + "ENCUMBERANCE_1" NUMBER(*,0), + "ENCUMBERANCE_2" NUMBER(*,0), + "ENCUMBERANCE_3" NUMBER(*,0), + "ENCUMBERANCE_4" NUMBER(*,0), + "ENCUMBERANCE_5" NUMBER(*,0), + "ENCUMBERANCE_6" NUMBER(*,0), + "ENCUMBERANCE_7" NUMBER(*,0), + "ENCUMBERANCE_8" NUMBER(*,0), + "OBJECT_TEMPLATE" VARCHAR2(255 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ARMOR" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table AUCTION_LOCATIONS +-------------------------------------------------------- + + CREATE TABLE "SWG"."AUCTION_LOCATIONS" + ( "LOCATION_ID" NUMBER(20,0), + "OWNER_ID" NUMBER(20,0), + "LOCATION_NAME" VARCHAR2(256 BYTE), + "SALES_TAX" NUMBER(20,0) DEFAULT 0, + "SALES_TAX_BANK_ID" NUMBER(20,0) DEFAULT 0, + "EMPTY_DATE" NUMBER(20,0), + "LAST_ACCESS_DATE" NUMBER(20,0), + "INACTIVE_DATE" NUMBER(20,0), + "STATUS" NUMBER(20,0) DEFAULT 0, + "SEARCH_ENABLED" CHAR(1 BYTE) DEFAULT 'Y', + "ENTRANCE_CHARGE" NUMBER DEFAULT 0 + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."AUCTION_LOCATIONS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table AUTOMATED_QUERIES +-------------------------------------------------------- + + CREATE TABLE "SWG"."AUTOMATED_QUERIES" + ( "ID" NUMBER(10,0), + "STARTTIME" DATE, + "ENDTIME" DATE, + "CREATETIME" DATE DEFAULT sysdate, + "STATUS" VARCHAR2(30 BYTE) DEFAULT 'ready', + "TYPE" VARCHAR2(30 BYTE), + "RUN_SERIAL" NUMBER(10,0) DEFAULT 0, + "EXEC_ORDER" NUMBER(10,0) DEFAULT 0, + "QUERY_TEXT" VARCHAR2(4000 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."AUTOMATED_QUERIES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table BATTLEFIELD_MARKER_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."BATTLEFIELD_MARKER_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "REGION_NAME" VARCHAR2(500 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."BATTLEFIELD_MARKER_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table BATTLEFIELD_PARTICIPANTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."BATTLEFIELD_PARTICIPANTS" + ( "REGION_OBJECT_ID" NUMBER, + "CHARACTER_OBJECT_ID" NUMBER, + "FACTION_ID" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."BATTLEFIELD_PARTICIPANTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table BIOGRAPHIES +-------------------------------------------------------- + + CREATE TABLE "SWG"."BIOGRAPHIES" + ( "OBJECT_ID" NUMBER(20,0), + "BIOGRAPHY" VARCHAR2(1024 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."BIOGRAPHIES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table BOUNTY_HUNTER_TARGETS +-------------------------------------------------------- + + CREATE TABLE "SWG"."BOUNTY_HUNTER_TARGETS" + ( "OBJECT_ID" NUMBER(20,0), + "TARGET_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."BOUNTY_HUNTER_TARGETS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table BUILDING_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."BUILDING_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "MAINTENANCE_COST" NUMBER(*,0), + "TIME_LAST_CHECKED" FLOAT(126), + "IS_PUBLIC" CHAR(1 BYTE), + "CITY_ID" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."BUILDING_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table CELL_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."CELL_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "CELL_NUMBER" NUMBER(*,0), + "IS_PUBLIC" CHAR(1 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."CELL_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table CHARACTER_PROFILE +-------------------------------------------------------- + + CREATE TABLE "SWG"."CHARACTER_PROFILE" + ( "CLUSTER_NAME" VARCHAR2(50 BYTE), + "CHARACTER_ID" NUMBER(20,0), + "CHARACTER_NAME" VARCHAR2(127 BYTE), + "OBJECT_NAME" VARCHAR2(127 BYTE), + "X" FLOAT(126), + "Y" FLOAT(126), + "Z" FLOAT(126), + "SCENE_ID" VARCHAR2(50 BYTE), + "CASH_BALANCE" NUMBER(*,0), + "BANK_BALANCE" NUMBER(*,0), + "OBJECT_TEMPLATE_NAME" VARCHAR2(500 BYTE), + "STATION_ID" NUMBER(20,0), + "CONTAINED_BY" NUMBER(20,0), + "CREATE_TIME" DATE, + "PLAYED_TIME" DATE, + "NUM_LOTS" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."CHARACTER_PROFILE" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table CHARACTER_TYPES +-------------------------------------------------------- + + CREATE TABLE "SWG"."CHARACTER_TYPES" + ( "ID" NUMBER, + "DESCRIPTION" VARCHAR2(1000 BYTE) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."CHARACTER_TYPES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table CITY_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."CITY_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."CITY_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table CLOCK +-------------------------------------------------------- + + CREATE TABLE "SWG"."CLOCK" + ( "LAST_SAVE_TIME" NUMBER(*,0), + "LAST_SAVE_TIMESTAMP" DATE + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."CLOCK" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table CLUSTER_LIST +-------------------------------------------------------- + + CREATE TABLE "SWG"."CLUSTER_LIST" + ( "ID" NUMBER, + "NAME" VARCHAR2(255 BYTE), + "NUM_CHARACTERS" NUMBER, + "ADDRESS" VARCHAR2(255 BYTE), + "PORT" NUMBER DEFAULT 44463, + "SECRET" CHAR(1 BYTE), + "LOCKED" CHAR(1 BYTE), + "NOT_RECOMMENDED" CHAR(1 BYTE), + "GROUP_ID" NUMBER(*,0) DEFAULT 1, + "ONLINE_PLAYER_LIMIT" NUMBER DEFAULT 100, + "ONLINE_FREE_TRIAL_LIMIT" NUMBER, + "FREE_TRIAL_CAN_CREATE_CHAR" CHAR(1 BYTE), + "ONLINE_TUTORIAL_LIMIT" NUMBER DEFAULT 350 + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."CLUSTER_LIST" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table CREATURE_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."CREATURE_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "SCALE_FACTOR" FLOAT(126), + "STATES" NUMBER(*,0), + "POSTURE" NUMBER(*,0), + "SHOCK_WOUNDS" NUMBER(*,0), + "MASTER_ID" NUMBER(20,0), + "RANK" NUMBER(*,0), + "BASE_WALK_SPEED" FLOAT(126), + "BASE_RUN_SPEED" FLOAT(126), + "ATTRIBUTE_0" NUMBER(*,0), + "ATTRIBUTE_1" NUMBER(*,0), + "ATTRIBUTE_2" NUMBER(*,0), + "ATTRIBUTE_3" NUMBER(*,0), + "ATTRIBUTE_4" NUMBER(*,0), + "ATTRIBUTE_5" NUMBER(*,0), + "ATTRIBUTE_6" NUMBER(*,0), + "ATTRIBUTE_7" NUMBER(*,0), + "ATTRIBUTE_8" NUMBER(*,0), + "ATTRIBUTE_9" NUMBER(*,0), + "ATTRIBUTE_10" NUMBER(*,0), + "ATTRIBUTE_11" NUMBER(*,0), + "ATTRIBUTE_12" NUMBER(*,0), + "ATTRIBUTE_13" NUMBER(*,0), + "ATTRIBUTE_14" NUMBER(*,0), + "ATTRIBUTE_15" NUMBER(*,0), + "ATTRIBUTE_16" NUMBER(*,0), + "ATTRIBUTE_17" NUMBER(*,0), + "ATTRIBUTE_18" NUMBER(*,0), + "ATTRIBUTE_19" NUMBER(*,0), + "ATTRIBUTE_20" NUMBER(*,0), + "ATTRIBUTE_21" NUMBER(*,0), + "ATTRIBUTE_22" NUMBER(*,0), + "ATTRIBUTE_23" NUMBER(*,0), + "ATTRIBUTE_24" NUMBER(*,0), + "ATTRIBUTE_25" NUMBER(*,0), + "ATTRIBUTE_26" NUMBER(*,0), + "PERSISTED_BUFFS" VARCHAR2(1000 BYTE), + "WS_X" FLOAT(126), + "WS_Y" FLOAT(126), + "WS_Z" FLOAT(126) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."CREATURE_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table DEFAULT_CHARACTER_SLOTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."DEFAULT_CHARACTER_SLOTS" + ( "CHARACTER_TYPE_ID" NUMBER, + "NUM_SLOTS" NUMBER + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."DEFAULT_CHARACTER_SLOTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table DEFAULT_CHAR_LIMITS +-------------------------------------------------------- + + CREATE TABLE "SWG"."DEFAULT_CHAR_LIMITS" + ( "ACCOUNT_LIMIT" NUMBER, + "CLUSTER_LIMIT" NUMBER + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."DEFAULT_CHAR_LIMITS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table DELETE_REASONS +-------------------------------------------------------- + + CREATE TABLE "SWG"."DELETE_REASONS" + ( "REASON_CODE" NUMBER, + "TAG" VARCHAR2(100 BYTE), + "DESCRIPTION" VARCHAR2(1000 BYTE) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."DELETE_REASONS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ERRORLOG +-------------------------------------------------------- + + CREATE TABLE "SWG"."ERRORLOG" + ( "ERROR_ID" NUMBER(20,0), + "TIMESTAMP" DATE DEFAULT SYSDATE, + "ORA_ERRNO" NUMBER(10,0), + "ORA_ERRMSG" VARCHAR2(255 BYTE), + "SCHEMA_NAME" VARCHAR2(30 BYTE), + "MODULE_NAME" VARCHAR2(80 BYTE), + "NOTES" VARCHAR2(4000 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ERRORLOG" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ERRORLOG_LEVEL +-------------------------------------------------------- + + CREATE TABLE "SWG"."ERRORLOG_LEVEL" + ( "LEVELID" NUMBER(10,0) DEFAULT 0 + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ERRORLOG_LEVEL" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ERRORLOG_LEVEL_DESC +-------------------------------------------------------- + + CREATE TABLE "SWG"."ERRORLOG_LEVEL_DESC" + ( "LEVELID" NUMBER(10,0) DEFAULT 0, + "DESCRIP" VARCHAR2(50 BYTE) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ERRORLOG_LEVEL_DESC" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ERRORLOG_RERAISE_LIMITS +-------------------------------------------------------- + + CREATE TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" + ( "PACKAGE" VARCHAR2(30 BYTE), + "PROCEDURE" VARCHAR2(30 BYTE), + "ERRORLIMIT" NUMBER(10,0) DEFAULT 0, + "ERRORCOUNT" NUMBER(10,0) DEFAULT 0, + "UNLIMITED_FLAG" NUMBER(10,0) DEFAULT 0 + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ERRORLOG_RERAISE_LIMITS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table ERRORLOG_VALUES +-------------------------------------------------------- + + CREATE TABLE "SWG"."ERRORLOG_VALUES" + ( "ERROR_ID" NUMBER(20,0), + "ELEMENT_OWNER" VARCHAR2(30 BYTE), + "ELEMENT_NAME" VARCHAR2(30 BYTE), + "ELEMENT_TYPE" VARCHAR2(30 BYTE), + "ELEMENT_VALUE" VARCHAR2(4000 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."ERRORLOG_VALUES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table EXPERIENCE_POINTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."EXPERIENCE_POINTS" + ( "OBJECT_ID" NUMBER, + "EXPERIENCE_TYPE" VARCHAR2(500 BYTE), + "POINTS" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."EXPERIENCE_POINTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table EXTRA_CHARACTER_SLOTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."EXTRA_CHARACTER_SLOTS" + ( "STATION_ID" NUMBER, + "CLUSTER_ID" NUMBER, + "CHARACTER_TYPE_ID" NUMBER, + "NUM_EXTRA_SLOTS" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."EXTRA_CHARACTER_SLOTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table FACTORY_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."FACTORY_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."FACTORY_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table FEATURE_ID_TRANSACTIONS +-------------------------------------------------------- + + CREATE TABLE "SWG"."FEATURE_ID_TRANSACTIONS" + ( "STATION_ID" NUMBER, + "CLUSTER_ID" NUMBER, + "CHARACTER_ID" NUMBER, + "ITEM_ID" VARCHAR2(255 BYTE), + "DATE_UPDATED" DATE, + "COUNT" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."FEATURE_ID_TRANSACTIONS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table FREE_OBJECT_IDS +-------------------------------------------------------- + + CREATE TABLE "SWG"."FREE_OBJECT_IDS" + ( "START_ID" NUMBER(*,0), + "END_ID" NUMBER(*,0) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."FREE_OBJECT_IDS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table GUILD_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."GUILD_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."GUILD_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table HARVESTER_INSTALLATION_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."HARVESTER_INSTALLATION_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "INSTALLED_EFFICIENCY" FLOAT(126), + "MAX_EXTRACTION_RATE" NUMBER(*,0), + "CURRENT_EXTRACTION_RATE" FLOAT(126), + "MAX_HOPPER_AMOUNT" NUMBER(*,0), + "HOPPER_RESOURCE" NUMBER(20,0), + "HOPPER_AMOUNT" FLOAT(126), + "RESOURCE_TYPE" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."HARVESTER_INSTALLATION_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table INSTALLATION_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."INSTALLATION_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "INSTALLATION_TYPE" NUMBER(*,0), + "ACTIVATED" CHAR(1 BYTE), + "TICK_COUNT" FLOAT(126), + "ACTIVATE_START_TIME" FLOAT(126), + "POWER" FLOAT(126), + "POWER_RATE" FLOAT(126) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."INSTALLATION_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table INTANGIBLE_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."INTANGIBLE_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "COUNT" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."INTANGIBLE_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table LOADBEACON_SERVER_MAP +-------------------------------------------------------- + + CREATE TABLE "SWG"."LOADBEACON_SERVER_MAP" + ( "OBJECT_TEMPLATE" VARCHAR2(255 BYTE), + "SERVER_ID" NUMBER(*,0), + "SECONDARY_SERVER_ID" NUMBER(*,0) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."LOADBEACON_SERVER_MAP" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table LOCATION_LISTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."LOCATION_LISTS" + ( "OBJECT_ID" NUMBER, + "LIST_ID" NUMBER, + "SEQUENCE_NUMBER" NUMBER, + "NAME" VARCHAR2(255 BYTE), + "SCENE" VARCHAR2(50 BYTE), + "X" NUMBER, + "Y" NUMBER, + "Z" NUMBER, + "RADIUS" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."LOCATION_LISTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MANF_SCHEMATIC_ATTRIBUTES +-------------------------------------------------------- + + CREATE TABLE "SWG"."MANF_SCHEMATIC_ATTRIBUTES" + ( "OBJECT_ID" NUMBER(20,0), + "ATTRIBUTE_TYPE" VARCHAR2(500 BYTE), + "VALUE" FLOAT(126) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MANF_SCHEMATIC_ATTRIBUTES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MANF_SCHEMATIC_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."MANF_SCHEMATIC_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "CREATOR_ID" NUMBER, + "CREATOR_NAME" VARCHAR2(127 BYTE), + "ITEMS_PER_CONTAINER" NUMBER(*,0), + "MANUFACTURE_TIME" FLOAT(126), + "DRAFT_SCHEMATIC" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MANF_SCHEMATIC_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MANUFACTURE_INST_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."MANUFACTURE_INST_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MANUFACTURE_INST_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MARKET_AUCTIONS +-------------------------------------------------------- + + CREATE TABLE "SWG"."MARKET_AUCTIONS" + ( "ITEM_ID" NUMBER(20,0), + "LOCATION_ID" NUMBER(20,0), + "CREATOR_ID" NUMBER(20,0), + "OWNER_ID" NUMBER(20,0), + "MIN_BID" NUMBER(20,0), + "BUY_NOW_PRICE" NUMBER(20,0), + "AUCTION_TIMER" NUMBER(20,0), + "USER_DESCRIPTION" VARCHAR2(4000 BYTE), + "ITEM_NAME" VARCHAR2(4000 BYTE), + "OOB" VARCHAR2(4000 BYTE), + "CATEGORY" NUMBER(20,0), + "ITEM_TIMER" NUMBER(20,0), + "ACTIVE" NUMBER(20,0), + "ITEM_SIZE" NUMBER(20,0) DEFAULT 1, + "OBJECT_TEMPLATE_ID" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MARKET_AUCTIONS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MARKET_AUCTION_ATTRIBUTES +-------------------------------------------------------- + + CREATE TABLE "SWG"."MARKET_AUCTION_ATTRIBUTES" + ( "ITEM_ID" NUMBER(20,0), + "ATTRIBUTE_NAME" VARCHAR2(1000 BYTE), + "ATTRIBUTE_VALUE" VARCHAR2(1000 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MARKET_AUCTION_ATTRIBUTES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MARKET_AUCTION_BIDS +-------------------------------------------------------- + + CREATE TABLE "SWG"."MARKET_AUCTION_BIDS" + ( "ITEM_ID" NUMBER(20,0), + "BIDDER_ID" NUMBER(20,0), + "BID" NUMBER(20,0), + "MAX_PROXY_BID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MARKET_AUCTION_BIDS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MESSAGES +-------------------------------------------------------- + + CREATE TABLE "SWG"."MESSAGES" + ( "MESSAGE_ID" NUMBER(*,0), + "TARGET" NUMBER(*,0), + "METHOD" VARCHAR2(50 BYTE), + "DATA" VARCHAR2(4000 BYTE), + "CALL_TIME" NUMBER(*,0), + "GUARANTEED" CHAR(1 BYTE), + "DELIVERY_TYPE" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MESSAGES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table MISSION_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."MISSION_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "DIFFICULTY" NUMBER(*,0), + "END_X" FLOAT(126), + "END_Y" FLOAT(126), + "END_Z" FLOAT(126), + "END_CELL" NUMBER(20,0), + "END_SCENE" NUMBER(*,0), + "MISSION_CREATOR" VARCHAR2(127 BYTE), + "REWARD" NUMBER(*,0), + "ROOT_SCRIPT_NAME" VARCHAR2(100 BYTE), + "START_X" FLOAT(126), + "START_Y" FLOAT(126), + "START_Z" FLOAT(126), + "START_CELL" NUMBER(20,0), + "START_SCENE" NUMBER(*,0), + "DESCRIPTION_TABLE" VARCHAR2(100 BYTE), + "DESCRIPTION_TEXT" VARCHAR2(100 BYTE), + "TITLE_TABLE" VARCHAR2(100 BYTE), + "TITLE_TEXT" VARCHAR2(100 BYTE), + "MISSION_HOLDER_ID" NUMBER(20,0), + "STATUS" NUMBER(*,0), + "MISSION_TYPE" NUMBER(*,0), + "TARGET_APPEARANCE" NUMBER(*,0), + "TARGET_NAME" VARCHAR2(127 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."MISSION_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "X" FLOAT(126), + "Y" FLOAT(126), + "Z" FLOAT(126), + "QUATERNION_W" FLOAT(126), + "QUATERNION_X" FLOAT(126), + "QUATERNION_Y" FLOAT(126), + "QUATERNION_Z" FLOAT(126), + "NODE_X" NUMBER(*,0), + "NODE_Y" NUMBER(*,0), + "NODE_Z" NUMBER(*,0), + "TYPE_ID" NUMBER(*,0), + "SCENE_ID" VARCHAR2(50 BYTE), + "CONTROLLER_TYPE" NUMBER(*,0), + "DELETED" NUMBER(*,0), + "OBJECT_NAME" VARCHAR2(127 BYTE), + "VOLUME" NUMBER(*,0), + "CONTAINED_BY" NUMBER(20,0), + "SLOT_ARRANGEMENT" NUMBER(*,0), + "PLAYER_CONTROLLED" CHAR(1 BYTE), + "CACHE_VERSION" NUMBER(*,0), + "LOAD_CONTENTS" CHAR(1 BYTE), + "CASH_BALANCE" NUMBER(*,0), + "BANK_BALANCE" NUMBER(*,0), + "COMPLEXITY" FLOAT(126), + "NAME_STRING_TABLE" VARCHAR2(500 BYTE), + "NAME_STRING_TEXT" VARCHAR2(500 BYTE), + "OBJECT_TEMPLATE_ID" NUMBER(*,0), + "STATIC_ITEM_NAME" VARCHAR2(128 BYTE), + "STATIC_ITEM_VERSION" NUMBER(*,0), + "CONVERSION_ID" NUMBER(*,0), + "DELETED_DATE" DATE, + "LOAD_WITH" NUMBER(20,0), + "OBJVAR_0_NAME" VARCHAR2(50 BYTE), + "OBJVAR_0_TYPE" NUMBER(*,0), + "OBJVAR_0_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_1_NAME" VARCHAR2(50 BYTE), + "OBJVAR_1_TYPE" NUMBER(*,0), + "OBJVAR_1_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_2_NAME" VARCHAR2(50 BYTE), + "OBJVAR_2_TYPE" NUMBER(*,0), + "OBJVAR_2_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_3_NAME" VARCHAR2(50 BYTE), + "OBJVAR_3_TYPE" NUMBER(*,0), + "OBJVAR_3_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_4_NAME" VARCHAR2(50 BYTE), + "OBJVAR_4_TYPE" NUMBER(*,0), + "OBJVAR_4_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_5_NAME" VARCHAR2(50 BYTE), + "OBJVAR_5_TYPE" NUMBER(*,0), + "OBJVAR_5_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_6_NAME" VARCHAR2(50 BYTE), + "OBJVAR_6_TYPE" NUMBER(*,0), + "OBJVAR_6_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_7_NAME" VARCHAR2(50 BYTE), + "OBJVAR_7_TYPE" NUMBER(*,0), + "OBJVAR_7_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_8_NAME" VARCHAR2(50 BYTE), + "OBJVAR_8_TYPE" NUMBER(*,0), + "OBJVAR_8_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_9_NAME" VARCHAR2(50 BYTE), + "OBJVAR_9_TYPE" NUMBER(*,0), + "OBJVAR_9_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_10_NAME" VARCHAR2(50 BYTE), + "OBJVAR_10_TYPE" NUMBER(*,0), + "OBJVAR_10_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_11_NAME" VARCHAR2(50 BYTE), + "OBJVAR_11_TYPE" NUMBER(*,0), + "OBJVAR_11_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_12_NAME" VARCHAR2(50 BYTE), + "OBJVAR_12_TYPE" NUMBER(*,0), + "OBJVAR_12_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_13_NAME" VARCHAR2(50 BYTE), + "OBJVAR_13_TYPE" NUMBER(*,0), + "OBJVAR_13_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_14_NAME" VARCHAR2(50 BYTE), + "OBJVAR_14_TYPE" NUMBER(*,0), + "OBJVAR_14_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_15_NAME" VARCHAR2(50 BYTE), + "OBJVAR_15_TYPE" NUMBER(*,0), + "OBJVAR_15_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_16_NAME" VARCHAR2(50 BYTE), + "OBJVAR_16_TYPE" NUMBER(*,0), + "OBJVAR_16_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_17_NAME" VARCHAR2(50 BYTE), + "OBJVAR_17_TYPE" NUMBER(*,0), + "OBJVAR_17_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_18_NAME" VARCHAR2(50 BYTE), + "OBJVAR_18_TYPE" NUMBER(*,0), + "OBJVAR_18_VALUE" VARCHAR2(50 BYTE), + "OBJVAR_19_NAME" VARCHAR2(50 BYTE), + "OBJVAR_19_TYPE" NUMBER(*,0), + "OBJVAR_19_VALUE" VARCHAR2(50 BYTE), + "SCRIPT_LIST" VARCHAR2(2000 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table OBJECT_LIST +-------------------------------------------------------- + + CREATE GLOBAL TEMPORARY TABLE "SWG"."OBJECT_LIST" + ( "OBJECT_ID" NUMBER(20,0), + "CONTAINER_LEVEL" NUMBER + ) ON COMMIT DELETE ROWS ; + GRANT ALTER, DELETE, INDEX, INSERT, SELECT, UPDATE, REFERENCES, ON COMMIT REFRESH, QUERY REWRITE, DEBUG, FLASHBACK ON "SWG"."OBJECT_LIST" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table OBJECT_TEMPLATES +-------------------------------------------------------- + + CREATE TABLE "SWG"."OBJECT_TEMPLATES" + ( "ID" NUMBER, + "NAME" VARCHAR2(255 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."OBJECT_TEMPLATES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table OBJECT_VARIABLES +-------------------------------------------------------- + + CREATE TABLE "SWG"."OBJECT_VARIABLES" + ( "OBJECT_ID" NUMBER(20,0), + "NAME_ID" NUMBER, + "TYPE" NUMBER(*,0), + "VALUE" VARCHAR2(1000 BYTE), + "DETACHED" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."OBJECT_VARIABLES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table OBJECT_VARIABLE_NAMES +-------------------------------------------------------- + + CREATE TABLE "SWG"."OBJECT_VARIABLE_NAMES" + ( "ID" NUMBER(20,0), + "NAME" VARCHAR2(500 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."OBJECT_VARIABLE_NAMES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PLANET_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."PLANET_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "PLANET_NAME" VARCHAR2(100 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PLANET_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PLAYERS +-------------------------------------------------------- + + CREATE TABLE "SWG"."PLAYERS" + ( "CHARACTER_OBJECT" NUMBER(*,0), + "STATION_ID" NUMBER(*,0), + "UC_CHARACTER_NAME" VARCHAR2(127 BYTE), + "CHARACTER_FULL_NAME" VARCHAR2(127 BYTE), + "CREATE_TIME" DATE, + "LAST_LOGIN_TIME" DATE DEFAULT sysdate + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PLAYERS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PLAYER_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."PLAYER_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "STATION_ID" NUMBER(*,0), + "PERSONAL_PROFILE_ID" VARCHAR2(200 BYTE), + "CHARACTER_PROFILE_ID" VARCHAR2(200 BYTE), + "SKILL_TITLE" VARCHAR2(200 BYTE), + "BORN_DATE" NUMBER(*,0), + "PLAYED_TIME" NUMBER(*,0), + "FORCE_REGEN_RATE" FLOAT(126), + "FORCE_POWER" NUMBER(*,0), + "MAX_FORCE_POWER" NUMBER(*,0), + "NUM_LOTS" NUMBER(*,0), + "ACTIVE_QUESTS" VARCHAR2(512 BYTE), + "COMPLETED_QUESTS" VARCHAR2(512 BYTE), + "CURRENT_QUEST" NUMBER(*,0), + "QUESTS" VARCHAR2(4000 BYTE), + "ROLE_ICON_CHOICE" NUMBER(*,0), + "QUESTS2" VARCHAR2(4000 BYTE), + "QUESTS3" VARCHAR2(4000 BYTE), + "QUESTS4" VARCHAR2(4000 BYTE), + "SKILL_TEMPLATE" VARCHAR2(200 BYTE), + "WORKING_SKILL" VARCHAR2(200 BYTE), + "CURRENT_GCW_POINTS" NUMBER(*,0), + "CURRENT_GCW_RATING" NUMBER(*,0), + "CURRENT_PVP_KILLS" NUMBER(*,0), + "LIFETIME_GCW_POINTS" NUMBER(*,0), + "MAX_GCW_IMPERIAL_RATING" NUMBER(*,0), + "MAX_GCW_REBEL_RATING" NUMBER(*,0), + "LIFETIME_PVP_KILLS" NUMBER(*,0), + "NEXT_GCW_RATING_CALC_TIME" NUMBER(*,0), + "COLLECTIONS" VARCHAR2(4000 BYTE), + "SHOW_BACKPACK" CHAR(1 BYTE), + "SHOW_HELMET" CHAR(1 BYTE), + "COLLECTIONS2" VARCHAR2(4000 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PLAYER_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PLAYER_QUEST_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."PLAYER_QUEST_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "TITLE" VARCHAR2(256 BYTE), + "DESCRIPTION" VARCHAR2(4000 BYTE), + "CREATOR" NUMBER(20,0), + "TOTAL_TASKS" NUMBER(*,0), + "DIFFICULTY" NUMBER(*,0), + "TASK_TITLE1" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION1" VARCHAR2(4000 BYTE), + "TASK_TITLE2" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION2" VARCHAR2(4000 BYTE), + "TASK_TITLE3" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION3" VARCHAR2(4000 BYTE), + "TASK_TITLE4" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION4" VARCHAR2(4000 BYTE), + "TASK_TITLE5" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION5" VARCHAR2(4000 BYTE), + "TASK_TITLE6" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION6" VARCHAR2(4000 BYTE), + "TASK_TITLE7" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION7" VARCHAR2(4000 BYTE), + "TASK_TITLE8" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION8" VARCHAR2(4000 BYTE), + "TASK_TITLE9" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION9" VARCHAR2(4000 BYTE), + "TASK_TITLE10" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION10" VARCHAR2(4000 BYTE), + "TASK_TITLE11" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION11" VARCHAR2(4000 BYTE), + "TASK_TITLE12" VARCHAR2(128 BYTE), + "TASK_DESCRIPTION12" VARCHAR2(4000 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PLAYER_QUEST_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PROPERTY_LISTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."PROPERTY_LISTS" + ( "OBJECT_ID" NUMBER(20,0), + "LIST_ID" NUMBER(*,0), + "VALUE" VARCHAR2(500 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PROPERTY_LISTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PUBLISH_PLAYER_FIXUP +-------------------------------------------------------- + + CREATE TABLE "SWG"."PUBLISH_PLAYER_FIXUP" + ( "PLAYER_OBJECT_ID" NUMBER(20,0), + "X" NUMBER, + "Y" NUMBER, + "Z" NUMBER + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PUBLISH_PLAYER_FIXUP" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PURGE_ACCOUNTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."PURGE_ACCOUNTS" + ( "STATION_ID" NUMBER, + "PURGE_PHASE" NUMBER, + "PURGE_START_DATE" DATE, + "PURGE_PHASE_DATE" DATE, + "PURGE_LOCK" DATE + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PURGE_ACCOUNTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table PURGE_PHASES +-------------------------------------------------------- + + CREATE TABLE "SWG"."PURGE_PHASES" + ( "ID" NUMBER, + "DESCRIPTION" VARCHAR2(200 BYTE) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."PURGE_PHASES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table RESOURCE_CONTAINER_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."RESOURCE_CONTAINER_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "RESOURCE_TYPE" NUMBER(20,0), + "QUANTITY" NUMBER(*,0), + "SOURCE" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."RESOURCE_CONTAINER_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table RESOURCE_TYPES +-------------------------------------------------------- + + CREATE TABLE "SWG"."RESOURCE_TYPES" + ( "RESOURCE_ID" NUMBER(20,0), + "RESOURCE_NAME" VARCHAR2(100 BYTE), + "RESOURCE_CLASS" VARCHAR2(100 BYTE), + "ATTRIBUTES" VARCHAR2(1024 BYTE), + "FRACTAL_SEEDS" VARCHAR2(1024 BYTE), + "DEPLETED_TIMESTAMP" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."RESOURCE_TYPES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table SCRIPTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."SCRIPTS" + ( "OBJECT_ID" NUMBER(20,0), + "SEQUENCE_NO" NUMBER(*,0), + "SCRIPT" VARCHAR2(100 BYTE), + "DETACHED" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."SCRIPTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table SCRUNCHER +-------------------------------------------------------- + + CREATE TABLE "SWG"."SCRUNCHER" + ( "NEW_OBJECT_ID" NUMBER(20,0), + "OLD_OBJECT_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."SCRUNCHER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table SHIP_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."SHIP_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "SLIDE_DAMPENER" FLOAT(126), + "CURRENT_CHASSIS_HIT_POINTS" FLOAT(126), + "MAXIMUM_CHASSIS_HIT_POINTS" FLOAT(126), + "CHASSIS_TYPE" NUMBER(*,0), + "CMP_ARMOR_HP_MAXIMUM" VARCHAR2(400 BYTE), + "CMP_ARMOR_HP_CURRENT" VARCHAR2(400 BYTE), + "CMP_EFFICIENCY_GENERAL" VARCHAR2(400 BYTE), + "CMP_EFFICIENCY_ENG" VARCHAR2(400 BYTE), + "CMP_ENG_MAINTENANCE" VARCHAR2(400 BYTE), + "CMP_MASS" VARCHAR2(400 BYTE), + "CMP_CRC" VARCHAR2(500 BYTE), + "CMP_HP_CURRENT" VARCHAR2(400 BYTE), + "CMP_HP_MAXIMUM" VARCHAR2(400 BYTE), + "CMP_FLAGS" VARCHAR2(400 BYTE), + "CMP_NAMES" VARCHAR2(4000 BYTE), + "WEAPON_DAMAGE_MAXIMUM" VARCHAR2(400 BYTE), + "WEAPON_DAMAGE_MINIMUM" VARCHAR2(400 BYTE), + "WEAPON_EFFECTIVENESS_SHIELDS" VARCHAR2(400 BYTE), + "WEAPON_EFFECTIVENESS_ARMOR" VARCHAR2(400 BYTE), + "WEAPON_ENG_PER_SHOT" VARCHAR2(400 BYTE), + "WEAPON_REFIRE_RATE" VARCHAR2(400 BYTE), + "WEAPON_AMMO_CURRENT" VARCHAR2(400 BYTE), + "WEAPON_AMMO_MAXIMUM" VARCHAR2(400 BYTE), + "WEAPON_AMMO_TYPE" VARCHAR2(400 BYTE), + "SHIELD_HP_FRONT_MAXIMUM" FLOAT(126), + "SHIELD_HP_BACK_MAXIMUM" FLOAT(126), + "SHIELD_RECHARGE_RATE" FLOAT(126), + "CAPACITOR_ENG_MAXIMUM" FLOAT(126), + "CAPACITOR_ENG_RECHARGE_RATE" FLOAT(126), + "ENGINE_ACC_RATE" FLOAT(126), + "ENGINE_DECELERATION_RATE" FLOAT(126), + "ENGINE_PITCH_ACC_RATE" FLOAT(126), + "ENGINE_YAW_ACC_RATE" FLOAT(126), + "ENGINE_ROLL_ACC_RATE" FLOAT(126), + "ENGINE_PITCH_RATE_MAXIMUM" FLOAT(126), + "ENGINE_YAW_RATE_MAXIMUM" FLOAT(126), + "ENGINE_ROLL_RATE_MAXIMUM" FLOAT(126), + "ENGINE_SPEED_MAXIMUM" FLOAT(126), + "REACTOR_ENG_GENERATION_RATE" FLOAT(126), + "BOOSTER_ENG_MAXIMUM" FLOAT(126), + "BOOSTER_ENG_RECHARGE_RATE" FLOAT(126), + "BOOSTER_ENG_CONSUMPTION_RATE" FLOAT(126), + "BOOSTER_ACC" FLOAT(126), + "BOOSTER_SPEED_MAXIMUM" FLOAT(126), + "DROID_IF_CMD_SPEED" FLOAT(126), + "INSTALLED_DCD" NUMBER(20,0), + "CHASSIS_CMP_MASS_MAXIMUM" FLOAT(126), + "CMP_CREATORS" VARCHAR2(400 BYTE), + "CARGO_HOLD_CONTENTS_MAXIMUM" NUMBER, + "CARGO_HOLD_CONTENTS_CURRENT" NUMBER, + "CARGO_HOLD_CONTENTS" VARCHAR2(500 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."SHIP_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table STATIC_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."STATIC_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."STATIC_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table STATUSES +-------------------------------------------------------- + + CREATE TABLE "SWG"."STATUSES" + ( "ID" NUMBER, + "DESCRIPTION" VARCHAR2(200 BYTE), + "DO_PURGE" CHAR(1 BYTE), + "REVIEWED" CHAR(1 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."STATUSES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table SWG_CHARACTERS +-------------------------------------------------------- + + CREATE TABLE "SWG"."SWG_CHARACTERS" + ( "STATION_ID" NUMBER, + "CLUSTER_ID" NUMBER, + "CHARACTER_NAME" VARCHAR2(127 BYTE), + "OBJECT_ID" NUMBER, + "CHARACTER_TYPE" NUMBER, + "TEMPLATE_ID" NUMBER, + "ENABLED" CHAR(1 BYTE) DEFAULT 'Y' + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."SWG_CHARACTERS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table TANGIBLE_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."TANGIBLE_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "MAX_HIT_POINTS" NUMBER(*,0), + "OWNER_ID" NUMBER(*,0), + "VISIBLE" CHAR(1 BYTE), + "APPEARANCE_DATA" VARCHAR2(2000 BYTE), + "INTEREST_RADIUS" NUMBER(*,0), + "PVP_TYPE" NUMBER(*,0), + "PVP_FACTION" NUMBER(*,0), + "DAMAGE_TAKEN" NUMBER(*,0), + "CUSTOM_APPEARANCE" VARCHAR2(2000 BYTE), + "COUNT" NUMBER(*,0), + "CONDITION" NUMBER(*,0), + "CREATOR_ID" NUMBER(20,0), + "SOURCE_DRAFT_SCHEMATIC" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."TANGIBLE_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table TEMP_CHARACTERS +-------------------------------------------------------- + + CREATE TABLE "SWG"."TEMP_CHARACTERS" + ( "TRANSACTION_TYPE" NUMBER, + "STATION_ID" NUMBER, + "CLUSTER_NAME" VARCHAR2(120 BYTE), + "CHARACTER_NAME" VARCHAR2(30 BYTE), + "OBJECT_ID" NUMBER, + "TEMPLATE_NAME" VARCHAR2(120 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."TEMP_CHARACTERS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table TEMP_FREE_OBJECT_IDS +-------------------------------------------------------- + + CREATE GLOBAL TEMPORARY TABLE "SWG"."TEMP_FREE_OBJECT_IDS" + ( "START_ID" NUMBER(*,0), + "END_ID" NUMBER(*,0) + ) ON COMMIT DELETE ROWS ; + GRANT SELECT ON "SWG"."TEMP_FREE_OBJECT_IDS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table TOKEN_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."TOKEN_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "REFERENCE" NUMBER(20,0), + "TARGET_SERVER_TEMPLATE_NAME" VARCHAR2(500 BYTE), + "TARGET_SHARED_TEMPLATE_NAME" VARCHAR2(500 BYTE), + "WAYPOINT" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."TOKEN_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table UNIVERSE_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."UNIVERSE_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."UNIVERSE_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table VEHICLE_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."VEHICLE_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "BOGUS" NUMBER(*,0) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."VEHICLE_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table VERSION_NUMBER +-------------------------------------------------------- + + CREATE TABLE "SWG"."VERSION_NUMBER" + ( "VERSION_NUMBER" NUMBER(*,0), + "MIN_VERSION_NUMBER" NUMBER(*,0), + "GOLDDATA" VARCHAR2(100 BYTE), + "BRANCH_NAME" VARCHAR2(30 BYTE) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."VERSION_NUMBER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table WAYPOINTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."WAYPOINTS" + ( "OBJECT_ID" NUMBER(20,0), + "WAYPOINT_ID" NUMBER(20,0), + "APPEARANCE_NAME_CRC" NUMBER(*,0), + "LOCATION_X" FLOAT(126), + "LOCATION_Y" FLOAT(126), + "LOCATION_Z" FLOAT(126), + "LOCATION_CELL" NUMBER(20,0), + "LOCATION_SCENE" NUMBER(*,0), + "NAME" VARCHAR2(512 BYTE), + "COLOR" NUMBER(*,0), + "ACTIVE" CHAR(1 BYTE) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."WAYPOINTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Table WEAPON_OBJECTS +-------------------------------------------------------- + + CREATE TABLE "SWG"."WEAPON_OBJECTS" + ( "OBJECT_ID" NUMBER(20,0), + "MIN_DAMAGE" NUMBER(*,0), + "MAX_DAMAGE" NUMBER(*,0), + "DAMAGE_TYPE" NUMBER(*,0), + "ELEMENTAL_TYPE" NUMBER(*,0), + "ELEMENTAL_VALUE" NUMBER(*,0), + "ATTACK_SPEED" FLOAT(126), + "WOUND_CHANCE" FLOAT(126), + "ACCURACY" NUMBER(*,0), + "ATTACK_COST" NUMBER(*,0), + "DAMAGE_RADIUS" FLOAT(126), + "MIN_RANGE" FLOAT(126), + "MAX_RANGE" FLOAT(126) + ) SEGMENT CREATION DEFERRED + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; + GRANT SELECT ON "SWG"."WEAPON_OBJECTS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for View CHARACTER_VIEW +-------------------------------------------------------- + + CREATE OR REPLACE FORCE VIEW "SWG"."CHARACTER_VIEW" ("STATION_ID", "CHARACTER_OBJECT", "OBJECT_TEMPLATE_ID", "SCENE_ID", "OBJECT_NAME", "CONTAINER", "X", "Y", "Z") AS + select p.station_id, p.character_object, o.object_template_id, o.scene_id, o.object_name, +(select object_id from objects where contained_by=0 start with object_id=character_object connect by prior contained_by=object_id) container, +(select x from objects where contained_by=0 start with object_id=character_object connect by prior contained_by=object_id) x, +(select y from objects where contained_by=0 start with object_id=character_object connect by prior contained_by=object_id) y, +(select z from objects where contained_by=0 start with object_id=character_object connect by prior contained_by=object_id) z +from players p, objects o +where p.character_object = o.object_id + and o.deleted = 0; +-------------------------------------------------------- +-- DDL for View OBJECTS_VIEW +-------------------------------------------------------- + + CREATE OR REPLACE FORCE VIEW "SWG"."OBJECTS_VIEW" ("OBJECT_ID", "X", "Y", "Z", "QUATERNION_W", "QUATERNION_X", "QUATERNION_Y", "QUATERNION_Z", "NODE_X", "NODE_Y", "NODE_Z", "TYPE_ID", "SCENE_ID", "CONTROLLER_TYPE", "DELETED", "OBJECT_NAME", "VOLUME", "CONTAINED_BY", "SLOT_ARRANGEMENT", "PLAYER_CONTROLLED", "CACHE_VERSION", "LOAD_CONTENTS", "CASH_BALANCE", "BANK_BALANCE", "COMPLEXITY", "NAME_STRING_TABLE", "NAME_STRING_TEXT", "OBJECT_TEMPLATE_ID", "STATIC_ITEM_NAME", "STATIC_ITEM_VERSION", "CONVERSION_ID", "DELETED_DATE", "LOAD_WITH", "OBJVAR_0_NAME", "OBJVAR_0_TYPE", "OBJVAR_0_VALUE", "OBJVAR_1_NAME", "OBJVAR_1_TYPE", "OBJVAR_1_VALUE", "OBJVAR_2_NAME", "OBJVAR_2_TYPE", "OBJVAR_2_VALUE", "OBJVAR_3_NAME", "OBJVAR_3_TYPE", "OBJVAR_3_VALUE", "OBJVAR_4_NAME", "OBJVAR_4_TYPE", "OBJVAR_4_VALUE", "OBJVAR_5_NAME", "OBJVAR_5_TYPE", "OBJVAR_5_VALUE", "OBJVAR_6_NAME", "OBJVAR_6_TYPE", "OBJVAR_6_VALUE", "OBJVAR_7_NAME", "OBJVAR_7_TYPE", "OBJVAR_7_VALUE", "OBJVAR_8_NAME", "OBJVAR_8_TYPE", "OBJVAR_8_VALUE", "OBJVAR_9_NAME", "OBJVAR_9_TYPE", "OBJVAR_9_VALUE", "OBJVAR_10_NAME", "OBJVAR_10_TYPE", "OBJVAR_10_VALUE", "OBJVAR_11_NAME", "OBJVAR_11_TYPE", "OBJVAR_11_VALUE", "OBJVAR_12_NAME", "OBJVAR_12_TYPE", "OBJVAR_12_VALUE", "OBJVAR_13_NAME", "OBJVAR_13_TYPE", "OBJVAR_13_VALUE", "OBJVAR_14_NAME", "OBJVAR_14_TYPE", "OBJVAR_14_VALUE", "OBJVAR_15_NAME", "OBJVAR_15_TYPE", "OBJVAR_15_VALUE", "OBJVAR_16_NAME", "OBJVAR_16_TYPE", "OBJVAR_16_VALUE", "OBJVAR_17_NAME", "OBJVAR_17_TYPE", "OBJVAR_17_VALUE", "OBJVAR_18_NAME", "OBJVAR_18_TYPE", "OBJVAR_18_VALUE", "OBJVAR_19_NAME", "OBJVAR_19_TYPE", "OBJVAR_19_VALUE", "SCRIPT_LIST", "OBJECT_TEMPLATE") AS + select o."OBJECT_ID",o."X",o."Y",o."Z",o."QUATERNION_W",o."QUATERNION_X",o."QUATERNION_Y",o."QUATERNION_Z",o."NODE_X",o."NODE_Y",o."NODE_Z",o."TYPE_ID",o."SCENE_ID",o."CONTROLLER_TYPE",o."DELETED",o."OBJECT_NAME",o."VOLUME",o."CONTAINED_BY",o."SLOT_ARRANGEMENT",o."PLAYER_CONTROLLED",o."CACHE_VERSION",o."LOAD_CONTENTS",o."CASH_BALANCE",o."BANK_BALANCE",o."COMPLEXITY",o."NAME_STRING_TABLE",o."NAME_STRING_TEXT",o."OBJECT_TEMPLATE_ID",o."STATIC_ITEM_NAME",o."STATIC_ITEM_VERSION",o."CONVERSION_ID",o."DELETED_DATE",o."LOAD_WITH",o."OBJVAR_0_NAME",o."OBJVAR_0_TYPE",o."OBJVAR_0_VALUE",o."OBJVAR_1_NAME",o."OBJVAR_1_TYPE",o."OBJVAR_1_VALUE",o."OBJVAR_2_NAME",o."OBJVAR_2_TYPE",o."OBJVAR_2_VALUE",o."OBJVAR_3_NAME",o."OBJVAR_3_TYPE",o."OBJVAR_3_VALUE",o."OBJVAR_4_NAME",o."OBJVAR_4_TYPE",o."OBJVAR_4_VALUE",o."OBJVAR_5_NAME",o."OBJVAR_5_TYPE",o."OBJVAR_5_VALUE",o."OBJVAR_6_NAME",o."OBJVAR_6_TYPE",o."OBJVAR_6_VALUE",o."OBJVAR_7_NAME",o."OBJVAR_7_TYPE",o."OBJVAR_7_VALUE",o."OBJVAR_8_NAME",o."OBJVAR_8_TYPE",o."OBJVAR_8_VALUE",o."OBJVAR_9_NAME",o."OBJVAR_9_TYPE",o."OBJVAR_9_VALUE",o."OBJVAR_10_NAME",o."OBJVAR_10_TYPE",o."OBJVAR_10_VALUE",o."OBJVAR_11_NAME",o."OBJVAR_11_TYPE",o."OBJVAR_11_VALUE",o."OBJVAR_12_NAME",o."OBJVAR_12_TYPE",o."OBJVAR_12_VALUE",o."OBJVAR_13_NAME",o."OBJVAR_13_TYPE",o."OBJVAR_13_VALUE",o."OBJVAR_14_NAME",o."OBJVAR_14_TYPE",o."OBJVAR_14_VALUE",o."OBJVAR_15_NAME",o."OBJVAR_15_TYPE",o."OBJVAR_15_VALUE",o."OBJVAR_16_NAME",o."OBJVAR_16_TYPE",o."OBJVAR_16_VALUE",o."OBJVAR_17_NAME",o."OBJVAR_17_TYPE",o."OBJVAR_17_VALUE",o."OBJVAR_18_NAME",o."OBJVAR_18_TYPE",o."OBJVAR_18_VALUE",o."OBJVAR_19_NAME",o."OBJVAR_19_TYPE",o."OBJVAR_19_VALUE",o."SCRIPT_LIST", t.name object_template +from objects o, object_templates t +where o.object_template_id = t.id; +-------------------------------------------------------- +-- DDL for View OBJECT_VARIABLES_VIEW +-------------------------------------------------------- + + CREATE OR REPLACE FORCE VIEW "SWG"."OBJECT_VARIABLES_VIEW" ("OBJECT_ID", "NAME", "TYPE", "VALUE", "PACKED") AS + select v.object_id, n.name, v.type, v.value, -1 packed +from object_variables v, object_variable_names n +where v.name_id = n.id +and v.detached = 0 +union all +select o.object_id, o.objvar_0_name, o.objvar_0_type, o.objvar_0_value, 0 +from objects o +where o.objvar_0_type >= 0 +union all +select o.object_id, o.objvar_1_name, o.objvar_1_type, o.objvar_1_value, 1 +from objects o +where o.objvar_1_type >= 0 +union all +select o.object_id, o.objvar_2_name, o.objvar_2_type, o.objvar_2_value, 2 +from objects o +where o.objvar_2_type >= 0 +union all +select o.object_id, o.objvar_3_name, o.objvar_3_type, o.objvar_3_value, 3 +from objects o +where o.objvar_3_type >= 0 +union all +select o.object_id, o.objvar_4_name, o.objvar_4_type, o.objvar_4_value, 4 +from objects o +where o.objvar_4_type >= 0 +union all +select o.object_id, o.objvar_5_name, o.objvar_5_type, o.objvar_5_value, 5 +from objects o +where o.objvar_5_type >= 0 +union all +select o.object_id, o.objvar_6_name, o.objvar_6_type, o.objvar_6_value, 6 +from objects o +where o.objvar_6_type >= 0 +union all +select o.object_id, o.objvar_7_name, o.objvar_7_type, o.objvar_7_value, 7 +from objects o +where o.objvar_7_type >= 0 +union all +select o.object_id, o.objvar_8_name, o.objvar_8_type, o.objvar_8_value, 8 +from objects o +where o.objvar_8_type >= 0 +union all +select o.object_id, o.objvar_9_name, o.objvar_9_type, o.objvar_9_value, 9 +from objects o +where o.objvar_9_type >= 0 +union all +select o.object_id, o.objvar_10_name, o.objvar_10_type, o.objvar_10_value, 10 +from objects o +where o.objvar_10_type >= 0 +union all +select o.object_id, o.objvar_11_name, o.objvar_11_type, o.objvar_11_value, 11 +from objects o +where o.objvar_11_type >= 0 +union all +select o.object_id, o.objvar_12_name, o.objvar_12_type, o.objvar_12_value, 12 +from objects o +where o.objvar_12_type >= 0 +union all +select o.object_id, o.objvar_13_name, o.objvar_13_type, o.objvar_13_value, 13 +from objects o +where o.objvar_13_type >= 0 +union all +select o.object_id, o.objvar_14_name, o.objvar_14_type, o.objvar_14_value, 14 +from objects o +where o.objvar_14_type >= 0 +union all +select o.object_id, o.objvar_15_name, o.objvar_15_type, o.objvar_15_value, 15 +from objects o +where o.objvar_15_type >= 0 +union all +select o.object_id, o.objvar_16_name, o.objvar_16_type, o.objvar_16_value, 16 +from objects o +where o.objvar_16_type >= 0 +union all +select o.object_id, o.objvar_17_name, o.objvar_17_type, o.objvar_17_value, 17 +from objects o +where o.objvar_17_type >= 0 +union all +select o.object_id, o.objvar_18_name, o.objvar_18_type, o.objvar_18_value, 18 +from objects o +where o.objvar_18_type >= 0 +union all +select o.object_id, o.objvar_19_name, o.objvar_19_type, o.objvar_19_value, 19 +from objects o +where o.objvar_19_type >= 0; +-------------------------------------------------------- +-- DDL for Index PK_WAYPOINTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_WAYPOINTS" ON "SWG"."WAYPOINTS" ("WAYPOINT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_DELETE_REASONS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_DELETE_REASONS" ON "SWG"."DELETE_REASONS" ("REASON_CODE") + PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_BIOGRAPHIES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_BIOGRAPHIES" ON "SWG"."BIOGRAPHIES" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_PLAYER_QUEST_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_PLAYER_QUEST_OBJECTS" ON "SWG"."PLAYER_QUEST_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_WEAPON_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_WEAPON_OBJECTS" ON "SWG"."WEAPON_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_TANGIBLE_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_TANGIBLE_OBJECTS" ON "SWG"."TANGIBLE_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_MARKET_AUCTION_ATTRIBUTES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_MARKET_AUCTION_ATTRIBUTES" ON "SWG"."MARKET_AUCTION_ATTRIBUTES" ("ITEM_ID", "ATTRIBUTE_NAME") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_ACCOUNT_REWARD_EVENTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_ACCOUNT_REWARD_EVENTS" ON "SWG"."ACCOUNT_REWARD_EVENTS" ("STATION_ID", "EVENT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_PROPERTY_LISTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_PROPERTY_LISTS" ON "SWG"."PROPERTY_LISTS" ("OBJECT_ID", "LIST_ID", "VALUE") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index OBJECT_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."OBJECT_IDX" ON "SWG"."MESSAGES" ("TARGET") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_MANF_SCHEMATIC_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_MANF_SCHEMATIC_OBJECTS" ON "SWG"."MANF_SCHEMATIC_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_CLOCK +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_CLOCK" ON "SWG"."CLOCK" ("LAST_SAVE_TIME") + PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_OBJECT_VARIABLES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_OBJECT_VARIABLES" ON "SWG"."OBJECT_VARIABLES" ("OBJECT_ID", "NAME_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_ACCOUNT_REWARD_ITEMS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_ACCOUNT_REWARD_ITEMS" ON "SWG"."ACCOUNT_REWARD_ITEMS" ("STATION_ID", "ITEM_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index OBJECT_VARIABLE_NAME_INDEX +-------------------------------------------------------- + + CREATE INDEX "SWG"."OBJECT_VARIABLE_NAME_INDEX" ON "SWG"."OBJECT_VARIABLE_NAMES" ("NAME") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_RERAISE_LIMITS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_RERAISE_LIMITS" ON "SWG"."ERRORLOG_RERAISE_LIMITS" ("PACKAGE", "PROCEDURE") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_LOADBEACON_SERVER_MAP +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_LOADBEACON_SERVER_MAP" ON "SWG"."LOADBEACON_SERVER_MAP" ("OBJECT_TEMPLATE") + PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index CONTAINER_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."CONTAINER_IDX" ON "SWG"."OBJECTS" ("CONTAINED_BY") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_FACTORY_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_FACTORY_OBJECTS" ON "SWG"."FACTORY_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_ACCOUNTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_ACCOUNTS" ON "SWG"."ACCOUNTS" ("STATION_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index ACCOUNT_MAP_INDEX1 +-------------------------------------------------------- + + CREATE INDEX "SWG"."ACCOUNT_MAP_INDEX1" ON "SWG"."ACCOUNT_MAP" ("CHILD_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index AUCTION_LOCATION_NAME_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."AUCTION_LOCATION_NAME_IDX" ON "SWG"."AUCTION_LOCATIONS" ("LOCATION_NAME") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_PLAYER_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_PLAYER_OBJECTS" ON "SWG"."PLAYER_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index ACCOUNT_INFO_PK +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."ACCOUNT_INFO_PK" ON "SWG"."ACCOUNT_INFO" ("STATION_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_SWG_CHARACTER +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_SWG_CHARACTER" ON "SWG"."SWG_CHARACTERS" ("STATION_ID", "CLUSTER_ID", "CHARACTER_NAME") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_FREE_OBJECT_IDS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_FREE_OBJECT_IDS" ON "SWG"."FREE_OBJECT_IDS" ("START_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PLAYERS_STATION_ID_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."PLAYERS_STATION_ID_IDX" ON "SWG"."PLAYERS" ("STATION_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_MARKET_AUCTIONS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_MARKET_AUCTIONS" ON "SWG"."MARKET_AUCTIONS" ("ITEM_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_ERRORLOG +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_ERRORLOG" ON "SWG"."ERRORLOG" ("ERROR_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_MANUFACTURE_INST_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_MANUFACTURE_INST_OBJECTS" ON "SWG"."MANUFACTURE_INST_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_PLAYERS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_PLAYERS" ON "SWG"."PLAYERS" ("CHARACTER_OBJECT") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_LOCATION_LISTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_LOCATION_LISTS" ON "SWG"."LOCATION_LISTS" ("OBJECT_ID", "LIST_ID", "SEQUENCE_NUMBER") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_RESOURCE_TYPES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_RESOURCE_TYPES" ON "SWG"."RESOURCE_TYPES" ("RESOURCE_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index OBJECT_TEMPLATES_NAME_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."OBJECT_TEMPLATES_NAME_IDX" ON "SWG"."OBJECT_TEMPLATES" ("NAME") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index CHUNK_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."CHUNK_IDX" ON "SWG"."OBJECTS" ("NODE_X", "NODE_Z", "SCENE_ID", "DELETED", "CONTAINED_BY", "PLAYER_CONTROLLED", "LOAD_CONTENTS") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index OWNER_ID_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."OWNER_ID_IDX" ON "SWG"."TANGIBLE_OBJECTS" ("OWNER_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_SCRUNCHER +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_SCRUNCHER" ON "SWG"."SCRUNCHER" ("OLD_OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_BATTLEFIELD_PARTICIPANTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_BATTLEFIELD_PARTICIPANTS" ON "SWG"."BATTLEFIELD_PARTICIPANTS" ("REGION_OBJECT_ID", "CHARACTER_OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_AUCTION_LOCATIONS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_AUCTION_LOCATIONS" ON "SWG"."AUCTION_LOCATIONS" ("LOCATION_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_BOUNTY_HUNTER_TARGETS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_BOUNTY_HUNTER_TARGETS" ON "SWG"."BOUNTY_HUNTER_TARGETS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_INTANGIBLE_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_INTANGIBLE_OBJECTS" ON "SWG"."INTANGIBLE_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_CLUSTER_LIST +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_CLUSTER_LIST" ON "SWG"."CLUSTER_LIST" ("ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PURGE_PHASES_PK +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PURGE_PHASES_PK" ON "SWG"."PURGE_PHASES" ("ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index REGION_NAME_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."REGION_NAME_IDX" ON "SWG"."BATTLEFIELD_MARKER_OBJECTS" ("REGION_NAME") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_EXPERIENCE_POINTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_EXPERIENCE_POINTS" ON "SWG"."EXPERIENCE_POINTS" ("OBJECT_ID", "EXPERIENCE_TYPE") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index ACCOUNT_EXTRACT_PK +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."ACCOUNT_EXTRACT_PK" ON "SWG"."ACCOUNT_EXTRACT" ("USER_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_OBJECTS" ON "SWG"."OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_MARKET_AUCTION_BIDS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_MARKET_AUCTION_BIDS" ON "SWG"."MARKET_AUCTION_BIDS" ("ITEM_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index DELETED_OBJECT_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."DELETED_OBJECT_IDX" ON "SWG"."OBJECTS" ("DELETED_DATE") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_MISSION_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_MISSION_OBJECTS" ON "SWG"."MISSION_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index TIMESTAMP_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."TIMESTAMP_IDX" ON "SWG"."ERRORLOG" ("TIMESTAMP") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_PUBLISH_PLAYER_FIXUP +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_PUBLISH_PLAYER_FIXUP" ON "SWG"."PUBLISH_PLAYER_FIXUP" ("PLAYER_OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_ARMOR +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_ARMOR" ON "SWG"."ARMOR" ("OBJECT_ID", "LAYER") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_SHIP_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_SHIP_OBJECTS" ON "SWG"."SHIP_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index WAYPOINT_LOAD_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."WAYPOINT_LOAD_IDX" ON "SWG"."WAYPOINTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index ACCOUNT_MAP_INDEX2 +-------------------------------------------------------- + + CREATE INDEX "SWG"."ACCOUNT_MAP_INDEX2" ON "SWG"."ACCOUNT_MAP" ("CHILD_ID", "PARENT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_DEFAULT_CHARACTER_SLOTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_DEFAULT_CHARACTER_SLOTS" ON "SWG"."DEFAULT_CHARACTER_SLOTS" ("CHARACTER_TYPE_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_MANF_SCHEMATIC_ATTRIBUTES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_MANF_SCHEMATIC_ATTRIBUTES" ON "SWG"."MANF_SCHEMATIC_ATTRIBUTES" ("OBJECT_ID", "ATTRIBUTE_TYPE") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_HARVESTER_INST_OBJECTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_HARVESTER_INST_OBJECTS" ON "SWG"."HARVESTER_INSTALLATION_OBJECTS" ("OBJECT_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_CHARACTER_PROFILE +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_CHARACTER_PROFILE" ON "SWG"."CHARACTER_PROFILE" ("CLUSTER_NAME", "CHARACTER_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index LOAD_WITH_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."LOAD_WITH_IDX" ON "SWG"."OBJECTS" ("LOAD_WITH") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_FEATURE_ID_TRANSACTIONS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_FEATURE_ID_TRANSACTIONS" ON "SWG"."FEATURE_ID_TRANSACTIONS" ("STATION_ID", "CLUSTER_ID", "CHARACTER_ID", "ITEM_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_CHARACTER_TYPES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_CHARACTER_TYPES" ON "SWG"."CHARACTER_TYPES" ("ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index FK_ERRORLOG_VALUES_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."FK_ERRORLOG_VALUES_IDX" ON "SWG"."ERRORLOG_VALUES" ("ERROR_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_OBJECT_VARIABLE_NAMES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_OBJECT_VARIABLE_NAMES" ON "SWG"."OBJECT_VARIABLE_NAMES" ("ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_OBJECT_TEMPLATES +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_OBJECT_TEMPLATES" ON "SWG"."OBJECT_TEMPLATES" ("ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PK_EXTRA_CHARACTER_SLOTS +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PK_EXTRA_CHARACTER_SLOTS" ON "SWG"."EXTRA_CHARACTER_SLOTS" ("STATION_ID", "CLUSTER_ID", "CHARACTER_TYPE_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index PURGE_ACCOUNTS_PK +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."PURGE_ACCOUNTS_PK" ON "SWG"."PURGE_ACCOUNTS" ("STATION_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index STATUSES_PK +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SWG"."STATUSES_PK" ON "SWG"."STATUSES" ("ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- DDL for Index MARKET_AUCTION_LOCATION_IDX +-------------------------------------------------------- + + CREATE INDEX "SWG"."MARKET_AUCTION_LOCATION_IDX" ON "SWG"."MARKET_AUCTIONS" ("LOCATION_ID") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ; +-------------------------------------------------------- +-- Constraints for Table PURGE_PHASES +-------------------------------------------------------- + + ALTER TABLE "SWG"."PURGE_PHASES" ADD CONSTRAINT "PURGE_PHASES_PK" PRIMARY KEY ("ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ERRORLOG_LEVEL +-------------------------------------------------------- + + ALTER TABLE "SWG"."ERRORLOG_LEVEL" MODIFY ("LEVELID" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table HARVESTER_INSTALLATION_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."HARVESTER_INSTALLATION_OBJECTS" ADD CONSTRAINT "PK_HARVESTER_INST_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table SCRUNCHER +-------------------------------------------------------- + + ALTER TABLE "SWG"."SCRUNCHER" ADD CONSTRAINT "PK_SCRUNCHER" PRIMARY KEY ("OLD_OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ERRORLOG_LEVEL_DESC +-------------------------------------------------------- + + ALTER TABLE "SWG"."ERRORLOG_LEVEL_DESC" MODIFY ("LEVELID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_LEVEL_DESC" MODIFY ("DESCRIP" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table VEHICLE_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."VEHICLE_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table PROPERTY_LISTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."PROPERTY_LISTS" ADD CONSTRAINT "PK_PROPERTY_LISTS" PRIMARY KEY ("OBJECT_ID", "LIST_ID", "VALUE") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table LOCATION_LISTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."LOCATION_LISTS" ADD CONSTRAINT "PK_LOCATION_LISTS" PRIMARY KEY ("OBJECT_ID", "LIST_ID", "SEQUENCE_NUMBER") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table WEAPON_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."WEAPON_OBJECTS" ADD CONSTRAINT "PK_WEAPON_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table OBJECT_VARIABLE_NAMES +-------------------------------------------------------- + + ALTER TABLE "SWG"."OBJECT_VARIABLE_NAMES" ADD CONSTRAINT "PK_OBJECT_VARIABLE_NAMES" PRIMARY KEY ("ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ERRORLOG +-------------------------------------------------------- + + ALTER TABLE "SWG"."ERRORLOG" ADD CONSTRAINT "PK_ERRORLOG" PRIMARY KEY ("ERROR_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."ERRORLOG" MODIFY ("ERROR_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG" MODIFY ("TIMESTAMP" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG" MODIFY ("ORA_ERRNO" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG" MODIFY ("ORA_ERRMSG" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG" MODIFY ("SCHEMA_NAME" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG" MODIFY ("MODULE_NAME" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table ACCOUNT_MAP +-------------------------------------------------------- + + ALTER TABLE "SWG"."ACCOUNT_MAP" ADD CONSTRAINT "ACCOUNT_MAP_UK1" UNIQUE ("CHILD_ID", "PARENT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."ACCOUNT_MAP" ADD CONSTRAINT "ACCOUNT_MAP_UK2" UNIQUE ("CHILD_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."ACCOUNT_MAP" MODIFY ("PARENT_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ACCOUNT_MAP" MODIFY ("CHILD_ID" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table WAYPOINTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."WAYPOINTS" ADD CONSTRAINT "PK_WAYPOINTS" PRIMARY KEY ("WAYPOINT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table PLAYER_QUEST_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."PLAYER_QUEST_OBJECTS" ADD CONSTRAINT "PK_PLAYER_QUEST_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table LOADBEACON_SERVER_MAP +-------------------------------------------------------- + + ALTER TABLE "SWG"."LOADBEACON_SERVER_MAP" ADD CONSTRAINT "PK_LOADBEACON_SERVER_MAP" PRIMARY KEY ("OBJECT_TEMPLATE") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MESSAGES +-------------------------------------------------------- + + ALTER TABLE "SWG"."MESSAGES" ADD PRIMARY KEY ("MESSAGE_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ACCOUNT_REWARD_EVENTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."ACCOUNT_REWARD_EVENTS" ADD CONSTRAINT "PK_ACCOUNT_REWARD_EVENTS" PRIMARY KEY ("STATION_ID", "EVENT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table GUILD_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."GUILD_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table VERSION_NUMBER +-------------------------------------------------------- + + ALTER TABLE "SWG"."VERSION_NUMBER" ADD PRIMARY KEY ("VERSION_NUMBER") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table CELL_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."CELL_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table PLANET_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."PLANET_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table INSTALLATION_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."INSTALLATION_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ACCOUNT_INFO +-------------------------------------------------------- + + ALTER TABLE "SWG"."ACCOUNT_INFO" ADD CONSTRAINT "ACCOUNT_INFO_PK" PRIMARY KEY ("STATION_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."ACCOUNT_INFO" MODIFY ("STATION_ID" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table CLOCK +-------------------------------------------------------- + + ALTER TABLE "SWG"."CLOCK" ADD CONSTRAINT "PK_CLOCK" PRIMARY KEY ("LAST_SAVE_TIME") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ACCOUNT_EXTRACT +-------------------------------------------------------- + + ALTER TABLE "SWG"."ACCOUNT_EXTRACT" ADD CONSTRAINT "ACCOUNT_EXTRACT_PK" PRIMARY KEY ("USER_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table AUCTION_LOCATIONS +-------------------------------------------------------- + + ALTER TABLE "SWG"."AUCTION_LOCATIONS" ADD CONSTRAINT "PK_AUCTION_LOCATIONS" PRIMARY KEY ("LOCATION_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."AUCTION_LOCATIONS" MODIFY ("EMPTY_DATE" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUCTION_LOCATIONS" MODIFY ("LAST_ACCESS_DATE" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUCTION_LOCATIONS" MODIFY ("INACTIVE_DATE" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUCTION_LOCATIONS" MODIFY ("STATUS" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUCTION_LOCATIONS" MODIFY ("ENTRANCE_CHARGE" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table CITY_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."CITY_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table TOKEN_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."TOKEN_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table TANGIBLE_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."TANGIBLE_OBJECTS" ADD CONSTRAINT "PK_TANGIBLE_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ERRORLOG_RERAISE_LIMITS +-------------------------------------------------------- + + ALTER TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" ADD CONSTRAINT "PK_RERAISE_LIMITS" PRIMARY KEY ("PACKAGE", "PROCEDURE") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" MODIFY ("PACKAGE" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" MODIFY ("PROCEDURE" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" MODIFY ("ERRORLIMIT" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" MODIFY ("ERRORCOUNT" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_RERAISE_LIMITS" MODIFY ("UNLIMITED_FLAG" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table INTANGIBLE_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."INTANGIBLE_OBJECTS" ADD CONSTRAINT "PK_INTANGIBLE_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table STATIC_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."STATIC_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table EXTRA_CHARACTER_SLOTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."EXTRA_CHARACTER_SLOTS" ADD CONSTRAINT "PK_EXTRA_CHARACTER_SLOTS" PRIMARY KEY ("STATION_ID", "CLUSTER_ID", "CHARACTER_TYPE_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."EXTRA_CHARACTER_SLOTS" MODIFY ("STATION_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."EXTRA_CHARACTER_SLOTS" MODIFY ("CLUSTER_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."EXTRA_CHARACTER_SLOTS" MODIFY ("CHARACTER_TYPE_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."EXTRA_CHARACTER_SLOTS" MODIFY ("NUM_EXTRA_SLOTS" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table ACCOUNT_REWARD_ITEMS +-------------------------------------------------------- + + ALTER TABLE "SWG"."ACCOUNT_REWARD_ITEMS" ADD CONSTRAINT "PK_ACCOUNT_REWARD_ITEMS" PRIMARY KEY ("STATION_ID", "ITEM_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table BATTLEFIELD_PARTICIPANTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."BATTLEFIELD_PARTICIPANTS" ADD CONSTRAINT "PK_BATTLEFIELD_PARTICIPANTS" PRIMARY KEY ("REGION_OBJECT_ID", "CHARACTER_OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table FREE_OBJECT_IDS +-------------------------------------------------------- + + ALTER TABLE "SWG"."FREE_OBJECT_IDS" ADD CONSTRAINT "PK_FREE_OBJECT_IDS" PRIMARY KEY ("START_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table EXPERIENCE_POINTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."EXPERIENCE_POINTS" ADD CONSTRAINT "PK_EXPERIENCE_POINTS" PRIMARY KEY ("OBJECT_ID", "EXPERIENCE_TYPE") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table SCRIPTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."SCRIPTS" ADD PRIMARY KEY ("OBJECT_ID", "SEQUENCE_NO") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table UNIVERSE_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."UNIVERSE_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table CHARACTER_TYPES +-------------------------------------------------------- + + ALTER TABLE "SWG"."CHARACTER_TYPES" ADD CONSTRAINT "PK_CHARACTER_TYPES" PRIMARY KEY ("ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."CHARACTER_TYPES" MODIFY ("ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."CHARACTER_TYPES" MODIFY ("DESCRIPTION" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table SHIP_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."SHIP_OBJECTS" ADD CONSTRAINT "PK_SHIP_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table BIOGRAPHIES +-------------------------------------------------------- + + ALTER TABLE "SWG"."BIOGRAPHIES" ADD CONSTRAINT "PK_BIOGRAPHIES" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table RESOURCE_CONTAINER_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."RESOURCE_CONTAINER_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MANF_SCHEMATIC_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."MANF_SCHEMATIC_OBJECTS" ADD CONSTRAINT "PK_MANF_SCHEMATIC_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."OBJECTS" ADD CONSTRAINT "PK_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table ERRORLOG_VALUES +-------------------------------------------------------- + + ALTER TABLE "SWG"."ERRORLOG_VALUES" MODIFY ("ERROR_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_VALUES" MODIFY ("ELEMENT_OWNER" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_VALUES" MODIFY ("ELEMENT_NAME" NOT NULL ENABLE); + + ALTER TABLE "SWG"."ERRORLOG_VALUES" MODIFY ("ELEMENT_TYPE" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table RESOURCE_TYPES +-------------------------------------------------------- + + ALTER TABLE "SWG"."RESOURCE_TYPES" ADD CONSTRAINT "PK_RESOURCE_TYPES" PRIMARY KEY ("RESOURCE_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table DEFAULT_CHARACTER_SLOTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."DEFAULT_CHARACTER_SLOTS" ADD CONSTRAINT "PK_DEFAULT_CHARACTER_SLOTS" PRIMARY KEY ("CHARACTER_TYPE_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."DEFAULT_CHARACTER_SLOTS" MODIFY ("CHARACTER_TYPE_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."DEFAULT_CHARACTER_SLOTS" MODIFY ("NUM_SLOTS" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table BATTLEFIELD_MARKER_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."BATTLEFIELD_MARKER_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table BUILDING_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."BUILDING_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table AUTOMATED_QUERIES +-------------------------------------------------------- + + ALTER TABLE "SWG"."AUTOMATED_QUERIES" MODIFY ("ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUTOMATED_QUERIES" MODIFY ("CREATETIME" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUTOMATED_QUERIES" MODIFY ("STATUS" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUTOMATED_QUERIES" MODIFY ("TYPE" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUTOMATED_QUERIES" MODIFY ("RUN_SERIAL" NOT NULL ENABLE); + + ALTER TABLE "SWG"."AUTOMATED_QUERIES" MODIFY ("QUERY_TEXT" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table FEATURE_ID_TRANSACTIONS +-------------------------------------------------------- + + ALTER TABLE "SWG"."FEATURE_ID_TRANSACTIONS" ADD CONSTRAINT "PK_FEATURE_ID_TRANSACTIONS" PRIMARY KEY ("STATION_ID", "CLUSTER_ID", "CHARACTER_ID", "ITEM_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table PLAYER_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."PLAYER_OBJECTS" ADD CONSTRAINT "PK_PLAYER_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table DEFAULT_CHAR_LIMITS +-------------------------------------------------------- + + ALTER TABLE "SWG"."DEFAULT_CHAR_LIMITS" MODIFY ("ACCOUNT_LIMIT" NOT NULL ENABLE); + + ALTER TABLE "SWG"."DEFAULT_CHAR_LIMITS" MODIFY ("CLUSTER_LIMIT" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table BOUNTY_HUNTER_TARGETS +-------------------------------------------------------- + + ALTER TABLE "SWG"."BOUNTY_HUNTER_TARGETS" ADD CONSTRAINT "PK_BOUNTY_HUNTER_TARGETS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."BOUNTY_HUNTER_TARGETS" MODIFY ("OBJECT_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."BOUNTY_HUNTER_TARGETS" MODIFY ("TARGET_ID" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table SWG_CHARACTERS +-------------------------------------------------------- + + ALTER TABLE "SWG"."SWG_CHARACTERS" ADD CONSTRAINT "PK_SWG_CHARACTER" PRIMARY KEY ("STATION_ID", "CLUSTER_ID", "CHARACTER_NAME") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."SWG_CHARACTERS" MODIFY ("STATION_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."SWG_CHARACTERS" MODIFY ("CLUSTER_ID" NOT NULL ENABLE); + + ALTER TABLE "SWG"."SWG_CHARACTERS" MODIFY ("CHARACTER_NAME" NOT NULL ENABLE); + + ALTER TABLE "SWG"."SWG_CHARACTERS" MODIFY ("ENABLED" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table OBJECT_VARIABLES +-------------------------------------------------------- + + ALTER TABLE "SWG"."OBJECT_VARIABLES" ADD CONSTRAINT "PK_OBJECT_VARIABLES" PRIMARY KEY ("OBJECT_ID", "NAME_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table PLAYERS +-------------------------------------------------------- + + ALTER TABLE "SWG"."PLAYERS" ADD CONSTRAINT "PK_PLAYERS" PRIMARY KEY ("CHARACTER_OBJECT") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table OBJECT_TEMPLATES +-------------------------------------------------------- + + ALTER TABLE "SWG"."OBJECT_TEMPLATES" ADD CONSTRAINT "PK_OBJECT_TEMPLATES" PRIMARY KEY ("ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MARKET_AUCTION_BIDS +-------------------------------------------------------- + + ALTER TABLE "SWG"."MARKET_AUCTION_BIDS" ADD CONSTRAINT "PK_MARKET_AUCTION_BIDS" PRIMARY KEY ("ITEM_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MISSION_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."MISSION_OBJECTS" ADD CONSTRAINT "PK_MISSION_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table CLUSTER_LIST +-------------------------------------------------------- + + ALTER TABLE "SWG"."CLUSTER_LIST" ADD CONSTRAINT "PK_CLUSTER_LIST" PRIMARY KEY ("ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."CLUSTER_LIST" MODIFY ("GROUP_ID" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table PUBLISH_PLAYER_FIXUP +-------------------------------------------------------- + + ALTER TABLE "SWG"."PUBLISH_PLAYER_FIXUP" ADD CONSTRAINT "PK_PUBLISH_PLAYER_FIXUP" PRIMARY KEY ("PLAYER_OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MARKET_AUCTIONS +-------------------------------------------------------- + + ALTER TABLE "SWG"."MARKET_AUCTIONS" ADD CONSTRAINT "PK_MARKET_AUCTIONS" PRIMARY KEY ("ITEM_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."MARKET_AUCTIONS" MODIFY ("ITEM_SIZE" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table ACCOUNTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."ACCOUNTS" ADD CONSTRAINT "PK_ACCOUNTS" PRIMARY KEY ("STATION_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table CHARACTER_PROFILE +-------------------------------------------------------- + + ALTER TABLE "SWG"."CHARACTER_PROFILE" ADD CONSTRAINT "PK_CHARACTER_PROFILE" PRIMARY KEY ("CLUSTER_NAME", "CHARACTER_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; + + ALTER TABLE "SWG"."CHARACTER_PROFILE" MODIFY ("CLUSTER_NAME" NOT NULL ENABLE); + + ALTER TABLE "SWG"."CHARACTER_PROFILE" MODIFY ("CHARACTER_ID" NOT NULL ENABLE); +-------------------------------------------------------- +-- Constraints for Table ARMOR +-------------------------------------------------------- + + ALTER TABLE "SWG"."ARMOR" ADD CONSTRAINT "PK_ARMOR" PRIMARY KEY ("OBJECT_ID", "LAYER") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MANUFACTURE_INST_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."MANUFACTURE_INST_OBJECTS" ADD CONSTRAINT "PK_MANUFACTURE_INST_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table PURGE_ACCOUNTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."PURGE_ACCOUNTS" ADD CONSTRAINT "PURGE_ACCOUNTS_PK" PRIMARY KEY ("STATION_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table STATUSES +-------------------------------------------------------- + + ALTER TABLE "SWG"."STATUSES" ADD CONSTRAINT "STATUSES_PK" PRIMARY KEY ("ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table FACTORY_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."FACTORY_OBJECTS" ADD CONSTRAINT "PK_FACTORY_OBJECTS" PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table CREATURE_OBJECTS +-------------------------------------------------------- + + ALTER TABLE "SWG"."CREATURE_OBJECTS" ADD PRIMARY KEY ("OBJECT_ID") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table DELETE_REASONS +-------------------------------------------------------- + + ALTER TABLE "SWG"."DELETE_REASONS" ADD CONSTRAINT "PK_DELETE_REASONS" PRIMARY KEY ("REASON_CODE") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MARKET_AUCTION_ATTRIBUTES +-------------------------------------------------------- + + ALTER TABLE "SWG"."MARKET_AUCTION_ATTRIBUTES" ADD CONSTRAINT "PK_MARKET_AUCTION_ATTRIBUTES" PRIMARY KEY ("ITEM_ID", "ATTRIBUTE_NAME") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Constraints for Table MANF_SCHEMATIC_ATTRIBUTES +-------------------------------------------------------- + + ALTER TABLE "SWG"."MANF_SCHEMATIC_ATTRIBUTES" ADD CONSTRAINT "PK_MANF_SCHEMATIC_ATTRIBUTES" PRIMARY KEY ("OBJECT_ID", "ATTRIBUTE_TYPE") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING + TABLESPACE "SWG" ENABLE; +-------------------------------------------------------- +-- Ref Constraints for Table ERRORLOG_VALUES +-------------------------------------------------------- + + ALTER TABLE "SWG"."ERRORLOG_VALUES" ADD CONSTRAINT "FK_ERRORLOG" FOREIGN KEY ("ERROR_ID") + REFERENCES "SWG"."ERRORLOG" ("ERROR_ID") ENABLE; +-------------------------------------------------------- +-- Ref Constraints for Table MARKET_AUCTIONS +-------------------------------------------------------- + + ALTER TABLE "SWG"."MARKET_AUCTIONS" ADD CONSTRAINT "MARKET_AUCTIONS_LOCATION_ID_FK" FOREIGN KEY ("LOCATION_ID") + REFERENCES "SWG"."AUCTION_LOCATIONS" ("LOCATION_ID") ON DELETE CASCADE ENABLE; +-------------------------------------------------------- +-- Ref Constraints for Table MARKET_AUCTION_ATTRIBUTES +-------------------------------------------------------- + + ALTER TABLE "SWG"."MARKET_AUCTION_ATTRIBUTES" ADD CONSTRAINT "MARKET_ATTRIBUTES_ITEM_ID_FK" FOREIGN KEY ("ITEM_ID") + REFERENCES "SWG"."MARKET_AUCTIONS" ("ITEM_ID") ON DELETE CASCADE ENABLE; +-------------------------------------------------------- +-- Ref Constraints for Table MARKET_AUCTION_BIDS +-------------------------------------------------------- + + ALTER TABLE "SWG"."MARKET_AUCTION_BIDS" ADD CONSTRAINT "MARKET_AUCTION_BIDS_ITEM_ID_FK" FOREIGN KEY ("ITEM_ID") + REFERENCES "SWG"."MARKET_AUCTIONS" ("ITEM_ID") ON DELETE CASCADE ENABLE; +-------------------------------------------------------- +-- DDL for Package ADMIN +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."ADMIN" +as + type refcursor is ref cursor; + subtype objectid is number; + + procedure move_to_player (p_object_id objectid, p_target_player objectid); + procedure move_to_player_bank (p_object_id objectid, p_target_player objectid); + procedure move_to_player_datapad (p_object_id objectid, p_target_player objectid, p_max_depth number); + procedure move_to_container (p_object_id objectid, p_target_container objectid, p_target_load_with objectid); + procedure move_to_container_depth (p_object_id objectid, p_target_container objectid, p_target_load_with objectid, p_max_depth number); + function get_inventory_for_player (p_player_id objectid) return objectid; + function get_bank_for_player (p_player_id objectid) return objectid; + function get_datapad_for_player (p_player_id objectid) return objectid; + function get_player_for_player (p_player_id objectid) return objectid; + function get_container_for_object(p_object_id objectid) return objectid; + function get_object_template_id (p_object_id objectid) return number; + function restore_house (p_house_id objectid) return number; + + function restore_character (p_player_id objectid, p_name out varchar2, p_account out number, p_template_id out number) return number; + function undelete_item (p_item_id objectid) return number; + function move_item_to_player (p_object_id objectid, p_target_player objectid) return number; + + procedure fix_load_with (p_topmost_object objectid, p_starting_loadwith objectid); + procedure fix_load_with_depth (p_topmost_object objectid, p_starting_loadwith objectid, p_max_depth number); +end; + +/ + + GRANT EXECUTE ON "SWG"."ADMIN" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package BIOGRAPHY +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."BIOGRAPHY" +as + type refcursor is ref cursor; + subtype objectid is number; + + procedure set_biography (p_owner objectid, p_biography varchar2); + function get_biography (p_owner objectid) return refcursor; +end; + +/ + + GRANT EXECUTE ON "SWG"."BIOGRAPHY" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package BLOB_DATA_CONVERSION +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."BLOB_DATA_CONVERSION" as + function blob_encodeoob (v_blob blob) return varchar2; + function blob_hexdump (v_blob blob) return varchar2; + function blob_encodeoob_old (v_blob blob) return varchar2; + function blob_to_string (v_blob blob) return varchar2; + function string_hexdump (v_string varchar2) return varchar2; + procedure convert_blob_data(v_item_id number); +end; + +/ + + GRANT EXECUTE ON "SWG"."BLOB_DATA_CONVERSION" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package CM_LOADER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."CM_LOADER" is + + TYPE swg_cur IS REF CURSOR; + + FUNCTION get_location_list return swg_cur; + -- + -- + -- + FUNCTION get_bid_list return swg_cur; + -- + -- + -- + FUNCTION get_auction_list return swg_cur; + -- + -- + -- + FUNCTION get_auction_attributes RETURN swg_cur; + +end cm_loader; + +/ + + GRANT EXECUTE ON "SWG"."CM_LOADER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package CM_PERSISTER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."CM_PERSISTER" +as + type refcursor is ref cursor; + subtype objectid is number; + + procedure update_auction_locations (p_location_id VAOFSTRING, + p_location_name VAOFSTRING, + p_owner_id VAOFSTRING, + p_sales_tax VAOFNUMBER, + p_sales_tax_bank_id VAOFSTRING, + p_empty_date VAOFNUMBER, + p_last_access_date VAOFNUMBER, + p_inactive_date VAOFNUMBER, + p_status VAOFNUMBER, + p_search_enabled VAOFSTRING, + p_entrance_charge VAOFNUMBER, + p_chunk_size number); + procedure insert_auction_locations (p_location_id VAOFSTRING, + p_location_name VAOFSTRING, + p_owner_id VAOFSTRING, + p_sales_tax VAOFNUMBER, + p_sales_tax_bank_id VAOFSTRING, + p_empty_date VAOFNUMBER, + p_last_access_date VAOFNUMBER, + p_inactive_date VAOFNUMBER, + p_status VAOFNUMBER, + p_search_enabled VAOFSTRING, + p_entrance_charge VAOFNUMBER, + p_chunk_size number); + procedure delete_auction_locations (p_location_id VAOFSTRING, p_chunk_size number); + + procedure insert_market_auction_bids (p_item_id VAOFSTRING, + p_bidder_id VAOFSTRING, + p_bid VAOFNUMBER, + p_max_proxy_bid VAOFNUMBER, + p_chunk_size number); + + procedure update_market_auctions (p_item_id VAOFSTRING, + p_owner_id VAOFSTRING, + p_active VAOFNUMBER, + p_chunk_size number); + procedure insert_market_auctions (p_item_id VAOFSTRING, + p_owner_id VAOFSTRING, + p_creator_id VAOFSTRING, + p_location_id VAOFSTRING, + p_min_bid VAOFNUMBER, + p_buy_now_price VAOFNUMBER, + p_auction_timer VAOFNUMBER, + p_oob VAOFLONGSTRING, + p_user_description VAOFLONGSTRING, + p_category VAOFNUMBER, + p_item_name VAOFLONGSTRING, + p_item_timer VAOFNUMBER, + p_active VAOFNUMBER, + p_item_size VAOFNUMBER, + p_object_template_id VAOFNUMBER, + p_chunk_size number); + procedure delete_market_auctions (p_item_id VAOFSTRING, p_chunk_size number); + + procedure insert_auction_attributes (p_item_id VAOFSTRING, p_attribute_name VAOFSTRING, p_attribute_value VAOFSTRING, p_chunk_size number); + +end; + +/ + + GRANT EXECUTE ON "SWG"."CM_PERSISTER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package CUSTSERV_PROCS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."CUSTSERV_PROCS" +as + type cursortype is ref cursor; + function get_characters_for_account +( + station_id_in IN players.station_id%TYPE +) + return cursortype; + + function get_deleted_items + ( + character_id_in IN objects.load_with%TYPE, + start_page_in IN number + ) + return cursortype; + + function get_structures + ( + character_id_in IN objects.object_id%TYPE + ) + return cursortype; + + function get_player_id + ( + character_name_in IN players.uc_character_name%TYPE + ) + return cursortype; + + procedure move_player + ( + character_id_in IN objects.object_id%TYPE, + x_in IN objects.x%TYPE, + y_in IN objects.y%TYPE, + z_in IN objects.z%TYPE, + scene_in IN objects.scene_id%TYPE + ); + + procedure undelete_item + ( + character_id_in IN objects.object_id%TYPE, + object_in IN objects.object_id%TYPE, + move_in IN number + ); + +end custserv_procs; + +/ + + GRANT EXECUTE ON "SWG"."CUSTSERV_PROCS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package DATALOOKUP +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."DATALOOKUP" +as + type refcursor is ref cursor; + + function check_character_name(p_name varchar2) return number; + function get_structures_for_purge(p_station_id number) return refcursor; + function get_vendors_for_purge(p_station_id number) return refcursor; + +end; + +/ + + GRANT EXECUTE ON "SWG"."DATALOOKUP" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package DATA_CLEANUP +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."DATA_CLEANUP" +as + type cursortype is ref cursor; + subtype objectid is number; + + procedure run_fix_bad_cells; + procedure run_fix_houses_w_bad_cells; + function getObjectsWithExpMessages return cursortype; + function getExperienceGrants(p_object_id objectid) return cursortype; + procedure delete_experience(p_object_id objectid); + procedure grant_experience(p_object_id objectid, p_experience_data varchar2); + function object_variable_name_cleanup return number; + function orphaned_object_cleanup return number; + function market_attributes_cleanup return number; + function messages_cleanup return number; + function vendor_object_cleanup return number; + function broken_object_cleanup return number; +end; + +/ + + GRANT EXECUTE ON "SWG"."DATA_CLEANUP" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package DB_ERROR_LOGGER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."DB_ERROR_LOGGER" +as + + procedure dblogerror( p_ora_errno number, p_notes varchar2 default NULL); + procedure dblogerror_values( p_owner varchar2, p_name varchar2, p_type varchar2, p_value varchar2); + procedure stack_search ( i_search in integer, o_schema out varchar2, o_module out varchar2 ); + function getloglevel RETURN INTEGER; + function reraisecheck ( p_package varchar2 default NULL, p_procedure varchar2 default NULL) return INTEGER; + +end; + +/ + + GRANT EXECUTE ON "SWG"."DB_ERROR_LOGGER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package GOLD_OVERRIDE +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."GOLD_OVERRIDE" +as + type cursortype is ref cursor; + + function load_objvar_overrides(p_schema varchar2) return cursortype; +end; + +/ + + GRANT EXECUTE ON "SWG"."GOLD_OVERRIDE" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package LAZY_DELETER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."LAZY_DELETER" as + procedure purge_one_object(object_in in number); + procedure purge_objects_bulk(p_object_id VAOFSTRING, p_chunk_size number, p_enable_db_logging number); +end lazy_deleter; + +/ + + GRANT EXECUTE ON "SWG"."LAZY_DELETER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package LOADER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."LOADER" +as + type cursortype is ref cursor; + + function get_character_name_list return cursortype; + + procedure get_version_number(current_version in out number, min_version in out number); + function get_characters (p_station_id number) return cursortype; + function verify_containment_chain(p_start_with_object_id in number) return number; + function fix_player_containment_chain(p_start_with_object_id in number) return number; + procedure verify_character (p_station_id in number, p_character_id in number, p_gold_schema in varchar2, p_approved out varchar2, p_character_name out varchar2, p_scene_id out varchar2, p_container_id out number, p_x out number, p_y out number, p_z out number, p_containment_check out number); + function locate_player (p_object_id number) return number; + procedure locate_universe; + procedure locate_contained_object (p_container_id number, p_object_id number); + function locate_by_loadwith_batch (p_loadwiths vaofstring, p_chunk_size number) return number; + procedure locate_contents (p_container_id number); + function load_chunk_object_list (p_scene_id varchar, p_node_x float, p_node_z float) return number; + procedure locate_structure (p_object_id number, p_x out number, p_z out number, p_scene_id out varchar2, p_found out number); + + function load_armor return cursortype; + function load_battlefield_participants return cursortype; + function load_property_lists return cursortype; + function load_experience return cursortype; + function load_location return cursortype; + function load_manf_schematic_attributes return cursortype; + function load_messages return cursortype; + function load_object_variables return cursortype; + function load_scripts return cursortype; + function load_object return cursortype; + function load_waypoint return cursortype; + function load_player_object return cursortype; + function load_resource_types return cursortype; + function load_bounty_hunter_targets return cursortype; + +-- GENERATED PLSQL FOLLOWS +-- generated by makeloader.pl + + + function load_battlefield_marker_object return cursortype; + function load_building_object return cursortype; + function load_cell_object return cursortype; + function load_city_object return cursortype; + function load_creature_object return cursortype; + function load_factory_object return cursortype; + function load_guild_object return cursortype; + function load_harvester_inst_object return cursortype; + function load_installation_object return cursortype; + function load_intangible_object return cursortype; + function load_manf_schematic_object return cursortype; + function load_manufacture_inst_object return cursortype; + function load_mission_object return cursortype; + function load_planet_object return cursortype; + function load_resource_container_object return cursortype; + function load_ship_object return cursortype; + function load_static_object return cursortype; + function load_tangible_object return cursortype; + function load_token_object return cursortype; + function load_universe_object return cursortype; + function load_vehicle_object return cursortype; + function load_weapon_object return cursortype; + function load_player_quest_object return cursortype; +end; + +/ + + GRANT EXECUTE ON "SWG"."LOADER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package LOGIN +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."LOGIN" +as + type refcursor is ref cursor; + subtype objectid is number; + + procedure register_new_cluster(p_cluster_name in varchar2, p_address in varchar2, p_cluster_id out number); + function get_cluster_list(p_group in number) return refcursor; + function get_avatar_list (p_station_id number, p_cluster_group number) return refcursor; + function get_open_character_slots(p_station_id number, p_cluster_id number) return refcursor; + function get_only_open_character_slots(p_station_id number, p_cluster_id number) return refcursor; + function is_cluster_at_limit(p_cluster_id number) return number; + function is_account_at_limit(p_station_id number) return number; + procedure delete_character(p_cluster_id number, p_character_id number, p_station_id number); + procedure rename_character(p_cluster_id number, p_character_id number, p_new_name varchar2); + procedure create_character(p_cluster_id number, p_station_id number, p_character_name varchar2, p_character_id number, p_template_id number, p_character_type number); + function restore_character(p_cluster_id number, p_station_id number, p_character_name varchar2, p_character_id number, p_template_id number, p_character_type number) return number; + procedure set_character_slots(p_cluster_id number, p_station_id number, p_slot_type number, p_num_slots number); + procedure set_character_type(p_cluster_id number, p_station_id number, p_character_id number, p_slot_type number); + function has_extra_character_slot(p_station_id number, p_character_type number) return number; + procedure toggle_disable_character(p_cluster_id number, p_character_id number, p_station_id number, p_enabled varchar2); + function enable_disable_character(p_station_id number, p_character_id number, p_enabled varchar2) return number; + function get_completed_tutorial(p_station_id number) return refcursor; + procedure toggle_completed_tutorial(p_station_id number, p_completed varchar2); + function get_consumed_reward_events(p_station_id number) return refcursor; + function get_claimed_reward_items(p_station_id number) return refcursor; + function consume_reward_event(p_station_id number, p_character_id number, p_cluster_id number, p_event_id varchar2) return number; + function claim_reward_item(p_station_id number, p_character_id number, p_cluster_id number, p_item_id varchar2) return number; + function get_feature_id_transactions(p_station_id in number, p_cluster_id in number, p_character_id in number) return refcursor; + function update_feature_id_transaction(p_station_id in number, p_cluster_id in number, p_character_id in number, p_item_id in varchar2, p_count_adjustment in number) return number; +end; + +/ + + GRANT EXECUTE ON "SWG"."LOGIN" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package OBJECTIDMANAGER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."OBJECTIDMANAGER" +as + type cursortype is ref cursor; + + procedure get_ids(how_many in out number, block_start_id out number, block_end_id out number); + function get_contiguous_ids(min_count number) return number; + function get_single_id return number; + + procedure rebuild_freelist; +end; + +/ + + GRANT EXECUTE ON "SWG"."OBJECTIDMANAGER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package OBJVAR_NAMES +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."OBJVAR_NAMES" +as + type cursortype is ref cursor; + + procedure add_name (p_id number, p_name varchar2); + function get_name_list return cursortype; +end; + +/ + + GRANT EXECUTE ON "SWG"."OBJVAR_NAMES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package PERSISTER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."PERSISTER" +as + type refcursor is ref cursor; + subtype objectid is number; + + procedure set_clock (p_time number); + procedure add_player (p_station_id number, p_character_object objectid, p_character_name varchar2, p_normalized_name varchar2); + function delete_character (p_station_id number, p_character_id number, p_delete_minutes number) return number; + procedure update_object_variable_batch (p_object_id vaofstring, p_name_id vaofnumber, p_type vaofnumber, p_value vaofstring, p_chunk_size number); + procedure add_object_variable_batch (p_object_id vaofstring, p_name_id vaofnumber, p_type vaofnumber, p_value vaofstring, p_chunk_size number); + procedure remove_object_variable_batch (p_object_id vaofstring, p_name_id vaofnumber, p_chunk_size number); + procedure clear_scripts (p_object_id objectid); + procedure save_message (p_message_id number, p_object_id objectid, p_method varchar, p_data varchar, p_call_time number, p_guaranteed varchar, p_delivery_type int); + procedure save_message_batch (p_message_id VAOFSTRING, p_object_id VAOFSTRING, p_method VAOFSTRING, p_data VAOFLONGSTRING, p_call_time VAOFNUMBER, p_guaranteed VAOFSTRING, p_delivery_type VAOFNUMBER, p_chunk_size number, p_enable_db_logging number ); + procedure acknowledge_message (p_message_id number); + procedure acknowledge_message_batch (p_message_id VAOFSTRING, p_chunk_size number, p_enable_db_logging number ); + procedure save_object ( p_x VAOFNUMBER, p_y VAOFNUMBER, p_z VAOFNUMBER, p_quaternion_w VAOFNUMBER, p_quaternion_x VAOFNUMBER, p_quaternion_y VAOFNUMBER, p_quaternion_z VAOFNUMBER, p_node_x VAOFNUMBER, p_node_y VAOFNUMBER, p_node_z VAOFNUMBER, p_object_template_id VAOFNUMBER, p_type_id VAOFNUMBER, p_scene_id VAOFSTRING, p_controller_type VAOFNUMBER, p_deleted VAOFNUMBER, p_object_name VAOFSTRING, p_volume VAOFNUMBER, p_contained_by VAOFSTRING, p_slot_arrangement VAOFNUMBER, p_player_controlled VAOFSTRING, p_cache_version VAOFNUMBER, p_load_contents VAOFSTRING, p_cash_balance VAOFNUMBER, p_bank_balance VAOFNUMBER, p_complexity VAOFNUMBER, p_name_string_table VAOFSTRING, p_name_string_text VAOFSTRING, p_static_item_name VAOFSTRING, p_static_item_version VAOFNUMBER, p_conversion_id VAOFNUMBER, p_load_with VAOFSTRING, + p_objvar_0_name VAOFSTRING,p_objvar_0_type VAOFNUMBER,p_objvar_0_value VAOFSTRING,p_objvar_1_name VAOFSTRING,p_objvar_1_type VAOFNUMBER,p_objvar_1_value VAOFSTRING,p_objvar_2_name VAOFSTRING,p_objvar_2_type VAOFNUMBER,p_objvar_2_value VAOFSTRING,p_objvar_3_name VAOFSTRING,p_objvar_3_type VAOFNUMBER,p_objvar_3_value VAOFSTRING,p_objvar_4_name VAOFSTRING,p_objvar_4_type VAOFNUMBER,p_objvar_4_value VAOFSTRING,p_objvar_5_name VAOFSTRING,p_objvar_5_type VAOFNUMBER,p_objvar_5_value VAOFSTRING,p_objvar_6_name VAOFSTRING,p_objvar_6_type VAOFNUMBER,p_objvar_6_value VAOFSTRING,p_objvar_7_name VAOFSTRING,p_objvar_7_type VAOFNUMBER,p_objvar_7_value VAOFSTRING,p_objvar_8_name VAOFSTRING,p_objvar_8_type VAOFNUMBER,p_objvar_8_value VAOFSTRING,p_objvar_9_name VAOFSTRING,p_objvar_9_type VAOFNUMBER,p_objvar_9_value VAOFSTRING, p_objvar_10_name VAOFSTRING,p_objvar_10_type VAOFNUMBER,p_objvar_10_value VAOFSTRING,p_objvar_11_name VAOFSTRING,p_objvar_11_type VAOFNUMBER,p_objvar_11_value VAOFSTRING,p_objvar_12_name VAOFSTRING,p_objvar_12_type VAOFNUMBER,p_objvar_12_value VAOFSTRING,p_objvar_13_name VAOFSTRING,p_objvar_13_type VAOFNUMBER,p_objvar_13_value VAOFSTRING,p_objvar_14_name VAOFSTRING,p_objvar_14_type VAOFNUMBER,p_objvar_14_value VAOFSTRING,p_objvar_15_name VAOFSTRING,p_objvar_15_type VAOFNUMBER,p_objvar_15_value VAOFSTRING,p_objvar_16_name VAOFSTRING,p_objvar_16_type VAOFNUMBER,p_objvar_16_value VAOFSTRING,p_objvar_17_name VAOFSTRING,p_objvar_17_type VAOFNUMBER,p_objvar_17_value VAOFSTRING,p_objvar_18_name VAOFSTRING,p_objvar_18_type VAOFNUMBER,p_objvar_18_value VAOFSTRING,p_objvar_19_name VAOFSTRING,p_objvar_19_type VAOFNUMBER,p_objvar_19_value VAOFSTRING, p_script_list VAOFLONGSTRING, p_object_id VAOFSTRING, p_chunk_size number); + procedure add_object ( p_x VAOFNUMBER, p_y VAOFNUMBER, p_z VAOFNUMBER, p_quaternion_w VAOFNUMBER, p_quaternion_x VAOFNUMBER, p_quaternion_y VAOFNUMBER, p_quaternion_z VAOFNUMBER, p_node_x VAOFNUMBER, p_node_y VAOFNUMBER, p_node_z VAOFNUMBER, p_object_template_id VAOFNUMBER, p_type_id VAOFNUMBER, p_scene_id VAOFSTRING, p_controller_type VAOFNUMBER, p_deleted VAOFNUMBER, p_object_name VAOFSTRING, p_volume VAOFNUMBER, p_contained_by VAOFSTRING, p_slot_arrangement VAOFNUMBER, p_player_controlled VAOFSTRING, p_cache_version VAOFNUMBER, p_load_contents VAOFSTRING, p_cash_balance VAOFNUMBER, p_bank_balance VAOFNUMBER, p_complexity VAOFNUMBER, p_name_string_table VAOFSTRING, p_name_string_text VAOFSTRING, p_static_item_name VAOFSTRING, p_static_item_version VAOFNUMBER, p_conversion_id VAOFNUMBER, p_load_with VAOFSTRING, + p_objvar_0_name VAOFSTRING,p_objvar_0_type VAOFNUMBER,p_objvar_0_value VAOFSTRING,p_objvar_1_name VAOFSTRING,p_objvar_1_type VAOFNUMBER,p_objvar_1_value VAOFSTRING,p_objvar_2_name VAOFSTRING,p_objvar_2_type VAOFNUMBER,p_objvar_2_value VAOFSTRING,p_objvar_3_name VAOFSTRING,p_objvar_3_type VAOFNUMBER,p_objvar_3_value VAOFSTRING,p_objvar_4_name VAOFSTRING,p_objvar_4_type VAOFNUMBER,p_objvar_4_value VAOFSTRING,p_objvar_5_name VAOFSTRING,p_objvar_5_type VAOFNUMBER,p_objvar_5_value VAOFSTRING,p_objvar_6_name VAOFSTRING,p_objvar_6_type VAOFNUMBER,p_objvar_6_value VAOFSTRING,p_objvar_7_name VAOFSTRING,p_objvar_7_type VAOFNUMBER,p_objvar_7_value VAOFSTRING,p_objvar_8_name VAOFSTRING,p_objvar_8_type VAOFNUMBER,p_objvar_8_value VAOFSTRING,p_objvar_9_name VAOFSTRING,p_objvar_9_type VAOFNUMBER,p_objvar_9_value VAOFSTRING, p_objvar_10_name VAOFSTRING,p_objvar_10_type VAOFNUMBER,p_objvar_10_value VAOFSTRING,p_objvar_11_name VAOFSTRING,p_objvar_11_type VAOFNUMBER,p_objvar_11_value VAOFSTRING,p_objvar_12_name VAOFSTRING,p_objvar_12_type VAOFNUMBER,p_objvar_12_value VAOFSTRING,p_objvar_13_name VAOFSTRING,p_objvar_13_type VAOFNUMBER,p_objvar_13_value VAOFSTRING,p_objvar_14_name VAOFSTRING,p_objvar_14_type VAOFNUMBER,p_objvar_14_value VAOFSTRING,p_objvar_15_name VAOFSTRING,p_objvar_15_type VAOFNUMBER,p_objvar_15_value VAOFSTRING,p_objvar_16_name VAOFSTRING,p_objvar_16_type VAOFNUMBER,p_objvar_16_value VAOFSTRING,p_objvar_17_name VAOFSTRING,p_objvar_17_type VAOFNUMBER,p_objvar_17_value VAOFSTRING,p_objvar_18_name VAOFSTRING,p_objvar_18_type VAOFNUMBER,p_objvar_18_value VAOFSTRING,p_objvar_19_name VAOFSTRING,p_objvar_19_type VAOFNUMBER,p_objvar_19_value VAOFSTRING, p_script_list VAOFLONGSTRING, p_object_id VAOFSTRING, p_chunk_size number); + procedure remove_object ( p_object_id VAOFSTRING, p_chunk_size number); + procedure save_manf_schem_attribute (p_action number, p_object_id objectid, p_attribute_type varchar2, p_value number); + procedure update_property_list (p_object_id objectid, p_list_id number, p_operation number, p_value varchar2); + procedure update_property_list_batch (p_object_id VAOFSTRING, p_list_id VAOFNUMBER, p_operation number, p_value VAOFSTRING, p_chunk_size number, p_enable_db_logging number ); + procedure save_armor (p_object_template varchar2, p_effectiveness number, p_integrity number, p_special_protections varchar2, p_encumberance_0 number, p_encumberance_1 number, p_encumberance_2 number, p_encumberance_3 number, p_encumberance_4 number, p_encumberance_5 number, p_encumberance_6 number, p_encumberance_7 number, p_encumberance_8 number, p_layer number, p_object_id objectid); + procedure add_armor (p_object_template varchar2, p_effectiveness number, p_integrity number, p_special_protections varchar2, p_encumberance_0 number, p_encumberance_1 number, p_encumberance_2 number, p_encumberance_3 number, p_encumberance_4 number, p_encumberance_5 number, p_encumberance_6 number, p_encumberance_7 number, p_encumberance_8 number, p_layer number, p_object_id objectid); + procedure save_location ( p_object_id number, p_list_id number, p_sequence_number number, p_operation number, p_name varchar2, p_scene varchar2, p_x number, p_y number, p_z number, p_radius number); + procedure save_experience ( p_points number, p_experience_type varchar2, p_object_id number ); + procedure save_battlefield_participants ( p_faction_id number, p_character_object_id number, p_region_object_id number ); + function rename_character( p_character_id objectid, p_new_name varchar2, p_normalized_name varchar2) return number; + procedure save_waypoint(p_object_id objectid, p_waypoint_id objectid, p_appearance_name_crc number, p_location_x number, p_location_y number, p_location_z number, p_location_cell number, p_location_scene number, p_name varchar2, p_color number, p_active char, p_detached char); + procedure save_player_obj( p_object_id VAOFSTRING, p_station_id VAOFNUMBER, p_house_id VAOFSTRING, p_account_num_lots VAOFNUMBER, p_account_is_outcast VAOFSTRING, p_account_cheater_level VAOFNUMBER, p_account_max_lots_adjustment VAOFNUMBER, p_personal_profile_id VAOFSTRING, p_character_profile_id VAOFSTRING, p_skill_title VAOFSTRING, p_born_date VAOFNUMBER, p_played_time VAOFNUMBER, p_force_regen_rate VAOFNUMBER, p_force_power VAOFNUMBER, p_max_force_power VAOFNUMBER, p_active_quests VAOFSTRING, p_completed_quests VAOFSTRING, p_current_quest VAOFNUMBER, p_quests VAOFLONGSTRING, p_role_icon_choice VAOFNUMBER, p_quests2 VAOFLONGSTRING, p_quests3 VAOFLONGSTRING, p_quests4 VAOFLONGSTRING, p_skill_template VAOFSTRING, p_working_skill VAOFSTRING, p_current_gcw_points VAOFNUMBER, p_current_gcw_rating VAOFNUMBER, p_current_pvp_kills VAOFNUMBER, p_lifetime_gcw_points VAOFNUMBER, p_max_gcw_imperial_rating VAOFNUMBER, p_max_gcw_rebel_rating VAOFNUMBER, p_lifetime_pvp_kills VAOFNUMBER, p_next_gcw_rating_calc_time VAOFNUMBER, p_collections VAOFLONGSTRING, p_show_backpack VAOFSTRING, p_show_helmet VAOFSTRING, p_collections2 VAOFLONGSTRING, p_chunk_size number ); + procedure add_player_obj( p_object_id VAOFSTRING, p_station_id VAOFNUMBER, p_house_id VAOFSTRING, p_account_num_lots VAOFNUMBER, p_account_is_outcast VAOFSTRING, p_account_cheater_level VAOFNUMBER, p_account_max_lots_adjustment VAOFNUMBER, p_personal_profile_id VAOFSTRING, p_character_profile_id VAOFSTRING, p_skill_title VAOFSTRING, p_born_date VAOFNUMBER, p_played_time VAOFNUMBER, p_force_regen_rate VAOFNUMBER, p_force_power VAOFNUMBER, p_max_force_power VAOFNUMBER, p_active_quests VAOFSTRING, p_completed_quests VAOFSTRING, p_current_quest VAOFNUMBER, p_quests VAOFLONGSTRING, p_role_icon_choice VAOFNUMBER, p_quests2 VAOFLONGSTRING, p_quests3 VAOFLONGSTRING, p_quests4 VAOFLONGSTRING, p_skill_template VAOFSTRING, p_working_skill VAOFSTRING, p_current_gcw_points VAOFNUMBER, p_current_gcw_rating VAOFNUMBER, p_current_pvp_kills VAOFNUMBER, p_lifetime_gcw_points VAOFNUMBER, p_max_gcw_imperial_rating VAOFNUMBER, p_max_gcw_rebel_rating VAOFNUMBER, p_lifetime_pvp_kills VAOFNUMBER, p_next_gcw_rating_calc_time VAOFNUMBER, p_collections VAOFLONGSTRING, p_show_backpack VAOFSTRING, p_show_helmet VAOFSTRING, p_collections2 VAOFLONGSTRING, p_chunk_size number ); + procedure remove_player_obj( p_object_id VAOFSTRING, p_chunk_size number ); + procedure delete_demand_container( p_object_id VAOFSTRING, p_reason VAOFNUMBER, p_chunk_size number ); + procedure save_resource_type(p_resource_id VAOFSTRING, p_resource_name VAOFSTRING, p_resource_class VAOFSTRING, p_attributes VAOFSTRING, p_fractal_seeds VAOFSTRING, p_depleted_timestamp VAOFNUMBER, p_chunk_size number); + procedure save_bounty_hunter_target(p_object_id VAOFSTRING, p_target_id VAOFSTRING, p_chunk_size number); + function subtract_money_from_object(p_object_id number, p_amount number) return char; + +-- GENERATED PLSQL FOLLOWS +-- generated by makepersister.pl + procedure save_battlefield_marker_obj(p_object_id VAOFSTRING, p_region_name VAOFSTRING, p_chunk_size number); + procedure add_battlefield_marker_obj(p_object_id VAOFSTRING, p_region_name VAOFSTRING, p_chunk_size number); + procedure remove_battlefield_marker_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_building_obj(p_object_id VAOFSTRING, p_maintenance_cost VAOFNUMBER, p_time_last_checked VAOFNUMBER, p_is_public VAOFSTRING, p_city_id VAOFNUMBER, p_chunk_size number); + procedure add_building_obj(p_object_id VAOFSTRING, p_maintenance_cost VAOFNUMBER, p_time_last_checked VAOFNUMBER, p_is_public VAOFSTRING, p_city_id VAOFNUMBER, p_chunk_size number); + procedure remove_building_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_cell_obj(p_object_id VAOFSTRING, p_cell_number VAOFNUMBER, p_is_public VAOFSTRING, p_chunk_size number); + procedure add_cell_obj(p_object_id VAOFSTRING, p_cell_number VAOFNUMBER, p_is_public VAOFSTRING, p_chunk_size number); + procedure remove_cell_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_city_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure add_city_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure remove_city_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_creature_obj(p_object_id VAOFSTRING, p_scale_factor VAOFNUMBER, p_states VAOFNUMBER, p_posture VAOFNUMBER, p_shock_wounds VAOFNUMBER, p_master_id VAOFSTRING, p_rank VAOFNUMBER, p_base_walk_speed VAOFNUMBER, p_base_run_speed VAOFNUMBER, p_attribute_0 VAOFNUMBER, p_attribute_1 VAOFNUMBER, p_attribute_2 VAOFNUMBER, p_attribute_3 VAOFNUMBER, p_attribute_4 VAOFNUMBER, p_attribute_5 VAOFNUMBER, p_attribute_6 VAOFNUMBER, p_attribute_7 VAOFNUMBER, p_attribute_8 VAOFNUMBER, p_attribute_9 VAOFNUMBER, p_attribute_10 VAOFNUMBER, p_attribute_11 VAOFNUMBER, p_attribute_12 VAOFNUMBER, p_attribute_13 VAOFNUMBER, p_attribute_14 VAOFNUMBER, p_attribute_15 VAOFNUMBER, p_attribute_16 VAOFNUMBER, p_attribute_17 VAOFNUMBER, p_attribute_18 VAOFNUMBER, p_attribute_19 VAOFNUMBER, p_attribute_20 VAOFNUMBER, p_attribute_21 VAOFNUMBER, p_attribute_22 VAOFNUMBER, p_attribute_23 VAOFNUMBER, p_attribute_24 VAOFNUMBER, p_attribute_25 VAOFNUMBER, p_attribute_26 VAOFNUMBER, p_persisted_buffs VAOFSTRING, p_ws_x VAOFNUMBER, p_ws_y VAOFNUMBER, p_ws_z VAOFNUMBER, p_chunk_size number); + procedure add_creature_obj(p_object_id VAOFSTRING, p_scale_factor VAOFNUMBER, p_states VAOFNUMBER, p_posture VAOFNUMBER, p_shock_wounds VAOFNUMBER, p_master_id VAOFSTRING, p_rank VAOFNUMBER, p_base_walk_speed VAOFNUMBER, p_base_run_speed VAOFNUMBER, p_attribute_0 VAOFNUMBER, p_attribute_1 VAOFNUMBER, p_attribute_2 VAOFNUMBER, p_attribute_3 VAOFNUMBER, p_attribute_4 VAOFNUMBER, p_attribute_5 VAOFNUMBER, p_attribute_6 VAOFNUMBER, p_attribute_7 VAOFNUMBER, p_attribute_8 VAOFNUMBER, p_attribute_9 VAOFNUMBER, p_attribute_10 VAOFNUMBER, p_attribute_11 VAOFNUMBER, p_attribute_12 VAOFNUMBER, p_attribute_13 VAOFNUMBER, p_attribute_14 VAOFNUMBER, p_attribute_15 VAOFNUMBER, p_attribute_16 VAOFNUMBER, p_attribute_17 VAOFNUMBER, p_attribute_18 VAOFNUMBER, p_attribute_19 VAOFNUMBER, p_attribute_20 VAOFNUMBER, p_attribute_21 VAOFNUMBER, p_attribute_22 VAOFNUMBER, p_attribute_23 VAOFNUMBER, p_attribute_24 VAOFNUMBER, p_attribute_25 VAOFNUMBER, p_attribute_26 VAOFNUMBER, p_persisted_buffs VAOFSTRING, p_ws_x VAOFNUMBER, p_ws_y VAOFNUMBER, p_ws_z VAOFNUMBER, p_chunk_size number); + procedure remove_creature_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_factory_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure add_factory_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure remove_factory_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_guild_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure add_guild_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure remove_guild_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_harvester_inst_obj(p_object_id VAOFSTRING, p_installed_efficiency VAOFNUMBER, p_max_extraction_rate VAOFNUMBER, p_current_extraction_rate VAOFNUMBER, p_max_hopper_amount VAOFNUMBER, p_hopper_resource VAOFSTRING, p_hopper_amount VAOFNUMBER, p_resource_type VAOFSTRING, p_chunk_size number); + procedure add_harvester_inst_obj(p_object_id VAOFSTRING, p_installed_efficiency VAOFNUMBER, p_max_extraction_rate VAOFNUMBER, p_current_extraction_rate VAOFNUMBER, p_max_hopper_amount VAOFNUMBER, p_hopper_resource VAOFSTRING, p_hopper_amount VAOFNUMBER, p_resource_type VAOFSTRING, p_chunk_size number); + procedure remove_harvester_inst_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_installation_obj(p_object_id VAOFSTRING, p_installation_type VAOFNUMBER, p_activated VAOFSTRING, p_tick_count VAOFNUMBER, p_activate_start_time VAOFNUMBER, p_power VAOFNUMBER, p_power_rate VAOFNUMBER, p_chunk_size number); + procedure add_installation_obj(p_object_id VAOFSTRING, p_installation_type VAOFNUMBER, p_activated VAOFSTRING, p_tick_count VAOFNUMBER, p_activate_start_time VAOFNUMBER, p_power VAOFNUMBER, p_power_rate VAOFNUMBER, p_chunk_size number); + procedure remove_installation_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_intangible_obj(p_object_id VAOFSTRING, p_count VAOFNUMBER, p_chunk_size number); + procedure add_intangible_obj(p_object_id VAOFSTRING, p_count VAOFNUMBER, p_chunk_size number); + procedure remove_intangible_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_manf_schematic_obj(p_object_id VAOFSTRING, p_creator_id VAOFSTRING, p_creator_name VAOFSTRING, p_items_per_container VAOFNUMBER, p_manufacture_time VAOFNUMBER, p_draft_schematic VAOFNUMBER, p_chunk_size number); + procedure add_manf_schematic_obj(p_object_id VAOFSTRING, p_creator_id VAOFSTRING, p_creator_name VAOFSTRING, p_items_per_container VAOFNUMBER, p_manufacture_time VAOFNUMBER, p_draft_schematic VAOFNUMBER, p_chunk_size number); + procedure remove_manf_schematic_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_manufacture_inst_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure add_manufacture_inst_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure remove_manufacture_inst_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_mission_obj(p_object_id VAOFSTRING, p_difficulty VAOFNUMBER, p_end_x VAOFNUMBER, p_end_y VAOFNUMBER, p_end_z VAOFNUMBER, p_end_cell VAOFSTRING, p_end_scene VAOFNUMBER, p_mission_creator VAOFSTRING, p_reward VAOFNUMBER, p_root_script_name VAOFSTRING, p_start_x VAOFNUMBER, p_start_y VAOFNUMBER, p_start_z VAOFNUMBER, p_start_cell VAOFSTRING, p_start_scene VAOFNUMBER, p_description_table VAOFSTRING, p_description_text VAOFSTRING, p_title_table VAOFSTRING, p_title_text VAOFSTRING, p_mission_holder_id VAOFSTRING, p_status VAOFNUMBER, p_mission_type VAOFNUMBER, p_target_appearance VAOFNUMBER, p_target_name VAOFSTRING, p_chunk_size number); + procedure add_mission_obj(p_object_id VAOFSTRING, p_difficulty VAOFNUMBER, p_end_x VAOFNUMBER, p_end_y VAOFNUMBER, p_end_z VAOFNUMBER, p_end_cell VAOFSTRING, p_end_scene VAOFNUMBER, p_mission_creator VAOFSTRING, p_reward VAOFNUMBER, p_root_script_name VAOFSTRING, p_start_x VAOFNUMBER, p_start_y VAOFNUMBER, p_start_z VAOFNUMBER, p_start_cell VAOFSTRING, p_start_scene VAOFNUMBER, p_description_table VAOFSTRING, p_description_text VAOFSTRING, p_title_table VAOFSTRING, p_title_text VAOFSTRING, p_mission_holder_id VAOFSTRING, p_status VAOFNUMBER, p_mission_type VAOFNUMBER, p_target_appearance VAOFNUMBER, p_target_name VAOFSTRING, p_chunk_size number); + procedure remove_mission_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_planet_obj(p_object_id VAOFSTRING, p_planet_name VAOFSTRING, p_chunk_size number); + procedure add_planet_obj(p_object_id VAOFSTRING, p_planet_name VAOFSTRING, p_chunk_size number); + procedure remove_planet_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_resource_container_obj(p_object_id VAOFSTRING, p_resource_type VAOFSTRING, p_quantity VAOFNUMBER, p_source VAOFSTRING, p_chunk_size number); + procedure add_resource_container_obj(p_object_id VAOFSTRING, p_resource_type VAOFSTRING, p_quantity VAOFNUMBER, p_source VAOFSTRING, p_chunk_size number); + procedure remove_resource_container_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_ship_obj(p_object_id VAOFSTRING, p_slide_dampener VAOFNUMBER, p_current_chassis_hit_points VAOFNUMBER, p_maximum_chassis_hit_points VAOFNUMBER, p_chassis_type VAOFNUMBER, p_cmp_armor_hp_maximum VAOFSTRING, p_cmp_armor_hp_current VAOFSTRING, p_cmp_efficiency_general VAOFSTRING, p_cmp_efficiency_eng VAOFSTRING, p_cmp_eng_maintenance VAOFSTRING, p_cmp_mass VAOFSTRING, p_cmp_crc VAOFSTRING, p_cmp_hp_current VAOFSTRING, p_cmp_hp_maximum VAOFSTRING, p_cmp_flags VAOFSTRING, p_cmp_names VAOFLONGSTRING, p_weapon_damage_maximum VAOFSTRING, p_weapon_damage_minimum VAOFSTRING, p_weapon_effectiveness_shields VAOFSTRING, p_weapon_effectiveness_armor VAOFSTRING, p_weapon_eng_per_shot VAOFSTRING, p_weapon_refire_rate VAOFSTRING, p_weapon_ammo_current VAOFSTRING, p_weapon_ammo_maximum VAOFSTRING, p_weapon_ammo_type VAOFSTRING, p_shield_hp_front_maximum VAOFNUMBER, p_shield_hp_back_maximum VAOFNUMBER, p_shield_recharge_rate VAOFNUMBER, p_capacitor_eng_maximum VAOFNUMBER, p_capacitor_eng_recharge_rate VAOFNUMBER, p_engine_acc_rate VAOFNUMBER, p_engine_deceleration_rate VAOFNUMBER, p_engine_pitch_acc_rate VAOFNUMBER, p_engine_yaw_acc_rate VAOFNUMBER, p_engine_roll_acc_rate VAOFNUMBER, p_engine_pitch_rate_maximum VAOFNUMBER, p_engine_yaw_rate_maximum VAOFNUMBER, p_engine_roll_rate_maximum VAOFNUMBER, p_engine_speed_maximum VAOFNUMBER, p_reactor_eng_generation_rate VAOFNUMBER, p_booster_eng_maximum VAOFNUMBER, p_booster_eng_recharge_rate VAOFNUMBER, p_booster_eng_consumption_rate VAOFNUMBER, p_booster_acc VAOFNUMBER, p_booster_speed_maximum VAOFNUMBER, p_droid_if_cmd_speed VAOFNUMBER, p_installed_dcd VAOFSTRING, p_chassis_cmp_mass_maximum VAOFNUMBER, p_cmp_creators VAOFSTRING, p_cargo_hold_contents_maximum VAOFNUMBER, p_cargo_hold_contents_current VAOFNUMBER, p_cargo_hold_contents VAOFSTRING, p_chunk_size number); + procedure add_ship_obj(p_object_id VAOFSTRING, p_slide_dampener VAOFNUMBER, p_current_chassis_hit_points VAOFNUMBER, p_maximum_chassis_hit_points VAOFNUMBER, p_chassis_type VAOFNUMBER, p_cmp_armor_hp_maximum VAOFSTRING, p_cmp_armor_hp_current VAOFSTRING, p_cmp_efficiency_general VAOFSTRING, p_cmp_efficiency_eng VAOFSTRING, p_cmp_eng_maintenance VAOFSTRING, p_cmp_mass VAOFSTRING, p_cmp_crc VAOFSTRING, p_cmp_hp_current VAOFSTRING, p_cmp_hp_maximum VAOFSTRING, p_cmp_flags VAOFSTRING, p_cmp_names VAOFLONGSTRING, p_weapon_damage_maximum VAOFSTRING, p_weapon_damage_minimum VAOFSTRING, p_weapon_effectiveness_shields VAOFSTRING, p_weapon_effectiveness_armor VAOFSTRING, p_weapon_eng_per_shot VAOFSTRING, p_weapon_refire_rate VAOFSTRING, p_weapon_ammo_current VAOFSTRING, p_weapon_ammo_maximum VAOFSTRING, p_weapon_ammo_type VAOFSTRING, p_shield_hp_front_maximum VAOFNUMBER, p_shield_hp_back_maximum VAOFNUMBER, p_shield_recharge_rate VAOFNUMBER, p_capacitor_eng_maximum VAOFNUMBER, p_capacitor_eng_recharge_rate VAOFNUMBER, p_engine_acc_rate VAOFNUMBER, p_engine_deceleration_rate VAOFNUMBER, p_engine_pitch_acc_rate VAOFNUMBER, p_engine_yaw_acc_rate VAOFNUMBER, p_engine_roll_acc_rate VAOFNUMBER, p_engine_pitch_rate_maximum VAOFNUMBER, p_engine_yaw_rate_maximum VAOFNUMBER, p_engine_roll_rate_maximum VAOFNUMBER, p_engine_speed_maximum VAOFNUMBER, p_reactor_eng_generation_rate VAOFNUMBER, p_booster_eng_maximum VAOFNUMBER, p_booster_eng_recharge_rate VAOFNUMBER, p_booster_eng_consumption_rate VAOFNUMBER, p_booster_acc VAOFNUMBER, p_booster_speed_maximum VAOFNUMBER, p_droid_if_cmd_speed VAOFNUMBER, p_installed_dcd VAOFSTRING, p_chassis_cmp_mass_maximum VAOFNUMBER, p_cmp_creators VAOFSTRING, p_cargo_hold_contents_maximum VAOFNUMBER, p_cargo_hold_contents_current VAOFNUMBER, p_cargo_hold_contents VAOFSTRING, p_chunk_size number); + procedure remove_ship_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_static_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure add_static_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure remove_static_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_tangible_obj(p_object_id VAOFSTRING, p_max_hit_points VAOFNUMBER, p_owner_id VAOFSTRING, p_visible VAOFSTRING, p_appearance_data VAOFSTRING, p_interest_radius VAOFNUMBER, p_pvp_type VAOFNUMBER, p_pvp_faction VAOFNUMBER, p_damage_taken VAOFNUMBER, p_custom_appearance VAOFSTRING, p_count VAOFNUMBER, p_condition VAOFNUMBER, p_creator_id VAOFSTRING, p_source_draft_schematic VAOFNUMBER, p_chunk_size number); + procedure add_tangible_obj(p_object_id VAOFSTRING, p_max_hit_points VAOFNUMBER, p_owner_id VAOFSTRING, p_visible VAOFSTRING, p_appearance_data VAOFSTRING, p_interest_radius VAOFNUMBER, p_pvp_type VAOFNUMBER, p_pvp_faction VAOFNUMBER, p_damage_taken VAOFNUMBER, p_custom_appearance VAOFSTRING, p_count VAOFNUMBER, p_condition VAOFNUMBER, p_creator_id VAOFSTRING, p_source_draft_schematic VAOFNUMBER, p_chunk_size number); + procedure remove_tangible_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_token_obj(p_object_id VAOFSTRING, p_reference VAOFSTRING, p_target_server_template_name VAOFSTRING, p_target_shared_template_name VAOFSTRING, p_waypoint VAOFSTRING, p_chunk_size number); + procedure add_token_obj(p_object_id VAOFSTRING, p_reference VAOFSTRING, p_target_server_template_name VAOFSTRING, p_target_shared_template_name VAOFSTRING, p_waypoint VAOFSTRING, p_chunk_size number); + procedure remove_token_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_universe_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure add_universe_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure remove_universe_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_vehicle_obj(p_object_id VAOFSTRING, p_bogus VAOFNUMBER, p_chunk_size number); + procedure add_vehicle_obj(p_object_id VAOFSTRING, p_bogus VAOFNUMBER, p_chunk_size number); + procedure remove_vehicle_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_weapon_obj(p_object_id VAOFSTRING, p_min_damage VAOFNUMBER, p_max_damage VAOFNUMBER, p_damage_type VAOFNUMBER, p_elemental_type VAOFNUMBER, p_elemental_value VAOFNUMBER, p_attack_speed VAOFNUMBER, p_wound_chance VAOFNUMBER, p_accuracy VAOFNUMBER, p_attack_cost VAOFNUMBER, p_damage_radius VAOFNUMBER, p_min_range VAOFNUMBER, p_max_range VAOFNUMBER, p_chunk_size number); + procedure add_weapon_obj(p_object_id VAOFSTRING, p_min_damage VAOFNUMBER, p_max_damage VAOFNUMBER, p_damage_type VAOFNUMBER, p_elemental_type VAOFNUMBER, p_elemental_value VAOFNUMBER, p_attack_speed VAOFNUMBER, p_wound_chance VAOFNUMBER, p_accuracy VAOFNUMBER, p_attack_cost VAOFNUMBER, p_damage_radius VAOFNUMBER, p_min_range VAOFNUMBER, p_max_range VAOFNUMBER, p_chunk_size number); + procedure remove_weapon_obj(p_object_id VAOFSTRING, p_chunk_size number); + procedure save_player_quest_obj( p_object_id VAOFSTRING, p_title VAOFSTRING, p_description VAOFSTRING, p_creator VAOFSTRING, p_total_tasks VAOFNUMBER, p_difficulty VAOFNUMBER, p_task_title1 VAOFSTRING, p_task_description1 VAOFSTRING, p_task_title2 VAOFSTRING, p_task_description2 VAOFSTRING, p_task_title3 VAOFSTRING, p_task_description3 VAOFSTRING, p_task_title4 VAOFSTRING, p_task_description4 VAOFSTRING, p_task_title5 VAOFSTRING, p_task_description5 VAOFSTRING, p_task_title6 VAOFSTRING, p_task_description6 VAOFSTRING, p_task_title7 VAOFSTRING, p_task_description7 VAOFSTRING, p_task_title8 VAOFSTRING, p_task_description8 VAOFSTRING, p_task_title9 VAOFSTRING, p_task_description9 VAOFSTRING, p_task_title10 VAOFSTRING, p_task_description10 VAOFSTRING, p_task_title11 VAOFSTRING, p_task_description11 VAOFSTRING, p_task_title12 VAOFSTRING, p_task_description12 VAOFSTRING, p_chunk_size number ); + procedure add_player_quest_obj( p_object_id VAOFSTRING, p_title VAOFSTRING, p_description VAOFSTRING, p_creator VAOFSTRING, p_total_tasks VAOFNUMBER, p_difficulty VAOFNUMBER, p_task_title1 VAOFSTRING, p_task_description1 VAOFSTRING, p_task_title2 VAOFSTRING, p_task_description2 VAOFSTRING, p_task_title3 VAOFSTRING, p_task_description3 VAOFSTRING, p_task_title4 VAOFSTRING, p_task_description4 VAOFSTRING, p_task_title5 VAOFSTRING, p_task_description5 VAOFSTRING, p_task_title6 VAOFSTRING, p_task_description6 VAOFSTRING, p_task_title7 VAOFSTRING, p_task_description7 VAOFSTRING, p_task_title8 VAOFSTRING, p_task_description8 VAOFSTRING, p_task_title9 VAOFSTRING, p_task_description9 VAOFSTRING, p_task_title10 VAOFSTRING, p_task_description10 VAOFSTRING, p_task_title11 VAOFSTRING, p_task_description11 VAOFSTRING, p_task_title12 VAOFSTRING, p_task_description12 VAOFSTRING, p_chunk_size number ); + procedure remove_player_quest_obj( p_object_id VAOFSTRING, p_chunk_size number); + +end; + +/ + + GRANT EXECUTE ON "SWG"."PERSISTER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package PURGE_METHODS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."PURGE_METHODS" is + + -- Author : AVALDES + -- Created : 19-Jun-03 4:59:49 PM + + + FUNCTION Purge_objects + (date_in in objects.deleted_date%type) + RETURN NUMBER; + -- + -- + -- + FUNCTION time_purge + (date_in IN VARCHAR2) + RETURN INTEGER; + + +end purge_methods; + +/ + + GRANT EXECUTE ON "SWG"."PURGE_METHODS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package PURGE_METHODS2 +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."PURGE_METHODS2" is + + -- Author : AVALDES + -- Created : 19-Jun-03 4:59:49 PM + -- Modified: 07/23/2003, DDM - changed to use bulk deleting and variable chunk size + + -- Notes: 07/29/2003 testing completed against a copy of SDKSWG04 on sdk-devdb + -- Tested running purge_objects from SYSDATE back on ~675k parent objects + -- -test run 1: ~40 min to delete all child and parent obj in batches of 10K + -- -test run 2: ~2.5 hours to do the same with rman running + -- Tested run purge_consumables from SYSDATE back on ~300k parent objects + -- -test run 1: ~50 min to delete all child and parent obj in batches of 10K + -- -test run 2: crashed with snap to old error - restarted and it finished the rest + -- + -- Progress can be gauged by looking in the Logger table. There is a logging system being + -- used to track deletion progress. It can be disabled pro commentting out references to + -- the 'LOGGING' package. This package is not necessary for the purge program to run but is + -- nice to be able to monitor progress. If used, the logger table should be cleared periodically. + + + -- number of records to delete in a bulk chunk + chunk_size CONSTANT PLS_INTEGER := 10000; + + -- collections for bulk deleting, # elements must be the same as chunk_size + TYPE Obj_list_t IS VARRAY(10000) of objects.object_id%type; -- for child table with object ids + TYPE Obj_rowid_list_t IS VARRAY(10000) of ROWID; -- for parent table (rowid lookups are faster) + + FUNCTION Purge_objects + (date_in in objects.deleted_date%type) + RETURN PLS_INTEGER; + + PROCEDURE Purge_objects_work + (Obj_list IN Obj_list_t); + -- + -- + -- + FUNCTION time_purge + (date_in IN VARCHAR2) + RETURN PLS_INTEGER; + + FUNCTION Purge_consumables + (start_date_in in objects.deleted_date%type, + end_date_in in objects.deleted_date%type) + RETURN PLS_INTEGER; + + PROCEDURE Purge_consumables_work + (Obj_list IN Obj_list_t); + -- + -- + -- + FUNCTION time_purge_consumables + (start_date_in in objects.deleted_date%type, + end_date_in in objects.deleted_date%type) + RETURN PLS_INTEGER; + + +end purge_methods2; + +/ + + GRANT EXECUTE ON "SWG"."PURGE_METHODS2" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package PURGE_PROCESS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."PURGE_PROCESS" +as + type refcursor is ref cursor; + subtype objectid is number; + + procedure update_account_list (source_table varchar2); + function get_account_for_purge(p_purge_phase number, p_min_age number) return number; + procedure set_purge_status(p_station_id number, p_new_phase number); +end; + +/ + + GRANT EXECUTE ON "SWG"."PURGE_PROCESS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package SERVERCLOCK +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."SERVERCLOCK" +as + function get_last_save_time return number; +end; + +/ + + GRANT EXECUTE ON "SWG"."SERVERCLOCK" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package STATION_PLAYERS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."STATION_PLAYERS" +as + type refcursor is ref cursor; + subtype networkid is number(20); + + procedure update_character(p_clusterName in varchar2 ,p_characterId in networkid, p_characterName in varchar2, p_objectName in varchar2, p_x in number, p_y in number, p_z in number, p_sceneId in varchar2, p_cash_balance in number, p_bank_balance in number, p_objectTemplateName in varchar2, p_stationId in networkid, p_containedBy in networkid, p_createTime in number, p_playedTime in number , p_numLots in number); +end; + +/ + + GRANT EXECUTE ON "SWG"."STATION_PLAYERS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package UNDELETE_METHODS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."UNDELETE_METHODS" is + + -- Author : AVALDES + -- Created : 17-Jun-03 3:35:25 PM + + FUNCTION restore_object + (object_id_in IN objects.object_id%TYPE) + RETURN NUMBER; + + +end undelete_methods; + +/ + + GRANT EXECUTE ON "SWG"."UNDELETE_METHODS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package UTIL +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE "SWG"."UTIL" +as + type refcursor is ref cursor; + subtype networkid is number(20); + + function unix_time_2_oracle_date_PDT(p_unix_time in number) return date; + function unix_time_2_oracle_date_PST(p_unix_time in number) return date; + function unix_time_2_oracle_date_CDT(p_unix_time in number) return date; + function unix_time_2_oracle_date_CST(p_unix_time in number) return date; + function unix_time_2_oracle_date(p_unix_time in number, p_timezone_offset in number) return date; + function unix_to_oracle_date(p_unix_time in number, p_timezone_offset in number) return date; + +end; + +/ + + GRANT EXECUTE ON "SWG"."UTIL" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body ADMIN +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."ADMIN" +as + + procedure move_to_player (p_object_id objectid, p_target_player objectid) + as + l_target_inventory objectid; + begin + l_target_inventory := admin.get_inventory_for_player(p_target_player); + + if (l_target_inventory <> 0) then + move_to_container(p_object_id, l_target_inventory, p_target_player); + end if; + end; + + procedure move_to_player_bank (p_object_id objectid, p_target_player objectid) + as + l_target_bank objectid; + begin + l_target_bank := admin.get_bank_for_player(p_target_player); + + if (l_target_bank <> 0) then + move_to_container(p_object_id, l_target_bank, l_target_bank); + end if; + end; + + procedure move_to_player_datapad (p_object_id objectid, p_target_player objectid, p_max_depth number) + as + l_target_datapad objectid; + begin + l_target_datapad := admin.get_datapad_for_player(p_target_player); + + if (l_target_datapad <> 0) then + move_to_container_depth(p_object_id, l_target_datapad, p_target_player, p_max_depth); + end if; + + exception + when others then + NULL; + end; + + procedure move_to_container_depth (p_object_id objectid, p_target_container objectid, p_target_load_with objectid, p_max_depth number) + as + begin + update objects + set contained_by = p_target_container, + load_with = p_target_load_with, + x = 0, + y = 0, + z = 0, + node_x = 0, + node_z = 0 + where object_id = p_object_id; + + delete market_auctions + where item_id = p_object_id; + + fix_load_with_depth(p_object_id, p_target_load_with, p_max_depth); + end; + + procedure move_to_container (p_object_id objectid, p_target_container objectid, p_target_load_with objectid) + as + begin + move_to_container_depth(p_object_id, p_target_container, p_target_load_with, -1); + end; + + function get_inventory_for_player (p_player_id objectid) return objectid + as + result objectid; + begin + select object_id + into result + from objects + where contained_by = p_player_id + and object_template_id = 2007924155 + and deleted = 0; + + return result; + + exception when others then + return 0; + end; + + function get_bank_for_player (p_player_id objectid) return objectid + as + result objectid; + begin + select object_id + into result + from objects + where contained_by = p_player_id + and object_template_id = -172438875 + and deleted = 0; + + return result; + + exception when others then + return 0; + end; + + function get_datapad_for_player (p_player_id objectid) return objectid + as + result objectid; + begin + select object_id + into result + from objects + where contained_by = p_player_id + and object_template_id = -1783727815 + and deleted = 0; + + return result; + + exception when others then + return 0; + end; + + function get_player_for_player (p_player_id objectid) return objectid + as + result objectid; + begin + select object_id + into result + from objects + where contained_by = p_player_id + and object_template_id = -640104330 + and deleted = 0; + + return result; + + exception when others then + return 0; + end; + + function get_container_for_object (p_object_id objectid) return objectid + as + result objectid; + begin + select contained_by + into result + from objects + where object_id = p_object_id; + return result; + exception when others then + return 0; + end; + + function get_object_template_id (p_object_id objectid) return number + as + result number; + begin + select object_template_id + into result + from objects + where object_id = p_object_id; + + return result; + + exception when others then + return 0; + end; + + function restore_house (p_house_id objectid) return number -- 1=success, 2=no such object or not deleted + -- result codes: + -- 1 = success + -- 2 = not a character or not deleted + -- 3 = database error + as + cells number; + begin + + select count(*) into cells + from objects + where contained_by = p_house_id; + + if (cells = 0) then + return 3; + end if; + + update objects + set deleted = 0, deleted_date = NULL, bank_balance = bank_balance + 1000 -- roughly 1 day maintenance + where object_id = p_house_id + and deleted <> 0; + + if (sql%rowcount <> 1) then + return 2; + end if; + + update tangible_objects + set damage_taken = 0 + where object_id = p_house_id; + + update objects + set deleted = 0, deleted_date = NULL + where object_id in ( + select object_id + from objects + start with object_id = p_house_id + connect by prior object_id = contained_by) and + deleted in (select reason_code + from delete_reasons + where tag in ('House', 'ContainerDeleted')); + + fix_load_with (p_house_id, p_house_id); + + return 1; + + exception + when others then + return 3; + end; + + + function restore_character (p_player_id objectid, p_name out varchar2, p_account out number, p_template_id out number) return number + -- result codes: + -- 1 = success + -- 2 = not a character or not deleted + -- 3 = database error + as + character_reason number; + begin + select reason_code + into character_reason + from delete_reasons + where tag='CharacterDeleted'; + + begin + select station_id, object_name, object_template_id + into p_account, p_name, p_template_id + from players p, objects o + where p.character_object = p_player_id + and o.object_id = p_player_id + and o.object_id = p.character_object; + exception + when no_data_found then + return 2; + end; + + update objects + set deleted = 0, deleted_date = NULL + where object_id in ( + select object_id + from objects + start with object_id = p_player_id + connect by prior object_id = contained_by + and deleted = character_reason); + + return 1; + + exception + when others then + return 3; + end; + + function undelete_item (p_item_id objectid) return number -- 1=success, 2=no such object or not deleted + -- result codes: + -- 1 = success + -- 2 = not exist + -- 3 = database error + -- 4 = success, items needs to be loaded + as + cnt number; + l_type_id number; + l_name varchar2(4000); + l_account number; + l_template_id number; + l_load_with number; + l_result number; + begin + select count(*) into cnt + from objects + where object_id = p_item_id; + + if (cnt = 0) then + return 2; + end if; + + select count(*) into cnt + from objects + where object_id = p_item_id and (deleted <> 0 or deleted_date is not null); + + if (cnt = 0) then + return 1; + end if; + + select type_id into l_type_id + from objects + where object_id = p_item_id; + + select count(*) into cnt + from players + where character_object = p_item_id; + + if (l_type_id = 1112885583) then + -- 0x4255494f = 'BUIO', building objects + l_result := restore_house(p_item_id); + if (l_result = 1) then + return 4; + else + return l_result; + end if; + else if (l_type_id = 1129465167 and cnt > 0) then + -- 0x4352454f = 'CREO', creture objects and has a row in players table + -- This is a player + return restore_character(p_item_id, l_name, l_account, l_template_id); + else + update objects + set deleted = 0, deleted_date = null + where object_id in ( + select object_id + from objects + start with object_id = p_item_id + connect by prior object_id = contained_by); + + -- find out the top most load_with + begin + select count(*) into cnt + from objects + where (contained_by = 0 or load_contents = 'N') and rownum = 1 + start with object_id = p_item_id + connect by object_id = prior contained_by; + + if (cnt > 0) then + select object_id into l_load_with + from objects + where (contained_by = 0 or load_contents = 'N') and rownum = 1 + start with object_id = p_item_id + connect by object_id = prior contained_by; + fix_load_with(p_item_id, l_load_with); + else + fix_load_with(p_item_id, p_item_id); + end if; + + exception + when others then + return 2; + end; + end if; + end if; + select count(*) into cnt + from objects + where object_id = p_item_id and + type_id in (1112885583, -- BuildingObject + 1212763727, -- HarvesterInstallationObject + 1229869903, -- InstallationObject + 1296649807); -- ManufactureInstallationObject + if (cnt = 0) then + return 1; + else + return 4; + end if; + exception + when others then + return 2; + end; + + /** + * move an object to a player + parameters: + p_object_id item object id to move + p_target_player target player id + result: + 1: success + 2: cannot find player's inventory + 3: object not found + 4: unknown database error + 5: object is a player + + if you add an item type here, also add it to ConsoleCommandParserObject::performParsing() + 6: failed because object_template_id is 2007924155 (object/tangible/inventory/character_inventory.iff) + 7: failed because object_template_id is -1436615854 (object/tangible/mission_bag/mission_bag.iff) + 8: failed because object_template_id is -1783727815 (object/tangible/datapad/character_datapad.iff) + 9: failed because object_template_id is -172438875 (object/tangible/bank/character_bank.iff) + 10: failed because object_template_id is 2131722719 (object/weapon/melee/unarmed/unarmed_default_player.iff) + 11: failed because object_template_id is -640104330 (object/player/player.iff) + 12: failed because object_template_id is -1388112109 (object/cell/cell.iff) + 13: failed because object_template_id is -1324492681 (object/tangible/inventory/vendor_inventory.iff) + 14: failed because direct parent is a datapad object. + 15: failed because object is a building object (has an entry in the building_objects table) + 16: failed because object is an installation object (has an entry in the installation_objects table) + 17: failed because object is a ship object (has an entry in the ship_objects table) + */ + function move_item_to_player (p_object_id objectid, p_target_player objectid) return number + as + l_target_inventory objectid; + l_object_player objectid; + l_object_template_id number; + l_container_id number; + l_container_template_id number; + l_row_count number; + begin + l_object_template_id := admin.get_object_template_id(p_object_id); + l_object_player := admin.get_player_for_player(p_object_id); + l_target_inventory := admin.get_inventory_for_player(p_target_player); + + if (l_object_player <> 0) then + return 5; + end if; + + if (l_object_template_id = 2007924155) then + return 6; + end if; + + if (l_object_template_id = -1436615854) then + return 7; + end if; + + if (l_object_template_id = -1783727815) then + return 8; + end if; + + if (l_object_template_id = -172438875) then + return 9; + end if; + + if (l_object_template_id = 2131722719) then + return 10; + end if; + + if (l_object_template_id = -640104330) then + return 11; + end if; + + if (l_object_template_id = -1388112109) then + return 12; + end if; + + if (l_object_template_id = -1324492681) then + return 13; + end if; + + -- check to see if our parent is a datapad. + + l_container_id := admin.get_container_for_object(p_object_id); + l_container_template_id := get_object_template_id(l_container_id); + if (l_container_template_id = -1783727815) then + return 14; + end if; + + -- check to see if we are a building + select count(*) + into l_row_count + from building_objects + where object_id = p_object_id; + if (l_row_count > 0) then + return 15; + end if; + + select count(*) + into l_row_count + from installation_objects + where object_id = p_object_id; + if (l_row_count > 0) then + return 16; + end if; + + -- check to see if we're trying to move a ship object. + select count(*) + into l_row_count + from ship_objects + where object_id = p_object_id; + if (l_row_count >0) then + return 17; + end if; + + if (l_target_inventory <> 0) then + update objects + set contained_by = l_target_inventory, + load_with = p_target_player, + x = 0, + y = 0, + z = 0, + node_x = 0, + node_z = 0 + where object_id = p_object_id; + if (sql%rowcount = 0) then + return 3; + end if; + delete market_auctions + where item_id = p_object_id; + fix_load_with(p_object_id, p_target_player); + else + return 2; + end if; + return 1; + exception + when others then + return 4; + end; + + /** + * Fix the load_with values for anything contained by the specified object with a max depth or unlimited if max depth = -1 + */ + procedure fix_load_with_depth (p_topmost_object objectid, p_starting_loadwith objectid, p_max_depth number) as + oid_stack vaofnumber := vaofnumber(p_topmost_object); -- objects to look at + load_with_stack vaofnumber := vaofnumber(p_starting_loadwith); -- the load_with to inherit from these objects + stack_top number := 1; + parent_object number := 0; + parent_load_with number := 0; + current_load_with number := 0; + inherit_load_with number := 0; + stack_top_depth vaofnumber := vaofnumber(0); -- the depth of the object at the top of the stack + current_depth number := 0; + topmost_load_contents char(1) := ''; + begin + -- Depth-first search + + update objects set load_with = p_starting_loadwith where object_id = p_topmost_object; + + -- if the first object being fixed is demand loaded, set child object load_with values to this object + if (sql%rowcount = 1) then + select load_contents into topmost_load_contents from objects where object_id = p_topmost_object; + if (topmost_load_contents = 'N') then + load_with_stack(stack_top) := p_topmost_object; + end if; + end if; + + while (stack_top <> 0) loop + parent_object := oid_stack(stack_top); + parent_load_with := load_with_stack(stack_top); + current_depth := stack_top_depth(stack_top) + 1; + stack_top := stack_top - 1; + oid_stack.trim; + load_with_stack.trim; + + -- keep adding children unless at max depth + if (p_max_depth = -1 or current_depth <= p_max_depth) then + for x in (select object_id, player_controlled, deleted, load_contents from objects where contained_by = parent_object) loop + -- look at child objects and set their load_withs + + current_load_with := parent_load_with; + inherit_load_with := parent_load_with; + + -- load_with defaults to the parent's load with, except in special cases: + + if (x.deleted <> 0 ) then -- deleted, load with is 0 for this and all its contents + current_load_with := NULL; + inherit_load_with := NULL; + else + if (x.player_controlled = 'Y') then -- player. load with = self for this and contents, even if container is deleted + current_load_with := x.object_id; + inherit_load_with := x.object_id; + else + if (x.load_contents = 'N' and current_load_with IS NOT NULL) then -- demand-load container. contents get this as their load_with except if a parent is deleted + inherit_load_with := x.object_id; + end if; + end if; + end if; + + stack_top := stack_top + 1; + oid_stack.extend; + load_with_stack.extend; + stack_top_depth.extend; + oid_stack(stack_top) := x.object_id; + load_with_stack(stack_top) := inherit_load_with; + stack_top_depth(stack_top) := current_depth; + + update objects set load_with = current_load_with where object_id = x.object_id; + end loop; + end if; + end loop; + end; + + /** + * Fix the load_with values for anything contained by the specified object + */ + procedure fix_load_with (p_topmost_object objectid, p_starting_loadwith objectid) as + begin + fix_load_with_depth(p_topmost_object, p_starting_loadwith, -1); + end; + +end; + +/ + + GRANT EXECUTE ON "SWG"."ADMIN" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body BIOGRAPHY +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."BIOGRAPHY" +as + procedure set_biography (p_owner objectid, p_biography varchar2) + as + + m_enable_db_logging INTEGER := 0; + + begin + if (p_biography is not null) then + update biographies + set biography = p_biography + where object_id = p_owner; + + if (sql%rowcount = 0) then + insert into biographies (object_id, biography) + values (p_owner, p_biography); + end if; + else + delete biographies + where object_id = p_owner; + end if; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'biography.set_biography : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('biography.set_biography','objectid','number',p_owner); + db_error_logger.dblogerror_values('biography.set_biography','biography','varchar2',p_biography); + END IF; + END IF; + IF (db_error_logger.reraisecheck('biography','set_biography') = 1) THEN + -- RAISE; + NULL; + END IF; + end; + end; + + function get_biography (p_owner objectid) return refcursor + as + rc refcursor; + begin + open rc for + select biography + from biographies + where object_id = p_owner; + + return rc; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."BIOGRAPHY" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body BLOB_DATA_CONVERSION +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."BLOB_DATA_CONVERSION" as + +function blob_encodeoob_old(v_blob blob) return varchar2 +is + retstring varchar2(4000); + b binary_integer; +begin + if utl_raw.length(v_blob) > 1 then + for i in 1..trunc(utl_raw.length(v_blob)/2) loop + begin + b := utl_raw.CAST_TO_BINARY_INTEGER(utl_raw.SUBSTR(v_blob,(i*2)-1,2),2); + if b = 0 then + retstring := retstring || chr(15712191) || chr(1); + elsif b = 65535 then + retstring := retstring || chr(15712191) || chr(2); + elsif b = 27 then + retstring := retstring || chr(15712191) || chr(3); + elsif b > 2048 then -- 3-byte encoding + retstring := retstring || chr(((224 + mod(trunc(b / 4096), 16)) * 65536) + ((128 + mod(trunc(b / 64),64)) * 256) + (128 + mod(b, 64))); + elsif b > 127 then -- 2-byte encoding + retstring := retstring || chr((mod(trunc(b / 64),32) + 192) * 256 + (mod(b, 64) + 128)); + else + retstring := retstring || chr(b); + end if; + exception + when others then + retstring := retstring || ' '; + end; + exit when length(retstring) >= 3996; + end loop; + retstring := retstring || chr(15712191) || chr(4); + return retstring; + else + return null; + end if; +exception + when others then + return null; +end; + +function blob_encodeoob(v_blob blob) return varchar2 +is + retstring varchar2(4000); + b binary_integer; + buf1 raw(10); + buf2 raw(10); + buf raw(10); +begin + if utl_raw.length(v_blob) > 1 then + for i in 1..trunc(utl_raw.length(v_blob)/2) loop + b := utl_raw.CAST_TO_BINARY_INTEGER(utl_raw.SUBSTR(v_blob,(i*2)-1,2),2); + retstring := retstring || substr(to_char(b, '0XXXX'), 3); + exit when length(retstring) >= 3998; + end loop; + return retstring; + else + return null; + end if; +exception + when others then + return null; +end; + +function blob_hexdump(v_blob blob) return varchar2 +is + retstring varchar2(4000); + b binary_integer; +begin + if utl_raw.length(v_blob) > 0 then + for i in 1..utl_raw.length(v_blob) loop + b := utl_raw.CAST_TO_BINARY_INTEGER(utl_raw.SUBSTR(v_blob,i,1)); + retstring := retstring || to_char(b, '0x'); + end loop; + return retstring; + else + return null; + end if; +exception + when others then + return null; +end; + + +function blob_to_string(v_blob blob) return varchar2 +is + retstring varchar2(2000); + c char; + b binary_integer; +begin + if utl_raw.length(v_blob) > 0 then + -- assumes blob is in UTF16 + for i in 1..trunc(utl_raw.length(v_blob)/2) loop + b := utl_raw.CAST_TO_BINARY_INTEGER(utl_raw.SUBSTR(v_blob,(i*2)-1,2),2); + if b > 2048 then -- 3-byte encoding + retstring := retstring || chr(((224 + mod(trunc(b / 4096), 16)) * 65536) + ((128 + mod(trunc(b / 64),64)) * 256) + (128 + mod(b, 64))); + elsif b > 127 then -- 2-byte encoding + retstring := retstring || chr((mod(trunc(b / 64),32) + 192) * 256 + (mod(b, 64) + 128)); + else + retstring := retstring || chr(b); + end if; + end loop; + return retstring; + else + return null; + end if; +exception + when others then + return null; +end; + + +function string_hexdump(v_string varchar2) return varchar2 +is +begin + return blob_hexdump(utl_raw.CAST_TO_RAW(v_string)); +exception + when others then + return null; +end; + + +procedure convert_blob_data(v_item_id number) +is + i number; +begin +-- update market_auctions +-- set new_oob = blob_encodeoob(oob), +-- new_item_name = blob_to_string(item_name), +-- new_user_desc = blob_to_string(user_description) +-- where item_id = v_item_id; +-- commit; + i := 0; +end; + +end; + +/ + + GRANT EXECUTE ON "SWG"."BLOB_DATA_CONVERSION" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body CM_LOADER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."CM_LOADER" is + + FUNCTION get_location_list RETURN swg_cur + IS + + swg_cur_out swg_cur; + + BEGIN + -- Clean up orphaned vendors + DELETE from Auction_Locations + WHERE owner_id > 0 and not exists + (select 1 from objects where object_id = location_id and deleted = 0); + commit; + + OPEN swg_cur_out FOR + SELECT location_id, + owner_id, + location_name, + sales_tax, + sales_tax_bank_id, + empty_date, + last_access_date, + inactive_date, + status, + search_enabled, + entrance_charge + FROM auction_locations; + + RETURN swg_cur_out; + + END get_location_list; + + FUNCTION get_bid_list RETURN swg_cur + IS + + swg_cur_out swg_cur; + + BEGIN + OPEN swg_cur_out FOR + SELECT item_id, + bidder_id, + bid, + max_proxy_bid + FROM market_auction_bids; + + RETURN swg_cur_out; + + END get_bid_list; + + FUNCTION get_auction_list RETURN swg_cur + IS + + swg_cur_out swg_cur; + + BEGIN + OPEN swg_cur_out FOR + SELECT creator_id, + min_bid, + auction_timer, + buy_now_price, + user_description, + oob, + location_id, + item_id, + category, + item_timer, + item_name, + owner_id, + active, + item_size, + object_template_id + FROM market_auctions WHERE object_template_id IS NOT NULL; + + RETURN swg_cur_out; + + END get_auction_list; + + FUNCTION get_auction_attributes RETURN swg_cur + IS + + swg_cur_out swg_cur; + + BEGIN + OPEN swg_cur_out FOR + SELECT item_id, + attribute_name, + attribute_value + FROM market_auction_attributes; + + RETURN swg_cur_out; + + END get_auction_attributes; +end cm_loader; + +/ + + GRANT EXECUTE ON "SWG"."CM_LOADER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body CM_PERSISTER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."CM_PERSISTER" +as + + procedure update_auction_locations (p_location_id VAOFSTRING, + p_location_name VAOFSTRING, + p_owner_id VAOFSTRING, + p_sales_tax VAOFNUMBER, + p_sales_tax_bank_id VAOFSTRING, + p_empty_date VAOFNUMBER, + p_last_access_date VAOFNUMBER, + p_inactive_date VAOFNUMBER, + p_status VAOFNUMBER, + p_search_enabled VAOFSTRING, + p_entrance_charge VAOFNUMBER, + p_chunk_size number) + as + errors number; + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + UPDATE AUCTION_LOCATIONS Set + location_name = DECODE(p_location_name(i), NULL, location_name, p_location_name(i)), + owner_id = DECODE(p_owner_id(i), NULL, owner_id, p_owner_id(i)), + sales_tax = DECODE(p_sales_tax(i), NULL, sales_tax, p_sales_tax(i)), + sales_tax_bank_id = DECODE(p_sales_tax_bank_id(i), NULL, sales_tax_bank_id, p_sales_tax_bank_id(i)), + empty_date = DECODE(p_empty_date(i), NULL, empty_date, p_empty_date(i)), + last_access_date = DECODE(p_last_access_date(i), NULL, last_access_date, p_last_access_date(i)), + inactive_date = DECODE(p_inactive_date(i), NULL, inactive_date, p_inactive_date(i)), + status = DECODE(p_status(i), NULL, status, p_status(i)), + search_enabled = DECODE(p_search_enabled(i), NULL, search_enabled, p_search_enabled(i)), + entrance_charge = DECODE(p_entrance_charge(i), NULL, entrance_charge, p_entrance_charge(i)) + WHERE + location_id = p_location_id(i); + exception + when dml_errors then + errors := SQL%BULK_EXCEPTIONS.count; + end; + + procedure insert_auction_locations (p_location_id VAOFSTRING, + p_location_name VAOFSTRING, + p_owner_id VAOFSTRING, + p_sales_tax VAOFNUMBER, + p_sales_tax_bank_id VAOFSTRING, + p_empty_date VAOFNUMBER, + p_last_access_date VAOFNUMBER, + p_inactive_date VAOFNUMBER, + p_status VAOFNUMBER, + p_search_enabled VAOFSTRING, + p_entrance_charge VAOFNUMBER, + p_chunk_size number) + as + errors number; + k number; + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + INSERT into auction_locations ( + location_id, + location_name, + owner_id, + sales_tax, + sales_tax_bank_id, + empty_date, + last_access_date, + inactive_date, + status, + search_enabled, + entrance_charge ) + VALUES ( + p_location_id(i), + p_location_name(i), + p_owner_id(i), + p_sales_tax(i), + p_sales_tax_bank_id(i), + p_empty_date(i), + p_last_access_date(i), + p_inactive_date(i), + p_status(i), + p_search_enabled(i), + p_entrance_charge(i) ); + exception + when dml_errors then + errors := SQL%BULK_EXCEPTIONS.count; + for j in 1..errors loop + k := SQL%BULK_EXCEPTIONS(j).ERROR_INDEX; + UPDATE auction_locations Set + location_name = p_location_name(k), + owner_id = p_owner_id(k), + sales_tax = p_sales_tax(k), + sales_tax_bank_id = p_sales_tax_bank_id(k), + empty_date = p_empty_date(k), + last_access_date = p_last_access_date(k), + inactive_date = p_inactive_date(k), + status = p_status(k), + search_enabled = p_search_enabled(k), + entrance_charge = p_entrance_charge(k) + WHERE + location_id = p_location_id(k); + end loop; + end; + + procedure delete_auction_locations (p_location_id VAOFSTRING, p_chunk_size number) + as + errors number; + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + delete from auction_locations + where location_id = p_location_id(i); + exception + when dml_errors then + errors := SQL%BULK_EXCEPTIONS.count; + end; + + procedure insert_market_auction_bids (p_item_id VAOFSTRING, + p_bidder_id VAOFSTRING, + p_bid VAOFNUMBER, + p_max_proxy_bid VAOFNUMBER, + p_chunk_size number) + as + errors number; + k number; + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + INSERT into market_auction_bids ( + item_id, + bidder_id, + bid, + max_proxy_bid ) + VALUES ( + p_item_id(i), + p_bidder_id(i), + p_bid(i), + p_max_proxy_bid(i) ); + exception + when dml_errors then + errors := SQL%BULK_EXCEPTIONS.count; + for j in 1..errors loop + k := SQL%BULK_EXCEPTIONS(j).ERROR_INDEX; + UPDATE market_auction_bids Set + bidder_id = p_bidder_id(k), + bid = p_bid(k), + max_proxy_bid = p_max_proxy_bid(k) + WHERE + item_id = p_item_id(k); + end loop; + end; + + procedure update_market_auctions (p_item_id VAOFSTRING, + p_owner_id VAOFSTRING, + p_active VAOFNUMBER, + p_chunk_size number) + as + errors number; + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + UPDATE market_auctions Set + owner_id = DECODE(p_owner_id(i), NULL, owner_id, p_owner_id(i)), + active = DECODE(p_active(i), NULL, active, p_active(i)) + WHERE + item_id = p_item_id(i); + exception + when dml_errors then + errors := SQL%BULK_EXCEPTIONS.count; + end; + + procedure insert_market_auctions (p_item_id VAOFSTRING, + p_owner_id VAOFSTRING, + p_creator_id VAOFSTRING, + p_location_id VAOFSTRING, + p_min_bid VAOFNUMBER, + p_buy_now_price VAOFNUMBER, + p_auction_timer VAOFNUMBER, + p_oob VAOFLONGSTRING, + p_user_description VAOFLONGSTRING, + p_category VAOFNUMBER, + p_item_name VAOFLONGSTRING, + p_item_timer VAOFNUMBER, + p_active VAOFNUMBER, + p_item_size VAOFNUMBER, + p_object_template_id VAOFNUMBER, + p_chunk_size number) + as + errors number; + k number; + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + INSERT into market_auctions ( + item_id, + owner_id, + creator_id, + location_id, + min_bid, + buy_now_price, + auction_timer, + oob, + user_description, + category, + item_name, + item_timer, + active, + item_size, + object_template_id ) + VALUES ( + p_item_id(i), + p_owner_id(i), + p_creator_id(i), + p_location_id(i), + p_min_bid(i), + p_buy_now_price(i), + p_auction_timer(i), + p_oob(i), + p_user_description(i), + p_category(i), + p_item_name(i), + p_item_timer(i), + p_active(i), + p_item_size(i), + p_object_template_id(i) ); + exception + when dml_errors then + errors := SQL%BULK_EXCEPTIONS.count; + for j in 1..errors loop + k := SQL%BULK_EXCEPTIONS(j).ERROR_INDEX; + UPDATE market_auctions Set + owner_id = p_owner_id(k), + creator_id = p_creator_id(k), + location_id = p_location_id(k), + min_bid = p_min_bid(k), + buy_now_price = p_buy_now_price(k), + auction_timer = p_auction_timer(k), + oob = p_oob(k), + user_description = p_user_description(k), + category = p_category(k), + item_name = p_item_name(k), + item_timer = p_item_timer(k), + active = p_active(k), + item_size = p_item_size(k), + object_template_id = p_object_template_id(k) + WHERE + item_id = p_item_id(k); + end loop; + end; + + procedure delete_market_auctions (p_item_id VAOFSTRING, p_chunk_size number) + as + errors number; + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + delete from market_auction_attributes + where item_id = p_item_id(i); + + FORALL i in 1..p_chunk_size save exceptions + delete from market_auctions + where item_id = p_item_id(i); + --exception + --when dml_errors then + --errors := SQL%BULK_EXCEPTIONS.count; + end; + + procedure insert_auction_attributes (p_item_id VAOFSTRING, p_attribute_name VAOFSTRING, p_attribute_value VAOFSTRING, p_chunk_size number) + as + dml_errors EXCEPTION; + PRAGMA exception_init(dml_errors, -24381); + begin + FORALL i in 1..p_chunk_size save exceptions + insert into market_auction_attributes (item_id, attribute_name, attribute_value) + values (p_item_id(i), p_attribute_name(i), p_attribute_value(i)); + exception when dml_errors then + null; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."CM_PERSISTER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body CUSTSERV_PROCS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."CUSTSERV_PROCS" +as + + function get_characters_for_account + ( + station_id_in IN players.station_id%TYPE + ) + return cursortype + is + result cursortype; + begin + open result for + select + character_object, uc_character_name + from + players + where + station_id = station_id_in; + return result; + end get_characters_for_account; + + function get_deleted_items + ( + character_id_in IN objects.load_with%TYPE, + start_page_in IN number + ) + return cursortype + is + result cursortype; + begin + open result for + select * from + (select a.*, rownum RN from + ( select + o.object_id, name_string_table, name_string_text, object_name + from objects o, + (select object_id from objects where contained_by = character_id_in and object_template_id = -1783727815) datapad, + (select object_id from tangible_objects where owner_id = character_id_in) tangibles + where + ( deleted > 0 ) + and ( o.object_id = tangibles.object_id + or contained_by = datapad.object_id) + order by deleted_date desc ) a + where rownum <= start_page_in * 20 + 20) + where rn >= start_page_in * 20; + return result; + end get_deleted_items; + + function get_structures + ( + character_id_in IN objects.object_id%TYPE + ) + return cursortype + is + result cursortype; + begin + open result for + select o.object_id as object_id, + o.x as x, + o.y as y, + o.z as z, + o.scene_id as scene_id, + o.name_string_text as object_template, + o.deleted as deleted + from objects o, tangible_objects tan + where tan.owner_id = character_id_in + and tan.object_id = o.object_id + and ( (o.object_id in (select object_id from building_objects ) ) + or ( o.object_id in (select object_id from installation_objects) ) ); + return result; + end get_structures; + + function get_player_id + ( + character_name_in IN players.uc_character_name%TYPE + ) + return cursortype + is + result cursortype; + begin + open result for + select character_object, station_id + from players + where upper(uc_character_name) = upper(character_name_in); + return result; + end get_player_id; + + procedure move_player + ( + character_id_in IN objects.object_id%TYPE, + x_in IN objects.x%TYPE, + y_in IN objects.y%TYPE, + z_in IN objects.z%TYPE, + scene_in IN objects.scene_id%TYPE + ) + as + begin + update objects + set x = x_in, + y = y_in, + z = z_in, + scene_id = scene_in + where object_id = character_id_in; + end move_player; + + procedure undelete_item + ( + character_id_in IN objects.object_id%TYPE, + object_in IN objects.object_id%TYPE, + move_in IN number + ) + as + restore_result number; + begin + restore_result := admin.undelete_item(object_in); + if ((restore_result != 1) and (restore_result != 4)) then + return; + end if; + + if (move_in > 0) then + restore_result := admin.move_item_to_player(object_in, character_id_in); + end if; + return; + exception + when others then + return; + end undelete_item; + +end custserv_procs; + +/ + + GRANT EXECUTE ON "SWG"."CUSTSERV_PROCS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body DATALOOKUP +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."DATALOOKUP" +as + + function check_character_name(p_name varchar2) return number as + obj_id number; + begin + select character_object + into obj_id + from players + where uc_character_name = p_name; + + if (obj_id is null) then + return 0; + else + return 1; + end if; + + exception + when no_data_found then + return 0; + + when too_many_rows then + return 1; + end; + + function get_structures_for_purge(p_station_id number) return refcursor + as + result_cursor refcursor; + begin + open result_cursor for + select o.object_id, t.owner_id + from players p, tangible_objects t, objects o + where p.station_id = p_station_id + and p.character_object = t.owner_id + and t.object_id = o.object_id + and o.contained_by = 0 + and o.deleted = 0 + and o.type_id in (1112885583, 1212763727, 1296649807) --house, harvester, factory + -- exclude city halls and faction hqs + and o.object_template_id not in + (2104917241, -1402078881, -1650739949, 1078805016, -1085193189, -2036447549, + -1503538066, 1083153409, -1889839602, 2103485856, -1318727266, -447776542, + -278088733, 456016075, 2103180392, -1782254683, 1221154416, 943757712, + 344955127, -1651881206, -1428516812, 121334480, -1391658348, 585958560, + 1568866170, -970221632, 1490696786, -274776875, 1419804026, -1907246, + -714325274, -2102543938, -382786695); + + return result_cursor; + end; + + function get_vendors_for_purge(p_station_id number) return refcursor + as + result_cursor refcursor; + begin + open result_cursor for + -- get all vendors owned by this station_id + select o.object_id, t.owner_id, o.object_name + from players p, tangible_objects t, objects o + where p.station_id = p_station_id + and p.character_object = t.owner_id + and t.object_id = o.object_id + and o.deleted = 0 + and o.script_list like '%terminal.vendor:%' + + union + -- plus all vendors in purge structures owned by this station_id + select t.object_id, t.owner_id, o.object_name + from tangible_objects t, objects o + where t.object_id in + ( + select object_id + from objects + where deleted = 0 + and script_list like '%terminal.vendor:%' + start with object_id in + ( + select o.object_id + from players p, tangible_objects t, objects o + where p.station_id = p_station_id + and p.character_object = t.owner_id + and t.object_id = o.object_id + and o.deleted = 0 + and o.type_id in (1112885583, 1212763727, 1296649807) --house, harvester, factory + -- exclude city halls and faction hqs + and o.object_template_id not in + (2104917241, -1402078881, -1650739949, 1078805016, -1085193189, -2036447549, + -1503538066, 1083153409, -1889839602, 2103485856, -1318727266, -447776542, + -278088733, 456016075, 2103180392, -1782254683, 1221154416, 943757712, + 344955127, -1651881206, -1428516812, 121334480, -1391658348, 585958560, + 1568866170, -970221632, 1490696786, -274776875, 1419804026, -1907246, + -714325274, -2102543938, -382786695) + ) + connect by contained_by = prior object_id + ) and t.object_id = o.object_id; + + return result_cursor; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."DATALOOKUP" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body DATA_CLEANUP +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."DATA_CLEANUP" +as + procedure run_cleanup as + begin + delete messages + where not exists ( + select 1 from objects + where objects.object_id = messages.target); + end; + + procedure run_fix_bad_cells as + + v_count PLS_INTEGER := 0; + + begin + + FOR x IN + ( + SELECT * from + ( + SELECT a.object_id, a.contained_by, a.load_with, a.deleted, + (select contained_by from objects where object_id = a.contained_by) contained_by_value + FROM objects a, cell_objects b + WHERE a.object_id = b.object_id + ) + where contained_by_value = 0 and + contained_by != load_with + ) + LOOP + + UPDATE objects + SET load_with = x.contained_by + where object_id = x.object_id; + + v_count := v_count + 1; + IF (MOD(v_count, 1000) = 0) then + COMMIT; + END IF; + + END LOOP; + + COMMIT; + + run_fix_houses_w_bad_cells; + + end; + + procedure run_fix_houses_w_bad_cells as + + v_count PLS_INTEGER := 0; + v_last_contained_by NUMBER := -1; + v_current_contained_by NUMBER := 0; + v_retval NUMBER; + + begin + + FOR x IN + ( + select o1.object_id, o1.contained_by + from cell_objects c, objects o1, objects o2 + where c.object_id = o1.object_id + and o1.deleted > 0 + and o2.object_id = o1.contained_by + and o2.deleted = 0 + order by o1.contained_by + ) + LOOP + + v_current_contained_by := x.contained_by; + + UPDATE objects + SET deleted = 13, + deleted_date = SYSDATE + 100 + where object_id = x.object_id; + + IF (((v_current_contained_by != v_last_contained_by) and v_last_contained_by >=0)) THEN + + UPDATE objects + SET deleted = 13, + deleted_date = SYSDATE + 100 + where object_id = v_last_contained_by; + + v_retval := admin.restore_house (v_last_contained_by); + -- result codes: + -- 1 = success + -- 2 = not a character or not deleted + -- 3 = database error + + + END IF; + + + v_count := v_count + 1; + IF (MOD(v_count, 1000) = 0) then + COMMIT; + END IF; + + v_last_contained_by := v_current_contained_by; + + END LOOP; + + UPDATE objects + SET deleted = 13, + deleted_date = SYSDATE + 100 + where object_id = v_last_contained_by; + + v_retval := admin.restore_house (v_last_contained_by); + + + COMMIT; + + end; + + function getObjectsWithExpMessages return cursortype as + result_cursor cursortype; + begin + open result_cursor for + select target from messages where method='C++experience' group by target having count(*) > 100 order by count(*) desc; + + return result_cursor; + end; + + function getExperienceGrants(p_object_id objectid) return cursortype as + result_cursor cursortype; + begin + open result_cursor for + select data from messages where target=p_object_id and method='C++experience'; + + return result_cursor; + end; + + procedure delete_experience(p_object_id objectid) as + begin + delete messages where target=p_object_id and method='C++experience'; + end; + + procedure grant_experience(p_object_id objectid, p_experience_data varchar2) as + begin + insert into messages (message_id, target, method, data, call_time, guaranteed, delivery_type) + values (objectidmanager.get_single_id(), p_object_id, 'C++experience', p_experience_data, 0, 'Y', 0); + end; + + + + + + + -- Delete 10,000 unused object variables at a time + function object_variable_name_cleanup return number + as + begin + delete from object_variable_names where id not in (select name_id from object_variables group by name_id) and rownum < 10000; + commit; + return sql%rowcount; + end; + + + + -- Delete 25,000 orphaned rows at a time + function orphaned_object_cleanup return number + as + begin + update objects set deleted = 7 where contained_by != 0 and contained_by not in (select object_id from objects) and deleted = 0 and rownum < 25000; + commit; + return sql%rowcount; + end; + + + -- Delete 10,000 orphaned attribute rows at a time + function market_attributes_cleanup return number + as + begin + delete from market_auction_attributes where market_auction_attributes.ITEM_ID not in (select market_auctions.ITEM_ID from market_auctions group by market_auctions.ITEM_ID) and rownum < 10000; + commit; + return sql%rowcount; + end; + + + -- Delete 50,000 orphaned message rows at a time + function messages_cleanup return number + as + begin + + delete messages + where not exists ( + select 1 from objects + where objects.object_id = messages.target) and rownum < 50000; + commit; + return sql%rowcount; + end; + + + -- Delete 25,000 orphaned vendor object rows at a time + function vendor_object_cleanup return number + as + begin + update objects set deleted = 9 where + deleted = 0 + and + object_id not in (select item_id from market_auctions) + and + contained_by in (select object_id from objects where script_list like '%terminal.vendor:%') + and + rownum < 25000; + + commit; + return sql%rowcount; + end; + + + + + -- Delete 10,000 broken object rows at a time + function broken_object_cleanup return number + as + numrows number; + begin + numrows := 0; + + + delete from building_objects where not exists ( select 1 from objects where objects.object_id = building_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from cell_objects where not exists ( select 1 from objects where objects.object_id = cell_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from city_objects where not exists ( select 1 from objects where objects.object_id = city_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from creature_objects where not exists ( select 1 from objects where objects.object_id = creature_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from factory_objects where not exists ( select 1 from objects where objects.object_id = factory_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from harvester_installation_objects where not exists ( select 1 from objects where objects.object_id = harvester_installation_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from installation_objects where not exists ( select 1 from objects where objects.object_id = installation_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from intangible_objects where not exists ( select 1 from objects where objects.object_id = intangible_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from manf_schematic_objects where not exists ( select 1 from objects where objects.object_id = manf_schematic_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from manufacture_inst_objects where not exists ( select 1 from objects where objects.object_id = manufacture_inst_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from mission_objects where not exists ( select 1 from objects where objects.object_id = mission_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from planet_objects where not exists ( select 1 from objects where objects.object_id = planet_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from player_objects where not exists ( select 1 from objects where objects.object_id = player_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from ship_objects where not exists ( select 1 from objects where objects.object_id = ship_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from static_objects where not exists ( select 1 from objects where objects.object_id = static_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from tangible_objects where not exists ( select 1 from objects where objects.object_id = tangible_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from token_objects where not exists ( select 1 from objects where objects.object_id = token_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from universe_objects where not exists ( select 1 from objects where objects.object_id = universe_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from vehicle_objects where not exists ( select 1 from objects where objects.object_id = vehicle_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + delete from weapon_objects where not exists ( select 1 from objects where objects.object_id = weapon_objects.object_id ) and rownum < 10000; + commit; + numrows := numrows + sql%rowcount; + + return numrows; + end; + + +end; + +/ + + GRANT EXECUTE ON "SWG"."DATA_CLEANUP" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body DB_ERROR_LOGGER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."DB_ERROR_LOGGER" + as + procedure dblogerror( p_ora_errno number, p_notes varchar2 default NULL) + as + + PRAGMA AUTONOMOUS_TRANSACTION; + + v_ora_errmsg varchar2(255); + v_schema varchar2(30); + v_module varchar2(80); + v_notes varchar2(4000); + + begin + + v_ora_errmsg := SQLERRM(p_ora_errno); + stack_search(2, v_schema, v_module); + + if length(p_notes) > 4000 then + v_notes := substr(p_notes,1,4000); + else + v_notes := p_notes; + end if; + + insert into errorlog + ( error_id, + ora_errno, + ora_errmsg, + schema_name, + module_name, + notes ) + values + ( seq_errorlog.nextval, + p_ora_errno, + v_ora_errmsg, + v_schema, + v_module, + v_notes ); + + COMMIT; + + exception + when others then + NULL; + end; + + procedure dblogerror_values( p_owner varchar2, p_name varchar2, p_type varchar2, p_value varchar2) + as + + PRAGMA AUTONOMOUS_TRANSACTION; + v_value varchar2(4000); + + begin + + if length(p_value) > 4000 then + v_value := substr(p_value,1,4000); + else + v_value := p_value; + end if; + + insert into errorlog_values + ( error_id, + element_owner, + element_name, + element_type, + element_value ) + values + ( seq_errorlog.currval, + p_owner, + p_name, + p_type, + v_value ); + + COMMIT; + + exception + when others then + NULL; + + end; + + procedure stack_search ( i_search in integer, o_schema out varchar2, o_module out varchar2 ) + ----- + -- Returns the schema and module of the specified stack level + -- (specified by i_search). Stack level 0 is this proc. + -- Stack level 1 is this proc's caller. Level 2 is THEIR + -- caller. And so on. + ----- + as + call_stack varchar2(4096) default dbms_utility.format_call_stack; + n number; + m_found_stack boolean default false; + m_line varchar2(255); + m_count number := 0; + m_start integer := 1; + m_end integer := -1; + begin + o_schema := 'Not found'; + o_module := 'Not found'; + loop + m_end := instr( call_stack, chr(10), m_start ); + exit when ( m_count > i_search or m_end is NULL or m_end = 0 ); + m_line := ltrim(substr( call_stack, m_start + 20, m_end - (m_start + 20 ))); + m_start := m_end + 1; + -- Remove formatted stack header + if ( NOT m_found_stack ) then + if ( m_line like 'name%' ) then + m_found_stack := TRUE; + end if; + else + if ( m_count = i_search ) then + if ( m_line like 'pr%' ) then + n := length( 'procedure ' ); + elsif ( m_line like 'fun%' ) then + n := length( 'function ' ); + elsif ( m_line like 'package body%' ) then + n := length( 'package body ' ); + elsif ( m_line like 'pack%' ) then + n := length( 'package ' ); + else + n := length( 'anonymous block ' ); + end if; + m_line := substr( m_line, n ); + n := instr( m_line, '.' ); + o_schema := ltrim(rtrim(substr( m_line, 1, n-1 ))); + o_module := ltrim(rtrim(substr( m_line, n+1 ))); + end if; + m_count := m_count + 1; + end if; + end loop; +end stack_search; + + function getloglevel + RETURN INTEGER + as + + m_level INTEGER; + + begin + + select levelid + into m_level + from errorlog_level; + + return m_level; + + exception + when others then + return 0; + + end getloglevel; + + +function reraisecheck ( p_package varchar2 default NULL, p_procedure varchar2 default NULL) +return INTEGER +as + +PRAGMA AUTONOMOUS_TRANSACTION; + + m_unlimited_errors INTEGER; + m_errorlimit INTEGER; + m_errorcount INTEGER; +begin + + if (p_package IS NULL or p_procedure IS NULL) then + return 1; + else + update errorlog_reraise_limits + set errorcount = errorcount + 1 + where package = p_package and + procedure = p_procedure; + + commit; + + if (sql%rowcount = 0) then + return 1; + else + select unlimited_flag, errorlimit, errorcount + into m_unlimited_errors, m_errorlimit, m_errorcount + from errorlog_reraise_limits + where package = p_package and + procedure = p_procedure; + + if (m_unlimited_errors = 1) then + return 0; + else + if (m_errorcount <= m_errorlimit) then + return 0; + end if; + end if; + end if; + end if; + + + + return 1; + +exception + when others then + return 1; + +end reraisecheck; + +end; + +/ + + GRANT EXECUTE ON "SWG"."DB_ERROR_LOGGER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body GOLD_OVERRIDE +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."GOLD_OVERRIDE" as + + function load_objvar_overrides(p_schema varchar2) return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + 'select /*+ ORDERED USE_NL(T)*/ ' || + 't.object_id, t.name_id, t.type, t.value ' || + 'from ' || + p_schema || 'object_list l, ' || + 'object_variables t ' || + 'where l.object_id = t.object_id ' || + 'and nvl(t.detached,0) = 0'; + + return result_cursor; + end; + +end; + +/ + + GRANT EXECUTE ON "SWG"."GOLD_OVERRIDE" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body LAZY_DELETER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."LAZY_DELETER" as + + procedure purge_one_object (object_in in number) as + BEGIN + DELETE FROM armor WHERE object_id = object_in; + DELETE FROM battlefield_marker_objects WHERE object_id = object_in; + DELETE FROM battlefield_participants WHERE region_object_id = object_in; + DELETE FROM battlefield_participants WHERE character_object_id = object_in; + DELETE FROM biographies WHERE object_id = object_in; + DELETE FROM building_objects WHERE object_id = object_in; + DELETE FROM cell_objects WHERE object_id = object_in; + DELETE FROM city_objects WHERE object_id = object_in; + DELETE FROM creature_objects WHERE object_id = object_in; + DELETE FROM experience_points WHERE object_id = object_in; + DELETE FROM factory_objects WHERE object_id = object_in; + DELETE FROM guild_objects WHERE object_id = object_in; + DELETE FROM harvester_installation_objects WHERE object_id = object_in; + DELETE FROM installation_objects WHERE object_id = object_in; + DELETE FROM intangible_objects WHERE object_id = object_in; + DELETE FROM location_lists WHERE object_id = object_in; + DELETE FROM manf_schematic_attributes WHERE object_id = object_in; + DELETE FROM manf_schematic_objects WHERE object_id = object_in; + DELETE FROM manufacture_inst_objects WHERE object_id = object_in; + DELETE FROM mission_objects WHERE object_id = object_in; + DELETE FROM object_variables WHERE object_id = object_in; + DELETE FROM planet_objects WHERE object_id = object_in; + DELETE FROM player_objects WHERE object_id = object_in; + DELETE FROM player_quest_objects WHERE object_id = object_in; + DELETE FROM property_lists WHERE object_id = object_in; + DELETE FROM resource_container_objects WHERE object_id = object_in; + DELETE FROM scripts WHERE object_id = object_in; + DELETE FROM ship_objects WHERE object_id = object_in; + DELETE FROM static_objects WHERE object_id = object_in; + DELETE FROM swg_characters WHERE object_id = object_in; + DELETE FROM tangible_objects WHERE object_id = object_in; + DELETE FROM temp_characters WHERE object_id = object_in; + DELETE FROM token_objects WHERE object_id = object_in; + DELETE FROM universe_objects WHERE object_id = object_in; + DELETE FROM vehicle_objects WHERE object_id = object_in; + DELETE FROM waypoints WHERE object_id = object_in; + DELETE FROM weapon_objects WHERE object_id = object_in; + DELETE FROM messages WHERE target = object_in; + DELETE FROM objects WHERE object_id = object_in; + END purge_one_object; + + procedure purge_objects_bulk(p_object_id VAOFSTRING, p_chunk_size number, p_enable_db_logging number ) + as + + errors NUMBER; + + begin + + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM armor WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM battlefield_marker_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM battlefield_participants WHERE region_object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM battlefield_participants WHERE character_object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM biographies WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM building_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM cell_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM city_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM creature_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM experience_points WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM factory_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM guild_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM harvester_installation_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM installation_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM intangible_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM location_lists WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM manf_schematic_attributes WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM manf_schematic_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM manufacture_inst_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM mission_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM object_variables WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM planet_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM player_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM player_quest_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM property_lists WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM resource_container_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM scripts WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM static_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM swg_characters WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM tangible_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM temp_characters WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM token_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM universe_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM vehicle_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM waypoints WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM weapon_objects WHERE object_id = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM messages WHERE target = p_object_id(i); + FORALL i in 1..p_chunk_size SAVE EXCEPTIONS DELETE FROM objects WHERE object_id = p_object_id(i); + + exception when others then + if ( p_enable_db_logging > 0 ) then + errors:=SQL%BULK_EXCEPTIONS.COUNT; + FOR x IN 1..errors LOOP + db_error_logger.dblogerror( -SQL%BULK_EXCEPTIONS(x).ERROR_CODE, 'procedure purge_objects_bulk: error occurred in FORALL DELETE during iteration: ' || SQL%BULK_EXCEPTIONS(x).ERROR_INDEX ); + if ( p_enable_db_logging > 1 ) then + db_error_logger.dblogerror_values( 'lazy deleter', 'object_id' , 'number', p_object_id(to_number(SQL%BULK_EXCEPTIONS(x).ERROR_INDEX))); + end if; + END LOOP; + + else + NULL; + end if; + + end; + +end lazy_deleter; + +/ + + GRANT EXECUTE ON "SWG"."LAZY_DELETER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body LOADER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."LOADER" as + + procedure get_version_number(current_version in out number, min_version in out number) + as + begin + select version_number, min_version_number + into current_version, min_version + from version_number; + end; + + function get_character_name_list return cursortype + as + result_cursor cursortype; + begin + -- free up names that aren't in use anymore + delete from players + where not exists (select 1 from objects where objects.object_id = character_object); + + open result_cursor for + select character_object, station_id, uc_character_name, character_full_name, + (create_time - to_date('01/01/1970', 'MM/DD/YYYY')) * 24 * 3600, + (last_login_time - to_date('01/01/1970', 'MM/DD/YYYY')) * 24 * 3600 + from players; + + return result_cursor; + end; + + function locate_player (p_object_id number) return number + as + begin + insert into object_list (object_id, container_level) + select object_id, 100 + from objects + where load_with = p_object_id and deleted = 0; + + return sql%rowcount; + end; + + procedure locate_universe + as + begin + insert into object_list (object_id) + select o.object_id + from objects o, universe_objects u + where o.object_id = u.object_id + and o.deleted=0; + end; + + procedure locate_contained_object (p_container_id number, p_object_id number) + as + begin + insert into object_list (object_id, container_level) + select object_id, 100 + from objects o + start with + o.object_id = p_object_id + and o.contained_by = p_container_id + and o.deleted = 0 + connect by + prior o.object_id = o.contained_by + and o.deleted = 0; + end; + + function locate_by_loadwith_batch (p_loadwiths vaofstring, p_chunk_size number) + return number + as + begin + forall i in 1..p_chunk_size + insert into object_list (object_id) + select o.object_id + from objects o + where o.load_with = p_loadwiths(i) and o.deleted = 0; + + return sql%rowcount; + end; + + procedure locate_contents (p_container_id number) + as + begin + insert into object_list (object_id, container_level) + select object_id, 100 + from objects o + where o.load_with = p_container_id and o.deleted = 0; + end; + + procedure locate_structure (p_object_id number, p_x out number, p_z out number, p_scene_id out varchar2, p_found out number) + as + begin + select x, z, scene_id, 1 into p_x, p_z, p_scene_id, p_found + from objects + where object_id = p_object_id and deleted = 0 and + type_id in (1112885583, -- BuildingObject + 1212763727, -- HarvesterInstallationObject + 1229869903, -- InstallationObject + 1296649807); -- ManufactureInstallationObject + exception + when no_data_found then + p_found := 0; + end; + + function get_characters (p_station_id number) return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select + character_object, + object_template_id, + scene_id, + object_name, + container, + x, + y, + z + from character_view + where station_id = p_station_id; + + return result_cursor; + end; + + function load_chunk_object_list (p_scene_id varchar, p_node_x float, p_node_z float) return number + as + num number; + begin + select count(*) + into num + from objects + where node_x = p_node_x + and node_z = p_node_z + and scene_id = p_scene_id + and deleted = 0; + + if (num > 0) then + insert into object_list (object_id, container_level) + select object_id, level + from objects + start with + node_x = p_node_x + and node_z = p_node_z + and scene_id = p_scene_id + and deleted = 0 + and contained_by = 0 + and player_controlled = 'N' + connect by + prior object_id = contained_by + and deleted = 0 + and player_controlled='N' + and prior load_contents='Y'; + + return sql%rowcount; + else + return 0; + end if; + end; + + function load_manf_schematic_attributes return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ t.object_id, t.attribute_type, t.value + from + object_list l, + manf_schematic_attributes t + where t.object_id = l.object_id; + + return result_cursor; + end; + + function load_armor return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.layer, + t.object_template, + t.effectiveness, + t.integrity, + t.special_protections, + t.encumberance_0, + t.encumberance_1, + t.encumberance_2, + t.encumberance_3, + t.encumberance_4, + t.encumberance_5, + t.encumberance_6, + t.encumberance_7, + t.encumberance_8 + from + object_list l, + armor t + where t.object_id = l.object_id; + + return result_cursor; + end; + + function load_scripts return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T)*/ + t.object_id, t.script, t.sequence_no + from + object_list l, + scripts t + where t.object_id = l.object_id; + + return result_cursor; + end; + + function load_object_variables return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T)*/ + t.object_id, t.name_id, t.type, t.value + from + object_list l, + object_variables t + where l.object_id = t.object_id + and nvl(t.detached,0) = 0; + + return result_cursor; + end; + + function load_property_lists return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, t.list_id, t.value + from object_list l, property_lists t + where t.object_id = l.object_id; + + return result_cursor; + end; + + function load_experience return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, t.experience_type, t.points + from object_list l, experience_points t + where t.object_id = l.object_id; + + return result_cursor; + end; + + function load_battlefield_participants return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select t.region_object_id, t.character_object_id, t.faction_id /*+ ORDERED USE_NL(T) */ + from object_list l, battlefield_participants t + where t.region_object_id = l.object_id; -- order does not matter + + return result_cursor; + end; + + function load_messages return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(MESSAGES) */ + target, message_id, method, data, call_time, guaranteed, delivery_type + from object_list, messages + where target =object_list.object_id; + + return result_cursor; + end; + + function load_location return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.list_id, + t.sequence_number, + t.name, + t.scene, + t.x, + t.y, + t.z, + t.radius + from + object_list l, + location_lists t + where t.object_id = l.object_id; + + return result_cursor; + end; + + function load_object + return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + x, + y, + z, + quaternion_w, + quaternion_x, + quaternion_y, + quaternion_z, + node_x, + node_y, + node_z, + object_template_id, + type_id, + scene_id, + controller_type, + deleted, + object_name, + volume, + contained_by, + slot_arrangement, + player_controlled, + cache_version, + load_contents, + cash_balance, + bank_balance, + complexity, + name_string_table, + name_string_text, + static_item_name, + nvl(static_item_version,0), + nvl(conversion_id,0), + load_with, + objvar_0_name, + objvar_0_type, + objvar_0_value, + objvar_1_name, + objvar_1_type, + objvar_1_value, + objvar_2_name, + objvar_2_type, + objvar_2_value, + objvar_3_name, + objvar_3_type, + objvar_3_value, + objvar_4_name, + objvar_4_type, + objvar_4_value, + objvar_5_name, + objvar_5_type, + objvar_5_value, + objvar_6_name, + objvar_6_type, + objvar_6_value, + objvar_7_name, + objvar_7_type, + objvar_7_value, + objvar_8_name, + objvar_8_type, + objvar_8_value, + objvar_9_name, + objvar_9_type, + objvar_9_value, + objvar_10_name, + objvar_10_type, + objvar_10_value, + objvar_11_name, + objvar_11_type, + objvar_11_value, + objvar_12_name, + objvar_12_type, + objvar_12_value, + objvar_13_name, + objvar_13_type, + objvar_13_value, + objvar_14_name, + objvar_14_type, + objvar_14_value, + objvar_15_name, + objvar_15_type, + objvar_15_value, + objvar_16_name, + objvar_16_type, + objvar_16_value, + objvar_17_name, + objvar_17_type, + objvar_17_value, + objvar_18_name, + objvar_18_type, + objvar_18_value, + objvar_19_name, + objvar_19_type, + objvar_19_value, + script_list, + l.container_level + from + object_list l, + objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function verify_containment_chain(p_start_with_object_id in number) return number + as + -- result codes: + -- 1 = containment chain is recursive and is in starting(character) object chain + -- (can be fixed by placing the object in the world if its a character) + -- 2 = containment chain is recursive but not in starting object chain (this must be fixed manually) + -- 3 = no recursion in containment chain + + m_retval pls_integer; + m_temp pls_integer; + begin +/* m_retval := 2; + + select count(*) into m_temp + from objects + start with object_id = p_start_with_object_id + connect by prior object_id = contained_by + and object_id != p_start_with_object_id; +*/ + m_retval := 1; + + select count(*) into m_temp + from objects + start with object_id = p_start_with_object_id + connect by object_id = prior contained_by; + + m_retval := 3; + + return m_retval; + exception + when others then + return m_retval; + end; + + function fix_player_containment_chain(p_start_with_object_id in number) return number + as + -- result codes: + -- 0 = database error + -- 4 = success fix player containment issues + + PRAGMA AUTONOMOUS_TRANSACTION; + + begin + update objects set contained_by = 0 where object_id = p_start_with_object_id; + admin.fix_load_with(p_start_with_object_id, p_start_with_object_id); + commit; + + return 4; + + exception + when others then + return 0; + end; + + + +procedure verify_character (p_station_id in number, p_character_id in number, p_gold_schema in varchar2, p_approved out varchar2, p_character_name out varchar2, p_scene_id out varchar2, p_container_id out number, p_x out number, p_y out number, p_z out number, p_containment_check out number) + as + + -- p_containment_check is a flag indicating the containment stautus to be used for logging on the C sid + -- 0 = there was a database error trying to fix containment + -- 1 = there is a recursive containment error in the character object chain that wasn't fixed + -- 2 = there is a recursive containment error in the containment chain not in the character chain + -- 3 = the containment chain is ok + -- 4 = there was a recursive containment error in the character object chain that was fixed + + m_containment_ok pls_integer; + + wsx number := null; + wsy number := null; + wsz number := null; + + begin + + + -- check containment chain + m_containment_ok := verify_containment_chain(p_character_id); + + -- if containment is bad for the character object try to fix it + if (m_containment_ok = 1) then + m_containment_ok := fix_player_containment_chain(p_character_id); + end if; + + p_containment_check := m_containment_ok; + + if (m_containment_ok >= 3) then + + select object_name, scene_id, contained_by, x, y, z, ws_x, ws_y, ws_z + into p_character_name, p_scene_id, p_container_id, p_x, p_y, p_z, wsx, wsy, wsz + from players p, objects o, creature_objects c + where p.station_id = p_station_id + and p.character_object = p_character_id + and o.object_id = p.character_object + and c.object_id = o.object_id + and o.deleted = 0; + + if (p_container_id = 0) then + begin + p_container_id := p_character_id; + p_approved := 'Y'; + end; + else + begin + select object_id, x,y,z,'Y' + into p_container_id, p_x, p_y, p_z, p_approved + from objects + where contained_by=0 + start with object_id = p_character_id + connect by prior contained_by=object_id and prior scene_id=scene_id and player_controlled = 'N'; + + exception + when no_data_found then + -- might be in a gold building + if (p_gold_schema is not null) then + begin + execute immediate + 'select object_id, x,y,z,''Y'' ' || + 'from ' || p_gold_schema || 'objects ' || + 'where contained_by=0 ' || + 'start with object_id = :container_id ' || + 'connect by prior contained_by=object_id' + into p_container_id, p_x, p_y, p_z, p_approved + using p_container_id; + + exception + when no_data_found then + select object_id, x,y,z,'Y' + into p_container_id, p_x, p_y, p_z, p_approved + from objects + where object_id = p_character_id; + end; + else + select object_id, x,y,z,'Y' + into p_container_id, p_x, p_y, p_z, p_approved + from objects + where object_id = p_character_id; + end if; + end; + end if; + + else + + select 'N' into p_approved from dual; + + end if; + + + if ( wsx is not null ) then + begin + p_x := wsx; + p_y := wsy; + p_z := wsz; + end; + end if; + + + update players + set last_login_time = sysdate + where station_id = p_station_id + and character_object = p_character_id; + + exception + when no_data_found then + select 'N' + into p_approved + from dual; + when too_many_rows then + select 'N' + into p_approved + from dual; + when others then + select 'N' + into p_approved + from dual; + end; + + + + + function load_waypoint + return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.waypoint_id, + t.appearance_name_crc, + t.location_x, + t.location_y, + t.location_z, + t.location_cell, + t.location_scene, + t.name, + t.color, + t.active + from + object_list l, + waypoints t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_player_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) USE_NL(A)*/ + t.object_id, + t.station_id, + a.house_id, + t.num_lots, + a.is_outcast, + a.cheater_level, + a.max_lots_adjustment, + t.personal_profile_id, + t.character_profile_id, + t.skill_title, + t.born_date, + t.played_time, + t.force_regen_rate, + t.force_power, + t.max_force_power, + t.active_quests, + t.completed_quests, + t.current_quest, + t.quests, + t.role_icon_choice, + t.quests2, + t.quests3, + t.quests4, + t.skill_template, + t.working_skill, + nvl(t.current_gcw_points,0), + nvl(t.current_gcw_rating,-1), + nvl(t.current_pvp_kills,0), + nvl(t.lifetime_gcw_points,0), + nvl(t.max_gcw_imperial_rating,-1), + nvl(t.max_gcw_rebel_rating,-1), + nvl(t.lifetime_pvp_kills,0), + nvl(t.next_gcw_rating_calc_time,0), + t.collections, + nvl(t.show_backpack,'Y'), + nvl(t.show_helmet,'Y'), + t.collections2 + from + object_list l, + player_objects t, + accounts a + where t.station_id = a.station_id and + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_resource_types return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select + resource_id, + resource_name, + resource_class, + attributes, + fractal_seeds, + depleted_timestamp + from + resource_types; + + return result_cursor; + end; + + function load_bounty_hunter_targets return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select object_id, target_id + from bounty_hunter_targets + where target_id <> 0; + return result_cursor; + end; + +-- GENERATED PLSQL FOLLOWS +-- generated by makeloader.pl + + function load_battlefield_marker_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.region_name + from + object_list l, + battlefield_marker_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_building_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.maintenance_cost, + t.time_last_checked, + t.is_public, + t.city_id + from + object_list l, + building_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_cell_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.cell_number, + t.is_public + from + object_list l, + cell_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_city_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id + from + object_list l, + city_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_creature_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.scale_factor, + t.states, + t.posture, + t.shock_wounds, + t.master_id, + t.rank, + t.base_walk_speed, + t.base_run_speed, + t.attribute_0, + t.attribute_1, + t.attribute_2, + t.attribute_3, + t.attribute_4, + t.attribute_5, + t.attribute_6, + t.attribute_7, + t.attribute_8, + t.attribute_9, + t.attribute_10, + t.attribute_11, + t.attribute_12, + t.attribute_13, + t.attribute_14, + t.attribute_15, + t.attribute_16, + t.attribute_17, + t.attribute_18, + t.attribute_19, + t.attribute_20, + t.attribute_21, + t.attribute_22, + t.attribute_23, + t.attribute_24, + t.attribute_25, + t.attribute_26, + t.persisted_buffs, + t.ws_x, + t.ws_y, + t.ws_z + from + object_list l, + creature_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_factory_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id + from + object_list l, + factory_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_guild_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id + from + object_list l, + guild_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_harvester_inst_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.installed_efficiency, + t.max_extraction_rate, + t.current_extraction_rate, + t.max_hopper_amount, + t.hopper_resource, + t.hopper_amount, + t.resource_type + from + object_list l, + harvester_installation_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_installation_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.installation_type, + t.activated, + t.tick_count, + t.activate_start_time, + t.power, + t.power_rate + from + object_list l, + installation_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_intangible_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.count + from + object_list l, + intangible_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_manf_schematic_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.creator_id, + t.creator_name, + t.items_per_container, + t.manufacture_time, + t.draft_schematic + from + object_list l, + manf_schematic_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_manufacture_inst_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id + from + object_list l, + manufacture_inst_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_mission_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.difficulty, + t.end_x, + t.end_y, + t.end_z, + t.end_cell, + t.end_scene, + t.mission_creator, + t.reward, + t.root_script_name, + t.start_x, + t.start_y, + t.start_z, + t.start_cell, + t.start_scene, + t.description_table, + t.description_text, + t.title_table, + t.title_text, + t.mission_holder_id, + t.status, + t.mission_type, + t.target_appearance, + t.target_name + from + object_list l, + mission_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_planet_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.planet_name + from + object_list l, + planet_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_resource_container_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.resource_type, + t.quantity, + t.source + from + object_list l, + resource_container_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_ship_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.slide_dampener, + t.current_chassis_hit_points, + t.maximum_chassis_hit_points, + t.chassis_type, + t.cmp_armor_hp_maximum, + t.cmp_armor_hp_current, + t.cmp_efficiency_general, + t.cmp_efficiency_eng, + t.cmp_eng_maintenance, + t.cmp_mass, + t.cmp_crc, + t.cmp_hp_current, + t.cmp_hp_maximum, + t.cmp_flags, + t.cmp_names, + t.weapon_damage_maximum, + t.weapon_damage_minimum, + t.weapon_effectiveness_shields, + t.weapon_effectiveness_armor, + t.weapon_eng_per_shot, + t.weapon_refire_rate, + t.weapon_ammo_current, + t.weapon_ammo_maximum, + t.weapon_ammo_type, + t.shield_hp_front_maximum, + t.shield_hp_back_maximum, + t.shield_recharge_rate, + t.capacitor_eng_maximum, + t.capacitor_eng_recharge_rate, + t.engine_acc_rate, + t.engine_deceleration_rate, + t.engine_pitch_acc_rate, + t.engine_yaw_acc_rate, + t.engine_roll_acc_rate, + t.engine_pitch_rate_maximum, + t.engine_yaw_rate_maximum, + t.engine_roll_rate_maximum, + t.engine_speed_maximum, + t.reactor_eng_generation_rate, + t.booster_eng_maximum, + t.booster_eng_recharge_rate, + t.booster_eng_consumption_rate, + t.booster_acc, + t.booster_speed_maximum, + t.droid_if_cmd_speed, + t.installed_dcd, + t.chassis_cmp_mass_maximum, + t.cmp_creators, + t.cargo_hold_contents_maximum, + t.cargo_hold_contents_current, + t.cargo_hold_contents + from + object_list l, + ship_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_static_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id + from + object_list l, + static_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_tangible_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.max_hit_points, + t.owner_id, + t.visible, + t.appearance_data, + t.interest_radius, + t.pvp_type, + t.pvp_faction, + t.damage_taken, + t.custom_appearance, + t.count, + t.condition, + t.creator_id, + t.source_draft_schematic + from + object_list l, + tangible_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_token_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.reference, + t.target_server_template_name, + t.target_shared_template_name, + t.waypoint + from + object_list l, + token_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_universe_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id + from + object_list l, + universe_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_vehicle_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.bogus + from + object_list l, + vehicle_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + function load_weapon_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.min_damage, + t.max_damage, + t.damage_type, + t.elemental_type, + t.elemental_value, + t.attack_speed, + t.wound_chance, + t.accuracy, + t.attack_cost, + t.damage_radius, + t.min_range, + t.max_range + from + object_list l, + weapon_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; + + + function load_player_quest_object return cursortype + as + result_cursor cursortype; + begin + open result_cursor for + select /*+ ORDERED USE_NL(T) */ + t.object_id, + t.title, + t.description, + t.creator, + t.total_tasks, + t.difficulty, + t.task_title1, + t.task_description1, + t.task_title2, + t.task_description2, + t.task_title3, + t.task_description3, + t.task_title4, + t.task_description4, + t.task_title5, + t.task_description5, + t.task_title6, + t.task_description6, + t.task_title7, + t.task_description7, + t.task_title8, + t.task_description8, + t.task_title9, + t.task_description9, + t.task_title10, + t.task_description10, + t.task_title11, + t.task_description11, + t.task_title12, + t.task_description12 + from + object_list l, + player_quest_objects t + where + t.object_id=l.object_id; + + return result_cursor; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."LOADER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body LOGIN +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."LOGIN" +as + + procedure register_new_cluster(p_cluster_name in varchar2, p_address in varchar2, p_cluster_id out number) + as + begin + select id + into p_cluster_id + from cluster_list + where name = p_cluster_name; + + exception + when no_data_found then + insert into cluster_list (id,name,address,secret,locked, not_recommended,group_id, + online_player_limit,online_free_trial_limit,free_trial_can_create_char, online_tutorial_limit) + select nvl(max(id)+1,1), p_cluster_name,p_address,'N','N','N',1, + 2500,250,'Y',350 + from cluster_list; + + select id + into p_cluster_id + from cluster_list + where name = p_cluster_name; + end; + + function get_cluster_list (p_group in number) return refcursor + as + result_cursor refcursor; + maxCharacterPerAccount number; + begin + select account_limit into maxCharacterPerAccount + from default_char_limits; + + open result_cursor for + select id, name, address, port, secret, locked, not_recommended, maxCharacterPerAccount, + online_player_limit,online_free_trial_limit,free_trial_can_create_char,online_tutorial_limit + from cluster_list + where group_id = p_group; + + return result_cursor; + end; + + function get_avatar_list (p_station_id number, p_cluster_group number) return refcursor + as + result refcursor; + begin + open result for + select + c.character_name, + c.template_id, + c.object_id, + c.cluster_id, + c.character_type + from + swg_characters c, cluster_list l + where + c.cluster_id = l.id and + l.group_id = p_cluster_group and + station_id = p_station_id and + enabled = 'Y'; + + return result; + end; + + function get_open_character_slots(p_station_id number, p_cluster_id number) return refcursor + as + result_cursor refcursor; + over_account_limit number; + over_cluster_limit number; + begin + -- does the account have too many characters, or does the cluster have too many characters? + + select account_limit - account_counter.num, cluster_limit - cluster_list.num_characters + into over_account_limit, over_cluster_limit + from + (select count(*) num from swg_characters + where (station_id = p_station_id + OR station_id IN (SELECT CASE WHEN child_id = p_station_id THEN parent_id + ELSE child_id END as station_id FROM account_map WHERE parent_id = p_station_id + OR child_id = p_station_id)) and enabled ='Y') account_counter, + default_char_limits, + cluster_list + where + cluster_list.id = p_cluster_id; + + if (over_account_limit <= 0 or over_cluster_limit <= 0) then + open result_cursor for + select 0 character_type_id, 0 remaining_slots + from dual + where 1=2; + + return result_cursor; + end if; + + -- if not, return the number of each type of character we're allowed to create + + open result_cursor for + select limits.character_type_id, limits.limit - nvl(existing.num,0) remaining_slots + from + (select def.character_type_id, def.num_slots + nvl(cls.num_extra_slots,0) limit + from extra_character_slots cls, default_character_slots def + where def.character_type_id = cls.character_type_id (+) + and cls.station_id (+) = p_station_id + and cls.cluster_id (+) = p_cluster_id) limits, + + (select character_type, count(*) num + from swg_characters + where station_id = p_station_id + and cluster_id = p_cluster_id + and enabled = 'Y' + group by character_type) existing + where + limits.character_type_id = existing.character_type (+); + + return result_cursor; + end; + + -- unlike get_open_character_slots, this function ignores account and cluster limits + function get_only_open_character_slots(p_station_id number, p_cluster_id number) return refcursor + as + result_cursor refcursor; + begin + -- return the number of each type of character we're allowed to create + + open result_cursor for + select limits.character_type_id, limits.limit - nvl(existing.num,0) remaining_slots + from + (select def.character_type_id, def.num_slots + nvl(cls.num_extra_slots,0) limit + from extra_character_slots cls, default_character_slots def + where def.character_type_id = cls.character_type_id (+) + and cls.station_id (+) = p_station_id + and cls.cluster_id (+) = p_cluster_id) limits, + + (select character_type, count(*) num + from swg_characters + where station_id = p_station_id + and cluster_id = p_cluster_id + and enabled = 'Y' + group by character_type) existing + where + limits.character_type_id = existing.character_type (+); + + return result_cursor; + end; + + function is_cluster_at_limit(p_cluster_id number) return number + as + v_cluster_limit number; + v_num_characters number; + begin + select cluster_limit + into v_cluster_limit + from default_char_limits; + + select num_characters + into v_num_characters + from cluster_list + where id = p_cluster_id; + + if (v_num_characters >= v_cluster_limit) then + return 1; + else + return 0; + end if; + + exception + when others then + return 0; + end; + + function is_account_at_limit(p_station_id number) return number + as + v_account_limit number; + v_num_characters number; + begin + select account_limit + into v_account_limit + from default_char_limits; + + select count(*) + into v_num_characters + from swg_characters + where station_id = p_station_id and enabled ='Y' and cluster_id not in (select id from cluster_list where name in ('Corbantis', 'Europe-Infinity', 'Intrepid', 'Kauri', 'Kettemoor', 'Lowca', 'Naritus', 'Scylla', 'Tarquinas', 'Tempest', 'Valcyn', 'Wanderhome', 'Japan-Katana', 'Japan-Harla')); + + if (v_num_characters >= v_account_limit) then + return 1; + else + return 0; + end if; + + exception + when others then + return 0; + end; + + procedure delete_character(p_cluster_id number, p_character_id number, p_station_id number) + as + begin + delete from swg_characters + where station_id = p_station_id + and cluster_id = p_cluster_id + and object_id = p_character_id; + + update cluster_list + set num_characters = num_characters - 1 + where cluster_list.id = p_cluster_id; + + end; + + procedure rename_character(p_cluster_id number, p_character_id number, p_new_name varchar2) + as + begin + update swg_characters + set character_name = p_new_name + where cluster_id = p_cluster_id + and object_id = p_character_id; + end; + + procedure create_character(p_cluster_id number, p_station_id number, p_character_name varchar2, p_character_id number, p_template_id number, p_character_type number) + as + begin + insert into swg_characters (station_id, cluster_id, character_name, object_id, template_id, character_type) + values (p_station_id, p_cluster_id, p_character_name, p_character_id, p_template_id, p_character_type); + + update cluster_list + set num_characters = nvl(num_characters,0) + 1 + where cluster_list.id = p_cluster_id; + + exception when DUP_VAL_ON_INDEX then + update swg_characters + set object_id = p_character_id, + template_id = p_template_id, + character_type = p_character_type + where cluster_id = p_cluster_id + and station_id = p_station_id + and character_name = p_character_name; + end; + + function restore_character(p_cluster_id number, p_station_id number, p_character_name varchar2, p_character_id number, p_template_id number, p_character_type number) return number + -- Return codes: + -- 1: restored + -- 2: restored, but too many characters on the account now + -- 3: database error + as + l_num_characters number; + l_limit number; + begin + begin + insert into swg_characters (station_id, cluster_id, character_name, object_id, template_id, character_type) + values (p_station_id, p_cluster_id, p_character_name, p_character_id, p_template_id, p_character_type); + + update cluster_list + set num_characters = nvl(num_characters,0) + 1 + where cluster_list.id = p_cluster_id; + + exception when DUP_VAL_ON_INDEX then + null; -- already restored + when others then + return 3; + end; + + -- Check the account against the limits + select count(*) + into l_num_characters + from swg_characters + where station_id = p_station_id + and character_type = p_character_type + and enabled = 'Y' + and cluster_id not in (select id from cluster_list where name in ('Corbantis', 'Europe-Infinity', 'Intrepid', 'Kauri', 'Kettemoor', 'Lowca', 'Naritus', 'Scylla', 'Tarquinas', 'Tempest', 'Valcyn', 'Wanderhome', 'Japan-Katana', 'Japan-Harla')); + + select def.num_slots + nvl(cls.num_extra_slots,0) + into l_limit + from extra_character_slots cls, default_character_slots def + where def.character_type_id = cls.character_type_id (+) + and cls.station_id (+) = p_station_id + and cls.cluster_id (+) = p_cluster_id + and def.character_type_id = p_character_type; + + if (l_num_characters > l_limit) then + return 2; + else + return 1; + end if; + + exception + when others then + return 3; + end; + + procedure set_character_slots(p_cluster_id number, p_station_id number, p_slot_type number, p_num_slots number) + as + begin + update extra_character_slots + set num_extra_slots = p_num_slots + where cluster_id = p_cluster_id + and station_id = p_station_id + and character_type_id = p_slot_type; + + if (sql%rowcount = 0) then + insert into extra_character_slots (station_id, cluster_id, character_type_id, num_extra_slots) + values (p_station_id, p_cluster_id, p_slot_type, p_num_slots); + end if; + end; + + procedure set_character_type(p_cluster_id number, p_station_id number, p_character_id number, p_slot_type number) + as + begin + update swg_characters + set character_type = p_slot_type + where station_id = p_station_id + and cluster_id = p_cluster_id + and object_id = p_character_id; + end; + + function has_extra_character_slot(p_station_id number, p_character_type number) return number + as + rows number; + total number; + begin + select count(*), sum(num_extra_slots) + into rows, total + from extra_character_slots + where station_id = p_station_id + and character_type_id = p_character_type; + + if (rows <= 0 or total < 0) then + total := 0; + end if; + + return total; + exception + when others then + return 0; + end; + + procedure toggle_disable_character(p_cluster_id number, p_character_id number, p_station_id number, p_enabled varchar2) + as + begin + update swg_characters + set enabled = p_enabled + where station_id = p_station_id + and cluster_id = p_cluster_id + and object_id = p_character_id; + + end; + + function enable_disable_character(p_station_id number, p_character_id number, p_enabled varchar2) return number + as + begin + update swg_characters + set enabled = p_enabled + where station_id = p_station_id and + object_id = p_character_id; + if (sql%rowcount > 0) then + return 1; + else + return 2; + end if; + exception + when others then + return 3; + end; + + function get_completed_tutorial(p_station_id number) return refcursor + as + cnt number; + result_cursor refcursor; + begin + select count (*) into cnt + from account_info + where station_id = p_station_id; + + if (cnt = 0) then + insert into account_info (station_id, completed_tutorial) + values (p_station_id, 'N'); + end if; + + open result_cursor for + select completed_tutorial + from account_info + where station_id = p_station_id; + + return result_cursor; + end; + + procedure toggle_completed_tutorial(p_station_id number, p_completed varchar2) + as + begin + update account_info + set completed_tutorial = p_completed + where station_id = p_station_id; + end; + + function get_consumed_reward_events(p_station_id number) return refcursor + as + result_cursor refcursor; + begin + open result_cursor for + select event_id, cluster_id, character_id + from account_reward_events + where station_id = p_station_id; + + return result_cursor; + end; + + function get_claimed_reward_items(p_station_id number) return refcursor + as + result_cursor refcursor; + begin + open result_cursor for + select item_id, cluster_id, character_id + from account_reward_items + where station_id = p_station_id; + + return result_cursor; + end; + + function consume_reward_event(p_station_id number, p_character_id number, p_cluster_id number, p_event_id varchar2) return number + as + begin + insert into account_reward_events (station_id, event_id, date_consumed, cluster_id, character_id) + values (p_station_id, p_event_id, sysdate, p_cluster_id, p_character_id); + + return 1; + + exception + when dup_val_on_index then + -- Check whether previous claim was from the same character and cluster, if so, allow it + declare + previous_claim_cluster number; + previous_claim_character number; + begin + select cluster_id, character_id + into previous_claim_cluster, previous_claim_character + from account_reward_events + where station_id = p_station_id + and event_id = p_event_id; + + if ((p_cluster_id=previous_claim_cluster) and (p_character_id=previous_claim_character)) then + return 1; + end if; + + return 0; + end; + when others then + return 0; + end; + + function claim_reward_item(p_station_id number, p_character_id number, p_cluster_id number, p_item_id varchar2) return number + as + begin + insert into account_reward_items (station_id, item_id, date_claimed, cluster_id, character_id) + values (p_station_id, p_item_id, sysdate, p_cluster_id, p_character_id); + + return 1; + + exception + when dup_val_on_index then + -- Check whether previous claim was from the same character and cluster, if so, allow it + declare + previous_claim_cluster number; + previous_claim_character number; + begin + select cluster_id, character_id + into previous_claim_cluster, previous_claim_character + from account_reward_items + where station_id = p_station_id + and item_id = p_item_id; + + if ((p_cluster_id=previous_claim_cluster) and (p_character_id=previous_claim_character)) then + return 1; + end if; + + return 0; + exception + when others then + return 0; + end; + when others then + return 0; + end; + + function get_feature_id_transactions(p_station_id in number, p_cluster_id in number, p_character_id in number) return refcursor + as + result_cursor refcursor; + begin + open result_cursor for + select item_id, count + from feature_id_transactions + where station_id = p_station_id and cluster_id = p_cluster_id and character_id = p_character_id; + + return result_cursor; + end; + + function update_feature_id_transaction(p_station_id in number, p_cluster_id in number, p_character_id in number, p_item_id in varchar2, p_count_adjustment in number) return number + as + begin + update feature_id_transactions set date_updated = sysdate, + count = count + p_count_adjustment + where station_id = p_station_id + and cluster_id = p_cluster_id + and character_id = p_character_id + and item_id = p_item_id; + + if (sql%rowcount = 0) then + insert into feature_id_transactions (station_id, cluster_id, character_id, item_id, date_updated, count) + values (p_station_id, p_cluster_id, p_character_id, p_item_id, sysdate, p_count_adjustment); + end if; + + return 1; + + exception + when others then + return 0; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."LOGIN" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body OBJECTIDMANAGER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."OBJECTIDMANAGER" +as + + procedure get_ids(how_many in out number, block_start_id out number, block_end_id out number) + as + result_cursor cursortype; + begin + delete free_object_ids + where end_id is not null + and rownum=1 + returning start_id, end_id + into block_start_id, block_end_id; + + if (sql%rowcount = 0) then + update free_object_ids + set start_id = start_id + how_many + where end_id is null + returning start_id - how_many, start_id - 1 + into block_start_id, block_end_id; + end if; + + how_many := block_end_id - block_start_id + 1; + end; + + -- same as get_ids, except guarantees the ids are all contiguous + -- (therefore it can return just the starting id) + function get_contiguous_ids(min_count number) return number + as + result_cursor cursortype; + block_start_id number; + block_end_id number; + begin + update free_object_ids + set start_id = start_id + min_count + where (end_id - start_id + 1 >= min_count + or end_id is null) + and rownum < 2 + returning start_id - min_count, start_id - 1 + into block_start_id, block_end_id; + + if (block_start_id > block_end_id) then -- entire block was consumed + delete free_object_ids where start_id = block_start_id; + end if; + + return block_start_id; + end; + + -- get only one id + function get_single_id return number + as + block_start_id number; + block_end_id number; + begin + update + free_object_ids + set + start_id = start_id + 1 + where + rownum=1 + returning + start_id, + end_id + into + block_start_id, + block_end_id; + + if (block_start_id > block_end_id) then -- entire block was consumed + delete free_object_ids where start_id = block_start_id; + end if; + + return block_start_id - 1; + end; + + procedure rebuild_freelist + as + message_count number; + message_id_block number; + begin + delete free_object_ids; + + -- following is not legal in PL/SQL, so it must be "execute immediated" + execute immediate 'insert into free_object_ids (end_id, start_id) '|| + 'select o1.object_id-1 end_id, (select max(o2.object_id) from objects o2 where o1.object_id > o2.object_id)+1 start_id ' || + 'from objects o1 ' || + 'where o1.object_id > (select max(o2.object_id)+1 from objects o2 where o1.object_id > o2.object_id)'; + + insert into free_object_ids (start_id, end_id) + select * from + (select 1,min(object_id)-1 + from objects) + where not exists (select * from objects where object_id = 1); + + insert into free_object_ids (start_id, end_id) + select * from + (select max(object_id)+1,NULL + from objects) + where exists (select * from objects); + + --easier to ignore messages while finding free object ids and then fix them up at the end: + + select count(*) + into message_count + from messages + where rownum = 1; + + if (message_count <> 0) then + message_id_block := get_contiguous_ids(message_count); + + update messages + set message_id = rownum + message_id_block - 1; + end if; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."OBJECTIDMANAGER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body OBJVAR_NAMES +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."OBJVAR_NAMES" +as + procedure add_name (p_id number, p_name varchar2) as + begin + insert into object_variable_names (id,name) + values (p_id, p_name); + end; + + function get_name_list return cursortype as + result_cursor cursortype; + begin + open result_cursor for + select id, name from object_variable_names; + + return result_cursor; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."OBJVAR_NAMES" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body PERSISTER +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."PERSISTER" +as + + procedure set_clock (p_time number) + as + begin + update clock set last_save_time = p_time, last_save_timestamp = sysdate; + end; + + procedure add_player (p_station_id number, p_character_object objectid, p_character_name varchar2, p_normalized_name varchar2) + as + rc number; + begin + insert into players (station_id, character_object,uc_character_name, character_full_name, create_time) + values (p_station_id, p_character_object, p_normalized_name, p_character_name, sysdate); + end; + + function delete_character (p_station_id number, p_character_id number, p_delete_minutes number) return number + as + valid_check number; + l_deleted_name number; + begin + l_deleted_name := 0; + + select count(*) + into valid_check + from players + where players.character_object = p_character_id + and players.station_id = p_station_id; + + if (valid_check = 1) then + + -- recursive query needed in order to get bank box contents, etc. + update objects + set + deleted = (select reason_code from delete_reasons where tag='CharacterDeleted'), + deleted_date = sysdate + where object_id in (select object_id + from objects + where deleted = 0 + start with load_with = p_character_id + connect by prior object_id = load_with and prior load_with <> load_with); + + -- remove character record if the character is new enough (so that players can experiment creating new characters + -- and deleting them right away) + delete players + where players.character_object = p_character_id + and players.station_id = p_station_id + and (sysdate - create_time) * (1440) < p_delete_minutes; + + if (sql%rowcount > 0) then + l_deleted_name := 1; + end if; + + -- Add a message for all deleted buildings owned by this character. The game will delete the buildings + -- and run appropriate cleanup the next time the buildings are loaded. + + for oid in (select o.object_id from objects o, tangible_objects t, building_objects b + where o.object_id = t.object_id + and o.object_id = b.object_id + and t.object_id = b.object_id + and t.owner_id = p_character_id + and o.deleted = 0) + loop + save_message (objectidmanager.get_single_id(), oid.object_id, 'msgDestroyStructure',NULL,0,'Y',1); + end loop; + + for oid1 in (select o.object_id from objects o, tangible_objects t, installation_objects b + where o.object_id = t.object_id + and o.object_id = b.object_id + and t.owner_id = p_character_id + and o.deleted = 0) + loop + save_message (objectidmanager.get_single_id(), oid1.object_id, 'msgDestroyStructure',NULL,0,'Y',1); + end loop; + + if (l_deleted_name=0) then + return 0; + else + return 2; + end if; + else + return 1; + end if; + end; + + + procedure update_object_variable_batch (p_object_id vaofstring, p_name_id VAOFNUMBER, p_type VAOFNUMBER, p_value VAOFSTRING, p_chunk_size number) + as + begin + FORALL i in 1..p_chunk_size + UPDATE OBJECT_VARIABLES Set + type = p_type(i), + value = p_value(i), + detached = 0 + WHERE + object_id = p_object_id(i) and + name_id = p_name_id(i); + end; + + procedure add_object_variable_batch (p_object_id vaofstring, p_name_id VAOFNUMBER, p_type VAOFNUMBER, p_value VAOFSTRING, p_chunk_size number) + as + errors number; + error_index number; + begin + FORALL i in 1..p_chunk_size + INSERT into OBJECT_VARIABLES ( + object_id, + name_id, + type, + value, + detached ) + VALUES ( + p_object_id(i), + p_name_id(i), + p_type(i), + p_value(i), + 0 ); + + exception + when DUP_VAL_ON_INDEX then + for i in 1..p_chunk_size loop + UPDATE OBJECT_VARIABLES Set + type = p_type(i), + value = p_value(i), + detached = 0 + WHERE + object_id = p_object_id(i) and + name_id = p_name_id(i); + + if SQL%ROWCOUNT=0 then + INSERT into OBJECT_VARIABLES ( + object_id, + name_id, + type, + value, + detached ) + VALUES ( + p_object_id(i), + p_name_id(i), + p_type(i), + p_value(i), + 0 ); + end if; + end loop; + end; + + procedure remove_object_variable_batch (p_object_id vaofstring, p_name_id VAOFNUMBER, p_chunk_size number) + as + begin + FORALL i in 1..p_chunk_size + delete from object_variables + where object_id = p_object_id(i) + and name_id = p_name_id(i); + end; + + procedure clear_scripts (p_object_id objectid) + as + begin + delete from scripts + where object_id = p_object_id; + end; + + procedure save_message (p_message_id number, p_object_id objectid, p_method varchar, p_data varchar, p_call_time number, p_guaranteed varchar, p_delivery_type int) + as + begin + insert into messages (message_id, target, method, data, call_time, guaranteed, delivery_type) + values (p_message_id, p_object_id, p_method, p_data, p_call_time, p_guaranteed, p_delivery_type); + end; + + procedure save_message_batch (p_message_id VAOFSTRING, p_object_id VAOFSTRING, p_method VAOFSTRING, p_data VAOFLONGSTRING, p_call_time VAOFNUMBER, p_guaranteed VAOFSTRING, p_delivery_type VAOFNUMBER, p_chunk_size number, p_enable_db_logging number ) + as + begin + + forall i in 1..p_chunk_size + insert into messages (message_id, target, method, data, call_time, guaranteed, delivery_type) + values (p_message_id(i), p_object_id(i), p_method(i), p_data(i), p_call_time(i), p_guaranteed(i), p_delivery_type(i)); + + exception when dup_val_on_index then + for i in 1..p_chunk_size loop + begin + insert into messages (message_id, target, method, data, call_time, guaranteed, delivery_type) + values (p_message_id(i), p_object_id(i), p_method(i), p_data(i), p_call_time(i), p_guaranteed(i), p_delivery_type(i)); + exception when dup_val_on_index then + if ( p_enable_db_logging > 0 ) then + + db_error_logger.dblogerror( SQLCODE, 'procedure save_message_batch: duplicate rows were sent to the message buffer that resulted in a dup_val_on_index error.'); + if ( p_enable_db_logging > 1 ) then + + db_error_logger.dblogerror_values( 'messages', 'message_id' , 'number', p_message_id(i)); + db_error_logger.dblogerror_values( 'messages', 'target' , 'number', p_object_id(i)); + db_error_logger.dblogerror_values( 'messages', 'method' , 'varchar2', p_method(i)); + db_error_logger.dblogerror_values( 'messages', 'data' , 'varchar2', p_data(i)); + db_error_logger.dblogerror_values( 'messages', 'call_time' , 'number', to_char(p_call_time(i))); + db_error_logger.dblogerror_values( 'messages', 'guaranteed' , 'varchar2', p_guaranteed(i)); + db_error_logger.dblogerror_values( 'messages', 'delivery_type' , 'number', to_char(p_delivery_type(i))); + + end if; + + else + NULL; + end if; + end; + end loop; + end; + + + procedure acknowledge_message(p_message_id number) + as + begin + delete from messages + where message_id = p_message_id; + end; + + procedure acknowledge_message_batch (p_message_id VAOFSTRING, p_chunk_size number, p_enable_db_logging number) + as + begin + + forall i in 1..p_chunk_size + delete from messages + where message_id = p_message_id(i); + + exception when dup_val_on_index then + for i in 1..p_chunk_size loop + begin + delete from messages + where message_id = p_message_id(i); + exception when dup_val_on_index then + if ( p_enable_db_logging > 0 ) then + + db_error_logger.dblogerror( SQLCODE, 'procedure acknowledge_message_batch: duplicate rows were sent to the message buffer that resulted in a dup_val_on_index error.'); + if ( p_enable_db_logging > 1 ) then + + db_error_logger.dblogerror_values( 'messages', 'message_id' , 'number', p_message_id(i)); + + end if; + + else + NULL; + end if; + end; + end loop; + + + end; + + procedure save_object ( p_x VAOFNUMBER, p_y VAOFNUMBER, p_z VAOFNUMBER, p_quaternion_w VAOFNUMBER, p_quaternion_x VAOFNUMBER, p_quaternion_y VAOFNUMBER, p_quaternion_z VAOFNUMBER, p_node_x VAOFNUMBER, p_node_y VAOFNUMBER, p_node_z VAOFNUMBER, p_object_template_id VAOFNUMBER, p_type_id VAOFNUMBER, p_scene_id VAOFSTRING, p_controller_type VAOFNUMBER, p_deleted VAOFNUMBER, p_object_name VAOFSTRING, p_volume VAOFNUMBER, p_contained_by VAOFSTRING, p_slot_arrangement VAOFNUMBER, p_player_controlled VAOFSTRING, p_cache_version VAOFNUMBER, p_load_contents VAOFSTRING, p_cash_balance VAOFNUMBER, p_bank_balance VAOFNUMBER, p_complexity VAOFNUMBER, p_name_string_table VAOFSTRING, p_name_string_text VAOFSTRING, p_static_item_name VAOFSTRING, p_static_item_version VAOFNUMBER, p_conversion_id VAOFNUMBER, p_load_with VAOFSTRING, + p_objvar_0_name VAOFSTRING,p_objvar_0_type VAOFNUMBER,p_objvar_0_value VAOFSTRING,p_objvar_1_name VAOFSTRING,p_objvar_1_type VAOFNUMBER,p_objvar_1_value VAOFSTRING,p_objvar_2_name VAOFSTRING,p_objvar_2_type VAOFNUMBER,p_objvar_2_value VAOFSTRING,p_objvar_3_name VAOFSTRING,p_objvar_3_type VAOFNUMBER,p_objvar_3_value VAOFSTRING,p_objvar_4_name VAOFSTRING,p_objvar_4_type VAOFNUMBER,p_objvar_4_value VAOFSTRING,p_objvar_5_name VAOFSTRING,p_objvar_5_type VAOFNUMBER,p_objvar_5_value VAOFSTRING,p_objvar_6_name VAOFSTRING,p_objvar_6_type VAOFNUMBER,p_objvar_6_value VAOFSTRING,p_objvar_7_name VAOFSTRING,p_objvar_7_type VAOFNUMBER,p_objvar_7_value VAOFSTRING,p_objvar_8_name VAOFSTRING,p_objvar_8_type VAOFNUMBER,p_objvar_8_value VAOFSTRING,p_objvar_9_name VAOFSTRING,p_objvar_9_type VAOFNUMBER,p_objvar_9_value VAOFSTRING, p_objvar_10_name VAOFSTRING,p_objvar_10_type VAOFNUMBER,p_objvar_10_value VAOFSTRING,p_objvar_11_name VAOFSTRING,p_objvar_11_type VAOFNUMBER,p_objvar_11_value VAOFSTRING,p_objvar_12_name VAOFSTRING,p_objvar_12_type VAOFNUMBER,p_objvar_12_value VAOFSTRING,p_objvar_13_name VAOFSTRING,p_objvar_13_type VAOFNUMBER,p_objvar_13_value VAOFSTRING,p_objvar_14_name VAOFSTRING,p_objvar_14_type VAOFNUMBER,p_objvar_14_value VAOFSTRING,p_objvar_15_name VAOFSTRING,p_objvar_15_type VAOFNUMBER,p_objvar_15_value VAOFSTRING,p_objvar_16_name VAOFSTRING,p_objvar_16_type VAOFNUMBER,p_objvar_16_value VAOFSTRING,p_objvar_17_name VAOFSTRING,p_objvar_17_type VAOFNUMBER,p_objvar_17_value VAOFSTRING,p_objvar_18_name VAOFSTRING,p_objvar_18_type VAOFNUMBER,p_objvar_18_value VAOFSTRING,p_objvar_19_name VAOFSTRING,p_objvar_19_type VAOFNUMBER,p_objvar_19_value VAOFSTRING, p_script_list VAOFLONGSTRING, p_object_id VAOFSTRING, p_chunk_size number) + as + cache_update VAOFNUMBER; + begin + + cache_update := VAOFNUMBER(); -- initialize VARRAY object + cache_update.extend(p_chunk_size); -- allocate VARRAY object memory to chunk size + + -- create cache_update array for use in bulk update + FOR i IN 1..p_chunk_size + LOOP + if + ((p_x(i) is not null) + or (p_y(i) is not null) + or (p_z(i) is not null) + or (p_quaternion_w(i) is not null) + or (p_quaternion_x(i) is not null) + or (p_quaternion_y(i) is not null) + or (p_quaternion_z(i) is not null) + or (p_contained_by(i) is not null) + or (p_cache_version(i) is not null)) + then + cache_update(i) := 0; + else + cache_update(i) := NULL; + end if; + END LOOP; + + + -- process deletes + FORALL i IN 1..p_chunk_size + update objects set + deleted = p_deleted(i), + deleted_date = sysdate, + load_with = NULL + where object_id = p_object_id(i) and + p_deleted(i) <> 0; + + -- process updates + FORALL i IN 1..p_chunk_size + update objects set + x = nvl(p_x(i),x), + y = nvl(p_y(i),y), + z = nvl(p_z(i),z), + quaternion_w = nvl(p_quaternion_w(i),quaternion_w), + quaternion_x = nvl(p_quaternion_x(i),quaternion_x), + quaternion_y = nvl(p_quaternion_y(i),quaternion_y), + quaternion_z = nvl(p_quaternion_z(i),quaternion_z), + node_x = nvl(p_node_x(i),node_x), + node_y = nvl(p_node_y(i),node_y), + node_z = nvl(p_node_z(i),node_z), + object_template_id = nvl(p_object_template_id(i),object_template_id), + type_id = nvl(p_type_id(i),type_id), + scene_id = nvl(p_scene_id(i),scene_id), + controller_type = nvl(p_controller_type(i),controller_type), + deleted = nvl(p_deleted(i),deleted), + object_name = nvl(p_object_name(i),object_name), + volume = nvl(p_volume(i),volume), + contained_by = nvl(p_contained_by(i),contained_by), + slot_arrangement = nvl(p_slot_arrangement(i),slot_arrangement), + player_controlled = nvl(p_player_controlled(i),player_controlled), + cache_version = nvl(cache_update(i),cache_version), + load_contents = nvl(p_load_contents(i),load_contents), + cash_balance = nvl(p_cash_balance(i),cash_balance), + bank_balance = nvl(p_bank_balance(i),bank_balance), + complexity = nvl(p_complexity(i),complexity), + name_string_table = nvl(p_name_string_table(i),name_string_table), + name_string_text = nvl(p_name_string_text(i),name_string_text), + static_item_name = nvl(p_static_item_name(i),static_item_name), + static_item_version = nvl(p_static_item_version(i),static_item_version), + conversion_id = nvl(p_conversion_id(i),conversion_id), + load_with = nvl(p_load_with(i),load_with), + + objvar_0_name = nvl(p_objvar_0_name(i), objvar_0_name), + objvar_0_type = nvl(p_objvar_0_type(i), objvar_0_type), + objvar_0_value= nvl(p_objvar_0_value(i),objvar_0_value), + objvar_1_name = nvl(p_objvar_1_name(i), objvar_1_name), + objvar_1_type = nvl(p_objvar_1_type(i), objvar_1_type), + objvar_1_value= nvl(p_objvar_1_value(i),objvar_1_value), + objvar_2_name = nvl(p_objvar_2_name(i), objvar_2_name), + objvar_2_type = nvl(p_objvar_2_type(i), objvar_2_type), + objvar_2_value= nvl(p_objvar_2_value(i),objvar_2_value), + objvar_3_name = nvl(p_objvar_3_name(i), objvar_3_name), + objvar_3_type = nvl(p_objvar_3_type(i), objvar_3_type), + objvar_3_value= nvl(p_objvar_3_value(i),objvar_3_value), + objvar_4_name = nvl(p_objvar_4_name(i), objvar_4_name), + objvar_4_type = nvl(p_objvar_4_type(i), objvar_4_type), + objvar_4_value= nvl(p_objvar_4_value(i),objvar_4_value), + objvar_5_name = nvl(p_objvar_5_name(i), objvar_5_name), + objvar_5_type = nvl(p_objvar_5_type(i), objvar_5_type), + objvar_5_value= nvl(p_objvar_5_value(i),objvar_5_value), + objvar_6_name = nvl(p_objvar_6_name(i), objvar_6_name), + objvar_6_type = nvl(p_objvar_6_type(i), objvar_6_type), + objvar_6_value= nvl(p_objvar_6_value(i),objvar_6_value), + objvar_7_name = nvl(p_objvar_7_name(i), objvar_7_name), + objvar_7_type = nvl(p_objvar_7_type(i), objvar_7_type), + objvar_7_value= nvl(p_objvar_7_value(i),objvar_7_value), + objvar_8_name = nvl(p_objvar_8_name(i), objvar_8_name), + objvar_8_type = nvl(p_objvar_8_type(i), objvar_8_type), + objvar_8_value= nvl(p_objvar_8_value(i),objvar_8_value), + objvar_9_name = nvl(p_objvar_9_name(i), objvar_9_name), + objvar_9_type = nvl(p_objvar_9_type(i), objvar_9_type), + objvar_9_value= nvl(p_objvar_9_value(i),objvar_9_value), + + objvar_10_name = nvl(p_objvar_10_name(i), objvar_10_name), + objvar_10_type = nvl(p_objvar_10_type(i), objvar_10_type), + objvar_10_value= nvl(p_objvar_10_value(i),objvar_10_value), + objvar_11_name = nvl(p_objvar_11_name(i), objvar_11_name), + objvar_11_type = nvl(p_objvar_11_type(i), objvar_11_type), + objvar_11_value= nvl(p_objvar_11_value(i),objvar_11_value), + objvar_12_name = nvl(p_objvar_12_name(i), objvar_12_name), + objvar_12_type = nvl(p_objvar_12_type(i), objvar_12_type), + objvar_12_value= nvl(p_objvar_12_value(i),objvar_12_value), + objvar_13_name = nvl(p_objvar_13_name(i), objvar_13_name), + objvar_13_type = nvl(p_objvar_13_type(i), objvar_13_type), + objvar_13_value= nvl(p_objvar_13_value(i),objvar_13_value), + objvar_14_name = nvl(p_objvar_14_name(i), objvar_14_name), + objvar_14_type = nvl(p_objvar_14_type(i), objvar_14_type), + objvar_14_value= nvl(p_objvar_14_value(i),objvar_14_value), + objvar_15_name = nvl(p_objvar_15_name(i), objvar_15_name), + objvar_15_type = nvl(p_objvar_15_type(i), objvar_15_type), + objvar_15_value= nvl(p_objvar_15_value(i),objvar_15_value), + objvar_16_name = nvl(p_objvar_16_name(i), objvar_16_name), + objvar_16_type = nvl(p_objvar_16_type(i), objvar_16_type), + objvar_16_value= nvl(p_objvar_16_value(i),objvar_16_value), + objvar_17_name = nvl(p_objvar_17_name(i), objvar_17_name), + objvar_17_type = nvl(p_objvar_17_type(i), objvar_17_type), + objvar_17_value= nvl(p_objvar_17_value(i),objvar_17_value), + objvar_18_name = nvl(p_objvar_18_name(i), objvar_18_name), + objvar_18_type = nvl(p_objvar_18_type(i), objvar_18_type), + objvar_18_value= nvl(p_objvar_18_value(i),objvar_18_value), + objvar_19_name = nvl(p_objvar_19_name(i), objvar_19_name), + objvar_19_type = nvl(p_objvar_19_type(i), objvar_19_type), + objvar_19_value= nvl(p_objvar_19_value(i),objvar_19_value), + + script_list = nvl(p_script_list(i),script_list) + where + object_id=p_object_id(i) and + (p_deleted(i) = 0 or p_deleted(i) is null); + + cache_update.delete; -- cleanup - delete VARRAY list + + end; + + procedure add_object ( p_x VAOFNUMBER, p_y VAOFNUMBER, p_z VAOFNUMBER, p_quaternion_w VAOFNUMBER, p_quaternion_x VAOFNUMBER, p_quaternion_y VAOFNUMBER, p_quaternion_z VAOFNUMBER, p_node_x VAOFNUMBER, p_node_y VAOFNUMBER, p_node_z VAOFNUMBER, p_object_template_id VAOFNUMBER, p_type_id VAOFNUMBER, p_scene_id VAOFSTRING, p_controller_type VAOFNUMBER, p_deleted VAOFNUMBER, p_object_name VAOFSTRING, p_volume VAOFNUMBER, p_contained_by VAOFSTRING, p_slot_arrangement VAOFNUMBER, p_player_controlled VAOFSTRING, p_cache_version VAOFNUMBER, p_load_contents VAOFSTRING, p_cash_balance VAOFNUMBER, p_bank_balance VAOFNUMBER, p_complexity VAOFNUMBER, p_name_string_table VAOFSTRING, p_name_string_text VAOFSTRING, p_static_item_name VAOFSTRING, p_static_item_version VAOFNUMBER, p_conversion_id VAOFNUMBER, p_load_with VAOFSTRING, + p_objvar_0_name VAOFSTRING,p_objvar_0_type VAOFNUMBER,p_objvar_0_value VAOFSTRING,p_objvar_1_name VAOFSTRING,p_objvar_1_type VAOFNUMBER,p_objvar_1_value VAOFSTRING,p_objvar_2_name VAOFSTRING,p_objvar_2_type VAOFNUMBER,p_objvar_2_value VAOFSTRING,p_objvar_3_name VAOFSTRING,p_objvar_3_type VAOFNUMBER,p_objvar_3_value VAOFSTRING,p_objvar_4_name VAOFSTRING,p_objvar_4_type VAOFNUMBER,p_objvar_4_value VAOFSTRING,p_objvar_5_name VAOFSTRING,p_objvar_5_type VAOFNUMBER,p_objvar_5_value VAOFSTRING,p_objvar_6_name VAOFSTRING,p_objvar_6_type VAOFNUMBER,p_objvar_6_value VAOFSTRING,p_objvar_7_name VAOFSTRING,p_objvar_7_type VAOFNUMBER,p_objvar_7_value VAOFSTRING,p_objvar_8_name VAOFSTRING,p_objvar_8_type VAOFNUMBER,p_objvar_8_value VAOFSTRING,p_objvar_9_name VAOFSTRING,p_objvar_9_type VAOFNUMBER,p_objvar_9_value VAOFSTRING, p_objvar_10_name VAOFSTRING,p_objvar_10_type VAOFNUMBER,p_objvar_10_value VAOFSTRING,p_objvar_11_name VAOFSTRING,p_objvar_11_type VAOFNUMBER,p_objvar_11_value VAOFSTRING,p_objvar_12_name VAOFSTRING,p_objvar_12_type VAOFNUMBER,p_objvar_12_value VAOFSTRING,p_objvar_13_name VAOFSTRING,p_objvar_13_type VAOFNUMBER,p_objvar_13_value VAOFSTRING,p_objvar_14_name VAOFSTRING,p_objvar_14_type VAOFNUMBER,p_objvar_14_value VAOFSTRING,p_objvar_15_name VAOFSTRING,p_objvar_15_type VAOFNUMBER,p_objvar_15_value VAOFSTRING,p_objvar_16_name VAOFSTRING,p_objvar_16_type VAOFNUMBER,p_objvar_16_value VAOFSTRING,p_objvar_17_name VAOFSTRING,p_objvar_17_type VAOFNUMBER,p_objvar_17_value VAOFSTRING,p_objvar_18_name VAOFSTRING,p_objvar_18_type VAOFNUMBER,p_objvar_18_value VAOFSTRING,p_objvar_19_name VAOFSTRING,p_objvar_19_type VAOFNUMBER,p_objvar_19_value VAOFSTRING, p_script_list VAOFLONGSTRING, p_object_id VAOFSTRING, p_chunk_size number) + as + + p_cache_update NUMBER; + + begin + FORALL i IN 1..p_chunk_size + insert into objects + ( + x, + y, + z, + quaternion_w, + quaternion_x, + quaternion_y, + quaternion_z, + node_x, + node_y, + node_z, + object_template_id, + type_id, + scene_id, + controller_type, + deleted, + object_name, + volume, + contained_by, + slot_arrangement, + player_controlled, + cache_version, + load_contents, + cash_balance, + bank_balance, + complexity, + name_string_table, + name_string_text, + static_item_name, + static_item_version, + conversion_id, + load_with, + + objvar_0_name, + objvar_0_type, + objvar_0_value, + objvar_1_name, + objvar_1_type, + objvar_1_value, + objvar_2_name, + objvar_2_type, + objvar_2_value, + objvar_3_name, + objvar_3_type, + objvar_3_value, + objvar_4_name, + objvar_4_type, + objvar_4_value, + objvar_5_name, + objvar_5_type, + objvar_5_value, + objvar_6_name, + objvar_6_type, + objvar_6_value, + objvar_7_name, + objvar_7_type, + objvar_7_value, + objvar_8_name, + objvar_8_type, + objvar_8_value, + objvar_9_name, + objvar_9_type, + objvar_9_value, + + objvar_10_name, + objvar_10_type, + objvar_10_value, + objvar_11_name, + objvar_11_type, + objvar_11_value, + objvar_12_name, + objvar_12_type, + objvar_12_value, + objvar_13_name, + objvar_13_type, + objvar_13_value, + objvar_14_name, + objvar_14_type, + objvar_14_value, + objvar_15_name, + objvar_15_type, + objvar_15_value, + objvar_16_name, + objvar_16_type, + objvar_16_value, + objvar_17_name, + objvar_17_type, + objvar_17_value, + objvar_18_name, + objvar_18_type, + objvar_18_value, + objvar_19_name, + objvar_19_type, + objvar_19_value, + + script_list, + + object_id + ) + values + ( + p_x(i), + p_y(i), + p_z(i), + p_quaternion_w(i), + p_quaternion_x(i), + p_quaternion_y(i), + p_quaternion_z(i), + p_node_x(i), + p_node_y(i), + p_node_z(i), + p_object_template_id(i), + p_type_id(i), + p_scene_id(i), + p_controller_type(i), + p_deleted(i), + p_object_name(i), + p_volume(i), + p_contained_by(i), + p_slot_arrangement(i), + p_player_controlled(i), + 0, + p_load_contents(i), + p_cash_balance(i), + p_bank_balance(i), + p_complexity(i), + p_name_string_table(i), + p_name_string_text(i), + p_static_item_name(i), + p_static_item_version(i), + p_conversion_id(i), + p_load_with(i), + + p_objvar_0_name(i), + p_objvar_0_type(i), + p_objvar_0_value(i), + p_objvar_1_name(i), + p_objvar_1_type(i), + p_objvar_1_value(i), + p_objvar_2_name(i), + p_objvar_2_type(i), + p_objvar_2_value(i), + p_objvar_3_name(i), + p_objvar_3_type(i), + p_objvar_3_value(i), + p_objvar_4_name(i), + p_objvar_4_type(i), + p_objvar_4_value(i), + p_objvar_5_name(i), + p_objvar_5_type(i), + p_objvar_5_value(i), + p_objvar_6_name(i), + p_objvar_6_type(i), + p_objvar_6_value(i), + p_objvar_7_name(i), + p_objvar_7_type(i), + p_objvar_7_value(i), + p_objvar_8_name(i), + p_objvar_8_type(i), + p_objvar_8_value(i), + p_objvar_9_name(i), + p_objvar_9_type(i), + p_objvar_9_value(i), + + p_objvar_10_name(i), + p_objvar_10_type(i), + p_objvar_10_value(i), + p_objvar_11_name(i), + p_objvar_11_type(i), + p_objvar_11_value(i), + p_objvar_12_name(i), + p_objvar_12_type(i), + p_objvar_12_value(i), + p_objvar_13_name(i), + p_objvar_13_type(i), + p_objvar_13_value(i), + p_objvar_14_name(i), + p_objvar_14_type(i), + p_objvar_14_value(i), + p_objvar_15_name(i), + p_objvar_15_type(i), + p_objvar_15_value(i), + p_objvar_16_name(i), + p_objvar_16_type(i), + p_objvar_16_value(i), + p_objvar_17_name(i), + p_objvar_17_type(i), + p_objvar_17_value(i), + p_objvar_18_name(i), + p_objvar_18_type(i), + p_objvar_18_value(i), + p_objvar_19_name(i), + p_objvar_19_type(i), + p_objvar_19_value(i), + + p_script_list(i), + + p_object_id(i) + ); + + exception when dup_val_on_index then + for i in 1..p_chunk_size loop + + if + ((p_x(i) is not null) + or (p_y(i) is not null) + or (p_z(i) is not null) + or (p_quaternion_w(i) is not null) + or (p_quaternion_x(i) is not null) + or (p_quaternion_y(i) is not null) + or (p_quaternion_z(i) is not null) + or (p_contained_by(i) is not null) + or (p_cache_version(i) is not null)) + then + p_cache_update := 0; + else + p_cache_update := NULL; + end if; + + UPDATE OBJECTS Set + x = nvl(p_x(i),x), + y = nvl(p_y(i),y), + z = nvl(p_z(i),z), + quaternion_w = nvl(p_quaternion_w(i),quaternion_w), + quaternion_x = nvl(p_quaternion_x(i),quaternion_x), + quaternion_y = nvl(p_quaternion_y(i),quaternion_y), + quaternion_z = nvl(p_quaternion_z(i),quaternion_z), + node_x = nvl(p_node_x(i),node_x), + node_y = nvl(p_node_y(i),node_y), + node_z = nvl(p_node_z(i),node_z), + object_template_id = nvl(p_object_template_id(i),object_template_id), + type_id = nvl(p_type_id(i),type_id), + scene_id = nvl(p_scene_id(i),scene_id), + controller_type = nvl(p_controller_type(i),controller_type), + deleted = nvl(p_deleted(i),deleted), + object_name = nvl(p_object_name(i),object_name), + volume = nvl(p_volume(i),volume), + contained_by = nvl(p_contained_by(i),contained_by), + slot_arrangement = nvl(p_slot_arrangement(i),slot_arrangement), + player_controlled = nvl(p_player_controlled(i),player_controlled), + cache_version = nvl(p_cache_update,cache_version), + load_contents = nvl(p_load_contents(i),load_contents), + cash_balance = nvl(p_cash_balance(i),cash_balance), + bank_balance = nvl(p_bank_balance(i),bank_balance), + complexity = nvl(p_complexity(i),complexity), + name_string_table = nvl(p_name_string_table(i),name_string_table), + name_string_text = nvl(p_name_string_text(i),name_string_text), + static_item_name = nvl(p_static_item_name(i),static_item_name), + static_item_version = nvl(p_static_item_version(i),static_item_version), + conversion_id = nvl(p_conversion_id(i),conversion_id), + load_with = nvl(p_load_with(i),load_with), + + objvar_0_name = nvl(p_objvar_0_name(i), objvar_0_name), + objvar_0_type = nvl(p_objvar_0_type(i), objvar_0_type), + objvar_0_value= nvl(p_objvar_0_value(i),objvar_0_value), + objvar_1_name = nvl(p_objvar_1_name(i), objvar_1_name), + objvar_1_type = nvl(p_objvar_1_type(i), objvar_1_type), + objvar_1_value= nvl(p_objvar_1_value(i),objvar_1_value), + objvar_2_name = nvl(p_objvar_2_name(i), objvar_2_name), + objvar_2_type = nvl(p_objvar_2_type(i), objvar_2_type), + objvar_2_value= nvl(p_objvar_2_value(i),objvar_2_value), + objvar_3_name = nvl(p_objvar_3_name(i), objvar_3_name), + objvar_3_type = nvl(p_objvar_3_type(i), objvar_3_type), + objvar_3_value= nvl(p_objvar_3_value(i),objvar_3_value), + objvar_4_name = nvl(p_objvar_4_name(i), objvar_4_name), + objvar_4_type = nvl(p_objvar_4_type(i), objvar_4_type), + objvar_4_value= nvl(p_objvar_4_value(i),objvar_4_value), + objvar_5_name = nvl(p_objvar_5_name(i), objvar_5_name), + objvar_5_type = nvl(p_objvar_5_type(i), objvar_5_type), + objvar_5_value= nvl(p_objvar_5_value(i),objvar_5_value), + objvar_6_name = nvl(p_objvar_6_name(i), objvar_6_name), + objvar_6_type = nvl(p_objvar_6_type(i), objvar_6_type), + objvar_6_value= nvl(p_objvar_6_value(i),objvar_6_value), + objvar_7_name = nvl(p_objvar_7_name(i), objvar_7_name), + objvar_7_type = nvl(p_objvar_7_type(i), objvar_7_type), + objvar_7_value= nvl(p_objvar_7_value(i),objvar_7_value), + objvar_8_name = nvl(p_objvar_8_name(i), objvar_8_name), + objvar_8_type = nvl(p_objvar_8_type(i), objvar_8_type), + objvar_8_value= nvl(p_objvar_8_value(i),objvar_8_value), + objvar_9_name = nvl(p_objvar_9_name(i), objvar_9_name), + objvar_9_type = nvl(p_objvar_9_type(i), objvar_9_type), + objvar_9_value= nvl(p_objvar_9_value(i),objvar_9_value), + + objvar_10_name = nvl(p_objvar_10_name(i), objvar_10_name), + objvar_10_type = nvl(p_objvar_10_type(i), objvar_10_type), + objvar_10_value= nvl(p_objvar_10_value(i),objvar_10_value), + objvar_11_name = nvl(p_objvar_11_name(i), objvar_11_name), + objvar_11_type = nvl(p_objvar_11_type(i), objvar_11_type), + objvar_11_value= nvl(p_objvar_11_value(i),objvar_11_value), + objvar_12_name = nvl(p_objvar_12_name(i), objvar_12_name), + objvar_12_type = nvl(p_objvar_12_type(i), objvar_12_type), + objvar_12_value= nvl(p_objvar_12_value(i),objvar_12_value), + objvar_13_name = nvl(p_objvar_13_name(i), objvar_13_name), + objvar_13_type = nvl(p_objvar_13_type(i), objvar_13_type), + objvar_13_value= nvl(p_objvar_13_value(i),objvar_13_value), + objvar_14_name = nvl(p_objvar_14_name(i), objvar_14_name), + objvar_14_type = nvl(p_objvar_14_type(i), objvar_14_type), + objvar_14_value= nvl(p_objvar_14_value(i),objvar_14_value), + objvar_15_name = nvl(p_objvar_15_name(i), objvar_15_name), + objvar_15_type = nvl(p_objvar_15_type(i), objvar_15_type), + objvar_15_value= nvl(p_objvar_15_value(i),objvar_15_value), + objvar_16_name = nvl(p_objvar_16_name(i), objvar_16_name), + objvar_16_type = nvl(p_objvar_16_type(i), objvar_16_type), + objvar_16_value= nvl(p_objvar_16_value(i),objvar_16_value), + objvar_17_name = nvl(p_objvar_17_name(i), objvar_17_name), + objvar_17_type = nvl(p_objvar_17_type(i), objvar_17_type), + objvar_17_value= nvl(p_objvar_17_value(i),objvar_17_value), + objvar_18_name = nvl(p_objvar_18_name(i), objvar_18_name), + objvar_18_type = nvl(p_objvar_18_type(i), objvar_18_type), + objvar_18_value= nvl(p_objvar_18_value(i),objvar_18_value), + objvar_19_name = nvl(p_objvar_19_name(i), objvar_19_name), + objvar_19_type = nvl(p_objvar_19_type(i), objvar_19_type), + objvar_19_value= nvl(p_objvar_19_value(i),objvar_19_value), + + script_list = nvl(p_script_list(i), script_list) + + WHERE + object_id=p_object_id(i) and + p_deleted(i) = 0; + + if SQL%ROWCOUNT=0 then + insert into objects + ( + x, + y, + z, + quaternion_w, + quaternion_x, + quaternion_y, + + quaternion_z, + node_x, + node_y, + node_z, + object_template_id, + type_id, + scene_id, + controller_type, + deleted, + object_name, + volume, + contained_by, + slot_arrangement, + player_controlled, + cache_version, + load_contents, + cash_balance, + bank_balance, + complexity, + name_string_table, + name_string_text, + static_item_name, + static_item_version, + conversion_id, + load_with, + + objvar_0_name, + objvar_0_type, + objvar_0_value, + objvar_1_name, + objvar_1_type, + objvar_1_value, + objvar_2_name, + objvar_2_type, + objvar_2_value, + objvar_3_name, + objvar_3_type, + objvar_3_value, + objvar_4_name, + objvar_4_type, + objvar_4_value, + objvar_5_name, + objvar_5_type, + objvar_5_value, + objvar_6_name, + objvar_6_type, + objvar_6_value, + objvar_7_name, + objvar_7_type, + objvar_7_value, + objvar_8_name, + objvar_8_type, + objvar_8_value, + objvar_9_name, + objvar_9_type, + objvar_9_value, + + objvar_10_name, + objvar_10_type, + objvar_10_value, + objvar_11_name, + objvar_11_type, + objvar_11_value, + objvar_12_name, + objvar_12_type, + objvar_12_value, + objvar_13_name, + objvar_13_type, + objvar_13_value, + objvar_14_name, + objvar_14_type, + objvar_14_value, + objvar_15_name, + objvar_15_type, + objvar_15_value, + objvar_16_name, + objvar_16_type, + objvar_16_value, + objvar_17_name, + objvar_17_type, + objvar_17_value, + objvar_18_name, + objvar_18_type, + objvar_18_value, + objvar_19_name, + objvar_19_type, + objvar_19_value, + + script_list, + + object_id + ) + values + ( + p_x(i), + p_y(i), + p_z(i), + p_quaternion_w(i), + p_quaternion_x(i), + p_quaternion_y(i), + p_quaternion_z(i), + p_node_x(i), + p_node_y(i), + p_node_z(i), + p_object_template_id(i), + p_type_id(i), + p_scene_id(i), + p_controller_type(i), + p_deleted(i), + p_object_name(i), + p_volume(i), + p_contained_by(i), + p_slot_arrangement(i), + p_player_controlled(i), + 0, + p_load_contents(i), + p_cash_balance(i), + p_bank_balance(i), + p_complexity(i), + p_name_string_table(i), + p_name_string_text(i), + p_static_item_name(i), + p_static_item_version(i), + p_conversion_id(i), + p_load_with(i), + + p_objvar_0_name(i), + p_objvar_0_type(i), + p_objvar_0_value(i), + p_objvar_1_name(i), + p_objvar_1_type(i), + p_objvar_1_value(i), + p_objvar_2_name(i), + p_objvar_2_type(i), + p_objvar_2_value(i), + p_objvar_3_name(i), + p_objvar_3_type(i), + p_objvar_3_value(i), + p_objvar_4_name(i), + p_objvar_4_type(i), + p_objvar_4_value(i), + p_objvar_5_name(i), + p_objvar_5_type(i), + p_objvar_5_value(i), + p_objvar_6_name(i), + p_objvar_6_type(i), + p_objvar_6_value(i), + p_objvar_7_name(i), + p_objvar_7_type(i), + p_objvar_7_value(i), + p_objvar_8_name(i), + p_objvar_8_type(i), + p_objvar_8_value(i), + p_objvar_9_name(i), + p_objvar_9_type(i), + p_objvar_9_value(i), + + p_objvar_10_name(i), + p_objvar_10_type(i), + p_objvar_10_value(i), + p_objvar_11_name(i), + p_objvar_11_type(i), + p_objvar_11_value(i), + p_objvar_12_name(i), + p_objvar_12_type(i), + p_objvar_12_value(i), + p_objvar_13_name(i), + p_objvar_13_type(i), + p_objvar_13_value(i), + p_objvar_14_name(i), + p_objvar_14_type(i), + p_objvar_14_value(i), + p_objvar_15_name(i), + p_objvar_15_type(i), + p_objvar_15_value(i), + p_objvar_16_name(i), + p_objvar_16_type(i), + p_objvar_16_value(i), + p_objvar_17_name(i), + p_objvar_17_type(i), + p_objvar_17_value(i), + p_objvar_18_name(i), + p_objvar_18_type(i), + p_objvar_18_value(i), + p_objvar_19_name(i), + p_objvar_19_type(i), + p_objvar_19_value(i), + + p_script_list(i), + + p_object_id(i) + ); + + end if; + end loop; + end; + + procedure remove_object ( p_object_id VAOFSTRING, p_chunk_size number) + as + begin + + FORALL i IN 1..p_chunk_size + delete from objects + where object_id = p_object_id(i); + + end; + + procedure save_manf_schem_attribute + ( + p_action number, + p_object_id objectid, + p_attribute_type varchar2, + p_value number + ) + as + begin + if (p_action = 0) then + delete manf_schematic_attributes + where object_id = p_object_id + and attribute_type = p_attribute_type; + else + update manf_schematic_attributes + set value = p_value + where + object_id = p_object_id + and attribute_type = p_attribute_type; + + if (sql%rowcount = 0) then + insert into manf_schematic_attributes (object_id, attribute_type, value) + values (p_object_id, p_attribute_type, p_value); + end if; + end if; + end; + + procedure update_property_list + ( + p_object_id objectid, + p_list_id number, + p_operation number, + p_value varchar2 + ) + as + begin + -- Operations: + -- 0=ERASE + -- 1=INSERT + -- 2=CLEAR + + IF p_operation = 0 THEN + delete from property_lists + where object_id = p_object_id + and list_id = p_list_id + and value = p_value; + + ELSIF p_operation = 1 THEN + insert into property_lists (object_id, list_id, value) + values (p_object_id, p_list_id, p_value); + + ELSIF p_operation = 2 THEN + delete from property_lists + where object_id = p_object_id + and list_id = p_list_id; + + ELSE + raise_application_error(-20000,'Invalid operation code passed to update_command.'); + + END IF; + + exception when dup_val_on_index then + null; + end; + + procedure update_property_list_batch (p_object_id VAOFSTRING, p_list_id VAOFNUMBER, p_operation number, p_value VAOFSTRING, p_chunk_size number, p_enable_db_logging number ) + as + begin + -- Operations: + -- 0=ERASE + -- 1=INSERT + -- 2=CLEAR + + if (p_operation = 0) THEN + FORALL i IN 1.. p_chunk_size + delete from property_lists + where object_id = p_object_id(i) + and list_id = p_list_id(i) + and value = p_value(i); + + ELSIF (p_operation = 1) THEN + FORALL i IN 1.. p_chunk_size + insert into property_lists (object_id, list_id, value) + values (p_object_id(i), p_list_id(i), p_value(i)); + + ELSIF (p_operation = 2) THEN + FORALL i IN 1.. p_chunk_size + delete from property_lists + where object_id = p_object_id(i) + and list_id = p_list_id(i); + + ELSE + raise_application_error(-20000,'Invalid operation code passed to update_command.'); + + END IF; + + exception when dup_val_on_index then + for i in 1..p_chunk_size loop + begin + insert into property_lists + ( + property_lists.list_id, + property_lists.value, + property_lists.object_id + ) + VALUES + ( + p_list_id(i), + p_value(i), + p_object_id(i) + ); + exception when dup_val_on_index then + if ( p_enable_db_logging > 0 ) then + + db_error_logger.dblogerror( SQLCODE, 'procedure update_property_list_batch: duplicate rows were sent to the property list buffer that resulted in a dup_val_on_index error.'); + if ( p_enable_db_logging > 1 ) then + + db_error_logger.dblogerror_values( 'property_lists', 'object_id' , 'number', p_object_id(i)); + db_error_logger.dblogerror_values( 'property_lists', 'list_id' , 'number', to_char(p_list_id(i))); + db_error_logger.dblogerror_values( 'property_lists', 'value' , 'varchar2', p_value(i)); + + end if; + + else + NULL; + end if; + end; + end loop; + end; + + + procedure save_armor + ( + p_object_template varchar2, + p_effectiveness number, + p_integrity number, + p_special_protections varchar2, + p_encumberance_0 number, + p_encumberance_1 number, + p_encumberance_2 number, + p_encumberance_3 number, + p_encumberance_4 number, + p_encumberance_5 number, + p_encumberance_6 number, + p_encumberance_7 number, + p_encumberance_8 number, + p_layer number, + p_object_id objectid + ) + as + begin + -- Note: armor always updates all properties + update armor + set + object_template = p_object_template, + effectiveness = p_effectiveness, + integrity = p_integrity, + special_protections = p_special_protections, + encumberance_0 = p_encumberance_0, + encumberance_1 = p_encumberance_1, + encumberance_2 = p_encumberance_2, + encumberance_3 = p_encumberance_3, + encumberance_4 = p_encumberance_4, + encumberance_5 = p_encumberance_5, + encumberance_6 = p_encumberance_6, + encumberance_7 = p_encumberance_7, + encumberance_8 = p_encumberance_8 + where + layer = p_layer + and object_id = p_object_id; + end; + + procedure add_armor + ( + p_object_template varchar2, + p_effectiveness number, + p_integrity number, + p_special_protections varchar2, + p_encumberance_0 number, + p_encumberance_1 number, + p_encumberance_2 number, + p_encumberance_3 number, + p_encumberance_4 number, + p_encumberance_5 number, + p_encumberance_6 number, + p_encumberance_7 number, + p_encumberance_8 number, + p_layer number, + p_object_id objectid + ) + as + begin + insert into armor + ( + object_template, + effectiveness, + integrity, + special_protections, + encumberance_0, + encumberance_1, + encumberance_2, + + encumberance_3, + encumberance_4, + encumberance_5, + encumberance_6, + encumberance_7, + encumberance_8, + layer, + object_id + ) + values + ( + p_object_template, + p_effectiveness, + p_integrity, + p_special_protections, + p_encumberance_0, + p_encumberance_1, + p_encumberance_2, + p_encumberance_3, + p_encumberance_4, + p_encumberance_5, + p_encumberance_6, + p_encumberance_7, + p_encumberance_8, + p_layer, + p_object_id + ); + + exception when dup_val_on_index then + null; + end; + + procedure save_location + ( + p_object_id number, + p_list_id number, + p_sequence_number number, + p_operation number, + p_name varchar2, + p_scene varchar2, + p_x number, + p_y number, + p_z number, + p_radius number + ) + as + begin + -- Operations: + -- 0=INSERT + + -- 1=DELETE + -- 2=SET + + IF p_operation = 0 THEN + insert into location_lists (object_id, list_id, sequence_number, name, scene, x, y, z, radius) + select p_object_id, p_list_id, p_sequence_number, p_name, p_scene, p_x, p_y, p_z, p_radius + from dual + where not exists (select * from location_lists + where object_id = p_object_id + and list_id = p_list_id + and sequence_number = p_sequence_number); + + ELSIF p_operation = 1 THEN + delete from location_lists + where object_id = p_object_id + and list_id = p_list_id + and sequence_number = p_sequence_number; + + update location_lists + set sequence_number = sequence_number - 1 + where object_id = p_object_id + + and list_id = p_list_id + and sequence_number > p_sequence_number; + + ELSIF p_operation = 2 THEN + update location_lists + set + name = p_name, + scene = p_scene, + x = p_x, + y = p_y, + z = p_z, + radius = p_radius + where object_id = p_object_id + and list_id = p_list_id + and sequence_number = p_sequence_number; + + ELSE + raise_application_error(-20000,'Invalid operation code passed to update_skill.'); + + END IF; + end; + + procedure save_experience ( p_points number, p_experience_type varchar2, p_object_id number ) + as + begin + update experience_points + set points = p_points + where object_id = p_object_id and experience_type = p_experience_type; + + if sql%rowcount = 0 then + insert into experience_points (object_id, experience_type, points) + values (p_object_id, p_experience_type, p_points); + end if; + end; + + procedure save_battlefield_participants ( p_faction_id number, p_character_object_id number, p_region_object_id number ) + as + begin + if (p_faction_id <> 0) then + update battlefield_participants + set faction_id = p_faction_id + where region_object_id = p_region_object_id and character_object_id = p_character_object_id; + + if sql%rowcount = 0 then + insert into battlefield_participants (region_object_id, character_object_id, faction_id) + values (p_region_object_id, p_character_object_id, p_faction_id); + end if; + else + delete battlefield_participants + where region_object_id = p_region_object_id and character_object_id = p_character_object_id; + end if; + end; + + function rename_character( p_character_id objectid, p_new_name varchar2, p_normalized_name varchar2) return number + as + l_existing_object_with_name objectid; + begin + select character_object + into l_existing_object_with_name + from players + where uc_character_name = p_normalized_name; + + if (l_existing_object_with_name = p_character_id) then + update objects + set object_name = p_new_name + where object_id = p_character_id; + + if (sql%rowcount=1) then + update players + set uc_character_name = p_normalized_name, character_full_name = p_new_name + where character_object = p_character_id; + + return 1; + else + return 0; + end if; + else + return 0; + end if; + + exception + when no_data_found then + update objects + set object_name = p_new_name + where object_id = p_character_id; + + if (sql%rowcount=1) then + update players + set uc_character_name = p_normalized_name, character_full_name = p_new_name + where character_object = p_character_id; + + return 1; + else + return 0; + end if; + + when others then + return 0; + end; + + procedure save_waypoint + ( + p_object_id objectid, + p_waypoint_id objectid, + p_appearance_name_crc number, + p_location_x number, + p_location_y number, + p_location_z number, + p_location_cell number, + p_location_scene number, + p_name varchar2, + p_color number, + p_active char, + p_detached char + ) + as + begin + if p_detached='N' then + + update waypoints set + appearance_name_crc = p_appearance_name_crc, + location_x = p_location_x, + location_y = p_location_y, + location_z = p_location_z, + location_cell = p_location_cell, + location_scene = p_location_scene, + name = p_name, + color = p_color, + active = p_active + + where + waypoint_id = p_waypoint_id; + + if (sql%rowcount=0) then + insert into waypoints + ( + object_id, + waypoint_id, + appearance_name_crc, + location_x, + location_y, + location_z, + + location_cell, + location_scene, + name, + color, + active + ) + values + ( + p_object_id, + p_waypoint_id, + p_appearance_name_crc, + p_location_x, + p_location_y, + p_location_z, + p_location_cell, + p_location_scene, + p_name, + p_color, + p_active + ); + end if; + + else -- p_detached <> 'N' + + delete waypoints + where waypoint_id = p_waypoint_id; + + end if; + EXCEPTION + WHEN OTHERS THEN + BEGIN + + Db_Error_Logger.dblogerror( SQLCODE, 'procedure save_waypoint: attempting to find numeric overflow error.'); + + Db_Error_Logger.dblogerror_values( 'waypoints', 'object_id' , 'number', p_object_id); + Db_Error_Logger.dblogerror_values( 'waypoints', 'waypoint_id' , 'number', p_waypoint_id); + Db_Error_Logger.dblogerror_values( 'waypoints', 'appearance_name_crc' , 'number', TO_CHAR(p_appearance_name_crc)); + Db_Error_Logger.dblogerror_values( 'waypoints', 'location_x' , 'number', TO_CHAR(p_location_x)); + Db_Error_Logger.dblogerror_values( 'waypoints', 'location_y' , 'number', TO_CHAR(p_location_y)); + Db_Error_Logger.dblogerror_values( 'waypoints', 'location_z' , 'number', TO_CHAR(p_location_z)); + Db_Error_Logger.dblogerror_values( 'waypoints', 'location_cell' , 'number', TO_CHAR(p_location_cell)); + Db_Error_Logger.dblogerror_values( 'waypoints', 'location_scene' , 'number', TO_CHAR(p_location_scene)); + Db_Error_Logger.dblogerror_values( 'waypoints', 'name' , 'varchar2', p_name); + Db_Error_Logger.dblogerror_values( 'waypoints', 'color' , 'char', p_color); + Db_Error_Logger.dblogerror_values( 'waypoints', 'active' , 'char', p_active); + EXCEPTION + WHEN OTHERS THEN + NULL; + END; + end; + + procedure save_player_obj( p_object_id VAOFSTRING, p_station_id VAOFNUMBER, p_house_id VAOFSTRING, p_account_num_lots VAOFNUMBER, p_account_is_outcast VAOFSTRING, p_account_cheater_level VAOFNUMBER, p_account_max_lots_adjustment VAOFNUMBER, p_personal_profile_id VAOFSTRING, p_character_profile_id VAOFSTRING, p_skill_title VAOFSTRING, p_born_date VAOFNUMBER, p_played_time VAOFNUMBER, p_force_regen_rate VAOFNUMBER, p_force_power VAOFNUMBER, p_max_force_power VAOFNUMBER, p_active_quests VAOFSTRING, p_completed_quests VAOFSTRING, p_current_quest VAOFNUMBER, p_quests VAOFLONGSTRING, p_role_icon_choice VAOFNUMBER, p_quests2 VAOFLONGSTRING, p_quests3 VAOFLONGSTRING, p_quests4 VAOFLONGSTRING, p_skill_template VAOFSTRING, p_working_skill VAOFSTRING, p_current_gcw_points VAOFNUMBER, p_current_gcw_rating VAOFNUMBER, p_current_pvp_kills VAOFNUMBER, p_lifetime_gcw_points VAOFNUMBER, p_max_gcw_imperial_rating VAOFNUMBER, p_max_gcw_rebel_rating VAOFNUMBER, p_lifetime_pvp_kills VAOFNUMBER, p_next_gcw_rating_calc_time VAOFNUMBER, p_collections VAOFLONGSTRING, p_show_backpack VAOFSTRING, p_show_helmet VAOFSTRING, p_collections2 VAOFLONGSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + update player_objects set + player_objects.station_id = nvl(p_station_id(i),player_objects.station_id), + player_objects.personal_profile_id = nvl(p_personal_profile_id(i),player_objects.personal_profile_id), + player_objects.character_profile_id = nvl(p_character_profile_id(i),player_objects.character_profile_id), + player_objects.skill_title = nvl(p_skill_title(i),player_objects.skill_title), + player_objects.born_date = nvl(p_born_date(i),player_objects.born_date), + player_objects.played_time = nvl(p_played_time(i),player_objects.played_time), + player_objects.force_regen_rate = nvl(p_force_regen_rate(i),player_objects.force_regen_rate), + player_objects.force_power = nvl(p_force_power(i),player_objects.force_power), + player_objects.max_force_power = nvl(p_max_force_power(i),player_objects.max_force_power), + player_objects.active_quests = nvl(p_active_quests(i),player_objects.active_quests), + player_objects.completed_quests = nvl(p_completed_quests(i),player_objects.completed_quests), + player_objects.current_quest = nvl(p_current_quest(i),player_objects.current_quest), + player_objects.quests = nvl(p_quests(i),player_objects.quests), + player_objects.role_icon_choice = nvl(p_role_icon_choice(i),player_objects.role_icon_choice), + player_objects.quests2 = nvl(p_quests2(i),player_objects.quests2), + player_objects.quests3 = nvl(p_quests3(i),player_objects.quests3), + player_objects.quests4 = nvl(p_quests4(i),player_objects.quests4), + player_objects.skill_template = nvl(p_skill_template(i),player_objects.skill_template), + player_objects.working_skill = nvl(p_working_skill(i),player_objects.working_skill), + player_objects.current_gcw_points = nvl(p_current_gcw_points(i),player_objects.current_gcw_points), + player_objects.current_gcw_rating = nvl(p_current_gcw_rating(i),player_objects.current_gcw_rating), + player_objects.current_pvp_kills = nvl(p_current_pvp_kills(i),player_objects.current_pvp_kills), + player_objects.lifetime_gcw_points = nvl(p_lifetime_gcw_points(i),player_objects.lifetime_gcw_points), + player_objects.max_gcw_imperial_rating = nvl(p_max_gcw_imperial_rating(i),player_objects.max_gcw_imperial_rating), + player_objects.max_gcw_rebel_rating = nvl(p_max_gcw_rebel_rating(i),player_objects.max_gcw_rebel_rating), + player_objects.lifetime_pvp_kills = nvl(p_lifetime_pvp_kills(i),player_objects.lifetime_pvp_kills), + player_objects.next_gcw_rating_calc_time = nvl(p_next_gcw_rating_calc_time(i),player_objects.next_gcw_rating_calc_time), + player_objects.collections = nvl(p_collections(i),player_objects.collections), + player_objects.show_backpack = nvl(p_show_backpack(i),player_objects.show_backpack), + player_objects.show_helmet = nvl(p_show_helmet(i),player_objects.show_helmet), + player_objects.collections2 = nvl(p_collections2(i),player_objects.collections2), + num_lots = nvl(p_account_num_lots(i), num_lots) + where + player_objects.object_id=p_object_id(i); + + FOR i IN 1.. p_chunk_size + LOOP + if (p_station_id(i) is not null) then + begin + insert into accounts (station_id, is_outcast, cheater_level) + values (p_station_id(i), 0,0); + + exception when dup_val_on_index then + null; + end; + end if; + end LOOP; + + FORALL i IN 1..p_chunk_size + update accounts + set + is_outcast = nvl(p_account_is_outcast(i), is_outcast), + cheater_level = nvl(p_account_cheater_level(i), cheater_level), + max_lots_adjustment = nvl(p_account_max_lots_adjustment(i), max_lots_adjustment), + house_id = nvl(p_house_id(i), house_id) + where + station_id = (select station_id from player_objects where object_id = p_object_id(i)); + + end; + + procedure add_player_obj( p_object_id VAOFSTRING, p_station_id VAOFNUMBER, p_house_id VAOFSTRING, p_account_num_lots VAOFNUMBER, p_account_is_outcast VAOFSTRING, p_account_cheater_level VAOFNUMBER, p_account_max_lots_adjustment VAOFNUMBER, p_personal_profile_id VAOFSTRING, p_character_profile_id VAOFSTRING, p_skill_title VAOFSTRING, p_born_date VAOFNUMBER, p_played_time VAOFNUMBER, p_force_regen_rate VAOFNUMBER, p_force_power VAOFNUMBER, p_max_force_power VAOFNUMBER, p_active_quests VAOFSTRING, p_completed_quests VAOFSTRING, p_current_quest VAOFNUMBER, p_quests VAOFLONGSTRING, p_role_icon_choice VAOFNUMBER, p_quests2 VAOFLONGSTRING, p_quests3 VAOFLONGSTRING, p_quests4 VAOFLONGSTRING, p_skill_template VAOFSTRING, p_working_skill VAOFSTRING, p_current_gcw_points VAOFNUMBER, p_current_gcw_rating VAOFNUMBER, p_current_pvp_kills VAOFNUMBER, p_lifetime_gcw_points VAOFNUMBER, p_max_gcw_imperial_rating VAOFNUMBER, p_max_gcw_rebel_rating VAOFNUMBER, p_lifetime_pvp_kills VAOFNUMBER, p_next_gcw_rating_calc_time VAOFNUMBER, p_collections VAOFLONGSTRING, p_show_backpack VAOFSTRING, p_show_helmet VAOFSTRING, p_collections2 VAOFLONGSTRING, p_chunk_size number ) + as + begin + + FORALL i IN 1..p_chunk_size + insert into player_objects + ( + player_objects.station_id, + player_objects.personal_profile_id, + player_objects.character_profile_id, + player_objects.skill_title, + player_objects.born_date, + player_objects.played_time, + player_objects.force_regen_rate, + player_objects.force_power, + player_objects.max_force_power, + player_objects.num_lots, + player_objects.object_id, + player_objects.active_quests, + player_objects.completed_quests, + player_objects.current_quest, + player_objects.quests, + player_objects.role_icon_choice, + player_objects.quests2, + player_objects.quests3, + player_objects.quests4, + player_objects.skill_template, + player_objects.working_skill, + player_objects.current_gcw_points, + player_objects.current_gcw_rating, + player_objects.current_pvp_kills, + player_objects.lifetime_gcw_points, + player_objects.max_gcw_imperial_rating, + player_objects.max_gcw_rebel_rating, + player_objects.lifetime_pvp_kills, + player_objects.next_gcw_rating_calc_time, + player_objects.collections, + player_objects.show_backpack, + player_objects.show_helmet, + player_objects.collections2 + ) + VALUES + ( + p_station_id(i), + p_personal_profile_id(i), + p_character_profile_id(i), + p_skill_title(i), + p_born_date(i), + p_played_time(i), + p_force_regen_rate(i), + p_force_power(i), + p_max_force_power(i), + p_account_num_lots(i), + p_object_id(i), + p_active_quests(i), + p_completed_quests(i), + p_current_quest(i), + p_quests(i), + p_role_icon_choice(i), + p_quests2(i), + p_quests3(i), + p_quests4(i), + p_skill_template(i), + p_working_skill(i), + p_current_gcw_points(i), + p_current_gcw_rating(i), + p_current_pvp_kills(i), + p_lifetime_gcw_points(i), + p_max_gcw_imperial_rating(i), + p_max_gcw_rebel_rating(i), + p_lifetime_pvp_kills(i), + p_next_gcw_rating_calc_time(i), + p_collections(i), + p_show_backpack(i), + p_show_helmet(i), + p_collections2(i) + ); + + FOR i IN 1.. p_chunk_size + LOOP + if (p_station_id(i) is not null) then + begin + insert into accounts (station_id, is_outcast, cheater_level, max_lots_adjustment, house_id) + values (p_station_id(i), p_account_is_outcast(i), p_account_cheater_level(i), p_account_max_lots_adjustment(i), p_house_id(i)); + + exception when dup_val_on_index then + null; + end; + end if; + end LOOP; + + exception when dup_val_on_index then + for i in 1..p_chunk_size loop + UPDATE player_objects Set + player_objects.station_id = nvl(p_station_id(i),player_objects.station_id), + player_objects.personal_profile_id = nvl(p_personal_profile_id(i),player_objects.personal_profile_id), + player_objects.character_profile_id = nvl(p_character_profile_id(i),player_objects.character_profile_id), + player_objects.skill_title = nvl(p_skill_title(i),player_objects.skill_title), + player_objects.born_date = nvl(p_born_date(i),player_objects.born_date), + player_objects.played_time = nvl(p_played_time(i),player_objects.played_time), + player_objects.force_regen_rate = nvl(p_force_regen_rate(i),player_objects.force_regen_rate), + player_objects.force_power = nvl(p_force_power(i),player_objects.force_power), + player_objects.max_force_power = nvl(p_max_force_power(i),player_objects.max_force_power), + player_objects.num_lots = nvl(p_account_num_lots(i), num_lots), + player_objects.active_quests = nvl(p_active_quests(i),player_objects.active_quests), + player_objects.completed_quests = nvl(p_completed_quests(i),player_objects.completed_quests), + player_objects.current_quest = nvl(p_current_quest(i),player_objects.current_quest), + player_objects.quests = nvl(p_quests(i),player_objects.quests), + player_objects.role_icon_choice = nvl(p_role_icon_choice(i),player_objects.role_icon_choice), + player_objects.quests2 = nvl(p_quests(i),player_objects.quests2), + player_objects.quests3 = nvl(p_quests(i),player_objects.quests3), + player_objects.quests4 = nvl(p_quests(i),player_objects.quests4), + player_objects.skill_template = nvl(p_skill_template(i),player_objects.skill_template), + player_objects.working_skill = nvl(p_working_skill(i),player_objects.working_skill), + player_objects.current_gcw_points = nvl(p_current_gcw_points(i),player_objects.current_gcw_points), + player_objects.current_gcw_rating = nvl(p_current_gcw_rating(i),player_objects.current_gcw_rating), + player_objects.current_pvp_kills = nvl(p_current_pvp_kills(i),player_objects.current_pvp_kills), + player_objects.lifetime_gcw_points = nvl(p_lifetime_gcw_points(i),player_objects.lifetime_gcw_points), + player_objects.max_gcw_imperial_rating = nvl(p_max_gcw_imperial_rating(i),player_objects.max_gcw_imperial_rating), + player_objects.max_gcw_rebel_rating = nvl(p_max_gcw_rebel_rating(i),player_objects.max_gcw_rebel_rating), + player_objects.lifetime_pvp_kills = nvl(p_lifetime_pvp_kills(i),player_objects.lifetime_pvp_kills), + player_objects.next_gcw_rating_calc_time = nvl(p_next_gcw_rating_calc_time(i),player_objects.next_gcw_rating_calc_time), + player_objects.collections = nvl(p_collections(i),player_objects.collections), + player_objects.show_backpack = nvl(p_show_backpack(i),player_objects.show_backpack), + player_objects.show_helmet = nvl(p_show_helmet(i),player_objects.show_helmet), + player_objects.collections2 = nvl(p_collections2(i),player_objects.collections2) + where + player_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into player_objects + ( + player_objects.station_id, + player_objects.personal_profile_id, + player_objects.character_profile_id, + player_objects.skill_title, + player_objects.born_date, + player_objects.played_time, + player_objects.force_regen_rate, + player_objects.force_power, + player_objects.max_force_power, + player_objects.num_lots, + player_objects.object_id, + player_objects.active_quests, + player_objects.completed_quests, + player_objects.current_quest, + player_objects.quests, + player_objects.role_icon_choice, + player_objects.quests2, + player_objects.quests3, + player_objects.quests4, + player_objects.skill_template, + player_objects.working_skill, + player_objects.current_gcw_points, + player_objects.current_gcw_rating, + player_objects.current_pvp_kills, + player_objects.lifetime_gcw_points, + player_objects.max_gcw_imperial_rating, + player_objects.max_gcw_rebel_rating, + player_objects.lifetime_pvp_kills, + player_objects.next_gcw_rating_calc_time, + player_objects.collections, + player_objects.show_backpack, + player_objects.show_helmet, + player_objects.collections2 + ) + VALUES + ( + p_station_id(i), + p_personal_profile_id(i), + p_character_profile_id(i), + p_skill_title(i), + p_born_date(i), + p_played_time(i), + p_force_regen_rate(i), + p_force_power(i), + p_max_force_power(i), + p_account_num_lots(i), + p_object_id(i), + p_active_quests(i), + p_completed_quests(i), + p_current_quest(i), + p_quests(i), + p_role_icon_choice(i), + p_quests2(i), + p_quests3(i), + p_quests4(i), + p_skill_template(i), + p_working_skill(i), + p_current_gcw_points(i), + p_current_gcw_rating(i), + p_current_pvp_kills(i), + p_lifetime_gcw_points(i), + p_max_gcw_imperial_rating(i), + p_max_gcw_rebel_rating(i), + p_lifetime_pvp_kills(i), + p_next_gcw_rating_calc_time(i), + p_collections(i), + p_show_backpack(i), + p_show_helmet(i), + p_collections2(i) + ); + end if; + end loop; + + FOR i IN 1.. p_chunk_size + LOOP + if (p_station_id(i) is not null) then + begin + insert into accounts (station_id, is_outcast, cheater_level, max_lots_adjustment, house_id) + values (p_station_id(i), p_account_is_outcast(i), p_account_cheater_level(i), p_account_max_lots_adjustment(i), p_house_id(i)); + + exception when dup_val_on_index then + null; + end; + end if; + end LOOP; + end; + + procedure remove_player_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete player_objects + where + object_id=p_object_id(i); + end; + + procedure delete_demand_container( p_object_id VAOFSTRING, p_reason VAOFNUMBER, p_chunk_size number ) + as + l_delete_reason number; + begin + select reason_code + into l_delete_reason + from delete_reasons + where tag='ContainerDeleted'; + + FOR i IN 1.. p_chunk_size + LOOP + update objects + set deleted = decode(p_reason(i),0,l_delete_reason,p_reason(i)), -- use reason if specified, otherwise use 'ContainerDeleted' if it is 0 + load_with = null, + deleted_date = sysdate + where load_with = p_object_id(i); + end LOOP; + end; + + procedure save_resource_type(p_resource_id VAOFSTRING, p_resource_name VAOFSTRING, p_resource_class VAOFSTRING, p_attributes VAOFSTRING, p_fractal_seeds VAOFSTRING, p_depleted_timestamp VAOFNUMBER, p_chunk_size number) + as + begin + forall i in 1..p_chunk_size + insert into resource_types + ( + resource_id, + resource_name, + resource_class, + attributes, + fractal_seeds, + depleted_timestamp + ) + values + ( + p_resource_id(i), + p_resource_name(i), + p_resource_class(i), + p_attributes(i), + p_fractal_seeds(i), + p_depleted_timestamp(i) + ); + + exception when dup_val_on_index then + for i in 1..p_chunk_size loop + update resource_types set + resource_name = p_resource_name(i), + resource_class = p_resource_class(i), + attributes = p_attributes(i), + fractal_seeds = p_fractal_seeds(i), + depleted_timestamp = p_depleted_timestamp(i) + where + resource_id=p_resource_id(i); + + if SQL%ROWCOUNT=0 then + insert into resource_types + ( + resource_id, + resource_name, + resource_class, + attributes, + fractal_seeds, + depleted_timestamp + ) + values + ( + p_resource_id(i), + p_resource_name(i), + p_resource_class(i), + p_attributes(i), + p_fractal_seeds(i), + p_depleted_timestamp(i) + ); + end if; + end loop; + end; + + procedure save_bounty_hunter_target(p_object_id VAOFSTRING, p_target_id VAOFSTRING, p_chunk_size number) + as + begin + forall i in 1..p_chunk_size + insert into bounty_hunter_targets + ( + object_id, + target_id + ) + values + ( + p_object_id(i), + p_target_id(i) + ); + + delete bounty_hunter_targets + where target_id = 0; + + exception when dup_val_on_index then + begin + for i in 1..p_chunk_size loop + update bounty_hunter_targets set + target_id = p_target_id(i) + where + object_id = p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into bounty_hunter_targets + ( + object_id, + target_id + ) + values + ( + p_object_id(i), + p_target_id(i) + ); + end if; + end loop; + + delete bounty_hunter_targets + where target_id = 0; + end; + end; + + function subtract_money_from_object(p_object_id number, p_amount number) return char + as + new_bank_balance number; + new_cash_balance number; + begin + select bank_balance, cash_balance + into new_bank_balance, new_cash_balance + from objects + where object_id = p_object_id + for update; + + if (new_bank_balance + new_cash_balance < p_amount) then + return 'N'; + end if; + + new_bank_balance := new_bank_balance - p_amount; + if (new_bank_balance < 0) then + new_cash_balance := new_cash_balance + new_bank_balance; + new_bank_balance := 0; + end if; + + update objects + set bank_balance = new_bank_balance, cash_balance = new_cash_balance + where object_id = p_object_id; + + return 'Y'; + exception + when others then + return 'N'; + end; + +-- GENERATED PLSQL FOLLOWS +-- generated by makepersister.pl + + procedure save_battlefield_marker_obj( p_object_id VAOFSTRING, p_region_name VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update battlefield_marker_objects set + battlefield_marker_objects.region_name = nvl(p_region_name(i),battlefield_marker_objects.region_name) + where + battlefield_marker_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update battlefield_marker_objects set + battlefield_marker_objects.region_name = nvl(p_region_name(i),battlefield_marker_objects.region_name) + where + battlefield_marker_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_battlefield_marker_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_battlefield_marker_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_battlefield_marker_obj','region_name','varchar2',p_region_name(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_battlefield_marker_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_battlefield_marker_obj( p_object_id VAOFSTRING, p_region_name VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into battlefield_marker_objects + ( + battlefield_marker_objects.region_name, + battlefield_marker_objects.object_id + ) + VALUES + ( + p_region_name(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_battlefield_marker_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE battlefield_marker_objects Set + battlefield_marker_objects.region_name = nvl(p_region_name(i),battlefield_marker_objects.region_name) + where + battlefield_marker_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into battlefield_marker_objects + ( + battlefield_marker_objects.region_name, + battlefield_marker_objects.object_id + ) + VALUES + ( + p_region_name(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into battlefield_marker_objects + ( + battlefield_marker_objects.region_name, + battlefield_marker_objects.object_id + ) + VALUES + ( + p_region_name(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_battlefield_marker_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_battlefield_marker_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_battlefield_marker_obj','region_name','varchar2',p_region_name(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_battlefield_marker_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_battlefield_marker_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete battlefield_marker_objects + where + object_id=p_object_id(i); + end; + + procedure save_building_obj( p_object_id VAOFSTRING, p_maintenance_cost VAOFNUMBER, p_time_last_checked VAOFNUMBER, p_is_public VAOFSTRING, p_city_id VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update building_objects set + building_objects.maintenance_cost = nvl(p_maintenance_cost(i),building_objects.maintenance_cost), + building_objects.time_last_checked = nvl(p_time_last_checked(i),building_objects.time_last_checked), + building_objects.is_public = nvl(p_is_public(i),building_objects.is_public), + building_objects.city_id = nvl(p_city_id(i),building_objects.city_id) + where + building_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update building_objects set + building_objects.maintenance_cost = nvl(p_maintenance_cost(i),building_objects.maintenance_cost), + building_objects.time_last_checked = nvl(p_time_last_checked(i),building_objects.time_last_checked), + building_objects.is_public = nvl(p_is_public(i),building_objects.is_public), + building_objects.city_id = nvl(p_city_id(i),building_objects.city_id) + where + building_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_building_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_building_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_building_obj','maintenance_cost','int',to_char(p_maintenance_cost(m_error_index))); + db_error_logger.dblogerror_values('persister.save_building_obj','time_last_checked','float',to_char(p_time_last_checked(m_error_index))); + db_error_logger.dblogerror_values('persister.save_building_obj','is_public','char',p_is_public(m_error_index)); + db_error_logger.dblogerror_values('persister.save_building_obj','city_id','int',to_char(p_city_id(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_building_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_building_obj( p_object_id VAOFSTRING, p_maintenance_cost VAOFNUMBER, p_time_last_checked VAOFNUMBER, p_is_public VAOFSTRING, p_city_id VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into building_objects + ( + building_objects.maintenance_cost, + building_objects.time_last_checked, + building_objects.is_public, + building_objects.city_id, + building_objects.object_id + ) + VALUES + ( + p_maintenance_cost(i), + p_time_last_checked(i), + p_is_public(i), + p_city_id(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_building_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE building_objects Set + building_objects.maintenance_cost = nvl(p_maintenance_cost(i),building_objects.maintenance_cost), + building_objects.time_last_checked = nvl(p_time_last_checked(i),building_objects.time_last_checked), + building_objects.is_public = nvl(p_is_public(i),building_objects.is_public), + building_objects.city_id = nvl(p_city_id(i),building_objects.city_id) + where + building_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into building_objects + ( + building_objects.maintenance_cost, + building_objects.time_last_checked, + building_objects.is_public, + building_objects.city_id, + building_objects.object_id + ) + VALUES + ( + p_maintenance_cost(i), + p_time_last_checked(i), + p_is_public(i), + p_city_id(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into building_objects + ( + building_objects.maintenance_cost, + building_objects.time_last_checked, + building_objects.is_public, + building_objects.city_id, + building_objects.object_id + ) + VALUES + ( + p_maintenance_cost(i), + p_time_last_checked(i), + p_is_public(i), + p_city_id(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_building_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_building_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_building_obj','maintenance_cost','int',to_char(p_maintenance_cost(m_error_index))); + db_error_logger.dblogerror_values('persister.add_building_obj','time_last_checked','float',to_char(p_time_last_checked(m_error_index))); + db_error_logger.dblogerror_values('persister.add_building_obj','is_public','char',p_is_public(m_error_index)); + db_error_logger.dblogerror_values('persister.add_building_obj','city_id','int',to_char(p_city_id(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_building_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_building_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete building_objects + where + object_id=p_object_id(i); + end; + + procedure save_cell_obj( p_object_id VAOFSTRING, p_cell_number VAOFNUMBER, p_is_public VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update cell_objects set + cell_objects.cell_number = nvl(p_cell_number(i),cell_objects.cell_number), + cell_objects.is_public = nvl(p_is_public(i),cell_objects.is_public) + where + cell_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update cell_objects set + cell_objects.cell_number = nvl(p_cell_number(i),cell_objects.cell_number), + cell_objects.is_public = nvl(p_is_public(i),cell_objects.is_public) + where + cell_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_cell_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_cell_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_cell_obj','cell_number','int',to_char(p_cell_number(m_error_index))); + db_error_logger.dblogerror_values('persister.save_cell_obj','is_public','char',p_is_public(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_cell_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_cell_obj( p_object_id VAOFSTRING, p_cell_number VAOFNUMBER, p_is_public VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into cell_objects + ( + cell_objects.cell_number, + cell_objects.is_public, + cell_objects.object_id + ) + VALUES + ( + p_cell_number(i), + p_is_public(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_cell_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE cell_objects Set + cell_objects.cell_number = nvl(p_cell_number(i),cell_objects.cell_number), + cell_objects.is_public = nvl(p_is_public(i),cell_objects.is_public) + where + cell_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into cell_objects + ( + cell_objects.cell_number, + cell_objects.is_public, + cell_objects.object_id + ) + VALUES + ( + p_cell_number(i), + p_is_public(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into cell_objects + ( + cell_objects.cell_number, + cell_objects.is_public, + cell_objects.object_id + ) + VALUES + ( + p_cell_number(i), + p_is_public(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_cell_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_cell_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_cell_obj','cell_number','int',to_char(p_cell_number(m_error_index))); + db_error_logger.dblogerror_values('persister.add_cell_obj','is_public','char',p_is_public(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_cell_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_cell_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete cell_objects + where + object_id=p_object_id(i); + end; + + procedure save_city_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + null; + end; + + procedure add_city_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into city_objects + ( + city_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_city_obj : dup_val_on_index error.'); + END IF; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into city_objects + ( + city_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_city_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_city_obj','object_id','number',p_object_id(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_city_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_city_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + null; + end; + + procedure save_creature_obj( p_object_id VAOFSTRING, p_scale_factor VAOFNUMBER, p_states VAOFNUMBER, p_posture VAOFNUMBER, p_shock_wounds VAOFNUMBER, p_master_id VAOFSTRING, p_rank VAOFNUMBER, p_base_walk_speed VAOFNUMBER, p_base_run_speed VAOFNUMBER, p_attribute_0 VAOFNUMBER, p_attribute_1 VAOFNUMBER, p_attribute_2 VAOFNUMBER, p_attribute_3 VAOFNUMBER, p_attribute_4 VAOFNUMBER, p_attribute_5 VAOFNUMBER, p_attribute_6 VAOFNUMBER, p_attribute_7 VAOFNUMBER, p_attribute_8 VAOFNUMBER, p_attribute_9 VAOFNUMBER, p_attribute_10 VAOFNUMBER, p_attribute_11 VAOFNUMBER, p_attribute_12 VAOFNUMBER, p_attribute_13 VAOFNUMBER, p_attribute_14 VAOFNUMBER, p_attribute_15 VAOFNUMBER, p_attribute_16 VAOFNUMBER, p_attribute_17 VAOFNUMBER, p_attribute_18 VAOFNUMBER, p_attribute_19 VAOFNUMBER, p_attribute_20 VAOFNUMBER, p_attribute_21 VAOFNUMBER, p_attribute_22 VAOFNUMBER, p_attribute_23 VAOFNUMBER, p_attribute_24 VAOFNUMBER, p_attribute_25 VAOFNUMBER, p_attribute_26 VAOFNUMBER, p_persisted_buffs VAOFSTRING, p_ws_x VAOFNUMBER, p_ws_y VAOFNUMBER, p_ws_z VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update creature_objects set + creature_objects.scale_factor = nvl(p_scale_factor(i),creature_objects.scale_factor), + creature_objects.states = nvl(p_states(i),creature_objects.states), + creature_objects.posture = nvl(p_posture(i),creature_objects.posture), + creature_objects.shock_wounds = nvl(p_shock_wounds(i),creature_objects.shock_wounds), + creature_objects.master_id = nvl(p_master_id(i),creature_objects.master_id), + creature_objects.rank = nvl(p_rank(i),creature_objects.rank), + creature_objects.base_walk_speed = nvl(p_base_walk_speed(i),creature_objects.base_walk_speed), + creature_objects.base_run_speed = nvl(p_base_run_speed(i),creature_objects.base_run_speed), + creature_objects.attribute_0 = nvl(p_attribute_0(i),creature_objects.attribute_0), + creature_objects.attribute_1 = nvl(p_attribute_1(i),creature_objects.attribute_1), + creature_objects.attribute_2 = nvl(p_attribute_2(i),creature_objects.attribute_2), + creature_objects.attribute_3 = nvl(p_attribute_3(i),creature_objects.attribute_3), + creature_objects.attribute_4 = nvl(p_attribute_4(i),creature_objects.attribute_4), + creature_objects.attribute_5 = nvl(p_attribute_5(i),creature_objects.attribute_5), + creature_objects.attribute_6 = nvl(p_attribute_6(i),creature_objects.attribute_6), + creature_objects.attribute_7 = nvl(p_attribute_7(i),creature_objects.attribute_7), + creature_objects.attribute_8 = nvl(p_attribute_8(i),creature_objects.attribute_8), + creature_objects.attribute_9 = nvl(p_attribute_9(i),creature_objects.attribute_9), + creature_objects.attribute_10 = nvl(p_attribute_10(i),creature_objects.attribute_10), + creature_objects.attribute_11 = nvl(p_attribute_11(i),creature_objects.attribute_11), + creature_objects.attribute_12 = nvl(p_attribute_12(i),creature_objects.attribute_12), + creature_objects.attribute_13 = nvl(p_attribute_13(i),creature_objects.attribute_13), + creature_objects.attribute_14 = nvl(p_attribute_14(i),creature_objects.attribute_14), + creature_objects.attribute_15 = nvl(p_attribute_15(i),creature_objects.attribute_15), + creature_objects.attribute_16 = nvl(p_attribute_16(i),creature_objects.attribute_16), + creature_objects.attribute_17 = nvl(p_attribute_17(i),creature_objects.attribute_17), + creature_objects.attribute_18 = nvl(p_attribute_18(i),creature_objects.attribute_18), + creature_objects.attribute_19 = nvl(p_attribute_19(i),creature_objects.attribute_19), + creature_objects.attribute_20 = nvl(p_attribute_20(i),creature_objects.attribute_20), + creature_objects.attribute_21 = nvl(p_attribute_21(i),creature_objects.attribute_21), + creature_objects.attribute_22 = nvl(p_attribute_22(i),creature_objects.attribute_22), + creature_objects.attribute_23 = nvl(p_attribute_23(i),creature_objects.attribute_23), + creature_objects.attribute_24 = nvl(p_attribute_24(i),creature_objects.attribute_24), + creature_objects.attribute_25 = nvl(p_attribute_25(i),creature_objects.attribute_25), + creature_objects.attribute_26 = nvl(p_attribute_26(i),creature_objects.attribute_26), + creature_objects.persisted_buffs = nvl(p_persisted_buffs(i),creature_objects.persisted_buffs), + creature_objects.ws_x = nvl(p_ws_x(i),creature_objects.ws_x), + creature_objects.ws_y = nvl(p_ws_y(i),creature_objects.ws_y), + creature_objects.ws_z = nvl(p_ws_z(i),creature_objects.ws_z) + where + creature_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update creature_objects set + creature_objects.scale_factor = nvl(p_scale_factor(i),creature_objects.scale_factor), + creature_objects.states = nvl(p_states(i),creature_objects.states), + creature_objects.posture = nvl(p_posture(i),creature_objects.posture), + creature_objects.shock_wounds = nvl(p_shock_wounds(i),creature_objects.shock_wounds), + creature_objects.master_id = nvl(p_master_id(i),creature_objects.master_id), + creature_objects.rank = nvl(p_rank(i),creature_objects.rank), + creature_objects.base_walk_speed = nvl(p_base_walk_speed(i),creature_objects.base_walk_speed), + creature_objects.base_run_speed = nvl(p_base_run_speed(i),creature_objects.base_run_speed), + creature_objects.attribute_0 = nvl(p_attribute_0(i),creature_objects.attribute_0), + creature_objects.attribute_1 = nvl(p_attribute_1(i),creature_objects.attribute_1), + creature_objects.attribute_2 = nvl(p_attribute_2(i),creature_objects.attribute_2), + creature_objects.attribute_3 = nvl(p_attribute_3(i),creature_objects.attribute_3), + creature_objects.attribute_4 = nvl(p_attribute_4(i),creature_objects.attribute_4), + creature_objects.attribute_5 = nvl(p_attribute_5(i),creature_objects.attribute_5), + creature_objects.attribute_6 = nvl(p_attribute_6(i),creature_objects.attribute_6), + creature_objects.attribute_7 = nvl(p_attribute_7(i),creature_objects.attribute_7), + creature_objects.attribute_8 = nvl(p_attribute_8(i),creature_objects.attribute_8), + creature_objects.attribute_9 = nvl(p_attribute_9(i),creature_objects.attribute_9), + creature_objects.attribute_10 = nvl(p_attribute_10(i),creature_objects.attribute_10), + creature_objects.attribute_11 = nvl(p_attribute_11(i),creature_objects.attribute_11), + creature_objects.attribute_12 = nvl(p_attribute_12(i),creature_objects.attribute_12), + creature_objects.attribute_13 = nvl(p_attribute_13(i),creature_objects.attribute_13), + creature_objects.attribute_14 = nvl(p_attribute_14(i),creature_objects.attribute_14), + creature_objects.attribute_15 = nvl(p_attribute_15(i),creature_objects.attribute_15), + creature_objects.attribute_16 = nvl(p_attribute_16(i),creature_objects.attribute_16), + creature_objects.attribute_17 = nvl(p_attribute_17(i),creature_objects.attribute_17), + creature_objects.attribute_18 = nvl(p_attribute_18(i),creature_objects.attribute_18), + creature_objects.attribute_19 = nvl(p_attribute_19(i),creature_objects.attribute_19), + creature_objects.attribute_20 = nvl(p_attribute_20(i),creature_objects.attribute_20), + creature_objects.attribute_21 = nvl(p_attribute_21(i),creature_objects.attribute_21), + creature_objects.attribute_22 = nvl(p_attribute_22(i),creature_objects.attribute_22), + creature_objects.attribute_23 = nvl(p_attribute_23(i),creature_objects.attribute_23), + creature_objects.attribute_24 = nvl(p_attribute_24(i),creature_objects.attribute_24), + creature_objects.attribute_25 = nvl(p_attribute_25(i),creature_objects.attribute_25), + creature_objects.attribute_26 = nvl(p_attribute_26(i),creature_objects.attribute_26), + creature_objects.persisted_buffs = nvl(p_persisted_buffs(i),creature_objects.persisted_buffs), + creature_objects.ws_x = nvl(p_ws_x(i),creature_objects.ws_x), + creature_objects.ws_y = nvl(p_ws_y(i),creature_objects.ws_y), + creature_objects.ws_z = nvl(p_ws_z(i),creature_objects.ws_z) + where + creature_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_creature_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_creature_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_creature_obj','scale_factor','float',to_char(p_scale_factor(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','states','int',to_char(p_states(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','posture','int',to_char(p_posture(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','shock_wounds','int',to_char(p_shock_wounds(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','master_id','number',p_master_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_creature_obj','rank','int',to_char(p_rank(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','base_walk_speed','float',to_char(p_base_walk_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','base_run_speed','float',to_char(p_base_run_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_0','int',to_char(p_attribute_0(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_1','int',to_char(p_attribute_1(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_2','int',to_char(p_attribute_2(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_3','int',to_char(p_attribute_3(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_4','int',to_char(p_attribute_4(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_5','int',to_char(p_attribute_5(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_6','int',to_char(p_attribute_6(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_7','int',to_char(p_attribute_7(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_8','int',to_char(p_attribute_8(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_9','int',to_char(p_attribute_9(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_10','int',to_char(p_attribute_10(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_11','int',to_char(p_attribute_11(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_12','int',to_char(p_attribute_12(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_13','int',to_char(p_attribute_13(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_14','int',to_char(p_attribute_14(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_15','int',to_char(p_attribute_15(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_16','int',to_char(p_attribute_16(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_17','int',to_char(p_attribute_17(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_18','int',to_char(p_attribute_18(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_19','int',to_char(p_attribute_19(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_20','int',to_char(p_attribute_20(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_21','int',to_char(p_attribute_21(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_22','int',to_char(p_attribute_22(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_23','int',to_char(p_attribute_23(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_24','int',to_char(p_attribute_24(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_25','int',to_char(p_attribute_25(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','attribute_26','int',to_char(p_attribute_26(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','persisted_buffs','varchar2',p_persisted_buffs(m_error_index)); + + db_error_logger.dblogerror_values('persister.save_creature_obj','ws_x','float',to_char(p_ws_x(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','ws_y','float',to_char(p_ws_y(m_error_index))); + db_error_logger.dblogerror_values('persister.save_creature_obj','ws_z','float',to_char(p_ws_z(m_error_index))); + + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_creature_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_creature_obj( p_object_id VAOFSTRING, p_scale_factor VAOFNUMBER, p_states VAOFNUMBER, p_posture VAOFNUMBER, p_shock_wounds VAOFNUMBER, p_master_id VAOFSTRING, p_rank VAOFNUMBER, p_base_walk_speed VAOFNUMBER, p_base_run_speed VAOFNUMBER, p_attribute_0 VAOFNUMBER, p_attribute_1 VAOFNUMBER, p_attribute_2 VAOFNUMBER, p_attribute_3 VAOFNUMBER, p_attribute_4 VAOFNUMBER, p_attribute_5 VAOFNUMBER, p_attribute_6 VAOFNUMBER, p_attribute_7 VAOFNUMBER, p_attribute_8 VAOFNUMBER, p_attribute_9 VAOFNUMBER, p_attribute_10 VAOFNUMBER, p_attribute_11 VAOFNUMBER, p_attribute_12 VAOFNUMBER, p_attribute_13 VAOFNUMBER, p_attribute_14 VAOFNUMBER, p_attribute_15 VAOFNUMBER, p_attribute_16 VAOFNUMBER, p_attribute_17 VAOFNUMBER, p_attribute_18 VAOFNUMBER, p_attribute_19 VAOFNUMBER, p_attribute_20 VAOFNUMBER, p_attribute_21 VAOFNUMBER, p_attribute_22 VAOFNUMBER, p_attribute_23 VAOFNUMBER, p_attribute_24 VAOFNUMBER, p_attribute_25 VAOFNUMBER, p_attribute_26 VAOFNUMBER, p_persisted_buffs VAOFSTRING, p_ws_x VAOFNUMBER, p_ws_y VAOFNUMBER, p_ws_z VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into creature_objects + ( + creature_objects.scale_factor, + creature_objects.states, + creature_objects.posture, + creature_objects.shock_wounds, + creature_objects.master_id, + creature_objects.rank, + creature_objects.base_walk_speed, + creature_objects.base_run_speed, + creature_objects.attribute_0, + creature_objects.attribute_1, + creature_objects.attribute_2, + creature_objects.attribute_3, + creature_objects.attribute_4, + creature_objects.attribute_5, + creature_objects.attribute_6, + creature_objects.attribute_7, + creature_objects.attribute_8, + creature_objects.attribute_9, + creature_objects.attribute_10, + creature_objects.attribute_11, + creature_objects.attribute_12, + creature_objects.attribute_13, + creature_objects.attribute_14, + creature_objects.attribute_15, + creature_objects.attribute_16, + creature_objects.attribute_17, + creature_objects.attribute_18, + creature_objects.attribute_19, + creature_objects.attribute_20, + creature_objects.attribute_21, + creature_objects.attribute_22, + creature_objects.attribute_23, + creature_objects.attribute_24, + creature_objects.attribute_25, + creature_objects.attribute_26, + creature_objects.persisted_buffs, + creature_objects.object_id, + creature_objects.ws_x, + creature_objects.ws_y, + creature_objects.ws_z + ) + VALUES + ( + p_scale_factor(i), + p_states(i), + p_posture(i), + p_shock_wounds(i), + p_master_id(i), + p_rank(i), + p_base_walk_speed(i), + p_base_run_speed(i), + p_attribute_0(i), + p_attribute_1(i), + p_attribute_2(i), + p_attribute_3(i), + p_attribute_4(i), + p_attribute_5(i), + p_attribute_6(i), + p_attribute_7(i), + p_attribute_8(i), + p_attribute_9(i), + p_attribute_10(i), + p_attribute_11(i), + p_attribute_12(i), + p_attribute_13(i), + p_attribute_14(i), + p_attribute_15(i), + p_attribute_16(i), + p_attribute_17(i), + p_attribute_18(i), + p_attribute_19(i), + p_attribute_20(i), + p_attribute_21(i), + p_attribute_22(i), + p_attribute_23(i), + p_attribute_24(i), + p_attribute_25(i), + p_attribute_26(i), + p_persisted_buffs(i), + p_object_id(i), + NULL, + NULL, + NULL + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_creature_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE creature_objects Set + creature_objects.scale_factor = nvl(p_scale_factor(i),creature_objects.scale_factor), + creature_objects.states = nvl(p_states(i),creature_objects.states), + creature_objects.posture = nvl(p_posture(i),creature_objects.posture), + creature_objects.shock_wounds = nvl(p_shock_wounds(i),creature_objects.shock_wounds), + creature_objects.master_id = nvl(p_master_id(i),creature_objects.master_id), + creature_objects.rank = nvl(p_rank(i),creature_objects.rank), + creature_objects.base_walk_speed = nvl(p_base_walk_speed(i),creature_objects.base_walk_speed), + creature_objects.base_run_speed = nvl(p_base_run_speed(i),creature_objects.base_run_speed), + creature_objects.attribute_0 = nvl(p_attribute_0(i),creature_objects.attribute_0), + creature_objects.attribute_1 = nvl(p_attribute_1(i),creature_objects.attribute_1), + creature_objects.attribute_2 = nvl(p_attribute_2(i),creature_objects.attribute_2), + creature_objects.attribute_3 = nvl(p_attribute_3(i),creature_objects.attribute_3), + creature_objects.attribute_4 = nvl(p_attribute_4(i),creature_objects.attribute_4), + creature_objects.attribute_5 = nvl(p_attribute_5(i),creature_objects.attribute_5), + creature_objects.attribute_6 = nvl(p_attribute_6(i),creature_objects.attribute_6), + creature_objects.attribute_7 = nvl(p_attribute_7(i),creature_objects.attribute_7), + creature_objects.attribute_8 = nvl(p_attribute_8(i),creature_objects.attribute_8), + creature_objects.attribute_9 = nvl(p_attribute_9(i),creature_objects.attribute_9), + creature_objects.attribute_10 = nvl(p_attribute_10(i),creature_objects.attribute_10), + creature_objects.attribute_11 = nvl(p_attribute_11(i),creature_objects.attribute_11), + creature_objects.attribute_12 = nvl(p_attribute_12(i),creature_objects.attribute_12), + creature_objects.attribute_13 = nvl(p_attribute_13(i),creature_objects.attribute_13), + creature_objects.attribute_14 = nvl(p_attribute_14(i),creature_objects.attribute_14), + creature_objects.attribute_15 = nvl(p_attribute_15(i),creature_objects.attribute_15), + creature_objects.attribute_16 = nvl(p_attribute_16(i),creature_objects.attribute_16), + creature_objects.attribute_17 = nvl(p_attribute_17(i),creature_objects.attribute_17), + creature_objects.attribute_18 = nvl(p_attribute_18(i),creature_objects.attribute_18), + creature_objects.attribute_19 = nvl(p_attribute_19(i),creature_objects.attribute_19), + creature_objects.attribute_20 = nvl(p_attribute_20(i),creature_objects.attribute_20), + creature_objects.attribute_21 = nvl(p_attribute_21(i),creature_objects.attribute_21), + creature_objects.attribute_22 = nvl(p_attribute_22(i),creature_objects.attribute_22), + creature_objects.attribute_23 = nvl(p_attribute_23(i),creature_objects.attribute_23), + creature_objects.attribute_24 = nvl(p_attribute_24(i),creature_objects.attribute_24), + creature_objects.attribute_25 = nvl(p_attribute_25(i),creature_objects.attribute_25), + creature_objects.attribute_26 = nvl(p_attribute_26(i),creature_objects.attribute_26), + creature_objects.persisted_buffs = nvl(p_persisted_buffs(i),creature_objects.persisted_buffs), + creature_objects.ws_x = nvl(p_ws_x(i),creature_objects.ws_x), + creature_objects.ws_y = nvl(p_ws_y(i),creature_objects.ws_y), + creature_objects.ws_z = nvl(p_ws_z(i),creature_objects.ws_z) + where + creature_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into creature_objects + ( + creature_objects.scale_factor, + creature_objects.states, + creature_objects.posture, + creature_objects.shock_wounds, + creature_objects.master_id, + creature_objects.rank, + creature_objects.base_walk_speed, + creature_objects.base_run_speed, + creature_objects.attribute_0, + creature_objects.attribute_1, + creature_objects.attribute_2, + creature_objects.attribute_3, + creature_objects.attribute_4, + creature_objects.attribute_5, + creature_objects.attribute_6, + creature_objects.attribute_7, + creature_objects.attribute_8, + creature_objects.attribute_9, + creature_objects.attribute_10, + creature_objects.attribute_11, + creature_objects.attribute_12, + creature_objects.attribute_13, + creature_objects.attribute_14, + creature_objects.attribute_15, + creature_objects.attribute_16, + creature_objects.attribute_17, + creature_objects.attribute_18, + creature_objects.attribute_19, + creature_objects.attribute_20, + creature_objects.attribute_21, + creature_objects.attribute_22, + creature_objects.attribute_23, + creature_objects.attribute_24, + creature_objects.attribute_25, + creature_objects.attribute_26, + creature_objects.persisted_buffs, + creature_objects.object_id, + creature_objects.ws_x, + creature_objects.ws_y, + creature_objects.ws_z + ) + VALUES + ( + p_scale_factor(i), + p_states(i), + p_posture(i), + p_shock_wounds(i), + p_master_id(i), + p_rank(i), + p_base_walk_speed(i), + p_base_run_speed(i), + p_attribute_0(i), + p_attribute_1(i), + p_attribute_2(i), + p_attribute_3(i), + p_attribute_4(i), + p_attribute_5(i), + p_attribute_6(i), + p_attribute_7(i), + p_attribute_8(i), + p_attribute_9(i), + p_attribute_10(i), + p_attribute_11(i), + p_attribute_12(i), + p_attribute_13(i), + p_attribute_14(i), + p_attribute_15(i), + p_attribute_16(i), + p_attribute_17(i), + p_attribute_18(i), + p_attribute_19(i), + p_attribute_20(i), + p_attribute_21(i), + p_attribute_22(i), + p_attribute_23(i), + p_attribute_24(i), + p_attribute_25(i), + p_attribute_26(i), + p_persisted_buffs(i), + p_object_id(i), + NULL, + NULL, + NULL + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into creature_objects + ( + creature_objects.scale_factor, + creature_objects.states, + creature_objects.posture, + creature_objects.shock_wounds, + creature_objects.master_id, + creature_objects.rank, + creature_objects.base_walk_speed, + creature_objects.base_run_speed, + creature_objects.attribute_0, + creature_objects.attribute_1, + creature_objects.attribute_2, + creature_objects.attribute_3, + creature_objects.attribute_4, + creature_objects.attribute_5, + creature_objects.attribute_6, + creature_objects.attribute_7, + creature_objects.attribute_8, + creature_objects.attribute_9, + creature_objects.attribute_10, + creature_objects.attribute_11, + creature_objects.attribute_12, + creature_objects.attribute_13, + creature_objects.attribute_14, + creature_objects.attribute_15, + creature_objects.attribute_16, + creature_objects.attribute_17, + creature_objects.attribute_18, + creature_objects.attribute_19, + creature_objects.attribute_20, + creature_objects.attribute_21, + creature_objects.attribute_22, + creature_objects.attribute_23, + creature_objects.attribute_24, + creature_objects.attribute_25, + creature_objects.attribute_26, + creature_objects.persisted_buffs, + creature_objects.object_id, + creature_objects.ws_x, + creature_objects.ws_y, + creature_objects.ws_z + ) + VALUES + ( + p_scale_factor(i), + p_states(i), + p_posture(i), + p_shock_wounds(i), + p_master_id(i), + p_rank(i), + p_base_walk_speed(i), + p_base_run_speed(i), + p_attribute_0(i), + p_attribute_1(i), + p_attribute_2(i), + p_attribute_3(i), + p_attribute_4(i), + p_attribute_5(i), + p_attribute_6(i), + p_attribute_7(i), + p_attribute_8(i), + p_attribute_9(i), + p_attribute_10(i), + p_attribute_11(i), + p_attribute_12(i), + p_attribute_13(i), + p_attribute_14(i), + p_attribute_15(i), + p_attribute_16(i), + p_attribute_17(i), + p_attribute_18(i), + p_attribute_19(i), + p_attribute_20(i), + p_attribute_21(i), + p_attribute_22(i), + p_attribute_23(i), + p_attribute_24(i), + p_attribute_25(i), + p_attribute_26(i), + p_persisted_buffs(i), + p_object_id(i), + NULL, + NULL, + NULL + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_creature_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_creature_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_creature_obj','scale_factor','float',to_char(p_scale_factor(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','states','int',to_char(p_states(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','posture','int',to_char(p_posture(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','shock_wounds','int',to_char(p_shock_wounds(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','master_id','number',p_master_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_creature_obj','rank','int',to_char(p_rank(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','base_walk_speed','float',to_char(p_base_walk_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','base_run_speed','float',to_char(p_base_run_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_0','int',to_char(p_attribute_0(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_1','int',to_char(p_attribute_1(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_2','int',to_char(p_attribute_2(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_3','int',to_char(p_attribute_3(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_4','int',to_char(p_attribute_4(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_5','int',to_char(p_attribute_5(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_6','int',to_char(p_attribute_6(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_7','int',to_char(p_attribute_7(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_8','int',to_char(p_attribute_8(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_9','int',to_char(p_attribute_9(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_10','int',to_char(p_attribute_10(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_11','int',to_char(p_attribute_11(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_12','int',to_char(p_attribute_12(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_13','int',to_char(p_attribute_13(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_14','int',to_char(p_attribute_14(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_15','int',to_char(p_attribute_15(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_16','int',to_char(p_attribute_16(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_17','int',to_char(p_attribute_17(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_18','int',to_char(p_attribute_18(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_19','int',to_char(p_attribute_19(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_20','int',to_char(p_attribute_20(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_21','int',to_char(p_attribute_21(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_22','int',to_char(p_attribute_22(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_23','int',to_char(p_attribute_23(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_24','int',to_char(p_attribute_24(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_25','int',to_char(p_attribute_25(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','attribute_26','int',to_char(p_attribute_26(m_error_index))); + db_error_logger.dblogerror_values('persister.add_creature_obj','persisted_buffs','varchar2',p_persisted_buffs(m_error_index)); + db_error_logger.dblogerror_values('persister.add_creature_obj','ws_x','float',p_ws_x(m_error_index)); + db_error_logger.dblogerror_values('persister.add_creature_obj','ws_y','float',p_ws_y(m_error_index)); + db_error_logger.dblogerror_values('persister.add_creature_obj','ws_z','float',p_ws_z(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_creature_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_creature_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete creature_objects + where + object_id=p_object_id(i); + end; + + procedure save_factory_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + null; + end; + + procedure add_factory_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into factory_objects + ( + factory_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_factory_obj : dup_val_on_index error.'); + END IF; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into factory_objects + ( + factory_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_factory_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_factory_obj','object_id','number',p_object_id(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_factory_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_factory_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + null; + end; + + procedure save_guild_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + null; + end; + + procedure add_guild_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into guild_objects + ( + guild_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_guild_obj : dup_val_on_index error.'); + END IF; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into guild_objects + ( + guild_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_guild_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_guild_obj','object_id','number',p_object_id(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_guild_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_guild_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + null; + end; + + procedure save_harvester_inst_obj( p_object_id VAOFSTRING, p_installed_efficiency VAOFNUMBER, p_max_extraction_rate VAOFNUMBER, p_current_extraction_rate VAOFNUMBER, p_max_hopper_amount VAOFNUMBER, p_hopper_resource VAOFSTRING, p_hopper_amount VAOFNUMBER, p_resource_type VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update harvester_installation_objects set + harvester_installation_objects.installed_efficiency = nvl(p_installed_efficiency(i),harvester_installation_objects.installed_efficiency), + harvester_installation_objects.max_extraction_rate = nvl(p_max_extraction_rate(i),harvester_installation_objects.max_extraction_rate), + harvester_installation_objects.current_extraction_rate = nvl(p_current_extraction_rate(i),harvester_installation_objects.current_extraction_rate), + harvester_installation_objects.max_hopper_amount = nvl(p_max_hopper_amount(i),harvester_installation_objects.max_hopper_amount), + harvester_installation_objects.hopper_resource = nvl(p_hopper_resource(i),harvester_installation_objects.hopper_resource), + harvester_installation_objects.hopper_amount = nvl(p_hopper_amount(i),harvester_installation_objects.hopper_amount), + harvester_installation_objects.resource_type = nvl(p_resource_type(i),harvester_installation_objects.resource_type) + where + harvester_installation_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update harvester_installation_objects set + harvester_installation_objects.installed_efficiency = nvl(p_installed_efficiency(i),harvester_installation_objects.installed_efficiency), + harvester_installation_objects.max_extraction_rate = nvl(p_max_extraction_rate(i),harvester_installation_objects.max_extraction_rate), + harvester_installation_objects.current_extraction_rate = nvl(p_current_extraction_rate(i),harvester_installation_objects.current_extraction_rate), + harvester_installation_objects.max_hopper_amount = nvl(p_max_hopper_amount(i),harvester_installation_objects.max_hopper_amount), + harvester_installation_objects.hopper_resource = nvl(p_hopper_resource(i),harvester_installation_objects.hopper_resource), + harvester_installation_objects.hopper_amount = nvl(p_hopper_amount(i),harvester_installation_objects.hopper_amount), + harvester_installation_objects.resource_type = nvl(p_resource_type(i),harvester_installation_objects.resource_type) + where + harvester_installation_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_harvester_inst_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','installed_efficiency','float',to_char(p_installed_efficiency(m_error_index))); + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','max_extraction_rate','int',to_char(p_max_extraction_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','current_extraction_rate','float',to_char(p_current_extraction_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','max_hopper_amount','int',to_char(p_max_hopper_amount(m_error_index))); + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','hopper_resource','number',p_hopper_resource(m_error_index)); + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','hopper_amount','float',to_char(p_hopper_amount(m_error_index))); + db_error_logger.dblogerror_values('persister.save_harvester_inst_obj','resource_type','number',p_resource_type(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_harvester_inst_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_harvester_inst_obj( p_object_id VAOFSTRING, p_installed_efficiency VAOFNUMBER, p_max_extraction_rate VAOFNUMBER, p_current_extraction_rate VAOFNUMBER, p_max_hopper_amount VAOFNUMBER, p_hopper_resource VAOFSTRING, p_hopper_amount VAOFNUMBER, p_resource_type VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into harvester_installation_objects + ( + harvester_installation_objects.installed_efficiency, + harvester_installation_objects.max_extraction_rate, + harvester_installation_objects.current_extraction_rate, + harvester_installation_objects.max_hopper_amount, + harvester_installation_objects.hopper_resource, + harvester_installation_objects.hopper_amount, + harvester_installation_objects.resource_type, + harvester_installation_objects.object_id + ) + VALUES + ( + p_installed_efficiency(i), + p_max_extraction_rate(i), + p_current_extraction_rate(i), + p_max_hopper_amount(i), + p_hopper_resource(i), + p_hopper_amount(i), + p_resource_type(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_harvester_inst_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE harvester_installation_objects Set + harvester_installation_objects.installed_efficiency = nvl(p_installed_efficiency(i),harvester_installation_objects.installed_efficiency), + harvester_installation_objects.max_extraction_rate = nvl(p_max_extraction_rate(i),harvester_installation_objects.max_extraction_rate), + harvester_installation_objects.current_extraction_rate = nvl(p_current_extraction_rate(i),harvester_installation_objects.current_extraction_rate), + harvester_installation_objects.max_hopper_amount = nvl(p_max_hopper_amount(i),harvester_installation_objects.max_hopper_amount), + harvester_installation_objects.hopper_resource = nvl(p_hopper_resource(i),harvester_installation_objects.hopper_resource), + harvester_installation_objects.hopper_amount = nvl(p_hopper_amount(i),harvester_installation_objects.hopper_amount), + harvester_installation_objects.resource_type = nvl(p_resource_type(i),harvester_installation_objects.resource_type) + where + harvester_installation_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into harvester_installation_objects + ( + harvester_installation_objects.installed_efficiency, + harvester_installation_objects.max_extraction_rate, + harvester_installation_objects.current_extraction_rate, + harvester_installation_objects.max_hopper_amount, + harvester_installation_objects.hopper_resource, + harvester_installation_objects.hopper_amount, + harvester_installation_objects.resource_type, + harvester_installation_objects.object_id + ) + VALUES + ( + p_installed_efficiency(i), + p_max_extraction_rate(i), + p_current_extraction_rate(i), + p_max_hopper_amount(i), + p_hopper_resource(i), + p_hopper_amount(i), + p_resource_type(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into harvester_installation_objects + ( + harvester_installation_objects.installed_efficiency, + harvester_installation_objects.max_extraction_rate, + harvester_installation_objects.current_extraction_rate, + harvester_installation_objects.max_hopper_amount, + harvester_installation_objects.hopper_resource, + harvester_installation_objects.hopper_amount, + harvester_installation_objects.resource_type, + harvester_installation_objects.object_id + ) + VALUES + ( + p_installed_efficiency(i), + p_max_extraction_rate(i), + p_current_extraction_rate(i), + p_max_hopper_amount(i), + p_hopper_resource(i), + p_hopper_amount(i), + p_resource_type(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_harvester_inst_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','installed_efficiency','float',to_char(p_installed_efficiency(m_error_index))); + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','max_extraction_rate','int',to_char(p_max_extraction_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','current_extraction_rate','float',to_char(p_current_extraction_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','max_hopper_amount','int',to_char(p_max_hopper_amount(m_error_index))); + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','hopper_resource','number',p_hopper_resource(m_error_index)); + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','hopper_amount','float',to_char(p_hopper_amount(m_error_index))); + db_error_logger.dblogerror_values('persister.add_harvester_inst_obj','resource_type','number',p_resource_type(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_harvester_inst_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_harvester_inst_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete harvester_installation_objects + where + object_id=p_object_id(i); + end; + + procedure save_installation_obj( p_object_id VAOFSTRING, p_installation_type VAOFNUMBER, p_activated VAOFSTRING, p_tick_count VAOFNUMBER, p_activate_start_time VAOFNUMBER, p_power VAOFNUMBER, p_power_rate VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update installation_objects set + installation_objects.installation_type = nvl(p_installation_type(i),installation_objects.installation_type), + installation_objects.activated = nvl(p_activated(i),installation_objects.activated), + installation_objects.tick_count = nvl(p_tick_count(i),installation_objects.tick_count), + installation_objects.activate_start_time = nvl(p_activate_start_time(i),installation_objects.activate_start_time), + installation_objects.power = nvl(p_power(i),installation_objects.power), + installation_objects.power_rate = nvl(p_power_rate(i),installation_objects.power_rate) + where + installation_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update installation_objects set + installation_objects.installation_type = nvl(p_installation_type(i),installation_objects.installation_type), + installation_objects.activated = nvl(p_activated(i),installation_objects.activated), + installation_objects.tick_count = nvl(p_tick_count(i),installation_objects.tick_count), + installation_objects.activate_start_time = nvl(p_activate_start_time(i),installation_objects.activate_start_time), + installation_objects.power = nvl(p_power(i),installation_objects.power), + installation_objects.power_rate = nvl(p_power_rate(i),installation_objects.power_rate) + where + installation_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_installation_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_installation_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_installation_obj','installation_type','int',to_char(p_installation_type(m_error_index))); + db_error_logger.dblogerror_values('persister.save_installation_obj','activated','char',p_activated(m_error_index)); + db_error_logger.dblogerror_values('persister.save_installation_obj','tick_count','float',to_char(p_tick_count(m_error_index))); + db_error_logger.dblogerror_values('persister.save_installation_obj','activate_start_time','float',to_char(p_activate_start_time(m_error_index))); + db_error_logger.dblogerror_values('persister.save_installation_obj','power','float',to_char(p_power(m_error_index))); + db_error_logger.dblogerror_values('persister.save_installation_obj','power_rate','float',to_char(p_power_rate(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_installation_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_installation_obj( p_object_id VAOFSTRING, p_installation_type VAOFNUMBER, p_activated VAOFSTRING, p_tick_count VAOFNUMBER, p_activate_start_time VAOFNUMBER, p_power VAOFNUMBER, p_power_rate VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into installation_objects + ( + installation_objects.installation_type, + installation_objects.activated, + installation_objects.tick_count, + installation_objects.activate_start_time, + installation_objects.power, + installation_objects.power_rate, + installation_objects.object_id + ) + VALUES + ( + p_installation_type(i), + p_activated(i), + p_tick_count(i), + p_activate_start_time(i), + p_power(i), + p_power_rate(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_installation_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE installation_objects Set + installation_objects.installation_type = nvl(p_installation_type(i),installation_objects.installation_type), + installation_objects.activated = nvl(p_activated(i),installation_objects.activated), + installation_objects.tick_count = nvl(p_tick_count(i),installation_objects.tick_count), + installation_objects.activate_start_time = nvl(p_activate_start_time(i),installation_objects.activate_start_time), + installation_objects.power = nvl(p_power(i),installation_objects.power), + installation_objects.power_rate = nvl(p_power_rate(i),installation_objects.power_rate) + where + installation_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into installation_objects + ( + installation_objects.installation_type, + installation_objects.activated, + installation_objects.tick_count, + installation_objects.activate_start_time, + installation_objects.power, + installation_objects.power_rate, + installation_objects.object_id + ) + VALUES + ( + p_installation_type(i), + p_activated(i), + p_tick_count(i), + p_activate_start_time(i), + p_power(i), + p_power_rate(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into installation_objects + ( + installation_objects.installation_type, + installation_objects.activated, + installation_objects.tick_count, + installation_objects.activate_start_time, + installation_objects.power, + installation_objects.power_rate, + installation_objects.object_id + ) + VALUES + ( + p_installation_type(i), + p_activated(i), + p_tick_count(i), + p_activate_start_time(i), + p_power(i), + p_power_rate(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_installation_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_installation_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_installation_obj','installation_type','int',to_char(p_installation_type(m_error_index))); + db_error_logger.dblogerror_values('persister.add_installation_obj','activated','char',p_activated(m_error_index)); + db_error_logger.dblogerror_values('persister.add_installation_obj','tick_count','float',to_char(p_tick_count(m_error_index))); + db_error_logger.dblogerror_values('persister.add_installation_obj','activate_start_time','float',to_char(p_activate_start_time(m_error_index))); + db_error_logger.dblogerror_values('persister.add_installation_obj','power','float',to_char(p_power(m_error_index))); + db_error_logger.dblogerror_values('persister.add_installation_obj','power_rate','float',to_char(p_power_rate(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_installation_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_installation_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete installation_objects + where + object_id=p_object_id(i); + end; + + procedure save_intangible_obj( p_object_id VAOFSTRING, p_count VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update intangible_objects set + intangible_objects.count = nvl(p_count(i),intangible_objects.count) + where + intangible_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update intangible_objects set + intangible_objects.count = nvl(p_count(i),intangible_objects.count) + where + intangible_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_intangible_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_intangible_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_intangible_obj','count','int',to_char(p_count(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_intangible_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_intangible_obj( p_object_id VAOFSTRING, p_count VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into intangible_objects + ( + intangible_objects.count, + intangible_objects.object_id + ) + VALUES + ( + p_count(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_intangible_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE intangible_objects Set + intangible_objects.count = nvl(p_count(i),intangible_objects.count) + where + intangible_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into intangible_objects + ( + intangible_objects.count, + intangible_objects.object_id + ) + VALUES + ( + p_count(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into intangible_objects + ( + intangible_objects.count, + intangible_objects.object_id + ) + VALUES + ( + p_count(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_intangible_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_intangible_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_intangible_obj','count','int',to_char(p_count(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_intangible_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_intangible_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete intangible_objects + where + object_id=p_object_id(i); + end; + + procedure save_manf_schematic_obj( p_object_id VAOFSTRING, p_creator_id VAOFSTRING, p_creator_name VAOFSTRING, p_items_per_container VAOFNUMBER, p_manufacture_time VAOFNUMBER, p_draft_schematic VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update manf_schematic_objects set + manf_schematic_objects.creator_id = nvl(p_creator_id(i),manf_schematic_objects.creator_id), + manf_schematic_objects.creator_name = nvl(p_creator_name(i),manf_schematic_objects.creator_name), + manf_schematic_objects.items_per_container = nvl(p_items_per_container(i),manf_schematic_objects.items_per_container), + manf_schematic_objects.manufacture_time = nvl(p_manufacture_time(i),manf_schematic_objects.manufacture_time), + manf_schematic_objects.draft_schematic = nvl(p_draft_schematic(i),manf_schematic_objects.draft_schematic) + where + manf_schematic_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update manf_schematic_objects set + manf_schematic_objects.creator_id = nvl(p_creator_id(i),manf_schematic_objects.creator_id), + manf_schematic_objects.creator_name = nvl(p_creator_name(i),manf_schematic_objects.creator_name), + manf_schematic_objects.items_per_container = nvl(p_items_per_container(i),manf_schematic_objects.items_per_container), + manf_schematic_objects.manufacture_time = nvl(p_manufacture_time(i),manf_schematic_objects.manufacture_time), + manf_schematic_objects.draft_schematic = nvl(p_draft_schematic(i),manf_schematic_objects.draft_schematic) + where + manf_schematic_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_manf_schematic_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_manf_schematic_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_manf_schematic_obj','creator_id','number',p_creator_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_manf_schematic_obj','creator_name','varchar2',p_creator_name(m_error_index)); + db_error_logger.dblogerror_values('persister.save_manf_schematic_obj','items_per_container','int',to_char(p_items_per_container(m_error_index))); + db_error_logger.dblogerror_values('persister.save_manf_schematic_obj','manufacture_time','float',to_char(p_manufacture_time(m_error_index))); + db_error_logger.dblogerror_values('persister.save_manf_schematic_obj','draft_schematic','int',to_char(p_draft_schematic(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_manf_schematic_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_manf_schematic_obj( p_object_id VAOFSTRING, p_creator_id VAOFSTRING, p_creator_name VAOFSTRING, p_items_per_container VAOFNUMBER, p_manufacture_time VAOFNUMBER, p_draft_schematic VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into manf_schematic_objects + ( + manf_schematic_objects.creator_id, + manf_schematic_objects.creator_name, + manf_schematic_objects.items_per_container, + manf_schematic_objects.manufacture_time, + manf_schematic_objects.draft_schematic, + manf_schematic_objects.object_id + ) + VALUES + ( + p_creator_id(i), + p_creator_name(i), + p_items_per_container(i), + p_manufacture_time(i), + p_draft_schematic(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_manf_schematic_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE manf_schematic_objects Set + manf_schematic_objects.creator_id = nvl(p_creator_id(i),manf_schematic_objects.creator_id), + manf_schematic_objects.creator_name = nvl(p_creator_name(i),manf_schematic_objects.creator_name), + manf_schematic_objects.items_per_container = nvl(p_items_per_container(i),manf_schematic_objects.items_per_container), + manf_schematic_objects.manufacture_time = nvl(p_manufacture_time(i),manf_schematic_objects.manufacture_time), + manf_schematic_objects.draft_schematic = nvl(p_draft_schematic(i),manf_schematic_objects.draft_schematic) + where + manf_schematic_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into manf_schematic_objects + ( + manf_schematic_objects.creator_id, + manf_schematic_objects.creator_name, + manf_schematic_objects.items_per_container, + manf_schematic_objects.manufacture_time, + manf_schematic_objects.draft_schematic, + manf_schematic_objects.object_id + ) + VALUES + ( + p_creator_id(i), + p_creator_name(i), + p_items_per_container(i), + p_manufacture_time(i), + p_draft_schematic(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into manf_schematic_objects + ( + manf_schematic_objects.creator_id, + manf_schematic_objects.creator_name, + manf_schematic_objects.items_per_container, + manf_schematic_objects.manufacture_time, + manf_schematic_objects.draft_schematic, + manf_schematic_objects.object_id + ) + VALUES + ( + p_creator_id(i), + p_creator_name(i), + p_items_per_container(i), + p_manufacture_time(i), + p_draft_schematic(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_manf_schematic_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_manf_schematic_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_manf_schematic_obj','creator_id','number',p_creator_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_manf_schematic_obj','creator_name','varchar2',p_creator_name(m_error_index)); + db_error_logger.dblogerror_values('persister.add_manf_schematic_obj','items_per_container','int',to_char(p_items_per_container(m_error_index))); + db_error_logger.dblogerror_values('persister.add_manf_schematic_obj','manufacture_time','float',to_char(p_manufacture_time(m_error_index))); + db_error_logger.dblogerror_values('persister.add_manf_schematic_obj','draft_schematic','int',to_char(p_draft_schematic(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_manf_schematic_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_manf_schematic_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete manf_schematic_objects + where + object_id=p_object_id(i); + end; + + procedure save_manufacture_inst_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + null; + end; + + procedure add_manufacture_inst_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into manufacture_inst_objects + ( + manufacture_inst_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_manufacture_inst_obj : dup_val_on_index error.'); + END IF; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into manufacture_inst_objects + ( + manufacture_inst_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_manufacture_inst_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_manufacture_inst_obj','object_id','number',p_object_id(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_manufacture_inst_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_manufacture_inst_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + null; + end; + + procedure save_mission_obj( p_object_id VAOFSTRING, p_difficulty VAOFNUMBER, p_end_x VAOFNUMBER, p_end_y VAOFNUMBER, p_end_z VAOFNUMBER, p_end_cell VAOFSTRING, p_end_scene VAOFNUMBER, p_mission_creator VAOFSTRING, p_reward VAOFNUMBER, p_root_script_name VAOFSTRING, p_start_x VAOFNUMBER, p_start_y VAOFNUMBER, p_start_z VAOFNUMBER, p_start_cell VAOFSTRING, p_start_scene VAOFNUMBER, p_description_table VAOFSTRING, p_description_text VAOFSTRING, p_title_table VAOFSTRING, p_title_text VAOFSTRING, p_mission_holder_id VAOFSTRING, p_status VAOFNUMBER, p_mission_type VAOFNUMBER, p_target_appearance VAOFNUMBER, p_target_name VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update mission_objects set + mission_objects.difficulty = nvl(p_difficulty(i),mission_objects.difficulty), + mission_objects.end_x = nvl(p_end_x(i),mission_objects.end_x), + mission_objects.end_y = nvl(p_end_y(i),mission_objects.end_y), + mission_objects.end_z = nvl(p_end_z(i),mission_objects.end_z), + mission_objects.end_cell = nvl(p_end_cell(i),mission_objects.end_cell), + mission_objects.end_scene = nvl(p_end_scene(i),mission_objects.end_scene), + mission_objects.mission_creator = nvl(p_mission_creator(i),mission_objects.mission_creator), + mission_objects.reward = nvl(p_reward(i),mission_objects.reward), + mission_objects.root_script_name = nvl(p_root_script_name(i),mission_objects.root_script_name), + mission_objects.start_x = nvl(p_start_x(i),mission_objects.start_x), + mission_objects.start_y = nvl(p_start_y(i),mission_objects.start_y), + mission_objects.start_z = nvl(p_start_z(i),mission_objects.start_z), + mission_objects.start_cell = nvl(p_start_cell(i),mission_objects.start_cell), + mission_objects.start_scene = nvl(p_start_scene(i),mission_objects.start_scene), + mission_objects.description_table = nvl(p_description_table(i),mission_objects.description_table), + mission_objects.description_text = nvl(p_description_text(i),mission_objects.description_text), + mission_objects.title_table = nvl(p_title_table(i),mission_objects.title_table), + mission_objects.title_text = nvl(p_title_text(i),mission_objects.title_text), + mission_objects.mission_holder_id = nvl(p_mission_holder_id(i),mission_objects.mission_holder_id), + mission_objects.status = nvl(p_status(i),mission_objects.status), + mission_objects.mission_type = nvl(p_mission_type(i),mission_objects.mission_type), + mission_objects.target_appearance = nvl(p_target_appearance(i),mission_objects.target_appearance), + mission_objects.target_name = nvl(p_target_name(i),mission_objects.target_name) + where + mission_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update mission_objects set + mission_objects.difficulty = nvl(p_difficulty(i),mission_objects.difficulty), + mission_objects.end_x = nvl(p_end_x(i),mission_objects.end_x), + mission_objects.end_y = nvl(p_end_y(i),mission_objects.end_y), + mission_objects.end_z = nvl(p_end_z(i),mission_objects.end_z), + mission_objects.end_cell = nvl(p_end_cell(i),mission_objects.end_cell), + mission_objects.end_scene = nvl(p_end_scene(i),mission_objects.end_scene), + mission_objects.mission_creator = nvl(p_mission_creator(i),mission_objects.mission_creator), + mission_objects.reward = nvl(p_reward(i),mission_objects.reward), + mission_objects.root_script_name = nvl(p_root_script_name(i),mission_objects.root_script_name), + mission_objects.start_x = nvl(p_start_x(i),mission_objects.start_x), + mission_objects.start_y = nvl(p_start_y(i),mission_objects.start_y), + mission_objects.start_z = nvl(p_start_z(i),mission_objects.start_z), + mission_objects.start_cell = nvl(p_start_cell(i),mission_objects.start_cell), + mission_objects.start_scene = nvl(p_start_scene(i),mission_objects.start_scene), + mission_objects.description_table = nvl(p_description_table(i),mission_objects.description_table), + mission_objects.description_text = nvl(p_description_text(i),mission_objects.description_text), + mission_objects.title_table = nvl(p_title_table(i),mission_objects.title_table), + mission_objects.title_text = nvl(p_title_text(i),mission_objects.title_text), + mission_objects.mission_holder_id = nvl(p_mission_holder_id(i),mission_objects.mission_holder_id), + mission_objects.status = nvl(p_status(i),mission_objects.status), + mission_objects.mission_type = nvl(p_mission_type(i),mission_objects.mission_type), + mission_objects.target_appearance = nvl(p_target_appearance(i),mission_objects.target_appearance), + mission_objects.target_name = nvl(p_target_name(i),mission_objects.target_name) + where + mission_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_mission_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_mission_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','difficulty','int',to_char(p_difficulty(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','end_x','float',to_char(p_end_x(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','end_y','float',to_char(p_end_y(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','end_z','float',to_char(p_end_z(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','end_cell','number',p_end_cell(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','end_scene','int',to_char(p_end_scene(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','mission_creator','varchar2',p_mission_creator(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','reward','int',to_char(p_reward(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','root_script_name','varchar2',p_root_script_name(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','start_x','float',to_char(p_start_x(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','start_y','float',to_char(p_start_y(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','start_z','float',to_char(p_start_z(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','start_cell','number',p_start_cell(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','start_scene','int',to_char(p_start_scene(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','description_table','varchar2',p_description_table(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','description_text','varchar2',p_description_text(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','title_table','varchar2',p_title_table(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','title_text','varchar2',p_title_text(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','mission_holder_id','number',p_mission_holder_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_mission_obj','status','int',to_char(p_status(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','mission_type','int',to_char(p_mission_type(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','target_appearance','int',to_char(p_target_appearance(m_error_index))); + db_error_logger.dblogerror_values('persister.save_mission_obj','target_name','varchar2',p_target_name(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_mission_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_mission_obj( p_object_id VAOFSTRING, p_difficulty VAOFNUMBER, p_end_x VAOFNUMBER, p_end_y VAOFNUMBER, p_end_z VAOFNUMBER, p_end_cell VAOFSTRING, p_end_scene VAOFNUMBER, p_mission_creator VAOFSTRING, p_reward VAOFNUMBER, p_root_script_name VAOFSTRING, p_start_x VAOFNUMBER, p_start_y VAOFNUMBER, p_start_z VAOFNUMBER, p_start_cell VAOFSTRING, p_start_scene VAOFNUMBER, p_description_table VAOFSTRING, p_description_text VAOFSTRING, p_title_table VAOFSTRING, p_title_text VAOFSTRING, p_mission_holder_id VAOFSTRING, p_status VAOFNUMBER, p_mission_type VAOFNUMBER, p_target_appearance VAOFNUMBER, p_target_name VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into mission_objects + ( + mission_objects.difficulty, + mission_objects.end_x, + mission_objects.end_y, + mission_objects.end_z, + mission_objects.end_cell, + mission_objects.end_scene, + mission_objects.mission_creator, + mission_objects.reward, + mission_objects.root_script_name, + mission_objects.start_x, + mission_objects.start_y, + mission_objects.start_z, + mission_objects.start_cell, + mission_objects.start_scene, + mission_objects.description_table, + mission_objects.description_text, + mission_objects.title_table, + mission_objects.title_text, + mission_objects.mission_holder_id, + mission_objects.status, + mission_objects.mission_type, + mission_objects.target_appearance, + mission_objects.target_name, + mission_objects.object_id + ) + VALUES + ( + p_difficulty(i), + p_end_x(i), + p_end_y(i), + p_end_z(i), + p_end_cell(i), + p_end_scene(i), + p_mission_creator(i), + p_reward(i), + p_root_script_name(i), + p_start_x(i), + p_start_y(i), + p_start_z(i), + p_start_cell(i), + p_start_scene(i), + p_description_table(i), + p_description_text(i), + p_title_table(i), + p_title_text(i), + p_mission_holder_id(i), + p_status(i), + p_mission_type(i), + p_target_appearance(i), + p_target_name(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_mission_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE mission_objects Set + mission_objects.difficulty = nvl(p_difficulty(i),mission_objects.difficulty), + mission_objects.end_x = nvl(p_end_x(i),mission_objects.end_x), + mission_objects.end_y = nvl(p_end_y(i),mission_objects.end_y), + mission_objects.end_z = nvl(p_end_z(i),mission_objects.end_z), + mission_objects.end_cell = nvl(p_end_cell(i),mission_objects.end_cell), + mission_objects.end_scene = nvl(p_end_scene(i),mission_objects.end_scene), + mission_objects.mission_creator = nvl(p_mission_creator(i),mission_objects.mission_creator), + mission_objects.reward = nvl(p_reward(i),mission_objects.reward), + mission_objects.root_script_name = nvl(p_root_script_name(i),mission_objects.root_script_name), + mission_objects.start_x = nvl(p_start_x(i),mission_objects.start_x), + mission_objects.start_y = nvl(p_start_y(i),mission_objects.start_y), + mission_objects.start_z = nvl(p_start_z(i),mission_objects.start_z), + mission_objects.start_cell = nvl(p_start_cell(i),mission_objects.start_cell), + mission_objects.start_scene = nvl(p_start_scene(i),mission_objects.start_scene), + mission_objects.description_table = nvl(p_description_table(i),mission_objects.description_table), + mission_objects.description_text = nvl(p_description_text(i),mission_objects.description_text), + mission_objects.title_table = nvl(p_title_table(i),mission_objects.title_table), + mission_objects.title_text = nvl(p_title_text(i),mission_objects.title_text), + mission_objects.mission_holder_id = nvl(p_mission_holder_id(i),mission_objects.mission_holder_id), + mission_objects.status = nvl(p_status(i),mission_objects.status), + mission_objects.mission_type = nvl(p_mission_type(i),mission_objects.mission_type), + mission_objects.target_appearance = nvl(p_target_appearance(i),mission_objects.target_appearance), + mission_objects.target_name = nvl(p_target_name(i),mission_objects.target_name) + where + mission_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into mission_objects + ( + mission_objects.difficulty, + mission_objects.end_x, + mission_objects.end_y, + mission_objects.end_z, + mission_objects.end_cell, + mission_objects.end_scene, + mission_objects.mission_creator, + mission_objects.reward, + mission_objects.root_script_name, + mission_objects.start_x, + mission_objects.start_y, + mission_objects.start_z, + mission_objects.start_cell, + mission_objects.start_scene, + mission_objects.description_table, + mission_objects.description_text, + mission_objects.title_table, + mission_objects.title_text, + mission_objects.mission_holder_id, + mission_objects.status, + mission_objects.mission_type, + mission_objects.target_appearance, + mission_objects.target_name, + mission_objects.object_id + ) + VALUES + ( + p_difficulty(i), + p_end_x(i), + p_end_y(i), + p_end_z(i), + p_end_cell(i), + p_end_scene(i), + p_mission_creator(i), + p_reward(i), + p_root_script_name(i), + p_start_x(i), + p_start_y(i), + p_start_z(i), + p_start_cell(i), + p_start_scene(i), + p_description_table(i), + p_description_text(i), + p_title_table(i), + p_title_text(i), + p_mission_holder_id(i), + p_status(i), + p_mission_type(i), + p_target_appearance(i), + p_target_name(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into mission_objects + ( + mission_objects.difficulty, + mission_objects.end_x, + mission_objects.end_y, + mission_objects.end_z, + mission_objects.end_cell, + mission_objects.end_scene, + mission_objects.mission_creator, + mission_objects.reward, + mission_objects.root_script_name, + mission_objects.start_x, + mission_objects.start_y, + mission_objects.start_z, + mission_objects.start_cell, + mission_objects.start_scene, + mission_objects.description_table, + mission_objects.description_text, + mission_objects.title_table, + mission_objects.title_text, + mission_objects.mission_holder_id, + mission_objects.status, + mission_objects.mission_type, + mission_objects.target_appearance, + mission_objects.target_name, + mission_objects.object_id + ) + VALUES + ( + p_difficulty(i), + p_end_x(i), + p_end_y(i), + p_end_z(i), + p_end_cell(i), + p_end_scene(i), + p_mission_creator(i), + p_reward(i), + p_root_script_name(i), + p_start_x(i), + p_start_y(i), + p_start_z(i), + p_start_cell(i), + p_start_scene(i), + p_description_table(i), + p_description_text(i), + p_title_table(i), + p_title_text(i), + p_mission_holder_id(i), + p_status(i), + p_mission_type(i), + p_target_appearance(i), + p_target_name(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_mission_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_mission_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','difficulty','int',to_char(p_difficulty(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','end_x','float',to_char(p_end_x(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','end_y','float',to_char(p_end_y(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','end_z','float',to_char(p_end_z(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','end_cell','number',p_end_cell(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','end_scene','int',to_char(p_end_scene(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','mission_creator','varchar2',p_mission_creator(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','reward','int',to_char(p_reward(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','root_script_name','varchar2',p_root_script_name(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','start_x','float',to_char(p_start_x(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','start_y','float',to_char(p_start_y(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','start_z','float',to_char(p_start_z(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','start_cell','number',p_start_cell(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','start_scene','int',to_char(p_start_scene(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','description_table','varchar2',p_description_table(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','description_text','varchar2',p_description_text(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','title_table','varchar2',p_title_table(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','title_text','varchar2',p_title_text(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','mission_holder_id','number',p_mission_holder_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_mission_obj','status','int',to_char(p_status(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','mission_type','int',to_char(p_mission_type(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','target_appearance','int',to_char(p_target_appearance(m_error_index))); + db_error_logger.dblogerror_values('persister.add_mission_obj','target_name','varchar2',p_target_name(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_mission_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_mission_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete mission_objects + where + object_id=p_object_id(i); + end; + + procedure save_planet_obj( p_object_id VAOFSTRING, p_planet_name VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update planet_objects set + planet_objects.planet_name = nvl(p_planet_name(i),planet_objects.planet_name) + where + planet_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update planet_objects set + planet_objects.planet_name = nvl(p_planet_name(i),planet_objects.planet_name) + where + planet_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_planet_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_planet_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_planet_obj','planet_name','varchar',p_planet_name(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_planet_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_planet_obj( p_object_id VAOFSTRING, p_planet_name VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into planet_objects + ( + planet_objects.planet_name, + planet_objects.object_id + ) + VALUES + ( + p_planet_name(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_planet_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE planet_objects Set + planet_objects.planet_name = nvl(p_planet_name(i),planet_objects.planet_name) + where + planet_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into planet_objects + ( + planet_objects.planet_name, + planet_objects.object_id + ) + VALUES + ( + p_planet_name(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into planet_objects + ( + planet_objects.planet_name, + planet_objects.object_id + ) + VALUES + ( + p_planet_name(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_planet_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_planet_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_planet_obj','planet_name','varchar',p_planet_name(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_planet_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_planet_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete planet_objects + where + object_id=p_object_id(i); + end; + + procedure save_resource_container_obj( p_object_id VAOFSTRING, p_resource_type VAOFSTRING, p_quantity VAOFNUMBER, p_source VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update resource_container_objects set + resource_container_objects.resource_type = nvl(p_resource_type(i),resource_container_objects.resource_type), + resource_container_objects.quantity = nvl(p_quantity(i),resource_container_objects.quantity), + resource_container_objects.source = nvl(p_source(i),resource_container_objects.source) + where + resource_container_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update resource_container_objects set + resource_container_objects.resource_type = nvl(p_resource_type(i),resource_container_objects.resource_type), + resource_container_objects.quantity = nvl(p_quantity(i),resource_container_objects.quantity), + resource_container_objects.source = nvl(p_source(i),resource_container_objects.source) + where + resource_container_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_resource_container_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_resource_container_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_resource_container_obj','resource_type','number',p_resource_type(m_error_index)); + db_error_logger.dblogerror_values('persister.save_resource_container_obj','quantity','int',to_char(p_quantity(m_error_index))); + db_error_logger.dblogerror_values('persister.save_resource_container_obj','source','number',p_source(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_resource_container_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_resource_container_obj( p_object_id VAOFSTRING, p_resource_type VAOFSTRING, p_quantity VAOFNUMBER, p_source VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into resource_container_objects + ( + resource_container_objects.resource_type, + resource_container_objects.quantity, + resource_container_objects.source, + resource_container_objects.object_id + ) + VALUES + ( + p_resource_type(i), + p_quantity(i), + p_source(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_resource_container_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE resource_container_objects Set + resource_container_objects.resource_type = nvl(p_resource_type(i),resource_container_objects.resource_type), + resource_container_objects.quantity = nvl(p_quantity(i),resource_container_objects.quantity), + resource_container_objects.source = nvl(p_source(i),resource_container_objects.source) + where + resource_container_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into resource_container_objects + ( + resource_container_objects.resource_type, + resource_container_objects.quantity, + resource_container_objects.source, + resource_container_objects.object_id + ) + VALUES + ( + p_resource_type(i), + p_quantity(i), + p_source(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into resource_container_objects + ( + resource_container_objects.resource_type, + resource_container_objects.quantity, + resource_container_objects.source, + resource_container_objects.object_id + ) + VALUES + ( + p_resource_type(i), + p_quantity(i), + p_source(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_resource_container_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_resource_container_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_resource_container_obj','resource_type','number',p_resource_type(m_error_index)); + db_error_logger.dblogerror_values('persister.add_resource_container_obj','quantity','int',to_char(p_quantity(m_error_index))); + db_error_logger.dblogerror_values('persister.add_resource_container_obj','source','number',p_source(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_resource_container_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_resource_container_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete resource_container_objects + where + object_id=p_object_id(i); + end; + + procedure save_ship_obj(p_object_id VAOFSTRING, p_slide_dampener VAOFNUMBER, p_current_chassis_hit_points VAOFNUMBER, p_maximum_chassis_hit_points VAOFNUMBER, p_chassis_type VAOFNUMBER, p_cmp_armor_hp_maximum VAOFSTRING, p_cmp_armor_hp_current VAOFSTRING, p_cmp_efficiency_general VAOFSTRING, p_cmp_efficiency_eng VAOFSTRING, p_cmp_eng_maintenance VAOFSTRING, p_cmp_mass VAOFSTRING, p_cmp_crc VAOFSTRING, p_cmp_hp_current VAOFSTRING, p_cmp_hp_maximum VAOFSTRING, p_cmp_flags VAOFSTRING, p_cmp_names VAOFLONGSTRING, p_weapon_damage_maximum VAOFSTRING, p_weapon_damage_minimum VAOFSTRING, p_weapon_effectiveness_shields VAOFSTRING, p_weapon_effectiveness_armor VAOFSTRING, p_weapon_eng_per_shot VAOFSTRING, p_weapon_refire_rate VAOFSTRING, p_weapon_ammo_current VAOFSTRING, p_weapon_ammo_maximum VAOFSTRING, p_weapon_ammo_type VAOFSTRING, p_shield_hp_front_maximum VAOFNUMBER, p_shield_hp_back_maximum VAOFNUMBER, p_shield_recharge_rate VAOFNUMBER, p_capacitor_eng_maximum VAOFNUMBER, p_capacitor_eng_recharge_rate VAOFNUMBER, p_engine_acc_rate VAOFNUMBER, p_engine_deceleration_rate VAOFNUMBER, p_engine_pitch_acc_rate VAOFNUMBER, p_engine_yaw_acc_rate VAOFNUMBER, p_engine_roll_acc_rate VAOFNUMBER, p_engine_pitch_rate_maximum VAOFNUMBER, p_engine_yaw_rate_maximum VAOFNUMBER, p_engine_roll_rate_maximum VAOFNUMBER, p_engine_speed_maximum VAOFNUMBER, p_reactor_eng_generation_rate VAOFNUMBER, p_booster_eng_maximum VAOFNUMBER, p_booster_eng_recharge_rate VAOFNUMBER, p_booster_eng_consumption_rate VAOFNUMBER, p_booster_acc VAOFNUMBER, p_booster_speed_maximum VAOFNUMBER, p_droid_if_cmd_speed VAOFNUMBER, p_installed_dcd VAOFSTRING, p_chassis_cmp_mass_maximum VAOFNUMBER, p_cmp_creators VAOFSTRING, p_cargo_hold_contents_maximum VAOFNUMBER, p_cargo_hold_contents_current VAOFNUMBER, p_cargo_hold_contents VAOFSTRING, p_chunk_size number) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update ship_objects set + ship_objects.slide_dampener = nvl(p_slide_dampener(i),ship_objects.slide_dampener), + ship_objects.current_chassis_hit_points = nvl(p_current_chassis_hit_points(i),ship_objects.current_chassis_hit_points), + ship_objects.maximum_chassis_hit_points = nvl(p_maximum_chassis_hit_points(i),ship_objects.maximum_chassis_hit_points), + ship_objects.chassis_type = nvl(p_chassis_type(i),ship_objects.chassis_type), + ship_objects.cmp_armor_hp_maximum = nvl(p_cmp_armor_hp_maximum(i),ship_objects.cmp_armor_hp_maximum), + ship_objects.cmp_armor_hp_current = nvl(p_cmp_armor_hp_current(i),ship_objects.cmp_armor_hp_current), + ship_objects.cmp_efficiency_general = nvl(p_cmp_efficiency_general(i),ship_objects.cmp_efficiency_general), + ship_objects.cmp_efficiency_eng = nvl(p_cmp_efficiency_eng(i),ship_objects.cmp_efficiency_eng), + ship_objects.cmp_eng_maintenance = nvl(p_cmp_eng_maintenance(i),ship_objects.cmp_eng_maintenance), + ship_objects.cmp_mass = nvl(p_cmp_mass(i),ship_objects.cmp_mass), + ship_objects.cmp_crc = nvl(p_cmp_crc(i),ship_objects.cmp_crc), + ship_objects.cmp_hp_current = nvl(p_cmp_hp_current(i),ship_objects.cmp_hp_current), + ship_objects.cmp_hp_maximum = nvl(p_cmp_hp_maximum(i),ship_objects.cmp_hp_maximum), + ship_objects.cmp_flags = nvl(p_cmp_flags(i),ship_objects.cmp_flags), + ship_objects.cmp_names = nvl(p_cmp_names(i),ship_objects.cmp_names), + ship_objects.weapon_damage_maximum = nvl(p_weapon_damage_maximum(i),ship_objects.weapon_damage_maximum), + ship_objects.weapon_damage_minimum = nvl(p_weapon_damage_minimum(i),ship_objects.weapon_damage_minimum), + ship_objects.weapon_effectiveness_shields = nvl(p_weapon_effectiveness_shields(i),ship_objects.weapon_effectiveness_shields), + ship_objects.weapon_effectiveness_armor = nvl(p_weapon_effectiveness_armor(i),ship_objects.weapon_effectiveness_armor), + ship_objects.weapon_eng_per_shot = nvl(p_weapon_eng_per_shot(i),ship_objects.weapon_eng_per_shot), + ship_objects.weapon_refire_rate = nvl(p_weapon_refire_rate(i),ship_objects.weapon_refire_rate), + ship_objects.weapon_ammo_current = nvl(p_weapon_ammo_current(i),ship_objects.weapon_ammo_current), + ship_objects.weapon_ammo_maximum = nvl(p_weapon_ammo_maximum(i),ship_objects.weapon_ammo_maximum), + ship_objects.weapon_ammo_type = nvl(p_weapon_ammo_type(i),ship_objects.weapon_ammo_type), + ship_objects.shield_hp_front_maximum = nvl(p_shield_hp_front_maximum(i),ship_objects.shield_hp_front_maximum), + ship_objects.shield_hp_back_maximum = nvl(p_shield_hp_back_maximum(i),ship_objects.shield_hp_back_maximum), + ship_objects.shield_recharge_rate = nvl(p_shield_recharge_rate(i),ship_objects.shield_recharge_rate), + ship_objects.capacitor_eng_maximum = nvl(p_capacitor_eng_maximum(i),ship_objects.capacitor_eng_maximum), + ship_objects.capacitor_eng_recharge_rate = nvl(p_capacitor_eng_recharge_rate(i),ship_objects.capacitor_eng_recharge_rate), + ship_objects.engine_acc_rate = nvl(p_engine_acc_rate(i),ship_objects.engine_acc_rate), + ship_objects.engine_deceleration_rate = nvl(p_engine_deceleration_rate(i),ship_objects.engine_deceleration_rate), + ship_objects.engine_pitch_acc_rate = nvl(p_engine_pitch_acc_rate(i),ship_objects.engine_pitch_acc_rate), + ship_objects.engine_yaw_acc_rate = nvl(p_engine_yaw_acc_rate(i),ship_objects.engine_yaw_acc_rate), + ship_objects.engine_roll_acc_rate = nvl(p_engine_roll_acc_rate(i),ship_objects.engine_roll_acc_rate), + ship_objects.engine_pitch_rate_maximum = nvl(p_engine_pitch_rate_maximum(i),ship_objects.engine_pitch_rate_maximum), + ship_objects.engine_yaw_rate_maximum = nvl(p_engine_yaw_rate_maximum(i),ship_objects.engine_yaw_rate_maximum), + ship_objects.engine_roll_rate_maximum = nvl(p_engine_roll_rate_maximum(i),ship_objects.engine_roll_rate_maximum), + ship_objects.engine_speed_maximum = nvl(p_engine_speed_maximum(i),ship_objects.engine_speed_maximum), + ship_objects.reactor_eng_generation_rate = nvl(p_reactor_eng_generation_rate(i),ship_objects.reactor_eng_generation_rate), + ship_objects.booster_eng_maximum = nvl(p_booster_eng_maximum(i),ship_objects.booster_eng_maximum), + ship_objects.booster_eng_recharge_rate = nvl(p_booster_eng_recharge_rate(i),ship_objects.booster_eng_recharge_rate), + ship_objects.booster_eng_consumption_rate = nvl(p_booster_eng_consumption_rate(i),ship_objects.booster_eng_consumption_rate), + ship_objects.booster_acc = nvl(p_booster_acc(i),ship_objects.booster_acc), + ship_objects.booster_speed_maximum = nvl(p_booster_speed_maximum(i),ship_objects.booster_speed_maximum), + ship_objects.droid_if_cmd_speed = nvl(p_droid_if_cmd_speed(i),ship_objects.droid_if_cmd_speed), + ship_objects.installed_dcd = nvl(p_installed_dcd(i),ship_objects.installed_dcd), + ship_objects.chassis_cmp_mass_maximum = nvl(p_chassis_cmp_mass_maximum(i),ship_objects.chassis_cmp_mass_maximum), + ship_objects.cmp_creators = nvl(p_cmp_creators(i),ship_objects.cmp_creators), + ship_objects.cargo_hold_contents_maximum = nvl(p_cargo_hold_contents_maximum(i),ship_objects.cargo_hold_contents_maximum), + ship_objects.cargo_hold_contents_current = nvl(p_cargo_hold_contents_current(i),ship_objects.cargo_hold_contents_current), + ship_objects.cargo_hold_contents = nvl(p_cargo_hold_contents(i),ship_objects.cargo_hold_contents) + where + ship_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update ship_objects set + ship_objects.slide_dampener = nvl(p_slide_dampener(i),ship_objects.slide_dampener), + ship_objects.current_chassis_hit_points = nvl(p_current_chassis_hit_points(i),ship_objects.current_chassis_hit_points), + ship_objects.maximum_chassis_hit_points = nvl(p_maximum_chassis_hit_points(i),ship_objects.maximum_chassis_hit_points), + ship_objects.chassis_type = nvl(p_chassis_type(i),ship_objects.chassis_type), + ship_objects.cmp_armor_hp_maximum = nvl(p_cmp_armor_hp_maximum(i),ship_objects.cmp_armor_hp_maximum), + ship_objects.cmp_armor_hp_current = nvl(p_cmp_armor_hp_current(i),ship_objects.cmp_armor_hp_current), + ship_objects.cmp_efficiency_general = nvl(p_cmp_efficiency_general(i),ship_objects.cmp_efficiency_general), + ship_objects.cmp_efficiency_eng = nvl(p_cmp_efficiency_eng(i),ship_objects.cmp_efficiency_eng), + ship_objects.cmp_eng_maintenance = nvl(p_cmp_eng_maintenance(i),ship_objects.cmp_eng_maintenance), + ship_objects.cmp_mass = nvl(p_cmp_mass(i),ship_objects.cmp_mass), + ship_objects.cmp_crc = nvl(p_cmp_crc(i),ship_objects.cmp_crc), + ship_objects.cmp_hp_current = nvl(p_cmp_hp_current(i),ship_objects.cmp_hp_current), + ship_objects.cmp_hp_maximum = nvl(p_cmp_hp_maximum(i),ship_objects.cmp_hp_maximum), + ship_objects.cmp_flags = nvl(p_cmp_flags(i),ship_objects.cmp_flags), + ship_objects.cmp_names = nvl(p_cmp_names(i),ship_objects.cmp_names), + ship_objects.weapon_damage_maximum = nvl(p_weapon_damage_maximum(i),ship_objects.weapon_damage_maximum), + ship_objects.weapon_damage_minimum = nvl(p_weapon_damage_minimum(i),ship_objects.weapon_damage_minimum), + ship_objects.weapon_effectiveness_shields = nvl(p_weapon_effectiveness_shields(i),ship_objects.weapon_effectiveness_shields), + ship_objects.weapon_effectiveness_armor = nvl(p_weapon_effectiveness_armor(i),ship_objects.weapon_effectiveness_armor), + ship_objects.weapon_eng_per_shot = nvl(p_weapon_eng_per_shot(i),ship_objects.weapon_eng_per_shot), + ship_objects.weapon_refire_rate = nvl(p_weapon_refire_rate(i),ship_objects.weapon_refire_rate), + ship_objects.weapon_ammo_current = nvl(p_weapon_ammo_current(i),ship_objects.weapon_ammo_current), + ship_objects.weapon_ammo_maximum = nvl(p_weapon_ammo_maximum(i),ship_objects.weapon_ammo_maximum), + ship_objects.weapon_ammo_type = nvl(p_weapon_ammo_type(i),ship_objects.weapon_ammo_type), + ship_objects.shield_hp_front_maximum = nvl(p_shield_hp_front_maximum(i),ship_objects.shield_hp_front_maximum), + ship_objects.shield_hp_back_maximum = nvl(p_shield_hp_back_maximum(i),ship_objects.shield_hp_back_maximum), + ship_objects.shield_recharge_rate = nvl(p_shield_recharge_rate(i),ship_objects.shield_recharge_rate), + ship_objects.capacitor_eng_maximum = nvl(p_capacitor_eng_maximum(i),ship_objects.capacitor_eng_maximum), + ship_objects.capacitor_eng_recharge_rate = nvl(p_capacitor_eng_recharge_rate(i),ship_objects.capacitor_eng_recharge_rate), + ship_objects.engine_acc_rate = nvl(p_engine_acc_rate(i),ship_objects.engine_acc_rate), + ship_objects.engine_deceleration_rate = nvl(p_engine_deceleration_rate(i),ship_objects.engine_deceleration_rate), + ship_objects.engine_pitch_acc_rate = nvl(p_engine_pitch_acc_rate(i),ship_objects.engine_pitch_acc_rate), + ship_objects.engine_yaw_acc_rate = nvl(p_engine_yaw_acc_rate(i),ship_objects.engine_yaw_acc_rate), + ship_objects.engine_roll_acc_rate = nvl(p_engine_roll_acc_rate(i),ship_objects.engine_roll_acc_rate), + ship_objects.engine_pitch_rate_maximum = nvl(p_engine_pitch_rate_maximum(i),ship_objects.engine_pitch_rate_maximum), + ship_objects.engine_yaw_rate_maximum = nvl(p_engine_yaw_rate_maximum(i),ship_objects.engine_yaw_rate_maximum), + ship_objects.engine_roll_rate_maximum = nvl(p_engine_roll_rate_maximum(i),ship_objects.engine_roll_rate_maximum), + ship_objects.engine_speed_maximum = nvl(p_engine_speed_maximum(i),ship_objects.engine_speed_maximum), + ship_objects.reactor_eng_generation_rate = nvl(p_reactor_eng_generation_rate(i),ship_objects.reactor_eng_generation_rate), + ship_objects.booster_eng_maximum = nvl(p_booster_eng_maximum(i),ship_objects.booster_eng_maximum), + ship_objects.booster_eng_recharge_rate = nvl(p_booster_eng_recharge_rate(i),ship_objects.booster_eng_recharge_rate), + ship_objects.booster_eng_consumption_rate = nvl(p_booster_eng_consumption_rate(i),ship_objects.booster_eng_consumption_rate), + ship_objects.booster_acc = nvl(p_booster_acc(i),ship_objects.booster_acc), + ship_objects.booster_speed_maximum = nvl(p_booster_speed_maximum(i),ship_objects.booster_speed_maximum), + ship_objects.droid_if_cmd_speed = nvl(p_droid_if_cmd_speed(i),ship_objects.droid_if_cmd_speed), + ship_objects.installed_dcd = nvl(p_installed_dcd(i),ship_objects.installed_dcd), + ship_objects.chassis_cmp_mass_maximum = nvl(p_chassis_cmp_mass_maximum(i),ship_objects.chassis_cmp_mass_maximum), + ship_objects.cmp_creators = nvl(p_cmp_creators(i),ship_objects.cmp_creators), + ship_objects.cargo_hold_contents_maximum = nvl(p_cargo_hold_contents_maximum(i),ship_objects.cargo_hold_contents_maximum), + ship_objects.cargo_hold_contents_current = nvl(p_cargo_hold_contents_current(i),ship_objects.cargo_hold_contents_current), + ship_objects.cargo_hold_contents = nvl(p_cargo_hold_contents(i),ship_objects.cargo_hold_contents) + where + ship_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_ship_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_ship_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','slide_dampener','float',to_char(p_slide_dampener(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','current_chassis_hit_points','float',to_char(p_current_chassis_hit_points(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','maximum_chassis_hit_points','float',to_char(p_maximum_chassis_hit_points(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','chassis_type','int',to_char(p_chassis_type(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_armor_hp_maximum','varchar2',p_cmp_armor_hp_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_armor_hp_current','varchar2',p_cmp_armor_hp_current(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_efficiency_general','varchar2',p_cmp_efficiency_general(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_efficiency_eng','varchar2',p_cmp_efficiency_eng(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_eng_maintenance','varchar2',p_cmp_eng_maintenance(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_mass','varchar2',p_cmp_mass(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_crc','varchar2',p_cmp_crc(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_hp_current','varchar2',p_cmp_hp_current(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_hp_maximum','varchar2',p_cmp_hp_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_flags','varchar2',p_cmp_flags(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_names','varchar2',p_cmp_names(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_damage_maximum','varchar2',p_weapon_damage_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_damage_minimum','varchar2',p_weapon_damage_minimum(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_effectiveness_shields','varchar2',p_weapon_effectiveness_shields(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_effectiveness_armor','varchar2',p_weapon_effectiveness_armor(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_eng_per_shot','varchar2',p_weapon_eng_per_shot(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_refire_rate','varchar2',p_weapon_refire_rate(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_ammo_current','varchar2',p_weapon_ammo_current(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_ammo_maximum','varchar2',p_weapon_ammo_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','weapon_ammo_type','varchar2',p_weapon_ammo_type(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','shield_hp_front_maximum','float',to_char(p_shield_hp_front_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','shield_hp_back_maximum','float',to_char(p_shield_hp_back_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','shield_recharge_rate','float',to_char(p_shield_recharge_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','capacitor_eng_maximum','float',to_char(p_capacitor_eng_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','capacitor_eng_recharge_rate','float',to_char(p_capacitor_eng_recharge_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_acc_rate','float',to_char(p_engine_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_deceleration_rate','float',to_char(p_engine_deceleration_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_pitch_acc_rate','float',to_char(p_engine_pitch_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_yaw_acc_rate','float',to_char(p_engine_yaw_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_roll_acc_rate','float',to_char(p_engine_roll_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_pitch_rate_maximum','float',to_char(p_engine_pitch_rate_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_yaw_rate_maximum','float',to_char(p_engine_yaw_rate_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_roll_rate_maximum','float',to_char(p_engine_roll_rate_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','engine_speed_maximum','float',to_char(p_engine_speed_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','reactor_eng_generation_rate','float',to_char(p_reactor_eng_generation_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','booster_eng_maximum','float',to_char(p_booster_eng_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','booster_eng_recharge_rate','float',to_char(p_booster_eng_recharge_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','booster_eng_consumption_rate','float',to_char(p_booster_eng_consumption_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','booster_acc','float',to_char(p_booster_acc(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','booster_speed_maximum','float',to_char(p_booster_speed_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','droid_if_cmd_speed','float',to_char(p_droid_if_cmd_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','installed_dcd','number',p_installed_dcd(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','chassis_cmp_mass_maximum','float',to_char(p_chassis_cmp_mass_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','cmp_creators','varchar2',p_cmp_creators(m_error_index)); + db_error_logger.dblogerror_values('persister.save_ship_obj','cargo_hold_contents_maximum','number',to_char(p_cargo_hold_contents_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','cargo_hold_contents_current','number',to_char(p_cargo_hold_contents_current(m_error_index))); + db_error_logger.dblogerror_values('persister.save_ship_obj','cargo_hold_contents','varchar2',p_cargo_hold_contents(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_ship_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_ship_obj(p_object_id VAOFSTRING, p_slide_dampener VAOFNUMBER, p_current_chassis_hit_points VAOFNUMBER, p_maximum_chassis_hit_points VAOFNUMBER, p_chassis_type VAOFNUMBER, p_cmp_armor_hp_maximum VAOFSTRING, p_cmp_armor_hp_current VAOFSTRING, p_cmp_efficiency_general VAOFSTRING, p_cmp_efficiency_eng VAOFSTRING, p_cmp_eng_maintenance VAOFSTRING, p_cmp_mass VAOFSTRING, p_cmp_crc VAOFSTRING, p_cmp_hp_current VAOFSTRING, p_cmp_hp_maximum VAOFSTRING, p_cmp_flags VAOFSTRING, p_cmp_names VAOFLONGSTRING, p_weapon_damage_maximum VAOFSTRING, p_weapon_damage_minimum VAOFSTRING, p_weapon_effectiveness_shields VAOFSTRING, p_weapon_effectiveness_armor VAOFSTRING, p_weapon_eng_per_shot VAOFSTRING, p_weapon_refire_rate VAOFSTRING, p_weapon_ammo_current VAOFSTRING, p_weapon_ammo_maximum VAOFSTRING, p_weapon_ammo_type VAOFSTRING, p_shield_hp_front_maximum VAOFNUMBER, p_shield_hp_back_maximum VAOFNUMBER, p_shield_recharge_rate VAOFNUMBER, p_capacitor_eng_maximum VAOFNUMBER, p_capacitor_eng_recharge_rate VAOFNUMBER, p_engine_acc_rate VAOFNUMBER, p_engine_deceleration_rate VAOFNUMBER, p_engine_pitch_acc_rate VAOFNUMBER, p_engine_yaw_acc_rate VAOFNUMBER, p_engine_roll_acc_rate VAOFNUMBER, p_engine_pitch_rate_maximum VAOFNUMBER, p_engine_yaw_rate_maximum VAOFNUMBER, p_engine_roll_rate_maximum VAOFNUMBER, p_engine_speed_maximum VAOFNUMBER, p_reactor_eng_generation_rate VAOFNUMBER, p_booster_eng_maximum VAOFNUMBER, p_booster_eng_recharge_rate VAOFNUMBER, p_booster_eng_consumption_rate VAOFNUMBER, p_booster_acc VAOFNUMBER, p_booster_speed_maximum VAOFNUMBER, p_droid_if_cmd_speed VAOFNUMBER, p_installed_dcd VAOFSTRING, p_chassis_cmp_mass_maximum VAOFNUMBER, p_cmp_creators VAOFSTRING, p_cargo_hold_contents_maximum VAOFNUMBER, p_cargo_hold_contents_current VAOFNUMBER, p_cargo_hold_contents VAOFSTRING, p_chunk_size number) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into ship_objects + ( + ship_objects.slide_dampener, + ship_objects.current_chassis_hit_points, + ship_objects.maximum_chassis_hit_points, + ship_objects.chassis_type, + ship_objects.cmp_armor_hp_maximum, + ship_objects.cmp_armor_hp_current, + ship_objects.cmp_efficiency_general, + ship_objects.cmp_efficiency_eng, + ship_objects.cmp_eng_maintenance, + ship_objects.cmp_mass, + ship_objects.cmp_crc, + ship_objects.cmp_hp_current, + ship_objects.cmp_hp_maximum, + ship_objects.cmp_flags, + ship_objects.cmp_names, + ship_objects.weapon_damage_maximum, + ship_objects.weapon_damage_minimum, + ship_objects.weapon_effectiveness_shields, + ship_objects.weapon_effectiveness_armor, + ship_objects.weapon_eng_per_shot, + ship_objects.weapon_refire_rate, + ship_objects.weapon_ammo_current, + ship_objects.weapon_ammo_maximum, + ship_objects.weapon_ammo_type, + ship_objects.shield_hp_front_maximum, + ship_objects.shield_hp_back_maximum, + ship_objects.shield_recharge_rate, + ship_objects.capacitor_eng_maximum, + ship_objects.capacitor_eng_recharge_rate, + ship_objects.engine_acc_rate, + ship_objects.engine_deceleration_rate, + ship_objects.engine_pitch_acc_rate, + ship_objects.engine_yaw_acc_rate, + ship_objects.engine_roll_acc_rate, + ship_objects.engine_pitch_rate_maximum, + ship_objects.engine_yaw_rate_maximum, + ship_objects.engine_roll_rate_maximum, + ship_objects.engine_speed_maximum, + ship_objects.reactor_eng_generation_rate, + ship_objects.booster_eng_maximum, + ship_objects.booster_eng_recharge_rate, + ship_objects.booster_eng_consumption_rate, + ship_objects.booster_acc, + ship_objects.booster_speed_maximum, + ship_objects.droid_if_cmd_speed, + ship_objects.installed_dcd, + ship_objects.chassis_cmp_mass_maximum, + ship_objects.cmp_creators, + ship_objects.cargo_hold_contents_maximum, + ship_objects.cargo_hold_contents_current, + ship_objects.cargo_hold_contents, + ship_objects.object_id + ) + VALUES + ( + p_slide_dampener(i), + p_current_chassis_hit_points(i), + p_maximum_chassis_hit_points(i), + p_chassis_type(i), + p_cmp_armor_hp_maximum(i), + p_cmp_armor_hp_current(i), + p_cmp_efficiency_general(i), + p_cmp_efficiency_eng(i), + p_cmp_eng_maintenance(i), + p_cmp_mass(i), + p_cmp_crc(i), + p_cmp_hp_current(i), + p_cmp_hp_maximum(i), + p_cmp_flags(i), + p_cmp_names(i), + p_weapon_damage_maximum(i), + p_weapon_damage_minimum(i), + p_weapon_effectiveness_shields(i), + p_weapon_effectiveness_armor(i), + p_weapon_eng_per_shot(i), + p_weapon_refire_rate(i), + p_weapon_ammo_current(i), + p_weapon_ammo_maximum(i), + p_weapon_ammo_type(i), + p_shield_hp_front_maximum(i), + p_shield_hp_back_maximum(i), + p_shield_recharge_rate(i), + p_capacitor_eng_maximum(i), + p_capacitor_eng_recharge_rate(i), + p_engine_acc_rate(i), + p_engine_deceleration_rate(i), + p_engine_pitch_acc_rate(i), + p_engine_yaw_acc_rate(i), + p_engine_roll_acc_rate(i), + p_engine_pitch_rate_maximum(i), + p_engine_yaw_rate_maximum(i), + p_engine_roll_rate_maximum(i), + p_engine_speed_maximum(i), + p_reactor_eng_generation_rate(i), + p_booster_eng_maximum(i), + p_booster_eng_recharge_rate(i), + p_booster_eng_consumption_rate(i), + p_booster_acc(i), + p_booster_speed_maximum(i), + p_droid_if_cmd_speed(i), + p_installed_dcd(i), + p_chassis_cmp_mass_maximum(i), + p_cmp_creators(i), + p_cargo_hold_contents_maximum(i), + p_cargo_hold_contents_current(i), + p_cargo_hold_contents(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_ship_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE ship_objects Set + ship_objects.slide_dampener = nvl(p_slide_dampener(i),ship_objects.slide_dampener), + ship_objects.current_chassis_hit_points = nvl(p_current_chassis_hit_points(i),ship_objects.current_chassis_hit_points), + ship_objects.maximum_chassis_hit_points = nvl(p_maximum_chassis_hit_points(i),ship_objects.maximum_chassis_hit_points), + ship_objects.chassis_type = nvl(p_chassis_type(i),ship_objects.chassis_type), + ship_objects.cmp_armor_hp_maximum = nvl(p_cmp_armor_hp_maximum(i),ship_objects.cmp_armor_hp_maximum), + ship_objects.cmp_armor_hp_current = nvl(p_cmp_armor_hp_current(i),ship_objects.cmp_armor_hp_current), + ship_objects.cmp_efficiency_general = nvl(p_cmp_efficiency_general(i),ship_objects.cmp_efficiency_general), + ship_objects.cmp_efficiency_eng = nvl(p_cmp_efficiency_eng(i),ship_objects.cmp_efficiency_eng), + ship_objects.cmp_eng_maintenance = nvl(p_cmp_eng_maintenance(i),ship_objects.cmp_eng_maintenance), + ship_objects.cmp_mass = nvl(p_cmp_mass(i),ship_objects.cmp_mass), + ship_objects.cmp_crc = nvl(p_cmp_crc(i),ship_objects.cmp_crc), + ship_objects.cmp_hp_current = nvl(p_cmp_hp_current(i),ship_objects.cmp_hp_current), + ship_objects.cmp_hp_maximum = nvl(p_cmp_hp_maximum(i),ship_objects.cmp_hp_maximum), + ship_objects.cmp_flags = nvl(p_cmp_flags(i),ship_objects.cmp_flags), + ship_objects.cmp_names = nvl(p_cmp_names(i),ship_objects.cmp_names), + ship_objects.weapon_damage_maximum = nvl(p_weapon_damage_maximum(i),ship_objects.weapon_damage_maximum), + ship_objects.weapon_damage_minimum = nvl(p_weapon_damage_minimum(i),ship_objects.weapon_damage_minimum), + ship_objects.weapon_effectiveness_shields = nvl(p_weapon_effectiveness_shields(i),ship_objects.weapon_effectiveness_shields), + ship_objects.weapon_effectiveness_armor = nvl(p_weapon_effectiveness_armor(i),ship_objects.weapon_effectiveness_armor), + ship_objects.weapon_eng_per_shot = nvl(p_weapon_eng_per_shot(i),ship_objects.weapon_eng_per_shot), + ship_objects.weapon_refire_rate = nvl(p_weapon_refire_rate(i),ship_objects.weapon_refire_rate), + ship_objects.weapon_ammo_current = nvl(p_weapon_ammo_current(i),ship_objects.weapon_ammo_current), + ship_objects.weapon_ammo_maximum = nvl(p_weapon_ammo_maximum(i),ship_objects.weapon_ammo_maximum), + ship_objects.weapon_ammo_type = nvl(p_weapon_ammo_type(i),ship_objects.weapon_ammo_type), + ship_objects.shield_hp_front_maximum = nvl(p_shield_hp_front_maximum(i),ship_objects.shield_hp_front_maximum), + ship_objects.shield_hp_back_maximum = nvl(p_shield_hp_back_maximum(i),ship_objects.shield_hp_back_maximum), + ship_objects.shield_recharge_rate = nvl(p_shield_recharge_rate(i),ship_objects.shield_recharge_rate), + ship_objects.capacitor_eng_maximum = nvl(p_capacitor_eng_maximum(i),ship_objects.capacitor_eng_maximum), + ship_objects.capacitor_eng_recharge_rate = nvl(p_capacitor_eng_recharge_rate(i),ship_objects.capacitor_eng_recharge_rate), + ship_objects.engine_acc_rate = nvl(p_engine_acc_rate(i),ship_objects.engine_acc_rate), + ship_objects.engine_deceleration_rate = nvl(p_engine_deceleration_rate(i),ship_objects.engine_deceleration_rate), + ship_objects.engine_pitch_acc_rate = nvl(p_engine_pitch_acc_rate(i),ship_objects.engine_pitch_acc_rate), + ship_objects.engine_yaw_acc_rate = nvl(p_engine_yaw_acc_rate(i),ship_objects.engine_yaw_acc_rate), + ship_objects.engine_roll_acc_rate = nvl(p_engine_roll_acc_rate(i),ship_objects.engine_roll_acc_rate), + ship_objects.engine_pitch_rate_maximum = nvl(p_engine_pitch_rate_maximum(i),ship_objects.engine_pitch_rate_maximum), + ship_objects.engine_yaw_rate_maximum = nvl(p_engine_yaw_rate_maximum(i),ship_objects.engine_yaw_rate_maximum), + ship_objects.engine_roll_rate_maximum = nvl(p_engine_roll_rate_maximum(i),ship_objects.engine_roll_rate_maximum), + ship_objects.engine_speed_maximum = nvl(p_engine_speed_maximum(i),ship_objects.engine_speed_maximum), + ship_objects.reactor_eng_generation_rate = nvl(p_reactor_eng_generation_rate(i),ship_objects.reactor_eng_generation_rate), + ship_objects.booster_eng_maximum = nvl(p_booster_eng_maximum(i),ship_objects.booster_eng_maximum), + ship_objects.booster_eng_recharge_rate = nvl(p_booster_eng_recharge_rate(i),ship_objects.booster_eng_recharge_rate), + ship_objects.booster_eng_consumption_rate = nvl(p_booster_eng_consumption_rate(i),ship_objects.booster_eng_consumption_rate), + ship_objects.booster_acc = nvl(p_booster_acc(i),ship_objects.booster_acc), + ship_objects.booster_speed_maximum = nvl(p_booster_speed_maximum(i),ship_objects.booster_speed_maximum), + ship_objects.droid_if_cmd_speed = nvl(p_droid_if_cmd_speed(i),ship_objects.droid_if_cmd_speed), + ship_objects.installed_dcd = nvl(p_installed_dcd(i),ship_objects.installed_dcd), + ship_objects.chassis_cmp_mass_maximum = nvl(p_chassis_cmp_mass_maximum(i),ship_objects.chassis_cmp_mass_maximum), + ship_objects.cmp_creators = nvl(p_cmp_creators(i),ship_objects.cmp_creators), + ship_objects.cargo_hold_contents_maximum = nvl(p_cargo_hold_contents_maximum(i),ship_objects.cargo_hold_contents_maximum), + ship_objects.cargo_hold_contents_current = nvl(p_cargo_hold_contents_current(i),ship_objects.cargo_hold_contents_current), + ship_objects.cargo_hold_contents = nvl(p_cargo_hold_contents(i),ship_objects.cargo_hold_contents) + where + ship_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into ship_objects + ( + ship_objects.slide_dampener, + ship_objects.current_chassis_hit_points, + ship_objects.maximum_chassis_hit_points, + ship_objects.chassis_type, + ship_objects.cmp_armor_hp_maximum, + ship_objects.cmp_armor_hp_current, + ship_objects.cmp_efficiency_general, + ship_objects.cmp_efficiency_eng, + ship_objects.cmp_eng_maintenance, + ship_objects.cmp_mass, + ship_objects.cmp_crc, + ship_objects.cmp_hp_current, + ship_objects.cmp_hp_maximum, + ship_objects.cmp_flags, + ship_objects.cmp_names, + ship_objects.weapon_damage_maximum, + ship_objects.weapon_damage_minimum, + ship_objects.weapon_effectiveness_shields, + ship_objects.weapon_effectiveness_armor, + ship_objects.weapon_eng_per_shot, + ship_objects.weapon_refire_rate, + ship_objects.weapon_ammo_current, + ship_objects.weapon_ammo_maximum, + ship_objects.weapon_ammo_type, + ship_objects.shield_hp_front_maximum, + ship_objects.shield_hp_back_maximum, + ship_objects.shield_recharge_rate, + ship_objects.capacitor_eng_maximum, + ship_objects.capacitor_eng_recharge_rate, + ship_objects.engine_acc_rate, + ship_objects.engine_deceleration_rate, + ship_objects.engine_pitch_acc_rate, + ship_objects.engine_yaw_acc_rate, + ship_objects.engine_roll_acc_rate, + ship_objects.engine_pitch_rate_maximum, + ship_objects.engine_yaw_rate_maximum, + ship_objects.engine_roll_rate_maximum, + ship_objects.engine_speed_maximum, + ship_objects.reactor_eng_generation_rate, + ship_objects.booster_eng_maximum, + ship_objects.booster_eng_recharge_rate, + ship_objects.booster_eng_consumption_rate, + ship_objects.booster_acc, + ship_objects.booster_speed_maximum, + ship_objects.droid_if_cmd_speed, + ship_objects.installed_dcd, + ship_objects.chassis_cmp_mass_maximum, + ship_objects.cmp_creators, + ship_objects.cargo_hold_contents_maximum, + ship_objects.cargo_hold_contents_current, + ship_objects.cargo_hold_contents, + ship_objects.object_id + ) + VALUES + ( + p_slide_dampener(i), + p_current_chassis_hit_points(i), + p_maximum_chassis_hit_points(i), + p_chassis_type(i), + p_cmp_armor_hp_maximum(i), + p_cmp_armor_hp_current(i), + p_cmp_efficiency_general(i), + p_cmp_efficiency_eng(i), + p_cmp_eng_maintenance(i), + p_cmp_mass(i), + p_cmp_crc(i), + p_cmp_hp_current(i), + p_cmp_hp_maximum(i), + p_cmp_flags(i), + p_cmp_names(i), + p_weapon_damage_maximum(i), + p_weapon_damage_minimum(i), + p_weapon_effectiveness_shields(i), + p_weapon_effectiveness_armor(i), + p_weapon_eng_per_shot(i), + p_weapon_refire_rate(i), + p_weapon_ammo_current(i), + p_weapon_ammo_maximum(i), + p_weapon_ammo_type(i), + p_shield_hp_front_maximum(i), + p_shield_hp_back_maximum(i), + p_shield_recharge_rate(i), + p_capacitor_eng_maximum(i), + p_capacitor_eng_recharge_rate(i), + p_engine_acc_rate(i), + p_engine_deceleration_rate(i), + p_engine_pitch_acc_rate(i), + p_engine_yaw_acc_rate(i), + p_engine_roll_acc_rate(i), + p_engine_pitch_rate_maximum(i), + p_engine_yaw_rate_maximum(i), + p_engine_roll_rate_maximum(i), + p_engine_speed_maximum(i), + p_reactor_eng_generation_rate(i), + p_booster_eng_maximum(i), + p_booster_eng_recharge_rate(i), + p_booster_eng_consumption_rate(i), + p_booster_acc(i), + p_booster_speed_maximum(i), + p_droid_if_cmd_speed(i), + p_installed_dcd(i), + p_chassis_cmp_mass_maximum(i), + p_cmp_creators(i), + p_cargo_hold_contents_maximum(i), + p_cargo_hold_contents_current(i), + p_cargo_hold_contents(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into ship_objects + ( + ship_objects.slide_dampener, + ship_objects.current_chassis_hit_points, + ship_objects.maximum_chassis_hit_points, + ship_objects.chassis_type, + ship_objects.cmp_armor_hp_maximum, + ship_objects.cmp_armor_hp_current, + ship_objects.cmp_efficiency_general, + ship_objects.cmp_efficiency_eng, + ship_objects.cmp_eng_maintenance, + ship_objects.cmp_mass, + ship_objects.cmp_crc, + ship_objects.cmp_hp_current, + ship_objects.cmp_hp_maximum, + ship_objects.cmp_flags, + ship_objects.cmp_names, + ship_objects.weapon_damage_maximum, + ship_objects.weapon_damage_minimum, + ship_objects.weapon_effectiveness_shields, + ship_objects.weapon_effectiveness_armor, + ship_objects.weapon_eng_per_shot, + ship_objects.weapon_refire_rate, + ship_objects.weapon_ammo_current, + ship_objects.weapon_ammo_maximum, + ship_objects.weapon_ammo_type, + ship_objects.shield_hp_front_maximum, + ship_objects.shield_hp_back_maximum, + ship_objects.shield_recharge_rate, + ship_objects.capacitor_eng_maximum, + ship_objects.capacitor_eng_recharge_rate, + ship_objects.engine_acc_rate, + ship_objects.engine_deceleration_rate, + ship_objects.engine_pitch_acc_rate, + ship_objects.engine_yaw_acc_rate, + ship_objects.engine_roll_acc_rate, + ship_objects.engine_pitch_rate_maximum, + ship_objects.engine_yaw_rate_maximum, + ship_objects.engine_roll_rate_maximum, + ship_objects.engine_speed_maximum, + ship_objects.reactor_eng_generation_rate, + ship_objects.booster_eng_maximum, + ship_objects.booster_eng_recharge_rate, + ship_objects.booster_eng_consumption_rate, + ship_objects.booster_acc, + ship_objects.booster_speed_maximum, + ship_objects.droid_if_cmd_speed, + ship_objects.installed_dcd, + ship_objects.chassis_cmp_mass_maximum, + ship_objects.cmp_creators, + ship_objects.cargo_hold_contents_maximum, + ship_objects.cargo_hold_contents_current, + ship_objects.cargo_hold_contents, + ship_objects.object_id + ) + VALUES + ( + p_slide_dampener(i), + p_current_chassis_hit_points(i), + p_maximum_chassis_hit_points(i), + p_chassis_type(i), + p_cmp_armor_hp_maximum(i), + p_cmp_armor_hp_current(i), + p_cmp_efficiency_general(i), + p_cmp_efficiency_eng(i), + p_cmp_eng_maintenance(i), + p_cmp_mass(i), + p_cmp_crc(i), + p_cmp_hp_current(i), + p_cmp_hp_maximum(i), + p_cmp_flags(i), + p_cmp_names(i), + p_weapon_damage_maximum(i), + p_weapon_damage_minimum(i), + p_weapon_effectiveness_shields(i), + p_weapon_effectiveness_armor(i), + p_weapon_eng_per_shot(i), + p_weapon_refire_rate(i), + p_weapon_ammo_current(i), + p_weapon_ammo_maximum(i), + p_weapon_ammo_type(i), + p_shield_hp_front_maximum(i), + p_shield_hp_back_maximum(i), + p_shield_recharge_rate(i), + p_capacitor_eng_maximum(i), + p_capacitor_eng_recharge_rate(i), + p_engine_acc_rate(i), + p_engine_deceleration_rate(i), + p_engine_pitch_acc_rate(i), + p_engine_yaw_acc_rate(i), + p_engine_roll_acc_rate(i), + p_engine_pitch_rate_maximum(i), + p_engine_yaw_rate_maximum(i), + p_engine_roll_rate_maximum(i), + p_engine_speed_maximum(i), + p_reactor_eng_generation_rate(i), + p_booster_eng_maximum(i), + p_booster_eng_recharge_rate(i), + p_booster_eng_consumption_rate(i), + p_booster_acc(i), + p_booster_speed_maximum(i), + p_droid_if_cmd_speed(i), + p_installed_dcd(i), + p_chassis_cmp_mass_maximum(i), + p_cmp_creators(i), + p_cargo_hold_contents_maximum(i), + p_cargo_hold_contents_current(i), + p_cargo_hold_contents(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_ship_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_ship_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','slide_dampener','float',to_char(p_slide_dampener(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','current_chassis_hit_points','float',to_char(p_current_chassis_hit_points(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','maximum_chassis_hit_points','float',to_char(p_maximum_chassis_hit_points(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','chassis_type','int',to_char(p_chassis_type(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_armor_hp_maximum','varchar2',p_cmp_armor_hp_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_armor_hp_current','varchar2',p_cmp_armor_hp_current(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_efficiency_general','varchar2',p_cmp_efficiency_general(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_efficiency_eng','varchar2',p_cmp_efficiency_eng(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_eng_maintenance','varchar2',p_cmp_eng_maintenance(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_mass','varchar2',p_cmp_mass(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_crc','varchar2',p_cmp_crc(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_hp_current','varchar2',p_cmp_hp_current(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_hp_maximum','varchar2',p_cmp_hp_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_flags','varchar2',p_cmp_flags(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_names','varchar2',p_cmp_names(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_damage_maximum','varchar2',p_weapon_damage_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_damage_minimum','varchar2',p_weapon_damage_minimum(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_effectiveness_shields','varchar2',p_weapon_effectiveness_shields(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_effectiveness_armor','varchar2',p_weapon_effectiveness_armor(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_eng_per_shot','varchar2',p_weapon_eng_per_shot(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_refire_rate','varchar2',p_weapon_refire_rate(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_ammo_current','varchar2',p_weapon_ammo_current(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_ammo_maximum','varchar2',p_weapon_ammo_maximum(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','weapon_ammo_type','varchar2',p_weapon_ammo_type(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','shield_hp_front_maximum','float',to_char(p_shield_hp_front_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','shield_hp_back_maximum','float',to_char(p_shield_hp_back_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','shield_recharge_rate','float',to_char(p_shield_recharge_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','capacitor_eng_maximum','float',to_char(p_capacitor_eng_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','capacitor_eng_recharge_rate','float',to_char(p_capacitor_eng_recharge_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_acc_rate','float',to_char(p_engine_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_deceleration_rate','float',to_char(p_engine_deceleration_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_pitch_acc_rate','float',to_char(p_engine_pitch_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_yaw_acc_rate','float',to_char(p_engine_yaw_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_roll_acc_rate','float',to_char(p_engine_roll_acc_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_pitch_rate_maximum','float',to_char(p_engine_pitch_rate_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_yaw_rate_maximum','float',to_char(p_engine_yaw_rate_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_roll_rate_maximum','float',to_char(p_engine_roll_rate_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','engine_speed_maximum','float',to_char(p_engine_speed_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','reactor_eng_generation_rate','float',to_char(p_reactor_eng_generation_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','booster_eng_maximum','float',to_char(p_booster_eng_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','booster_eng_recharge_rate','float',to_char(p_booster_eng_recharge_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','booster_eng_consumption_rate','float',to_char(p_booster_eng_consumption_rate(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','booster_acc','float',to_char(p_booster_acc(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','booster_speed_maximum','float',to_char(p_booster_speed_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','droid_if_cmd_speed','float',to_char(p_droid_if_cmd_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','installed_dcd','number',p_installed_dcd(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','chassis_cmp_mass_maximum','float',to_char(p_chassis_cmp_mass_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','cmp_creators','varchar2',p_cmp_creators(m_error_index)); + db_error_logger.dblogerror_values('persister.add_ship_obj','cargo_hold_contents_maximum','number',to_char(p_cargo_hold_contents_maximum(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','cargo_hold_contents_current','number',to_char(p_cargo_hold_contents_current(m_error_index))); + db_error_logger.dblogerror_values('persister.add_ship_obj','cargo_hold_contents','varchar2',p_cargo_hold_contents(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_ship_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_ship_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete ship_objects + where + object_id=p_object_id(i); + end; + + procedure save_static_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + null; + end; + + procedure add_static_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into static_objects + ( + static_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_static_obj : dup_val_on_index error.'); + END IF; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into static_objects + ( + static_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_static_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_static_obj','object_id','number',p_object_id(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_static_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_static_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + null; + end; + + procedure save_tangible_obj( p_object_id VAOFSTRING, p_max_hit_points VAOFNUMBER, p_owner_id VAOFSTRING, p_visible VAOFSTRING, p_appearance_data VAOFSTRING, p_interest_radius VAOFNUMBER, p_pvp_type VAOFNUMBER, p_pvp_faction VAOFNUMBER, p_damage_taken VAOFNUMBER, p_custom_appearance VAOFSTRING, p_count VAOFNUMBER, p_condition VAOFNUMBER, p_creator_id VAOFSTRING, p_source_draft_schematic VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update tangible_objects set + tangible_objects.max_hit_points = nvl(p_max_hit_points(i),tangible_objects.max_hit_points), + tangible_objects.owner_id = nvl(p_owner_id(i),tangible_objects.owner_id), + tangible_objects.visible = nvl(p_visible(i),tangible_objects.visible), + tangible_objects.appearance_data = nvl(p_appearance_data(i),tangible_objects.appearance_data), + tangible_objects.interest_radius = nvl(p_interest_radius(i),tangible_objects.interest_radius), + tangible_objects.pvp_type = nvl(p_pvp_type(i),tangible_objects.pvp_type), + tangible_objects.pvp_faction = nvl(p_pvp_faction(i),tangible_objects.pvp_faction), + tangible_objects.damage_taken = nvl(p_damage_taken(i),tangible_objects.damage_taken), + tangible_objects.custom_appearance = nvl(p_custom_appearance(i),tangible_objects.custom_appearance), + tangible_objects.count = nvl(p_count(i),tangible_objects.count), + tangible_objects.condition = nvl(p_condition(i),tangible_objects.condition), + tangible_objects.creator_id = nvl(p_creator_id(i),tangible_objects.creator_id), + tangible_objects.source_draft_schematic = nvl(p_source_draft_schematic(i),tangible_objects.source_draft_schematic) + where + tangible_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update tangible_objects set + tangible_objects.max_hit_points = nvl(p_max_hit_points(i),tangible_objects.max_hit_points), + tangible_objects.owner_id = nvl(p_owner_id(i),tangible_objects.owner_id), + tangible_objects.visible = nvl(p_visible(i),tangible_objects.visible), + tangible_objects.appearance_data = nvl(p_appearance_data(i),tangible_objects.appearance_data), + tangible_objects.interest_radius = nvl(p_interest_radius(i),tangible_objects.interest_radius), + tangible_objects.pvp_type = nvl(p_pvp_type(i),tangible_objects.pvp_type), + tangible_objects.pvp_faction = nvl(p_pvp_faction(i),tangible_objects.pvp_faction), + tangible_objects.damage_taken = nvl(p_damage_taken(i),tangible_objects.damage_taken), + tangible_objects.custom_appearance = nvl(p_custom_appearance(i),tangible_objects.custom_appearance), + tangible_objects.count = nvl(p_count(i),tangible_objects.count), + tangible_objects.condition = nvl(p_condition(i),tangible_objects.condition), + tangible_objects.creator_id = nvl(p_creator_id(i),tangible_objects.creator_id), + tangible_objects.source_draft_schematic = nvl(p_source_draft_schematic(i),tangible_objects.source_draft_schematic) + where + tangible_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_tangible_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_tangible_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_tangible_obj','max_hit_points','int',to_char(p_max_hit_points(m_error_index))); + db_error_logger.dblogerror_values('persister.save_tangible_obj','owner_id','int',p_owner_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_tangible_obj','visible','char',p_visible(m_error_index)); + db_error_logger.dblogerror_values('persister.save_tangible_obj','appearance_data','varchar',p_appearance_data(m_error_index)); + db_error_logger.dblogerror_values('persister.save_tangible_obj','interest_radius','int',to_char(p_interest_radius(m_error_index))); + db_error_logger.dblogerror_values('persister.save_tangible_obj','pvp_type','int',to_char(p_pvp_type(m_error_index))); + db_error_logger.dblogerror_values('persister.save_tangible_obj','pvp_faction','int',to_char(p_pvp_faction(m_error_index))); + db_error_logger.dblogerror_values('persister.save_tangible_obj','damage_taken','int',to_char(p_damage_taken(m_error_index))); + db_error_logger.dblogerror_values('persister.save_tangible_obj','custom_appearance','varchar2',p_custom_appearance(m_error_index)); + db_error_logger.dblogerror_values('persister.save_tangible_obj','count','int',to_char(p_count(m_error_index))); + db_error_logger.dblogerror_values('persister.save_tangible_obj','condition','int',to_char(p_condition(m_error_index))); + db_error_logger.dblogerror_values('persister.save_tangible_obj','creator_id','number',p_creator_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_tangible_obj','source_draft_schematic','int',to_char(p_source_draft_schematic(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_tangible_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_tangible_obj( p_object_id VAOFSTRING, p_max_hit_points VAOFNUMBER, p_owner_id VAOFSTRING, p_visible VAOFSTRING, p_appearance_data VAOFSTRING, p_interest_radius VAOFNUMBER, p_pvp_type VAOFNUMBER, p_pvp_faction VAOFNUMBER, p_damage_taken VAOFNUMBER, p_custom_appearance VAOFSTRING, p_count VAOFNUMBER, p_condition VAOFNUMBER, p_creator_id VAOFSTRING, p_source_draft_schematic VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into tangible_objects + ( + tangible_objects.max_hit_points, + tangible_objects.owner_id, + tangible_objects.visible, + tangible_objects.appearance_data, + tangible_objects.interest_radius, + tangible_objects.pvp_type, + tangible_objects.pvp_faction, + tangible_objects.damage_taken, + tangible_objects.custom_appearance, + tangible_objects.count, + tangible_objects.condition, + tangible_objects.creator_id, + tangible_objects.source_draft_schematic, + tangible_objects.object_id + ) + VALUES + ( + p_max_hit_points(i), + p_owner_id(i), + p_visible(i), + p_appearance_data(i), + p_interest_radius(i), + p_pvp_type(i), + p_pvp_faction(i), + p_damage_taken(i), + p_custom_appearance(i), + p_count(i), + p_condition(i), + p_creator_id(i), + p_source_draft_schematic(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_tangible_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE tangible_objects Set + tangible_objects.max_hit_points = nvl(p_max_hit_points(i),tangible_objects.max_hit_points), + tangible_objects.owner_id = nvl(p_owner_id(i),tangible_objects.owner_id), + tangible_objects.visible = nvl(p_visible(i),tangible_objects.visible), + tangible_objects.appearance_data = nvl(p_appearance_data(i),tangible_objects.appearance_data), + tangible_objects.interest_radius = nvl(p_interest_radius(i),tangible_objects.interest_radius), + tangible_objects.pvp_type = nvl(p_pvp_type(i),tangible_objects.pvp_type), + tangible_objects.pvp_faction = nvl(p_pvp_faction(i),tangible_objects.pvp_faction), + tangible_objects.damage_taken = nvl(p_damage_taken(i),tangible_objects.damage_taken), + tangible_objects.custom_appearance = nvl(p_custom_appearance(i),tangible_objects.custom_appearance), + tangible_objects.count = nvl(p_count(i),tangible_objects.count), + tangible_objects.condition = nvl(p_condition(i),tangible_objects.condition), + tangible_objects.creator_id = nvl(p_creator_id(i),tangible_objects.creator_id), + tangible_objects.source_draft_schematic = nvl(p_source_draft_schematic(i),tangible_objects.source_draft_schematic) + where + tangible_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into tangible_objects + ( + tangible_objects.max_hit_points, + tangible_objects.owner_id, + tangible_objects.visible, + tangible_objects.appearance_data, + tangible_objects.interest_radius, + tangible_objects.pvp_type, + tangible_objects.pvp_faction, + tangible_objects.damage_taken, + tangible_objects.custom_appearance, + tangible_objects.count, + tangible_objects.condition, + tangible_objects.creator_id, + tangible_objects.source_draft_schematic, + tangible_objects.object_id + ) + VALUES + ( + p_max_hit_points(i), + p_owner_id(i), + p_visible(i), + p_appearance_data(i), + p_interest_radius(i), + p_pvp_type(i), + p_pvp_faction(i), + p_damage_taken(i), + p_custom_appearance(i), + p_count(i), + p_condition(i), + p_creator_id(i), + p_source_draft_schematic(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into tangible_objects + ( + tangible_objects.max_hit_points, + tangible_objects.owner_id, + tangible_objects.visible, + tangible_objects.appearance_data, + tangible_objects.interest_radius, + tangible_objects.pvp_type, + tangible_objects.pvp_faction, + tangible_objects.damage_taken, + tangible_objects.custom_appearance, + tangible_objects.count, + tangible_objects.condition, + tangible_objects.creator_id, + tangible_objects.source_draft_schematic, + tangible_objects.object_id + ) + VALUES + ( + p_max_hit_points(i), + p_owner_id(i), + p_visible(i), + p_appearance_data(i), + p_interest_radius(i), + p_pvp_type(i), + p_pvp_faction(i), + p_damage_taken(i), + p_custom_appearance(i), + p_count(i), + p_condition(i), + p_creator_id(i), + p_source_draft_schematic(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_tangible_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_tangible_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_tangible_obj','max_hit_points','int',to_char(p_max_hit_points(m_error_index))); + db_error_logger.dblogerror_values('persister.add_tangible_obj','owner_id','int',p_owner_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_tangible_obj','visible','char',p_visible(m_error_index)); + db_error_logger.dblogerror_values('persister.add_tangible_obj','appearance_data','varchar',p_appearance_data(m_error_index)); + db_error_logger.dblogerror_values('persister.add_tangible_obj','interest_radius','int',to_char(p_interest_radius(m_error_index))); + db_error_logger.dblogerror_values('persister.add_tangible_obj','pvp_type','int',to_char(p_pvp_type(m_error_index))); + db_error_logger.dblogerror_values('persister.add_tangible_obj','pvp_faction','int',to_char(p_pvp_faction(m_error_index))); + db_error_logger.dblogerror_values('persister.add_tangible_obj','damage_taken','int',to_char(p_damage_taken(m_error_index))); + db_error_logger.dblogerror_values('persister.add_tangible_obj','custom_appearance','varchar2',p_custom_appearance(m_error_index)); + db_error_logger.dblogerror_values('persister.add_tangible_obj','count','int',to_char(p_count(m_error_index))); + db_error_logger.dblogerror_values('persister.add_tangible_obj','condition','int',to_char(p_condition(m_error_index))); + db_error_logger.dblogerror_values('persister.add_tangible_obj','creator_id','number',p_creator_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_tangible_obj','source_draft_schematic','int',to_char(p_source_draft_schematic(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_tangible_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_tangible_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete tangible_objects + where + object_id=p_object_id(i); + end; + + procedure save_token_obj( p_object_id VAOFSTRING, p_reference VAOFSTRING, p_target_server_template_name VAOFSTRING, p_target_shared_template_name VAOFSTRING, p_waypoint VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update token_objects set + token_objects.reference = nvl(p_reference(i),token_objects.reference), + token_objects.target_server_template_name = nvl(p_target_server_template_name(i),token_objects.target_server_template_name), + token_objects.target_shared_template_name = nvl(p_target_shared_template_name(i),token_objects.target_shared_template_name), + token_objects.waypoint = nvl(p_waypoint(i),token_objects.waypoint) + where + token_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update token_objects set + token_objects.reference = nvl(p_reference(i),token_objects.reference), + token_objects.target_server_template_name = nvl(p_target_server_template_name(i),token_objects.target_server_template_name), + token_objects.target_shared_template_name = nvl(p_target_shared_template_name(i),token_objects.target_shared_template_name), + token_objects.waypoint = nvl(p_waypoint(i),token_objects.waypoint) + where + token_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_token_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_token_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_token_obj','reference','number',p_reference(m_error_index)); + db_error_logger.dblogerror_values('persister.save_token_obj','target_server_template_name','varchar2',p_target_server_template_name(m_error_index)); + db_error_logger.dblogerror_values('persister.save_token_obj','target_shared_template_name','varchar2',p_target_shared_template_name(m_error_index)); + db_error_logger.dblogerror_values('persister.save_token_obj','waypoint','number',p_waypoint(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_token_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_token_obj( p_object_id VAOFSTRING, p_reference VAOFSTRING, p_target_server_template_name VAOFSTRING, p_target_shared_template_name VAOFSTRING, p_waypoint VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into token_objects + ( + token_objects.reference, + token_objects.target_server_template_name, + token_objects.target_shared_template_name, + token_objects.waypoint, + token_objects.object_id + ) + VALUES + ( + p_reference(i), + p_target_server_template_name(i), + p_target_shared_template_name(i), + p_waypoint(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_token_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE token_objects Set + token_objects.reference = nvl(p_reference(i),token_objects.reference), + token_objects.target_server_template_name = nvl(p_target_server_template_name(i),token_objects.target_server_template_name), + token_objects.target_shared_template_name = nvl(p_target_shared_template_name(i),token_objects.target_shared_template_name), + token_objects.waypoint = nvl(p_waypoint(i),token_objects.waypoint) + where + token_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into token_objects + ( + token_objects.reference, + token_objects.target_server_template_name, + token_objects.target_shared_template_name, + token_objects.waypoint, + token_objects.object_id + ) + VALUES + ( + p_reference(i), + p_target_server_template_name(i), + p_target_shared_template_name(i), + p_waypoint(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into token_objects + ( + token_objects.reference, + token_objects.target_server_template_name, + token_objects.target_shared_template_name, + token_objects.waypoint, + token_objects.object_id + ) + VALUES + ( + p_reference(i), + p_target_server_template_name(i), + p_target_shared_template_name(i), + p_waypoint(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_token_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_token_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_token_obj','reference','number',p_reference(m_error_index)); + db_error_logger.dblogerror_values('persister.add_token_obj','target_server_template_name','varchar2',p_target_server_template_name(m_error_index)); + db_error_logger.dblogerror_values('persister.add_token_obj','target_shared_template_name','varchar2',p_target_shared_template_name(m_error_index)); + db_error_logger.dblogerror_values('persister.add_token_obj','waypoint','number',p_waypoint(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_token_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_token_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete token_objects + where + object_id=p_object_id(i); + end; + + procedure save_universe_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + null; + end; + + procedure add_universe_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into universe_objects + ( + universe_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_universe_obj : dup_val_on_index error.'); + END IF; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into universe_objects + ( + universe_objects.object_id + ) + VALUES + ( + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_universe_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_universe_obj','object_id','number',p_object_id(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_universe_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_universe_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + null; + end; + + procedure save_vehicle_obj( p_object_id VAOFSTRING, p_bogus VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update vehicle_objects set + vehicle_objects.bogus = nvl(p_bogus(i),vehicle_objects.bogus) + where + vehicle_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update vehicle_objects set + vehicle_objects.bogus = nvl(p_bogus(i),vehicle_objects.bogus) + where + vehicle_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_vehicle_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_vehicle_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_vehicle_obj','bogus','int',to_char(p_bogus(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_vehicle_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_vehicle_obj( p_object_id VAOFSTRING, p_bogus VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into vehicle_objects + ( + vehicle_objects.bogus, + vehicle_objects.object_id + ) + VALUES + ( + p_bogus(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_vehicle_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE vehicle_objects Set + vehicle_objects.bogus = nvl(p_bogus(i),vehicle_objects.bogus) + where + vehicle_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into vehicle_objects + ( + vehicle_objects.bogus, + vehicle_objects.object_id + ) + VALUES + ( + p_bogus(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into vehicle_objects + ( + vehicle_objects.bogus, + vehicle_objects.object_id + ) + VALUES + ( + p_bogus(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_vehicle_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_vehicle_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_vehicle_obj','bogus','int',to_char(p_bogus(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_vehicle_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_vehicle_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete vehicle_objects + where + object_id=p_object_id(i); + end; + + procedure save_weapon_obj( p_object_id VAOFSTRING, p_min_damage VAOFNUMBER, p_max_damage VAOFNUMBER, p_damage_type VAOFNUMBER, p_elemental_type VAOFNUMBER, p_elemental_value VAOFNUMBER, p_attack_speed VAOFNUMBER, p_wound_chance VAOFNUMBER, p_accuracy VAOFNUMBER, p_attack_cost VAOFNUMBER, p_damage_radius VAOFNUMBER, p_min_range VAOFNUMBER, p_max_range VAOFNUMBER, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + update weapon_objects set + weapon_objects.min_damage = nvl(p_min_damage(i),weapon_objects.min_damage), + weapon_objects.max_damage = nvl(p_max_damage(i),weapon_objects.max_damage), + weapon_objects.damage_type = nvl(p_damage_type(i),weapon_objects.damage_type), + weapon_objects.elemental_type = nvl(p_elemental_type(i),weapon_objects.elemental_type), + weapon_objects.elemental_value = nvl(p_elemental_value(i),weapon_objects.elemental_value), + weapon_objects.attack_speed = nvl(p_attack_speed(i),weapon_objects.attack_speed), + weapon_objects.wound_chance = nvl(p_wound_chance(i),weapon_objects.wound_chance), + weapon_objects.accuracy = nvl(p_accuracy(i),weapon_objects.accuracy), + weapon_objects.attack_cost = nvl(p_attack_cost(i),weapon_objects.attack_cost), + weapon_objects.damage_radius = nvl(p_damage_radius(i),weapon_objects.damage_radius), + weapon_objects.min_range = nvl(p_min_range(i),weapon_objects.min_range), + weapon_objects.max_range = nvl(p_max_range(i),weapon_objects.max_range) + where + weapon_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update weapon_objects set + weapon_objects.min_damage = nvl(p_min_damage(i),weapon_objects.min_damage), + weapon_objects.max_damage = nvl(p_max_damage(i),weapon_objects.max_damage), + weapon_objects.damage_type = nvl(p_damage_type(i),weapon_objects.damage_type), + weapon_objects.elemental_type = nvl(p_elemental_type(i),weapon_objects.elemental_type), + weapon_objects.elemental_value = nvl(p_elemental_value(i),weapon_objects.elemental_value), + weapon_objects.attack_speed = nvl(p_attack_speed(i),weapon_objects.attack_speed), + weapon_objects.wound_chance = nvl(p_wound_chance(i),weapon_objects.wound_chance), + weapon_objects.accuracy = nvl(p_accuracy(i),weapon_objects.accuracy), + weapon_objects.attack_cost = nvl(p_attack_cost(i),weapon_objects.attack_cost), + weapon_objects.damage_radius = nvl(p_damage_radius(i),weapon_objects.damage_radius), + weapon_objects.min_range = nvl(p_min_range(i),weapon_objects.min_range), + weapon_objects.max_range = nvl(p_max_range(i),weapon_objects.max_range) + where + weapon_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_weapon_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_weapon_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_weapon_obj','min_damage','int',to_char(p_min_damage(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','max_damage','int',to_char(p_max_damage(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','damage_type','int',to_char(p_damage_type(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','elemental_type','int',to_char(p_elemental_type(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','elemental_value','int',to_char(p_elemental_value(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','attack_speed','float',to_char(p_attack_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','wound_chance','float',to_char(p_wound_chance(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','accuracy','int',to_char(p_accuracy(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','attack_cost','int',to_char(p_attack_cost(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','damage_radius','float',to_char(p_damage_radius(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','min_range','float',to_char(p_min_range(m_error_index))); + db_error_logger.dblogerror_values('persister.save_weapon_obj','max_range','float',to_char(p_max_range(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_weapon_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_weapon_obj( p_object_id VAOFSTRING, p_min_damage VAOFNUMBER, p_max_damage VAOFNUMBER, p_damage_type VAOFNUMBER, p_elemental_type VAOFNUMBER, p_elemental_value VAOFNUMBER, p_attack_speed VAOFNUMBER, p_wound_chance VAOFNUMBER, p_accuracy VAOFNUMBER, p_attack_cost VAOFNUMBER, p_damage_radius VAOFNUMBER, p_min_range VAOFNUMBER, p_max_range VAOFNUMBER, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=1; + begin + FORALL i IN 1..p_chunk_size + insert into weapon_objects + ( + weapon_objects.min_damage, + weapon_objects.max_damage, + weapon_objects.damage_type, + weapon_objects.elemental_type, + weapon_objects.elemental_value, + weapon_objects.attack_speed, + weapon_objects.wound_chance, + weapon_objects.accuracy, + weapon_objects.attack_cost, + weapon_objects.damage_radius, + weapon_objects.min_range, + weapon_objects.max_range, + weapon_objects.object_id + ) + VALUES + ( + p_min_damage(i), + p_max_damage(i), + p_damage_type(i), + p_elemental_type(i), + p_elemental_value(i), + p_attack_speed(i), + p_wound_chance(i), + p_accuracy(i), + p_attack_cost(i), + p_damage_radius(i), + p_min_range(i), + p_max_range(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_weapon_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE weapon_objects Set + weapon_objects.min_damage = nvl(p_min_damage(i),weapon_objects.min_damage), + weapon_objects.max_damage = nvl(p_max_damage(i),weapon_objects.max_damage), + weapon_objects.damage_type = nvl(p_damage_type(i),weapon_objects.damage_type), + weapon_objects.elemental_type = nvl(p_elemental_type(i),weapon_objects.elemental_type), + weapon_objects.elemental_value = nvl(p_elemental_value(i),weapon_objects.elemental_value), + weapon_objects.attack_speed = nvl(p_attack_speed(i),weapon_objects.attack_speed), + weapon_objects.wound_chance = nvl(p_wound_chance(i),weapon_objects.wound_chance), + weapon_objects.accuracy = nvl(p_accuracy(i),weapon_objects.accuracy), + weapon_objects.attack_cost = nvl(p_attack_cost(i),weapon_objects.attack_cost), + weapon_objects.damage_radius = nvl(p_damage_radius(i),weapon_objects.damage_radius), + weapon_objects.min_range = nvl(p_min_range(i),weapon_objects.min_range), + weapon_objects.max_range = nvl(p_max_range(i),weapon_objects.max_range) + where + weapon_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into weapon_objects + ( + weapon_objects.min_damage, + weapon_objects.max_damage, + weapon_objects.damage_type, + weapon_objects.elemental_type, + weapon_objects.elemental_value, + weapon_objects.attack_speed, + weapon_objects.wound_chance, + weapon_objects.accuracy, + weapon_objects.attack_cost, + weapon_objects.damage_radius, + weapon_objects.min_range, + weapon_objects.max_range, + weapon_objects.object_id + ) + VALUES + ( + p_min_damage(i), + p_max_damage(i), + p_damage_type(i), + p_elemental_type(i), + p_elemental_value(i), + p_attack_speed(i), + p_wound_chance(i), + p_accuracy(i), + p_attack_cost(i), + p_damage_radius(i), + p_min_range(i), + p_max_range(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into weapon_objects + ( + weapon_objects.min_damage, + weapon_objects.max_damage, + weapon_objects.damage_type, + weapon_objects.elemental_type, + weapon_objects.elemental_value, + weapon_objects.attack_speed, + weapon_objects.wound_chance, + weapon_objects.accuracy, + weapon_objects.attack_cost, + weapon_objects.damage_radius, + weapon_objects.min_range, + weapon_objects.max_range, + weapon_objects.object_id + ) + VALUES + ( + p_min_damage(i), + p_max_damage(i), + p_damage_type(i), + p_elemental_type(i), + p_elemental_value(i), + p_attack_speed(i), + p_wound_chance(i), + p_accuracy(i), + p_attack_cost(i), + p_damage_radius(i), + p_min_range(i), + p_max_range(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_weapon_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_weapon_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_weapon_obj','min_damage','int',to_char(p_min_damage(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','max_damage','int',to_char(p_max_damage(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','damage_type','int',to_char(p_damage_type(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','elemental_type','int',to_char(p_elemental_type(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','elemental_value','int',to_char(p_elemental_value(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','attack_speed','float',to_char(p_attack_speed(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','wound_chance','float',to_char(p_wound_chance(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','accuracy','int',to_char(p_accuracy(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','attack_cost','int',to_char(p_attack_cost(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','damage_radius','float',to_char(p_damage_radius(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','min_range','float',to_char(p_min_range(m_error_index))); + db_error_logger.dblogerror_values('persister.add_weapon_obj','max_range','float',to_char(p_max_range(m_error_index))); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_weapon_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_weapon_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete weapon_objects + where + object_id=p_object_id(i); + end; + + procedure save_player_quest_obj( p_object_id VAOFSTRING, p_title VAOFSTRING, p_description VAOFSTRING, p_creator VAOFSTRING, p_total_tasks VAOFNUMBER, p_difficulty VAOFNUMBER, p_task_title1 VAOFSTRING, p_task_description1 VAOFSTRING, p_task_title2 VAOFSTRING, p_task_description2 VAOFSTRING, p_task_title3 VAOFSTRING, p_task_description3 VAOFSTRING, p_task_title4 VAOFSTRING, p_task_description4 VAOFSTRING, p_task_title5 VAOFSTRING, p_task_description5 VAOFSTRING, p_task_title6 VAOFSTRING, p_task_description6 VAOFSTRING, p_task_title7 VAOFSTRING, p_task_description7 VAOFSTRING, p_task_title8 VAOFSTRING, p_task_description8 VAOFSTRING, p_task_title9 VAOFSTRING, p_task_description9 VAOFSTRING, p_task_title10 VAOFSTRING, p_task_description10 VAOFSTRING, p_task_title11 VAOFSTRING, p_task_description11 VAOFSTRING, p_task_title12 VAOFSTRING, p_task_description12 VAOFSTRING, p_chunk_size number ) + as + + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=0; + begin + FORALL i IN 1..p_chunk_size + update player_quest_objects set + player_quest_objects.title = nvl(p_title(i),player_quest_objects.title), + player_quest_objects.description = nvl(p_description(i),player_quest_objects.description), + player_quest_objects.creator = nvl(p_creator(i),player_quest_objects.creator), + player_quest_objects.total_tasks = nvl(p_total_tasks(i),player_quest_objects.total_tasks), + player_quest_objects.difficulty = nvl(p_difficulty(i),player_quest_objects.difficulty), + player_quest_objects.task_title1 = nvl(p_task_title1(i),player_quest_objects.task_title1), + player_quest_objects.task_description1 = nvl(p_task_description1(i),player_quest_objects.task_description1), + player_quest_objects.task_title2 = nvl(p_task_title2(i),player_quest_objects.task_title2), + player_quest_objects.task_description2 = nvl(p_task_description2(i),player_quest_objects.task_description2), + player_quest_objects.task_title3 = nvl(p_task_title3(i),player_quest_objects.task_title3), + player_quest_objects.task_description3 = nvl(p_task_description3(i),player_quest_objects.task_description3), + player_quest_objects.task_title4 = nvl(p_task_title4(i),player_quest_objects.task_title4), + player_quest_objects.task_description4 = nvl(p_task_description4(i),player_quest_objects.task_description4), + player_quest_objects.task_title5 = nvl(p_task_title5(i),player_quest_objects.task_title5), + player_quest_objects.task_description5 = nvl(p_task_description5(i),player_quest_objects.task_description5), + player_quest_objects.task_title6 = nvl(p_task_title6(i),player_quest_objects.task_title6), + player_quest_objects.task_description6 = nvl(p_task_description6(i),player_quest_objects.task_description6), + player_quest_objects.task_title7 = nvl(p_task_title7(i),player_quest_objects.task_title7), + player_quest_objects.task_description7 = nvl(p_task_description7(i),player_quest_objects.task_description7), + player_quest_objects.task_title8 = nvl(p_task_title8(i),player_quest_objects.task_title8), + player_quest_objects.task_description8 = nvl(p_task_description8(i),player_quest_objects.task_description8), + player_quest_objects.task_title9 = nvl(p_task_title9(i),player_quest_objects.task_title9), + player_quest_objects.task_description9 = nvl(p_task_description9(i),player_quest_objects.task_description9), + player_quest_objects.task_title10 = nvl(p_task_title10(i),player_quest_objects.task_title10), + player_quest_objects.task_description10 = nvl(p_task_description10(i),player_quest_objects.task_description10), + player_quest_objects.task_title11 = nvl(p_task_title11(i),player_quest_objects.task_title11), + player_quest_objects.task_description11 = nvl(p_task_description11(i),player_quest_objects.task_description11), + player_quest_objects.task_title12 = nvl(p_task_title12(i),player_quest_objects.task_title12), + player_quest_objects.task_description12 = nvl(p_task_description12(i),player_quest_objects.task_description12) + where + player_quest_objects.object_id=p_object_id(i); + exception + when others then + begin + FOR i IN 1..p_chunk_size LOOP + m_error_index := i; + update player_quest_objects set + player_quest_objects.title = nvl(p_title(i),player_quest_objects.title), + player_quest_objects.description = nvl(p_description(i),player_quest_objects.description), + player_quest_objects.creator = nvl(p_creator(i),player_quest_objects.creator), + player_quest_objects.total_tasks = nvl(p_total_tasks(i),player_quest_objects.total_tasks), + player_quest_objects.difficulty = nvl(p_difficulty(i),player_quest_objects.difficulty), + player_quest_objects.task_title1 = nvl(p_task_title1(i),player_quest_objects.task_title1), + player_quest_objects.task_description1 = nvl(p_task_description1(i),player_quest_objects.task_description1), + player_quest_objects.task_title2 = nvl(p_task_title2(i),player_quest_objects.task_title2), + player_quest_objects.task_description2 = nvl(p_task_description2(i),player_quest_objects.task_description2), + player_quest_objects.task_title3 = nvl(p_task_title3(i),player_quest_objects.task_title3), + player_quest_objects.task_description3 = nvl(p_task_description3(i),player_quest_objects.task_description3), + player_quest_objects.task_title4 = nvl(p_task_title4(i),player_quest_objects.task_title4), + player_quest_objects.task_description4 = nvl(p_task_description4(i),player_quest_objects.task_description4), + player_quest_objects.task_title5 = nvl(p_task_title5(i),player_quest_objects.task_title5), + player_quest_objects.task_description5 = nvl(p_task_description5(i),player_quest_objects.task_description5), + player_quest_objects.task_title6 = nvl(p_task_title6(i),player_quest_objects.task_title6), + player_quest_objects.task_description6 = nvl(p_task_description6(i),player_quest_objects.task_description6), + player_quest_objects.task_title7 = nvl(p_task_title7(i),player_quest_objects.task_title7), + player_quest_objects.task_description7 = nvl(p_task_description7(i),player_quest_objects.task_description7), + player_quest_objects.task_title8 = nvl(p_task_title8(i),player_quest_objects.task_title8), + player_quest_objects.task_description8 = nvl(p_task_description8(i),player_quest_objects.task_description8), + player_quest_objects.task_title9 = nvl(p_task_title9(i),player_quest_objects.task_title9), + player_quest_objects.task_description9 = nvl(p_task_description9(i),player_quest_objects.task_description9), + player_quest_objects.task_title10 = nvl(p_task_title10(i),player_quest_objects.task_title10), + player_quest_objects.task_description10 = nvl(p_task_description10(i),player_quest_objects.task_description10), + player_quest_objects.task_title11 = nvl(p_task_title11(i),player_quest_objects.task_title11), + player_quest_objects.task_description11 = nvl(p_task_description11(i),player_quest_objects.task_description11), + player_quest_objects.task_title12 = nvl(p_task_title12(i),player_quest_objects.task_title12), + player_quest_objects.task_description12 = nvl(p_task_description12(i),player_quest_objects.task_description12) + where + player_quest_objects.object_id=p_object_id(i); + end LOOP; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.save_player_quest_obj : update error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.save_player_quest_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','title','varchar2',p_title(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','description','varchar2',p_description(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','creator','number',p_creator(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','total_tasks','int',to_char(p_total_tasks(m_error_index))); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','difficulty','int',to_char(p_difficulty(m_error_index))); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title1','varchar2',p_task_title1(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description1','varchar2',p_task_description1(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title2','varchar2',p_task_title2(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description2','varchar2',p_task_description2(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title3','varchar2',p_task_title3(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description3','varchar2',p_task_description3(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title4','varchar2',p_task_title4(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description4','varchar2',p_task_description4(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title5','varchar2',p_task_title5(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description5','varchar2',p_task_description5(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title6','varchar2',p_task_title6(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description6','varchar2',p_task_description6(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title7','varchar2',p_task_title7(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description7','varchar2',p_task_description7(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title8','varchar2',p_task_title8(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description8','varchar2',p_task_description8(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title9','varchar2',p_task_title9(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description9','varchar2',p_task_description9(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title10','varchar2',p_task_title10(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description10','varchar2',p_task_description10(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title11','varchar2',p_task_title11(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description11','varchar2',p_task_description11(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_title12','varchar2',p_task_title12(m_error_index)); + db_error_logger.dblogerror_values('persister.save_player_quest_obj','task_description12','varchar2',p_task_description12(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','save_player_quest_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure add_player_quest_obj( p_object_id VAOFSTRING, p_title VAOFSTRING, p_description VAOFSTRING, p_creator VAOFSTRING, p_total_tasks VAOFNUMBER, p_difficulty VAOFNUMBER, p_task_title1 VAOFSTRING, p_task_description1 VAOFSTRING, p_task_title2 VAOFSTRING, p_task_description2 VAOFSTRING, p_task_title3 VAOFSTRING, p_task_description3 VAOFSTRING, p_task_title4 VAOFSTRING, p_task_description4 VAOFSTRING, p_task_title5 VAOFSTRING, p_task_description5 VAOFSTRING, p_task_title6 VAOFSTRING, p_task_description6 VAOFSTRING, p_task_title7 VAOFSTRING, p_task_description7 VAOFSTRING, p_task_title8 VAOFSTRING, p_task_description8 VAOFSTRING, p_task_title9 VAOFSTRING, p_task_description9 VAOFSTRING, p_task_title10 VAOFSTRING, p_task_description10 VAOFSTRING, p_task_title11 VAOFSTRING, p_task_description11 VAOFSTRING, p_task_title12 VAOFSTRING, p_task_description12 VAOFSTRING, p_chunk_size number ) + as + m_enable_db_logging INTEGER := 0; + m_error_index INTEGER :=0; + begin + FORALL i IN 1..p_chunk_size + insert into player_quest_objects + ( + player_quest_objects.title, + player_quest_objects.description, + player_quest_objects.creator, + player_quest_objects.total_tasks, + player_quest_objects.difficulty, + player_quest_objects.task_title1, + player_quest_objects.task_description1, + player_quest_objects.task_title2, + player_quest_objects.task_description2, + player_quest_objects.task_title3, + player_quest_objects.task_description3, + player_quest_objects.task_title4, + player_quest_objects.task_description4, + player_quest_objects.task_title5, + player_quest_objects.task_description5, + player_quest_objects.task_title6, + player_quest_objects.task_description6, + player_quest_objects.task_title7, + player_quest_objects.task_description7, + player_quest_objects.task_title8, + player_quest_objects.task_description8, + player_quest_objects.task_title9, + player_quest_objects.task_description9, + player_quest_objects.task_title10, + player_quest_objects.task_description10, + player_quest_objects.task_title11, + player_quest_objects.task_description11, + player_quest_objects.task_title12, + player_quest_objects.task_description12, + player_quest_objects.object_id + ) + VALUES + ( + p_title(i), + p_description(i), + p_creator(i), + p_total_tasks(i), + p_difficulty(i), + p_task_title1(i), + p_task_description1(i), + p_task_title2(i), + p_task_description2(i), + p_task_title3(i), + p_task_description3(i), + p_task_title4(i), + p_task_description4(i), + p_task_title5(i), + p_task_description5(i), + p_task_title6(i), + p_task_description6(i), + p_task_title7(i), + p_task_description7(i), + p_task_title8(i), + p_task_description8(i), + p_task_title9(i), + p_task_description9(i), + p_task_title10(i), + p_task_description10(i), + p_task_title11(i), + p_task_description11(i), + p_task_title12(i), + p_task_description12(i), + p_object_id(i) + ); + + exception + when dup_val_on_index then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_player_quest_obj : dup_val_on_index error.'); + END IF; + for i in 1..p_chunk_size loop + m_error_index := i; + UPDATE player_quest_objects Set + player_quest_objects.title = nvl(p_title(i),player_quest_objects.title), + player_quest_objects.description = nvl(p_description(i),player_quest_objects.description), + player_quest_objects.creator = nvl(p_creator(i),player_quest_objects.creator), + player_quest_objects.total_tasks = nvl(p_total_tasks(i),player_quest_objects.total_tasks), + player_quest_objects.difficulty = nvl(p_difficulty(i),player_quest_objects.difficulty), + player_quest_objects.task_title1 = nvl(p_task_title1(i),player_quest_objects.task_title1), + player_quest_objects.task_description1 = nvl(p_task_description1(i),player_quest_objects.task_description1), + player_quest_objects.task_title2 = nvl(p_task_title2(i),player_quest_objects.task_title2), + player_quest_objects.task_description2 = nvl(p_task_description2(i),player_quest_objects.task_description2), + player_quest_objects.task_title3 = nvl(p_task_title3(i),player_quest_objects.task_title3), + player_quest_objects.task_description3 = nvl(p_task_description3(i),player_quest_objects.task_description3), + player_quest_objects.task_title4 = nvl(p_task_title4(i),player_quest_objects.task_title4), + player_quest_objects.task_description4 = nvl(p_task_description4(i),player_quest_objects.task_description4), + player_quest_objects.task_title5 = nvl(p_task_title5(i),player_quest_objects.task_title5), + player_quest_objects.task_description5 = nvl(p_task_description5(i),player_quest_objects.task_description5), + player_quest_objects.task_title6 = nvl(p_task_title6(i),player_quest_objects.task_title6), + player_quest_objects.task_description6 = nvl(p_task_description6(i),player_quest_objects.task_description6), + player_quest_objects.task_title7 = nvl(p_task_title7(i),player_quest_objects.task_title7), + player_quest_objects.task_description7 = nvl(p_task_description7(i),player_quest_objects.task_description7), + player_quest_objects.task_title8 = nvl(p_task_title8(i),player_quest_objects.task_title8), + player_quest_objects.task_description8 = nvl(p_task_description8(i),player_quest_objects.task_description8), + player_quest_objects.task_title9 = nvl(p_task_title9(i),player_quest_objects.task_title9), + player_quest_objects.task_description9 = nvl(p_task_description9(i),player_quest_objects.task_description9), + player_quest_objects.task_title10 = nvl(p_task_title10(i),player_quest_objects.task_title10), + player_quest_objects.task_description10 = nvl(p_task_description10(i),player_quest_objects.task_description10), + player_quest_objects.task_title11 = nvl(p_task_title11(i),player_quest_objects.task_title11), + player_quest_objects.task_description11 = nvl(p_task_description11(i),player_quest_objects.task_description11), + player_quest_objects.task_title12 = nvl(p_task_title12(i),player_quest_objects.task_title12), + player_quest_objects.task_description12 = nvl(p_task_description12(i),player_quest_objects.task_description12) + where + player_quest_objects.object_id=p_object_id(i); + + if SQL%ROWCOUNT=0 then + insert into player_quest_objects + ( + player_quest_objects.title, + player_quest_objects.description, + player_quest_objects.creator, + player_quest_objects.total_tasks, + player_quest_objects.difficulty, + player_quest_objects.task_title1, + player_quest_objects.task_description1, + player_quest_objects.task_title2, + player_quest_objects.task_description2, + player_quest_objects.task_title3, + player_quest_objects.task_description3, + player_quest_objects.task_title4, + player_quest_objects.task_description4, + player_quest_objects.task_title5, + player_quest_objects.task_description5, + player_quest_objects.task_title6, + player_quest_objects.task_description6, + player_quest_objects.task_title7, + player_quest_objects.task_description7, + player_quest_objects.task_title8, + player_quest_objects.task_description8, + player_quest_objects.task_title9, + player_quest_objects.task_description9, + player_quest_objects.task_title10, + player_quest_objects.task_description10, + player_quest_objects.task_title11, + player_quest_objects.task_description11, + player_quest_objects.task_title12, + player_quest_objects.task_description12, + player_quest_objects.object_id + ) + VALUES + ( + p_title(i), + p_description(i), + p_creator(i), + p_total_tasks(i), + p_difficulty(i), + p_task_title1(i), + p_task_description1(i), + p_task_title2(i), + p_task_description2(i), + p_task_title3(i), + p_task_description3(i), + p_task_title4(i), + p_task_description4(i), + p_task_title5(i), + p_task_description5(i), + p_task_title6(i), + p_task_description6(i), + p_task_title7(i), + p_task_description7(i), + p_task_title8(i), + p_task_description8(i), + p_task_title9(i), + p_task_description9(i), + p_task_title10(i), + p_task_description10(i), + p_task_title11(i), + p_task_description11(i), + p_task_title12(i), + p_task_description12(i), + p_object_id(i) + ); + end if; + end loop; + end; + when others then + begin + for i in 1..p_chunk_size loop + m_error_index := i; + insert into player_quest_objects + ( + player_quest_objects.title, + player_quest_objects.description, + player_quest_objects.creator, + player_quest_objects.total_tasks, + player_quest_objects.difficulty, + player_quest_objects.task_title1, + player_quest_objects.task_description1, + player_quest_objects.task_title2, + player_quest_objects.task_description2, + player_quest_objects.task_title3, + player_quest_objects.task_description3, + player_quest_objects.task_title4, + player_quest_objects.task_description4, + player_quest_objects.task_title5, + player_quest_objects.task_description5, + player_quest_objects.task_title6, + player_quest_objects.task_description6, + player_quest_objects.task_title7, + player_quest_objects.task_description7, + player_quest_objects.task_title8, + player_quest_objects.task_description8, + player_quest_objects.task_title9, + player_quest_objects.task_description9, + player_quest_objects.task_title10, + player_quest_objects.task_description10, + player_quest_objects.task_title11, + player_quest_objects.task_description11, + player_quest_objects.task_title12, + player_quest_objects.task_description12, + player_quest_objects.object_id + ) + VALUES + ( + p_title(i), + p_description(i), + p_creator(i), + p_total_tasks(i), + p_difficulty(i), + p_task_title1(i), + p_task_description1(i), + p_task_title2(i), + p_task_description2(i), + p_task_title3(i), + p_task_description3(i), + p_task_title4(i), + p_task_description4(i), + p_task_title5(i), + p_task_description5(i), + p_task_title6(i), + p_task_description6(i), + p_task_title7(i), + p_task_description7(i), + p_task_title8(i), + p_task_description8(i), + p_task_title9(i), + p_task_description9(i), + p_task_title10(i), + p_task_description10(i), + p_task_title11(i), + p_task_description11(i), + p_task_title12(i), + p_task_description12(i), + p_object_id(i) + ); + + end loop; + exception + when others then + begin + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'persister.add_player_quest_obj : error.'); + IF (m_enable_db_logging > 1) THEN + db_error_logger.dblogerror_values('persister.add_player_quest_obj','object_id','number',p_object_id(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','title','varchar2',p_title(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','description','varchar2',p_description(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','creator','number',p_creator(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','total_tasks','int',to_char(p_total_tasks(m_error_index))); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','difficulty','int',to_char(p_difficulty(m_error_index))); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title1','varchar2',p_task_title1(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description1','varchar2',p_task_description1(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title2','varchar2',p_task_title2(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description2','varchar2',p_task_description2(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title3','varchar2',p_task_title3(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description3','varchar2',p_task_description3(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title4','varchar2',p_task_title4(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description4','varchar2',p_task_description4(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title5','varchar2',p_task_title5(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description5','varchar2',p_task_description5(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title6','varchar2',p_task_title6(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description6','varchar2',p_task_description6(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title7','varchar2',p_task_title7(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description7','varchar2',p_task_description7(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title8','varchar2',p_task_title8(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description8','varchar2',p_task_description8(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title9','varchar2',p_task_title9(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description9','varchar2',p_task_description9(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title10','varchar2',p_task_title10(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description10','varchar2',p_task_description10(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title11','varchar2',p_task_title11(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description11','varchar2',p_task_description11(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_title12','varchar2',p_task_title12(m_error_index)); + db_error_logger.dblogerror_values('persister.add_player_quest_obj','task_description12','varchar2',p_task_description12(m_error_index)); + END IF; + END IF; + IF (db_error_logger.reraisecheck('persister','add_player_quest_obj') = 1) THEN + RAISE; + END IF; + end; + end; + end; + + procedure remove_player_quest_obj( p_object_id VAOFSTRING, p_chunk_size number ) + as + begin + FORALL i IN 1..p_chunk_size + delete player_quest_objects + where + object_id=p_object_id(i); + end; + +end; + +/ + + GRANT EXECUTE ON "SWG"."PERSISTER" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body PURGE_METHODS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."PURGE_METHODS" IS + + FUNCTION Purge_objects + (date_in in objects.deleted_date%type) + RETURN NUMBER IS + v_count NUMBER := 0; + BEGIN + --open the cursor for the object ids we want to purge. + --we will use these ids to delete child records from other tables + FOR x IN (SELECT /*+ INDEX (OBJECTS DELETED_OBJECT_IDX) */ object_id + FROM objects + WHERE deleted_date < date_in) LOOP + + IF v_count = 0 THEN + dbms_output.put_line ('Starting to delete....'); + END IF; + + --delete all children + DELETE FROM armor nologging WHERE object_id = x.object_id; + + DELETE FROM battlefield_marker_objects nologging WHERE object_id = x.object_id; + DELETE FROM battlefield_participants nologging WHERE region_object_id = x.object_id; + DELETE FROM battlefield_participants nologging WHERE character_object_id = x.object_id ; + DELETE FROM biographies nologging WHERE object_id = x.object_id ; + DELETE FROM building_objects nologging WHERE object_id = x.object_id ; + DELETE FROM cell_objects nologging WHERE object_id = x.object_id ; + DELETE FROM creature_objects nologging WHERE object_id = x.object_id ; + DELETE FROM experience_points nologging WHERE object_id = x.object_id ; + DELETE FROM factory_objects nologging WHERE object_id = x.object_id ; + DELETE FROM guild_objects nologging WHERE object_id = x.object_id ; + DELETE FROM harvester_installation_objects nologging WHERE object_id = x.object_id ; + DELETE FROM installation_objects nologging WHERE object_id = x.object_id ; + DELETE FROM intangible_objects nologging WHERE object_id = x.object_id ; + DELETE FROM location_lists nologging WHERE object_id = x.object_id ; + DELETE FROM manf_schematic_attributes nologging WHERE object_id = x.object_id ; + DELETE FROM manf_schematic_objects nologging WHERE object_id = x.object_id ; + DELETE FROM manufacture_inst_objects nologging WHERE object_id = x.object_id ; + DELETE FROM mission_objects nologging WHERE object_id = x.object_id ; + + DELETE FROM object_variables nologging WHERE object_id = x.object_id ; + DELETE FROM planet_objects nologging WHERE object_id = x.object_id ; + DELETE FROM player_objects nologging WHERE object_id = x.object_id ; + DELETE FROM property_lists nologging WHERE object_id = x.object_id ; + DELETE FROM resource_container_objects nologging WHERE object_id = x.object_id ; + DELETE FROM scripts nologging WHERE object_id = x.object_id ; + DELETE FROM static_objects nologging WHERE object_id = x.object_id ; + DELETE FROM tangible_objects nologging WHERE object_id = x.object_id ; + DELETE FROM token_objects nologging WHERE object_id = x.object_id ; + DELETE FROM universe_objects nologging WHERE object_id = x.object_id ; + DELETE FROM vehicle_objects nologging WHERE object_id = x.object_id ; + DELETE FROM waypoints nologging WHERE object_id = x.object_id ; + DELETE FROM weapon_objects nologging WHERE object_id = x.object_id ; + --delete messages target(object_id) + DELETE FROM messages nologging WHERE target = x.object_id ; + + v_count := v_count + 1; + + COMMIT; + + END LOOP; + + --delete parent + DELETE /*+ INDEX (OBJECTS DELETED_OBJECT_IDX) */ FROM objects + nologging WHERE deleted_date < date_in; + + dbms_output.put_line (v_count||': iterations'); + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + IF v_count = 0 THEN + dbms_output.put_line ('never deleted'); + END IF; + dbms_output.put_line (v_count||': iterations'); + RETURN SQLCODE; + END Purge_objects; + -- + -- + -- + FUNCTION time_purge + (date_in IN VARCHAR2) + RETURN INTEGER IS + v_retval NUMBER := 0; + v_date VARCHAR2(20) := date_in; + v_time NUMBER := 1; + BEGIN + + FOR i IN 1..24 LOOP + dbms_output.put_line(to_char(to_date(v_date, 'dd-mon-yy hh24:mi:ss') + v_time/24, 'DD-MON-YY hh24:mi:ss')); + v_retval := purge_objects(to_date(v_date, 'dd-mon-yy hh24:mi:ss') + v_time/24); + EXIT WHEN v_retval <> 0; + + IF v_time = 23 THEN + v_time := v_time + (59/60); + ELSE + v_time := v_time + 1; + END IF; + END LOOP; + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + dbms_output.put_line('Purge return values: '||v_retval); + dbms_output.put_line('Time it failed at: '||v_time); + RETURN SQLCODE; + END time_purge; + +end purge_methods; + +/ + + GRANT EXECUTE ON "SWG"."PURGE_METHODS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body PURGE_METHODS2 +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."PURGE_METHODS2" is +/**********************************************************************/ +/*** Purge Objects ***/ +/*** ***/ +/*** Deletes objects marked for deletion in object tables and ***/ +/*** then the master objects table based on date value ***/ +/**********************************************************************/ + + FUNCTION Purge_objects + (date_in in objects.deleted_date%type) + RETURN PLS_INTEGER + IS + v_count PLS_INTEGER := 0; + + Obj_list Obj_list_t; -- VARRAY object to hold ids to bulk delete for child objects + Obj_list_index PLS_INTEGER; -- index into VARRAY object + + BEGIN + + Obj_list := Obj_list_t(); -- initialize VARRAY object + Obj_list.extend(chunk_size); -- allocate VARRAY object memory to chunk size + + -- LOGGING.LOG_STATUS(1,'Starting object deletions.'); + + --open the cursor for the object ids we want to purge. + --we will use these ids to delete records from other tables + FOR x IN (SELECT /*+ INDEX (OBJECTS DELETED_OBJECT_IDX) */ object_id + FROM objects + WHERE deleted_date < date_in) LOOP + + v_count := v_count + 1; + Obj_list_index := MOD(v_count, chunk_size); -- what obj index for this batch + + If Obj_list_index = 0 then + Obj_list(chunk_size) := x.object_id; -- make sure we fill last VARRAY element + Purge_objects_work(Obj_list); -- bulk delete object ids in VARRAY list + COMMIT; + -- LOGGING.LOG_STATUS(v_count,'batch purged'); + Else + Obj_list(Obj_list_index) := x.object_id; -- fill VARRAY with ids + End If; + + END LOOP; + + -- LOGGING.LOG_STATUS(v_count,'Child object main loop exited.'); + + --Now delete remaining partially full object list for objects + If Obj_list_index != 0 then + Obj_list.trim(chunk_size - Obj_list_index); + Purge_objects_work(Obj_list); + COMMIT; + -- LOGGING.LOG_STATUS(v_count,'Deleting chunk remainder.'); + End If; + + Obj_list.delete; -- cleanup - delete VARRAY list + +-- LOGGING.LOG_STATUS(v_count,'Finished deleting '|| to_char(v_count) ||' references to objects.'); + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + + IF v_count = 0 THEN + dbms_output.put_line ('never deleted'); + -- LOGGING.LOG_ERROR(SQLCODE, SQLERRM); + END IF; + dbms_output.put_line (v_count||': iterations'); + -- LOGGING.LOG_ERROR(SQLCODE, SQLERRM); + RETURN SQLCODE; + END Purge_objects; + +/**********************************************************************/ +/*** Purge Objects Work ***/ +/*** ***/ +/*** Bulk delete objects marked for deletion in child object tables ***/ +/*** given a list of object ids passed in from a VARRAY. Called ***/ +/*** purge objects function. ***/ +/**********************************************************************/ + + PROCEDURE Purge_objects_work + (Obj_list IN Obj_list_t) IS + + BEGIN + + --delete all children + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM armor WHERE object_id = Obj_list(i); + + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM battlefield_marker_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM battlefield_participants WHERE region_object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM battlefield_participants WHERE character_object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM biographies WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM building_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM cell_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM creature_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM experience_points WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM factory_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM guild_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM harvester_installation_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM installation_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM intangible_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM location_lists WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM manf_schematic_attributes WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM manf_schematic_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM manufacture_inst_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM mission_objects WHERE object_id = Obj_list(i); + + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM object_variables WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM planet_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM player_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM property_lists WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM resource_container_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM scripts WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM static_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM tangible_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM token_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM universe_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM vehicle_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM waypoints WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM weapon_objects WHERE object_id = Obj_list(i); + --delete messages target(object_id) + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM messages WHERE target = Obj_list(i); + + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM objects WHERE object_id = Obj_list(i); + + END Purge_objects_work; + -- + -- + -- + FUNCTION time_purge + (date_in IN VARCHAR2) + RETURN PLS_INTEGER IS + v_retval PLS_INTEGER := 0; + v_date VARCHAR2(20) := date_in; + v_time NUMBER := 1; + BEGIN + + FOR i IN 1..24 LOOP + dbms_output.put_line(to_char(to_date(v_date, 'dd-mon-yy hh24:mi:ss') + v_time/24, 'DD-MON-YY hh24:mi:ss')); + v_retval := purge_objects(to_date(v_date, 'dd-mon-yy hh24:mi:ss') + v_time/24); + EXIT WHEN v_retval <> 0; + + IF v_time = 23 THEN + v_time := v_time + (59/60); + ELSE + v_time := v_time + 1; + END IF; + END LOOP; + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + dbms_output.put_line('Purge return values: '||v_retval); + dbms_output.put_line('Time it failed at: '||v_time); + RETURN SQLCODE; + END time_purge; + +/**********************************************************************/ +/*** Purge Consumables ***/ +/*** ***/ +/*** Deletes consumable objects marked for deletion in child object ***/ +/*** tables and then the master objects table based on date value ***/ +/**********************************************************************/ + + FUNCTION Purge_consumables + (start_date_in in objects.deleted_date%type, + end_date_in in objects.deleted_date%type) + RETURN PLS_INTEGER + IS + v_count PLS_INTEGER := 0; + + Obj_list Obj_list_t; -- VARRAY object to hold ids to bulk delete for objects + Obj_list_index PLS_INTEGER; -- index into VARRAY object + + BEGIN + + Obj_list := Obj_list_t(); -- initialize VARRAY object + Obj_list.extend(chunk_size); -- allocate VARRAY object memory to chunk size + + -- LOGGING.LOG_STATUS(1,'Starting child object deletions for consumables.'); + + --open the cursor for the object ids we want to purge. + --we will use these ids to delete records from other tables + FOR x IN (SELECT object_id + FROM objects + WHERE deleted_date is not NULL + AND deleted_date BETWEEN start_date_in AND end_date_in + and object_template_id in ( + 300281711, + 352903310, + 1006954225, + 9343642, + 35614291, + 339194814, + 1001781097, + 1632911215, + 1139268412, + 2059421636, + 1349101341, + -1657672270, + 1931602976, + -1440714292, + -1436615854, + -1614624973, + -1556205486, + -679440489, + -1397391672, + -541746271, + -718648728, + -789429729, + -786663538, + -610128810, + -132487792, + -1129945606, + -104858180, + -82570045)) LOOP + + v_count := v_count + 1; + Obj_list_index := MOD(v_count, chunk_size); -- what obj index for this batch + + If Obj_list_index = 0 then + Obj_list(chunk_size) := x.object_id; -- make sure we fill last VARRAY element + Purge_consumables_work(Obj_list); -- bulk delete object ids in VARRAY list + COMMIT; + -- LOGGING.LOG_STATUS(v_count,'batch purged'); + Else + Obj_list(Obj_list_index) := x.object_id; -- fill VARRAY with ids + End If; + + END LOOP; + + -- LOGGING.LOG_STATUS(v_count,'Consumables object main loop exited.'); + + --Now delete remaining partially full object list for objects + If Obj_list_index != 0 then + Obj_list.trim(chunk_size - Obj_list_index); + Purge_consumables_work(Obj_list); + COMMIT; + -- LOGGING.LOG_STATUS(v_count,'Deleting chunk remainder.'); + End If; + + Obj_list.delete; -- cleanup - delete VARRAY list + + -- LOGGING.LOG_STATUS(v_count,'Finished deleting '|| to_char(v_count) ||' consumable objects.'); + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + IF v_count = 0 THEN + dbms_output.put_line ('never deleted'); + -- LOGGING.LOG_ERROR(SQLCODE, SQLERRM); + END IF; + dbms_output.put_line (v_count||': iterations'); + -- LOGGING.LOG_ERROR(SQLCODE, SQLERRM); + RETURN SQLCODE; + END Purge_consumables; + +/**********************************************************************/ +/*** Purge Consumables Work ***/ +/*** ***/ +/*** Bulk delete consumable objects marked for deletion in child ***/ +/*** object tables given a list of object ids passed in from a ***/ +/*** VARRAY. Called purge consumables function. ***/ +/**********************************************************************/ + + PROCEDURE Purge_consumables_work + (Obj_list IN Obj_list_t) + IS + + BEGIN + + --delete all children + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM armor WHERE object_id = Obj_list(i); + + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM battlefield_marker_objects WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM biographies nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM creature_objects nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM experience_points nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM factory_objects nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM intangible_objects nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM location_lists nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM mission_objects nologging WHERE object_id = Obj_list(i); + + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM object_variables nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM property_lists nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM resource_container_objects nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM scripts nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM tangible_objects nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM token_objects nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM vehicle_objects nologging WHERE object_id = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM weapon_objects nologging WHERE object_id = Obj_list(i); + --delete messages target(object_id) + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM messages nologging WHERE target = Obj_list(i); + FORALL i IN Obj_list.First..Obj_list.Last DELETE FROM objects nologging WHERE object_id = Obj_list(i); + END Purge_consumables_work; + + + -- + -- + -- + FUNCTION time_purge_consumables + (start_date_in in objects.deleted_date%type, + end_date_in in objects.deleted_date%type) + RETURN PLS_INTEGER IS + v_retval PLS_INTEGER := 0; + v_start_date DATE := start_date_in; + v_end_date DATE := end_date_in; + v_hours NUMBER := (v_end_date - v_start_date) * 24; + v_time NUMBER := 1; + BEGIN + dbms_output.put_line('Hours between dates: '||v_hours); + FOR i IN 1..v_hours LOOP + v_end_date := v_start_date + v_time/24; + dbms_output.put_line ('Calling proc with Start Date: '||to_char(v_start_date, 'dd-mon-yy hh24:mi:ss')||'-'||'End Date: '||to_char(v_end_date, 'dd-mon-yy hh24:mi:ss')); + v_retval := purge_consumables(v_start_date, v_end_date); + v_start_date := v_start_date + v_time/24; + + EXIT WHEN v_retval <> 0; + + END LOOP; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + dbms_output.put_line('Purge return value: '||v_retval); + RETURN SQLCODE; + END time_purge_consumables; + +end purge_methods2; + +/ + + GRANT EXECUTE ON "SWG"."PURGE_METHODS2" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body PURGE_PROCESS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."PURGE_PROCESS" +as + procedure update_account_list (source_table varchar2) as + begin + --Add new status codes + execute immediate + 'insert into statuses (id, description, do_purge, reviewed) ' || + 'select distinct status, status_desc, ''N'', ''N'' ' || + 'from ' || source_table || ' ' || + 'where not exists (select * from statuses where statuses.id = ' || source_table || '.status)'; + + --Add any new accounts. + execute immediate + 'insert into purge_accounts (station_id,purge_phase) ' || + 'select user_id, 0 ' || + 'from ' || source_table || ' ' || + 'where not exists (select * from purge_accounts where purge_accounts.station_id = ' || source_table ||'.user_id)'; + + --Reset purge phase on existing accounts who may have reactivated: + execute immediate + 'update purge_accounts ' || + 'set purge_phase = 0, ' || + 'purge_start_date = null ' || + 'where purge_phase<>0 ' || + 'and exists (select * from ' || source_table || ' , statuses ' || + 'where ' || source_table || '.user_id = purge_accounts.station_id ' || + 'and ' || source_table || '.status = statuses.id ' || + 'and statuses.do_purge=''N'')'; + + --Start purge process on accounts who have deactivated: + execute immediate + 'update purge_accounts ' || + 'set purge_phase = 1, ' || + 'purge_start_date=(select nvl(max(close_date),sysdate) from ' || source_table || + ' where ' || source_table || '.user_id = purge_accounts.station_id) ' || + 'where purge_phase=0 ' || + 'and exists (select * from ' || source_table || ', statuses ' || + 'where ' || source_table || '.user_id = purge_accounts.station_id ' || + 'and ' || source_table || '.status = statuses.id ' || + 'and statuses.do_purge=''Y'')'; + --TODO: immediate purge for banned accounts + end; + + function get_account_for_purge(p_purge_phase number, p_min_age number) return number + -- Grabs one account from the list to be purged, and sets a lock on it so that no other process + -- will attempt to purge it. (Ignores locks from more than 1 day ago, because those probably mean + -- something in the process failed.) + as + result number; + begin + select station_id + into result + from purge_accounts + where purge_accounts.purge_phase = p_purge_phase + and sysdate - nvl(purge_accounts.purge_phase_date, purge_accounts.purge_start_date) > p_min_age + and (purge_lock is null or sysdate - purge_lock > 1) + and rownum < 2 + order by purge_accounts.purge_start_date + for update; + + update purge_accounts + set purge_lock=sysdate + where station_id = result; + + return result; + end; + + procedure set_purge_status(p_station_id number, p_new_phase number) + as + begin + if (p_new_phase = 0) then + update purge_accounts + set purge_phase = p_new_phase, + purge_start_date = null, + purge_phase_date = null, + purge_lock = null + where station_id = p_station_id; + else + update purge_accounts + set purge_phase = p_new_phase, + purge_phase_date = sysdate, + purge_lock = null + where station_id = p_station_id; + end if; + + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."PURGE_PROCESS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body SERVERCLOCK +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."SERVERCLOCK" +as + + function get_last_save_time return number + as + result number; + begin + select + last_save_time + into + result + from + clock; + return result; + end; + +end; + +/ + + GRANT EXECUTE ON "SWG"."SERVERCLOCK" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body STATION_PLAYERS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."STATION_PLAYERS" +as + procedure update_character(p_clusterName in varchar2 ,p_characterId in networkid, p_characterName in varchar2, p_objectName in varchar2, p_x in number, p_y in number, p_z in number, p_sceneId in varchar2, p_cash_balance in number, p_bank_balance in number, p_objectTemplateName in varchar2, p_stationId in networkid, p_containedBy in networkid, p_createTime in number, p_playedTime in number , p_numLots in number) + as + m_enable_db_logging INTEGER := 0; + begin + insert into character_profile (cluster_name, character_id, character_name, object_name, x, y, z, scene_id, cash_balance, bank_balance, object_template_name, station_id, contained_by, create_time, played_time, num_lots) + values (p_clusterName, p_characterId, p_characterName, p_objectName, p_x, p_y, p_z, p_sceneId, p_cash_balance, p_bank_balance, p_objectTemplateName, p_stationId, p_containedBy, util.unix_time_2_oracle_date_PDT(p_createTime), util.unix_time_2_oracle_date_PDT(p_playedTime), p_numLots); + + + + exception + when dup_val_on_index then + begin + + update character_profile set + character_name = NVL(p_characterName,character_name), + object_name = NVL(p_objectName, object_name), + x = NVL(p_x, x), + y = NVL(p_y, y), + z = NVL(p_z, z), + scene_id = NVL(p_sceneId, scene_id), + cash_balance = NVL(p_cash_balance, cash_balance), + bank_balance = NVL(p_bank_balance, bank_balance), + object_template_name = NVL(p_objectTemplateName, object_template_name), + station_id = NVL(p_stationId, station_id), + contained_by = NVL(p_containedBy, contained_by), + create_time = NVL(util.unix_time_2_oracle_date_PDT(p_createTime), create_time), + played_time = NVL(util.unix_time_2_oracle_date_PDT(p_playedTime), played_time), + num_lots = NVL(p_numLots, num_lots) + where cluster_name = p_clusterName + and character_id = p_characterId; + + end; + when others then + m_enable_db_logging := db_error_logger.getLogLevel(); + IF (m_enable_db_logging > 0) THEN + db_error_logger.dblogerror(SQLCODE,'station_players.update_character : error.'); + IF (m_enable_db_logging > 1) THEN + NULL; + END IF; + END IF; + IF (db_error_logger.reraisecheck('station_players','update_character') = 1) THEN + RAISE; + END IF; + end; +end; + +/ + + GRANT EXECUTE ON "SWG"."STATION_PLAYERS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body UNDELETE_METHODS +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."UNDELETE_METHODS" is + + FUNCTION restore_object + (object_id_in IN objects.object_id%TYPE) + RETURN NUMBER IS + BEGIN + --update an object and its children + --continue down tree with any object + --whose contained_by is a valid object id. + UPDATE objects + SET deleted = 0, + deleted_date = NULL + WHERE object_id = object_id_in; + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END restore_object; + +end undelete_methods; + +/ + + GRANT EXECUTE ON "SWG"."UNDELETE_METHODS" TO PUBLIC; +-------------------------------------------------------- +-- DDL for Package Body UTIL +-------------------------------------------------------- + + CREATE OR REPLACE PACKAGE BODY "SWG"."UTIL" +as + function unix_time_2_oracle_date_PDT(p_unix_time in number) return date + as + begin + return new_time( to_date('01011970','ddmmyyyy') + 1/24/60/60 * p_unix_time, 'GMT', 'PDT' ); + end; + + function unix_time_2_oracle_date_PST(p_unix_time in number) return date + as + begin + return new_time( to_date('01011970','ddmmyyyy') + 1/24/60/60 * p_unix_time, 'GMT', 'PST' ); + end; + + function unix_time_2_oracle_date_CDT(p_unix_time in number) return date + as + begin + return new_time( to_date('01011970','ddmmyyyy') + 1/24/60/60 * p_unix_time, 'GMT', 'CDT' ); + end; + + function unix_time_2_oracle_date_CST(p_unix_time in number) return date + as + begin + return new_time( to_date('01011970','ddmmyyyy') + 1/24/60/60 * p_unix_time, 'GMT', 'CST' ); + end; + + function unix_time_2_oracle_date(p_unix_time in number, p_timezone_offset in number) return date + as + begin + return ((to_date('01011970','ddmmyyyy') + 1/24/60/60 * p_unix_time) + p_timezone_offset/24); + end; + + function unix_to_oracle_date(p_unix_time in number, p_timezone_offset in number) return date + as + begin + return unix_time_2_oracle_date(p_unix_time, p_timezone_offset); + end; + +end; + +/ + + GRANT EXECUTE ON "SWG"."UTIL" TO PUBLIC; From fcbbfdff8e3fc3d3b64e541f8e077f58e7d59a2a Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Mon, 9 Jan 2017 03:14:26 +0000 Subject: [PATCH 55/55] exit on completion --- game/server/database/build/linux/swg_blankdb.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/game/server/database/build/linux/swg_blankdb.sql b/game/server/database/build/linux/swg_blankdb.sql index e8168a48..a696990c 100644 --- a/game/server/database/build/linux/swg_blankdb.sql +++ b/game/server/database/build/linux/swg_blankdb.sql @@ -14744,3 +14744,5 @@ end; / GRANT EXECUTE ON "SWG"."UTIL" TO PUBLIC; + +exit;