this should be the last of them

This commit is contained in:
DarthArgus
2016-09-30 20:23:57 -05:00
parent ea879babe4
commit f1f4db17be
4 changed files with 498 additions and 439 deletions
@@ -23,6 +23,8 @@
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
#include "sharedObject/NetworkIdManager.h"
#include "sharedFoundation/CrcConstexpr.hpp"
// ======================================================================
std::string MessageToQueue::ms_nullString;
@@ -234,53 +236,63 @@ void MessageToQueue::receiveMessage(MessageDispatch::Emitter const &, MessageDis
static Archive::ReadIterator ri;
ri = static_cast<GameNetworkMessage const &>(message).getByteStream().begin(); //lint !e1774 // could use dynamic_cast
if (message.isType("MessageToMessage"))
{
ri = static_cast<GameNetworkMessage const &>(message).getByteStream().begin();
MessageToMessage const msg(ri);
const uint32 messageType = message.getType();
switch(messageType) {
case constcrc("MessageToMessage") :
{
ri = static_cast<GameNetworkMessage const &>(message).getByteStream().begin();
MessageToMessage const msg(ri);
// const_cast avoids having to make another copy of the data. Since we expect to receive lots of these mesages,
// avoiding making extra copies matters. In this particular case, we know it is safe since the message is about
// to go out of scope anyway.
handleMessageFromNetwork(const_cast<MessageToPayload&>(msg.getData()), msg.getSourceServerPid());
}
else if (message.isType("WhoHasMessage"))
{
// Attempt to find the object, tell the source server if we have it or not
GenericValueTypeMessage<std::pair<uint32, NetworkId> > const whoHasMessage(ri);
uint32 sourceServer = whoHasMessage.getValue().first;
NetworkId const & networkId = whoHasMessage.getValue().second;
ServerMessageForwarding::begin(sourceServer);
ServerObject const * const object = safe_cast<ServerObject const *>(NetworkIdManager::getObjectById(networkId));
if (object)
{
GenericValueTypeMessage<std::pair<uint32, std::pair<NetworkId, bool> > > reply(
"ObjectOnServerMessage",
std::make_pair(GameServer::getInstance().getProcessId(),
std::make_pair(networkId,
object->isAuthoritative())));
ServerMessageForwarding::send(reply);
// const_cast avoids having to make another copy of the data. Since we expect to receive lots of these mesages,
// avoiding making extra copies matters. In this particular case, we know it is safe since the message is about
// to go out of scope anyway.
handleMessageFromNetwork(const_cast<MessageToPayload&>(msg.getData()), msg.getSourceServerPid());
break;
}
else
case constcrc("WhoHasMessage") :
{
GenericValueTypeMessage<std::pair<uint32, NetworkId> > reply(
"ObjectNotOnServerMessage",
std::make_pair(GameServer::getInstance().getProcessId(),
networkId));
ServerMessageForwarding::send(reply);
// Attempt to find the object, tell the source server if we have it or not
GenericValueTypeMessage<std::pair<uint32, NetworkId> > const whoHasMessage(ri);
uint32 sourceServer = whoHasMessage.getValue().first;
NetworkId const & networkId = whoHasMessage.getValue().second;
ServerMessageForwarding::begin(sourceServer);
ServerObject const * const object = safe_cast<ServerObject const *>(NetworkIdManager::getObjectById(networkId));
if (object)
{
GenericValueTypeMessage<std::pair<uint32, std::pair<NetworkId, bool> > > reply(
"ObjectOnServerMessage",
std::make_pair(GameServer::getInstance().getProcessId(),
std::make_pair(networkId,
object->isAuthoritative())));
ServerMessageForwarding::send(reply);
}
else
{
GenericValueTypeMessage<std::pair<uint32, NetworkId> > reply(
"ObjectNotOnServerMessage",
std::make_pair(GameServer::getInstance().getProcessId(),
networkId));
ServerMessageForwarding::send(reply);
}
ServerMessageForwarding::end();
break;
}
case constcrc("ObjectNotOnServerMessage") :
{
GenericValueTypeMessage<std::pair<uint32, NetworkId> > const msg(ri);
handleObjectNotOnServer(msg.getValue().first, msg.getValue().second);
break;
}
case constcrc("ObjectOnServerMessage") :
{
GenericValueTypeMessage<std::pair<uint32, std::pair<NetworkId, bool> > > const msg(ri);
handleObjectOnServer(msg.getValue().first, msg.getValue().second.first, msg.getValue().second.second);
break;
}
ServerMessageForwarding::end();
}
else if (message.isType("ObjectNotOnServerMessage"))
{
GenericValueTypeMessage<std::pair<uint32, NetworkId> > const msg(ri);
handleObjectNotOnServer(msg.getValue().first, msg.getValue().second);
}
else if (message.isType("ObjectOnServerMessage"))
{
GenericValueTypeMessage<std::pair<uint32, std::pair<NetworkId, bool> > > const msg(ri);
handleObjectOnServer(msg.getValue().first, msg.getValue().second.first, msg.getValue().second.second);
}
}
@@ -26,6 +26,9 @@
#include "sharedNetworkMessages/SuiCreatePageMessage.h"
#include "sharedNetworkMessages/SuiEventNotification.h"
#include "sharedNetworkMessages/SuiUpdatePageMessage.h"
#include "sharedFoundation/CrcConstexpr.hpp"
#include <algorithm>
#include <map>
#include <memory>
@@ -268,6 +271,7 @@ bool ServerUIManager::removePage(int pageId)
void ServerUIManager::receiveMessage(const MessageDispatch::MessageBase& message)
{
Archive::ReadIterator ri = NON_NULL(dynamic_cast<const GameNetworkMessage *>(&message))->getByteStream().begin();
if (message.isType(SuiEventNotification::MessageType))
{
SuiEventNotification const suiEventNotification(ri);
@@ -397,7 +401,7 @@ void ServerUIManager::receiveMessage(const MessageDispatch::MessageBase& message
if ((eventType == SuiEventType::SET_onClosedOk) || (eventType == SuiEventType::SET_onClosedCancel))
IGNORE_RETURN(removePage(pageId));
}
else if(message.isType("PageChangeAuthority"))
else if(message.getType() == constexpr("PageChangeAuthority"))
{
//DEBUG_WARNING(true, ("ServerUIManager: received PageChangeAuthority message"));
const GenericValueTypeMessage<std::pair<NetworkId, SuiPageDataServer> > pageChangeAuthority(ri);
@@ -33,6 +33,8 @@
#include "sharedObject/ObjectTemplateList.h"
#include "UnicodeUtils.h"
#include "sharedFoundation/CrcConstexpr.hpp"
//-----------------------------------------------------------------------
CentralServerConnection::CentralServerConnection(const std::string & a, const unsigned short p) :
@@ -76,110 +78,122 @@ void CentralServerConnection::onReceive(const Archive::ByteStream & message)
Archive::ReadIterator ri = message.begin();
GameNetworkMessage msg(ri);
ri = message.begin();
const uint32 messageType = msg.getType();
if(msg.isType("ConGenericMessage"))
{
// dispatch to CentralCommandParser
ConGenericMessage con(ri);
Unicode::String wideResult;
m_centralCommandParser->parse(NetworkId(static_cast<NetworkId::NetworkIdType>(con.getMsgId())), Unicode::narrowToWide(con.getMsg()), wideResult);
ConGenericMessage response(Unicode::wideToNarrow(wideResult), con.getMsgId());
send(response, true);
}
else if(msg.isType("CharacterTransferStatusMessage"))
{
CharacterTransferStatusMessage c(ri);
CreatureObject * character = safe_cast<CreatureObject *>(NetworkIdManager::getObjectById(c.getToCharacterId()));
if(character)
switch(messageType) {
case constcrc("ConGenericMessage") :
{
if(character->getClient())
// dispatch to CentralCommandParser
ConGenericMessage con(ri);
Unicode::String wideResult;
m_centralCommandParser->parse(NetworkId(static_cast<NetworkId::NetworkIdType>(con.getMsgId())), Unicode::narrowToWide(con.getMsg()), wideResult);
ConGenericMessage response(Unicode::wideToNarrow(wideResult), con.getMsgId());
send(response, true);
break;
}
case constcrc("CharacterTransferStatusMessage") :
{
CharacterTransferStatusMessage c(ri);
CreatureObject * character = safe_cast<CreatureObject *>(NetworkIdManager::getObjectById(c.getToCharacterId()));
if(character)
{
character->receiveCharacterTransferStatusMessage(c.getStatusMessage());
if(character->getClient())
{
character->receiveCharacterTransferStatusMessage(c.getStatusMessage());
}
}
break;
}
}
else if(msg.isType("TransferRequestNameValidation"))
{
const GenericValueTypeMessage<TransferCharacterData> requestNameValidation(ri);
LOG("CustomerService", ("CharacterTransfer: Received TransferRequestNameValidation from CentralServer : %s", requestNameValidation.getValue().toString().c_str()));
std::string name = requestNameValidation.getValue().getDestinationCharacterName();
if(name.empty())
case constcrc("TransferRequestNameValidation") :
{
name = requestNameValidation.getValue().getSourceCharacterName();
}
const GenericValueTypeMessage<TransferCharacterData> requestNameValidation(ri);
LOG("CustomerService", ("CharacterTransfer: Received TransferRequestNameValidation from CentralServer : %s", requestNameValidation.getValue().toString().c_str()));
// call the same name validation code that gets called for normal character creation
std::string templateName = requestNameValidation.getValue().getObjectTemplateName();
if (templateName.empty())
{
uint32 const templateCrc = requestNameValidation.getValue().getObjectTemplateCrc();
if (templateCrc != 0)
std::string name = requestNameValidation.getValue().getDestinationCharacterName();
if(name.empty())
{
templateName = ObjectTemplateList::lookUp(templateCrc).getString();
name = requestNameValidation.getValue().getSourceCharacterName();
}
// call the same name validation code that gets called for normal character creation
std::string templateName = requestNameValidation.getValue().getObjectTemplateName();
if (templateName.empty())
{
uint32 const templateCrc = requestNameValidation.getValue().getObjectTemplateCrc();
if (templateCrc != 0)
{
templateName = ObjectTemplateList::lookUp(templateCrc).getString();
}
}
VerifyAndLockNameRequest const verifyRequest(requestNameValidation.getValue().getDestinationStationId(), NetworkId::cms_invalid, templateName, Unicode::narrowToWide(name), 0xFFFFFFFF);
StringId const verifyResult = GameServer::getInstance().handleVerifyAndLockNameRequest(verifyRequest, false, false);
TransferCharacterData replyData(requestNameValidation.getValue());
replyData.setIsValidName(verifyResult == NameErrors::nameApproved);
GenericValueTypeMessage<std::pair<std::string, TransferCharacterData> > reply("TransferReplyNameValidation", std::make_pair(std::string("@") + verifyResult.getCanonicalRepresentation(), replyData));
send(reply, true);
break;
}
VerifyAndLockNameRequest const verifyRequest(requestNameValidation.getValue().getDestinationStationId(), NetworkId::cms_invalid, templateName, Unicode::narrowToWide(name), 0xFFFFFFFF);
StringId const verifyResult = GameServer::getInstance().handleVerifyAndLockNameRequest(verifyRequest, false, false);
TransferCharacterData replyData(requestNameValidation.getValue());
replyData.setIsValidName(verifyResult == NameErrors::nameApproved);
GenericValueTypeMessage<std::pair<std::string, TransferCharacterData> > reply("TransferReplyNameValidation", std::make_pair(std::string("@") + verifyResult.getCanonicalRepresentation(), replyData));
send(reply, true);
}
else if(msg.isType("TransferReplyCharacterList"))
{
const TransferReplyCharacterList reply(ri);
const AvatarList & oldAl = reply.getAvatarList();
// remove any characters from the list that would qualify for free CTS; characters that
// qualify for free CTS should/must use the in-game free CTS to transfer the character;
AvatarList newAl;
std::string const & clusterName = GameServer::getInstance().getClusterName();
for (AvatarList::const_iterator iter = oldAl.begin(); iter != oldAl.end(); ++iter)
case constcrc("TransferReplyCharacterList") :
{
if (!FreeCtsDataTable::getFreeCtsInfoForCharacter(static_cast<time_t>(NameManager::getInstance().getPlayerCreateTime(iter->m_networkId)), clusterName, false))
newAl.push_back(*iter);
const TransferReplyCharacterList reply(ri);
const AvatarList & oldAl = reply.getAvatarList();
// remove any characters from the list that would qualify for free CTS; characters that
// qualify for free CTS should/must use the in-game free CTS to transfer the character;
AvatarList newAl;
std::string const & clusterName = GameServer::getInstance().getClusterName();
for (AvatarList::const_iterator iter = oldAl.begin(); iter != oldAl.end(); ++iter)
{
if (!FreeCtsDataTable::getFreeCtsInfoForCharacter(static_cast<time_t>(NameManager::getInstance().getPlayerCreateTime(iter->m_networkId)), clusterName, false))
newAl.push_back(*iter);
else
LOG("CustomerService", ("CharacterTransfer: removing (%s, %s, %s) from paid CTS character list for station id %u because the character qualifies for free CTS", clusterName.c_str(), Unicode::wideToNarrow(iter->m_name).c_str(), iter->m_networkId.getValueString().c_str(), reply.getStationId()));
}
// send updated character list back to CentralServer
const TransferReplyCharacterList updatedReply(reply.getTrack(), reply.getStationId(), newAl);
send(updatedReply, true);
break;
}
case constcrc("CtsCompletedForcharacter") :
{
const GenericValueTypeMessage<std::pair<std::string, NetworkId> > msg(ri);
MessageToQueue::getInstance().sendMessageToJava(msg.getValue().second, "ctsCompletedForCharacter", std::vector<int8>(), 0, false);
break;
}
case constcrc("GameServerCSRequest" ) :
{
GameServerCSRequestMessage request( ri );
GameServer::getInstance().handleCSRequest( request );
break;
}
case constcrc( "CSFindAuthObject" ) :
{
// see if we have the object.
GenericValueTypeMessage< std::pair<NetworkId, unsigned int> > msg( ri );
ServerObject * object = safe_cast<ServerObject *>( NetworkIdManager::getObjectById( msg.getValue().first ) );
// return an appropriate response.
if( object && object->isAuthoritative() )
{
GenericValueTypeMessage< std::pair< unsigned int, bool > > rmsg( "CSFindAuthObjectReply", std::make_pair( msg.getValue().second, true ) );
GameServer::getInstance().sendToCentralServer( rmsg );
}
else
LOG("CustomerService", ("CharacterTransfer: removing (%s, %s, %s) from paid CTS character list for station id %u because the character qualifies for free CTS", clusterName.c_str(), Unicode::wideToNarrow(iter->m_name).c_str(), iter->m_networkId.getValueString().c_str(), reply.getStationId()));
{
GenericValueTypeMessage< std::pair< unsigned int, bool > > rmsg( "CSFindAuthObjectReply", std::make_pair( msg.getValue().second, false ) );
GameServer::getInstance().sendToCentralServer( rmsg );
}
break;
}
// send updated character list back to CentralServer
const TransferReplyCharacterList updatedReply(reply.getTrack(), reply.getStationId(), newAl);
send(updatedReply, true);
}
else if(msg.isType("CtsCompletedForcharacter"))
{
const GenericValueTypeMessage<std::pair<std::string, NetworkId> > msg(ri);
MessageToQueue::getInstance().sendMessageToJava(msg.getValue().second, "ctsCompletedForCharacter", std::vector<int8>(), 0, false);
}
else if( msg.isType( "GameServerCSRequest" ) )
{
GameServerCSRequestMessage request( ri );
GameServer::getInstance().handleCSRequest( request );
}
else if( msg.isType( "CSFindAuthObject" ) )
{
// see if we have the object.
GenericValueTypeMessage< std::pair<NetworkId, unsigned int> > msg( ri );
ServerObject * object = safe_cast<ServerObject *>( NetworkIdManager::getObjectById( msg.getValue().first ) );
// return an appropriate response.
if( object && object->isAuthoritative() )
default :
{
GenericValueTypeMessage< std::pair< unsigned int, bool > > rmsg( "CSFindAuthObjectReply", std::make_pair( msg.getValue().second, true ) );
GameServer::getInstance().sendToCentralServer( rmsg );
ServerConnection::onReceive(message);
break;
}
else
{
GenericValueTypeMessage< std::pair< unsigned int, bool > > rmsg( "CSFindAuthObjectReply", std::make_pair( msg.getValue().second, false ) );
GameServer::getInstance().sendToCentralServer( rmsg );
}
}
else
{
ServerConnection::onReceive(message);
}
}
@@ -41,6 +41,8 @@
#include "sharedObject/VolumeContainer.h"
#include "sharedSkillSystem/SkillObject.h"
#include "sharedFoundation/CrcConstexpr.hpp"
// ======================================================================
namespace ConnectionServerConnectionNamespace
@@ -111,370 +113,397 @@ void ConnectionServerConnection::onReceive (const Archive::ByteStream & message)
Archive::ReadIterator ri = message.begin();
GameNetworkMessage m(ri);
ri = message.begin();
if(m.isType("GameClientMessage"))
{
GameClientMessage c(ri);
const std::vector<NetworkId> & idList = c.getDistributionList();
std::vector<NetworkId>::const_iterator i;
for(i = idList.begin(); i != idList.end(); ++i)
const uint32 messageType = m.getType();
switch(messageType) {
if(m.isType("GameClientMessage"))
{
GameServer::getInstance().deliverMessageToClientObject((*i), c.getByteStream());
}
}
else if (m.isType("SetSyncStamp"))
{
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::pair<uint16, uint32> > syncStampMessage(readIterator);
setSyncStamps(syncStampMessage.getValue().first, syncStampMessage.getValue().second);
}
else if (m.isType("ChatOnChangeFriendStatus"))
{
ChatOnChangeFriendStatus chat(ri);
CommunityManager::handleMessage(chat);
}
else if (m.isType("ChatOnGetFriendsList"))
{
ChatOnGetFriendsList chat(ri);
CommunityManager::handleMessage(chat);
}
else if (m.isType("ChatOnChangeIgnoreStatus"))
{
ChatOnChangeIgnoreStatus chat(ri);
CommunityManager::handleMessage(chat);
}
else if (m.isType("ChatOnGetIgnoreList"))
{
ChatOnGetIgnoreList chat(ri);
CommunityManager::handleMessage(chat);
}
else if (m.isType("ChatStatisticsCS"))
{
GenericValueTypeMessage<std::pair<std::pair<NetworkId, int>, std::pair<int, int> > > chatStatistics(ri);
ServerObject * const so = ServerWorld::findObjectByNetworkId(chatStatistics.getValue().first.first);
if (so)
{
CreatureObject * const character = so->asCreatureObject();
if (character)
GameClientMessage c(ri);
const std::vector<NetworkId> & idList = c.getDistributionList();
std::vector<NetworkId>::const_iterator i;
for(i = idList.begin(); i != idList.end(); ++i)
{
PlayerObject * const player = PlayerCreatureController::getPlayerObject(character);
if (player)
GameServer::getInstance().deliverMessageToClientObject((*i), c.getByteStream());
}
break;
}
case constcrc("SetSyncStamp") :
{
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::pair<uint16, uint32> > syncStampMessage(readIterator);
setSyncStamps(syncStampMessage.getValue().first, syncStampMessage.getValue().second);
break;
}
case constcrc("ChatOnChangeFriendStatus") :
{
ChatOnChangeFriendStatus chat(ri);
CommunityManager::handleMessage(chat);
break;
}
case constcrc("ChatOnGetFriendsList") :
{
ChatOnGetFriendsList chat(ri);
CommunityManager::handleMessage(chat);
break;
}
case constcrc("ChatOnChangeIgnoreStatus") :
{
ChatOnChangeIgnoreStatus chat(ri);
CommunityManager::handleMessage(chat);
break;
}
case constcrc("ChatOnGetIgnoreList") :
{
ChatOnGetIgnoreList chat(ri);
CommunityManager::handleMessage(chat);
break;
}
case constcrc("ChatStatisticsCS") :
{
GenericValueTypeMessage<std::pair<std::pair<NetworkId, int>, std::pair<int, int> > > chatStatistics(ri);
ServerObject * const so = ServerWorld::findObjectByNetworkId(chatStatistics.getValue().first.first);
if (so)
{
CreatureObject * const character = so->asCreatureObject();
if (character)
{
player->handleChatStatisticsFromChatServer(chatStatistics.getValue().first.first, chatStatistics.getValue().first.second, chatStatistics.getValue().second.first, chatStatistics.getValue().second.second);
PlayerObject * const player = PlayerCreatureController::getPlayerObject(character);
if (player)
{
player->handleChatStatisticsFromChatServer(chatStatistics.getValue().first.first, chatStatistics.getValue().first.second, chatStatistics.getValue().second.first, chatStatistics.getValue().second.second);
}
}
}
break;
}
}
else if (m.isType("RequestLoadPackedHouses"))
{
GenericValueTypeMessage<NetworkId> characterId(ri);
LOG("CustomerService", ("CharacterTransfer: ConnectionServerConnection received RequestLoadPackedHouses for %s", characterId.getValue().getValueString().c_str()));
CreatureObject * character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(characterId.getValue()));
if(character)
case constcrc("RequestLoadPackedHouses") :
{
int numHouses = 0;
numHouses = character->loadPackedHouses();
if (numHouses > 0)
{
character->setLoadCTSPackedHouses(true);
// add the objvar.
character->setObjVarItem("cts.packed_house_count", numHouses);
LOG("CustomerService", ("CharacterTransfer: starting %d packed house load for CTS character %s", numHouses, PlayerObject::getAccountDescription(character).c_str()));
}
else
{
// houses are loaded, go ahead and send the reply message
GenericValueTypeMessage<NetworkId> loadedMsg("PackedHousesLoaded", characterId.getValue());
send(loadedMsg, true);
LOG("CustomerService", ("CharacterTransfer: CTS character %s does not have any packed houses, so telling the connection server", PlayerObject::getAccountDescription(character).c_str()));
}
}
else
LOG("CustomerService", ("CharacterTransfer: character object was nullptr so unable to check if bank is loaded"));
GenericValueTypeMessage<NetworkId> characterId(ri);
LOG("CustomerService", ("CharacterTransfer: ConnectionServerConnection received RequestLoadPackedHouses for %s", characterId.getValue().getValueString().c_str()));
}
else if (m.isType("RequestLoadCTSBank"))
{
GenericValueTypeMessage<NetworkId> characterId(ri);
LOG("CustomerService", ("CharacterTransfer: ConnectionServerConnection received RequestLoadCTSBank for %s", characterId.getValue().getValueString().c_str()));
CreatureObject * character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(characterId.getValue()));
if(character)
{
ServerObject *bankContainer = character->getBankContainer();
if (bankContainer)
CreatureObject * character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(characterId.getValue()));
if(character)
{
if (!bankContainer->areContentsLoaded())
int numHouses = 0;
numHouses = character->loadPackedHouses();
if (numHouses > 0)
{
LOG("CustomerService", ("CharacterTransfer: setting LoadCTSBank flag and request bank to be loaded for %s", PlayerObject::getAccountDescription(character).c_str()));
character->setLoadCTSBank(true);
bankContainer->loadAllContentsFromDB();
character->setLoadCTSPackedHouses(true);
// add the objvar.
character->setObjVarItem("cts.packed_house_count", numHouses);
LOG("CustomerService", ("CharacterTransfer: starting %d packed house load for CTS character %s", numHouses, PlayerObject::getAccountDescription(character).c_str()));
}
else
{
LOG("CustomerService", ("CharacterTransfer: bank contents already loaded for %s, sending ReplyBankCTSLoaded back to client", PlayerObject::getAccountDescription(character).c_str()));
//Bank contents are already loaded
GenericValueTypeMessage<NetworkId> reply("ReplyBankCTSLoaded", characterId.getValue());
send(reply, true);
// houses are loaded, go ahead and send the reply message
GenericValueTypeMessage<NetworkId> loadedMsg("PackedHousesLoaded", characterId.getValue());
send(loadedMsg, true);
LOG("CustomerService", ("CharacterTransfer: CTS character %s does not have any packed houses, so telling the connection server", PlayerObject::getAccountDescription(character).c_str()));
}
}
else
LOG("CustomerService", ("CharacterTransfer: bank container object was nullptr for getBankContainer call"));
}
else
LOG("CustomerService", ("CharacterTransfer: character object was nullptr so unable to check if bank is loaded"));
}
else if (m.isType("RequestTransferData"))
{
GenericValueTypeMessage<TransferCharacterData> requestTransferData(ri);
const TransferCharacterData & transferCharacterData = requestTransferData.getValue();
CreatureObject * const character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(requestTransferData.getValue().getCharacterId()));
PlayerObject * const playerObject = PlayerCreatureController::getPlayerObject(character);
time_t characterCreateTime = -1;
FreeCtsDataTable::FreeCtsInfo const * freeCtsInfo = nullptr;
bool freeCtsBypassTimeRestriction = false;
if (character && playerObject)
{
characterCreateTime = static_cast<time_t>(NameManager::getInstance().getPlayerCreateTime(character->getNetworkId()));
LOG("CustomerService", ("CharacterTransfer: character object was nullptr so unable to check if bank is loaded"));
freeCtsInfo = FreeCtsDataTable::wouldCharacterTransferBeFree(characterCreateTime, static_cast<uint32>(transferCharacterData.getSourceStationId()), transferCharacterData.getSourceGalaxy(), static_cast<uint32>(transferCharacterData.getDestinationStationId()), transferCharacterData.getDestinationGalaxy(), false);
break;
// see if we can/should bypass the free CTS time restriction
if (!freeCtsInfo && ConfigServerGame::getAllowIgnoreFreeCtsTimeRestriction() && (transferCharacterData.getTransferRequestSource() == TransferRequestMoveValidation::TRS_ingame_freects_command_transfer))
{
// if we got this far and the CTS request came from TRS_ingame_freects_command_transfer, then it
// should be allowed as a free CTS, so do another check bypassing the free CTS time restriction
// check to find any matching free CTS rule, even if the time restriction on the rule has expired
freeCtsInfo = FreeCtsDataTable::wouldCharacterTransferBeFree(characterCreateTime, static_cast<uint32>(transferCharacterData.getSourceStationId()), transferCharacterData.getSourceGalaxy(), static_cast<uint32>(transferCharacterData.getDestinationStationId()), transferCharacterData.getDestinationGalaxy(), true);
if (freeCtsInfo)
{
freeCtsBypassTimeRestriction = true;
}
}
}
LOG("CustomerService", ("CharacterTransfer: Received RequestTransferData for character [character create time (%s) free transfer (%s)] %s", ((characterCreateTime > 0) ? CalendarTime::convertEpochToTimeStringLocal(characterCreateTime).c_str() : "NA"), (freeCtsInfo ? (freeCtsBypassTimeRestriction ? "yes - bypass" : "yes") : "no "), transferCharacterData.toString().c_str()));
bool succeeded = false;
if(ServerWorld::getSceneId() != NewbieTutorial::getSceneId())
case constcrc("RequestLoadCTSBank") :
{
GenericValueTypeMessage<NetworkId> characterId(ri);
LOG("CustomerService", ("CharacterTransfer: ConnectionServerConnection received RequestLoadCTSBank for %s", characterId.getValue().getValueString().c_str()));
CreatureObject * character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(characterId.getValue()));
if(character)
{
// get hair
std::string hairObjectTemplateName;
std::string hairObjectAppearanceData;
SlottedContainer * const container = ContainerInterface::getSlottedContainer(*character);
if(container)
ServerObject *bankContainer = character->getBankContainer();
if (bankContainer)
{
SlotId hairSlot = SlotIdManager::findSlotId(ConstCharCrcString("hair"));
if(hairSlot != SlotId::invalid)
if (!bankContainer->areContentsLoaded())
{
Container::ContainerErrorCode containerErrorCode = Container::CEC_Success;
Container::ContainedItem hairItem = container->getObjectInSlot(hairSlot, containerErrorCode);
const TangibleObject * hairObject = dynamic_cast<const TangibleObject *>(hairItem.getObject());
if(hairObject)
{
hairObjectTemplateName = hairObject->getObjectTemplateName();
hairObjectAppearanceData = hairObject->getAppearanceData();
}
}
}
std::string professionName;
const CreatureObject::SkillList & skills = character->getSkillList();
if (!skills.empty())
{
for (CreatureObject::SkillList::const_iterator i = skills.begin(); i != skills.end(); ++i)
{
const SkillObject * profession = (*i)->findProfessionForSkill();
if (profession != nullptr)
professionName = profession->getSkillName();
}
}
if (professionName.empty())
{
// just get the 1st profession available
PlayerCreationManager::StringVector professions;
PlayerCreationManager::getProfessionVector (professions, "");
if (! professions.empty())
{
professionName = professions[0];
}
}
if (playerObject)
{
// set objvar on the creature indicating that transfer will be free,
// so that script can include the information in the packed dictionary
// so that the information can be transferred to the destination galaxy
// indicating that it's a free transfer
character->removeObjVarItem("freeCtsTransactionRuleName");
if (freeCtsInfo)
IGNORE_RETURN(character->setObjVarItem("freeCtsTransactionRuleName", (freeCtsInfo->ruleName.empty() ? "freeCts" : freeCtsInfo->ruleName)));
std::vector<unsigned char> dictionaryData = character->uploadCharacterData(transferCharacterData.getWithItems(), transferCharacterData.getAllowOverride());
character->removeObjVarItem("freeCtsTransactionRuleName");
if(! dictionaryData.empty())
{
// send the response to the Connection server
TransferCharacterData replyData(transferCharacterData);
replyData.setCustomizationData(character->getAppearanceData());
replyData.setScriptDictionaryData(dictionaryData);
replyData.setObjectTemplateName(character->getObjectTemplateName());
replyData.setObjectTemplateCrc(character->getTemplateCrc());
replyData.setScaleFactor(character->getScaleFactor());
replyData.setHairTemplateName(hairObjectTemplateName);
replyData.setHairAppearanceData(hairObjectAppearanceData);
replyData.setProfession(professionName);
replyData.setSkillTemplate(playerObject->getSkillTemplate());
replyData.setWorkingSkill(playerObject->getWorkingSkill());
GenericValueTypeMessage<TransferCharacterData> reply("ReplyTransferData", replyData);
send(reply, true);
succeeded = true;
LOG("CustomerService", ("CharacterTransfer: setting LoadCTSBank flag and request bank to be loaded for %s", PlayerObject::getAccountDescription(character).c_str()));
character->setLoadCTSBank(true);
bankContainer->loadAllContentsFromDB();
}
else
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Could not retrieve dictionary for character object (%s) for transfer request. %s", requestTransferData.getValue().getCharacterId().getValueString().c_str(), requestTransferData.getValue().toString().c_str()));
LOG("CustomerService", ("CharacterTransfer: bank contents already loaded for %s, sending ReplyBankCTSLoaded back to client", PlayerObject::getAccountDescription(character).c_str()));
//Bank contents are already loaded
GenericValueTypeMessage<NetworkId> reply("ReplyBankCTSLoaded", characterId.getValue());
send(reply, true);
}
}
else
LOG("CustomerService", ("CharacterTransfer: bank container object was nullptr for getBankContainer call"));
}
else
LOG("CustomerService", ("CharacterTransfer: character object was nullptr so unable to check if bank is loaded"));
break;
}
case constcrc("RequestTransferData") :
{
GenericValueTypeMessage<TransferCharacterData> requestTransferData(ri);
const TransferCharacterData & transferCharacterData = requestTransferData.getValue();
CreatureObject * const character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(requestTransferData.getValue().getCharacterId()));
PlayerObject * const playerObject = PlayerCreatureController::getPlayerObject(character);
time_t characterCreateTime = -1;
FreeCtsDataTable::FreeCtsInfo const * freeCtsInfo = nullptr;
bool freeCtsBypassTimeRestriction = false;
if (character && playerObject)
{
characterCreateTime = static_cast<time_t>(NameManager::getInstance().getPlayerCreateTime(character->getNetworkId()));
freeCtsInfo = FreeCtsDataTable::wouldCharacterTransferBeFree(characterCreateTime, static_cast<uint32>(transferCharacterData.getSourceStationId()), transferCharacterData.getSourceGalaxy(), static_cast<uint32>(transferCharacterData.getDestinationStationId()), transferCharacterData.getDestinationGalaxy(), false);
// see if we can/should bypass the free CTS time restriction
if (!freeCtsInfo && ConfigServerGame::getAllowIgnoreFreeCtsTimeRestriction() && (transferCharacterData.getTransferRequestSource() == TransferRequestMoveValidation::TRS_ingame_freects_command_transfer))
{
// if we got this far and the CTS request came from TRS_ingame_freects_command_transfer, then it
// should be allowed as a free CTS, so do another check bypassing the free CTS time restriction
// check to find any matching free CTS rule, even if the time restriction on the rule has expired
freeCtsInfo = FreeCtsDataTable::wouldCharacterTransferBeFree(characterCreateTime, static_cast<uint32>(transferCharacterData.getSourceStationId()), transferCharacterData.getSourceGalaxy(), static_cast<uint32>(transferCharacterData.getDestinationStationId()), transferCharacterData.getDestinationGalaxy(), true);
if (freeCtsInfo)
{
freeCtsBypassTimeRestriction = true;
}
}
}
LOG("CustomerService", ("CharacterTransfer: Received RequestTransferData for character [character create time (%s) free transfer (%s)] %s", ((characterCreateTime > 0) ? CalendarTime::convertEpochToTimeStringLocal(characterCreateTime).c_str() : "NA"), (freeCtsInfo ? (freeCtsBypassTimeRestriction ? "yes - bypass" : "yes") : "no "), transferCharacterData.toString().c_str()));
bool succeeded = false;
if(ServerWorld::getSceneId() != NewbieTutorial::getSceneId())
{
if(character)
{
// get hair
std::string hairObjectTemplateName;
std::string hairObjectAppearanceData;
SlottedContainer * const container = ContainerInterface::getSlottedContainer(*character);
if(container)
{
SlotId hairSlot = SlotIdManager::findSlotId(ConstCharCrcString("hair"));
if(hairSlot != SlotId::invalid)
{
Container::ContainerErrorCode containerErrorCode = Container::CEC_Success;
Container::ContainedItem hairItem = container->getObjectInSlot(hairSlot, containerErrorCode);
const TangibleObject * hairObject = dynamic_cast<const TangibleObject *>(hairItem.getObject());
if(hairObject)
{
hairObjectTemplateName = hairObject->getObjectTemplateName();
hairObjectAppearanceData = hairObject->getAppearanceData();
}
}
}
std::string professionName;
const CreatureObject::SkillList & skills = character->getSkillList();
if (!skills.empty())
{
for (CreatureObject::SkillList::const_iterator i = skills.begin(); i != skills.end(); ++i)
{
const SkillObject * profession = (*i)->findProfessionForSkill();
if (profession != nullptr)
professionName = profession->getSkillName();
}
}
if (professionName.empty())
{
// just get the 1st profession available
PlayerCreationManager::StringVector professions;
PlayerCreationManager::getProfessionVector (professions, "");
if (! professions.empty())
{
professionName = professions[0];
}
}
if (playerObject)
{
// set objvar on the creature indicating that transfer will be free,
// so that script can include the information in the packed dictionary
// so that the information can be transferred to the destination galaxy
// indicating that it's a free transfer
character->removeObjVarItem("freeCtsTransactionRuleName");
if (freeCtsInfo)
IGNORE_RETURN(character->setObjVarItem("freeCtsTransactionRuleName", (freeCtsInfo->ruleName.empty() ? "freeCts" : freeCtsInfo->ruleName)));
std::vector<unsigned char> dictionaryData = character->uploadCharacterData(transferCharacterData.getWithItems(), transferCharacterData.getAllowOverride());
character->removeObjVarItem("freeCtsTransactionRuleName");
if(! dictionaryData.empty())
{
// send the response to the Connection server
TransferCharacterData replyData(transferCharacterData);
replyData.setCustomizationData(character->getAppearanceData());
replyData.setScriptDictionaryData(dictionaryData);
replyData.setObjectTemplateName(character->getObjectTemplateName());
replyData.setObjectTemplateCrc(character->getTemplateCrc());
replyData.setScaleFactor(character->getScaleFactor());
replyData.setHairTemplateName(hairObjectTemplateName);
replyData.setHairAppearanceData(hairObjectAppearanceData);
replyData.setProfession(professionName);
replyData.setSkillTemplate(playerObject->getSkillTemplate());
replyData.setWorkingSkill(playerObject->getWorkingSkill());
GenericValueTypeMessage<TransferCharacterData> reply("ReplyTransferData", replyData);
send(reply, true);
succeeded = true;
}
else
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Could not retrieve dictionary for character object (%s) for transfer request. %s", requestTransferData.getValue().getCharacterId().getValueString().c_str(), requestTransferData.getValue().toString().c_str()));
}
}
else
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Could not load player object (%s) for transfer request. %s", requestTransferData.getValue().getCharacterId().getValueString().c_str(), requestTransferData.getValue().toString().c_str()));
}
}
else
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Could not load player object (%s) for transfer request. %s", requestTransferData.getValue().getCharacterId().getValueString().c_str(), requestTransferData.getValue().toString().c_str()));
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Could not load character object (%s) for transfer request. %s", requestTransferData.getValue().getCharacterId().getValueString().c_str(), requestTransferData.getValue().toString().c_str()));
}
}
else
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Could not load character object (%s) for transfer request. %s", requestTransferData.getValue().getCharacterId().getValueString().c_str(), requestTransferData.getValue().toString().c_str()));
LOG("CustomerService", ("CharacterTransfer: Transfer failed: transfers from the Tutorial are not allowed. %s", transferCharacterData.toString().c_str()));
}
}
else
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: transfers from the Tutorial are not allowed. %s", transferCharacterData.toString().c_str()));
}
if(! succeeded)
{
GenericValueTypeMessage<TransferCharacterData> reply("ReplyTransferDataFail", requestTransferData.getValue());
send(reply, true);
}
}
else if (m.isType("ApplyTransferData"))
{
GenericValueTypeMessage<TransferCharacterData> applyTransferData(ri);
LOG("CustomerService", ("CharacterTransfer: Received ApplyTransferData for character %s", applyTransferData.getValue().toString().c_str()));
const TransferCharacterData & transferCharacterData = applyTransferData.getValue();
CreatureObject * character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(transferCharacterData.getDestinationCharacterId()));
if(character)
{
if(character->receiveCharacterTransferMessage(transferCharacterData.getScriptDictionaryData()))
if(! succeeded)
{
// force CTS failure if the source character has this objvar (which has now been
// transferred to the target character); this is for testing CTS failure handing
if (character->getObjVars().hasItem("testing_only_force_cts_failure_testing_only"))
GenericValueTypeMessage<TransferCharacterData> reply("ReplyTransferDataFail", requestTransferData.getValue());
send(reply, true);
}
break;
}
case constcrc("ApplyTransferData") :
{
GenericValueTypeMessage<TransferCharacterData> applyTransferData(ri);
LOG("CustomerService", ("CharacterTransfer: Received ApplyTransferData for character %s", applyTransferData.getValue().toString().c_str()));
const TransferCharacterData & transferCharacterData = applyTransferData.getValue();
CreatureObject * character = dynamic_cast<CreatureObject *>(NetworkIdManager::getObjectById(transferCharacterData.getDestinationCharacterId()));
if(character)
{
if(character->receiveCharacterTransferMessage(transferCharacterData.getScriptDictionaryData()))
{
GenericValueTypeMessage<TransferCharacterData> applyTransferDataFail("ApplyTransferDataFail", transferCharacterData);
send(applyTransferDataFail, true);
LOG("CustomerService", ("CharacterTransfer: *** ERROR: Character has testing_only_force_cts_failure_testing_only objvar, sending ApplyTransferDataFail to central %s", applyTransferData.getValue().toString().c_str()));
// force CTS failure if the source character has this objvar (which has now been
// transferred to the target character); this is for testing CTS failure handing
if (character->getObjVars().hasItem("testing_only_force_cts_failure_testing_only"))
{
GenericValueTypeMessage<TransferCharacterData> applyTransferDataFail("ApplyTransferDataFail", transferCharacterData);
send(applyTransferDataFail, true);
LOG("CustomerService", ("CharacterTransfer: *** ERROR: Character has testing_only_force_cts_failure_testing_only objvar, sending ApplyTransferDataFail to central %s", applyTransferData.getValue().toString().c_str()));
}
else
{
GenericValueTypeMessage<TransferCharacterData> applyTransferDataSuccess("ApplyTransferDataSuccess", transferCharacterData);
send(applyTransferDataSuccess, true);
LOG("CustomerService", ("CharacterTransfer: Sending ApplyTransferDataSuccess for character %s", applyTransferData.getValue().toString().c_str()));
}
}
else
{
GenericValueTypeMessage<TransferCharacterData> applyTransferDataSuccess("ApplyTransferDataSuccess", transferCharacterData);
send(applyTransferDataSuccess, true);
LOG("CustomerService", ("CharacterTransfer: Sending ApplyTransferDataSuccess for character %s", applyTransferData.getValue().toString().c_str()));
GenericValueTypeMessage<TransferCharacterData> applyTransferDataFail("ApplyTransferDataFail", transferCharacterData);
send(applyTransferDataFail, true);
LOG("CustomerService", ("CharacterTransfer: *** ERROR: Sending ApplyTransferDataFail for character %s", applyTransferData.getValue().toString().c_str()));
}
}
else
{
GenericValueTypeMessage<TransferCharacterData> applyTransferDataFail("ApplyTransferDataFail", transferCharacterData);
send(applyTransferDataFail, true);
LOG("CustomerService", ("CharacterTransfer: *** ERROR: Sending ApplyTransferDataFail for character %s", applyTransferData.getValue().toString().c_str()));
LOG("CustomerService", ("CharacterTransfer: *** ERROR: Could not find object for character, sending ApplyTransferDataFail to central %s", applyTransferData.getValue().toString().c_str()));
}
break;
}
else
case constcrc("ChatEnterRoomValidationRequest") :
{
GenericValueTypeMessage<TransferCharacterData> applyTransferDataFail("ApplyTransferDataFail", transferCharacterData);
send(applyTransferDataFail, true);
LOG("CustomerService", ("CharacterTransfer: *** ERROR: Could not find object for character, sending ApplyTransferDataFail to central %s", applyTransferData.getValue().toString().c_str()));
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, unsigned int> > const cervreq(readIterator);
unsigned int result = CHATRESULT_SUCCESS;
ServerObject const * const o = ServerWorld::findObjectByNetworkId(cervreq.getValue().first.first);
CreatureObject const * const co = (o ? o->asCreatureObject() : nullptr);
if (co)
{
result = Chat::isAllowedToEnterRoom(*co, cervreq.getValue().first.second);
}
else
{
result = SWG_CHAT_ERR_INVALID_OBJECT;
}
GenericValueTypeMessage<std::pair<std::pair<NetworkId, unsigned int>, unsigned int> > const cervresp(
"ChatEnterRoomValidationResponse",
std::make_pair(
std::make_pair(cervreq.getValue().first.first, result),
cervreq.getValue().second));
send(cervresp, true);
break;
}
}
else if (m.isType("ChatEnterRoomValidationRequest"))
{
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, unsigned int> > const cervreq(readIterator);
unsigned int result = CHATRESULT_SUCCESS;
ServerObject const * const o = ServerWorld::findObjectByNetworkId(cervreq.getValue().first.first);
CreatureObject const * const co = (o ? o->asCreatureObject() : nullptr);
if (co)
case constcrc("ChatQueryRoomValidationRequest") :
{
result = Chat::isAllowedToEnterRoom(*co, cervreq.getValue().first.second);
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, unsigned int> > const cqrvreq(readIterator);
bool success = false;
ServerObject const * const o = ServerWorld::findObjectByNetworkId(cqrvreq.getValue().first.first);
CreatureObject const * const co = (o ? o->asCreatureObject() : nullptr);
if (co)
{
success = (CHATRESULT_SUCCESS == Chat::isAllowedToEnterRoom(*co, cqrvreq.getValue().first.second));
}
GenericValueTypeMessage<std::pair<std::pair<NetworkId, bool>, unsigned int> > const cqrvresp(
"ChatQueryRoomValidationResponse",
std::make_pair(
std::make_pair(cqrvreq.getValue().first.first, success),
cqrvreq.getValue().second));
send(cqrvresp, true);
break;
}
else
case constcrc("PlayerDroppedFromGameServerCrash") :
{
result = SWG_CHAT_ERR_INVALID_OBJECT;
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::set<NetworkId> > const m(readIterator);
std::map<NetworkId, LfgCharacterData> const & connectedCharacterLfgData = ServerUniverse::getConnectedCharacterLfgData();
std::map<NetworkId, Unicode::String> const & connectedCharacterBiographyData = ServerUniverse::getConnectedCharacterBiographyData();
std::set<NetworkId>::const_iterator const end = m.getValue().end();
for (std::set<NetworkId>::const_iterator iter = m.getValue().begin(); iter != end; ++iter)
{
if (connectedCharacterLfgData.count(*iter) > 0)
ServerUniverse::removeConnectedCharacterData(*iter);
if (connectedCharacterBiographyData.count(*iter) > 0)
ServerUniverse::removeConnectedCharacterBiographyData(*iter);
}
break;
}
GenericValueTypeMessage<std::pair<std::pair<NetworkId, unsigned int>, unsigned int> > const cervresp(
"ChatEnterRoomValidationResponse",
std::make_pair(
std::make_pair(cervreq.getValue().first.first, result),
cervreq.getValue().second));
send(cervresp, true);
}
else if (m.isType("ChatQueryRoomValidationRequest"))
{
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::pair<std::pair<NetworkId, std::string>, unsigned int> > const cqrvreq(readIterator);
bool success = false;
ServerObject const * const o = ServerWorld::findObjectByNetworkId(cqrvreq.getValue().first.first);
CreatureObject const * const co = (o ? o->asCreatureObject() : nullptr);
if (co)
default :
{
success = (CHATRESULT_SUCCESS == Chat::isAllowedToEnterRoom(*co, cqrvreq.getValue().first.second));
ServerConnection::emitMessage(m);
break;
}
GenericValueTypeMessage<std::pair<std::pair<NetworkId, bool>, unsigned int> > const cqrvresp(
"ChatQueryRoomValidationResponse",
std::make_pair(
std::make_pair(cqrvreq.getValue().first.first, success),
cqrvreq.getValue().second));
send(cqrvresp, true);
}
else if (m.isType("PlayerDroppedFromGameServerCrash"))
{
Archive::ReadIterator readIterator = message.begin();
GenericValueTypeMessage<std::set<NetworkId> > const m(readIterator);
std::map<NetworkId, LfgCharacterData> const & connectedCharacterLfgData = ServerUniverse::getConnectedCharacterLfgData();
std::map<NetworkId, Unicode::String> const & connectedCharacterBiographyData = ServerUniverse::getConnectedCharacterBiographyData();
std::set<NetworkId>::const_iterator const end = m.getValue().end();
for (std::set<NetworkId>::const_iterator iter = m.getValue().begin(); iter != end; ++iter)
{
if (connectedCharacterLfgData.count(*iter) > 0)
ServerUniverse::removeConnectedCharacterData(*iter);
if (connectedCharacterBiographyData.count(*iter) > 0)
ServerUniverse::removeConnectedCharacterBiographyData(*iter);
}
}
else
{
ServerConnection::emitMessage(m);
}
}