cyphesis/server/StorageManager.cpp
Al Riddoch 0285deded5 2008-08-27 Al Riddoch <alriddoch@googlemail.com>
* server/StorageManager.cpp, server/StorageManager.h: Encode
	  properties as rather messy Atlas, and store them in the
	  database.
2008-08-27 15:46:14 +00:00

157 lines
5.2 KiB
C++

// Cyphesis Online RPG Server and AI Engine
// Copyright (C) 2008 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
// $Id$
#include "StorageManager.h"
#include "WorldRouter.h"
#include "rulesets/Entity.h"
#include "common/Database.h"
#include "common/TypeNode.h"
#include "common/Property.h"
#include "common/debug.h"
#include <sigc++/adaptors/bind.h>
#include <sigc++/functors/mem_fun.h>
#include <iostream>
typedef Database::KeyValues KeyValues;
static const bool debug_flag = true;
StorageManager:: StorageManager(WorldRouter & world)
{
world.inserted.connect(sigc::mem_fun(this, &StorageManager::entityInserted));
}
/// \brief Called when a new Entity is inserted in the world
void StorageManager::entityInserted(Entity * ent)
{
m_unstoredEntities.push_back(EntityRef(ent));
ent->setFlags(entity_queued);
ent->updated.connect(sigc::bind(sigc::mem_fun(this, &StorageManager::entityUpdated), ent));
}
/// \brief Called when an Entity is modified
void StorageManager::entityUpdated(Entity * ent)
{
// Is it already in the dirty Entities queue?
// Perhaps we need to modify the semantics of the updated signal
// so it is only emitted if the entity was not marked as dirty.
if (ent->getFlags() & entity_queued) {
// std::cout << "Already queued " << ent->getId() << std::endl << std::flush;
return;
}
m_dirtyEntities.push_back(EntityRef(ent));
// std::cout << "Updated fired " << ent->getId() << std::endl << std::flush;
ent->setFlags(entity_queued);
}
void StorageManager::encodeProperty(PropertyBase * prop, std::string & store)
{
Atlas::Message::MapType map;
prop->get(map["val"]);
Database::instance()->encodeObject(map, store);
}
void StorageManager::insertEntity(Entity * ent)
{
Database::instance()->insertEntity(ent->getId(),
ent->m_location.m_loc->getId(),
ent->getType()->name(),
ent->getSeq());
KeyValues property_tuples;
const PropertyDict & properties = ent->getProperties();
PropertyDict::const_iterator I = properties.begin();
PropertyDict::const_iterator Iend = properties.end();
for (; I != Iend; ++I) {
PropertyBase * prop = I->second;
encodeProperty(prop, property_tuples[I->first]);
prop->setFlags(per_clean | per_seen);
}
Database::instance()->insertProperties(ent->getId(), property_tuples);
ent->resetFlags(entity_queued);
ent->setFlags(entity_clean);
}
void StorageManager::updateEntity(Entity * ent)
{
Database::instance()->updateEntity(ent->getId(), ent->getSeq());
KeyValues new_property_tuples;
KeyValues upd_property_tuples;
const PropertyDict & properties = ent->getProperties();
PropertyDict::const_iterator I = properties.begin();
PropertyDict::const_iterator Iend = properties.end();
for (; I != Iend; ++I) {
PropertyBase * prop = I->second;
if (prop->flags() & per_clean) {
continue;
}
// FIXME check if this is new or just modded.
if (prop->flags() & per_seen) {
encodeProperty(prop, upd_property_tuples[I->first]);
} else {
encodeProperty(prop, new_property_tuples[I->first]);
}
prop->setFlags(per_clean | per_seen);
}
if (!new_property_tuples.empty()) {
Database::instance()->insertProperties(ent->getId(),
new_property_tuples);
}
if (!upd_property_tuples.empty()) {
Database::instance()->updateProperties(ent->getId(),
upd_property_tuples);
}
ent->resetFlags(entity_queued);
ent->setFlags(entity_clean);
}
void StorageManager::tick()
{
while (!m_unstoredEntities.empty()) {
const EntityRef & ent = m_unstoredEntities.front();
if (ent.get() != 0) {
debug( std::cout << "storing " << ent->getId() << std::endl << std::flush; );
insertEntity(ent.get());
} else {
debug( std::cout << "deleted" << std::endl << std::flush; );
}
m_unstoredEntities.pop_front();
}
while (!m_dirtyEntities.empty()) {
const EntityRef & ent = m_dirtyEntities.front();
if (ent.get() != 0) {
debug( std::cout << "updating " << ent->getId() << std::endl << std::flush; );
updateEntity(ent.get());
} else {
debug( std::cout << "deleted" << std::endl << std::flush; );
}
m_dirtyEntities.pop_front();
}
}
int StorageManager::initWorld()
{
return 0;
}