mirror of
https://github.com/worldforge/cyphesis
synced 2026-08-13 12:26:04 -04:00
* common/Database.cpp, common/Database.h: Modify the Entity database functions to include a chunk of text for location data. * server/StorageManager.cpp: Implement naive storage of location data to the database.
174 lines
5.9 KiB
C++
174 lines
5.9 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 <wfmath/atlasconv.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)
|
|
{
|
|
std::string location;
|
|
Atlas::Message::MapType map;
|
|
map["pos"] = ent->m_location.pos().toAtlas();
|
|
map["orientation"] = ent->m_location.orientation().toAtlas();
|
|
Database::instance()->encodeObject(map, location);
|
|
|
|
Database::instance()->insertEntity(ent->getId(),
|
|
ent->m_location.m_loc->getId(),
|
|
ent->getType()->name(),
|
|
ent->getSeq(),
|
|
location);
|
|
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 | entity_pos_clean | entity_orient_clean);
|
|
}
|
|
|
|
void StorageManager::updateEntity(Entity * ent)
|
|
{
|
|
std::string location;
|
|
Atlas::Message::MapType map;
|
|
map["pos"] = ent->m_location.pos().toAtlas();
|
|
map["orientation"] = ent->m_location.orientation().toAtlas();
|
|
Database::instance()->encodeObject(map, location);
|
|
|
|
Database::instance()->updateEntity(ent->getId(),
|
|
ent->getSeq(),
|
|
location);
|
|
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;
|
|
}
|