cyphesis/aiclient/PossessionClient.cpp

171 lines
5.2 KiB
C++
Raw Permalink Normal View History

/*
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
#endif
#include "PossessionClient.h"
2015-05-05 22:01:11 +02:00
#include "PossessionAccount.h"
2013-07-27 23:38:47 +02:00
#include "common/Possess.h"
2015-05-05 22:01:11 +02:00
#include "common/id.h"
#include "common/custom.h"
#include "common/SystemTime.h"
#include "common/Inheritance.h"
2013-07-27 23:38:47 +02:00
#include "common/debug.h"
#include <Atlas/Objects/Entity.h>
static const bool debug_flag = false;
using Atlas::Message::Element;
using Atlas::Objects::Root;
using Atlas::Objects::Entity::Anonymous;
using Atlas::Objects::Operation::RootOperation;
PossessionClient::PossessionClient(MindKit& mindFactory) :
m_mindFactory(mindFactory),
m_account(nullptr),
m_operationsDispatcher([&](const Operation& op, BaseMind& from) { this->operationFromEntity(op, from); },
[&]() -> double { return getTime(); }),
m_inheritance(new Inheritance())
{
}
2015-05-05 22:01:11 +02:00
bool PossessionClient::idle()
{
2015-05-05 22:01:11 +02:00
return m_operationsDispatcher.idle();
}
2015-05-05 22:01:11 +02:00
double PossessionClient::secondsUntilNextOp() const
{
return m_operationsDispatcher.secondsUntilNextOp();
}
2015-05-05 22:01:11 +02:00
bool PossessionClient::isQueueDirty() const
2013-07-27 23:38:47 +02:00
{
2015-05-05 22:01:11 +02:00
return m_operationsDispatcher.isQueueDirty();
}
2015-05-05 22:01:11 +02:00
void PossessionClient::markQueueAsClean()
{
m_operationsDispatcher.markQueueAsClean();
}
void PossessionClient::addLocatedEntity(BaseMind* entity)
2015-05-05 22:01:11 +02:00
{
2015-05-06 22:30:19 +02:00
m_minds.insert(std::make_pair(entity->getIntId(), entity));
entity->incRef();
2015-05-05 22:01:11 +02:00
}
void PossessionClient::removeLocatedEntity(BaseMind* entity)
2015-05-05 22:01:11 +02:00
{
2015-05-06 22:30:19 +02:00
m_minds.erase(entity->getIntId());
entity->decRef();
2015-05-05 22:01:11 +02:00
}
2015-05-05 22:01:11 +02:00
void PossessionClient::createAccount(const std::string& accountId)
{
m_account = new PossessionAccount(accountId, integerId(accountId), *this, m_mindFactory);
OpVector res;
m_account->enablePossession(res);
for (auto& op : res) {
m_connection.send(op);
}
}
void PossessionClient::operationFromEntity(const Operation& op, BaseMind& locatedEntity)
2013-07-27 23:38:47 +02:00
{
2015-05-05 22:01:11 +02:00
if (!locatedEntity.isDestroyed()) {
OpVector res;
locatedEntity.operation(op, res);
for (auto& resOp : res) {
//All resulting ops should go out to the server, except for Ticks which we'll keep ourselves.
if (resOp->getClassNo() == Atlas::Objects::Operation::TICK_NO) {
resOp->setTo(resOp->getFrom());
m_operationsDispatcher.addOperationToQueue(resOp, locatedEntity);
} else {
resOp->setFrom(locatedEntity.getId());
send(resOp);
}
2013-08-09 21:37:36 +02:00
}
if (locatedEntity.isDestroyed()) {
2015-05-06 22:30:19 +02:00
removeLocatedEntity(&locatedEntity);
}
2013-08-09 21:37:36 +02:00
}
2015-05-05 22:01:11 +02:00
}
2013-08-09 21:37:36 +02:00
void PossessionClient::operation(const Operation& op, OpVector& res)
2015-05-05 22:01:11 +02:00
{
if (debug_flag) {
std::cout << "PossessionClient::operation {" << std::endl;
debug_dump(op, std::cout);
std::cout << "}" << std::endl << std::flush;
}
2015-05-05 22:01:11 +02:00
if (op->isDefaultTo() || op->getTo() == m_account->getId()) {
OpVector accountRes;
m_account->operation(op, accountRes);
for (auto& resOp : accountRes) {
//All resulting ops should go out to the server, except for Ticks which we'll keep ourselves.
if (resOp->getClassNo() == Atlas::Objects::Operation::TICK_NO) {
auto I = m_minds.find(integerId(resOp->getFrom()));
if (I != m_minds.end()) {
resOp->setTo(resOp->getFrom());
m_operationsDispatcher.addOperationToQueue(resOp, *I->second);
}
} else {
res.push_back(resOp);
}
}
2013-07-27 23:38:47 +02:00
} else {
2015-05-05 22:01:11 +02:00
auto mindI = m_minds.find(integerId(op->getTo()));
if (mindI != m_minds.end()) {
2015-05-05 22:01:11 +02:00
OpVector mindRes;
auto mind = mindI->second;
mind->operation(op, mindRes);
2015-05-05 22:01:11 +02:00
for (auto& resOp : mindRes) {
resOp->setFrom(mind->getId());
2015-05-05 22:01:11 +02:00
//All resulting ops should go out to the server, except for Ticks which we'll keep ourselves.
if (resOp->getClassNo() == Atlas::Objects::Operation::TICK_NO) {
resOp->setTo(mind->getId());
m_operationsDispatcher.addOperationToQueue(resOp, *mind);
2015-05-05 22:01:11 +02:00
} else {
res.push_back(resOp);
}
}
2015-05-05 22:01:11 +02:00
if (mind->isDestroyed()) {
2015-05-06 22:30:19 +02:00
removeLocatedEntity(mind);
}
} else {
2015-05-05 22:01:11 +02:00
m_account->operation(op, res);
}
2013-07-27 23:38:47 +02:00
}
}
2015-05-05 22:01:11 +02:00
double PossessionClient::getTime() const
2013-07-27 23:38:47 +02:00
{
2015-05-05 22:01:11 +02:00
SystemTime time;
time.update();
return (double) (time.seconds()) + (double) time.microseconds() / 1000000.;
2013-07-27 23:38:47 +02:00
}