RLVa 1.1.2 to 1.1.3 upgrade. InvLinks + COF

This commit is contained in:
Siana Gearz
2010-11-25 23:47:11 +01:00
parent 074bec3ad1
commit f9dcb1bb09
88 changed files with 8710 additions and 4707 deletions

View File

@@ -35,8 +35,8 @@
#include "stdtypes.h"
#include "stdenums.h"
#include "cofmgr.h"
#include "llagent.h"
#include "llcamera.h"
#include "llcoordframe.h"
#include "indra_constants.h"
@@ -142,8 +142,10 @@
#include "llworldmapmessage.h"
#include "llfollowcam.h"
// [RLVa:KB]
// [RLVa:KB] - Checked: 2010-09-27 (RLVa-1.1.3b)
#include "rlvhandler.h"
#include "rlvinventory.h"
#include "llattachmentsmgr.h"
// [/RLVa:KB]
using namespace LLVOAvatarDefines;
@@ -3480,13 +3482,18 @@ void LLAgent::updateCamera()
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
LLViewerObject *attached_object = attachment->getObject();
if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
// clear any existing "early" movements of attachment
attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
attached_object->updateText();
LLViewerObject *attached_object = (*attachment_iter);
if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
{
// clear any existing "early" movements of attachment
attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
attached_object->updateText();
}
}
}
@@ -6285,6 +6292,7 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
( (gRlvHandler.hasBehaviour(RLV_BHVR_TPLM)) ||
((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting)) ))
{
RlvNotifications::notifyBlockedTeleport();
return;
}
// [/RLVa:KB]
@@ -6361,6 +6369,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
( (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) &&
(gRlvHandler.hasBehaviourExcept(RLV_BHVR_UNSIT, gRlvHandler.getCurrentObject()))) )
{
RlvNotifications::notifyBlockedTeleport();
return;
}
@@ -6422,6 +6431,16 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
// Teleport to global position, but keep facing in the same direction
void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global)
{
// [RLVa:KB] - Checked: 2010-10-07 (RLVa-1.2.1f) | Added: RLVa-1.2.1f
// RELEASE-RLVa: [SL-2.2.0] Make sure this isn't used for anything except double-click teleporting
if ( (rlv_handler_t::isEnabled()) && (!RlvUtil::isForceTp()) &&
((gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) || (!gRlvHandler.canStand())) )
{
RlvNotifications::notifyBlockedTeleport();
return;
}
// [/RLVa:KB]
mbTeleportKeepsLookAt = true;
setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction
U64 region_handle = to_region_handle(pos_global);
@@ -6690,6 +6709,9 @@ void LLAgent::sendAgentWearablesUpdate()
// Then make sure the inventory is in sync with the avatar.
gInventory.notifyObservers();
// This isn't the proper place to be doing this, but it's a good "catch-all"
LLCOFMgr::instance().synchWearables();
// Send the AgentIsNowWearing
gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
@@ -6709,7 +6731,15 @@ void LLAgent::sendAgentWearablesUpdate()
if( wearable )
{
LL_DEBUGS("Wearables") << "Sending wearable " << wearable->getName() << " mItemID = " << mWearableEntry[ i ].mItemID << LL_ENDL;
gMessageSystem->addUUIDFast(_PREHASH_ItemID, mWearableEntry[ i ].mItemID );
LLUUID item_id = mWearableEntry[i].mItemID;
const LLViewerInventoryItem *item = gInventory.getItem(item_id);
if (item && item->getIsLinkType())
{
// Get the itemID that this item points to. i.e. make sure
// we are storing baseitems, not their links, in the database.
item_id = item->getLinkedUUID();
}
gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);
}
else
{
@@ -7018,7 +7048,8 @@ BOOL LLAgent::selfHasWearable( void* userdata )
BOOL LLAgent::isWearingItem( const LLUUID& item_id )
{
return (getWearableFromWearableItem( item_id ) != NULL);
const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
return (getWearableFromWearableItem(base_item_id) != NULL);
}
// static
@@ -7095,19 +7126,14 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void
LL_DEBUGS("Wearables") << " " << LLWearable::typeToTypeLabel(type) << " " << asset_id << " item id " << gAgent.mWearableEntry[type].mItemID.asString() << LL_ENDL;
}
LLCOFMgr::instance().fetchCOF();
// now that we have the asset ids...request the wearable assets
// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
LLInventoryFetchObserver::item_ref_t rlvItems;
// [/RLVa:KB]
for( i = 0; i < WT_COUNT; i++ )
{
LL_DEBUGS("Wearables") << " fetching " << asset_id_array[i] << LL_ENDL;
if( !gAgent.mWearableEntry[i].mItemID.isNull() )
{
// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
if (rlv_handler_t::isEnabled())
rlvItems.push_back(gAgent.mWearableEntry[i].mItemID);
// [/RLVa:KB]
gWearableList.getAsset(
asset_id_array[i],
LLStringUtil::null,
@@ -7116,14 +7142,8 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void
}
}
// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-08-08 (RLVa-1.0.1g) | Added: RLVa-1.0.1g
// TODO-RLVa: checking that we're in STATE_STARTED is probably not needed, but leave it until we can be absolutely sure
if ( (rlv_handler_t::isEnabled()) && (LLStartUp::getStartupState() == STATE_STARTED) )
{
RlvCurrentlyWorn f;
f.fetchItems(rlvItems);
}
// [/RLVa:KB]
// Not really sure where else to put this
gIdleCallbacks.addFunction(&LLAttachmentsMgr::onIdle, NULL);
}
}
@@ -7331,11 +7351,14 @@ void LLAgent::makeNewOutfit(
return;
}
// First, make a folder in the Clothes directory.
LLUUID folder_id = gInventory.createNewCategory(
gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING),
LLAssetType::AT_NONE,
new_folder_name);
BOOL fUseLinks = !gSavedSettings.getBOOL("UseInventoryLinks");
BOOL fUseOutfits = gSavedSettings.getBOOL("UseOutfitFolders");
LLAssetType::EType typeDest = (fUseOutfits) ? LLAssetType::AT_MY_OUTFITS : LLAssetType::AT_CLOTHING;
LLAssetType::EType typeFolder = (fUseOutfits) ? LLAssetType::AT_OUTFIT : LLAssetType::AT_NONE;
// First, make a folder for the outfit.
LLUUID folder_id = gInventory.createNewCategory(gInventory.findCategoryUUIDForType(typeDest), typeFolder, new_folder_name);
bool found_first_item = false;
@@ -7347,7 +7370,6 @@ void LLAgent::makeNewOutfit(
// Then, iterate though each of the wearables and save copies of them in the folder.
S32 i;
S32 count = wearables_to_include.count();
LLDynamicArray<LLUUID> delete_items;
LLPointer<LLRefCount> cbdone = NULL;
for( i = 0; i < count; ++i )
{
@@ -7355,53 +7377,86 @@ void LLAgent::makeNewOutfit(
LLWearable* old_wearable = mWearableEntry[ index ].mWearable;
if( old_wearable )
{
std::string new_name;
LLWearable* new_wearable;
new_wearable = gWearableList.createCopy(old_wearable);
if (rename_clothing)
{
new_name = new_folder_name;
new_name.append(" ");
new_name.append(old_wearable->getTypeLabel());
LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
new_wearable->setName(new_name);
}
LLViewerInventoryItem* item = gInventory.getItem(mWearableEntry[index].mItemID);
S32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
if (!found_first_item)
if (fUseOutfits)
{
found_first_item = true;
/* set the focus to the first item */
todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE;
/* send the agent wearables update when done */
cbdone = new sendAgentWearablesUpdateCallback;
}
LLPointer<LLInventoryCallback> cb =
new addWearableToAgentInventoryCallback(
cbdone,
index,
new_wearable,
todo);
if (isWearableCopyable((EWearableType)index))
{
copy_inventory_item(
std::string strOrdering = llformat("@%d", item->getWearableType() * 100);
link_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
item->getLinkedUUID(),
folder_id,
new_name,
cb);
item->getName(),
strOrdering,
LLAssetType::AT_LINK,
LLPointer<LLInventoryCallback>(NULL));
}
else
{
move_inventory_item(
gAgent.getID(),
gAgent.getSessionID(),
item->getUUID(),
folder_id,
new_name,
cb);
std::string new_name = item->getName();
if (rename_clothing)
{
new_name = new_folder_name;
new_name.append(" ");
new_name.append(old_wearable->getTypeLabel());
LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
}
if (fUseLinks || isWearableCopyable((EWearableType)index))
{
LLWearable* new_wearable = gWearableList.createCopy(old_wearable);
if (rename_clothing)
{
new_wearable->setName(new_name);
}
S32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
if (!found_first_item)
{
found_first_item = true;
/* set the focus to the first item */
todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE;
/* send the agent wearables update when done */
cbdone = new sendAgentWearablesUpdateCallback;
}
LLPointer<LLInventoryCallback> cb =
new addWearableToAgentInventoryCallback(
cbdone,
index,
new_wearable,
todo);
if (isWearableCopyable((EWearableType)index))
{
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getLinkedUUID(),
folder_id,
new_name,
cb);
}
else
{
move_inventory_item(
gAgent.getID(),
gAgent.getSessionID(),
item->getLinkedUUID(),
folder_id,
new_name,
cb);
}
}
else
{
link_inventory_item(
gAgent.getID(),
item->getLinkedUUID(),
folder_id,
item->getName(), // Apparently, links cannot have arbitrary names...
item->getDescription(),
LLAssetType::AT_LINK,
LLPointer<LLInventoryCallback>(NULL));
}
}
}
}
@@ -7414,39 +7469,71 @@ void LLAgent::makeNewOutfit(
if( attachments_to_include.count() )
{
BOOL msg_started = FALSE;
LLMessageSystem* msg = gMessageSystem;
for( S32 i = 0; i < attachments_to_include.count(); i++ )
{
S32 attachment_pt = attachments_to_include[i];
LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL );
if(!attachment) continue;
LLViewerObject* attached_object = attachment->getObject();
if(!attached_object) continue;
const LLUUID& item_id = attachment->getItemID();
if(item_id.isNull()) continue;
LLInventoryItem* item = gInventory.getItem(item_id);
if(!item) continue;
if(!msg_started)
{
msg_started = TRUE;
msg->newMessage("CreateNewOutfitAttachments");
msg->nextBlock("AgentData");
msg->addUUID("AgentID", getID());
msg->addUUID("SessionID", getSessionID());
msg->nextBlock("HeaderData");
msg->addUUID("NewFolderID", folder_id);
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *attached_object = (*attachment_iter);
if (!attached_object) continue;
const LLUUID& item_id = attached_object->getAttachmentItemID();
if (item_id.isNull()) continue;
LLInventoryItem* item = gInventory.getItem(item_id);
if (!item) continue;
if (fUseOutfits)
{
link_inventory_item(
gAgent.getID(),
item->getLinkedUUID(),
folder_id,
item->getName(),
item->getDescription(),
LLAssetType::AT_LINK,
LLPointer<LLInventoryCallback>(NULL));
}
else
{
if (fUseLinks || item->getPermissions().allowCopyBy(gAgent.getID()))
{
const LLUUID& old_folder_id = item->getParentUUID();
move_inventory_item(
gAgent.getID(),
gAgent.getSessionID(),
item->getLinkedUUID(),
folder_id,
item->getName(),
LLPointer<LLInventoryCallback>(NULL));
if (item->getPermissions().allowCopyBy(gAgent.getID()))
{
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getLinkedUUID(),
old_folder_id,
item->getName(),
LLPointer<LLInventoryCallback>(NULL));
}
}
else
{
link_inventory_item(
gAgent.getID(),
item->getLinkedUUID(),
folder_id,
item->getName(),
item->getDescription(),
LLAssetType::AT_LINK,
LLPointer<LLInventoryCallback>(NULL));
}
}
}
msg->nextBlock("ObjectData");
msg->addUUID("OldItemID", item_id);
msg->addUUID("OldFolderID", item->getParentUUID());
}
if( msg_started )
{
sendReliableMessage();
}
}
}
@@ -7518,6 +7605,10 @@ void LLAgent::sendAgentSetAppearance()
body_size.mV[VY] = body_size.mV[VY] + gSavedSettings.getF32("AscentAvatarYModifier");
body_size.mV[VZ] = body_size.mV[VZ] + gSavedSettings.getF32("AscentAvatarZModifier");
// [RLVa:KB] - Checked: 2010-10-11 (RLVa-1.2.0e) | Added: RLVa-1.2.0e
body_size.mV[VZ] += RlvSettings::getAvatarOffsetZ();
// [/RLVa:KB]
msg->addVector3Fast(_PREHASH_Size, body_size);
// To guard against out of order packets
@@ -7668,8 +7759,8 @@ void LLAgent::removeWearable( EWearableType type )
return;
}
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-07 (RLVa-1.0.0d)
if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.isRemovable(type)) )
// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.1.3b)
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(type)) )
{
return;
}
@@ -7801,19 +7892,19 @@ void LLAgent::setWearableOutfit(
wearables_to_remove[WT_SKIN] = FALSE;
wearables_to_remove[WT_HAIR] = FALSE;
wearables_to_remove[WT_EYES] = FALSE;
// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | Added: RLVa-0.2.2a
wearables_to_remove[WT_SHIRT] = remove && gRlvHandler.isRemovable(WT_SHIRT);
wearables_to_remove[WT_PANTS] = remove && gRlvHandler.isRemovable(WT_PANTS);
wearables_to_remove[WT_SHOES] = remove && gRlvHandler.isRemovable(WT_SHOES);
wearables_to_remove[WT_SOCKS] = remove && gRlvHandler.isRemovable(WT_SOCKS);
wearables_to_remove[WT_JACKET] = remove && gRlvHandler.isRemovable(WT_JACKET);
wearables_to_remove[WT_GLOVES] = remove && gRlvHandler.isRemovable(WT_GLOVES);
wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERSHIRT);
wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) && remove && gRlvHandler.isRemovable(WT_UNDERPANTS);
wearables_to_remove[WT_SKIRT] = remove && gRlvHandler.isRemovable(WT_SKIRT);
// [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.1.3b) | Added: RLVa-0.2.2a
wearables_to_remove[WT_SHIRT] = remove && gRlvWearableLocks.canRemove(WT_SHIRT);
wearables_to_remove[WT_PANTS] = remove && gRlvWearableLocks.canRemove(WT_PANTS);
wearables_to_remove[WT_SHOES] = remove && gRlvWearableLocks.canRemove(WT_SHOES);
wearables_to_remove[WT_SOCKS] = remove && gRlvWearableLocks.canRemove(WT_SOCKS);
wearables_to_remove[WT_JACKET] = remove && gRlvWearableLocks.canRemove(WT_JACKET);
wearables_to_remove[WT_GLOVES] = remove && gRlvWearableLocks.canRemove(WT_GLOVES);
wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) && remove && gRlvWearableLocks.canRemove(WT_UNDERSHIRT);
wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) && remove && gRlvWearableLocks.canRemove(WT_UNDERPANTS);
wearables_to_remove[WT_SKIRT] = remove && gRlvWearableLocks.canRemove(WT_SKIRT);
wearables_to_remove[WT_ALPHA] = remove && gRlvWearableLocks.canRemove(WT_ALPHA);
wearables_to_remove[WT_TATTOO] = remove && gRlvWearableLocks.canRemove(WT_TATTOO);
// [/RLVa:KB]
wearables_to_remove[WT_ALPHA] = remove;
wearables_to_remove[WT_TATTOO] = remove;
S32 count = wearables.count();
llassert( items.count() == count );
@@ -7906,7 +7997,7 @@ void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable )
// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
// Block if: we can't wear on that layer; or we're already wearing something there we can't take off
if ( (rlv_handler_t::isEnabled()) && ((!gRlvHandler.isWearable(type)) || ((old_wearable) && (!gRlvHandler.isRemovable(type)))) )
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canWear(type)) )
{
return;
}
@@ -8106,38 +8197,28 @@ void LLAgent::userRemoveAllAttachments( void* userdata )
return;
}
// [RLVa:KB] - Checked: 2009-11-24 (RLVa-1.1.0f) | Modified: RLVa-1.1.0e
std::list<U32> LocalIDs;
for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); iter != avatarp->mAttachmentPoints.end(); )
llvo_vec_t objects_to_remove;
for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
iter != avatarp->mAttachmentPoints.end();)
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
LLViewerObject* objectp = attachment->getObject();
if (objectp)
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.isLockedAttachment(curiter->first, RLV_LOCK_REMOVE)) )
continue;
LocalIDs.push_back(objectp->getLocalID());
}
}
// Only send the message if we actually have something to detach
if (LocalIDs.size() > 0)
{
gMessageSystem->newMessage("ObjectDetach");
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
for (std::list<U32>::const_iterator itLocalID = LocalIDs.begin(); itLocalID != LocalIDs.end(); ++itLocalID)
{
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, *itLocalID);
}
gMessageSystem->sendReliable(gAgent.getRegionHost());
}
LLViewerObject *attached_object = (*attachment_iter);
// if (attached_object)
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b
if ( (attached_object) && ((!rlv_handler_t::isEnabled()) || (!gRlvAttachmentLocks.isLockedAttachment(attached_object))) )
// [/RLVa:KB]
{
objects_to_remove.push_back(attached_object);
}
}
}
userRemoveMultipleAttachments(objects_to_remove);
}
void LLAgent::observeFriends()
@@ -8202,6 +8283,208 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename)
}//end for (all message sets in xml file)
}
// Combines userRemoveAllAttachments() and userAttachMultipleAttachments() logic to
// get attachments into desired state with minimal number of adds/removes.
//void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array)
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2.0a) | Added: Catznip-2.2.0a
void LLAgent::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array, bool fAttachOnly)
// [/SL:KB]
{
// Possible cases:
// already wearing but not in request set -> take off.
// already wearing and in request set -> leave alone.
// not wearing and in request set -> put on.
LLVOAvatar* pAvatar = gAgent.getAvatarObject();
if (!pAvatar) return;
std::set<LLUUID> requested_item_ids;
std::set<LLUUID> current_item_ids;
for (S32 i=0; i<obj_item_array.count(); i++)
requested_item_ids.insert(obj_item_array[i].get()->getLinkedUUID());
// Build up list of objects to be removed and items currently attached.
llvo_vec_t objects_to_remove;
for (LLVOAvatar::attachment_map_t::iterator iter = pAvatar->mAttachmentPoints.begin();
iter != pAvatar->mAttachmentPoints.end();)
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *objectp = (*attachment_iter);
if (objectp)
{
LLUUID object_item_id = objectp->getAttachmentItemID();
if (requested_item_ids.find(object_item_id) != requested_item_ids.end())
{
// Object currently worn, was requested.
// Flag as currently worn so we won't have to add it again.
current_item_ids.insert(object_item_id);
}
else
{
// object currently worn, not requested.
objects_to_remove.push_back(objectp);
}
}
}
}
LLInventoryModel::item_array_t items_to_add;
for (LLInventoryModel::item_array_t::iterator it = obj_item_array.begin();
it != obj_item_array.end();
++it)
{
LLUUID linked_id = (*it).get()->getLinkedUUID();
if (current_item_ids.find(linked_id) != current_item_ids.end())
{
// Requested attachment is already worn.
}
else
{
// Requested attachment is not worn yet.
items_to_add.push_back(*it);
}
}
// S32 remove_count = objects_to_remove.size();
// S32 add_count = items_to_add.size();
// llinfos << "remove " << remove_count << " add " << add_count << llendl;
// Remove everything in objects_to_remove
// userRemoveMultipleAttachments(objects_to_remove);
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2.0a) | Added: Catznip-2.2.0a
if (!fAttachOnly)
{
userRemoveMultipleAttachments(objects_to_remove);
}
// [/SL:KB]
// Add everything in items_to_add
userAttachMultipleAttachments(items_to_add);
}
void LLAgent::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove)
{
if (!gAgent.getAvatarObject()) return;
// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.1.3b) | Modified: RLVa-1.2.0a
// RELEASE-RLVa: [SL-2.0.0] Check our callers and verify that erasing elements from the passed vector won't break random things
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) )
{
llvo_vec_t::iterator itObj = objects_to_remove.begin();
while (itObj != objects_to_remove.end())
{
const LLViewerObject* pAttachObj = *itObj;
if (gRlvAttachmentLocks.isLockedAttachment(pAttachObj))
{
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)
LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items;
LLLinkedItemIDMatches f(pAttachObj->getAttachmentItemID());
gInventory.collectDescendentsIf(LLCOFMgr::instance().getCOF(), folders, items, LLInventoryModel::EXCLUDE_TRASH, f);
RLV_ASSERT( 0 != items.count() );
if (0 == items.count())
LLCOFMgr::instance().addAttachment(pAttachObj->getAttachmentItemID());
}
else
{
++itObj;
}
}
}
// [/RLVa:KB]
if (objects_to_remove.empty())
return;
gMessageSystem->newMessage("ObjectDetach");
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
for (llvo_vec_t::iterator it = objects_to_remove.begin();
it != objects_to_remove.end();
++it)
{
LLViewerObject *objectp = *it;
gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());
}
gMessageSystem->sendReliable(gAgent.getRegionHost());
}
void LLAgent::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array)
{
// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
// RELEASE-RLVa: [SL-2.0.0] Check our callers and verify that erasing elements from the passed vector won't break random things
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) )
{
// Fall-back code: everything should really already have been pruned before we get this far
for (S32 idxItem = obj_item_array.count() - 1; idxItem >= 0; idxItem--)
{
const LLInventoryItem* pItem = obj_item_array.get(idxItem).get();
if (!gRlvAttachmentLocks.canAttach(pItem))
{
obj_item_array.remove(idxItem);
RLV_ASSERT(false);
}
}
}
// [/RLVa:KB]
// Build a compound message to send all the objects that need to be rezzed.
S32 obj_count = obj_item_array.count();
// Limit number of packets to send
const S32 MAX_PACKETS_TO_SEND = 10;
const S32 OBJECTS_PER_PACKET = 4;
const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
if( obj_count > MAX_OBJECTS_TO_SEND )
{
obj_count = MAX_OBJECTS_TO_SEND;
}
// Create an id to keep the parts of the compound message together
LLUUID compound_msg_id;
compound_msg_id.generate();
LLMessageSystem* msg = gMessageSystem;
for(S32 i = 0; i < obj_count; ++i)
{
if( 0 == (i % OBJECTS_PER_PACKET) )
{
// Start a new message chunk
msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_HeaderData);
msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
msg->addBOOLFast(_PREHASH_FirstDetachAll, false );
}
const LLInventoryItem* item = obj_item_array.get(i).get();
msg->nextBlockFast(_PREHASH_ObjectData );
msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD); // Wear at the previous or default attachment point
pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
msg->addStringFast(_PREHASH_Name, item->getName());
msg->addStringFast(_PREHASH_Description, item->getDescription());
if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
{
// End of message chunk
msg->sendReliable( gAgent.getRegion()->getHost() );
}
}
}
// OGPX - This code will change when capabilities get refactored.
// Right now this is used for capabilities that we get from OGP agent domain
void LLAgent::setCapability(const std::string& name, const std::string& url)