2013-07-28 22:25:15 +02:00
|
|
|
/*
|
|
|
|
|
Copyright (C) 2013 Erik Ogenvik
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "MindClient.h"
|
|
|
|
|
|
2013-08-02 14:20:09 +02:00
|
|
|
#include "ClientConnection.h"
|
|
|
|
|
|
2013-07-28 22:25:15 +02:00
|
|
|
#include "common/log.h"
|
|
|
|
|
#include "common/compose.hpp"
|
|
|
|
|
#include "common/debug.h"
|
2013-07-29 00:02:43 +02:00
|
|
|
#include "common/id.h"
|
|
|
|
|
#include "common/ScriptKit.h"
|
|
|
|
|
#include "common/Setup.h"
|
2013-07-30 13:38:27 +02:00
|
|
|
#include "common/TypeNode.h"
|
2013-07-31 00:04:12 +02:00
|
|
|
#include "common/Tick.h"
|
2013-07-29 00:02:43 +02:00
|
|
|
|
|
|
|
|
#include "rulesets/MindFactory.h"
|
|
|
|
|
#include "rulesets/BaseMind.h"
|
2013-07-28 22:25:15 +02:00
|
|
|
|
|
|
|
|
#include <Atlas/Objects/Operation.h>
|
|
|
|
|
#include <Atlas/Objects/Entity.h>
|
2013-07-29 00:02:43 +02:00
|
|
|
#include <Atlas/Objects/SmartPtr.h>
|
2013-07-28 22:25:15 +02:00
|
|
|
|
|
|
|
|
using Atlas::Message::MapType;
|
|
|
|
|
using Atlas::Objects::Root;
|
|
|
|
|
using Atlas::Objects::Operation::RootOperation;
|
|
|
|
|
using Atlas::Objects::Operation::Look;
|
|
|
|
|
using Atlas::Objects::Operation::Login;
|
2015-05-26 22:28:14 +02:00
|
|
|
using Atlas::Objects::Operation::Tick;
|
2013-07-28 22:25:15 +02:00
|
|
|
using Atlas::Objects::Entity::RootEntity;
|
|
|
|
|
using Atlas::Objects::Entity::Anonymous;
|
|
|
|
|
|
|
|
|
|
static const bool debug_flag = false;
|
|
|
|
|
|
2015-05-05 22:01:11 +02:00
|
|
|
MindClient::MindClient(const std::string& id, int intId,
|
|
|
|
|
MindFactory& mindFactory) :
|
|
|
|
|
Router(id, intId), m_mindFactory(mindFactory), m_mind(0), m_nextTick(0)
|
2013-07-28 22:25:15 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MindClient::~MindClient()
|
|
|
|
|
{
|
2013-08-05 11:24:35 +02:00
|
|
|
if (m_mind) {
|
|
|
|
|
m_mind->decRef();
|
|
|
|
|
}
|
2013-07-28 22:25:15 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-02 14:20:09 +02:00
|
|
|
void MindClient::idle(OpVector& res)
|
2013-07-28 22:25:15 +02:00
|
|
|
{
|
2013-07-31 00:04:12 +02:00
|
|
|
//Send a Tick operation every second
|
|
|
|
|
//TODO: make this better and more dynamic
|
|
|
|
|
m_systemTime.update();
|
|
|
|
|
if (m_systemTime.seconds() >= m_nextTick) {
|
|
|
|
|
Atlas::Objects::Operation::Tick tick;
|
|
|
|
|
|
|
|
|
|
operationToMind(tick, res);
|
|
|
|
|
|
|
|
|
|
m_systemTime.update();
|
|
|
|
|
m_nextTick = m_systemTime.seconds() + 1;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-28 22:25:15 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-09 21:37:36 +02:00
|
|
|
void MindClient::takePossession(OpVector& res, ClientConnection& connection,
|
2013-08-02 19:52:22 +02:00
|
|
|
std::string& accountId, const std::string& possessEntityId,
|
2013-07-29 00:02:43 +02:00
|
|
|
const std::string& possessKey)
|
2013-07-28 22:25:15 +02:00
|
|
|
{
|
2013-07-29 00:02:43 +02:00
|
|
|
log(INFO,
|
|
|
|
|
String::compose("Taking possession of entity with id %1.",
|
|
|
|
|
possessEntityId));
|
|
|
|
|
|
|
|
|
|
m_entityId = possessEntityId;
|
2013-07-28 22:25:15 +02:00
|
|
|
|
|
|
|
|
Anonymous what;
|
|
|
|
|
what->setId(possessEntityId);
|
|
|
|
|
what->setAttr("possess_key", possessKey);
|
|
|
|
|
|
|
|
|
|
Look l;
|
2013-08-02 14:20:09 +02:00
|
|
|
l->setFrom(accountId);
|
2013-07-28 22:25:15 +02:00
|
|
|
l->setArgs1(what);
|
2013-08-09 21:37:36 +02:00
|
|
|
l->setSerialno(connection.newSerialNo());
|
|
|
|
|
res.push_back(l);
|
2013-07-28 22:25:15 +02:00
|
|
|
}
|
|
|
|
|
|
2013-07-31 00:13:59 +02:00
|
|
|
void MindClient::operationToMind(const Operation & op, OpVector & res)
|
|
|
|
|
{
|
|
|
|
|
if (m_mind) {
|
|
|
|
|
OpVector mindRes;
|
|
|
|
|
m_mind->operation(op, mindRes);
|
|
|
|
|
for (Operation& resOp : mindRes) {
|
2015-05-05 22:01:11 +02:00
|
|
|
resOp->setFrom(m_mind->getId());
|
|
|
|
|
res.push_back(resOp);
|
2013-07-31 00:13:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-28 22:25:15 +02:00
|
|
|
void MindClient::operation(const Operation & op, OpVector & res)
|
|
|
|
|
{
|
2013-08-09 21:37:36 +02:00
|
|
|
if (!m_mind) {
|
|
|
|
|
if (op->getClassNo() == Atlas::Objects::Operation::SIGHT_NO) {
|
|
|
|
|
createMind(op, res);
|
|
|
|
|
} else {
|
|
|
|
|
log(ERROR,
|
|
|
|
|
String::compose("Unrecognized response to possession: %1",
|
|
|
|
|
op->getParents().front()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
operationToMind(op, res);
|
|
|
|
|
}
|
2013-07-28 22:25:15 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-09 21:37:36 +02:00
|
|
|
void MindClient::createMind(const Operation & op, OpVector & res)
|
2013-07-28 22:25:15 +02:00
|
|
|
{
|
2013-07-30 13:38:27 +02:00
|
|
|
|
2013-07-29 00:02:43 +02:00
|
|
|
const std::vector<Root>& args = op->getArgs();
|
|
|
|
|
if (args.empty()) {
|
2013-07-30 13:38:27 +02:00
|
|
|
log(ERROR, "no args character create/take response");
|
2013-07-29 00:02:43 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RootEntity ent = Atlas::Objects::smart_dynamic_cast<RootEntity>(
|
|
|
|
|
args.front());
|
|
|
|
|
if (!ent.isValid()) {
|
2013-07-30 13:38:27 +02:00
|
|
|
log(ERROR, "malformed character create/take response");
|
2013-07-29 00:02:43 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-30 13:38:27 +02:00
|
|
|
std::string entityId = ent->getId();
|
|
|
|
|
std::string entityType = ent->getParents().front();
|
2013-07-29 00:02:43 +02:00
|
|
|
|
2013-07-30 13:38:27 +02:00
|
|
|
log(INFO,
|
|
|
|
|
String::compose(
|
|
|
|
|
"Got info on account, creating mind for entity with id %1 of type %2.",
|
|
|
|
|
entityId, entityType));
|
|
|
|
|
m_mind = m_mindFactory.newMind(entityId, integerId(entityId));
|
2013-08-05 11:24:35 +02:00
|
|
|
//We'll keep a reference to the mind so it isn't deleted willy-nilly
|
|
|
|
|
m_mind->incRef();
|
2013-07-30 13:38:27 +02:00
|
|
|
//TODO: setup and get type from Inheritance
|
|
|
|
|
m_mind->setType(new TypeNode(entityType));
|
|
|
|
|
|
|
|
|
|
if (m_mindFactory.m_scriptFactory != 0) {
|
|
|
|
|
log(INFO, "Adding script to entity.");
|
|
|
|
|
m_mindFactory.m_scriptFactory->addScript(m_mind);
|
|
|
|
|
}
|
2013-07-29 00:02:43 +02:00
|
|
|
|
2013-07-31 00:14:23 +02:00
|
|
|
//Send the Sight operation we just got on to the mind, since it contains info about the entity.
|
|
|
|
|
operationToMind(op, res);
|
|
|
|
|
|
|
|
|
|
//Also send a "Setup" op to the mind, which will trigger any setup hooks.
|
2013-07-30 13:38:27 +02:00
|
|
|
Atlas::Objects::Operation::Setup s;
|
|
|
|
|
Anonymous setup_arg;
|
|
|
|
|
setup_arg->setName("mind");
|
|
|
|
|
s->setTo(ent->getId());
|
|
|
|
|
s->setArgs1(setup_arg);
|
2013-07-31 00:13:59 +02:00
|
|
|
operationToMind(s, res);
|
2013-07-30 13:38:27 +02:00
|
|
|
|
|
|
|
|
//Start by sending a unspecified "Look". This tells the server to send us a bootstrapped view.
|
|
|
|
|
Look l;
|
|
|
|
|
l->setFrom(entityId);
|
2013-08-09 21:37:36 +02:00
|
|
|
res.push_back(l);
|
2013-07-30 13:38:27 +02:00
|
|
|
|
2013-07-28 22:25:15 +02:00
|
|
|
}
|
2013-07-30 13:38:27 +02:00
|
|
|
|
2013-08-05 11:27:34 +02:00
|
|
|
bool MindClient::isMindDestroyed() const
|
|
|
|
|
{
|
|
|
|
|
if (m_mind == nullptr || m_mind->isDestroyed()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|