summaryrefslogtreecommitdiff
path: root/indra/newview/llattachmentsmgr.cpp
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@lindenlab.com>2026-08-17 20:30:20 -0400
committerGitHub <noreply@github.com>2026-08-17 20:30:20 -0400
commit18648fc51e2a0c750182d8aa3814ed5b6bf8445e (patch)
tree0517959512fc0d6876780641da88b74dd72aec5b /indra/newview/llattachmentsmgr.cpp
parent6d4c4c029ce43aa413266135829cd2bc00001890 (diff)
parent932e8ac318eb2e29ea519249348315b50c7d1d58 (diff)
Merge pull request #5638 from secondlife/release/26.3
Release/26.3
Diffstat (limited to 'indra/newview/llattachmentsmgr.cpp')
-rw-r--r--indra/newview/llattachmentsmgr.cpp146
1 files changed, 59 insertions, 87 deletions
diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp
index 8b5db2c0fa..f73d4241c9 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)
{
}
@@ -80,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;
@@ -113,8 +125,6 @@ void LLAttachmentsMgr::onIdle()
expireOldDetachRequests();
- checkInvalidCOFLinks();
-
spamStatusInfo();
}
@@ -222,6 +232,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 +283,49 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
}
if (ids_to_link.size())
{
- LLPointer<LLInventoryCallback> cb = new LLRequestServerAppearanceUpdateOnDestroy();
- for (uuid_vec_t::const_iterator uuid_it = ids_to_link.begin();
- uuid_it != ids_to_link.end(); ++uuid_it)
+ LLPointer<LLInventoryCallback> 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<LLUUID>& 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 +454,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 +477,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 +485,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; i<item_array.size(); i++)
- {
- const LLViewerInventoryItem* inv_item = item_array.at(i).get();
- const LLUUID& item_id = inv_item->getLinkedUUID();
- 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()
{