From ce1fe4850c4b49ccf599382f18b37a8b87885400 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 29 Aug 2024 13:54:11 +0200 Subject: [PATCH 1/8] Clean up unused code --- indra/newview/llappearancemgr.cpp | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 101aca3823..f372341830 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -705,7 +705,6 @@ class LLWearableHoldingPattern bool pollMissingWearables(); bool isMissingCompleted(); void recoverMissingWearable(LLWearableType::EType type); - void clearCOFLinksForMissingWearables(); void onWearableAssetFetch(LLViewerWearable *wearable); void onAllComplete(); @@ -1117,20 +1116,6 @@ bool LLWearableHoldingPattern::isMissingCompleted() return mTypesToLink.size()==0 && mTypesToRecover.size()==0; } -void LLWearableHoldingPattern::clearCOFLinksForMissingWearables() -{ - for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it) - { - LLFoundData &data = *it; - if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable)) - { - // Wearable link that was never resolved; remove links to it from COF - LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " removing link for unresolved item " << data.mItemID.asString() << LL_ENDL; - LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID); - } - } -} - bool LLWearableHoldingPattern::pollMissingWearables() { if (!isMostRecent()) @@ -1161,14 +1146,6 @@ bool LLWearableHoldingPattern::pollMissingWearables() gAgentAvatarp->debugWearablesLoaded(); - // BAP - if we don't call clearCOFLinksForMissingWearables() - // here, we won't have to add the link back in later if the - // wearable arrives late. This is to avoid corruption of - // wearable ordering info. Also has the effect of making - // unworn item links visible in the COF under some - // circumstances. - - //clearCOFLinksForMissingWearables(); onAllComplete(); } return done; @@ -1215,13 +1192,6 @@ void LLWearableHoldingPattern::handleLateArrivals() replaced_types.insert(data.mWearableType); - // BAP - if we didn't call - // clearCOFLinksForMissingWearables() earlier, we - // don't need to restore the link here. Fixes - // wearable ordering problems. - - // LLAppearanceMgr::instance().addCOFItemLink(data.mItemID,false); - // BAP failing this means inventory or asset server // are corrupted in a way we don't handle. llassert((data.mWearableType < LLWearableType::WT_COUNT) && (wearable->getType() == data.mWearableType)); From c1f0f577f6cfdfadfdf5a306bad038cc4e5d1ebe Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 29 Aug 2024 14:49:59 +0200 Subject: [PATCH 2/8] LLViewerObject::getAttachmentItemID() sometimes returns the NULL UUID for the avatar's own attachments --- indra/newview/llviewerjointattachment.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 511fac9788..cad96afd98 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -168,7 +168,6 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) //----------------------------------------------------------------------------- bool LLViewerJointAttachment::addObject(LLViewerObject* object) { - object->extractAttachmentItemID(); // Same object reattached if (isObjectAttached(object)) @@ -179,6 +178,8 @@ bool LLViewerJointAttachment::addObject(LLViewerObject* object) // re-connect object to the joint correctly } + object->extractAttachmentItemID(); + // Two instances of the same inventory item attached -- // Request detach, and kill the object in the meantime. if (getAttachedObject(object->getAttachmentItemID())) From 48bae10e11bce392c86b65e5a7dba2aa3dd4daae Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 29 Aug 2024 14:54:56 +0200 Subject: [PATCH 3/8] LLAppearanceMgr::updateAppearanceFromCOF() doesn't properly filter items collected from folder links --- indra/newview/llappearancemgr.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f372341830..437cfc1e04 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2573,6 +2573,11 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, remove_non_link_items(wear_items); remove_non_link_items(obj_items); remove_non_link_items(gest_items); + // Since we're following folder links we might have picked up new duplicates, or exceeded MAX_CLOTHING_LAYERS + removeDuplicateItems(wear_items); + removeDuplicateItems(obj_items); + removeDuplicateItems(gest_items); + filterWearableItems(wear_items, 0, LLAgentWearables::MAX_CLOTHING_LAYERS); dumpItemArray(wear_items,"asset_dump: wear_item"); dumpItemArray(obj_items,"asset_dump: obj_item"); From f85389e1ab7fd7624a752b97583991c74628f551 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 29 Aug 2024 20:42:02 +0200 Subject: [PATCH 4/8] Resolve race condition when removing/add attachments inside of a LLWearableHoldingPattern (see PR for details) --- indra/newview/llappearancemgr.cpp | 103 +++++++++++++++--------------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 437cfc1e04..b13926afc2 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -713,7 +713,6 @@ class LLWearableHoldingPattern found_list_t& getFoundList(); void eraseTypeToLink(LLWearableType::EType type); void eraseTypeToRecover(LLWearableType::EType type); - void setObjItems(const LLInventoryModel::item_array_t& items); void setGestItems(const LLInventoryModel::item_array_t& items); bool isMostRecent(); void handleLateArrivals(); @@ -723,7 +722,6 @@ class LLWearableHoldingPattern private: found_list_t mFoundList; - LLInventoryModel::item_array_t mObjItems; LLInventoryModel::item_array_t mGestItems; typedef std::set type_set_t; type_set_t mTypesToRecover; @@ -800,11 +798,6 @@ void LLWearableHoldingPattern::eraseTypeToRecover(LLWearableType::EType type) mTypesToRecover.erase(type); } -void LLWearableHoldingPattern::setObjItems(const LLInventoryModel::item_array_t& items) -{ - mObjItems = items; -} - void LLWearableHoldingPattern::setGestItems(const LLInventoryModel::item_array_t& items) { mGestItems = items; @@ -910,55 +903,10 @@ void LLWearableHoldingPattern::onAllComplete() if (isAgentAvatarValid()) { - LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.size() << " attachments" << LL_ENDL; - LLAgentWearables::llvo_vec_t objects_to_remove; - LLAgentWearables::llvo_vec_t objects_to_retain; - LLInventoryModel::item_array_t items_to_add; - - LLAgentWearables::findAttachmentsAddRemoveInfo(mObjItems, - objects_to_remove, - objects_to_retain, - items_to_add); - - LL_DEBUGS("Avatar") << self_av_string() << "Removing " << objects_to_remove.size() - << " attachments" << LL_ENDL; - - // Here we remove the attachment pos overrides for *all* - // attachments, even those that are not being removed. This is - // needed to get joint positions all slammed down to their - // pre-attachment states. - gAgentAvatarp->clearAttachmentOverrides(); - - if (objects_to_remove.size() || items_to_add.size()) - { - LL_DEBUGS("Avatar") << "ATT will remove " << objects_to_remove.size() - << " and add " << items_to_add.size() << " items" << LL_ENDL; - } - - // Take off the attachments that will no longer be in the outfit. - LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); - // Update wearables. LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " << mResolved << " wearable items " << LL_ENDL; LLAppearanceMgr::instance().updateAgentWearables(this); - - // Restore attachment pos overrides for the attachments that - // are remaining in the outfit. - for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); - it != objects_to_retain.end(); - ++it) - { - LLViewerObject *objectp = *it; - if (!objectp->isAnimatedObject()) - { - gAgentAvatarp->addAttachmentOverridesForObject(objectp); - } - } - - // Add new attachments to match those requested. - LL_DEBUGS("Avatar") << self_av_string() << "Adding " << items_to_add.size() << " attachments" << LL_ENDL; - LLAgentWearables::userAttachMultipleAttachments(items_to_add); } if (isFetchCompleted() && isMissingCompleted()) @@ -2589,6 +2537,56 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, << " descendent_count " << cof->getDescendentCount() << " viewer desc count " << cof->getViewerDescendentCount() << LL_ENDL; } + + // Update attachments to match those requested. + if (isAgentAvatarValid()) + { + LL_DEBUGS("Avatar") << self_av_string() << "Updating " << obj_items.size() << " attachments" << LL_ENDL; + LLAgentWearables::llvo_vec_t objects_to_remove; + LLAgentWearables::llvo_vec_t objects_to_retain; + LLInventoryModel::item_array_t items_to_add; + + LLAgentWearables::findAttachmentsAddRemoveInfo(obj_items, + objects_to_remove, + objects_to_retain, + items_to_add); + + LL_DEBUGS("Avatar") << self_av_string() << "Removing " << objects_to_remove.size() + << " attachments" << LL_ENDL; + + // Here we remove the attachment pos overrides for *all* + // attachments, even those that are not being removed. This is + // needed to get joint positions all slammed down to their + // pre-attachment states. + gAgentAvatarp->clearAttachmentOverrides(); + + if (objects_to_remove.size() || items_to_add.size()) + { + LL_DEBUGS("Avatar") << "ATT will remove " << objects_to_remove.size() + << " and add " << items_to_add.size() << " items" << LL_ENDL; + } + + // Take off the attachments that will no longer be in the outfit. + LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); + + // Restore attachment pos overrides for the attachments that + // are remaining in the outfit. + for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); + it != objects_to_retain.end(); + ++it) + { + LLViewerObject *objectp = *it; + if (!objectp->isAnimatedObject()) + { + gAgentAvatarp->addAttachmentOverridesForObject(objectp); + } + } + + // Add new attachments to match those requested. + LL_DEBUGS("Avatar") << self_av_string() << "Adding " << items_to_add.size() << " attachments" << LL_ENDL; + LLAgentWearables::userAttachMultipleAttachments(items_to_add); + } + if(!wear_items.size()) { LLNotificationsUtil::add("CouldNotPutOnOutfit"); @@ -2603,7 +2601,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, LLTimer hp_block_timer; LLWearableHoldingPattern* holder = new LLWearableHoldingPattern; - holder->setObjItems(obj_items); holder->setGestItems(gest_items); // Note: can't do normal iteration, because if all the From 420a3f10144efbb2385a75048779431addf1803e Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 29 Aug 2024 20:51:00 +0200 Subject: [PATCH 5/8] Resolve issues tracking worn attachments that aren't in COF yet (see PR for more details) --- indra/newview/llappearancemgr.cpp | 24 ++++- indra/newview/llappearancemgr.h | 1 + indra/newview/llattachmentsmgr.cpp | 143 +++++++++++------------------ indra/newview/llattachmentsmgr.h | 12 ++- indra/newview/llvoavatar.cpp | 2 +- 5 files changed, 89 insertions(+), 93 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b13926afc2..dbc1a3c5d1 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2541,6 +2541,23 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, // Update attachments to match those requested. if (isAgentAvatarValid()) { + // Include attachments which should be in COF but don't have their link created yet + std::set pendingAttachments; + LLAttachmentsMgr::instance().getPendingAttachments(pendingAttachments); + for (const LLUUID& idAttachItem : pendingAttachments) + { + if ( !gAgentAvatarp->isWearingAttachment(idAttachItem) || isLinkedInCOF(idAttachItem) ) + { + LLAttachmentsMgr::instance().clearPendingAttachmentLink(idAttachItem); + continue; + } + + if (LLViewerInventoryItem* pAttachItem = gInventory.getItem(idAttachItem)) + { + obj_items.push_back(pAttachItem); + } + } + LL_DEBUGS("Avatar") << self_av_string() << "Updating " << obj_items.size() << " attachments" << LL_ENDL; LLAgentWearables::llvo_vec_t objects_to_remove; LLAgentWearables::llvo_vec_t objects_to_retain; @@ -2567,7 +2584,11 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, } // Take off the attachments that will no longer be in the outfit. - LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); + // (don't remove attachments until avatar is fully loaded - reduces random attaching/detaching/reattaching at log-on) + if (gAgentAvatarp->isFullyLoaded()) + { + LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); + } // Restore attachment pos overrides for the attachments that // are remaining in the outfit. @@ -4140,6 +4161,7 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nul continue; } removeCOFItemLinks(linked_item_id, cb); + LLAttachmentsMgr::instance().clearPendingAttachmentLink(linked_item_id); addDoomedTempAttachment(linked_item_id); } } diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 6c45a32856..1e779bbd6f 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -150,6 +150,7 @@ class LLAppearanceMgr: public LLSingleton // Attachment link management void unregisterAttachment(const LLUUID& item_id); void registerAttachment(const LLUUID& item_id); + bool getAttachmentInvLinkEnable() const { return mAttachmentInvLinkEnabled; } void setAttachmentInvLinkEnable(bool val); // Add COF link to individual item. diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index 8b5db2c0fa..e27d6fb1f5 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -42,10 +42,19 @@ const F32 MAX_ATTACHMENT_REQUEST_LIFETIME = 30.0F; const F32 MIN_RETRY_REQUEST_TIME = 5.0F; const F32 MAX_BAD_COF_TIME = 30.0F; +class LLRegisterAttachmentCallback : public LLRequestServerAppearanceUpdateOnDestroy +{ +public: + void fire(const LLUUID& item_id) override + { + LLAttachmentsMgr::instance().onRegisterAttachmentComplete(item_id); + LLRequestServerAppearanceUpdateOnDestroy::fire(item_id); + } +}; + LLAttachmentsMgr::LLAttachmentsMgr(): mAttachmentRequests("attach",MIN_RETRY_REQUEST_TIME), - mDetachRequests("detach",MIN_RETRY_REQUEST_TIME), - mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME) + mDetachRequests("detach",MIN_RETRY_REQUEST_TIME) { } @@ -113,8 +122,6 @@ void LLAttachmentsMgr::onIdle() expireOldDetachRequests(); - checkInvalidCOFLinks(); - spamStatusInfo(); } @@ -222,6 +229,11 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments() { if (mRecentlyArrivedAttachments.size()) { + if (!LLAppearanceMgr::instance().getAttachmentInvLinkEnable()) + { + return; + } + // One or more attachments have arrived but have not yet been // processed for COF links if (mAttachmentRequests.empty()) @@ -268,17 +280,49 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments() } if (ids_to_link.size()) { - LLPointer cb = new LLRequestServerAppearanceUpdateOnDestroy(); - for (uuid_vec_t::const_iterator uuid_it = ids_to_link.begin(); - uuid_it != ids_to_link.end(); ++uuid_it) + LLPointer cb = new LLRegisterAttachmentCallback(); + for (const LLUUID& id_item: ids_to_link) { - LLAppearanceMgr::instance().addCOFItemLink(*uuid_it, cb); + if (std::find(mPendingAttachLinks.begin(), mPendingAttachLinks.end(), id_item) == mPendingAttachLinks.end()) + { + LLAppearanceMgr::instance().addCOFItemLink(id_item, cb); + mPendingAttachLinks.insert(id_item); + } } } mRecentlyArrivedAttachments.clear(); } } +bool LLAttachmentsMgr::getPendingAttachments(std::set& ids) const +{ + ids.clear(); + + // Returns the combined set of attachments that are pending link creation and those that currently have an ongoing link creation process. + set_union(mRecentlyArrivedAttachments.begin(), mRecentlyArrivedAttachments.end(), mPendingAttachLinks.begin(), mPendingAttachLinks.end(), std::inserter(ids, ids.begin())); + + return !ids.empty(); +} + +void LLAttachmentsMgr::clearPendingAttachmentLink(const LLUUID& idItem) +{ + mPendingAttachLinks.erase(idItem); +} + +void LLAttachmentsMgr::onRegisterAttachmentComplete(const LLUUID& id_item_link) +{ + if (const LLUUID& id_item = gInventory.getLinkedItemID(id_item_link); id_item != id_item_link) + { + clearPendingAttachmentLink(id_item); + + // It may have been detached already in which case we should remove the COF link + if ( isAgentAvatarValid() && !gAgentAvatarp->isWearingAttachment(id_item) ) + { + LLAppearanceMgr::instance().removeCOFItemLinks(id_item); + } + } +} + LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes(const std::string& op_name, F32 timeout): mOpName(op_name), mTimeout(timeout) @@ -407,6 +451,8 @@ void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id) void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id) { + clearPendingAttachmentLink(inv_item_id); + LLTimer timer; LLInventoryItem *item = gInventory.getItem(inv_item_id); if (mDetachRequests.getTime(inv_item_id, timer)) @@ -428,10 +474,6 @@ void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id) { LL_DEBUGS("Avatar") << "ATT detach on shutdown for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; } - - LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking " - << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; - mQuestionableCOFLinks.addTime(inv_item_id); } bool LLAttachmentsMgr::isAttachmentStateComplete() const @@ -440,81 +482,8 @@ bool LLAttachmentsMgr::isAttachmentStateComplete() const && mAttachmentRequests.empty() && mDetachRequests.empty() && mRecentlyArrivedAttachments.empty() - && mQuestionableCOFLinks.empty(); -} - -// Check for attachments that are (a) linked in COF and (b) not -// attached to the avatar. This is a rotten function to have to -// include, because it runs the risk of either repeatedly spamming out -// COF link removals if they're failing for some reason, or getting -// into a tug of war with some other sequence of events that's in the -// process of adding the attachment in question. However, it's needed -// because we have no definitive source of authority for what things -// are actually supposed to be attached. Scripts, run on the server -// side, can remove an attachment without our expecting it. If this -// happens to an attachment that's just been added, then the COF link -// creation may still be in flight, and we will have to delete the -// link after it shows up. -// -// Note that we only flag items for possible link removal if they have -// been previously detached. This means that an attachment failure -// will leave the link in the COF, where it will hopefully resolve -// correctly on relog. -// -// See related: MAINT-5070, MAINT-4409 -// -void LLAttachmentsMgr::checkInvalidCOFLinks() -{ - if (!gInventory.isInventoryUsable() || mQuestionableCOFLinks.empty()) - { - return; - } - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), - cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); - for (S32 i=0; igetLinkedUUID(); - if (inv_item->getType() == LLAssetType::AT_OBJECT) - { - LLTimer timer; - bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer); - bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id); - if (is_wearing_attachment && is_flagged_questionable) - { - LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now " - << (is_wearing_attachment ? "attached " : "") - <<"removing flag after " - << timer.getElapsedTimeF32() << " item " - << inv_item->getName() << " id " << item_id << LL_ENDL; - mQuestionableCOFLinks.removeTime(item_id); - } - } - } - - for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin(); - it != mQuestionableCOFLinks.end(); ) - { - LLItemRequestTimes::iterator curr_it = it; - ++it; - const LLUUID& item_id = curr_it->first; - LLViewerInventoryItem *inv_item = gInventory.getItem(item_id); - if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME) - { - if (LLAppearanceMgr::instance().isLinkedInCOF(item_id)) - { - LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after " - << curr_it->second.getElapsedTimeF32() << " seconds for " - << (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; - LLAppearanceMgr::instance().removeCOFItemLinks(item_id); - } - mQuestionableCOFLinks.erase(curr_it); - continue; - } - } -} + && mPendingAttachLinks.empty(); + } void LLAttachmentsMgr::spamStatusInfo() { diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h index 2428acfb38..4ccd4d3224 100644 --- a/indra/newview/llattachmentsmgr.h +++ b/indra/newview/llattachmentsmgr.h @@ -85,8 +85,14 @@ class LLAttachmentsMgr: public LLSingleton void onDetachRequested(const LLUUID& inv_item_id); void onDetachCompleted(const LLUUID& inv_item_id); + void clearPendingAttachmentLink(const LLUUID& idItem); + bool getPendingAttachments(std::set& ids) const; bool isAttachmentStateComplete() const; +protected: + void onRegisterAttachmentComplete(const LLUUID& id_item_link); + friend class LLRegisterAttachmentCallback; + private: class LLItemRequestTimes: public std::map @@ -109,7 +115,6 @@ class LLAttachmentsMgr: public LLSingleton void linkRecentlyArrivedAttachments(); void expireOldAttachmentRequests(); void expireOldDetachRequests(); - void checkInvalidCOFLinks(); void spamStatusInfo(); // Attachments that we are planning to rez but haven't requested from the server yet. @@ -124,9 +129,8 @@ class LLAttachmentsMgr: public LLSingleton // Attachments that have arrived but have not been linked in the COF yet. std::set mRecentlyArrivedAttachments; LLTimer mCOFLinkBatchTimer; - - // Attachments that are linked in the COF but may be invalid. - LLItemRequestTimes mQuestionableCOFLinks; + // Attachments that have pending COF link creation + std::set mPendingAttachLinks; }; #endif diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c5ca8030fe..9929e626c8 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8535,7 +8535,7 @@ bool LLVOAvatar::processFullyLoadedChange(bool loading) bool LLVOAvatar::isFullyLoaded() const { - return (mRenderUnloadedAvatar || mFullyLoaded); + return (mRenderUnloadedAvatar && !isSelf()) || mFullyLoaded; } bool LLVOAvatar::hasFirstFullAttachmentData() const From f36b95b62a6a990572bc7a9029936bbff14a1a0d Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Fri, 30 Aug 2024 01:03:23 +0200 Subject: [PATCH 6/8] If multiple LLWearableHoldingPattern instances are waiting for completion, only the most recently created one should progress --- indra/newview/llappearancemgr.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index dbc1a3c5d1..be6f598bae 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -700,6 +700,7 @@ class LLWearableHoldingPattern void onFetchCompletion(); bool isFetchCompleted(); bool isTimedOut(); + bool pollStopped(); void checkMissingWearables(); bool pollMissingWearables(); @@ -944,6 +945,10 @@ bool LLWearableHoldingPattern::pollFetchCompletion() { // runway skip here? LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL; + + // If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves + doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollStopped, this)); + return true; } bool completed = isFetchCompleted(); @@ -1014,6 +1019,9 @@ void recovered_item_cb(const LLUUID& item_id, LLWearableType::EType type, LLView { // runway skip here? LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL; + + // If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves + return; } LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << type << LL_ENDL; @@ -1064,12 +1072,27 @@ bool LLWearableHoldingPattern::isMissingCompleted() return mTypesToLink.size()==0 && mTypesToRecover.size()==0; } +bool LLWearableHoldingPattern::pollStopped() +{ + // We have to keep on polling until we're sure that all callbacks have completed or they'll cause a crash + if (isFetchCompleted() && isMissingCompleted()) + { + delete this; + return true; + } + return false; +} + bool LLWearableHoldingPattern::pollMissingWearables() { if (!isMostRecent()) { // runway skip here? LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL; + + // If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves + doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollStopped, this)); + return true; } bool timed_out = isTimedOut(); From 82a93ee7c7b01c6e3405eae57bf6133309853d1a Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 30 Jan 2025 00:10:33 +0100 Subject: [PATCH 7/8] Accurately reflect the worn status of inventory items (the reasons for why this was needed have been resolved in previous commits) --- indra/newview/llinventoryfunctions.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1ccefa3212..c8d85952ba 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -606,12 +606,6 @@ bool get_is_item_worn(const LLUUID& id, const LLViewerInventoryItem* item) return false; } - // Consider the item as worn if it has links in COF. - if (LLAppearanceMgr::instance().isLinkedInCOF(id)) - { - return true; - } - switch(item->getType()) { case LLAssetType::AT_OBJECT: From 3fab1306eeb2cc516c14ed84a959c0c944850918 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 30 Jan 2025 00:13:12 +0100 Subject: [PATCH 8/8] Attaching a rezzed object incorrectly delays attachment link creation by 5 seconds --- indra/newview/llattachmentsmgr.cpp | 3 +++ indra/newview/llselectmgr.cpp | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index e27d6fb1f5..f73d4241c9 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -89,6 +89,9 @@ void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id, void LLAttachmentsMgr::onAttachmentRequested(const LLUUID& item_id) { + if (item_id.isNull()) + return; + LLViewerInventoryItem *item = gInventory.getItem(item_id); LL_DEBUGS("Avatar") << "ATT attachment was requested " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index fbf5aa84d8..a5bbd62eb5 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2969,7 +2969,6 @@ void LLSelectMgr::logNoOp(LLSelectNode* node, void *) // static void LLSelectMgr::logAttachmentRequest(LLSelectNode* node, void *) { - LLAttachmentsMgr::instance().onAttachmentRequested(node->mItemID); } // static