FIRE-34084: Restore minimal set of appearance fixes

master
Kitty Barnett 2025-06-12 20:39:58 +02:00
parent d44b21065d
commit 6368d112c9
6 changed files with 356 additions and 150 deletions

View File

@ -709,12 +709,15 @@ public:
void onFetchCompletion();
bool isFetchCompleted();
bool isTimedOut();
// [SL:KB] - Appearance-Fixes
bool pollStopped();
// [/SL:KB]
void checkMissingWearables();
bool pollMissingWearables();
bool isMissingCompleted();
void recoverMissingWearable(LLWearableType::EType type);
void clearCOFLinksForMissingWearables();
// void clearCOFLinksForMissingWearables();
void onWearableAssetFetch(LLViewerWearable *wearable);
void onAllComplete();
@ -723,7 +726,7 @@ public:
found_list_t& getFoundList();
void eraseTypeToLink(LLWearableType::EType type);
void eraseTypeToRecover(LLWearableType::EType type);
void setObjItems(const LLInventoryModel::item_array_t& items);
// void setObjItems(const LLInventoryModel::item_array_t& items);
void setGestItems(const LLInventoryModel::item_array_t& items);
bool isMostRecent();
void handleLateArrivals();
@ -733,7 +736,7 @@ public:
private:
found_list_t mFoundList;
LLInventoryModel::item_array_t mObjItems;
// LLInventoryModel::item_array_t mObjItems;
LLInventoryModel::item_array_t mGestItems;
typedef std::set<S32> type_set_t;
type_set_t mTypesToRecover;
@ -810,10 +813,10 @@ void LLWearableHoldingPattern::eraseTypeToRecover(LLWearableType::EType type)
mTypesToRecover.erase(type);
}
void LLWearableHoldingPattern::setObjItems(const LLInventoryModel::item_array_t& items)
{
mObjItems = items;
}
//void LLWearableHoldingPattern::setObjItems(const LLInventoryModel::item_array_t& items)
//{
// mObjItems = items;
//}
void LLWearableHoldingPattern::setGestItems(const LLInventoryModel::item_array_t& items)
{
@ -920,55 +923,55 @@ 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);
// 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);
// // 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())
@ -1006,6 +1009,12 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
{
// runway skip here?
LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
// [SL:KB] - Appearance-Fixes
// 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;
// [/SL:KB]
}
bool completed = isFetchCompleted();
@ -1035,6 +1044,11 @@ void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, L
{
LL_WARNS() << "HP " << holder->index() << " skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
// runway skip here?
// [SL:KB] - Appearance-Fixes
// If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves
return;
// [/SL:KB]
}
LL_INFOS("Avatar") << "HP " << holder->index() << " recovered item link for type " << type << LL_ENDL;
@ -1126,19 +1140,32 @@ bool LLWearableHoldingPattern::isMissingCompleted()
return mTypesToLink.size()==0 && mTypesToRecover.size()==0;
}
void LLWearableHoldingPattern::clearCOFLinksForMissingWearables()
// [SL:KB] - Appearance-Fixes
bool LLWearableHoldingPattern::pollStopped()
{
for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it)
// We have to keep on polling until we're sure that all callbacks have completed or they'll cause a crash
if (isFetchCompleted() && isMissingCompleted())
{
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);
}
delete this;
return true;
}
return false;
}
// [/SL:KB]
//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()
{
@ -1146,6 +1173,12 @@ bool LLWearableHoldingPattern::pollMissingWearables()
{
// runway skip here?
LL_WARNS() << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << LL_ENDL;
// [SL:KB] - Appearance-Fixes
// 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;
// [/SL:KB]
}
bool timed_out = isTimedOut();
@ -2840,12 +2873,12 @@ 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);
// [SL:KB] - Patch: Apperance-Misc | Checked: 2010-11-24 (Catznip-2.4)
// [SL:KB] - Appearance-Fixes
// 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, LLAgentWearables::MAX_CLOTHING_LAYERS, LLAgentWearables::MAX_CLOTHING_LAYERS);
filterWearableItems(wear_items, 0, LLAgentWearables::MAX_CLOTHING_LAYERS);
// [/SL:KB]
dumpItemArray(wear_items,"asset_dump: wear_item");
@ -2858,6 +2891,79 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
<< " descendent_count " << cof->getDescendentCount()
<< " viewer desc count " << cof->getViewerDescendentCount() << LL_ENDL;
}
// [SL:KB] - Appearance-Fixes
// 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<LLUUID> 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;
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.
// (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.
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);
}
// [/SL:KB]
if(!wear_items.size())
{
LLNotificationsUtil::add("CouldNotPutOnOutfit");
@ -2872,7 +2978,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
LLTimer hp_block_timer;
LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
holder->setObjItems(obj_items);
// holder->setObjItems(obj_items);
holder->setGestItems(gest_items);
// Note: can't do normal iteration, because if all the
@ -4603,6 +4709,9 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nul
if (!cb)
cb = new LLUpdateAppearanceOnDestroy(true, true, post_update_func);
removeCOFItemLinks(linked_item_id, cb, immediate_delete);
// [SL:KB] - Appearance-Fixes
LLAttachmentsMgr::instance().clearPendingAttachmentLink(linked_item_id);
// [/SL:KB]
addDoomedTempAttachment(linked_item_id);
}
// [/RLVa:KB]

View File

@ -155,6 +155,9 @@ public:
// Attachment link management
void unregisterAttachment(const LLUUID& item_id);
void registerAttachment(const LLUUID& item_id);
// [SL:KB] - Appearance-Fixes
bool getAttachmentInvLinkEnable() const { return mAttachmentInvLinkEnabled; }
// [/SL:KB]
void setAttachmentInvLinkEnable(bool val);
// Add COF link to individual item.

View File

@ -46,10 +46,25 @@ const F32 MAX_ATTACHMENT_REQUEST_LIFETIME = 30.0F;
const F32 MIN_RETRY_REQUEST_TIME = 5.0F;
const F32 MAX_BAD_COF_TIME = 30.0F;
// [SL:KB] - Appearance-Fixes
class LLRegisterAttachmentCallback : public LLRequestServerAppearanceUpdateOnDestroy
{
public:
void fire(const LLUUID& item_id) override
{
LLAttachmentsMgr::instance().onRegisterAttachmentComplete(item_id);
LLRequestServerAppearanceUpdateOnDestroy::fire(item_id);
}
};
// [/SL:KB]
LLAttachmentsMgr::LLAttachmentsMgr():
mAttachmentRequests("attach",MIN_RETRY_REQUEST_TIME),
mDetachRequests("detach",MIN_RETRY_REQUEST_TIME),
mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME)
// [SL:KB] - Appearance-Fixes
mDetachRequests("detach",MIN_RETRY_REQUEST_TIME)
// [/SL:KB]
// mDetachRequests("detach",MIN_RETRY_REQUEST_TIME),
// mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME)
{
}
@ -66,6 +81,11 @@ void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id,
const bool add, const bool fRlvForce /*=false*/)
// [/RLVa:KB]
{
// [SL:KB] - Appearance-Fixes
if (item_id.isNull())
return;
// [/SL:KB]
LLViewerInventoryItem *item = gInventory.getItem(item_id);
if (mAttachmentRequests.wasRequestedRecently(item_id))
@ -142,7 +162,7 @@ void LLAttachmentsMgr::onIdle()
expireOldDetachRequests();
checkInvalidCOFLinks();
// checkInvalidCOFLinks();
spamStatusInfo();
}
@ -254,6 +274,13 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
{
if (mRecentlyArrivedAttachments.size())
{
// [SL:KB] - Appearance-Fixes
if (!LLAppearanceMgr::instance().getAttachmentInvLinkEnable())
{
return;
}
// [/SL:KB]
// One or more attachments have arrived but have not yet been
// processed for COF links
if (mAttachmentRequests.empty())
@ -300,17 +327,59 @@ 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)
// [SL:KB] - Appearance-Fixes
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);
}
}
// [/SL:KB]
// 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)
// {
// LLAppearanceMgr::instance().addCOFItemLink(*uuid_it, cb);
// }
}
mRecentlyArrivedAttachments.clear();
}
}
// [SL:KB] - Appearance-Fixes
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);
}
}
}
// [/SL:KB]
LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes(const std::string& op_name, F32 timeout):
mOpName(op_name),
mTimeout(timeout)
@ -439,6 +508,10 @@ void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id)
void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id)
{
// [SL:KB] - Appearance-Fixes
clearPendingAttachmentLink(inv_item_id);
// [/SL:KB]
LLTimer timer;
LLInventoryItem *item = gInventory.getItem(inv_item_id);
if (mDetachRequests.getTime(inv_item_id, timer))
@ -461,9 +534,9 @@ 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);
// 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
@ -472,81 +545,85 @@ 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.
// [SL:KB] - Appearance-Fixes
&& mPendingAttachLinks.empty();
}
// [/SL:KB]
// && mQuestionableCOFLinks.empty();
//}
//
// 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.
//// 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);
// }
// }
// }
//
// 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;
}
}
}
// 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;
// }
// }
//}
void LLAttachmentsMgr::spamStatusInfo()
{

View File

@ -90,11 +90,21 @@ public:
void onDetachRequested(const LLUUID& inv_item_id);
void onDetachCompleted(const LLUUID& inv_item_id);
// [SL:KB] - Appearance-Fixes
void clearPendingAttachmentLink(const LLUUID& idItem);
bool getPendingAttachments(std::set<LLUUID>& ids) const;
// [/SL:KB]
bool isAttachmentStateComplete() const;
// [SL:KB] - Patch: Appearance-PhantomAttach | Checked: Catznip-5.0
void refreshAttachments();
// [SL:KB] - Appearance-Fixes
protected:
void onRegisterAttachmentComplete(const LLUUID& id_item_link);
friend class LLRegisterAttachmentCallback;
// [/SL:KB]
private:
class LLItemRequestTimes: public std::map<LLUUID,LLTimer>
@ -117,7 +127,7 @@ private:
void linkRecentlyArrivedAttachments();
void expireOldAttachmentRequests();
void expireOldDetachRequests();
void checkInvalidCOFLinks();
// void checkInvalidCOFLinks();
void spamStatusInfo();
// Attachments that we are planning to rez but haven't requested from the server yet.
@ -133,8 +143,12 @@ private:
std::set<LLUUID> mRecentlyArrivedAttachments;
LLTimer mCOFLinkBatchTimer;
// Attachments that are linked in the COF but may be invalid.
LLItemRequestTimes mQuestionableCOFLinks;
// [Sl:KB] - Appearance-Fixes
// Attachments that have pending COF link creation
std::set<LLUUID> mPendingAttachLinks;
// [/SL:KB]
// // Attachments that are linked in the COF but may be invalid.
// LLItemRequestTimes mQuestionableCOFLinks;
};
#endif

View File

@ -3115,7 +3115,7 @@ void LLSelectMgr::logNoOp(LLSelectNode* node, void *)
// static
void LLSelectMgr::logAttachmentRequest(LLSelectNode* node, void *)
{
LLAttachmentsMgr::instance().onAttachmentRequested(node->mItemID);
// LLAttachmentsMgr::instance().onAttachmentRequested(node->mItemID);
}
// static

View File

@ -9630,7 +9630,10 @@ bool LLVOAvatar::processFullyLoadedChange(bool loading)
bool LLVOAvatar::isFullyLoaded() const
{
return (mRenderUnloadedAvatar || mFullyLoaded);
// [SL:KB] - Appearance-Fixes
return (mRenderUnloadedAvatar && !isSelf()) || mFullyLoaded;
// [/SL:KB]
// return (mRenderUnloadedAvatar || mFullyLoaded);
}
bool LLVOAvatar::hasFirstFullAttachmentData() const