cyphesis/common/TypeNode.cpp

179 lines
5.6 KiB
C++
Raw Permalink Normal View History

// Cyphesis Online RPG Server and AI Engine
// Copyright (C) 2007 Alistair Riddoch
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "TypeNode.h"
#include "debug.h"
#include "Property.h"
#include "PropertyManager.h"
#include <set>
static const bool debug_flag = false;
using Atlas::Message::MapType;
TypeNode::TypeNode(const std::string & name) : m_name(name),
m_parent(nullptr)
{
}
TypeNode::TypeNode(const std::string & name,
const Atlas::Objects::Root & d) : m_name(name),
m_description(d),
m_parent(nullptr)
{
}
TypeNode::~TypeNode()
{
for (auto entry: m_defaults) {
delete entry.second;
}
}
void TypeNode::injectProperty(const std::string& name,
PropertyBase* p)
{
auto existingI = m_defaults.find(name);
if (existingI != m_defaults.end() && existingI->second != p) {
delete existingI->second;
m_defaults.erase(existingI);
} else {
m_defaults.emplace(name, p);
}
2018-02-15 12:39:15 +01:00
Atlas::Message::Element attributesElement = Atlas::Message::MapType();
if (m_description->hasAttr("attributes")) {
attributesElement = m_description->getAttr("attributes");
}
Atlas::Message::Element propertyElement;
p->get(propertyElement);
attributesElement.Map()[name] = Atlas::Message::MapType{
{"visibility", "public"},
{"default", propertyElement}
};
m_description->setAttr("attributes", attributesElement);
}
void TypeNode::addProperties(const MapType & attributes)
{
for (auto entry : attributes) {
PropertyBase * p = PropertyManager::instance().addProperty(entry.first,
entry.second.getType());
assert(p != nullptr);
p->set(entry.second);
p->addFlags(flag_class);
p->install(this, entry.first);
m_defaults[entry.first] = p;
}
}
TypeNode::PropertiesUpdate TypeNode::updateProperties(const MapType & attributes)
{
PropertiesUpdate propertiesUpdate;
//Update the description
Atlas::Message::Element attributesElement = Atlas::Message::MapType();
if (m_description->hasAttr("attributes")) {
attributesElement = m_description->getAttr("attributes");
}
// Discover the default attributes which are no longer
// present after the update.
2017-05-27 18:29:03 +02:00
for (auto& entry : m_defaults) {
//Don't remove ephemeral attributes.
if (attributes.find(entry.first) == attributes.end() && (entry.second->flags() & per_ephem) == 0) {
2017-05-27 18:29:03 +02:00
debug( std::cout << entry.first << " removed" << std::endl; );
propertiesUpdate.removedProps.insert(entry.first);
}
}
// Remove the class properties for the default attributes that
// no longer exist
for (auto& entry : propertiesUpdate.removedProps) {
auto M = m_defaults.find(entry);
delete M->second;
m_defaults.erase(M);
}
// Update the values of existing class properties, and add new class
// properties for added default attributes.
2017-05-27 18:29:03 +02:00
for (auto& entry : attributes) {
PropertyBase * p;
2017-05-27 18:29:03 +02:00
auto I = m_defaults.find(entry.first);
if (I == m_defaults.end()) {
p = PropertyManager::instance().addProperty(entry.first, entry.second.getType());
2017-05-27 18:29:03 +02:00
assert(p != nullptr);
p->addFlags(flag_class);
p->install(this, entry.first);
2017-05-27 18:29:03 +02:00
m_defaults[entry.first] = p;
propertiesUpdate.newProps.emplace(entry.first);
p->set(entry.second);
attributesElement.Map()[entry.first] = Atlas::Message::MapType{
{"visibility", "public"},
{"default", entry.second}
};
} else {
Atlas::Message::Element oldVal;
p = I->second;
p->get(oldVal);
if (oldVal != entry.second) {
p->set(entry.second);
propertiesUpdate.changedProps.emplace(entry.first);
attributesElement.Map()[entry.first] = Atlas::Message::MapType{
{"visibility", "public"},
{"default", entry.second}
};
// attributesElement.Map()[entry.first].Map()["default"] = entry.second;
}
}
}
m_description->setAttr("attributes", attributesElement);
return propertiesUpdate;
}
bool TypeNode::isTypeOf(const std::string & base_type) const
{
const TypeNode * node = this;
do {
if (node->name() == base_type) {
return true;
}
node = node->parent();
} while (node != nullptr);
return false;
}
bool TypeNode::isTypeOf(const TypeNode * base_type) const
{
const TypeNode * node = this;
do {
if (node == base_type) {
return true;
}
node = node->parent();
} while (node != nullptr);
return false;
}