First pass at requesting ID for unknown data

Keep list of AvatarData that was created from a
data packet without a matching ID. If items get
old enough send an ID request and remove them.
This commit is contained in:
Simon Walton 2018-06-20 12:21:39 -07:00
parent c8c135a985
commit d638bdd986
7 changed files with 52 additions and 5 deletions

View file

@ -639,6 +639,7 @@ void AvatarMixer::handleAvatarIdentityRequestPacket(QSharedPointer<ReceivedMessa
auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true); auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
identityPackets->write(serializedAvatar); identityPackets->write(serializedAvatar);
nodeList->sendPacketList(std::move(identityPackets), *senderNode); nodeList->sendPacketList(std::move(identityPackets), *senderNode);
++_sumIdentityPackets;
} }
} }
} }

View file

@ -54,6 +54,9 @@ static const quint64 MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS = USECS_PER_SECOND /
// We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key. // We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key.
const QUuid MY_AVATAR_KEY; // NULL key const QUuid MY_AVATAR_KEY; // NULL key
// For an unknown avatar-data packet, wait this long before requesting the identity (in µs).
const quint64 AvatarManager::REQUEST_UNKNOWN_IDENTITY_DELAY = 500 * 1000;
AvatarManager::AvatarManager(QObject* parent) : AvatarManager::AvatarManager(QObject* parent) :
_avatarsToFade(), _avatarsToFade(),
_myAvatar(new MyAvatar(qApp->thread()), [](MyAvatar* ptr) { ptr->deleteLater(); }) _myAvatar(new MyAvatar(qApp->thread()), [](MyAvatar* ptr) { ptr->deleteLater(); })
@ -118,6 +121,7 @@ void AvatarManager::updateMyAvatar(float deltaTime) {
_lastSendAvatarDataTime = now; _lastSendAvatarDataTime = now;
_myAvatarSendRate.increment(); _myAvatarSendRate.increment();
} }
} }
@ -276,6 +280,19 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
simulateAvatarFades(deltaTime); simulateAvatarFades(deltaTime);
const quint64 now = usecTimestampNow();
QWriteLocker writeLock(&_hashLock);
for (auto avatarData = _pendingAvatars.begin(); avatarData != _pendingAvatars.end(); ++avatarData) {
Avatar* pendingAvatar = dynamic_cast<Avatar*>(avatarData->get());
if (now - pendingAvatar->getLastRenderUpdateTime() >= REQUEST_UNKNOWN_IDENTITY_DELAY) {
pendingAvatar->sendIdentityRequest();
avatarData = _pendingAvatars.erase(avatarData);
if (avatarData == _pendingAvatars.end()) {
break;
}
}
}
_avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC; _avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC;
} }

View file

@ -194,6 +194,8 @@ private:
int _numAvatarsNotUpdated { 0 }; int _numAvatarsNotUpdated { 0 };
float _avatarSimulationTime { 0.0f }; float _avatarSimulationTime { 0.0f };
bool _shouldRender { true }; bool _shouldRender { true };
static const quint64 REQUEST_UNKNOWN_IDENTITY_DELAY;
}; };
#endif // hifi_AvatarManager_h #endif // hifi_AvatarManager_h

View file

@ -1919,6 +1919,19 @@ void AvatarData::sendIdentityPacket() {
_identityDataChanged = false; _identityDataChanged = false;
} }
void AvatarData::sendIdentityRequest() const {
auto nodeList = DependencyManager::get<NodeList>();
auto packet = NLPacket::create(PacketType::AvatarIdentityRequest, NUM_BYTES_RFC4122_UUID, true);
packet->write(getID().toRfc4122());
nodeList->eachMatchingNode(
[&](const SharedNodePointer& node)->bool {
return node->getType() == NodeType::AvatarMixer && node->getActiveSocket();
},
[&](const SharedNodePointer& node) {
nodeList->sendPacket(std::move(packet), *node);
});
}
void AvatarData::updateJointMappings() { void AvatarData::updateJointMappings() {
{ {
QWriteLocker writeLock(&_jointDataLock); QWriteLocker writeLock(&_jointDataLock);

View file

@ -401,7 +401,7 @@ class AvatarData : public QObject, public SpatiallyNestable {
Q_PROPERTY(float sensorToWorldScale READ getSensorToWorldScale) Q_PROPERTY(float sensorToWorldScale READ getSensorToWorldScale)
public: public:
void sendIdentityRequest() const;
virtual QString getName() const override { return QString("Avatar:") + _displayName; } virtual QString getName() const override { return QString("Avatar:") + _displayName; }
static const QString FRAME_NAME; static const QString FRAME_NAME;

View file

@ -89,11 +89,15 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe
return avatar; return avatar;
} }
AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) { AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer,
bool& isNew) {
QWriteLocker locker(&_hashLock); QWriteLocker locker(&_hashLock);
auto avatar = _avatarHash.value(sessionUUID); auto avatar = _avatarHash.value(sessionUUID);
if (!avatar) { if (!avatar) {
avatar = addAvatar(sessionUUID, mixerWeakPointer); avatar = addAvatar(sessionUUID, mixerWeakPointer);
isNew = true;
} else {
isNew = false;
} }
return avatar; return avatar;
} }
@ -125,8 +129,13 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer<ReceivedMessag
// make sure this isn't our own avatar data or for a previously ignored node // make sure this isn't our own avatar data or for a previously ignored node
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
bool isNewAvatar;
if (sessionUUID != _lastOwnerSessionUUID && (!nodeList->isIgnoringNode(sessionUUID) || nodeList->getRequestsDomainListData())) { if (sessionUUID != _lastOwnerSessionUUID && (!nodeList->isIgnoringNode(sessionUUID) || nodeList->getRequestsDomainListData())) {
auto avatar = newOrExistingAvatar(sessionUUID, sendingNode); auto avatar = newOrExistingAvatar(sessionUUID, sendingNode, isNewAvatar);
if (isNewAvatar) {
QWriteLocker locker(&_hashLock);
_pendingAvatars.insert(sessionUUID, avatar);
}
// have the matching (or new) avatar parse the data from the packet // have the matching (or new) avatar parse the data from the packet
int bytesRead = avatar->parseDataFromBuffer(byteArray); int bytesRead = avatar->parseDataFromBuffer(byteArray);
@ -157,6 +166,7 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
{ {
QReadLocker locker(&_hashLock); QReadLocker locker(&_hashLock);
_pendingAvatars.remove(identityUUID);
auto me = _avatarHash.find(EMPTY); auto me = _avatarHash.find(EMPTY);
if ((me != _avatarHash.end()) && (identityUUID == me.value()->getSessionUUID())) { if ((me != _avatarHash.end()) && (identityUUID == me.value()->getSessionUUID())) {
// We add MyAvatar to _avatarHash with an empty UUID. Code relies on this. In order to correctly handle an // We add MyAvatar to _avatarHash with an empty UUID. Code relies on this. In order to correctly handle an
@ -168,7 +178,8 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
if (!nodeList->isIgnoringNode(identityUUID) || nodeList->getRequestsDomainListData()) { if (!nodeList->isIgnoringNode(identityUUID) || nodeList->getRequestsDomainListData()) {
// mesh URL for a UUID, find avatar in our list // mesh URL for a UUID, find avatar in our list
auto avatar = newOrExistingAvatar(identityUUID, sendingNode); bool isNewAvatar;
auto avatar = newOrExistingAvatar(identityUUID, sendingNode, isNewAvatar);
bool identityChanged = false; bool identityChanged = false;
bool displayNameChanged = false; bool displayNameChanged = false;
bool skeletonModelUrlChanged = false; bool skeletonModelUrlChanged = false;
@ -189,6 +200,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer<ReceivedMessage> message, S
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) {
QWriteLocker locker(&_hashLock); QWriteLocker locker(&_hashLock);
_pendingAvatars.remove(sessionUUID);
auto removedAvatar = _avatarHash.take(sessionUUID); auto removedAvatar = _avatarHash.take(sessionUUID);
if (removedAvatar) { if (removedAvatar) {

View file

@ -145,13 +145,15 @@ protected:
virtual AvatarSharedPointer parseAvatarData(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode); virtual AvatarSharedPointer parseAvatarData(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
virtual AvatarSharedPointer newSharedAvatar(); virtual AvatarSharedPointer newSharedAvatar();
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer); virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
AvatarSharedPointer newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer); AvatarSharedPointer newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer,
bool& isNew);
virtual AvatarSharedPointer findAvatar(const QUuid& sessionUUID) const; // uses a QReadLocker on the hashLock virtual AvatarSharedPointer findAvatar(const QUuid& sessionUUID) const; // uses a QReadLocker on the hashLock
virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason); virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason);
virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason); virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason);
AvatarHash _avatarHash; AvatarHash _avatarHash;
AvatarHash _pendingAvatars;
mutable QReadWriteLock _hashLock; mutable QReadWriteLock _hashLock;
private: private: