Пример #1
0
unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) {
    currentPosition += packNodeId(currentPosition, nodeToAdd->getNodeID());

    AvatarData *nodeData = (AvatarData *)nodeToAdd->getLinkedData();
    currentPosition += nodeData->getBroadcastData(currentPosition);
    
    return currentPosition;
}
Пример #2
0
unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) {
    QByteArray rfcUUID = nodeToAdd->getUUID().toRfc4122();
    memcpy(currentPosition, rfcUUID.constData(), rfcUUID.size());
    currentPosition += rfcUUID.size();
    
    AvatarData *nodeData = (AvatarData *)nodeToAdd->getLinkedData();
    currentPosition += nodeData->getBroadcastData(currentPosition);
    
    return currentPosition;
}
Пример #3
0
    qint64 packVersionedTraitInstance(TraitType traitType, TraitInstanceID traitInstanceID,
                                      ExtendedIODevice& destination, TraitVersion traitVersion,
                                      AvatarData& avatar) {
        // Call packer function
        auto traitBinaryData = avatar.packTraitInstance(traitType, traitInstanceID);
        auto traitBinaryDataSize = traitBinaryData.size();


        // Verify packed data
        if (traitBinaryDataSize > AvatarTraits::MAXIMUM_TRAIT_SIZE) {
            qWarning() << "Refusing to pack instanced trait" << traitType << "of size" << traitBinaryDataSize
                        << "bytes since it exceeds the maximum size " << AvatarTraits::MAXIMUM_TRAIT_SIZE << "bytes";
            return 0;
        }

        // Write packed data to stream
        qint64 bytesWritten = 0;
        bytesWritten += destination.writePrimitive((TraitType)traitType);
        bytesWritten += destination.writePrimitive((TraitVersion)traitVersion);
        bytesWritten += destination.write(traitInstanceID.toRfc4122());

        if (!traitBinaryData.isNull()) {
            bytesWritten += destination.writePrimitive((TraitWireSize)traitBinaryDataSize);
            bytesWritten += destination.write(traitBinaryData);
        } else {
            bytesWritten += destination.writePrimitive(AvatarTraits::DELETED_TRAIT_SIZE);
        }

        return bytesWritten;
    }
Пример #4
0
void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
    int bytesRead = numBytesForPacketHeader(datagram);
    
    // enumerate over all of the avatars in this packet
    // only add them if mixerWeakPointer points to something (meaning that mixer is still around)
    while (bytesRead < datagram.size() && mixerWeakPointer.data()) {
        QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID));
        bytesRead += NUM_BYTES_RFC4122_UUID;
        
        if (sessionUUID != _lastOwnerSessionUUID) {
            AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
            
            // have the matching (or new) avatar parse the data from the packet
            bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
        } else {
            // create a dummy AvatarData class to throw this data on the ground
            AvatarData dummyData;
            bytesRead += dummyData.parseDataAtOffset(datagram, bytesRead);
        }
    }
}
Пример #5
0
    qint64 packTrait(TraitType traitType, ExtendedIODevice& destination, const AvatarData& avatar) {
        // Call packer function
        auto traitBinaryData = avatar.packTrait(traitType);
        auto traitBinaryDataSize = traitBinaryData.size();

        // Verify packed data
        if (traitBinaryDataSize > MAXIMUM_TRAIT_SIZE) {
            qWarning() << "Refusing to pack simple trait" << traitType << "of size" << traitBinaryDataSize
                        << "bytes since it exceeds the maximum size" << MAXIMUM_TRAIT_SIZE << "bytes";
            return 0;
        }

        // Write packed data to stream
        qint64 bytesWritten = 0;
        bytesWritten += destination.writePrimitive((TraitType)traitType);
        bytesWritten += destination.writePrimitive((TraitWireSize)traitBinaryDataSize);
        bytesWritten += destination.write(traitBinaryData);
        return bytesWritten;
    }
Пример #6
0
void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
    // particles that are in hand, don't collide with avatars
    if (!_avatars || particle->getInHand()) {
        return;
    }

    glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
    float radius = particle->getRadius() * (float)(TREE_SCALE);
    const float ELASTICITY = 0.9f;
    const float DAMPING = 0.1f;
    const float COLLISION_FREQUENCY = 0.5f;
    glm::vec3 penetration;

    _collisions.clear();
    foreach (const AvatarSharedPointer& avatarPointer, _avatars->getAvatarHash()) {
        AvatarData* avatar = avatarPointer.data();

        // use a very generous bounding radius since the arms can stretch
        float totalRadius = 2.f * avatar->getBoundingRadius() + radius;
        glm::vec3 relativePosition = center - avatar->getPosition();
        if (glm::dot(relativePosition, relativePosition) > (totalRadius * totalRadius)) {
            continue;
        }

        if (avatar->findParticleCollisions(center, radius, _collisions)) {
            int numCollisions = _collisions.size();
            for (int i = 0; i < numCollisions; ++i) {
                CollisionInfo* collision = _collisions.getCollision(i);
                collision->_damping = DAMPING;
                collision->_elasticity = ELASTICITY;
    
                collision->_addedVelocity /= (float)(TREE_SCALE);
                glm::vec3 relativeVelocity = collision->_addedVelocity - particle->getVelocity();
    
                if (glm::dot(relativeVelocity, collision->_penetration) <= 0.f) {
                    // only collide when particle and collision point are moving toward each other
                    // (doing this prevents some "collision snagging" when particle penetrates the object)
    
                    // HACK BEGIN: to allow paddle hands to "hold" particles we attenuate soft collisions against them.
                    if (collision->_type == COLLISION_TYPE_PADDLE_HAND) {
                        // NOTE: the physics are wrong (particles cannot roll) but it IS possible to catch a slow moving particle.
                        // TODO: make this less hacky when we have more per-collision details
                        float elasticity = ELASTICITY;
                        float attenuationFactor = glm::length(collision->_addedVelocity) / HALTING_SPEED;
                        float damping = DAMPING;
                        if (attenuationFactor < 1.f) {
                            collision->_addedVelocity *= attenuationFactor;
                            elasticity *= attenuationFactor;
                            // NOTE: the math below keeps the damping piecewise continuous,
                            // while ramping it up to 1 when attenuationFactor = 0
                            damping = DAMPING + (1.f - attenuationFactor) * (1.f - DAMPING);
                        }
                        collision->_damping = damping;
                    }
                    // HACK END
    
                    updateCollisionSound(particle, collision->_penetration, COLLISION_FREQUENCY);
                    collision->_penetration /= (float)(TREE_SCALE);
                    particle->applyHardCollision(*collision);
                    queueParticlePropertiesUpdate(particle);
                }
            }
        }
    }
}
Пример #7
0
void Agent::run() {
    ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent);
    
    NodeList* nodeList = NodeList::getInstance();
    nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet()
                                                 << NodeType::AudioMixer
                                                 << NodeType::AvatarMixer
                                                 << NodeType::VoxelServer
                                                 << NodeType::ParticleServer
                                                 << NodeType::ModelServer
                                                );
    
    // figure out the URL for the script for this agent assignment
    QUrl scriptURL;
    if (_payload.isEmpty())  {
        scriptURL = QUrl(QString("http://%1:%2/assignment/%3")
            .arg(NodeList::getInstance()->getDomainHandler().getIP().toString())
            .arg(DOMAIN_SERVER_HTTP_PORT)
            .arg(uuidStringWithoutCurlyBraces(_uuid)));
    } else {
        scriptURL = QUrl(_payload);
    }
   
    QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
    QNetworkReply *reply = networkManager->get(QNetworkRequest(scriptURL));
    QNetworkDiskCache* cache = new QNetworkDiskCache(networkManager);
    QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
    networkManager->setCache(cache);
    
    qDebug() << "Downloading script at" << scriptURL.toString();
    
    QEventLoop loop;
    QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
    
    loop.exec();
    
    // let the AvatarData and ResourceCache classes use our QNetworkAccessManager
    AvatarData::setNetworkAccessManager(networkManager);
    ResourceCache::setNetworkAccessManager(networkManager);
    
    QString scriptContents(reply->readAll());
    
    qDebug() << "Downloaded script:" << scriptContents;
    
    // setup an Avatar for the script to use
    AvatarData scriptedAvatar;
    
    // call model URL setters with empty URLs so our avatar, if user, will have the default models
    scriptedAvatar.setFaceModelURL(QUrl());
    scriptedAvatar.setSkeletonModelURL(QUrl());
    
    // give this AvatarData object to the script engine
    _scriptEngine.setAvatarData(&scriptedAvatar, "Avatar");
    _scriptEngine.setAvatarHashMap(&_avatarHashMap, "AvatarList");
    
    // register ourselves to the script engine
    _scriptEngine.registerGlobalObject("Agent", this);

    _scriptEngine.init(); // must be done before we set up the viewers

    _scriptEngine.registerGlobalObject("VoxelViewer", &_voxelViewer);
    // connect the VoxelViewer and the VoxelScriptingInterface to each other
    JurisdictionListener* voxelJL = _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener();
    _voxelViewer.setJurisdictionListener(voxelJL);
    _voxelViewer.init();
    _scriptEngine.getVoxelsScriptingInterface()->setVoxelTree(_voxelViewer.getTree());
    
    _scriptEngine.registerGlobalObject("ParticleViewer", &_particleViewer);
    JurisdictionListener* particleJL = _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener();
    _particleViewer.setJurisdictionListener(particleJL);
    _particleViewer.init();
    _scriptEngine.getParticlesScriptingInterface()->setParticleTree(_particleViewer.getTree());

    _scriptEngine.setScriptContents(scriptContents);
    _scriptEngine.run();
    setFinished(true);
}
Пример #8
0
// -----------------------------------------------------------------
// Name : autoStartGame
// -----------------------------------------------------------------
void DebugManager::autoStartGame()
{
    // Build client data
    int nbClients = 1;
    ClientData * clients = new ClientData[nbClients];
    int iClient = 0;
    clients[iClient].bLocal = true;

    // Re-init map data
    MapReader * pMapReader = new MapReader(m_pLocalClient);
    pMapReader->init("standard.lua");
    ObjectList * pMapParameters = new ObjectList(true);
    pMapReader->getMapParameters(pMapParameters, LABEL_MAX_CHARS);

    int * pCustomParams = NULL;
    if (pMapParameters->size > 0)
        pCustomParams = new int[pMapParameters->size];

    // Map custom parameters
    int i = 0;
    MapReader::MapParameters * pParam = (MapReader::MapParameters*) pMapParameters->getFirst(0);
    while (pParam != NULL)
    {
        pCustomParams[i++] = pParam->defaultValueIndex;
        pParam = (MapReader::MapParameters*) pMapParameters->getNext(0);
    }

    // Init map generator (we will not delete it here, as the pointer now belong to Server object)
    pMapReader->setMapParameters(pCustomParams, pMapParameters->size, 2);
    delete[] pCustomParams;
    MapReader::deleteMapParameters(pMapParameters);
    delete pMapParameters;

    // Init server
    Server * pServer = m_pLocalClient->initServer("", 1, clients, pMapReader, -1, -1);
    delete[] clients;
    if (pServer == NULL)
    {
        notifyErrorMessage("Error: server could not be initialized.");
        return;
    }

    // Build players data
    ObjectList * pServerPlayers = pServer->getSolver()->getPlayersList();
    // Create neutral player
    char sName[NAME_MAX_CHARS];
    i18n->getText("NEUTRA", sName, NAME_MAX_CHARS);
    Player * pPlayer = new Player(0, 0, pServer->getSolver()->getGlobalSpellsPtr());
    wsafecpy(pPlayer->m_sProfileName, NAME_MAX_CHARS, sName);
    pPlayer->m_Color = rgb(0.5, 0.5, 0.5);
    wsafecpy(pPlayer->m_sBanner, 64, "blason1");
    pServer->getSolver()->setNeutralPlayer(pPlayer);
    // Human players
    int playerId = 1;
    for (int fdfdf = 0; fdfdf < 2; fdfdf++)
    {
        // Create player object
        pPlayer = new Player(playerId, 0, pServer->getSolver()->getGlobalSpellsPtr());
        snprintf(pPlayer->m_sProfileName, NAME_MAX_CHARS, "test%d", playerId);
        Profile * pProfile = m_pLocalClient->getDataFactory()->findProfile(pPlayer->m_sProfileName);
        AvatarData * pAvatar = (AvatarData*) pProfile->getAvatarsList()->getFirst(0);
        pPlayer->m_Color = rgb(1, 1, 1);
        pAvatar->getBanner(pPlayer->m_sBanner, 64);
        pServerPlayers->addLast(pPlayer);
        // Set Avatar
        CoordsMap pos = pMapReader->getPlayerPosition(playerId-1);
        pServer->getSolver()->setInitialAvatar(pAvatar->clone(m_pLocalClient), pPlayer, pos);
        // Add spells that are equipped
        Profile::SpellData * pSpellDesc = (Profile::SpellData*) pProfile->getSpellsList()->getFirst(0);
        while (pSpellDesc != NULL)
        {
            AvatarData * pOwner = pSpellDesc->m_pOwner;
            if (pOwner != NULL && strcmp(pAvatar->m_sEdition, pOwner->m_sEdition) == 0
                    && strcmp(pAvatar->m_sObjectId, pOwner->m_sObjectId) == 0)
                pServer->getSolver()->addInitialPlayerSpell(pPlayer, pSpellDesc->m_sEdition, pSpellDesc->m_sName);
            pSpellDesc = (Profile::SpellData*) pProfile->getSpellsList()->getNext(0);
        }
        // Add equipped artifacts
        Artifact * pArtifact = (Artifact*) pProfile->getArtifactsList()->getFirst(0);
        while (pArtifact != NULL)
        {
            AvatarData * pOwner = pArtifact->m_pOwner;
            if (pOwner != NULL && strcmp(pAvatar->m_sEdition, pOwner->m_sEdition) == 0
                    && strcmp(pAvatar->m_sObjectId, pOwner->m_sObjectId) == 0)
            {
                Unit * pAvatarInGame = pPlayer->getAvatar();
                assert(pAvatarInGame != NULL);
                ArtifactEffect * pEffect = (ArtifactEffect*) pArtifact->getArtifactEffects()->getFirst(0);
                while (pEffect != NULL)
                {
                    switch (pEffect->getType())
                    {
                    case ARTIFACT_EFFECT_CHARAC:
                    {
                        bool bFound = true;
                        long val = pAvatarInGame->getValue(((ArtifactEffect_Charac*)pEffect)->m_sKey, false, &bFound);
                        if (bFound)
                            pAvatarInGame->setBaseValue(((ArtifactEffect_Charac*)pEffect)->m_sKey, max(0, val + ((ArtifactEffect_Charac*)pEffect)->m_iModifier));
                        else
                        {
                            char sError[1024];
                            snprintf(sError, 1024, "Warning: artifact %s tries to modify characteristic that doesn't exist (%s)", pArtifact->m_sObjectId, ((ArtifactEffect_Charac*)pEffect)->m_sKey);
                            m_pLocalClient->getDebug()->notifyErrorMessage(sError);
                        }
                        break;
                    }
                    case ARTIFACT_EFFECT_SPELL:
                    {
                        Spell * pSpell = m_pLocalClient->getDataFactory()->findSpell(((ArtifactEffect_Spell*)pEffect)->m_sSpellEdition, ((ArtifactEffect_Spell*)pEffect)->m_sSpellName);
                        if (pSpell != NULL)
                            pServer->getSolver()->addInitialPlayerSpell(pPlayer, ((ArtifactEffect_Spell*)pEffect)->m_sSpellEdition, ((ArtifactEffect_Spell*)pEffect)->m_sSpellName);
                        else
                        {
                            char sError[1024];
                            snprintf(sError, 1024, "Warning: artifact %s tries to add spell that doesn't exist (%s)", pArtifact->m_sObjectId, ((ArtifactEffect_Spell*)pEffect)->m_sSpellName);
                            m_pLocalClient->getDebug()->notifyErrorMessage(sError);
                        }
                        break;
                    }
                    case ARTIFACT_EFFECT_SKILL:
                    {
                        Skill * pSkill = new Skill(((ArtifactEffect_Skill*)pEffect)->m_sSkillEdition, ((ArtifactEffect_Skill*)pEffect)->m_sSkillName, ((ArtifactEffect_Skill*)pEffect)->m_sSkillParameters, pServer->getDebug());
                        if (pSkill != NULL && pSkill->isLoaded())
                            pAvatarInGame->addSkill(pSkill);
                        else
                        {
                            char sError[1024];
                            snprintf(sError, 1024, "Warning: artifact %s tries to add skill that doesn't exist or that can't be loaded (%s)", pArtifact->m_sObjectId, ((ArtifactEffect_Skill*)pEffect)->m_sSkillName);
                            m_pLocalClient->getDebug()->notifyErrorMessage(sError);
                        }
                        break;
                    }
                    }
                    pEffect = (ArtifactEffect*) pArtifact->getArtifactEffects()->getNext(0);
                }
            }
            pArtifact = (Artifact*) pProfile->getArtifactsList()->getNext(0);
        }
        playerId++;
    }
    delete pMapReader;
    pServer->onInitFinished();
}
Пример #9
0
void Agent::run(QUrl scriptURL) {
    NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT);
    NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AVATAR_MIXER, 1);
    
    QNetworkAccessManager* manager = new QNetworkAccessManager();
    
    qDebug() << "Attemping download of " << scriptURL;
    
    QNetworkReply* reply = manager->get(QNetworkRequest(scriptURL));
    
    QEventLoop loop;
    QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();
    
    QString scriptString = QString(reply->readAll());
    
    QScriptEngine engine;
    
    AvatarData *testAvatarData = new AvatarData;
    
    QScriptValue avatarDataValue = engine.newQObject(testAvatarData);
    engine.globalObject().setProperty("Avatar", avatarDataValue);
    
    QScriptValue agentValue = engine.newQObject(this);
    engine.globalObject().setProperty("Agent", agentValue);
    
    qDebug() << "Downloaded script:" << scriptString;
    
    qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString();
    
    timeval thisSend;
    timeval lastDomainServerCheckIn = {};
    int numMicrosecondsSleep = 0;
    
    const float DATA_SEND_INTERVAL_USECS = (1 / 60.0f) * 1000 * 1000;
    
    sockaddr_in senderAddress;
    unsigned char receivedData[MAX_PACKET_SIZE];
    ssize_t receivedBytes;
    
    while (!_shouldStop) {
        // update the thisSend timeval to the current time
        gettimeofday(&thisSend, NULL);
        
        // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
        if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
            gettimeofday(&lastDomainServerCheckIn, NULL);
            NodeList::getInstance()->sendDomainServerCheckIn();
        }
        
        emit preSendCallback();
        
        testAvatarData->sendData();
        
        if (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)) {
            NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes);
        }
        
        // sleep for the correct amount of time to have data send be consistently timed
        if ((numMicrosecondsSleep = DATA_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
            usleep(numMicrosecondsSleep);
        }
    }
    
}