void ClientConnection::createCharacter(const RootOperation& op) { static unsigned int charCounter = 0; char charId[64]; ::snprintf(charId, 64, "_customChar_%d", ++charCounter); RootEntity ent = smart_dynamic_cast<RootEntity>(op->getArgs().front()); ent->setId(charId); ent->setLoc("_world"); m_server->m_world[charId] = ent; StringList children(m_server->m_world["_world"]->getContains()); children.push_back(charId); m_server->m_world["_world"]->setContains(children); Agent* ag = new Agent(this, charId); ag->setEntityVisible(charId, true); m_agents[charId] = ag; Info info; info->setArgs1(m_server->m_world[charId]); info->setFrom(charId); info->setTo(m_account); // I *think* this is right info->setRefno(op->getSerialno()); send(info); }
void AtlasStreamClient::infoArrived(const RootOperation & op) { reply_flag = true; if (!op->isDefaultFrom()) { return; } if (op->isDefaultArgs() || op->getArgs().empty()) { std::cerr << "WARNING: Malformed account from server" << std::endl << std::flush; return; } if (op->isDefaultRefno()) { return; } if (op->getRefno() != serialNo) { return; } m_infoReply = op->getArgs().front(); }
void Connection::handleServerInfo(const RootOperation& op) { RootEntity svr = smart_dynamic_cast<RootEntity>(op->getArgs().front()); if (!svr.isValid()) { error() << "server INFO argument object is broken"; return; } m_info.processServer(svr); GotServerInfo.emit(); }
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); }
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; }
/// \brief Called when an Error operation arrives /// /// @param op Operation to be processed void AtlasStreamClient::errorArrived(const RootOperation & op) { reply_flag = true; error_flag = true; const std::vector<Root> & args = op->getArgs(); if (args.empty()) { return; } const Root & arg = args.front(); Element message_attr; if (arg->copyAttr("message", message_attr) == 0 && message_attr.isString()) { m_errorMessage = message_attr.String(); } }
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 }
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; }
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; }
void Commander::dispatch(const RootOperation& op) { Appearance appear = smart_dynamic_cast<Appearance>(op); if (appear.isValid()) { assert(op->hasAttr("for")); Agent* ag = m_server->findAgentForEntity(op->getAttr("for").asString()); if (ag) { ag->setEntityVisible(op->getTo(), true); } else { // doesn't exist yet, mark as visible if / when the agent is created Agent::setEntityVisibleForFutureAgent(op->getTo(), op->getAttr("for").asString()); } } Disappearance disap = smart_dynamic_cast<Disappearance>(op); if (disap.isValid()) { assert(op->hasAttr("for")); Agent* ag = m_server->findAgentForEntity(op->getAttr("for").asString()); if (ag) ag->setEntityVisible(op->getTo(), false); } Create cr = smart_dynamic_cast<Create>(op); if (cr.isValid()) { std::vector<Root> args(op->getArgs()); assert(!args.empty()); RootEntity ent = smart_dynamic_cast<RootEntity>(args.front()); assert(ent.isValid()); static int idCounter = 900; char buf[32]; snprintf(buf, 32, "_created_%d", ++idCounter); std::string id(buf); ent->setId(id); std::string loc = ent->getLoc(); assert(m_server->m_world.count(loc)); StringList children(m_server->m_world[loc]->getContains()); children.push_back(id); m_server->m_world[loc]->setContains(children); m_server->m_world[id] = ent; Create bcr(cr); bcr->setArgs1(ent); Agent::broadcastSight(bcr); } Delete del = smart_dynamic_cast<Delete>(op); if (del.isValid()) { std::vector<Root> args(op->getArgs()); assert(!args.empty()); std::string id = args.front()->getId(); assert(m_server->m_world.count(id)); m_server->m_world.erase(id); Agent::broadcastSight(op); } Move mv = smart_dynamic_cast<Move>(op); if (mv.isValid()) { RootEntity ent = m_server->getEntity(op->getTo()); std::vector<Root> args(op->getArgs()); if (args.front()->hasAttr("loc")) { std::string newLocId = args.front()->getAttr("loc").asString(); RootEntity oldLoc = m_server->getEntity(ent->getLoc()), newLoc = m_server->getEntity(newLocId); ent->setLoc(newLocId); // modify stamps? oldLoc->modifyContains().remove(ent->getId()); newLoc->modifyContains().push_back(ent->getId()); } if (args.front()->hasAttr("pos")) ent->setPosAsList(args.front()->getAttr("pos").asList()); // handle velocity changes Agent::broadcastSight(op); return; } Sound snd = smart_dynamic_cast<Sound>(op); if (snd.isValid()) { std::vector<Root> args(op->getArgs()); assert(!args.empty()); if (snd->hasAttr("broadcast")) { Agent::broadcastSound(smart_dynamic_cast<RootOperation>(args.front())); } } Sight st = smart_dynamic_cast<Sight>(op); if (st.isValid()) { if (st->hasAttr("broadcast")) { std::vector<Root> args(op->getArgs()); assert(!args.empty()); Agent::broadcastSight(smart_dynamic_cast<RootOperation>(args.front())); } } Set s = smart_dynamic_cast<Set>(op); if (s.isValid()) { std::vector<Root> args(op->getArgs()); for (unsigned int A=0; A < args.size(); ++A) { std::string eid = args[A]->getId(); RootEntity entity = m_server->getEntity(eid); Root::const_iterator I = args[A]->begin(); for (; I != args[A]->end(); ++I) { if ((I->first == "id") || (I->first == "parents") || (I->first == "objtype")) { continue; } assert(I->first != "loc"); entity->setAttr(I->first, I->second); } } Agent::broadcastSight(s); } Action act = smart_dynamic_cast<Action>(op); if (act.isValid()) { std::vector<Root> args(op->getArgs()); if (act->getParents().front() == "command") { std::string cid = args[0]->getAttr("cid").asString(); if (cid == "socket-shutdown") { std::string acc = args[0]->getAttr("acc").asString(); ClientConnection* cc = m_server->getConnectionForAccount(acc); assert(cc); cc->shutdown(); } else if (cid == "add-many-objects") { m_server->addManyObjects(args[0]->getAttr("acc").asString()); } else if (cid == "set-world-time") { /* double t = */ args[0]->getAttr("seconds").asFloat(); } else { std::cerr << "unknown command " << cid << std::endl; } } // of command action case } // of action case }
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; }