// ====================================================================== // // ContainmentMessageManager.cpp // // Copyright 2003 Sony Online Entertainment // // ====================================================================== #include "serverGame/FirstServerGame.h" #include "serverGame/ContainmentMessageManager.h" #include "serverGame/ConnectionServerConnection.h" #include "serverGame/ContainerInterface.h" #include "serverGame/DistributionListStack.h" #include "serverGame/ServerObject.h" #include "serverNetworkMessages/GameConnectionServerMessages.h" #include "sharedNetworkMessages/UpdateContainmentMessage.h" #include "sharedObject/ContainedByProperty.h" #include "sharedObject/SlottedContainmentProperty.h" #include // ====================================================================== // // Order of containment messages is preserved, and changes are sent for any objects that still exist. // Containment states for each update are as of the time at which the message is added, to preserve causality. // // ====================================================================== namespace ContainmentMessageManagerNamespace { // ---------------------------------------------------------------------- class ContainmentMessageData { public: ContainmentMessageData(); explicit ContainmentMessageData(ServerObject &object); void update() const; private: Watcher m_watcher; NetworkId m_containedBy; int m_currentArrangement; }; // ---------------------------------------------------------------------- std::vector s_containmentMessages; std::map > s_frameBaselines; // ---------------------------------------------------------------------- std::set const *getClientBaselinesThisFrame(NetworkId const &networkId); // ---------------------------------------------------------------------- } using namespace ContainmentMessageManagerNamespace; // ====================================================================== void ContainmentMessageManager::addContainmentMessage(ServerObject &object) { s_containmentMessages.push_back(ContainmentMessageData(object)); } // ---------------------------------------------------------------------- void ContainmentMessageManager::addFrameBaselines(NetworkId const &networkId, std::vector > const &distributionList) { std::set& baselines = s_frameBaselines[networkId]; for (std::vector >::const_iterator i = distributionList.begin(); i != distributionList.end(); ++i) IGNORE_RETURN(baselines.insert(*i)); } // ---------------------------------------------------------------------- void ContainmentMessageManager::update() { for (std::vector::iterator i = s_containmentMessages.begin(); i != s_containmentMessages.end(); ++i) (*i).update(); s_containmentMessages.clear(); s_frameBaselines.clear(); } // ---------------------------------------------------------------------- ContainmentMessageManagerNamespace::ContainmentMessageData::ContainmentMessageData() : m_watcher(), m_containedBy(NetworkId::cms_invalid), m_currentArrangement(-1) { } // ---------------------------------------------------------------------- ContainmentMessageManagerNamespace::ContainmentMessageData::ContainmentMessageData(ServerObject &object) : m_watcher(&object), m_containedBy(ContainerInterface::getContainedByProperty(object)->getContainedByNetworkId()), m_currentArrangement(ContainerInterface::getSlottedContainmentProperty(object)->getCurrentArrangement()) { } // ---------------------------------------------------------------------- void ContainmentMessageManagerNamespace::ContainmentMessageData::update() const { static std::set clientResultSet; ServerObject * const obj = m_watcher.getPointer(); if (obj) { std::set const &observers = obj->getObservers(); std::set const * const baselines = getClientBaselinesThisFrame(obj->getNetworkId()); std::set const *clients; if (!baselines) clients = &observers; else { clientResultSet.clear(); std::insert_iterator > insertIter(clientResultSet, clientResultSet.begin()); IGNORE_RETURN(std::set_difference(observers.begin(), observers.end(), baselines->begin(), baselines->end(), insertIter)); clients = &clientResultSet; } std::map > &tmpDistributionList = DistributionListStack::alloc(); for (std::set::const_iterator i = clients->begin(); i != clients->end(); ++i) tmpDistributionList[(*i)->getConnection()].push_back((*i)->getCharacterObjectId()); if (!tmpDistributionList.empty()) { UpdateContainmentMessage const ucm(obj->getNetworkId(), m_containedBy, m_currentArrangement); for (std::map >::const_iterator j = tmpDistributionList.begin(); j != tmpDistributionList.end(); ++j) { GameClientMessage const gcm((*j).second, true, ucm); (*j).first->send(gcm, true); } } DistributionListStack::release(); clientResultSet.clear(); } } // ---------------------------------------------------------------------- std::set const *ContainmentMessageManagerNamespace::getClientBaselinesThisFrame(NetworkId const &networkId) { std::map >::const_iterator i = s_frameBaselines.find(networkId); if (i != s_frameBaselines.end()) return &((*i).second); return 0; } // ======================================================================