remove skeleton from identity, handle in clients

This commit is contained in:
Stephen Birarda 2018-08-07 15:38:57 -07:00
parent 26a1f03314
commit a80d19a44a
11 changed files with 104 additions and 47 deletions

View file

@ -447,11 +447,6 @@ void Agent::executeScript() {
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
_scriptEngine->registerGlobalObject("AvatarList", avatarHashMap.data());
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket");
packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar");
packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket");
// register ourselves to the script engine
_scriptEngine->registerGlobalObject("Agent", new AgentScriptingInterface(this));

View file

@ -109,17 +109,10 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message) {
message.readPrimitive(&traitSize);
if (packetTraitVersion > _receivedSimpleTraitVersions[traitType]) {
if (traitType == AvatarTraits::SkeletonModelURL) {
// get the URL from the binary data
auto skeletonModelURL = QUrl::fromEncoded(message.read(traitSize));
_avatar->setSkeletonModelURL(skeletonModelURL);
qDebug() << "Set skeleton URL to" << skeletonModelURL << "for trait packet version" << packetTraitVersion;
_receivedSimpleTraitVersions[traitType] = packetTraitVersion;
anyTraitsChanged = true;
}
_avatar->processTrait(traitType, message.readWithoutCopy(traitSize));
_receivedSimpleTraitVersions[traitType] = packetTraitVersion;
anyTraitsChanged = true;
} else {
message.seek(message.getPosition() + traitSize);
}

View file

@ -81,9 +81,6 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket");
packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar");
packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket");
packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket");
packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket");

View file

@ -72,10 +72,6 @@ AvatarManager::AvatarManager(QObject* parent) :
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
auto nodeList = DependencyManager::get<NodeList>();
auto& packetReceiver = nodeList->getPacketReceiver();
packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket");
packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar");
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket");
// when we hear that the user has ignored an avatar by session UUID
// immediately remove that avatar instead of waiting for the absence of packets from avatar mixer

View file

@ -1705,8 +1705,6 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
if (previousSkeletonModelURL != _skeletonModelURL) {
_clientTraitsHandler.markTraitChanged(AvatarTraits::SkeletonModelURL);
} else {
qDebug() << "Not marking skeleton model URL trait changed since the new value matches the previous";
}
}

View file

@ -42,6 +42,7 @@
#include <BitVectorHelpers.h>
#include "AvatarLogging.h"
#include "AvatarTraits.h"
//#define WANT_DEBUG
@ -1756,7 +1757,7 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const {
}
void AvatarData::processAvatarIdentity(const QByteArray& identityData, bool& identityChanged,
bool& displayNameChanged, bool& skeletonModelUrlChanged) {
bool& displayNameChanged) {
QDataStream packetStream(identityData);
@ -1777,7 +1778,7 @@ void AvatarData::processAvatarIdentity(const QByteArray& identityData, bool& ide
if (incomingSequenceNumber > _identitySequenceNumber) {
Identity identity;
packetStream >> identity.skeletonModelURL
packetStream
>> identity.attachmentData
>> identity.displayName
>> identity.sessionDisplayName
@ -1789,16 +1790,6 @@ void AvatarData::processAvatarIdentity(const QByteArray& identityData, bool& ide
// set the store identity sequence number to match the incoming identity
_identitySequenceNumber = incomingSequenceNumber;
if (_firstSkeletonCheck || (identity.skeletonModelURL != cannonicalSkeletonModelURL(emptyURL))) {
setSkeletonModelURL(identity.skeletonModelURL);
identityChanged = true;
skeletonModelUrlChanged = true;
if (_firstSkeletonCheck) {
displayNameChanged = true;
}
_firstSkeletonCheck = false;
}
if (identity.displayName != _displayName) {
_displayName = identity.displayName;
identityChanged = true;
@ -1834,7 +1825,6 @@ void AvatarData::processAvatarIdentity(const QByteArray& identityData, bool& ide
#ifdef WANT_DEBUG
qCDebug(avatars) << __FUNCTION__
<< "identity.uuid:" << identity.uuid
<< "identity.skeletonModelURL:" << identity.skeletonModelURL
<< "identity.displayName:" << identity.displayName
<< "identity.sessionDisplayName:" << identity.sessionDisplayName;
} else {
@ -1846,10 +1836,18 @@ void AvatarData::processAvatarIdentity(const QByteArray& identityData, bool& ide
}
}
void AvatarData::processTrait(AvatarTraits::TraitType traitType, QByteArray traitBinaryData) {
if (traitType == AvatarTraits::SkeletonModelURL) {
// get the URL from the binary data
auto skeletonModelURL = QUrl::fromEncoded(traitBinaryData);
qDebug() << "Setting skeleton model URL from trait packet to" << skeletonModelURL;
setSkeletonModelURL(skeletonModelURL);
}
}
QByteArray AvatarData::identityByteArray(bool setIsReplicated) const {
QByteArray identityData;
QDataStream identityStream(&identityData, QIODevice::Append);
const QUrl& urlToSend = cannonicalSkeletonModelURL(emptyURL); // depends on _skeletonModelURL
// when mixers send identity packets to agents, they simply forward along the last incoming sequence number they received
// whereas agents send a fresh outgoing sequence number when identity data has changed
@ -1857,7 +1855,6 @@ QByteArray AvatarData::identityByteArray(bool setIsReplicated) const {
_avatarEntitiesLock.withReadLock([&] {
identityStream << getSessionUUID()
<< (udt::SequenceNumber::Type) _identitySequenceNumber
<< urlToSend
<< _attachmentData
<< _displayName
<< getSessionDisplayNameForTransport() // depends on _sessionDisplayName

View file

@ -51,6 +51,7 @@
#include <udt/SequenceNumber.h>
#include "AABox.h"
#include "AvatarTraits.h"
#include "HeadData.h"
#include "PathUtils.h"
@ -955,8 +956,9 @@ public:
// identityChanged returns true if identity has changed, false otherwise.
// identityChanged returns true if identity has changed, false otherwise. Similarly for displayNameChanged and skeletonModelUrlChange.
void processAvatarIdentity(const QByteArray& identityData, bool& identityChanged,
bool& displayNameChanged, bool& skeletonModelUrlChanged);
void processAvatarIdentity(const QByteArray& identityData, bool& identityChanged, bool& displayNameChanged);
void processTrait(AvatarTraits::TraitType traitType, QByteArray traitBinaryData);
QByteArray identityByteArray(bool setIsReplicated = false) const;
@ -1327,7 +1329,6 @@ protected:
mutable HeadData* _headData { nullptr };
QUrl _skeletonModelURL;
bool _firstSkeletonCheck { true };
QUrl _skeletonFBXURL;
QVector<AttachmentData> _attachmentData;
QVector<AttachmentData> _oldAttachmentData;

View file

@ -19,10 +19,17 @@
#include <SharedUtil.h>
#include "AvatarLogging.h"
#include "AvatarTraits.h"
AvatarHashMap::AvatarHashMap() {
auto nodeList = DependencyManager::get<NodeList>();
auto& packetReceiver = nodeList->getPacketReceiver();
packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket");
packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar");
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket");
packetReceiver.registerListener(PacketType::BulkAvatarTraits, this, "processBulkAvatarTraits");
connect(nodeList.data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
}
@ -182,9 +189,74 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
auto avatar = newOrExistingAvatar(identityUUID, sendingNode, isNewAvatar);
bool identityChanged = false;
bool displayNameChanged = false;
bool skeletonModelUrlChanged = false;
// In this case, the "sendingNode" is the Avatar Mixer.
avatar->processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged, skeletonModelUrlChanged);
avatar->processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged);
}
}
bool AvatarHashMap::checkLastProcessedTraitVersion(QUuid avatarID,
AvatarTraits::TraitType traitType, AvatarTraits::TraitVersion newVersion) {
auto it = _processedSimpleTraitVersions.find(avatarID);
if (it == _processedSimpleTraitVersions.end()) {
auto pair = _processedSimpleTraitVersions.insert({
avatarID,
{ AvatarTraits::TotalTraitTypes, AvatarTraits::DEFAULT_TRAIT_VERSION }
});
it = pair.first;
};
if (it->second[traitType] < newVersion) {
it->second[traitType] = newVersion;
return true;
} else {
return false;
}
}
void AvatarHashMap::processBulkAvatarTraits(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
while (message->getBytesLeftToRead()) {
// read the avatar ID to figure out which avatar this is for
auto avatarID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
// grab the avatar so we can ask it to process trait data
AvatarSharedPointer avatar;
QReadLocker locker(&_hashLock);
auto it = _avatarHash.find(avatarID);
if (it != _avatarHash.end()) {
avatar = *it;
}
locker.unlock();
// read the first trait type for this avatar
AvatarTraits::TraitType traitType;
message->readPrimitive(&traitType);
while (traitType != AvatarTraits::NullTrait) {
AvatarTraits::TraitVersion traitVersion;
message->readPrimitive(&traitVersion);
AvatarTraits::TraitWireSize traitBinarySize;
message->readPrimitive(&traitBinarySize);
if (avatar) {
// check if this trait version is newer than what we already have for this avatar
bool traitIsNewer = checkLastProcessedTraitVersion(avatarID, traitType, traitVersion);
if (traitIsNewer) {
avatar->processTrait(traitType, message->readWithoutCopy(traitBinarySize));
} else {
message->seek(message->getPosition() + traitBinarySize);
}
} else {
// though we have no avatar pointer, we still hop through the packet in case there are
// traits for avatars we do have later in the packet
message->seek(message->getPosition() + traitBinarySize);
}
// read the next trait type, which is null if there are no more traits for this avatar
message->readPrimitive(&traitType);
}
}
}

View file

@ -30,6 +30,7 @@
#include "ScriptAvatarData.h"
#include "AvatarData.h"
#include "AvatarTraits.h"
/**jsdoc
* <strong>Note:</strong> An <code>AvatarList</code> API is also provided for Interface and client entity scripts: it is a
@ -133,6 +134,8 @@ protected slots:
*/
void processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void processBulkAvatarTraits(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
/**jsdoc
* @function AvatarList.processKillAvatar
* @param {} message
@ -153,6 +156,9 @@ protected:
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason);
bool checkLastProcessedTraitVersion(QUuid avatarID,
AvatarTraits::TraitType traitType, AvatarTraits::TraitVersion newVersion);
AvatarHash _avatarHash;
struct PendingAvatar {
std::chrono::steady_clock::time_point creationTime;
@ -163,6 +169,7 @@ protected:
AvatarPendingHash _pendingAvatars;
mutable QReadWriteLock _hashLock;
std::unordered_map<QUuid, AvatarTraits::SimpleTraitVersions> _processedSimpleTraitVersions;
private:
QUuid _lastOwnerSessionUUID;
};

View file

@ -40,7 +40,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::AvatarData:
case PacketType::BulkAvatarData:
case PacketType::KillAvatar:
return static_cast<PacketVersion>(AvatarMixerPacketVersion::FarGrabJoints);
return static_cast<PacketVersion>(AvatarMixerPacketVersion::MigrateSkeletonURLToTraits);
case PacketType::MessagesData:
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
// ICE packets

View file

@ -134,7 +134,7 @@ public:
EntityClone,
EntityQueryInitialResultsComplete,
BulkAvatarTraits,
NUM_PACKET_TYPE
};
@ -291,6 +291,7 @@ enum class AvatarMixerPacketVersion : PacketVersion {
FixMannequinDefaultAvatarFeet,
ProceduralFaceMovementFlagsAndBlendshapes,
FarGrabJoints
MigrateSkeletonURLToTraits
};
enum class DomainConnectRequestVersion : PacketVersion {