khanat-opennel-code/code/ryzom/server/src/ai_service/alias_tree_owner.cpp

170 lines
5.9 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "alias_tree_owner.h"
#include "nel/misc/variable.h"
using namespace AITYPES;
extern NLMISC::CVariable<bool> LogAliasTreeOwner;
CAliasTreeOwnerLocator* CAliasTreeOwnerLocator::_Instance = NULL;
CAliasTreeOwnerLocator* CAliasTreeOwnerLocator::getInstance()
{
if (!_Instance)
_Instance = new CAliasTreeOwnerLocator();
return _Instance;
}
CAliasTreeOwner* CAliasTreeOwnerLocator::getEntity(uint32 const alias) const
{
std::map<uint32, CAliasTreeOwner*>::const_iterator it = _EntitiesByAlias.find(alias);
if (it!=_EntitiesByAlias.end())
return it->second;
else
return NULL;
}
CAliasTreeOwner* CAliasTreeOwnerLocator::getEntity(std::string const& name) const
{
std::map<std::string, CAliasTreeOwner*>::const_iterator it = _EntitiesByName.find(name);
if (it!=_EntitiesByName.end())
return it->second;
else
return NULL;
}
void CAliasTreeOwnerLocator::addEntity(uint32 const alias, std::string const& name, CAliasTreeOwner* entity)
{
_EntitiesByAlias.insert(std::make_pair(alias, entity));
_EntitiesByName.insert(std::make_pair(name, entity));
}
void CAliasTreeOwnerLocator::delEntity(uint32 const alias, std::string const& name, CAliasTreeOwner* entity)
{
_EntitiesByName.erase(name);
_EntitiesByAlias.erase(alias);
}
std::vector<NLMISC::CDbgPtr<CAliasTreeOwner> > CAliasTreeOwner::_CurrentOwnerList;
void CAliasTreeOwner::updateAliasTree(const CAIAliasDescriptionNode &newTree)
{
_CurrentOwnerList.push_back(this);
// check if this objet already have an associated Tree :)
if (getAliasNode())
{
CAIAliasDescriptionNode &oldTree = *getAliasNode();
// scan my own alias tree and make sure that everything listed still exists in the new tree
// Check for no more existing Alias Nodes ..
// scan destruction is reverse for coherence with construction.
for (int i=oldTree.getChildCount()-1;i>=0;i--)
{
CAIAliasDescriptionNode*const oldChild=oldTree.getChild(i);
// search new alias tree for a record corresponding to the one we're on in the old tree
if (!newTree.getChildByAlias (oldChild->getAlias()))
{
//nlstop("Have to parse the rest of child because a cchild may have been added in the upper hierarchy");
// LOG("updateAliasTreeDelete(): deleting: %s:%u (%s)", getName(oldChild->getType()), oldChild->getAlias(), oldChild->fullName().c_str());
// if (!updateAliasTreeDelete(oldChild))
// nlwarning("updateAliasTreeDelete(): Don't know how to deal with node: %s:%u (%s)", getName(oldChild->getType()), oldChild->getAlias(), oldChild->fullName().c_str());
IAliasCont*const cont = getAliasCont(oldChild->getType());
if (cont)
cont->removeChildByAlias(oldChild->getAlias()); // smartPtr will do the job if necessary.
}
}
}
// scan the new alias tree for entries that aren't in the old tree
// Check for new existing Alias Nodes ..
for (uint j=0;j<newTree.getChildCount();j++)
{
CAIAliasDescriptionNode*const newAliasChild = newTree.getChild(j);
CAliasTreeOwner* currentDeeperChild=this;
breakable
{
// special case, the node represents a folder. Have to parse him normally on the current object.
if (newAliasChild->getType()==AITypeFolder)
break;
CAliasTreeOwner* childOwner = NULL;
IAliasCont* cont = NULL;
// we try to get a valid IAliasCont for this type.
if (!getCont(childOwner,cont,newAliasChild->getType()))
{
// kick hack to prevent special parsing case.
if ( newAliasChild->getType()!=AITypeEventAction
&& newAliasChild->getType()!=AITypeFaunaSpawnAtom )
{
if (LogAliasTreeOwner)
nlwarning("ATO: '%s' not found in '%s', Skeeping ..", std::string(AITYPES::getName(newAliasChild->getType())).c_str(), getName().c_str() );
}
break;
}
CAliasTreeOwner* child = cont->getAliasChildByAlias(newAliasChild->getAlias());
if (!child) // a child related to this alias not yet exists ..
{
// so we ask to create one objet of this type ( implementation is specialized :) )
// giving it the so precious CAIAliasDescriptionNode.
// assumes that it adds the child to its parent ( check by the next assert ).
child=childOwner->createChild(cont,newAliasChild);
nlassert(cont->getAliasChildByAlias(newAliasChild->getAlias())!=NULL);
if (LogAliasTreeOwner)
nldebug("ATO: In '%s' @ %p, created child '%s' @ %p", this->getName().c_str(), this, child->getName().c_str(), child);
}
if (!child)
{
nlwarning("ATO: Cannot create child '%s' in '%s', Skeeping ..", std::string(AITYPES::getName(newAliasChild->getType())).c_str(), getName().c_str() );
break;
}
currentDeeperChild=child;
}
currentDeeperChild->updateAliasTree(*newAliasChild);
updateDependencies(*newAliasChild, currentDeeperChild);
}
_CurrentOwnerList.pop_back();
}
bool CAliasTreeOwner::getCont(CAliasTreeOwner *&childOwner, IAliasCont *&cont, TAIType _type)
{
std::vector<NLMISC::CDbgPtr<CAliasTreeOwner> >::reverse_iterator first(_CurrentOwnerList.rbegin()), last(_CurrentOwnerList.rend());
for (; first != last; ++first)
{
cont=(*first)->getAliasCont(_type);
if (!cont)
continue;
childOwner = *first;
return true;
}
return false;
}