khanat-opennel-code/code/ryzom/server/src/ags_test/actor_manager.cpp
acemtp@users.sourceforge.net d5c601ffa5 initial version
2010-05-06 02:08:41 +02:00

440 lines
12 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/>.
// Nel
//#include "nel/net/service.h"
// Local headers
#include "position_generator.h"
#include "actor_manager.h"
#include "sheets.h"
#include <nel/net/unified_network.h>
#include "game_share/people.h"
#include "game_share/synchronised_message.h"
#include "nel/misc/variable.h"
#include <set>
using namespace NLMISC;
using namespace NLNET;
using namespace std;
namespace AGS_TEST
{
//-------------------------------------------------------------------------
// Some global variables
extern uint32 GlobalActorCount;
extern uint32 GlobalActorUpdates;
extern uint32 GlobalActorMoves;
CEntityId LastActorId;
NLMISC_DYNVARIABLE(string, LastActorId, "Last created actor")
{
if (get)
*pointer = LastActorId.toString();
else
LastActorId.fromString((*pointer).c_str());
}
//-------------------------------------------------------------------------
// Some function prototypes
static void cbServiceUp( const string& serviceName, uint16 serviceId, void * );
static void cbServiceDown( const string& serviceName, uint16 serviceId, void * );
//------------------------------------------------------------------------
// static data for CActorManager
std::vector<CActor*> CActorManager::_actors;
std::vector<CActorGroup*> CActorManager::_actorGroups;
int CActorManager::_nextActorID=0;
std::set<uint> CActorManager::_visionHandlingServices;
CActorGroup *CActorManager::_defaultActorGroup;
//------------------------------------------------------------------------
// basic functionality for CActorManager singleton
void CActorManager::init()
{
static bool first_time=true;
if (first_time)
{
// Init callback for service up / down
CUnifiedNetwork::getInstance()->setServiceUpCallback ("*", cbServiceUp, NULL);
CUnifiedNetwork::getInstance()->setServiceDownCallback("*", cbServiceDown, NULL);
first_time=false;
}
else
release();
_nextActorID=0;
/*
CPositionGenerator::setPattern(std::string("grid"));
CPositionGenerator::setPosition(17981,-33200);
CPositionGenerator::setSpacing(2000);
*/
_defaultActorGroup = newActorGroup("defaultGroup");
}
void CActorManager::update()
{
set< pair<sint32, sint32> > iaZones;
std::vector<CActorGroup*>::iterator itg;
for (itg=_actorGroups.begin(); itg!=_actorGroups.end(); ++itg)
(*itg)->update();
// iterate through all known actors, calling their update
uint16 positionChangeCount=0;
uint16 updateCount=0;
std::vector<CActor*>::iterator it;
for (it=_actors.begin(); it!=_actors.end(); ++it)
{
bool updated= (*it)->update();
if (updated)
updateCount++;
/*
if ((*it)->positionChanged())
positionChangeCount++;
sint32 zx = (*it)->getX()/160000;
sint32 zy = -(*it)->getY()/160000;
iaZones.insert(make_pair<sint32,sint32>(zx, zy));
*/
}
// for all entities, request vision zones
/*CMessage msg("AGENT_VISON");
sint64 fakeId = 0;
msg.serial(fakeId);
sint32 pos = msg.getPos();
set< pair<sint32, sint32> >::iterator itz;
for (itz=iaZones.begin(); itz!=iaZones.end(); ++itz)
{
sint32 x = (*itz).first,
y = (*itz).second;
msg.serial(x);
msg.serial(y);
}
if (msg.getPos() > pos)
CUnifiedNetwork::getInstance()->send("GPMS", msg);*/
/*
// build the position changed message and send it to GPMS
if (positionChangeCount>0)
{
NLNET::CMessage gpmPosMsg("UPDATE_ENTITIES_POSITIONS");
gpmPosMsg.serial(positionChangeCount);
for (it=_actors.begin(); it!=_actors.end(); ++it)
(*it)->addPositionChangesToMessage(gpmPosMsg);
sendMessageViaMirror( "GPMS", gpmPosMsg );
}
*/
GlobalActorUpdates=updateCount;
//GlobalActorMoves=positionChangeCount;
}
void CActorManager::release()
{
std::vector<CActor*>::iterator it;
for (it=_actors.begin(); it!=_actors.end(); ++it)
{
(*it)->removeFromOtherServices();
}
_actors.clear();
}
// Callback called at service connexion
static void cbServiceUp( const string& serviceName, uint16 serviceId, void * )
{
/*if (serviceName==std::string("EGS"))
CActorManager::reconnectEGS((uint8)serviceId);
if (serviceName==std::string("IOS"))
CActorManager::reconnectIOS((uint8)serviceId);
if (serviceName==std::string("GPMS"))
CActorManager::reconnectGPMS((uint8)serviceId);*/
/*CMessage reqVision("ASK_VISION_ZONE");
CUnifiedNetwork::getInstance()->send(serviceId, reqVision);*/
}
//
static void cbServiceDown( const string& serviceName, uint16 serviceId, void * )
{
CActorManager::removeVisionService(serviceId);
}
//---------------------------------------------------------------------------------
// methods for dealing with tardy connection of a key service
/*void CActorManager::reconnectEGS(uint8 serviceId)
{
}
void CActorManager::reconnectIOS(uint8 serviceId)
{
std::vector<CActor*>::iterator it;
for (it=_actors.begin(); it!=_actors.end(); ++it)
{
(*it)->addToIOS(serviceId);
}
}
void CActorManager::reconnectGPMS(uint8 serviceId)
{
std::vector<CActor*>::iterator it;
for (it=_actors.begin(); it!=_actors.end(); ++it)
{
(*it)->addToGPMS(serviceId);
}
}*/
//---------------------------------------------------------------------------------
// CActorManager methods for creating and killing actors
// method for adding a new actor to the scene
CActor *CActorManager::newActor(const std::string &type, const std::string &name)
{
LastActorId = CEntityId::Unknown;
if (getActor(name)!=NULL)
{
nlinfo("Actor already exists: %s",name.c_str());
return NULL;
}
CSheetId sheetId(type);
const CSheets::CSheet *sheet=CSheets::lookup(sheetId);
if (!sheet)
{
nlwarning("ERROR: Can't find static type data for '%s'(%d) for entity %s", type.c_str(), sheetId.asInt(), name.c_str());
return NULL;
}
// create a new actor record and COPY it into the actor vector
// EGSPD::CPeople::TPeople p_type = EGSPD::CPeople::fromString( type );
bool success = false;
CActor *aNewActor;
if ( sheet->isNpc /*EGSPD::CPeople::isPlayableRace( p_type )*/ )
aNewActor = new CActor(type,name,CEntityId(RYZOMID::npc,_nextActorID++),success);
else
aNewActor = new CActor(type,name,CEntityId(RYZOMID::creature,_nextActorID++),success);
if ( ! success )
{
if (aNewActor)
delete aNewActor;
return NULL;
}
LastActorId = aNewActor->_id;
int x,y;
CPositionGenerator::next(x,y);
aNewActor->setPos(x, y, 0);
aNewActor->setAngle(0);
_actors.push_back(aNewActor);
// get hold of a pointer of the copy of the actor in the actor vector
CActor *theActor=getActor(name);
// add the actor to the GPMS, the IOS, etc
if (theActor!=0)
theActor->addToOtherServices();
/*
CMessage msgMode("SET_MODE");
TDataSetRow index = CMirrors::DataSet->getDataSetRow(theActor->_id);
msgMode.serial(index);
MBEHAV::TMode mode(MBEHAV::NORMAL, x, y);
msgMode.serial(mode);
sendMessageViaMirror("EGS", msgMode);
*/
CMirrors::initSheet( aNewActor->getSid(), sheetId ); // initialize out the sheet
// Let the position & angle & tick be sent ("UPDATE_ENTITIES_POSITIONS") in update
//aNewActor->initMode();
MBEHAV::TMode mode(MBEHAV::NORMAL, x, y);
theActor->_mode = mode.RawModeAndParam;
aNewActor->display();
theActor->setGroup(_defaultActorGroup);
GlobalActorCount++;
return theActor;
}
// method for retrievng a pointer to a named actor
// returns NULL if the actor doesn't exist
CActor *CActorManager::getActor(const std::string &name)
{
std::vector<CActor*>::iterator it;
for (it=_actors.begin(); it!=_actors.end(); ++it)
{
if ((*it)->getName()==name)
return (*it);
}
return 0;
}
// method for retrievng a pointer to given actor
CActor *CActorManager::getActor(unsigned index)
{
if (index>=_actors.size())
return NULL;
else
return (_actors[index]);
}
// method for retrievng a pointer to given actor
CActor *CActorManager::getActor(const NLMISC::CEntityId &id)
{
std::vector<CActor*>::iterator it;
for (it=_actors.begin(); it!=_actors.end(); ++it)
{
if ((*it)->getSid()==id)
return (*it);
}
return NULL;
}
void CActorManager::killActor(const std::string &name)
{
std::vector<CActor*>::iterator it;
for (it=_actors.begin(); it!=_actors.end(); ++it)
{
if ((*it)->getName()==name)
{
// remove from net refferences
(*it)->removeFromOtherServices();
// remove from vision xrefs
std::vector<CActor*>::iterator it2;
for (it2=_actors.begin(); it2!=_actors.end(); ++it2)
{
(*it2)->removeRefs(*it);
}
for (int i=_actorGroups.size();i--;)
_actorGroups[i]->removeActor(*it);
// remove from container
delete *it;
_actors.erase(it);
GlobalActorCount--;
return;
}
}
}
//------------------------------------------------------------------------
// basic functionality for actor group management
// method for adding a new actorGroup to the scene
CActorGroup *CActorManager::newActorGroup(const std::string &name)
{
if (!getActorGroup(name))
{
// create a new actorGroup record and COPY it into the actorGroup vector
CActorGroup *aNewActorGroup = new CActorGroup(name);
_actorGroups.push_back(aNewActorGroup);
aNewActorGroup->display();
}
// get hold of a pointer of the copy of the actorGroup in the actorGroup vector
return getActorGroup(name);
}
// method for retrievng a pointer to a named actorGroup
// returns NULL if the actorGroup doesn't exist
CActorGroup *CActorManager::getActorGroup(const std::string &name)
{
std::vector<CActorGroup*>::iterator it;
for (it=_actorGroups.begin(); it!=_actorGroups.end(); ++it)
{
if ((*it)->getName()==name)
return (*it);
}
return NULL;
}
// method for retrievng a pointer to given actorGroup
CActorGroup *CActorManager::getActorGroup(unsigned index)
{
if (index>=_actorGroups.size())
return NULL;
else
return (_actorGroups[index]);
}
void CActorManager::removeActorGroup(const std::string &name)
{
std::vector<CActorGroup*>::iterator it;
for (it=_actorGroups.begin(); it!=_actorGroups.end(); ++it)
{
if ((*it)->getName()==name)
{
// remove all actors from this group into default group
uint i;
for (i=0; i<(*it)->actorCount(); ++i)
(*(*it))[i]->setGroup(_defaultActorGroup);
// remove from container
delete (*it);
_actorGroups.erase(it);
return;
}
}
}
//
void CActorManager::setActorsToGroup(const std::string &sourceActorGroup, const std::string &destActorGroup)
{
CActorGroup *srcGroup = getActorGroup(sourceActorGroup);
if (srcGroup == NULL)
{
nlwarning("source actor group '%s' is unknown, abort setActorsToGroup(%s, %s)", sourceActorGroup.c_str(), sourceActorGroup.c_str(), destActorGroup.c_str());
return;
}
CActorGroup *destGroup = getActorGroup(destActorGroup);
if (destGroup == NULL)
{
nlwarning("destination actor group '%s' is unknown, abort setActorsToGroup(%s, %s)", destActorGroup.c_str(), sourceActorGroup.c_str(), destActorGroup.c_str());
return;
}
uint i;
for (i=0; i<srcGroup->actorCount(); ++i)
(*srcGroup)[i]->setGroup(destGroup);
}
} // end of namespace AGS_TEST