diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index c4497a1066..6e3dd150a4 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -67,15 +67,13 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) { - int bytesSent = 0; QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(); - auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size()); individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious - bytesSent += individualData.size(); - identityPacket->write(individualData); - DependencyManager::get<NodeList>()->sendPacket(std::move(identityPacket), *destinationNode); + auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true); + identityPackets->write(individualData); + DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPackets), *destinationNode); _stats.numIdentityPackets++; - return bytesSent; + return individualData.size(); } static const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45; @@ -265,8 +263,16 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // make sure we haven't already sent this data from this sender to this receiver // or that somehow we haven't sent if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { - ++numAvatarsHeldBack; - shouldIgnore = true; + // don't ignore this avatar if we haven't sent any update for a long while + // in an effort to prevent other interfaces from deleting a stale avatar instance + uint64_t lastBroadcastTime = nodeData->getLastBroadcastTime(avatarNode->getUUID()); + const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(avatarNode->getLinkedData()); + const uint64_t AVATAR_UPDATE_STALE = AVATAR_UPDATE_TIMEOUT - USECS_PER_SECOND; + if (lastBroadcastTime > otherNodeData->getIdentityChangeTimestamp() && + lastBroadcastTime + AVATAR_UPDATE_STALE > startIgnoreCalculation) { + ++numAvatarsHeldBack; + shouldIgnore = true; + } } else if (lastSeqFromSender - lastSeqToReceiver > 1) { // this is a skip - we still send the packet but capture the presence of the skip so we see it happening ++numAvatarsWithSkippedFrames; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5ade0c448e..8319eb5249 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -110,6 +110,8 @@ const char LEFT_HAND_POINTING_FLAG = 1; const char RIGHT_HAND_POINTING_FLAG = 2; const char IS_FINGER_POINTING_FLAG = 4; +const qint64 AVATAR_UPDATE_TIMEOUT = 5 * USECS_PER_SECOND; + // AvatarData state flags - we store the details about the packet encoding in the first byte, // before the "header" structure const char AVATARDATA_FLAGS_MINIMUM = 0; @@ -599,10 +601,7 @@ public: } - bool shouldDie() const { - const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND; - return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; - } + bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_UPDATE_TIMEOUT; } static const float OUT_OF_VIEW_PENALTY;