static void addTypeToList(const Root & type, ListType & typeList) { typeList.push_back(type->getId()); Element children; if (type->copyAttr("children", children) != 0) { return; } if (!children.isList()) { log(ERROR, compose("Type %1 children attribute has type %2 instead of " "string.", type->getId(), Element::typeName(children.getType()))); return; } ListType::const_iterator I = children.List().begin(); ListType::const_iterator Iend = children.List().end(); for (; I != Iend; ++I) { Root child = Inheritance::instance().getClass(I->asString()); if (!child.isValid()) { log(ERROR, compose("Unable to find %1 in inheritance table", I->asString())); continue; } addTypeToList(child, typeList); } }
void TrustedConnectionCreatorintegration::setup() { m_Link_send_sent = 0; m_BaseWorld_message_called = 0; m_BaseWorld_message_called_from = 0; m_Entity_callOperation_called = 0; Entity * gw = new Entity(compose("%1", m_id_counter), m_id_counter++); m_server = new ServerRouting(*new TestWorld(*gw), "dd7452be-0137-4664-b90e-77dfb395ac39", "a2feda8e-62e9-4ba0-95c4-09f92eda6a78", compose("%1", m_id_counter), m_id_counter++, compose("%1", m_id_counter), m_id_counter++); m_connection = new Connection(*(CommSocket*)0, *m_server, "25251955-7e8c-4043-8a5e-adfb8a1e76f7", compose("%1", m_id_counter), m_id_counter++); m_creator = new Creator(compose("%1", m_id_counter), m_id_counter++); m_creatorType = new TypeNode("test_avatar"); m_creator->setType(m_creatorType); m_connection->addObject(m_creator); m_BaseWorld_message_called = 0; m_BaseWorld_message_called_from = 0; }
void TrustedConnectionCreatorintegration::test_external_op_puppet_nonexistant() { // Dispatching a Talk external op from the creator, to the creator should // result in it being passed directly to the normal op dispatch, // shortcutting the world. m_creator->m_externalMind = new ExternalMind(*m_creator); m_creator->m_externalMind->linkUp(m_connection); Entity * other = new Entity(compose("%1", m_id_counter), m_id_counter++); other->setType(m_creatorType); m_server->m_world.addEntity(other); Atlas::Objects::Operation::Talk op; op->setFrom(m_creator->getId()); op->setTo(compose("%1", m_id_counter++)); m_connection->externalOperation(op, *m_connection); // Operation should be via world dispatch, as if it was from the Entity // we are puppeting. ASSERT_TRUE(m_Link_send_sent.isValid()); ASSERT_EQUAL(m_Link_send_sent->getParents().front(), "unseen"); ASSERT_TRUE(!m_Link_send_sent->isDefaultTo()); ASSERT_EQUAL(m_Link_send_sent->getTo(), m_creator->getId()); }
TestAccount::TestAccount(ServerRouting & svr, long id, long cid) : Account(new Connection(*(CommSocket*)0, svr, "7546215f-ac75-4e1a-a2c3-a9226219259b", compose("%1", cid), cid), "cec7a6f5-ebf1-4531-a0d9-ed9bb46882ad", "59cf380e-7398-48a7-81cc-961265fadcd0", compose("%1", cid), cid) { }
void TrustedConnectionCreatorintegration::test_external_op_puppet() { // Dispatching a Talk external op from the creator, to the creator should // result in it being passed directly to the normal op dispatch, // shortcutting the world. m_creator->m_externalMind = new ExternalMind(*m_creator); m_creator->m_externalMind->linkUp(m_connection); Entity * other = new Entity(compose("%1", m_id_counter), m_id_counter++); other->setType(m_creatorType); m_server->m_world.addEntity(other); Atlas::Objects::Operation::Talk op; op->setFrom(m_creator->getId()); op->setTo(other->getId()); m_connection->externalOperation(op, *m_connection); // Operation should be via world dispatch, as if it was from the Entity // we are puppeting. ASSERT_TRUE(m_BaseWorld_message_called.isValid()); ASSERT_EQUAL(m_BaseWorld_message_called->getClassNo(), Atlas::Objects::Operation::TALK_NO); ASSERT_TRUE(!m_BaseWorld_message_called->isDefaultTo()); ASSERT_EQUAL(m_BaseWorld_message_called->getTo(), other->getId()); ASSERT_NOT_NULL(m_BaseWorld_message_called_from); ASSERT_EQUAL(m_BaseWorld_message_called_from, other); }
void Admin::createObject(const std::string & type_str, const Root & arg, const Operation & op, OpVector & res) { const std::string & objtype = arg->getObjtype(); if (objtype == "class" || objtype == "op_definition") { // New entity type if (!arg->hasAttrFlag(Atlas::Objects::ID_FLAG)) { error(op, "Set arg has no id.", res, getId()); return; } const std::string & id = arg->getId(); if (Inheritance::instance().hasClass(id)) { error(op, "Attempt to install type that already exists", res, getId()); return; } const Root & o = Inheritance::instance().getClass(type_str); if (!o.isValid()) { error(op, compose("Attempt to install type with non-existant " "parent \"%1\"", type_str), res, getId()); return; } if (Ruleset::instance()->installRule(id, "unknown", arg) == 0) { Info info; info->setTo(getId()); info->setArgs1(arg); res.push_back(info); } else { error(op, "Installing new type failed", res, getId()); } } else if (type_str == "juncture") { std::string junc_id; long junc_iid = newId(junc_id); if (junc_iid < 0) { error(op, "Juncture failed as no ID available", res, getId()); return; } Juncture * j = new Juncture(m_connection, junc_id, junc_iid); m_connection->addObject(j); m_connection->m_server.addObject(j); Anonymous info_arg; j->addToEntity(info_arg); Info info; info->setTo(getId()); info->setArgs1(info_arg); if (!op->isDefaultSerialno()) { info->setRefno(op->getSerialno()); } res.push_back(info); } else { Account::createObject(type_str, arg, op, res); } }
void Admintest::test_SetOperation_obj_IG() { Account_SetOperation_called = 0; long cid = m_id_counter++; Entity * c = new Entity(compose("%1", cid), cid); m_account->m_charactersDict.insert(std::make_pair(cid, c)); Atlas::Objects::Operation::Set op; OpVector res; Anonymous arg; arg->setObjtype("obj"); arg->setId(c->getId()); op->setArgs1(arg); m_account->SetOperation(op, res); ASSERT_EQUAL(Account_SetOperation_called, m_account); // The operation returned would have come from Account::SetOperation // but that is stubbed out ASSERT_EQUAL(res.size(), 0u); delete c; }
void ServerAccounttest::test_createObject_success_possess() { long cid = m_id_counter++; TestWorld_addNewEntity_ret_value = new Character(compose("%1", cid), cid); std::string type_str("unimportant_string"); RootEntity arg; RootEntity arg2; arg2->setAttr("possess_key", "unimportant_string"); RootOperation op; op->setArgs1(arg); op->modifyArgs().push_back(arg2); OpVector res; m_account->createObject(type_str, arg, op, res); ASSERT_EQUAL(res.size(), 1u); const RootOperation & reply = res.front(); ASSERT_EQUAL(reply->getClassNo(), Atlas::Objects::Operation::INFO_NO); delete TestWorld_addNewEntity_ret_value; TestWorld_addNewEntity_ret_value = 0; }
void ServerAccounttest::test_createObject_success_refo() { long cid = m_id_counter++; TestWorld_addNewEntity_ret_value = new Character(compose("%1", cid), cid); std::string type_str("unimportant_string"); RootEntity arg; RootOperation op; op->setSerialno(44295); OpVector res; m_account->createObject(type_str, arg, op, res); ASSERT_EQUAL(res.size(), 1u); const RootOperation & reply = res.front(); ASSERT_EQUAL(reply->getClassNo(), Atlas::Objects::Operation::INFO_NO); ASSERT_TRUE(!reply->isDefaultRefno()); ASSERT_EQUAL(reply->getRefno(), op->getSerialno()); delete TestWorld_addNewEntity_ret_value; TestWorld_addNewEntity_ret_value = 0; }
/// \brief Create a new account on the server /// /// @param name User name of the new account /// @param password Password of the new account Root BaseClient::createSystemAccount() { Anonymous player_ent; player_ent->setAttr("username", create_session_username()); player_ent->setAttr("password", compose("%1%2", ::rand(), ::rand())); player_ent->setParents(std::list<std::string>(1, "sys")); Create createAccountOp; createAccountOp->setArgs1(player_ent); createAccountOp->setSerialno(m_connection.newSerialNo()); send(createAccountOp); if (m_connection.wait() != 0) { std::cerr << "ERROR: Failed to log into server: \"" << m_connection.errorMessage() << "\"" << std::endl << std::flush; return Root(0); } const Root & ent = m_connection.getInfoReply(); if (!ent->hasAttrFlag(Atlas::Objects::ID_FLAG)) { std::cerr << "ERROR: Logged in, but account has no id" << std::endl << std::flush; } else { m_playerId = ent->getId(); // m_playerName = name; } return ent; }
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); } }
void SystemAccounttest::setup() { Entity * gw = new Entity(compose("%1", m_id_counter), m_id_counter++); m_server = new ServerRouting(*new TestWorld(*gw), "5529d7a4-0158-4dc1-b4a5-b5f260cac635", "bad621d4-616d-4faf-b9e6-471d12b139a9", compose("%1", m_id_counter), m_id_counter++, compose("%1", m_id_counter), m_id_counter++); m_connection = new Connection(*(CommSocket*)0, *m_server, "8d18a4e8-f14f-4a46-997e-ada120d5438f", compose("%1", m_id_counter), m_id_counter++); m_account = new SystemAccount(m_connection, "6c9f3236-5de7-4ba4-8b7a-b0222df0af38", "fa1a03a2-a745-4033-85cb-bb694e921e62", compose("%1", m_id_counter), m_id_counter++); }
DatabasePostgres::~DatabasePostgres() { if (!pendingQueries.empty()) { log(ERROR, compose("Database delete with %1 queries pending", pendingQueries.size())); } shutdownConnection(); }
void AccountServerLobbyintegration::setup() { LocatedEntity * gw = new Entity(compose("%1", m_id_counter), m_id_counter++); m_server = new ServerRouting(*new TestWorld(*gw), "59331d74-bb5d-4a54-b1c2-860999a4e344", "93e1f67f-63c5-4b07-af4c-574b2273563d", compose("%1", m_id_counter), m_id_counter++, compose("%1", m_id_counter), m_id_counter++); for (int i = 0; i < 3; ++i) { m_account = new TestAccount(*m_server, m_id_counter++, m_id_counter++); m_server->addAccount(m_account); m_server->m_lobby.addAccount(m_account); } ASSERT_NOT_NULL(m_account); }
int DatabasePostgres::connect(const std::string& context, std::string& error_msg) { std::stringstream conninfos; std::string db_server; if (readConfigItem(context, "dbserver", db_server) == 0) { if (db_server.empty()) { log(WARNING, "Empty database hostname specified in config file. " "Using none."); } else { conninfos << "host=" << db_server << " "; } } std::string dbname; if (context == CYPHESIS) { dbname = CYPHESIS; } else { dbname = compose("%1_%2", CYPHESIS, ::instance); } readConfigItem(context, "dbname", dbname); conninfos << "dbname=" << dbname << " "; std::string db_user; if (readConfigItem(context, "dbuser", db_user) == 0) { if (db_user.empty()) { log(WARNING, "Empty username specified in config file. " "Using current user."); } else { conninfos << "user="******" "; } } std::string db_passwd; if (readConfigItem(context, "dbpasswd", db_passwd) == 0) { conninfos << "password="******" "; } const std::string cinfo = conninfos.str(); m_connection = PQconnectdb(cinfo.c_str()); if (m_connection == nullptr) { error_msg = "Unknown error"; return -1; } if (PQstatus(m_connection) != CONNECTION_OK) { error_msg = PQerrorMessage(m_connection); PQfinish(m_connection); m_connection = nullptr; return -1; } return 0; }
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); } }
int RuleHandler::getScriptDetails(const Atlas::Message::MapType & script, const std::string & class_name, const std::string & context, std::string & script_package, std::string & script_class) { MapType::const_iterator J = script.find("name"); MapType::const_iterator Jend = script.end(); if (J == Jend || !J->second.isString()) { log(ERROR, compose("%1 \"%2\" script has no name.", context, class_name)); return -1; } const std::string & script_name = J->second.String(); J = script.find("language"); if (J == Jend || !J->second.isString()) { log(ERROR, compose("%1 \"%2\" script has no language.", context, class_name)); return -1; } const std::string & script_language = J->second.String(); if (script_language != "python") { log(ERROR, compose("%1 \"%2\" script has unknown language \"%3\".", context, class_name, script_language)); return -1; } std::string::size_type ptr = script_name.rfind("."); if (ptr == std::string::npos) { log(ERROR, compose("%1 \"%2\" python script has bad class name \"%3\".", context, class_name, script_name)); return -1; } script_package = script_name.substr(0, ptr); script_class = script_name.substr(ptr + 1); return 0; }
void ServerAccounttest::test_addNewEntity_success() { long cid = m_id_counter++; Entity * c = new Character(compose("%1", cid), cid); TestWorld_addNewEntity_ret_value = c; std::string type_str("unimportant_string"); RootEntity arg; LocatedEntity * e = m_account->addNewEntity(type_str, arg, arg); ASSERT_EQUAL(c, e); delete TestWorld_addNewEntity_ret_value; TestWorld_addNewEntity_ret_value = 0; }
bool Motion::resolveCollision() { Location & location(m_entity.m_location); bool moving = true; assert(m_collision); assert(m_collEntity != 0); assert(m_collEntity->m_location.m_loc != 0); // We have arrived at our target position and must // stop, or be deflected // FIXME This should become an assertion. if (location.m_loc != m_collEntity->m_location.m_loc) { // Race condition // This occurs if we get asked for a new update before // the last move has taken effect, so we make the new // pos exactly as it was when the last collision was // predicted. log(ERROR, compose("Collision Error: %1(%2) with parent %3 " "colliding with %4(%5) with parent %6", m_entity.getId(), m_entity.getType()->name(), location.m_loc->getId(), m_collEntity->getId(), m_collEntity->getType()->name(), m_collEntity->m_location.m_loc->getId())); } else { // FIXME Generate touch ops // This code relies on m_collNormal being a unit vector float vel_square_mag = location.velocity().sqrMag(); location.m_velocity -= m_collNormal * Dot(m_collNormal, location.m_velocity); if (location.m_velocity.mag() / consts::base_velocity > 0.05) { m_collEntity = NULL; location.m_velocity.normalize(); location.m_velocity *= std::sqrt(vel_square_mag); } else { // reset(); location.m_velocity = Vector3D(0,0,0); moving = false; } } clearCollision(); return moving; }
void ServerAccounttest::test_createObject_no_possess() { long cid = m_id_counter++; TestWorld_addNewEntity_ret_value = new Character(compose("%1", cid), cid); std::string type_str("unimportant_string"); RootEntity arg; RootEntity arg2; RootOperation op; op->setArgs1(arg); op->modifyArgs().push_back(arg2); OpVector res; m_account->createObject(type_str, arg, op, res); // FIXME No error to the client! ASSERT_TRUE(res.empty()); delete TestWorld_addNewEntity_ret_value; TestWorld_addNewEntity_ret_value = 0; }
void Admintest::test_SetOperation_obj_not_found() { Account_SetOperation_called = 0; long cid = m_id_counter++; Atlas::Objects::Operation::Set op; OpVector res; Anonymous arg; arg->setObjtype("obj"); arg->setId(compose("%1", cid)); op->setArgs1(arg); m_account->SetOperation(op, res); ASSERT_NULL(Account_SetOperation_called); // FIXME No error? Is that right? ASSERT_EQUAL(res.size(), 0u); }
return; } const std::string & hostname = hostname_attr.String(); Element port_attr; if (arg->copyAttr("port", port_attr) != 0 || !port_attr.isInt()) { error(op, "Argument to connect op has no port", res, getId()); return; } int port = port_attr.Int(); debug(std::cout << "Connecting to " << hostname << std::endl << std::flush;); m_address = new PeerAddress; boost::asio::ip::tcp::resolver resolver(m_connection->m_commSocket.m_io_service); boost::asio::ip::tcp::resolver::query query(hostname, compose("%1", port)); try { m_address->i = resolver.resolve(query); } catch (const std::exception& e) { error(op, "Could not connect to peer host.", res, getId()); return; } m_connectRef = op->getSerialno(); if (attemptConnect(hostname, port) != 0) { error(op, "Connection failed", res, getId()); } }
int OpRuleHandler::installOpDefinition(const std::string & class_name, const std::string & parent, const Atlas::Objects::Root & class_desc, std::string & dependent, std::string & reason) { assert(class_name == class_desc->getId()); Inheritance & i = Inheritance::instance(); if (!i.hasClass(parent)) { debug(std::cout << "op_definition \"" << class_name << "\" has non existant parent \"" << parent << "\". Waiting." << std::endl << std::flush;); dependent = parent; reason = compose("Operation \"%1\" has parent \"%2\" which does " "not exist.", class_name, parent); return 1; } Atlas::Objects::Root r = atlasOpDefinition(class_name, parent); if (i.addChild(class_desc) == 0) { return -1; } Atlas::Objects::Factories::instance()->addFactory(class_name, &Atlas::Objects::generic_factory); return 0; } int OpRuleHandler::modifyOpDefinition(const std::string & class_name,
void Admin::GetOperation(const Operation & op, OpVector & res) { const std::vector<Root> & args = op->getArgs(); if (args.empty()) { error(op, "Get has no args.", res, getId()); return; } const Root & arg = args.front(); if (!arg->hasAttrFlag(Atlas::Objects::OBJTYPE_FLAG)) { error(op, "Get arg has no objtype.", res, getId()); return; } const std::string & objtype = arg->getObjtype(); if (!arg->hasAttrFlag(Atlas::Objects::ID_FLAG)) { error(op, "Get arg has no id.", res, getId()); return; } const std::string & id = arg->getId(); if (id.empty()) { error(op, "Get arg id empty", res, getId()); return; } Info info; if (objtype == "object" || objtype == "obj") { if (m_connection == 0) { return; } long intId = integerId(id); const RouterMap & OOGDict = m_connection->m_server.getObjects(); RouterMap::const_iterator J = OOGDict.find(intId); const EntityDict & worldDict = m_connection->m_server.m_world.getEntities(); EntityDict::const_iterator K = worldDict.find(intId); if (J != OOGDict.end()) { Router * obj = J->second; Anonymous info_arg; obj->addToEntity(info_arg); info->setArgs1(info_arg); } else if (K != worldDict.end()) { Anonymous info_arg; K->second->addToEntity(info_arg); info->setArgs1(info_arg); } else { clientError(op, compose("Unknown object id \"%1\" requested", id), res, getId()); return; } } else if (objtype == "class" || objtype == "meta" || objtype == "op_definition") { const Root & o = Inheritance::instance().getClass(id); if (!o.isValid()) { clientError(op, compose("Unknown type definition for \"%1\" " "requested", id), res); return; } info->setArgs1(o); } else if (objtype == "op") { if (arg->getClassNo() == Atlas::Objects::Operation::THOUGHT_NO) { long intId = integerId(id); const EntityDict & worldDict = m_connection->m_server.m_world.getEntities(); EntityDict::const_iterator K = worldDict.find(intId); if (K != worldDict.end()) { Character* character = dynamic_cast<Character*>(K->second); if (character) { character->sendMind(op, res); } else { clientError(op, compose("Entity with id \"%1\" is not a character", id), res, getId()); return; } std::vector<Root> newRet; //Why can't I do "info->setArgs(res)"? for (auto& operation : res) { newRet.push_back(operation); } info->setArgs(newRet); res.clear(); } else { clientError(op, compose("Unknown object id \"%1\" requested", id), res, getId()); return; } } else if (arg->getClassNo() == Atlas::Objects::Operation::GOAL_INFO_NO) { long intId = integerId(id); const EntityDict & worldDict = m_connection->m_server.m_world.getEntities(); EntityDict::const_iterator K = worldDict.find(intId); if (K != worldDict.end()) { Character* character = dynamic_cast<Character*>(K->second); if (character) { character->sendMind(op, res); } else { clientError(op, compose("Entity with id \"%1\" is not a character", id), res, getId()); return; } std::vector<Root> newRet; //Why can't I do "info->setArgs(res)"? for (auto& operation : res) { newRet.push_back(operation); } info->setArgs(newRet); res.clear(); } else { clientError(op, compose("Unknown object id \"%1\" requested", id), res, getId()); return; } } } else { error(op, compose("Unknown object type \"%1\" requested for \"%2\"", objtype, id), res, getId()); return; } res.push_back(info); }
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); }
void SpawnerProperty::createNewEntity(LocatedEntity * e, const Operation & op, OpVector & res, const std::string& locId) { Anonymous create_arg; if (!m_entity.empty()) { create_arg = smart_dynamic_cast<Anonymous>( Factories::instance()->createObject(m_entity)); if (!create_arg.isValid()) { log(ERROR, "Could not parse 'entity' data on spawner into Entity instance."); return; } } else { create_arg->setParents(std::list<std::string>(1, m_type)); } create_arg->setLoc(locId); WFMath::MTRand& rand = WFMath::MTRand::instance; if (m_mode_external) { if (!e->m_location.pos().isValid()) { log(ERROR, "Tried to spawn entity for which parent has no valid position."); return; } //randomize position and rotation float angle = rand.randf(WFMath::numeric_constants<float>::pi() * 2); //place it between 0 and 2 meters away float distance = rand.randf(2.0f); //if we're solid we should make sure it's not within our own radius if (e->m_location.isSolid() && e->m_location.bBox().isValid()) { distance += e->m_location.radius(); } //and finally make sure that it's not beyond the radius for checking if (m_radius != 0.0f) { distance = std::min(m_radius, distance); } float x = (distance * std::cos(angle)); float y = (distance * std::sin(angle)); ::addToEntity( WFMath::Point<3>(e->m_location.pos()).shift( WFMath::Vector<3>(x, y, 0)), create_arg->modifyPos()); } else { //If it's an internal spawner, spawn anywhere within the bounding box. const BBox bbox = e->m_location.m_bBox; if (bbox.isValid()) { float x = rand.rand(bbox.highCorner().x() - bbox.lowCorner().x()) + bbox.lowCorner().x(); float y = rand.rand(bbox.highCorner().y() - bbox.lowCorner().y()) + bbox.lowCorner().y(); ::addToEntity(WFMath::Point<3>(x, y, 0), create_arg->modifyPos()); } else { ::addToEntity(WFMath::Point<3>::ZERO(), create_arg->modifyPos()); } } float rotation = rand.randf(WFMath::numeric_constants<float>::pi() * 2); WFMath::Quaternion orientation(WFMath::Vector<3>(0, 0, 1), rotation); create_arg->setAttr("orientation", orientation.toAtlas()); Create create; create->setTo(e->m_location.m_loc->getId()); create->setArgs1(create_arg); res.push_back(create); debug(log(NOTICE, compose("Spawner belonging to entity %1 creating new" " entity of type %2", e->getId(), m_type)) ;);
const std::string & parent, const Root & class_desc, std::string & dependent, std::string & reason) { assert(class_name == class_desc->getId()); // Get the new factory for this rule ArchetypeFactory * parent_factory = dynamic_cast<ArchetypeFactory*>(m_builder->getClassFactory(parent)); if (parent_factory == 0) { debug( std::cout << "class \"" << class_name << "\" has non existant parent \"" << parent << "\". Waiting." << std::endl << std::flush ;); dependent = parent; reason = compose("Entity rule \"%1\" has parent \"%2\" which does " "not exist.", class_name, parent); return 1; } ArchetypeFactory * factory = parent_factory->duplicateFactory(); if (factory == 0) { log(ERROR, compose( "Attempt to install rule \"%1\" which has parent \"%2\" " "which cannot be instantiated", class_name, parent)); return -1; } assert(factory->m_parent == parent_factory); if (populateArchetypeFactory(class_name, factory, class_desc->asMessage(),