void StorageManager::restoreThoughts(LocatedEntity * ent) { Database * db = Database::instance(); const DatabaseResult res = db->selectThoughts(ent->getId()); Atlas::Message::ListType thoughts_data; DatabaseResult::const_iterator I = res.begin(); DatabaseResult::const_iterator Iend = res.end(); for (; I != Iend; ++I) { const std::string thought = I.column("thought"); if (thought.empty()) { log(ERROR, compose("No thought column in property row for %1", ent->getId())); continue; } MapType thought_data; db->decodeMessage(thought, thought_data); thoughts_data.push_back(thought_data); } if (!thoughts_data.empty()) { OpVector opRes; Atlas::Objects::Operation::Think thoughtOp; Atlas::Objects::Operation::Set setOp; setOp->setArgsAsList(thoughts_data); //Make the thought come from the entity itself thoughtOp->setArgs1(setOp); thoughtOp->setTo(ent->getId()); thoughtOp->setFrom(ent->getId()); ent->sendWorld(thoughtOp); } }
/// \brief Read all the rules in one ruleset from the rules table. /// /// @param ruleset the name of the ruleset to be read. /// @param o Atlas map to store the rules in. void readRuleTable(const std::string & ruleset, MapType & o) { std::stringstream query; query << "SELECT * FROM " << m_connection.rule() << " WHERE " << " ruleset = '" << ruleset << "'"; DatabaseResult res = m_connection.runSimpleSelectQuery(query.str()); DatabaseResult::const_iterator I = res.begin(); DatabaseResult::const_iterator Iend = res.end(); for (; I != Iend; ++I) { MapType & data = (o[I.column("id")] = MapType()).asMap(); m_connection.decodeMessage(I.column("contents"), data); } }
/// \brief Read all the rules sets from the rules table /// void readRuleTableSets(std::set<std::string> & sets) { std::stringstream query; query << "SELECT ruleset FROM " << m_connection.rule(); DatabaseResult res = m_connection.runSimpleSelectQuery(query.str()); DatabaseResult::const_iterator I = res.begin(); DatabaseResult::const_iterator Iend = res.end(); for (; I != Iend; ++I) { std::string ruleset_name = I.column("ruleset"); if (sets.find(ruleset_name) == sets.end()) { sets.insert(ruleset_name); } } }
void StorageManager::restoreChildren(LocatedEntity * parent) { Database * db = Database::instance(); DatabaseResult res = db->selectEntities(parent->getId()); EntityBuilder * eb = EntityBuilder::instance(); // Iterate over res creating entities, and sorting out position, location // and orientation. Restore children, but don't restore any properties yet. DatabaseResult::const_iterator I = res.begin(); DatabaseResult::const_iterator Iend = res.end(); for (; I != Iend; ++I) { const std::string id = I.column("id"); const int int_id = forceIntegerId(id); const std::string type = I.column("type"); //By sending an empty attributes pointer we're telling the builder not to apply any default //attributes. We will instead apply all attributes ourselves when we later on restore attributes. Atlas::Objects::SmartPtr<Atlas::Objects::Entity::RootEntityData> attrs(nullptr); LocatedEntity * child = eb->newEntity(id, int_id, type, attrs, BaseWorld::instance()); if (!child) { log(ERROR, compose("Could not restore entity with id %1 of type %2" ", most likely caused by this type missing.", id, type)); continue; } const std::string location_string = I.column("location"); MapType loc_data; db->decodeMessage(location_string, loc_data); child->m_location.readFromMessage(loc_data); if (!child->m_location.pos().isValid()) { std::cout << "No pos data" << std::endl << std::flush; log(ERROR, compose("Entity %1 restored from database has no " "POS data. Ignored.", child->getId())); delete child; continue; } child->m_location.m_loc = parent; child->setFlags(entity_clean | entity_pos_clean | entity_orient_clean); BaseWorld::instance().addEntity(child); restoreChildren(child); } }
void StorageManager::restorePropertiesRecursively(LocatedEntity * ent) { Database * db = Database::instance(); PropertyManager * pm = PropertyManager::instance(); DatabaseResult res = db->selectProperties(ent->getId()); //Keep track of those properties that have been set on the instance, so we'll know what //type properties we should ignore. std::unordered_set<std::string> instanceProperties; DatabaseResult::const_iterator I = res.begin(); DatabaseResult::const_iterator Iend = res.end(); for (; I != Iend; ++I) { const std::string name = I.column("name"); if (name.empty()) { log(ERROR, compose("No name column in property row for %1", ent->getId())); continue; } const std::string val_string = I.column("value"); if (name.empty()) { log(ERROR, compose("No value column in property row for %1,%2", ent->getId(), name)); continue; } MapType prop_data; db->decodeMessage(val_string, prop_data); MapType::const_iterator J = prop_data.find("val"); if (J == prop_data.end()) { log(ERROR, compose("No property value data for %1:%2", ent->getId(), name)); continue; } assert(ent->getType() != 0); const Element & val = J->second; Element existingVal; if (ent->getAttr(name, existingVal) == 0) { if (existingVal == val) { //If the existing property, either on the instance or the type, is equal to the persisted one just skip it. continue; } } PropertyBase * prop = ent->modProperty(name); if (prop == nullptr) { prop = pm->addProperty(name, val.getType()); prop->install(ent, name); //This transfers ownership of the property to the entity. ent->setProperty(name, prop); } //If we get to here the property either doesn't exists, or have a different value than the default or existing property. prop->set(val); prop->setFlags(per_clean | per_seen); prop->apply(ent); instanceProperties.insert(name); } if (ent->getType()) { for (auto& propIter : ent->getType()->defaults()) { if (!instanceProperties.count(propIter.first)) { PropertyBase * prop = propIter.second; // If a property is in the class it won't have been installed // as setAttr() checks prop->install(ent, propIter.first); // The property will have been applied if it has an overriden // value, so we only apply it the value is still default. prop->apply(ent); } } } //Now restore all properties of the child entities. if (ent->m_contains) { for (auto& childEntity : *ent->m_contains) { restorePropertiesRecursively(childEntity); } } //We must send a sight op to the entity informing it of itself before we send any thoughts. //Else the mind won't have any information about itself. { Atlas::Objects::Operation::Sight sight; sight->setTo(ent->getId()); Atlas::Objects::Entity::Anonymous args; ent->addToEntity(args); sight->setArgs1(args); ent->sendWorld(sight); } //We should also send a sight op to the parent entity which owns the entity. //TODO: should this really be necessary or should we rely on other Sight functionality? if (ent->m_location.m_loc) { Atlas::Objects::Operation::Sight sight; sight->setTo(ent->m_location.m_loc->getId()); Atlas::Objects::Entity::Anonymous args; ent->addToEntity(args); sight->setArgs1(args); ent->m_location.m_loc->sendWorld(sight); } restoreThoughts(ent); }