2013-07-26 21:43: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
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "ExternalMindsManager.h"
|
2013-08-09 16:25:04 +02:00
|
|
|
#include "PossessionAuthenticator.h"
|
2013-07-26 21:43:15 +02:00
|
|
|
|
2013-07-27 23:38:11 +02:00
|
|
|
#include "common/Link.h"
|
2018-10-30 20:12:45 +01:00
|
|
|
#include "common/operations/Possess.h"
|
2013-07-27 23:38:11 +02:00
|
|
|
#include "common/log.h"
|
|
|
|
|
#include "common/compose.hpp"
|
2015-05-23 23:38:13 +02:00
|
|
|
#include "common/debug.h"
|
2018-10-31 21:38:35 +01:00
|
|
|
#include "rules/simulation/ExternalMind.h"
|
|
|
|
|
#include "rules/LocatedEntity.h"
|
2013-07-26 21:43:15 +02:00
|
|
|
|
|
|
|
|
#include <Atlas/Objects/Entity.h>
|
|
|
|
|
|
2013-08-09 16:25:04 +02:00
|
|
|
#include <wfmath/MersenneTwister.h>
|
|
|
|
|
|
|
|
|
|
#include <sigc++/bind.h>
|
2018-10-31 21:38:35 +01:00
|
|
|
#include <rules/simulation/MindsProperty.h>
|
2013-08-09 16:25:04 +02:00
|
|
|
|
2018-08-14 22:25:56 +02:00
|
|
|
#include <iostream>
|
|
|
|
|
|
2015-05-23 23:38:13 +02:00
|
|
|
static const bool debug_flag = false;
|
|
|
|
|
|
2018-08-04 01:12:45 +02:00
|
|
|
template<>
|
|
|
|
|
ExternalMindsManager* Singleton<ExternalMindsManager>::ms_Singleton = nullptr;
|
2013-07-26 21:43:15 +02:00
|
|
|
|
2013-08-08 00:50:29 +02:00
|
|
|
|
|
|
|
|
int ExternalMindsManager::addConnection(
|
2018-08-09 21:30:10 +02:00
|
|
|
const ExternalMindsConnection& connection)
|
2013-07-26 21:43:15 +02:00
|
|
|
{
|
2018-08-09 21:30:10 +02:00
|
|
|
auto result = m_connections.insert(std::make_pair(connection.getRouterId(), connection));
|
2013-08-08 00:50:29 +02:00
|
|
|
if (!result.second) {
|
2018-08-09 21:30:10 +02:00
|
|
|
log(WARNING, String::compose(
|
|
|
|
|
"Tried to register a external mind connection for "
|
|
|
|
|
"router %1 for which there's already a connection registered.",
|
|
|
|
|
connection.getRouterId()));
|
2013-08-09 16:25:04 +02:00
|
|
|
return -1;
|
|
|
|
|
}
|
2018-08-09 21:30:10 +02:00
|
|
|
log(INFO, String::compose(
|
|
|
|
|
"New external mind connection registered for router %1. "
|
|
|
|
|
"There are now %2 connections.",
|
|
|
|
|
connection.getRouterId(), m_connections.size()));
|
2013-08-09 16:25:04 +02:00
|
|
|
|
|
|
|
|
//As we now have a new connection we'll see if there are any minds in waiting
|
|
|
|
|
|
|
|
|
|
for (auto character : m_unpossessedEntities) {
|
|
|
|
|
requestPossessionFromRegisteredClients(character->getId());
|
2013-08-08 00:50:29 +02:00
|
|
|
}
|
2013-08-09 16:25:04 +02:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
2013-08-08 00:50:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ExternalMindsManager::removeConnection(const std::string& routerId)
|
|
|
|
|
{
|
|
|
|
|
auto result = m_connections.erase(routerId);
|
|
|
|
|
if (result == 0) {
|
|
|
|
|
log(WARNING,
|
2018-08-09 21:30:10 +02:00
|
|
|
String::compose(
|
|
|
|
|
"Tried to deregister a external mind connection for "
|
|
|
|
|
"router %1 for which there's no connection registered.",
|
|
|
|
|
routerId));
|
2013-08-09 16:25:04 +02:00
|
|
|
return -1;
|
2013-08-08 00:50:29 +02:00
|
|
|
} else {
|
2015-05-23 23:38:13 +02:00
|
|
|
debug(std::cout << String::compose(
|
2018-08-09 21:30:10 +02:00
|
|
|
"Deregistered external mind connection registered for router %1. "
|
|
|
|
|
"There are now %2 connections.", routerId,
|
|
|
|
|
m_connections.size()) << std::endl;);
|
2013-08-08 00:50:29 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
2013-07-26 21:43:15 +02:00
|
|
|
}
|
|
|
|
|
|
2018-08-09 21:30:10 +02:00
|
|
|
void ExternalMindsManager::addPossessionEntryForCharacter(LocatedEntity* entity)
|
2013-07-26 21:43:15 +02:00
|
|
|
{
|
2018-08-09 21:30:10 +02:00
|
|
|
std::string key = entity->getId() + "_";
|
2013-08-09 16:25:04 +02:00
|
|
|
WFMath::MTRand generator;
|
|
|
|
|
for (int i = 0; i < 32; i++) {
|
2018-08-09 21:30:10 +02:00
|
|
|
char ch = (char) ((int) 'a' + generator.rand(25));
|
2013-08-09 16:25:04 +02:00
|
|
|
key += ch;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-09 21:30:10 +02:00
|
|
|
PossessionAuthenticator::instance().addPossession(entity->getId(), key);
|
2013-08-11 23:27:13 +02:00
|
|
|
}
|
2013-08-09 16:25:04 +02:00
|
|
|
|
2018-08-09 21:30:10 +02:00
|
|
|
int ExternalMindsManager::requestPossession(LocatedEntity* entity)
|
2013-08-11 23:27:13 +02:00
|
|
|
{
|
2018-08-09 21:30:10 +02:00
|
|
|
addPossessionEntryForCharacter(entity);
|
|
|
|
|
entity->destroyed.connect(sigc::bind(sigc::mem_fun(*this, &ExternalMindsManager::entity_destroyed), entity));
|
|
|
|
|
m_unpossessedEntities.insert(entity);
|
|
|
|
|
|
|
|
|
|
entity->propertyApplied.connect([this, entity](const std::string& propName, const PropertyBase& prop) {
|
|
|
|
|
if (propName == MindsProperty::property_name) {
|
|
|
|
|
auto changedMindsProp = dynamic_cast<const MindsProperty*>(&prop);
|
|
|
|
|
if (changedMindsProp) {
|
|
|
|
|
entity_mindsChanged(entity, changedMindsProp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2013-08-09 16:25:04 +02:00
|
|
|
|
2018-08-09 21:30:10 +02:00
|
|
|
auto mindsProperty = entity->getPropertyClassFixed<MindsProperty>();
|
|
|
|
|
if (!mindsProperty || mindsProperty->getMinds().empty()) {
|
|
|
|
|
requestPossessionFromRegisteredClients(entity->getId());
|
2013-08-09 16:25:04 +02:00
|
|
|
}
|
|
|
|
|
return 0;
|
2013-07-26 21:43:15 +02:00
|
|
|
|
2013-08-09 16:25:04 +02:00
|
|
|
}
|
2013-07-26 21:43:15 +02:00
|
|
|
|
2018-08-09 21:30:10 +02:00
|
|
|
int ExternalMindsManager::requestPossessionFromRegisteredClients(const std::string& entity_id)
|
2013-08-09 16:25:04 +02:00
|
|
|
{
|
|
|
|
|
if (!m_connections.empty()) {
|
2018-08-04 01:12:45 +02:00
|
|
|
auto result = PossessionAuthenticator::instance().getPossessionKey(entity_id);
|
2013-08-09 16:25:04 +02:00
|
|
|
if (result.is_initialized()) {
|
|
|
|
|
//Use the last one registered.
|
|
|
|
|
//TODO: implement a better way to select the connection to use. Should we rotate the connections?
|
|
|
|
|
//Or do some kind of selection?
|
|
|
|
|
ExternalMindsConnection& connection = m_connections.rbegin()->second;
|
|
|
|
|
|
|
|
|
|
Atlas::Objects::Operation::Possess possessOp;
|
|
|
|
|
|
|
|
|
|
Atlas::Objects::Entity::Anonymous possess_args;
|
|
|
|
|
possess_args->setAttr("possess_key", *result);
|
|
|
|
|
possess_args->setAttr("possess_entity_id", entity_id);
|
|
|
|
|
|
|
|
|
|
possessOp->setArgs1(possess_args);
|
|
|
|
|
possessOp->setTo(connection.getRouterId());
|
|
|
|
|
|
2015-05-23 23:38:13 +02:00
|
|
|
debug(std::cout << String::compose(
|
2018-08-09 21:30:10 +02:00
|
|
|
"Requesting possession of mind for entity %1 from link with id %2 and router with id %3.",
|
|
|
|
|
entity_id, connection.getLink()->getId(),
|
|
|
|
|
connection.getRouterId()) << std::endl;);
|
2015-05-23 23:38:13 +02:00
|
|
|
|
2013-08-09 16:25:04 +02:00
|
|
|
connection.getLink()->send(possessOp);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2013-07-28 22:25:03 +02:00
|
|
|
|
2013-08-09 16:25:04 +02:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-09 21:30:10 +02:00
|
|
|
void ExternalMindsManager::entity_destroyed(LocatedEntity* entity)
|
2013-08-09 16:25:04 +02:00
|
|
|
{
|
|
|
|
|
m_unpossessedEntities.erase(entity);
|
|
|
|
|
m_possessedEntities.erase(entity);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-09 21:30:10 +02:00
|
|
|
void ExternalMindsManager::entity_mindsChanged(LocatedEntity* entity, const MindsProperty* mindsProp)
|
2013-08-09 16:25:04 +02:00
|
|
|
{
|
2018-08-09 21:30:10 +02:00
|
|
|
//If there are no minds controlling the entity we should try to possess it
|
|
|
|
|
if (mindsProp->getMinds().empty()) {
|
|
|
|
|
m_possessedEntities.erase(entity);
|
|
|
|
|
m_unpossessedEntities.insert(entity);
|
2013-08-09 16:25:04 +02:00
|
|
|
|
2013-08-11 23:27:13 +02:00
|
|
|
//The possession entry was removed when the character was possessed last, so we need to add one back.
|
2018-08-09 21:30:10 +02:00
|
|
|
addPossessionEntryForCharacter(entity);
|
2013-08-11 23:27:13 +02:00
|
|
|
|
2013-08-09 16:25:04 +02:00
|
|
|
//We'll now check for any registered possessive clients and ask them for possession of the newly unpossessed character.
|
2018-08-09 21:30:10 +02:00
|
|
|
requestPossessionFromRegisteredClients(entity->getId());
|
2013-08-09 16:25:04 +02:00
|
|
|
} else {
|
2018-08-09 21:30:10 +02:00
|
|
|
//Mark that the entity now is possessed (although it might not be by us).
|
|
|
|
|
m_unpossessedEntities.erase(entity);
|
|
|
|
|
m_possessedEntities.insert(entity);
|
2013-07-26 21:43:15 +02:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|