10#include "Redispatch.h"
12#include <sigc++/slot.h>
14#include <Atlas/Objects/Operation.h>
15#include <Atlas/Objects/Entity.h>
16#include <Atlas/Objects/Anonymous.h>
23typedef Atlas::Objects::Entity::Account AtlasAccount;
24using namespace Atlas::Objects::Operation;
25using Atlas::Objects::Root;
26using Atlas::Objects::smart_static_cast;
27using Atlas::Objects::smart_dynamic_cast;
28using Atlas::Objects::Entity::RootEntity;
29using Atlas::Objects::Entity::Anonymous;
38 m_anonymousLookSerialno(0)
41 void setAnonymousLookSerialno(std::int64_t serial)
43 m_anonymousLookSerialno = serial;
47 RouterResult handleOperation(
const RootOperation& op)
override
49 const std::vector<Root>& args = op->getArgs();
51 if (op->instanceOf(APPEARANCE_NO)) {
52 for (
const auto & arg : args) {
53 m_lobby->recvAppearance(arg);
59 if (op->instanceOf(DISAPPEARANCE_NO)) {
60 for (
const auto & arg : args) {
61 m_lobby->recvDisappearance(arg);
69 if (op->getClassNo() == Atlas::Objects::Operation::SIGHT_NO) {
70 for (
const auto & arg : args) {
71 AtlasAccount acc = smart_dynamic_cast<AtlasAccount>(arg);
73 m_lobby->sightPerson(acc);
77 if (op->getRefno() == m_anonymousLookSerialno) {
78 RootEntity ent = smart_dynamic_cast<RootEntity>(arg);
79 m_lobby->recvInitialSight(ent);
83 Imaginary im = smart_dynamic_cast<Imaginary>(arg);
85 m_lobby->recvImaginary(im);
92 Sound sound = smart_dynamic_cast<Sound>(op);
95 for (
const auto & arg : args) {
96 Talk talk = smart_dynamic_cast<Talk>(arg);
98 m_lobby->recvTalk(talk);
116 std::int64_t m_anonymousLookSerialno;
121 Room(this, std::string()),
124 m_router = std::make_unique<OOGRouter>(
this);
129 m_account.
LoginSuccess.connect(sigc::mem_fun(
this, &Lobby::onLoggedIn));
132 m_account.
LogoutComplete.connect(sigc::mem_fun(
this, &Lobby::onLogout));
138 m_rooms[
getId()].release();
141void Lobby::look(
const std::string &
id)
144 error() <<
"Lobby trying look while not logged in";
149 look->setFrom(m_account.
getId());
155 look->setArgs1(what);
159 m_router->setAnonymousLookSerialno(look->getSerialno());
169 error() <<
"Lobby trying join while not logged in";
174 what->setAttr(
"loc", roomId);
175 what->setAttr(
"mode",
"join");
180 join->setArgs1(what);
183 auto R = m_rooms.find(roomId);
184 if (R == m_rooms.end()) {
185 m_rooms.emplace(roomId, std::make_unique<Room>(
this, roomId));
186 R = m_rooms.find(roomId);
189 return R->second.get();
199 auto P = m_people.find(acc);
200 if (P == m_people.end())
204 P = m_people.insert(P, IdPersonMap::value_type(acc,
nullptr));
207 return P->second.get();
212 auto R = m_rooms.find(
id);
213 if (R == m_rooms.end()) {
214 error() <<
"called getRoom with unknown ID " << id;
218 return R->second.get();
221void Lobby::sightPerson(
const AtlasAccount &ac)
223 if (!ac->isDefaultId()) {
224 auto P = m_people.find(ac->getId());
225 if (P == m_people.end()) {
226 error() <<
"got un-requested sight of person " << ac->getId();
231 P->second->sight(ac);
234 P->second = std::make_unique<Person>(*
this, ac);
242void Lobby::recvInitialSight(
const RootEntity& ent)
246 if (!m_roomId.empty()) {
250 m_roomId = ent->getId();
251 m_rooms[m_roomId] = std::unique_ptr<Lobby>(
this);
252 m_account.
getConnection().registerRouterForFrom(
this, m_roomId);
264 m_person(std::move(pid))
267 void onSightPerson(
Person* p)
272 std::string m_person;
275Router::RouterResult Lobby::recvTalk(
const Talk& tk)
277 if (tk->isDefaultFrom()) {
280 IdPersonMap::const_iterator P = m_people.find(tk->getFrom());
281 if ((P == m_people.end()) || (P->second ==
nullptr)) {
283 debug() <<
"creating sight-person-redispatch for " << tk->getFrom();
289 auto *spr =
new SightPersonRedispatch(
getConnection(), tk->getFrom(), sight);
290 SightPerson.connect(sigc::mem_fun(spr, &SightPersonRedispatch::onSightPerson));
295 const std::vector<Root>& args = tk->getArgs();
297 error() <<
"received sound(talk) with no args";
301 for (
const auto& arg : args) {
302 if (!args.front()->hasAttr(
"say")) {
303 error() <<
"received sound(talk) with bad arg";
306 std::string speech = arg->getAttr(
"say").asString();
308 if (arg->hasAttr(
"loc")) {
309 std::string loc = arg->getAttr(
"loc").asString();
310 auto room = m_rooms.find(loc);
312 if (room != m_rooms.end()) {
313 room->second->handleSoundTalk(P->second.get(), speech);
315 warning() <<
"lobby got sound(talk) with unknown loc: " << loc;
328void Lobby::recvAppearance(
const Atlas::Objects::Root& obj)
330 if (!obj->hasAttr(
"loc")) {
331 error() <<
"lobby got appearance arg without loc: " << obj;
335 std::string loc = obj->getAttr(
"loc").asString();
336 auto room = m_rooms.find(loc);
338 if (room != m_rooms.end()) {
339 room->second->appearance(obj->getId());
341 warning() <<
"lobby got appearance with unknown loc: " << loc;
344Router::RouterResult Lobby::recvImaginary(
const Imaginary& im)
346 const auto& args = im->getArgs();
348 warning() <<
"received sight(imaginary) with no args: " << im;
351 for (
const auto& arg : args) {
352 if (arg->hasAttr(
"description")) {
353 warning() <<
"received sight(imaginary) with bad args: " << im;
357 std::string description = arg->getAttr(
"description").asString();
359 if (im->isDefaultFrom()) {
362 IdPersonMap::const_iterator P = m_people.find(im->getFrom());
363 if ((P == m_people.end()) || (P->second ==
nullptr)) {
365 debug() <<
"creating sight-person-redispatch for " << im->getFrom();
371 auto *spr =
new SightPersonRedispatch(
getConnection(), im->getFrom(), sight);
372 SightPerson.connect(sigc::mem_fun(spr, &SightPersonRedispatch::onSightPerson));
377 if (arg->hasAttr(
"loc")) {
378 std::string loc = arg->getAttr(
"loc").asString();
379 auto room = m_rooms.find(loc);
381 if (room != m_rooms.end()) {
382 room->second->handleEmote(P->second.get(), description);
384 error() <<
"lobby got sight(imaginary) with unknown loc: " << loc;
387 warning() <<
"received imaginary with no loc set:" << im;
397void Lobby::recvDisappearance(
const Atlas::Objects::Root& obj)
399 if (!obj->hasAttr(
"loc")) {
400 error() <<
"lobby got disappearance arg without loc: " << obj;
404 auto locAttr = obj->getAttr(
"loc");
405 if (locAttr.isString()) {
406 std::string loc = locAttr.String();
407 auto room = m_rooms.find(loc);
409 if (room != m_rooms.end()) {
410 room->second->disappearance(obj->getId());
412 error() <<
"lobby got disappearance with unknown loc: " << loc;
450void Lobby::onLoggedIn()
457void Lobby::onLogout(
bool clean)
Encapsulates all the state of an Atlas Account, and methods that operation on that state.
const std::string & getId() const
returns the account ID if logged in
sigc::signal< void > LoginSuccess
Connection & getConnection() const
Access the underlying Connection for this account.
sigc::signal< void, bool > LogoutComplete
Emitted when a logout completes.
bool isLoggedIn() const
Check if the account is logged in.
virtual void send(const Atlas::Objects::Root &obj)
Transmit an Atlas::Objects instance to the server.
Room * join(const std::string &roomID)
Room * getRoom(const std::string &id)
Person * getPerson(const std::string &acc)
obtain a person's info, given their account ID; may return nullptr
Connection & getConnection() const
Helper method to access the underlying Connection from the Account.
sigc::signal< void, Person *, const std::string & > PrivateTalk
Account & getAccount() const
Retrive the Account which this lobbby is bound to.
sigc::signal< void, Person * > SightPerson
Emitted when sight of a person is received.
const std::string & getAccount() const
access the Atlas account ID for this person
std::string getId() const
std::int64_t getNewSerialno()
operation serial number sequencing