More of the last, this time update llattachmentsmgr.cpp to the latest.

Hopefully it'll compile now?
This commit is contained in:
Lirusaito
2016-05-26 11:03:08 -04:00
parent 3bedb5f6d4
commit a388ddb0d0
6 changed files with 763 additions and 232 deletions

View File

@@ -27,11 +27,13 @@
#include "llviewerprecompiledheaders.h"
#include "llagentwearables.h"
#include "llattachmentsmgr.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "llagentwearablesfetch.h"
#include "llappearancemgr.h"
#include "llcallbacklist.h"
#include "llfloatercustomize.h"
#include "llfolderview.h"
#include "llgesturemgr.h"
#include "llinventorybridge.h"
@@ -51,7 +53,6 @@
#include "llwearablelist.h"
#include "lllocaltextureobject.h"
#include "llfloatercustomize.h"
#include "llfloaterperms.h"
@@ -246,7 +247,7 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
*
* Would like to pass the agent in here, but we can't safely
* count on it being around later. Just use gAgent directly.
* @param cb callback to execute on completion (??? unused ???)
* @param cb callback to execute on completion (? unused ?)
* @param type Type for the wearable in the agent
* @param wearable The wearable data.
* @param todo Bitmask of actions to take on completion.
@@ -413,7 +414,6 @@ void LLAgentWearables::sendAgentWearablesUpdate()
void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update,
const std::string new_name)
{
//llassert_always(index == 0);
LLViewerWearable* old_wearable = getViewerWearable(type, index);
if(!old_wearable) return;
bool name_changed = !new_name.empty() && (new_name != old_wearable->getName());
@@ -641,7 +641,6 @@ void LLAgentWearables::nameOrDescriptionChanged(LLUUID const& item_id)
BOOL LLAgentWearables::isWearableModifiable(LLWearableType::EType type, U32 index) const
{
//llassert_always(index == 0);
LLUUID item_id = getWearableItemID(type, index);
return item_id.notNull() ? isWearableModifiable(item_id) : FALSE;
}
@@ -652,7 +651,7 @@ BOOL LLAgentWearables::isWearableModifiable(const LLUUID& item_id) const
if (linked_id.notNull())
{
LLInventoryItem* item = gInventory.getItem(linked_id);
if(item && item->getPermissions().allowModifyBy(gAgent.getID(),
if (item && item->getPermissions().allowModifyBy(gAgent.getID(),
gAgent.getGroupID()))
{
return TRUE;
@@ -663,12 +662,11 @@ BOOL LLAgentWearables::isWearableModifiable(const LLUUID& item_id) const
BOOL LLAgentWearables::isWearableCopyable(LLWearableType::EType type, U32 index) const
{
//llassert_always(index == 0);
LLUUID item_id = getWearableItemID(type, index);
if (!item_id.isNull())
{
LLInventoryItem* item = gInventory.getItem(item_id);
if(item && item->getPermissions().allowCopyBy(gAgent.getID(),
if (item && item->getPermissions().allowCopyBy(gAgent.getID(),
gAgent.getGroupID()))
{
return TRUE;
@@ -681,24 +679,23 @@ BOOL LLAgentWearables::isWearableCopyable(LLWearableType::EType type, U32 index)
U32 LLAgentWearables::getWearablePermMask(LLWearableType::EType type)
{
LLUUID item_id = getWearableItemID(type);
if(!item_id.isNull())
if (!item_id.isNull())
{
LLInventoryItem* item = gInventory.getItem(item_id);
if(item)
if (item)
{
return item->getPermissions().getMaskOwner();
}
}
return PERM_NONE;
}
}
*/
LLInventoryItem* LLAgentWearables::getWearableInventoryItem(LLWearableType::EType type, U32 index)
{
//llassert_always(index == 0);
LLUUID item_id = getWearableItemID(type,index);
LLInventoryItem* item = NULL;
if(item_id.notNull())
if (item_id.notNull())
{
item = gInventory.getItem(item_id);
}
@@ -785,8 +782,7 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
{
if (isAgentAvatarValid())
{
const BOOL upload_result = removed;
gAgentAvatarp->wearableUpdated(wearable->getType(), upload_result);
gAgentAvatarp->wearableUpdated(wearable->getType(), removed);
}
LLWearableData::wearableUpdated(wearable, removed);
@@ -821,7 +817,6 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
checkWearableAgainstInventory(viewer_wearable);
}
}
@@ -1225,7 +1220,6 @@ void LLAgentWearables::createStandardWearablesAllDone()
LL_INFOS() << "all done?" << LL_ENDL;
mWearablesLoaded = TRUE;
checkWearablesLoaded();
notifyLoadingFinished();
updateServer();
@@ -1340,14 +1334,13 @@ bool LLAgentWearables::onRemoveWearableDialog(const LLSD& notification, const LL
// Called by removeWearable() and onRemoveWearableDialog() to actually do the removal.
void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_remove_all, U32 index)
{
//llassert_always(index == 0);
//LLAgentDumper dumper("removeWearable");
if (do_remove_all)
{
S32 max_entry = getWearableCount(type)-1;
for (S32 i=max_entry; i>=0; i--)
{
LLViewerWearable* old_wearable = getViewerWearable(type,i);
//queryWearableCache(); // moved below
if (old_wearable)
{
eraseWearable(old_wearable);
@@ -1363,7 +1356,6 @@ void LLAgentWearables::removeWearableFinal( LLWearableType::EType type, bool do_
else
{
LLViewerWearable* old_wearable = getViewerWearable(type, index);
//queryWearableCache(); // moved below
if (old_wearable)
{
@@ -1459,7 +1451,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
<< curr_wearable->getName() << " vs " << new_item->getName()
<< " item ids " << curr_wearable->getItemID() << " vs " << new_item->getUUID()
<< LL_ENDL;
mismatched++;
update_inventory = TRUE;
continue;
}
#endif
@@ -1488,6 +1480,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
return;
}
// updating inventory
// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later
// note: shirt is the first non-body part wearable item. Update if wearable order changes.
@@ -1538,7 +1531,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
// Start rendering & update the server
mWearablesLoaded = TRUE;
checkWearablesLoaded();
// [SL:KB] - Patch: Appearance-InitialWearablesLoadedCallback | Checked: 2010-09-22 (Catznip-2.2)
if (!mInitialWearablesLoaded)
{
@@ -1556,141 +1549,119 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
// User has picked "wear on avatar" from a menu.
/*void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append)
{
//LLAgentDumper dumper("setWearableItem");
if (isWearingItem(new_item->getUUID()))
{
LL_WARNS() << "wearable " << new_item->getUUID() << " is already worn" << LL_ENDL;
return;
}
const LLWearableType::EType type = new_wearable->getType();
// [RLVa:KB] - Checked: 2010-03-19 (RLVa-1.2.0a) | Modified: RLVa-1.2.0g
// TODO-RLVa: [RLVa-1.2.1] This looks like dead code in SL-2.0.2 so we can't really check to see if it works :|
if (rlv_handler_t::isEnabled())
{
ERlvWearMask eWear = gRlvWearableLocks.canWear(type);
if ( (RLV_WEAR_LOCKED == eWear) || ((!do_append) && (!(eWear & RLV_WEAR_REPLACE))) )
return;
}
// [/RLVa:KB]
if (!do_append)
{
// Remove old wearable, if any
// MULTI_WEARABLE: hardwired to 0
LLViewerWearable* old_wearable = getViewerWearable(type,0);
if( old_wearable )
{
const LLUUID& old_item_id = old_wearable->getItemID();
if( (old_wearable->getAssetID() == new_wearable->getAssetID()) &&
(old_item_id == new_item->getUUID()) )
{
LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getTypeName( type ) << LL_ENDL;
return;
}
if( old_wearable->isDirty() )
{
// Bring up modal dialog: Save changes? Yes, No, Cancel
LLSD payload;
payload["item_id"] = new_item->getUUID();
LLNotificationsUtil::add( "WearableSave", LLSD(), payload, boost::bind(onSetWearableDialog, _1, _2, new_wearable));
return;
}
}
}
setWearableFinal(new_item, new_wearable, do_append);
}*/
//void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append)
//{
// //LLAgentDumper dumper("setWearableItem");
// if (isWearingItem(new_item->getUUID()))
// {
// LL_WARNS() << "wearable " << new_item->getUUID() << " is already worn" << LL_ENDL;
// return;
// }
//
// const LLWearableType::EType type = new_wearable->getType();
//
// if (!do_append)
// {
// // Remove old wearable, if any
// // MULTI_WEARABLE: hardwired to 0
// LLViewerWearable* old_wearable = getViewerWearable(type,0);
// if (old_wearable)
// {
// const LLUUID& old_item_id = old_wearable->getItemID();
// if ((old_wearable->getAssetID() == new_wearable->getAssetID()) &&
// (old_item_id == new_item->getUUID()))
// {
// LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getTypeName(type) << LL_ENDL;
// return;
// }
//
// if (old_wearable->isDirty())
// {
// // Bring up modal dialog: Save changes? Yes, No, Cancel
// LLSD payload;
// payload["item_id"] = new_item->getUUID();
// LLNotificationsUtil::add("WearableSave", LLSD(), payload, boost::bind(onSetWearableDialog, _1, _2, new_wearable));
// return;
// }
// }
// }
//
// setWearableFinal(new_item, new_wearable, do_append);
//}
// static
bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID());
U32 index;
if (!gAgentWearables.getWearableIndex(wearable,index))
{
LL_WARNS() << "Wearable not found" << LL_ENDL;
delete wearable;
return false;
}
if( !new_item )
{
delete wearable;
return false;
}
switch( option )
{
case 0: // "Save"
gAgentWearables.saveWearable(wearable->getType(),index);
gAgentWearables.setWearableFinal( new_item, wearable );
break;
case 1: // "Don't Save"
gAgentWearables.setWearableFinal( new_item, wearable );
break;
case 2: // "Cancel"
break;
default:
llassert(0);
break;
}
delete wearable;
return false;
}
//bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLViewerWearable* wearable)
//{
// S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// LLInventoryItem* new_item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
// U32 index;
// if (!gAgentWearables.getWearableIndex(wearable,index))
// {
// LL_WARNS() << "Wearable not found" << LL_ENDL;
// delete wearable;
// return false;
// }
// switch(option)
// {
// case 0: // "Save"
// gAgentWearables.saveWearable(wearable->getType(),index);
// gAgentWearables.setWearableFinal(new_item, wearable);
// break;
//
// case 1: // "Don't Save"
// gAgentWearables.setWearableFinal(new_item, wearable);
// break;
//
// case 2: // "Cancel"
// break;
//
// default:
// llassert(0);
// break;
// }
//
// delete wearable;
// return false;
//}
// Called from setWearableItem() and onSetWearableDialog() to actually set the wearable.
// MULTI_WEARABLE: unify code after null objects are gone.
void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append)
{
const LLWearableType::EType type = new_wearable->getType();
if (do_append && getWearableItemID(type,0).notNull())
{
new_wearable->setItemID(new_item->getUUID());
const bool trigger_updated = false;
pushWearable(type, new_wearable, trigger_updated);
LL_INFOS() << "Added additional wearable for type " << type
<< " size is now " << getWearableCount(type) << LL_ENDL;
checkWearableAgainstInventory(new_wearable);
}
else
{
// Replace the old wearable with a new one.
llassert(new_item->getAssetUUID() == new_wearable->getAssetID());
LLViewerWearable *old_wearable = getViewerWearable(type,0);
LLUUID old_item_id;
if (old_wearable)
{
old_item_id = old_wearable->getItemID();
}
new_wearable->setItemID(new_item->getUUID());
setWearable(type,0,new_wearable);
if (old_item_id.notNull())
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
gInventory.notifyObservers();
}
LL_INFOS() << "Replaced current element 0 for type " << type
<< " size is now " << getWearableCount(type) << LL_ENDL;
}
//LL_INFOS() << "LLVOAvatar::setWearableItem()" << LL_ENDL;
queryWearableCache();
//new_wearable->writeToAvatar(TRUE);
updateServer();
}
//void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLViewerWearable* new_wearable, bool do_append)
//{
// const LLWearableType::EType type = new_wearable->getType();
//
// if (do_append && getWearableItemID(type,0).notNull())
// {
// new_wearable->setItemID(new_item->getUUID());
// const bool trigger_updated = false;
// pushWearable(type, new_wearable, trigger_updated);
// LL_INFOS() << "Added additional wearable for type " << type
// << " size is now " << getWearableCount(type) << LL_ENDL;
// checkWearableAgainstInventory(new_wearable);
// }
// else
// {
// // Replace the old wearable with a new one.
// llassert(new_item->getAssetUUID() == new_wearable->getAssetID());
//
// LLViewerWearable *old_wearable = getViewerWearable(type,0);
// LLUUID old_item_id;
// if (old_wearable)
// {
// old_item_id = old_wearable->getItemID();
// }
// new_wearable->setItemID(new_item->getUUID());
// setWearable(type,0,new_wearable);
//
// if (old_item_id.notNull())
// {
// gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
// gInventory.notifyObservers();
// }
// LL_INFOS() << "Replaced current element 0 for type " << type
// << " size is now " << getWearableCount(type) << LL_ENDL;
// }
//}
void LLAgentWearables::queryWearableCache()
{
@@ -1749,17 +1720,28 @@ void LLAgentWearables::queryWearableCache()
}
}
// virtual
void LLAgentWearables::invalidateBakedTextureHash(LLMD5& hash) const
{
// Add some garbage into the hash so that it becomes invalid.
if (isAgentAvatarValid())
{
hash.update((const unsigned char*)gAgentAvatarp->getID().mData, UUID_BYTES);
}
}
// User has picked "remove from avatar" from a menu.
// static
//void LLAgentWearables::userRemoveWearable(const LLWearableType::EType &type, const U32 &index)
//{
// if (!(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES)) //&&
// //!((!gAgent.isTeen()) && (type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT)))
// {
// gAgentWearables.removeWearable(type,false,index);
// }
//}
/// Given a desired set of attachments, find what objects need to be
//static
//void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &type)
//{
// if (!(type==LLWearableType::WT_SHAPE || type==LLWearableType::WT_SKIN || type==LLWearableType::WT_HAIR || type==LLWearableType::WT_EYES)) //&&
// //!((!gAgent.isTeen()) && (type==LLWearableType::WT_UNDERPANTS || type==LLWearableType::WT_UNDERSHIRT)))
// {
// gAgentWearables.removeWearable(type,true,0);
// }
//}
// Given a desired set of attachments, find what objects need to be
// removed, and what additional inventory items need to be added.
void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array,
llvo_vec_t& objects_to_remove,
@@ -1859,7 +1841,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo
itObj = objects_to_remove.erase(itObj);
// Fall-back code: re-add the attachment if it got removed from COF somehow (compensates for possible bugs elsewhere)
bool fInCOF = LLAppearanceMgr::isLinkInCOF(pAttachObj->getAttachmentItemID());
bool fInCOF = LLAppearanceMgr::instance().isLinkedInCOF(pAttachObj->getAttachmentItemID());
RLV_ASSERT(fInCOF);
if (!fInCOF)
{
@@ -1877,6 +1859,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo
if (objects_to_remove.empty())
return;
LL_DEBUGS("Avatar") << "ATT [ObjectDetach] removing " << objects_to_remove.size() << " objects" << LL_ENDL;
gMessageSystem->newMessage("ObjectDetach");
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -1887,8 +1870,13 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo
++it)
{
LLViewerObject *objectp = *it;
//gAgentAvatarp->resetJointPositionsOnDetach(objectp);
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());
const LLUUID& item_id = objectp->getAttachmentItemID();
LLViewerInventoryItem *item = gInventory.getItem(item_id);
LL_DEBUGS("Avatar") << "ATT removing object, item is " << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL;
LLAttachmentsMgr::instance().onDetachRequested(item_id);
}
gMessageSystem->sendReliable(gAgent.getRegionHost());
}
@@ -1960,24 +1948,21 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra
// End of message chunk
msg->sendReliable( gAgent.getRegion()->getHost() );
}
}
for(LLInventoryModel::item_array_t::const_iterator it = obj_item_array.begin();
it != obj_item_array.end();
++it)
{
const LLInventoryItem* item = *it;
LLAttachmentsMgr::instance().addAttachmentRequest(item->getLinkedUUID(), 0, TRUE);
}
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1)
sInitialAttachmentsRequested = true;
// [/RLVa:KB]
}
void LLAgentWearables::checkWearablesLoaded() const
{
#ifdef SHOW_ASSERT
U32 item_pend_count = itemUpdatePendingCount();
if (mWearablesLoaded)
{
llassert(item_pend_count==0);
}
#endif
}
// Returns false if the given wearable is already topmost/bottommost
// (depending on closer_to_body parameter).
bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_body) const
@@ -1994,7 +1979,6 @@ bool LLAgentWearables::canMoveWearable(const LLUUID& item_id, bool closer_to_bod
BOOL LLAgentWearables::areWearablesLoaded() const
{
checkWearablesLoaded();
return mWearablesLoaded;
}

View File

@@ -170,7 +170,6 @@ public:
protected:
/*virtual*/ void invalidateBakedTextureHash(LLMD5& hash) const;
void sendAgentWearablesUpdate();
void sendAgentWearablesRequest();
void queryWearableCache();

View File

@@ -2588,6 +2588,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
<< " descendent_count " << cof->getDescendentCount()
<< " viewer desc count " << cof->getViewerDescendentCount() << LL_ENDL;
}
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2)
// Update attachments to match those requested.
if (isAgentAvatarValid())

View File

@@ -27,7 +27,9 @@
#include "llviewerprecompiledheaders.h"
#include "llattachmentsmgr.h"
#include "llvoavatarself.h"
#include "llagent.h"
#include "llappearancemgr.h"
#include "llinventorymodel.h"
#include "lltooldraganddrop.h" // pack_permissions_slam
#include "llviewerinventory.h"
@@ -38,7 +40,35 @@
#include "rlvlocks.h"
// [/RLVa:KB]
LLAttachmentsMgr::LLAttachmentsMgr()
const F32 COF_LINK_BATCH_TIME = 5.0F;
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] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7)
class LLRegisterAttachmentCallback : public LLRequestServerAppearanceUpdateOnDestroy
{
public:
LLRegisterAttachmentCallback()
: LLRequestServerAppearanceUpdateOnDestroy()
{
}
/*virtual*/ ~LLRegisterAttachmentCallback()
{
}
/*virtual*/ void fire(const LLUUID& idItem)
{
LLAttachmentsMgr::instance().onRegisterAttachmentComplete(idItem);
}
};
// [/SL:KB]
LLAttachmentsMgr::LLAttachmentsMgr():
mAttachmentRequests("attach",MIN_RETRY_REQUEST_TIME),
mDetachRequests("detach",MIN_RETRY_REQUEST_TIME)
// , mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME)
{
}
@@ -46,20 +76,34 @@ LLAttachmentsMgr::~LLAttachmentsMgr()
{
}
void LLAttachmentsMgr::addAttachment(const LLUUID& item_id,
const U8 attachment_pt,
//void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id,
// const U8 attachment_pt,
// const BOOL add)
// [RLVa:KB] - Checked: 2010-09-13 (RLVa-1.2.1)
void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id,
const U8 attachment_pt,
const BOOL add, const BOOL fRlvForce /*=FALSE*/)
// [/RLVa:KB]
{
LLViewerInventoryItem *item = gInventory.getItem(item_id);
if (mAttachmentRequests.wasRequestedRecently(item_id))
{
LL_DEBUGS("Avatar") << "ATT not adding attachment to mPendingAttachments, recent request is already pending: "
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
return;
}
LL_DEBUGS("Avatar") << "ATT adding attachment to mPendingAttachments "
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
AttachmentsInfo attachment;
attachment.mItemID = item_id;
attachment.mAttachmentPt = attachment_pt;
attachment.mAdd = add;
// [RLVa:KB] - Checked: 2010-09-23 (RLVa-1.2.1)
if ( (rlv_handler_t::isEnabled()) && (!fRlvForce) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) )
if ( (rlv_handler_t::isEnabled()) && (!fRlvForce) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) && (gAgentWearables.areInitialAttachmentsRequested()) )
{
const LLInventoryItem* pItem = gInventory.getItem(item_id);
if (!pItem)
@@ -78,6 +122,21 @@ void LLAttachmentsMgr::addAttachment(const LLUUID& item_id,
// [/RLVa:KB]
mPendingAttachments.push_back(attachment);
mAttachmentRequests.addTime(item_id);
}
void LLAttachmentsMgr::onAttachmentRequested(const LLUUID& item_id)
{
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7)
if (item_id.isNull())
return;
// [/SL:KB]
LLViewerInventoryItem *item = gInventory.getItem(item_id);
LL_DEBUGS("Avatar") << "ATT attachment was requested "
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
mAttachmentRequests.addTime(item_id);
}
// static
@@ -88,10 +147,55 @@ void LLAttachmentsMgr::onIdle(void *)
void LLAttachmentsMgr::onIdle()
{
if(!gAgent.getRegion())
// Make sure we got a region before trying anything else
if( !gAgent.getRegion() )
{
return;
}
S32 obj_count = mPendingAttachments.size();
if (LLApp::isExiting())
{
return;
}
requestPendingAttachments();
linkRecentlyArrivedAttachments();
expireOldAttachmentRequests();
expireOldDetachRequests();
// checkInvalidCOFLinks();
spamStatusInfo();
}
void LLAttachmentsMgr::requestPendingAttachments()
{
if (mPendingAttachments.size())
{
requestAttachments(mPendingAttachments);
}
}
// Send request(s) for a group of attachments. As coded, this can
// request at most 40 attachments and the rest will be
// ignored. Currently the max attachments per avatar is 38, so the 40
// limit should not be hit in practice.
void LLAttachmentsMgr::requestAttachments(attachments_vec_t& attachment_requests)
{
// Make sure we got a region before trying anything else
if( !gAgent.getRegion() )
{
return;
}
// For unknown reasons, requesting many attachments at once causes
// frequent server-side failures. Here we're limiting the number
// of attachments requested per idle loop.
const S32 max_objects_per_request = 5;
S32 obj_count = llmin((S32)attachment_requests.size(),max_objects_per_request);
if (obj_count == 0)
{
return;
@@ -103,18 +207,24 @@ void LLAttachmentsMgr::onIdle()
const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
if( obj_count > MAX_OBJECTS_TO_SEND )
{
LL_WARNS() << "ATT Too many attachments requested: " << obj_count
<< " exceeds limit of " << MAX_OBJECTS_TO_SEND << LL_ENDL;
obj_count = MAX_OBJECTS_TO_SEND;
}
LL_DEBUGS("Avatar") << "ATT [RezMultipleAttachmentsFromInv] attaching multiple from attachment_requests,"
" total obj_count " << obj_count << LL_ENDL;
LLUUID compound_msg_id;
compound_msg_id.generate();
LLMessageSystem* msg = gMessageSystem;
// by construction above, obj_count <= attachment_requests.size(), so no
// check against attachment_requests.empty() is needed.
llassert(obj_count <= attachment_requests.size());
S32 i = 0;
for (attachments_vec_t::const_iterator iter = mPendingAttachments.begin();
iter != mPendingAttachments.end();
++iter)
for (S32 i=0; i<obj_count; i++)
{
if( 0 == (i % OBJECTS_PER_PACKET) )
{
@@ -129,32 +239,395 @@ void LLAttachmentsMgr::onIdle()
msg->addBOOLFast(_PREHASH_FirstDetachAll, false );
}
const AttachmentsInfo &attachment = (*iter);
const AttachmentsInfo& attachment = attachment_requests.front();
LLViewerInventoryItem* item = gInventory.getItem(attachment.mItemID);
if (!item)
if (item)
{
LL_INFOS() << "Attempted to add non-existant item ID:" << attachment.mItemID << LL_ENDL;
continue;
}
S32 attachment_pt = attachment.mAttachmentPt;
if (attachment.mAdd)
attachment_pt |= ATTACHMENT_ADD;
LL_DEBUGS("Avatar") << "ATT requesting from attachment_requests " << item->getName()
<< " " << item->getLinkedUUID() << LL_ENDL;
S32 attachment_pt = attachment.mAttachmentPt;
if (attachment.mAdd)
attachment_pt |= ATTACHMENT_ADD;
msg->nextBlockFast(_PREHASH_ObjectData );
msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
msg->addStringFast(_PREHASH_Name, item->getName());
msg->addStringFast(_PREHASH_Description, item->getDescription());
msg->nextBlockFast(_PREHASH_ObjectData );
msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
msg->addStringFast(_PREHASH_Name, item->getName());
msg->addStringFast(_PREHASH_Description, item->getDescription());
}
else
{
LL_WARNS("Avatar") << "ATT Attempted to add non-existent item ID:" << attachment.mItemID << LL_ENDL;
}
if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
{
// End of message chunk
msg->sendReliable( gAgent.getRegion()->getHost() );
}
i++;
attachment_requests.pop_front();
}
mPendingAttachments.clear();
}
void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
{
if (mRecentlyArrivedAttachments.size())
{
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7)
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())
{
// Not waiting for any more.
LL_DEBUGS("Avatar") << "ATT all pending attachments have arrived after "
<< mCOFLinkBatchTimer.getElapsedTimeF32() << " seconds" << LL_ENDL;
}
else if (mCOFLinkBatchTimer.getElapsedTimeF32() > COF_LINK_BATCH_TIME)
{
LL_DEBUGS("Avatar") << "ATT " << mAttachmentRequests.size()
<< " pending attachments have not arrived, but wait time exceeded" << LL_ENDL;
}
else
{
return;
}
LL_DEBUGS("Avatar") << "ATT checking COF linkability for " << mRecentlyArrivedAttachments.size()
<< " recently arrived items" << LL_ENDL;
uuid_vec_t ids_to_link;
for (std::set<LLUUID>::iterator it = mRecentlyArrivedAttachments.begin();
it != mRecentlyArrivedAttachments.end(); ++it)
{
if (isAgentAvatarValid() &&
gAgentAvatarp->isWearingAttachment(*it) &&
!LLAppearanceMgr::instance().isLinkedInCOF(*it))
{
LLUUID item_id = *it;
LLViewerInventoryItem *item = gInventory.getItem(item_id);
LL_DEBUGS("Avatar") << "ATT adding COF link for attachment "
<< (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL;
ids_to_link.push_back(item_id);
}
}
if (ids_to_link.size())
{
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2015-06-24 (Catznip-3.7)
LLPointer<LLInventoryCallback> cb = new LLRegisterAttachmentCallback();
for (const LLUUID& idAttach : ids_to_link)
{
if (std::find(mPendingAttachLinks.begin(), mPendingAttachLinks.end(), idAttach) == mPendingAttachLinks.end())
{
LLAppearanceMgr::instance().addCOFItemLink(idAttach, cb);
mPendingAttachLinks.insert(idAttach);
}
}
// [/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] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.2)
bool LLAttachmentsMgr::getPendingAttachments(std::set<LLUUID>& ids) const
{
ids.clear();
// Returns the union of the LL maintained list of attachments that are waiting for link creation and our maintained list of attachments that are pending link creation
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& idAttachLink)
{
const LLViewerInventoryItem* pAttachLink = gInventory.getItem(idAttachLink);
if (!pAttachLink)
return;
const LLUUID& idAttachBase = pAttachLink->getLinkedUUID();
// Remove the attachment from the pending list
clearPendingAttachmentLink(idAttachBase);
// It may have been detached already in which case we should remove the COF link
if ( (isAgentAvatarValid()) && (!gAgentAvatarp->isWearingAttachment(idAttachBase)) )
{
LLAppearanceMgr::instance().removeCOFItemLinks(idAttachBase, NULL, true);
}
}
// [/SL:KB]
LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes(const std::string& op_name, F32 timeout):
mOpName(op_name),
mTimeout(timeout)
{
}
void LLAttachmentsMgr::LLItemRequestTimes::addTime(const LLUUID& inv_item_id)
{
LLInventoryItem *item = gInventory.getItem(inv_item_id);
LL_DEBUGS("Avatar") << "ATT " << mOpName << " adding request time " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL;
LLTimer current_time;
(*this)[inv_item_id] = current_time;
}
void LLAttachmentsMgr::LLItemRequestTimes::removeTime(const LLUUID& inv_item_id)
{
LLInventoryItem *item = gInventory.getItem(inv_item_id);
S32 remove_count = (*this).erase(inv_item_id);
if (remove_count)
{
LL_DEBUGS("Avatar") << "ATT " << mOpName << " removing request time "
<< (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL;
}
}
BOOL LLAttachmentsMgr::LLItemRequestTimes::getTime(const LLUUID& inv_item_id, LLTimer& timer) const
{
std::map<LLUUID,LLTimer>::const_iterator it = (*this).find(inv_item_id);
if (it != (*this).end())
{
timer = it->second;
return TRUE;
}
return FALSE;
}
BOOL LLAttachmentsMgr::LLItemRequestTimes::wasRequestedRecently(const LLUUID& inv_item_id) const
{
LLTimer request_time;
if (getTime(inv_item_id, request_time))
{
F32 request_time_elapsed = request_time.getElapsedTimeF32();
return request_time_elapsed < mTimeout;
}
else
{
return FALSE;
}
}
// If we've been waiting for an attachment a long time, we want to
// forget the request, because if the request is invalid (say the
// object does not exist), the existence of a request that never goes
// away will gum up the COF batch logic, causing it to always wait for
// the timeout. Expiring a request means if the item does show up
// late, the COF link request may not get properly batched up, but
// behavior will be no worse than before we had the batching mechanism
// in place; the COF link will still be created, but extra
// requestServerAppearanceUpdate() calls may occur.
void LLAttachmentsMgr::expireOldAttachmentRequests()
{
for (std::map<LLUUID,LLTimer>::iterator it = mAttachmentRequests.begin();
it != mAttachmentRequests.end(); )
{
std::map<LLUUID,LLTimer>::iterator curr_it = it;
++it;
if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME)
{
LLInventoryItem *item = gInventory.getItem(curr_it->first);
LL_WARNS("Avatar") << "ATT expiring request for attachment "
<< (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first
<< " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL;
mAttachmentRequests.erase(curr_it);
}
}
}
void LLAttachmentsMgr::expireOldDetachRequests()
{
for (std::map<LLUUID,LLTimer>::iterator it = mDetachRequests.begin();
it != mDetachRequests.end(); )
{
std::map<LLUUID,LLTimer>::iterator curr_it = it;
++it;
if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME)
{
LLInventoryItem *item = gInventory.getItem(curr_it->first);
LL_WARNS("Avatar") << "ATT expiring request for detach "
<< (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first
<< " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL;
mDetachRequests.erase(curr_it);
}
}
}
// When an attachment arrives, we want to stop waiting for it, and add
// it to the set of recently arrived items.
void LLAttachmentsMgr::onAttachmentArrived(const LLUUID& inv_item_id)
{
LLTimer timer;
bool expected = mAttachmentRequests.getTime(inv_item_id, timer);
if (!expected)
{
LLInventoryItem *item = gInventory.getItem(inv_item_id);
LL_WARNS() << "ATT Attachment was unexpected or arrived after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds: "
<< (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL;
}
mAttachmentRequests.removeTime(inv_item_id);
if (expected && mAttachmentRequests.empty())
{
// mAttachmentRequests just emptied out
LL_DEBUGS("Avatar") << "ATT all active attachment requests have completed" << LL_ENDL;
}
if (mRecentlyArrivedAttachments.empty())
{
// Start the timer for sending off a COF link batch.
mCOFLinkBatchTimer.reset();
}
mRecentlyArrivedAttachments.insert(inv_item_id);
}
void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id)
{
mDetachRequests.addTime(inv_item_id);
}
void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id)
{
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-10-05 (Catznip-2.2)
// (mRecentlyArrivedAttachments doesn't need pruning since it'll check the attachment is actually worn before linking)
clearPendingAttachmentLink(inv_item_id);
// [/SL:KB]
LLTimer timer;
LLInventoryItem *item = gInventory.getItem(inv_item_id);
if (mDetachRequests.getTime(inv_item_id, timer))
{
LL_DEBUGS("Avatar") << "ATT detach completed after " << timer.getElapsedTimeF32()
<< " seconds for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL;
mDetachRequests.removeTime(inv_item_id);
if (mDetachRequests.empty())
{
LL_DEBUGS("Avatar") << "ATT all detach requests have completed" << LL_ENDL;
}
}
else
{
LL_WARNS() << "ATT unexpected detach for "
<< (item ? item->getName() : "UNKNOWN") << " id " << 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);
}
// 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()
//{
// 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;
// }
// }
//}
void LLAttachmentsMgr::spamStatusInfo()
{
#if 0
static LLTimer spam_timer;
const F32 spam_frequency = 100.0F;
if (spam_timer.getElapsedTimeF32() > spam_frequency)
{
spam_timer.reset();
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();
if (inv_item->getType() == LLAssetType::AT_OBJECT)
{
LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID()
<< " linked_item_id: " << inv_item->getLinkedUUID()
<< " name: " << inv_item->getName()
<< " parent: " << inv_item->getParentUUID()
<< LL_ENDL;
}
}
}
#endif
}

View File

@@ -32,45 +32,120 @@
class LLViewerInventoryItem;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//--------------------------------------------------------------------------------
// LLAttachmentsMgr
//
// The sole purpose of this class is to take attachment
// requests, queue them up, and send them all at once.
// This handles situations where the viewer may request
// a bunch of attachments at once in a short period of
// time, where each of the requests would normally be
// sent as a separate message versus being batched into
// one single message.
// This class manages batching up of requests at two stages of
// attachment rezzing.
//
// The intent of this batching is to reduce viewer->server
// traffic.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// First, attachments requested to rez get saved in
// mPendingAttachments and sent as a single
// RezMultipleAttachmentsFromInv request. This batching is needed
// mainly because of weaknessing the UI element->inventory item
// handling, such that we don't always know when we are requesting
// multiple items. Now they just pile up and get swept into a single
// request during the idle loop.
//
// Second, after attachments arrive, we need to generate COF links for
// them. There are both efficiency and UI correctness reasons why it
// is better to request all the COF links at once and run a single
// callback after they all complete. Given the vagaries of the
// attachment system, there is no guarantee that we will get all the
// attachments we ask for, but we frequently do. So in the common case
// that all the desired attachments arrive fairly quickly, we generate
// a single batched request for COF links. If attachments arrive late
// or not at all, we will still issue COF link requests once a timeout
// value has been exceeded.
//
// To handle attachments that never arrive, we forget about requests
// that exceed a timeout value.
//--------------------------------------------------------------------------------
class LLAttachmentsMgr: public LLSingleton<LLAttachmentsMgr>
{
public:
LLAttachmentsMgr();
virtual ~LLAttachmentsMgr();
void addAttachment(const LLUUID& item_id,
const U8 attachment_pt,
// const BOOL add);
// [RLVa:KB] - Checked: 2010-09-13 (RLVa-1.2.1c) | Added: RLVa-1.2.1c
const BOOL add, const BOOL fRlvForce = FALSE);
// [/RLVa:KB]
static void onIdle(void *);
protected:
void onIdle();
private:
// Stores info for attachments that will be requested during idle.
struct AttachmentsInfo
{
LLUUID mItemID;
U8 mAttachmentPt;
BOOL mAdd;
};
typedef std::deque<AttachmentsInfo> attachments_vec_t;
typedef std::vector<AttachmentsInfo> attachments_vec_t;
LLAttachmentsMgr();
virtual ~LLAttachmentsMgr();
// [RLVa:KB] - Checked: 2010-09-13 (RLVa-1.2.1)
void addAttachmentRequest(const LLUUID& item_id,
const U8 attachment_pt,
const BOOL add, const BOOL fRlvForce = FALSE);
// [/RLVa:KB]
// void addAttachmentRequest(const LLUUID& item_id,
// const U8 attachment_pt,
// const BOOL add);
void onAttachmentRequested(const LLUUID& item_id);
void requestAttachments(attachments_vec_t& attachment_requests);
static void onIdle(void *);
void onAttachmentArrived(const LLUUID& inv_item_id);
void onDetachRequested(const LLUUID& inv_item_id);
void onDetachCompleted(const LLUUID& inv_item_id);
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.1)
public:
void clearPendingAttachmentLink(const LLUUID& idItem);
bool getPendingAttachments(std::set<LLUUID>& ids) const;
protected:
void onRegisterAttachmentComplete(const LLUUID& idAttachLink);
friend class LLRegisterAttachmentCallback;
// [/SL:KB]
private:
class LLItemRequestTimes: public std::map<LLUUID,LLTimer>
{
public:
LLItemRequestTimes(const std::string& op_name, F32 timeout);
void addTime(const LLUUID& inv_item_id);
void removeTime(const LLUUID& inv_item_id);
BOOL wasRequestedRecently(const LLUUID& item_id) const;
BOOL getTime(const LLUUID& inv_item_id, LLTimer& timer) const;
private:
F32 mTimeout;
std::string mOpName;
};
void removeAttachmentRequestTime(const LLUUID& inv_item_id);
void onIdle();
void requestPendingAttachments();
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.
attachments_vec_t mPendingAttachments;
// Attachments that have been requested from server but have not arrived yet.
LLItemRequestTimes mAttachmentRequests;
// Attachments that have been requested to detach but have not gone away yet.
LLItemRequestTimes mDetachRequests;
// Attachments that have arrived but have not been linked in the COF yet.
std::set<LLUUID> mRecentlyArrivedAttachments;
LLTimer mCOFLinkBatchTimer;
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.1)
// Attachments that have pending link creation
std::set<LLUUID> mPendingAttachLinks;
// [/SL:KB]
// // Attachments that are linked in the COF but may be invalid.
// LLItemRequestTimes mQuestionableCOFLinks;
};
#endif

View File

@@ -5545,9 +5545,8 @@ bool confirm_attachment_rez(const LLSD& notification, const LLSD& response)
U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
BOOL is_add = notification["payload"]["is_add"].asBoolean();
LLAttachmentsMgr::instance().addAttachment(item_id,
attachment_pt,
is_add);
LL_DEBUGS("Avatar") << "ATT calling addAttachmentRequest " << (itemp ? itemp->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
LLAttachmentsMgr::instance().addAttachmentRequest(item_id, attachment_pt, is_add);
}
}
return false;