File: EntityRouter.cpp

package info (click to toggle)
eris 1.3.10-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 2,592 kB
  • ctags: 1,516
  • sloc: cpp: 9,850; sh: 8,288; perl: 287; ansic: 165; makefile: 162
file content (116 lines) | stat: -rw-r--r-- 3,301 bytes parent folder | download
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