void run_operation_checks(TestServerAccount * ac, Entity * chr, WorldRouter & world) { // Entity injection test { Anonymous ent; // Add the test attributes ent->setAttr("objtype", "obj"); ent->setAttr("name", "test_entity"); ent->setParents(std::list<std::string>(1,"thing")); Create op; OpVector res; op->setArgs1(ent); ac->operation(op, res); Entity *reply = world.findByName("test_entity"); assert(reply != 0); } // Regular create op tests { // This is the only op we've overridden Create op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setParents(std::list<std::string>()); ac->operation(op, res); op_arg->setParents(std::list<std::string>(1, "game_entity")); ac->operation(op, res); op_arg->setObjtype("obj"); ac->operation(op, res); op_arg->setName("Bob"); ac->operation(op, res); op_arg->setObjtype("class"); ac->operation(op, res); op_arg->setId("game_entity"); ac->operation(op, res); op_arg->setId("new_class"); ac->operation(op, res); op_arg->setParents(std::list<std::string>(1, "")); ac->operation(op, res); op_arg->setParents(std::list<std::string>(1, "non_exist")); ac->operation(op, res); } }
/// \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 Connectiontest::test_CreateOperation_root_arg() { Create op; OpVector res; op->setArgs1(Root()); m_connection->operation(op, res); ASSERT_EQUAL(m_connection->m_objects.size(), 0u); ASSERT_TRUE(Router_error_called); }
void Connectiontest::test_CreateOperation_empty_arg() { Create op; OpVector res; restricted_flag = false; Anonymous op_arg; op->setArgs1(op_arg); m_connection->operation(op, res); ASSERT_EQUAL(m_connection->m_objects.size(), 0u); ASSERT_TRUE(Router_error_called); }
void Accountintegration::test_CreateOperation() { Anonymous op_arg; op_arg->setParents(std::list<std::string>(1, "game_entity")); op_arg->setName("Bob"); Create op; op->setArgs1(op_arg); OpVector res; m_ac->operation(op, res); }
void Connectiontest::test_CreateOperation_number_username() { Create op; OpVector res; Anonymous op_arg; op->setArgs1(op_arg); op_arg->setAttr("username", 1); // Malformed username m_connection->operation(op, res); ASSERT_EQUAL(m_connection->m_objects.size(), 0u); ASSERT_TRUE(Router_error_called); }
void Connectiontest::test_CreateOperation() { Create op; OpVector res; Anonymous op_arg; op->setArgs1(op_arg); op_arg->setAttr("username", "jim"); op_arg->setAttr("password", "foo"); // valid username and password m_connection->operation(op, res); ASSERT_EQUAL(m_connection->m_objects.size(), 1u); }
void Connectiontest::test_CreateOperation_no_passed() { Create op; OpVector res; Anonymous op_arg; op->setArgs1(op_arg); op_arg->setAttr("username", "jim"); // username, no password m_connection->operation(op, res); ASSERT_EQUAL(m_connection->m_objects.size(), 0u); ASSERT_TRUE(Router_error_called); }
void Connectiontest::test_CreateOperation_account_by_id() { Create op; OpVector res; Anonymous op_arg; op->setArgs1(op_arg); op_arg->setId("jim"); // Legacy op m_connection->operation(op, res); ASSERT_EQUAL(m_connection->m_objects.size(), 0u); ASSERT_TRUE(Router_error_called); }
void Connectiontest::test_CreateOperation_username() { Create op; OpVector res; Anonymous op_arg; op->setArgs1(op_arg); op_arg->setAttr("username", ""); op_arg->setAttr("password", "foo"); // zero length username m_connection->operation(op, res); ASSERT_EQUAL(m_connection->m_objects.size(), 0u); ASSERT_TRUE(Router_clientError_called); }
LocatedEntity * CreatorClient::make(const RootEntity & entity) { Create op; op->setArgs1(entity); op->setFrom(getId()); op->setTo(getId()); OpVector result; if (sendAndWaitReply(op, result) != 0) { std::cerr << "No reply to make" << std::endl << std::flush; return NULL; } assert(!result.empty()); const Operation & res = result.front(); if (!res.isValid()) { std::cerr << "NULL reply to make" << std::endl << std::flush; return NULL; } // FIXME Make this more robust against an info response if (res->getClassNo() == Atlas::Objects::Operation::SIGHT_NO) { if (res->getArgs().empty()) { std::cerr << "Reply to make has no args" << std::endl << std::flush; return NULL; } RootOperation arg = smart_dynamic_cast<RootOperation>(res->getArgs().front()); if (!arg.isValid()) { std::cerr << "Arg of reply to make is not an operation" << std::endl << std::flush; return NULL; } if (arg->getClassNo() != Atlas::Objects::Operation::CREATE_NO) { std::cerr << "Reply to make isn't sight of create" << std::endl << std::flush; return NULL; } return handleMakeResponse(arg, res->getSeconds()); } else if (res->getClassNo() == Atlas::Objects::Operation::INFO_NO) { return handleMakeResponse(res, res->getSeconds()); } else { std::cerr << "Reply to make isn't sight or info" << std::endl << std::flush; return NULL; } }
int AtlasStreamClient::create(const std::string & type, const std::string & username, const std::string & password) { m_username = username; Create c; Anonymous account; account->setAttr("username", username); account->setAttr("password", password); account->setParents(std::list<std::string>(1, type)); c->setArgs1(account); c->setSerialno(newSerialNo()); send(c); return waitForLoginResponse(); }
void EntityImporterBase::createEntity(const RootEntity & obj, OpVector & res) { ++mStats.entitiesProcessedCount; ++mStats.entitiesCreateCount; EventProgress.emit(); m_state = ENTITY_CREATING; assert(mTreeStack.size() > 1); std::deque<StackEntry>::reverse_iterator I = mTreeStack.rbegin(); ++I; assert(I != mTreeStack.rend()); const std::string & loc = I->restored_id; RootEntity create_arg = obj.copy(); create_arg->removeAttrFlag(Atlas::Objects::Entity::CONTAINS_FLAG); create_arg->removeAttrFlag(Atlas::Objects::Entity::VELOCITY_FLAG); create_arg->removeAttrFlag(Atlas::Objects::ID_FLAG); create_arg->setLoc(loc); //Remove any attribute which references another entity from the Create op. //This is because the attribute will at this time with certainty refer to the wrong or a non-existing entity. //The attribute will later on be set through a Set op in sendResolvedEntityReferences(). auto referenceMapEntryI = mEntitiesWithReferenceAttributes.find(obj->getId()); if (referenceMapEntryI != mEntitiesWithReferenceAttributes.end()) { for (const auto& attributeName : referenceMapEntryI->second) { create_arg->removeAttr(attributeName); } } Create create; create->setArgs1(create_arg); create->setFrom(mAvatarId); create->setSerialno(newSerialNumber()); mCreateEntityMapping.insert(std::make_pair(create->getSerialno(), obj->getId())); res.push_back(create); }
void EntityImporterBase::createEntity(const RootEntity & obj, OpVector & res) { ++mStats.entitiesProcessedCount; ++mStats.entitiesCreateCount; EventProgress.emit(); m_state = ENTITY_CREATING; assert(mTreeStack.size() > 1); auto I = mTreeStack.rbegin(); ++I; assert(I != mTreeStack.rend()); const std::string & loc = I->restored_id; RootEntity create_arg = obj.copy(); create_arg->removeAttrFlag(Atlas::Objects::Entity::CONTAINS_FLAG); create_arg->removeAttrFlag(Atlas::Objects::Entity::VELOCITY_FLAG); create_arg->removeAttrFlag(Atlas::Objects::ID_FLAG); create_arg->setLoc(loc); //Remove any attribute which references another entity from the Create op. //This is because the attribute will at this time with certainty refer to the wrong or a non-existing entity. //The attribute will later on be set through a Set op in sendResolvedEntityReferences(). auto referenceMapEntryI = mEntitiesWithReferenceAttributes.find(obj->getId()); if (referenceMapEntryI != mEntitiesWithReferenceAttributes.end()) { std::set<std::string> resolvedAttributes; for (const auto& referenceEntry : referenceMapEntryI->second) { size_t resolvedEntitiesCount = 0; //Check if all the referenced entities perhaps already have been created. for (const auto& entityId : referenceEntry.referencedEntities) { auto resolvedI = mEntityIdMap.find(entityId); if (resolvedI != mEntityIdMap.end()) { resolvedEntitiesCount++; } } //If all entities were resolved, we should resolve the property now. if (resolvedEntitiesCount == referenceEntry.referencedEntities.size()) { Element element = create_arg->getAttr(referenceEntry.propertyName); resolveEntityReferences(element); create_arg->setAttr(referenceEntry.propertyName, element); resolvedAttributes.insert(referenceEntry.propertyName); } else { create_arg->removeAttr(referenceEntry.propertyName); } } //Remove those attributes that were resolved if (resolvedAttributes.size() == referenceMapEntryI->second.size()) { //All attributes were resolved, remove the entry completely. mEntitiesWithReferenceAttributes.erase(referenceMapEntryI); } else { //Only remove those entries that were destroyed. std::vector<ReferencedEntry> copy; for (auto& referenceEntry : referenceMapEntryI->second) { if (resolvedAttributes.find(referenceEntry.propertyName) == resolvedAttributes.end()) { copy.push_back(std::move(referenceEntry)); } } referenceMapEntryI->second = std::move(copy); } } Create create; create->setArgs1(create_arg); create->setFrom(mAvatarId); create->setSerialno(newSerialNumber()); mCreateEntityMapping.insert(std::make_pair(create->getSerialno(), obj->getId())); res.push_back(create); }
LocatedEntity * CreatorClient::make(const RootEntity & entity) { Create op; op->setArgs1(entity); op->setFrom(getId()); op->setTo(getId()); OpVector result; if (sendAndWaitReply(op, result) != 0) { std::cerr << "No reply to make" << std::endl << std::flush; return NULL; } assert(!result.empty()); const Operation & res = result.front(); if (!res.isValid()) { std::cerr << "NULL reply to make" << std::endl << std::flush; return NULL; } if (res->getClassNo() != Atlas::Objects::Operation::SIGHT_NO) { std::cerr << "Reply to make isn't sight" << std::endl << std::flush; return NULL; } if (res->getArgs().empty()) { std::cerr << "Reply to make has no args" << std::endl << std::flush; return NULL; } RootOperation arg = smart_dynamic_cast<RootOperation>(res->getArgs().front()); if (!arg.isValid()) { std::cerr << "Arg of reply to make is not an operation" << std::endl << std::flush; return NULL; } if (arg->getClassNo() != Atlas::Objects::Operation::CREATE_NO) { std::cerr << "Reply to make isn't sight of create" << std::endl << std::flush; return NULL; } if (arg->getArgs().empty()) { std::cerr << "Arg of reply to make has no args" << std::endl << std::flush; return NULL; } RootEntity created = smart_dynamic_cast<RootEntity>(arg->getArgs().front()); if (!created.isValid()) { std::cerr << "Created argument is not an entity" << std::endl << std::flush; return NULL; } if (!created->hasAttrFlag(Atlas::Objects::ID_FLAG)) { std::cerr << "Created entity has no id" << std::endl << std::flush; return NULL; } const std::string & created_id = created->getId(); if (created->getParents().empty()) { std::cerr << "Created entity " << created_id << " has no type" << std::endl << std::flush; return NULL; } const std::string & created_type = created->getParents().front(); std::cout << "Created: " << created_type << "(" << created_id << ")" << std::endl << std::flush; LocatedEntity * obj = m_map.updateAdd(created, res->getSeconds()); return obj; }
void AccountConnectionintegration::test_account_creation() { // Basic player account creation { ASSERT_NOT_NULL(m_connection); ASSERT_TRUE(m_connection->objects().empty()); Create op; Anonymous create_arg; create_arg->setParents(std::list<std::string>(1, "player")); create_arg->setAttr("username", "39d409ec"); create_arg->setAttr("password", "6a6e71bab281"); op->setArgs1(create_arg); ASSERT_TRUE(test_sent_ops.empty()); // Send the operation to create the account m_connection->externalOperation(op, *m_connection); // There should be a response op ASSERT_TRUE(!test_sent_ops.empty()); ASSERT_EQUAL(test_sent_ops.size(), 1u); // and the account creation should have created an object bound // to this connection. ASSERT_TRUE(!m_connection->objects().empty()); // Check the response is an info indicating successful account // creation. const Operation & reply = test_sent_ops.front(); ASSERT_EQUAL(reply->getClassNo(), Atlas::Objects::Operation::INFO_NO); // The Info response should have an argument describing the created // account const std::vector<Root> & reply_args = reply->getArgs(); ASSERT_TRUE(!reply_args.empty()); RootEntity account = smart_dynamic_cast<RootEntity>(reply_args.front()); ASSERT_TRUE(account.isValid()); // The account ID should be provided ASSERT_TRUE(!account->isDefaultId()); const std::string account_id = account->getId(); ASSERT_TRUE(!account_id.empty()); // Check the account has been registered in the server object Router * account_router_ptr = m_server->getObject(account_id); ASSERT_NOT_NULL(account_router_ptr); // Check the account has been logged into the lobby const AccountDict & lobby_dict = m_server->m_lobby.getAccounts(); AccountDict::const_iterator I = lobby_dict.find(account_id); ASSERT_TRUE(I != lobby_dict.end()); Account * account_ptr = I->second; ASSERT_EQUAL(account_router_ptr, account_ptr); // Basic login as now been established by account creation // Set up some other account details create_arg->setAttr("username", "89cae312"); create_arg->setAttr("password", "d730b8bd2d6c"); // and try an additional account creation, which should fail. // Multiple logins are ok, but there is no reason to allow multiple // account creations. test_sent_ops.clear(); m_connection->externalOperation(op, *m_connection); ASSERT_TRUE(!test_sent_ops.empty()); ASSERT_EQUAL(test_sent_ops.size(), 1u); const Operation & error_reply = test_sent_ops.front(); ASSERT_EQUAL(error_reply->getClassNo(), Atlas::Objects::Operation::ERROR_NO); Player::playableTypes.insert(test_valid_character_type); Anonymous character_arg; character_arg->setParents(std::list<std::string>(1, test_valid_character_type)); character_arg->setName("938862f2-4db2-4e8e-b944-7b0935e569db"); Create character_op; character_op->setArgs1(character_arg); character_op->setFrom(account_id); test_sent_ops.clear(); m_connection->externalOperation(character_op, *m_connection); // FIXME the above went through Account::externalOperation, so there // is no reply in res. The reply has gone directly to the Link::send // method. Add a way of checking, once there are better stubs. ASSERT_TRUE(!test_sent_ops.empty()); ASSERT_EQUAL(test_sent_ops.size(), 2u); const Operation & create_reply = test_sent_ops.front(); ASSERT_EQUAL(create_reply->getClassNo(), Atlas::Objects::Operation::INFO_NO); // TODO Character creation etc? // TODO Lobby interaction? // TODO Logout ? } }
void AccountConnectionintegration::test_account_creation() { // Basic player account creation { ASSERT_NOT_NULL(m_connection); ASSERT_TRUE(m_connection->objects().empty()); Create op; Anonymous create_arg; create_arg->setParent("player"); create_arg->setAttr("username", "39d409ec"); create_arg->setAttr("password", "6a6e71bab281"); op->setArgs1(create_arg); ASSERT_TRUE(test_sent_ops.empty()); // Send the operation to create the account m_connection->externalOperation(op, *m_connection); // There should be a response op ASSERT_TRUE(!test_sent_ops.empty()); ASSERT_EQUAL(test_sent_ops.size(), 1u); // and the account creation should have created an object bound // to this connection. ASSERT_TRUE(!m_connection->objects().empty()); // Check the response is an info indicating successful account // creation. const Operation & reply = test_sent_ops.front(); ASSERT_EQUAL(reply->getClassNo(), Atlas::Objects::Operation::INFO_NO); // The Info response should have an argument describing the created // account const std::vector<Root> & reply_args = reply->getArgs(); ASSERT_TRUE(!reply_args.empty()); RootEntity account = smart_dynamic_cast<RootEntity>(reply_args.front()); ASSERT_TRUE(account.isValid()); // The account ID should be provided ASSERT_TRUE(!account->isDefaultId()); const std::string account_id = account->getId(); ASSERT_TRUE(!account_id.empty()); // Check the account has been registered in the server object Router * account_router_ptr = m_server->getObject(account_id); ASSERT_NOT_NULL(account_router_ptr); // Check the account has been logged into the lobby const auto & lobby_dict = m_server->m_lobby.getAccounts(); auto I = lobby_dict.find(account_id); ASSERT_TRUE(I != lobby_dict.end()); auto account_ptr = I->second; ASSERT_EQUAL(account_router_ptr, account_ptr); // Basic login as now been established by account creation // Set up some other account details create_arg->setAttr("username", "89cae312"); create_arg->setAttr("password", "d730b8bd2d6c"); // and try an additional account creation, which should fail. // Multiple logins are ok, but there is no reason to allow multiple // account creations. test_sent_ops.clear(); m_connection->externalOperation(op, *m_connection); ASSERT_TRUE(!test_sent_ops.empty()); ASSERT_EQUAL(test_sent_ops.size(), 1u); const Operation & error_reply = test_sent_ops.front(); ASSERT_EQUAL(error_reply->getClassNo(), Atlas::Objects::Operation::ERROR_NO); // TODO Character creation etc? // TODO Lobby interaction? // TODO Logout ? } }
int main() { // WorldRouter world; // Entity & e = world.m_gameWorld; ServerRouting server(*(BaseWorld*)0, "noruleset", "unittesting", "1", 1, "2", 2); CommServer commServer(server); TestCommClient * tcc = new TestCommClient(commServer); TestConnection * tc = new TestConnection(*tcc, server, "addr", "3", 3); Account * ac = tc->testAddAccount("bob", "foo"); assert(ac != 0); ac = tc->testRemoveAccount(ac); assert(ac != 0); tc->removeObject(ac); assert(tc->numObjects() == 0); { Create op; OpVector res; tc->operation(op, res); op->setArgs1(Root()); tc->operation(op, res); restricted_flag = true; tc->operation(op, res); restricted_flag = false; Anonymous op_arg; op->setArgs1(op_arg); tc->operation(op, res); op_arg->setId("jim"); // Legacy op tc->operation(op, res); op_arg->setAttr("username", 1); // Malformed username tc->operation(op, res); op_arg->setAttr("username", "jim"); // username, no password tc->operation(op, res); op_arg->setAttr("password", ""); // zero length password tc->operation(op, res); op_arg->setAttr("username", ""); op_arg->setAttr("password", "foo"); // zero length username tc->operation(op, res); op_arg->setAttr("username", "jim"); // valid username and password tc->operation(op, res); assert(tc->numObjects() != 0); } { Login op; OpVector res; tc->operation(op, res); op->setArgs1(Root()); tc->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); tc->operation(op, res); op_arg->setId("bob"); tc->operation(op, res); op_arg->setAttr("username", 1); tc->operation(op, res); op_arg->setAttr("username", ""); tc->operation(op, res); op_arg->setAttr("username", "bob"); tc->operation(op, res); op_arg->setAttr("password", "foo"); tc->operation(op, res); tc->operation(op, res); } { Get op; OpVector res; tc->operation(op, res); Root op_arg; op->setArgs1(op_arg); tc->operation(op, res); op_arg->setId("1"); tc->operation(op, res); op_arg->setId("game_entity"); tc->operation(op, res); } { Logout op; OpVector res; tc->operation(op, res); op->setSerialno(24); tc->operation(op, res); Root op_arg; op->setArgs1(op_arg); tc->operation(op, res); op_arg->setId("-1"); tc->operation(op, res); op_arg->setId("23"); tc->operation(op, res); // How to determine the real ID? const RouterMap rm = tc->getObjects(); RouterMap::const_iterator I = rm.begin(); for (;I != rm.end(); ++I) { std::string object_id = String::compose("%1", I->first); std::cout << "ID: " << object_id << std::endl; op_arg->setId(object_id); tc->operation(op, res); } } delete tc; }
/// \brief Teleport an entity to the connected peer /// /// @param ent The entity to be teleported /// @return Returns 0 on success and -1 on failure int Peer::teleportEntity(const Entity * ent) { if (m_state != PEER_AUTHENTICATED) { log(ERROR, "Peer not authenticated yet."); return -1; } long iid = ent->getIntId(); if (m_teleports.find(iid) != m_teleports.end()) { log(INFO, "Transfer of this entity already in progress"); return -1; } struct timeval timeVal; gettimeofday(&timeVal, NULL); time_t teleport_time = timeVal.tv_sec; // Add a teleport state object to identify this teleport request TeleportState * s = new TeleportState(teleport_time); if (s == NULL) { log(ERROR, "Unable to allocate teleport state object"); return -1; } // Check if the entity has a mind const Character * chr = dynamic_cast<const Character *>(ent); ExternalMind * mind = 0; if (chr != 0 && chr->m_externalMind != 0) { mind = dynamic_cast<ExternalMind*>(chr->m_externalMind); } Atlas::Objects::Entity::Anonymous atlas_repr; ent->addToEntity(atlas_repr); Create op; op->setFrom(m_accountId); op->setSerialno(iid); op->setArgs1(atlas_repr); if (mind != 0 && mind->isConnected()) { // Entities with a mind require an additional one-time possess key that // is used by the client to authenticate a teleport on the destination // peer std::string key; log(INFO, "Entity has a mind. Generating random key"); // FIXME non-random, plus potetial timing attack. WFMath::MTRand generator; for(int i=0;i<32;i++) { char ch = (char)((int)'a' + generator.rand(25)); key += ch; } s->setKey(key); // Add an additional possess key argument log(INFO, String::compose("Adding possess key %1 to Create op", key)); Anonymous key_arg; key_arg->setAttr("possess_key", key); std::vector<Root> & create_args = op->modifyArgs(); create_args.push_back(key_arg); } m_commClient.send(op); log(INFO, "Sent Create op to peer"); // Set it as validated and add to the list of teleports s->setRequested(); m_teleports[iid] = s; log(INFO, "Added new teleport state"); return 0; }
void Interactive::exec(const std::string & cmd, const std::string & arg) { bool reply_expected = true; reply_flag = false; error_flag = false; boost::shared_ptr<ObjectContext> command_context = m_currentContext.lock(); if (!command_context) { std::cout << "ERROR: Context free" << std::endl << std::flush; return; } if (cmd == "stat") { Get g; send(g); } else if (cmd == "install") { size_t space = arg.find(' '); if (space == std::string::npos || space >= (arg.size() - 1)) { std::cout << "usage: install <type id> <parent id>" << std::endl << std::flush; } else { Create c; c->setFrom(m_accountId); Anonymous ent; ent->setId(std::string(arg, 0, space)); ent->setObjtype("class"); ent->setParents(std::list<std::string>(1, std::string(arg, space + 1))); c->setArgs1(ent); send(c); } reply_expected = false; } else if (cmd == "look") { Look l; if (!arg.empty()) { Anonymous cmap; cmap->setId(arg); l->setArgs1(cmap); } l->setSerialno(newSerialNo()); command_context->setFromContext(l); send(l); reply_expected = false; } else if (cmd == "logout") { Logout l; l->setFrom(m_accountId); if (!arg.empty()) { Anonymous lmap; lmap->setId(arg); l->setArgs1(lmap); reply_expected = false; } send(l); } else if (cmd == "say") { Talk t; Anonymous ent; ent->setAttr("say", arg); t->setArgs1(ent); t->setFrom(m_accountId); send(t); } else if (cmd == "help" || cmd == "?") { reply_expected = false; help(); } else if (cmd == "query") { Get g; if (!arg.empty()) { Anonymous cmap; if (::isdigit(arg[0])) { cmap->setObjtype("obj"); } else { cmap->setObjtype("meta"); } cmap->setId(arg); g->setArgs1(cmap); } g->setFrom(m_accountId); send(g); } else if (cmd == "reload") { if (arg.empty()) { reply_expected = false; std::cout << "reload: Argument required" << std::endl << std::flush; } else { Set s; Anonymous tmap; tmap->setObjtype("class"); tmap->setId(arg); s->setArgs1(tmap); s->setFrom(m_accountId); send(s); } } else if (cmd == "get") { Get g; if (!arg.empty()) { Anonymous cmap; if (::isdigit(arg[0])) { cmap->setObjtype("obj"); } else { cmap->setObjtype("meta"); } cmap->setId(arg); g->setArgs1(cmap); } g->setFrom(m_accountId); send(g); } else if (cmd == "monitor") { ClientTask * task = new OperationMonitor; if (runTask(task, arg) == 0) { Monitor m; m->setArgs1(Anonymous()); m->setFrom(m_accountId); send(m); } reply_expected = false; } else if (cmd == "unmonitor") { OperationMonitor * om = dynamic_cast<OperationMonitor *>(m_currentTask); if (om != 0) { Monitor m; m->setFrom(m_accountId); send(m); reply_expected = false; SystemTime now; now.update(); time_t monitor_time = now.seconds() - om->startTime(); std::cout << om->count() << " operations monitored in " << monitor_time << " seconds = " << om->count() / monitor_time << " operations per second" << std::endl << std::flush; endTask(); } } else if (cmd == "connect") { std::vector<std::string> args; tokenize(arg, args); if (args.size() != 2) { std::cout << "usage: connect <hostname> <port>" << std::endl << std::flush; reply_expected = false; } else { Anonymous cmap; cmap->setAttr("hostname", args[0]); cmap->setAttr("port", strtol(args[1].c_str(), 0, 10)); Connect m; m->setArgs1(cmap); // No serialno yet // FIXME add serialno once Juncture context can handle this command_context->setFromContext(m); send(m); } } else if (cmd == "add_agent") { std::string agent_type("creator"); if (!arg.empty()) { agent_type = arg; } Create c; Anonymous cmap; cmap->setParents(std::list<std::string>(1, agent_type)); cmap->setName("cycmd agent"); cmap->setObjtype("obj"); c->setArgs1(cmap); c->setSerialno(newSerialNo()); command_context->setFromContext(c); send(c); } else if (cmd == "delete") { if (arg.empty()) { std::cout << "Please specify the entity to delete" << std::endl << std::flush; reply_expected = false; } else { Delete del; Anonymous del_arg; del_arg->setId(arg); del->setArgs1(del_arg); command_context->setFromContext(del); send(del); reply_expected = false; } } else if (cmd == "find_by_name") { if (arg.empty()) { std::cout << "Please specify the name to search for" << std::endl << std::flush; reply_expected = false; } else { Look l; Anonymous lmap; lmap->setName(arg); l->setArgs1(lmap); l->setSerialno(newSerialNo()); command_context->setFromContext(l); send(l); reply_expected = false; } } else if (cmd == "find_by_type") { if (arg.empty()) { std::cout << "Please specify the type to search for" << std::endl << std::flush; reply_expected = false; } else { Look l; Anonymous lmap; lmap->setParents(std::list<std::string>(1, arg)); l->setArgs1(lmap); l->setSerialno(newSerialNo()); command_context->setFromContext(l); send(l); reply_expected = false; } } else if (cmd == "flush") { if (arg.empty()) { // FIXME usage std::cout << "Please specify the type to flush" << std::endl << std::flush; reply_expected = false; } else { ClientTask * task = new Flusher(command_context); runTask(task, arg); reply_expected = false; } } else if (cmd == "cancel") { if (endTask() != 0) { std::cout << "No task currently running" << std::endl << std::flush; } } else if (cmd == "dump") { if (command_context->repr() != "avatar") { std::cout << "You must have an agent in the world in order to dump the world." << std::endl << std::flush; } else { //Extract the avatar id by "misusing" the setFromContext method Operation op; command_context->setFromContext(op); ClientTask * task = new EntityExporter(m_accountId, op->getFrom()); runTask(task, "world.xml"); reply_expected = false; } } else if (cmd == "restore") { if (command_context->repr() != "avatar") { std::cout << "You must have an agent in the world in order to dump the world." << std::endl << std::flush; } else { //Extract the avatar id by "misusing" the setFromContext method Operation op; command_context->setFromContext(op); ClientTask * task = new EntityImporter(m_accountId, op->getFrom()); runTask(task, "world.xml"); reply_expected = false; } } else if (cmd == "create") { std::vector<std::string> args; tokenize(arg, args); if (args.size() < 1) { std::cout << "usage: create <type> <params> ... " << std::endl << std::flush; } else { Anonymous cmap; cmap->setParents(std::list<std::string>(1, args[0])); cmap->setObjtype("obj"); Create c; c->setArgs1(cmap); c->setSerialno(newSerialNo()); command_context->setFromContext(c); send(c); } reply_expected = false; } else if (cmd == "login") { std::vector<std::string> args; tokenize(arg, args); if (args.size() != 2) { std::cout << "usage: login <username> <password>" << std::endl << std::flush; reply_expected = false; } else { Anonymous cmap; cmap->setAttr("username", args[0]); cmap->setAttr("password", args[1]); Login m; m->setArgs1(cmap); m->setSerialno(newSerialNo()); command_context->setFromContext(m); send(m); } } else { reply_expected = false; std::cout << cmd << ": Command not known" << std::endl << std::flush; } if (!reply_expected) { updatePrompt(); return; } // Wait for reply time_t wait_start_time = time(NULL); while (!reply_flag) { if (time(NULL) - wait_start_time > 5) { std::cout << cmd << ": No reply from server" << std::endl << std::flush; return; } if (select(false) != 0) { return; } } }
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)) ;);
int main() { database_flag = false; (void)new Domain; WorldRouter world; Entity & e = world.m_gameWorld; ServerRouting server(world, "noruleset", "unittesting", "1", 1, "2", 2); CommServer commServer(server); TestCommClient * tc = new TestCommClient(commServer); Connection * c = new Connection(*tc, server, "addr", "3", 3); TestAccount * ac = new TestAccount(c, "user", "password", "4", 4); Entity * chr; { chr = new Entity("5", 5); chr->m_location.m_loc = &e; chr->m_location.m_loc->makeContainer(); assert(chr->m_location.m_loc->m_contains != 0); chr->m_location.m_loc->m_contains->insert(chr); ac->addCharacter(chr); chr->destroy(); } { chr = new Character("6", 6); chr->m_location.m_loc = &e; chr->m_location.m_loc->makeContainer(); assert(chr->m_location.m_loc->m_contains != 0); chr->m_location.m_loc->m_contains->insert(chr); ac->addCharacter(chr); chr->destroy(); } { chr = new Character("7", 7); chr->m_location.m_loc = &e; chr->m_location.m_loc->makeContainer(); assert(chr->m_location.m_loc->m_contains != 0); chr->m_location.m_loc->m_contains->insert(chr); ac->addCharacter(chr); } { Anonymous new_char; Entity * chr = ac->testAddNewCharacter("thing", new_char, RootEntity()); assert(chr != 0); } ac->getType(); { MapType emap; ac->addToMessage(emap); } { RootEntity ent; ac->addToEntity(ent); } { Create op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setParents(std::list<std::string>()); ac->operation(op, res); op_arg->setParents(std::list<std::string>(1, "game_entity")); ac->operation(op, res); op_arg->setName("Bob"); ac->operation(op, res); } { Get op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setParents(std::list<std::string>()); ac->operation(op, res); } { Imaginary op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); op->setSerialno(1); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setLoc("2"); ac->operation(op, res); } { Look op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setId("1"); ac->operation(op, res); op_arg->setId(chr->getId()); ac->operation(op, res); } { Set op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setId("1"); ac->operation(op, res); op_arg->setId(chr->getId()); ac->operation(op, res); op_arg->setAttr("guise", "foo"); ac->operation(op, res); op_arg->setAttr("height", 3.0); ac->operation(op, res); BBox newBox(WFMath::Point<3>(-0.5, -0.5, 0.0), WFMath::Point<3>(-0.5, -0.5, 2.0)); chr->m_location.setBBox(newBox); op_arg->setAttr("height", 3.0); ac->operation(op, res); op_arg->setAttr("tasks", ListType()); ac->operation(op, res); } { Talk op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setParents(std::list<std::string>()); ac->operation(op, res); op->setSerialno(1); ac->operation(op, res); op_arg->setLoc("1"); ac->operation(op, res); } { Logout op; OpVector res; ac->operation(op, res); op->setSerialno(1); ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setParents(std::list<std::string>()); ac->operation(op, res); } { // Move has no meaning Move op; OpVector res; ac->operation(op, res); op->setArgs1(Root()); ac->operation(op, res); Anonymous op_arg; op->setArgs1(op_arg); ac->operation(op, res); op_arg->setParents(std::list<std::string>()); ac->operation(op, res); } { Entity e("7", 7); int ret = ac->connectCharacter(&e); assert(ret == -1); } { Character e("8", 8); int ret = ac->connectCharacter(&e); assert(ret == 0); } delete ac; return 0; }