예제 #1
0
void ConnectedAdapter::setAttributes(Eris::Entity* entity, Atlas::Message::MapType& elements)
{
	try {
		Atlas::Objects::Entity::Anonymous what;
		what->setId(entity->getId());
		//We'll use this flag to make sure that nothing gets sent in the case that the only thing changed was immutable attributes (like "pos").
		bool areAttributesToSend = false;
		for (Atlas::Message::MapType::iterator I = elements.begin(); I != elements.end(); ++I) {
			//The "pos" attribute is immutable and cannot be altered by a "set" op. Instead we must use a "move" op.
			if (I->first == "pos") {
				place(entity, entity->getLocation(), WFMath::Point<3>(I->second));
			} else {
				what->setAttr(I->first, I->second);
				areAttributesToSend = true;
			}
		}

		if (areAttributesToSend) {
			Atlas::Objects::Operation::Set setOp;
			setOp->setFrom(mAvatar.getEntity()->getId());
			//setOp->setTo(entity->getId());
			setOp->setArgs1(what);

			S_LOG_INFO("Setting attributes of entity with id " << entity->getId() << ", named " << entity->getName());
			mConnection.send(setOp);
		}
	} catch (const std::exception& ex) {
		S_LOG_WARNING("Got error on setting attributes on entity." << ex);
	}
}
예제 #2
0
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;
}
예제 #3
0
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);
    }
}
예제 #4
0
void ConnectedAdapter::setTypeInfo(const Atlas::Objects::Root& typeInfo)
{
	try {
		Atlas::Objects::Operation::Set setOp;
		setOp->setFrom(mAccount.getId());
		setOp->setArgs1(typeInfo);

		S_LOG_INFO("Sending updated type info data.");
		mConnection.send(setOp);
	} catch (const std::exception& ex) {
		S_LOG_WARNING("Got error on sending updated type info data." << ex);
	}
}
예제 #5
0
void Admintest::test_SetOperation_no_objtype()
{
    Atlas::Objects::Operation::Set op;
    OpVector res;

    Anonymous arg;
    op->setArgs1(arg);

    m_account->SetOperation(op, res);

    ASSERT_EQUAL(res.size(), 1u);
    ASSERT_EQUAL(res.front()->getClassNo(),
                 Atlas::Objects::Operation::ERROR_NO);
}
예제 #6
0
void Admintest::test_SetOperation_unknown()
{
    Atlas::Objects::Operation::Set op;
    OpVector res;

    Anonymous arg;
    arg->setObjtype("unimportant_unknown_string");
    arg->setId("root");
    op->setArgs1(arg);

    m_account->SetOperation(op, res);

    ASSERT_EQUAL(res.size(), 1u);
    ASSERT_EQUAL(res.front()->getClassNo(),
                 Atlas::Objects::Operation::ERROR_NO);
}
예제 #7
0
void EntityImporterBase::updateRule(const Root& existingDefinition, const Root& newDefinition, OpVector & res)
{

    m_state = RULE_UPDATING;
    Root updatedDefinition = newDefinition.copy();

    //If the existing definition had any children that aren't part of the import, we should preserve those
    std::list<std::string> existingChildren, newChildren;
    extractChildren(existingDefinition, existingChildren);
    extractChildren(newDefinition, newChildren);

    for (auto& child : newChildren) {
        existingChildren.remove(child);
    }

    for (auto& child : existingChildren) {
        if (mPersistedRules.find(child) == mPersistedRules.end()) {
            newChildren.push_back(child);
        }
    }

    if (!newChildren.empty() && !existingChildren.empty()) {
        Atlas::Message::ListType childrenElement;
        for (auto& child : newChildren) {
            childrenElement.emplace_back(child);
        }
        updatedDefinition->setAttr("children", childrenElement);
    }

    if (updatedDefinition->asMessage() != existingDefinition->asMessage()) {
        S_LOG_INFO("Updating server rule '"<< updatedDefinition->getId() << "'.");
        Atlas::Objects::Operation::Set setOp;
        setOp->setFrom(mAccountId);
        setOp->setArgs1(updatedDefinition);

        setOp->setSerialno(newSerialNumber());
        res.push_back(setOp);
    } else {
        mStats.rulesProcessedCount++;
        EventProgress.emit();
        S_LOG_VERBOSE("Not updating server rule '"<< updatedDefinition->getId() << "' as nothing is changed.");
        walkRules(res);
    }
}
예제 #8
0
void Admintest::test_SetOperation_rule_unknown()
{
    Ruleset_modifyRule_called = false;

    Atlas::Objects::Operation::Set op;
    OpVector res;

    Anonymous arg;
    arg->setObjtype("class");
    arg->setId("unimportant_unmatched_string");
    op->setArgs1(arg);

    m_account->SetOperation(op, res);

    ASSERT_EQUAL(res.size(), 1u);
    ASSERT_EQUAL(res.front()->getClassNo(),
                 Atlas::Objects::Operation::ERROR_NO);
    ASSERT_TRUE(!Ruleset_modifyRule_called);
}
예제 #9
0
void Admintest::test_SetOperation_rule_fail()
{
    Ruleset_modifyRule_called = false;
    Ruleset_modifyRule_retval = -1;

    Atlas::Objects::Operation::Set op;
    OpVector res;

    Anonymous arg;
    arg->setObjtype("class");
    arg->setId("root");
    op->setArgs1(arg);

    m_account->SetOperation(op, res);

    ASSERT_EQUAL(res.size(), 1u);
    ASSERT_EQUAL(res.front()->getClassNo(),
                 Atlas::Objects::Operation::ERROR_NO);
    ASSERT_TRUE(Ruleset_modifyRule_called);
}
예제 #10
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);
}
예제 #11
0
void EntityImporterBase::sendMinds()
{
    if (!mResolvedMindMapping.empty()) {
        S_LOG_INFO("Sending minds.");
        for (auto mind : mResolvedMindMapping) {
            Atlas::Message::MapType message;
            mind.second->addToMessage(message);

            Atlas::Message::Element thoughtsElem = message["thoughts"];
            Atlas::Message::ListType thoughtArgs;

            if (thoughtsElem.isList()) {
                Atlas::Message::ListType thoughtList = thoughtsElem.List();

                for (auto& thought : thoughtList) {
                    //If the thought is a list of things the entity owns, we should adjust it with the new entity ids.
                    if (thought.isMap()) {
                        auto& thoughtMap = thought.Map();
                        if (thoughtMap.count("things") > 0) {
                            auto& thingsElement = thoughtMap.find("things")->second;
                            if (thingsElement.isMap()) {
                                for (auto& thingI : thingsElement.asMap()) {
                                    if (thingI.second.isList()) {
                                        Atlas::Message::ListType newList;
                                        for (auto& thingId : thingI.second.asList()) {
                                            if (thingId.isString()) {
                                                const auto& entityIdLookupI = mEntityIdMap.find(thingId.asString());
                                                //Check if the owned entity has been created with a new id. If so, replace the data.
                                                if (entityIdLookupI != mEntityIdMap.end()) {
                                                    newList.emplace_back(entityIdLookupI->second);
                                                } else {
                                                    newList.push_back(thingId);
                                                }
                                            } else {
                                                newList.push_back(thingId);
                                            }
                                        }
                                        thingI.second = newList;
                                    }
                                }
                            }
                        }

                        if (thoughtMap.count("pending_things") > 0) {
                            //things that the entity owns, but haven't yet discovered are expressed as a list of entity ids
                            auto& pendingThingsElement = thoughtMap.find("pending_things")->second;
                            if (pendingThingsElement.isList()) {
                                Atlas::Message::ListType newList;
                                for (auto& thingId : pendingThingsElement.asList()) {
                                    if (thingId.isString()) {
                                        const auto& entityIdLookupI = mEntityIdMap.find(thingId.asString());
                                        //Check if the owned entity has been created with a new id. If so, replace the data.
                                        if (entityIdLookupI != mEntityIdMap.end()) {
                                            newList.emplace_back(entityIdLookupI->second);
                                        } else {
                                            newList.push_back(thingId);
                                        }
                                    } else {
                                        newList.push_back(thingId);
                                    }
                                }
                                pendingThingsElement = newList;
                            }
                        }

                        if (thoughtMap.count("object") > 0) {
                            auto& objectElement = thoughtMap.find("object")->second;
                            if (objectElement.isString()) {
                                std::string& objectString = objectElement.String();
                                //Other entities are referred to using the syntax "'$eid:...'".
                                //For example, the entity with id 2 would be "'$eid:2'".
                                auto pos = objectString.find("$eid:");
                                if (pos != std::string::npos) {
                                    auto quotePos = objectString.find('\'', pos);
                                    if (quotePos != std::string::npos) {
                                        auto id = objectString.substr(pos + 5, quotePos - pos - 5);
                                        auto I = mEntityIdMap.find(id);
                                        if (I != mEntityIdMap.end()) {
                                            objectString.replace(pos + 5, quotePos - 7, I->second);
                                        }
                                    }
                                }
                            }
                        }

                    }
                    thoughtArgs.push_back(thought);
                }
            }

            Atlas::Objects::Operation::RootOperation thinkOp;
            thinkOp->setParent("think");
            thinkOp->setTo(mind.first);
            //By setting it TO an entity and FROM our avatar we'll make the server deliver it as
            //if it came from the entity itself (the server rewrites the FROM to be of the entity).
            thinkOp->setFrom(mAvatarId);
            thinkOp->setSerialno(newSerialNumber());

            Atlas::Objects::Operation::Set setOp;
            setOp->setArgsAsList(thoughtArgs);
            thinkOp->setArgs1(setOp);


            mStats.mindsProcessedCount++;
            S_LOG_VERBOSE("Restoring mind of " << mind.first);
            mThoughtOpsInTransit++;

            sigc::slot<void, const Operation&> slot = sigc::mem_fun(*this, &EntityImporterBase::operationThinkResult);
            sendAndAwaitResponse(thinkOp, slot);
            EventProgress.emit();
        }
        mResolvedMindMapping.clear();
    } else {
        complete();
    }
}
예제 #12
0
int main()
{
    TestWorld world;

    {
        Entity e("2", 2);

        ExternalMind em(e);
    }

    {
        Entity e("2", 2);

        TestExternalMind em(e);

        em.test_deleteEntity("3");
    }

    // Purge with empty contains
    {
        Entity e("2", 2);
        e.m_contains = new LocatedEntitySet;

        TestExternalMind em(e);

        em.test_purgeEntity(e);
    }

    // Purge with populated contains
    {
        Entity e("2", 2);
        e.m_contains = new LocatedEntitySet;
        e.m_contains->insert(new Entity("3", 3));

        TestExternalMind em(e);

        em.test_purgeEntity(e);
    }

    // Connect to nothing
    {
        Entity e("2", 2);

        ExternalMind em(e);

        em.linkUp(0);
    }

    // Connect to something
    {
        Entity e("2", 2);

        ExternalMind em(e);

        em.linkUp(new Connection(*(CommSocket*)0,
                                 *(ServerRouting*)0,
                                 "addr", "4", 4));
    }

    // Connect to something, then disconnect
    {
        Entity e("2", 2);

        ExternalMind em(e);

        em.linkUp(new Connection(*(CommSocket*)0,
                                 *(ServerRouting*)0,
                                 "addr", "4", 4));
        em.linkUp(0);
    }

    // Connect to something, then check connection ID
    {
        Entity e("2", 2);

        ExternalMind em(e);

        em.linkUp(new Connection(*(CommSocket*)0,
                                 *(ServerRouting*)0,
                                 "addr", "4", 4));
        const std::string & id = em.connectionId();
        assert(id == "4");
    }

    // Send a random operation
    {
        Entity e("2", 2);

        TestExternalMind em(e);
        em.test_setLossTime(BaseWorld::instance().getTime());

        stub_baseworld_receieved_op = -1;
        OpVector res;
        em.operation(Atlas::Objects::Operation::RootOperation(), res);
        assert(stub_baseworld_receieved_op == -1);
    }

    // Send a Delete operation
    {
        Entity e("2", 2);

        TestExternalMind em(e);
        em.test_setLossTime(BaseWorld::instance().getTime());

        stub_baseworld_receieved_op = -1;
        OpVector res;
        em.operation(Atlas::Objects::Operation::Delete(), res);
        assert(stub_baseworld_receieved_op == -1);
    }

    // Send a Delete operation to an ephemeral entity
    {
        Entity e("2", 2);
        e.setFlags(entity_ephem);

        TestExternalMind em(e);
        em.test_setLossTime(BaseWorld::instance().getTime());

        stub_baseworld_receieved_op = -1;
        OpVector res;
        em.operation(Atlas::Objects::Operation::Delete(), res);
        assert(stub_baseworld_receieved_op == -1);
    }

    // Send a non Delete operation to an ephemeral entity
    {
        Entity e("2", 2);
        e.setFlags(entity_ephem);

        TestExternalMind em(e);
        em.test_setLossTime(BaseWorld::instance().getTime());

        stub_baseworld_receieved_op = -1;
        OpVector res;
        em.operation(Atlas::Objects::Operation::RootOperation(), res);
        assert(stub_baseworld_receieved_op == Atlas::Objects::Operation::DELETE_NO);
    }

    // Send a random operation to something that has been recorded as
    // disconnected for a while
    {
        Entity e("2", 2);

        // FIXME hard code the expiry time here.
        TestExternalMind em(e);
        em.test_setLossTime(BaseWorld::instance().getTime() - 60*60 - 5);

        stub_baseworld_receieved_op = -1;
        OpVector res;
        em.operation(Atlas::Objects::Operation::RootOperation(), res);
        assert(stub_baseworld_receieved_op == Atlas::Objects::Operation::DELETE_NO);
    }

    // Send a random operation to a connected mind
    {
        Entity e("2", 2);

        TestExternalMind em(e);

        em.linkUp(new Connection(*(CommSocket*)0,
                                 *(ServerRouting*)0,
                                 "addr", "4", 4));

        stub_link_send_op = -1;
        stub_link_send_count = 0;
        OpVector res;
        em.operation(Atlas::Objects::Operation::RootOperation(), res);
        assert(stub_link_send_op == Atlas::Objects::Operation::ROOT_OPERATION_NO);
        assert(stub_link_send_count == 1);
    }

    // Send a Sight operation to a connected mind
    {
        Entity e("2", 2);

        TestExternalMind em(e);

        em.linkUp(new Connection(*(CommSocket*)0,
                                 *(ServerRouting*)0,
                                 "addr", "4", 4));

        stub_link_send_op = -1;
        stub_link_send_count = 0;
        OpVector res;
        em.operation(Atlas::Objects::Operation::Sight(), res);
        assert(stub_link_send_op == Atlas::Objects::Operation::SIGHT_NO);
        assert(stub_link_send_count == 1);
    }

    // Send a Sight(Set) of hungry operation to a connected mind
    {
        Entity e("2", 2);

        TestExternalMind em(e);

        em.linkUp(new Connection(*(CommSocket*)0,
                                 *(ServerRouting*)0,
                                 "addr", "4", 4));

        stub_link_send_op = -1;
        stub_link_send_count = 0;

        // A sight(set) of a starving entity
        Atlas::Objects::Root arg;
        arg->setAttr("status", 0.05);
        arg->setId(e.getId());
        Atlas::Objects::Operation::Set set;
        set->setArgs1(arg);
        Atlas::Objects::Operation::Sight op;
        op->setArgs1(set);

        // It should trigger an extra Sight(Imaginary)
        OpVector res;
        em.operation(op, res);
        assert(stub_link_send_op == Atlas::Objects::Operation::SIGHT_NO);
        assert(stub_link_send_count > 1);
    }

    // Send a Sight(Set) of starving operation to a connected mind
    {
        Entity e("2", 2);

        TestExternalMind em(e);

        em.linkUp(new Connection(*(CommSocket*)0,
                                 *(ServerRouting*)0,
                                 "addr", "4", 4));

        stub_link_send_op = -1;
        stub_link_send_count = 0;

        // A sight(set) of a starving entity
        Atlas::Objects::Root arg;
        arg->setAttr("status", 0.005);
        arg->setId(e.getId());
        Atlas::Objects::Operation::Set set;
        set->setArgs1(arg);
        Atlas::Objects::Operation::Sight op;
        op->setArgs1(set);

        // It should trigger an extra Sight(Imaginary)
        OpVector res;
        em.operation(op, res);
        assert(stub_link_send_op == Atlas::Objects::Operation::SIGHT_NO);
        assert(stub_link_send_count > 1);
    }

    return 0;
}