void ClientConnection::dispatch(const RootOperation& op) { const std::vector<Root>& args = op->getArgs(); if (op->getFrom().empty()) { if (m_account.empty()) { // not logged in yet if (op->getClassNo() == LOGIN_NO) { processLogin(smart_dynamic_cast<Login>(op)); return; } if (op->getClassNo() == CREATE_NO) { assert(!args.empty()); processAccountCreate(smart_dynamic_cast<Create>(op)); return; } } if (op->getClassNo() == GET_NO) { processAnonymousGet(smart_dynamic_cast<Get>(op)); return; } if (op->getClassNo() == LOGOUT_NO) { return; } throw TestFailure("got anonymous op I couldn't dispatch"); } if (op->getFrom() == m_account) { dispatchOOG(op); return; } if (m_agents.count(op->getFrom())) { m_agents[op->getFrom()]->processOp(op); return; } if (entityIsCharacter(op->getFrom())) { // IG activation activateCharacter(op->getFrom(), op); return; } debug() << "totally failed to handle operation " << objectSummary(op); }
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; } warning() << "entity " << m_entity->getId() << " emitted sound with strange argument: " << op; // other sounds ! } return IGNORED; }
int AccountContext::dispatch(const RootOperation & op) { std::cout << "Dispatching with account context to see if it matches" << std::endl << std::flush; if (op->getClassNo() == Atlas::Objects::Operation::INFO_NO && !op->getArgs().empty()) { std::cout << "Dispatching info" << std::endl << std::flush; const Root & ent = op->getArgs().front(); if (ent->hasAttrFlag(Atlas::Objects::ID_FLAG) && ent->hasAttrFlag(Atlas::Objects::PARENTS_FLAG) && ent->getParents().size() > 0) { const std::string & type = ent->getParents().front(); if (type == "juncture") { std::cout << "created juncture" << std::endl << std::flush; m_client.addCurrentContext(shared_ptr<ObjectContext>( new JunctureContext(m_client, ent->getId()))); } else { std::cout << "created avatar" << std::endl << std::flush; m_client.addCurrentContext(shared_ptr<ObjectContext>( new AvatarContext(m_client, ent->getId()))); } } else { // FIXME Report an error? } } else if (op->getClassNo() == Atlas::Objects::Operation::SIGHT_NO && !op->getArgs().empty()) { std::cout << "Sight(" << std::endl; m_client.output(op->getArgs().front()); std::cout << ")" << std::endl << std::flush; } assert(m_refNo != 0L); m_refNo = 0L; return 0; }
void ClientConnection::dispatchOOG(const RootOperation& op) { switch (op->getClassNo()) { case LOOK_NO: processOOGLook(smart_dynamic_cast<Look>(op)); return; case MOVE_NO: return; case TALK_NO: { Talk tk = smart_dynamic_cast<Talk>(op); processTalk(tk); return; } case LOGOUT_NO: { Logout logout = smart_dynamic_cast<Logout>(op); Info logoutInfo; logoutInfo->setArgs1(logout); logoutInfo->setTo(m_account); logoutInfo->setRefno(logout->getSerialno()); send(logoutInfo); return; } case CREATE_NO: { const StringList& arg0Parents(op->getArgs().front()->getParents()); if (arg0Parents.front() == "__fail__") { sendError("bad type for char creation", op); return; } if (arg0Parents.front() == "settler") { createCharacter(op); return; } } default: error() << "clientConnection failed to handle OOG op"; } // of classNo switch }
LocatedEntity * CreatorClient::make(const RootEntity & entity) { Create op; op->setArgs1(entity); op->setFrom(getId()); op->setTo(getId()); OpVector result; if (sendAndWaitReply(op, result) != 0) { std::cerr << "No reply to make" << std::endl << std::flush; return NULL; } assert(!result.empty()); const Operation & res = result.front(); if (!res.isValid()) { std::cerr << "NULL reply to make" << std::endl << std::flush; return NULL; } // FIXME Make this more robust against an info response if (res->getClassNo() == Atlas::Objects::Operation::SIGHT_NO) { if (res->getArgs().empty()) { std::cerr << "Reply to make has no args" << std::endl << std::flush; return NULL; } RootOperation arg = smart_dynamic_cast<RootOperation>(res->getArgs().front()); if (!arg.isValid()) { std::cerr << "Arg of reply to make is not an operation" << std::endl << std::flush; return NULL; } if (arg->getClassNo() != Atlas::Objects::Operation::CREATE_NO) { std::cerr << "Reply to make isn't sight of create" << std::endl << std::flush; return NULL; } return handleMakeResponse(arg, res->getSeconds()); } else if (res->getClassNo() == Atlas::Objects::Operation::INFO_NO) { return handleMakeResponse(res, res->getSeconds()); } else { std::cerr << "Reply to make isn't sight or info" << std::endl << std::flush; return NULL; } }
void AtlasStreamClient::operation(const RootOperation & op) { if (m_currentTask != 0) { OpVector res; m_currentTask->operation(op, res); OpVector::const_iterator Iend = res.end(); for (OpVector::const_iterator I = res.begin(); I != Iend; ++I) { send(*I); } if (m_currentTask->isComplete()) { delete m_currentTask; m_currentTask = 0; } } switch (op->getClassNo()) { case Atlas::Objects::Operation::APPEARANCE_NO: appearanceArrived(op); break; case Atlas::Objects::Operation::DISAPPEARANCE_NO: disappearanceArrived(op); break; case Atlas::Objects::Operation::INFO_NO: infoArrived(op); break; case Atlas::Objects::Operation::ERROR_NO: errorArrived(op); break; case Atlas::Objects::Operation::SIGHT_NO: sightArrived(op); break; case Atlas::Objects::Operation::SOUND_NO: soundArrived(op); break; default: break; } }
Router::RouterResult EntityRouter::handleSightOp(const RootOperation& op) { const std::vector<Root>& args = op->getArgs(); if (op->getClassNo() == MOVE_NO) { //If we get a MOVE op for an entity that's not visible, it means that the entity has moved //within our field of vision without sending an Appear op first. We should treat this as a //regular Appear op and issue a Look op back, to get more info. if (!m_entity->isVisible()) { m_entity->getView()->sendLookAt(m_entity->getId()); } // 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; }
LocatedEntity * CreatorClient::make(const RootEntity & entity) { Create op; op->setArgs1(entity); op->setFrom(getId()); op->setTo(getId()); OpVector result; if (sendAndWaitReply(op, result) != 0) { std::cerr << "No reply to make" << std::endl << std::flush; return NULL; } assert(!result.empty()); const Operation & res = result.front(); if (!res.isValid()) { std::cerr << "NULL reply to make" << std::endl << std::flush; return NULL; } if (res->getClassNo() != Atlas::Objects::Operation::SIGHT_NO) { std::cerr << "Reply to make isn't sight" << std::endl << std::flush; return NULL; } if (res->getArgs().empty()) { std::cerr << "Reply to make has no args" << std::endl << std::flush; return NULL; } RootOperation arg = smart_dynamic_cast<RootOperation>(res->getArgs().front()); if (!arg.isValid()) { std::cerr << "Arg of reply to make is not an operation" << std::endl << std::flush; return NULL; } if (arg->getClassNo() != Atlas::Objects::Operation::CREATE_NO) { std::cerr << "Reply to make isn't sight of create" << std::endl << std::flush; return NULL; } if (arg->getArgs().empty()) { std::cerr << "Arg of reply to make has no args" << std::endl << std::flush; return NULL; } RootEntity created = smart_dynamic_cast<RootEntity>(arg->getArgs().front()); if (!created.isValid()) { std::cerr << "Created argument is not an entity" << std::endl << std::flush; return NULL; } if (!created->hasAttrFlag(Atlas::Objects::ID_FLAG)) { std::cerr << "Created entity has no id" << std::endl << std::flush; return NULL; } const std::string & created_id = created->getId(); if (created->getParents().empty()) { std::cerr << "Created entity " << created_id << " has no type" << std::endl << std::flush; return NULL; } const std::string & created_type = created->getParents().front(); std::cout << "Created: " << created_type << "(" << created_id << ")" << std::endl << std::flush; LocatedEntity * obj = m_map.updateAdd(created, res->getSeconds()); return obj; }