1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Eris/EntityRouter.h>
#include <Eris/LogStream.h>
#include <Eris/Entity.h>
#include <Eris/TypeService.h>
#include <Eris/Avatar.h>
#include <Eris/TypeInfo.h>
#include <Eris/View.h>
#include <Eris/Connection.h>
#include <Eris/TypeBoundRedispatch.h>
#include <Atlas/Objects/Operation.h>
#include <Atlas/Objects/Entity.h>
using namespace Atlas::Objects::Operation;
using Atlas::Objects::Root;
using Atlas::Objects::smart_dynamic_cast;
namespace Eris {
EntityRouter::EntityRouter(Entity* ent) :
m_entity(ent)
{
assert(ent);
}
EntityRouter::~EntityRouter()
{
}
Router::RouterResult EntityRouter::handleOperation(const RootOperation& op)
{
assert(op->getFrom() == m_entity->getId());
const std::vector<Root>& args = op->getArgs();
// note it's important we match exactly on sight here, and not deried ops
// like appearance and disappearance
if (op->getClassNo() == SIGHT_NO) {
assert(!args.empty());
RootOperation sop = smart_dynamic_cast<RootOperation>(args.front());
if (sop.isValid()) return handleSightOp(sop);
}
if (op->getClassNo() == SOUND_NO) {
assert(!args.empty());
if (args.front()->getClassNo() == TALK_NO)
{
RootOperation talk = smart_dynamic_cast<RootOperation>(args.front());
m_entity->onTalk(talk);
return HANDLED;
}
TypeInfo* ty = typeService()->getTypeForAtlas(args.front());
if (!ty->isBound()) {
new TypeBoundRedispatch(m_entity->getView()->getAvatar()->getConnection(), op, ty);
return WILL_REDISPATCH;
}
if (ty->isA(typeService()->getTypeByName("action")))
{
// sound of action
RootOperation act = smart_dynamic_cast<RootOperation>(args.front());
m_entity->onSoundAction(act);
return HANDLED;
}
debug() << "entity " << m_entity->getId() << " emitted sound with strange argument: " << op;
// other sounds !
}
return IGNORED;
}
Router::RouterResult EntityRouter::handleSightOp(const RootOperation& op)
{
const std::vector<Root>& args = op->getArgs();
if (op->getClassNo() == MOVE_NO) {
// sight of move, we handle as a specialization of set.
assert(!args.empty());
const Root & arg = args.front();
// break out LOC, which MOVE ops are allowed to update
if (arg->hasAttr("loc")) {
m_entity->setLocationFromAtlas(arg->getAttr("loc").asString());
}
m_entity->setFromRoot(arg, true /* movement allowed */);
return HANDLED;
}
if (op->instanceOf(IMAGINARY_NO)) {
if (args.empty())
error() << "entity " << m_entity->getId() << " sent imaginary with no args: " << op;
else
m_entity->onImaginary(args.front());
return HANDLED;
}
// explicitly do NOT handle set ops here, since they can
// validly change multiple entities - handled by the IGRouter
return IGNORED;
}
TypeService* EntityRouter::typeService()
{
return m_entity->getView()->getAvatar()->getConnection()->getTypeService();
}
} // of namespace Eris
|