// Cyphesis Online RPG Server and AI Engine // Copyright (C) 2000,2001 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: Persistor.cpp,v 1.39 2007-12-03 23:18:52 alriddoch Exp $ #include "Persistor.h" #include "Persistor_impl.h" #include "rulesets/Entity.h" #include "rulesets/Thing.h" #include "rulesets/Character.h" #include "rulesets/Creator.h" #include "rulesets/Plant.h" #include "rulesets/Stackable.h" #include "rulesets/Structure.h" #include "rulesets/World.h" #include "common/Database.h" #include "common/terrain_utils.h" using Atlas::Message::MapType; template<> Persistor::Persistor(bool temp) : m_class("entity") { if (temp) { return; } MapType desc; desc["class"] = " "; desc["type"] = " "; // desc["loc"] = " "; desc["loc"] = 0; desc["cont"] = 0; desc["px"] = 1.0; desc["py"] = 1.0; desc["pz"] = 1.0; desc["ox"] = 1.0; desc["oy"] = 1.0; desc["oz"] = 1.0; desc["ow"] = 1.0; desc["hasBox"] = 0xb001; desc["bnx"] = 1.0; desc["bny"] = 1.0; desc["bnz"] = 1.0; desc["bfx"] = 1.0; desc["bfy"] = 1.0; desc["bfz"] = 1.0; desc["status"] = 1.0; desc["name"] = " "; desc["mass"] = 1.0; desc["seq"] = 0; desc["attributes"] = ""; Database::instance()->registerEntityTable(m_class, desc); } template<> Persistor::Persistor(bool temp) : m_class("thing") { if (temp) { return; } MapType desc; // FIXME Sort out attributes Database::instance()->registerEntityTable(m_class, desc, "entity"); } template<> Persistor::Persistor(bool temp) : m_class("line") { if (temp) { return; } MapType desc; // FIXME Sort out attributes Database::instance()->registerEntityTable(m_class, desc, "thing"); } template<> Persistor::Persistor(bool temp) : m_class("area") { if (temp) { return; } MapType desc; // FIXME Sort out attributes Database::instance()->registerEntityTable(m_class, desc, "thing"); } template<> Persistor::Persistor(bool temp) : m_class("character") { if (temp) { return; } MapType desc; // FIXME Sort out attributes desc["sex"] = " "; desc["drunkness"] = 1.0; desc["food"] = 1.0; desc["right_hand_wield"] = " "; Database::instance()->registerEntityTable(m_class, desc, "thing"); } template<> Persistor::Persistor(bool temp) : m_class("creator") { if (temp) { return; } // Creator entities are not persisted } template<> Persistor::Persistor(bool temp) : m_class("plant") { if (temp) { return; } MapType desc; // FIXME Sort out attributes desc["fruits"] = 1; desc["fruitName"] = " "; desc["fruitChance"] = 1; desc["sizeAdult"] = 1.0; Database::instance()->registerEntityTable(m_class, desc, "thing"); } template<> Persistor::Persistor(bool temp) : m_class("stackable") { if (temp) { return; } MapType desc; // FIXME Sort out attributes desc["num"] = 1; Database::instance()->registerEntityTable(m_class, desc, "thing"); } template<> Persistor::Persistor(bool temp) : m_class("structure") { if (temp) { return; } MapType desc; // FIXME Sort out attributes Database::instance()->registerEntityTable(m_class, desc, "thing"); } template<> Persistor::Persistor(bool temp) : m_class("world") { if (temp) { return; } MapType desc; // FIXME Sort out attributes Database::instance()->registerEntityTable(m_class, desc, "entity"); desc.clear(); desc["height"] = 0.1f; Database::instance()->registerArrayTable("terrain", 2, desc); } template<> void Persistor::update(Character * t) { std::string columns; uCharacter(*t, columns); uEntity(*t, columns); Database::instance()->updateEntityRow(m_class, t->getId(), columns); t->clearUpdateFlags(); } template<> void Persistor::update(Creator * t) { // Creator entities are not persisted // Is this really needed? Probably not, as its never called. } template<> void Persistor::update(Plant * t) { std::string columns; uPlant(*t, columns); uEntity(*t, columns); Database::instance()->updateEntityRow(m_class, t->getId(), columns); t->clearUpdateFlags(); } template<> void Persistor::update(World * t) { if (t->getUpdateFlags() & ~a_terrain) { std::string columns; uEntity(*t, columns); Database::instance()->updateEntityRow(m_class, t->getId(), columns); } if (t->getUpdateFlags() & a_terrain) { updateStoredTerrain(t->getId(), t->terrain(), t->modifiedTerrain(), t->createdTerrain()); t->clearTerrainFlags(); } t->clearUpdateFlags(); } template<> void Persistor::hookup(Character & t) { t.updated.connect(sigc::bind(sigc::mem_fun(this, &Persistor::update), &t)); t.destroyed.connect(sigc::bind(sigc::mem_fun(this, &Persistor::remove), &t)); } template<> void Persistor::persist(Character & t) { hookup(t); std::string columns; std::string values; cEntity(t, columns, values); cCharacter(t, columns, values); Database::instance()->createEntityRow(m_class, t.getId(), columns, values); } template<> void Persistor::persist(Plant & p) { hookup(p); std::string columns; std::string values; cEntity(p, columns, values); cPlant(p, columns, values); Database::instance()->createEntityRow(m_class, p.getId(), columns, values); } template<> void Persistor::persist(Creator & t) { // Creator entities are not persisted } template<> void Persistor::hookup(World & t) { t.updated.connect(sigc::bind(sigc::mem_fun(this, &Persistor::update), &t)); // The game world should never be destroyed, so we don't connect // it to a remove function. } template<> void Persistor::cEntity(Entity & t, std::string & c, std::string & v) { const char * cs = ", "; const char * sq = "'"; if (!c.empty()) { c += cs; } c += "class, type, cont, px, py, pz, ox, oy, oz, ow, hasBox, bnx, bny, bnz, bfx, bfy, bfz, status, name, mass, seq, attributes"; std::stringstream q; q << sq << m_class << sq << cs << sq << t.getType() << sq << cs << t.m_contains.size() << cs << t.m_location.pos().x() << cs << t.m_location.pos().y() << cs << t.m_location.pos().z() << cs; if (t.m_location.orientation().isValid()) { q << t.m_location.orientation().vector().x() << cs << t.m_location.orientation().vector().y() << cs << t.m_location.orientation().vector().z() << cs << t.m_location.orientation().scalar() << cs; } else { q << "0, 0, 0, 1, "; } if (t.m_location.bBox().isValid()) { q << "'t', " << t.m_location.bBox().lowCorner().x() << cs << t.m_location.bBox().lowCorner().y() << cs << t.m_location.bBox().lowCorner().z() << cs << t.m_location.bBox().highCorner().x() << cs << t.m_location.bBox().highCorner().y() << cs << t.m_location.bBox().highCorner().z() << cs; } else { q << "'f', 0, 0, 0, 0, 0, 0, "; } q << t.getSeq() << cs; if (t.getAttributes().empty()) { q << "''"; } else { std::string aString; Database::instance()->encodeObject(t.getAttributes(), aString); q << "'" << aString << "'"; } if (!v.empty()) { v += cs; } v += q.str(); } template<> void Persistor::persist(World & t) { hookup(t); std::string columns; std::string values; cEntity(t, columns, values); Database::instance()->createEntityRow(m_class, t.getId(), columns, values); storeTerrain(t.getId(), t.terrain()); } template class Persistor; template class Persistor; template class Persistor; template class Persistor; template class Persistor; template class Persistor; template class Persistor; template class Persistor;