From efa1a64f0e15bf3a4edcab8f12187911f8d4f2b4 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 24 Mar 2012 12:42:46 +0100 Subject: [PATCH] Fixes for LSL bridge: * Use overloaded LLInventoryFetchDescendentsObserver to check for load of bridge and bridge rock category before doing anything! * Request object inventory first before checking it's contents * Properly stop bridge creation process if somehow the bridge rock wasn't found in the library (caused stalling) * Only attach unattached bridge if it's not in the CoF already --- indra/newview/fslslbridge.cpp | 235 +++++++++++++++++++++++++--------- indra/newview/fslslbridge.h | 18 ++- 2 files changed, 189 insertions(+), 64 deletions(-) diff --git a/indra/newview/fslslbridge.cpp b/indra/newview/fslslbridge.cpp index 85723c635e..816a290656 100644 --- a/indra/newview/fslslbridge.cpp +++ b/indra/newview/fslslbridge.cpp @@ -50,6 +50,7 @@ // #include "llnearbychatbar.h" // Dead code #include "llnotificationmanager.h" #include "llviewerobject.h" +#include "llappearancemgr.h" #include #include @@ -65,6 +66,7 @@ //#define ROOT_FIRESTORM_FOLDER "#Firestorm" //moved to llinventoryfunctions to synch with the AO object #define FS_BRIDGE_FOLDER "#LSL Bridge" #define FS_BRIDGE_NAME "#Firestorm LSL Bridge v" +#define FS_BRIDGE_CONTAINER_FOLDER "Landscaping" #define FS_BRIDGE_MAJOR_VERSION 2 #define FS_BRIDGE_MINOR_VERSION 2 #define FS_MAX_MINOR_VERSION 99 @@ -247,6 +249,14 @@ void FSLSLBridge :: recreateBridge() if (!gSavedSettings.getBOOL("UseLSLBridge")) return; + if (gSavedSettings.getBOOL("NoInventoryLibrary")) + { + llwarns << "Asked to create bridge, but we don't have a library. Aborting." << llendl; + reportToNearbyChat("Firestorm could not create an LSL bridge. Please enable your library and relog"); + mBridgeCreating = false; + return; + } + if (mBridgeCreating) { llwarns << "Bridge creation already in progress, aborting new attempt." << llendl; @@ -276,17 +286,34 @@ void FSLSLBridge :: initBridge() if (!gSavedSettings.getBOOL("UseLSLBridge")) return; + if (gSavedSettings.getBOOL("NoInventoryLibrary")) + { + llwarns << "Asked to create bridge, but we don't have a library. Aborting." << llendl; + reportToNearbyChat("Firestorm could not create an LSL bridge. Please enable your library and relog"); + mBridgeCreating = false; + return; + } + LLUUID catID = findFSCategory(); + LLUUID libCatID = findFSBridgeContainerCategory(); //check for inventory load - FSLSLBridgeInventoryObserver *bridgeInventoryObserver = new FSLSLBridgeInventoryObserver(catID); + // AH: Use overloaded LLInventoryFetchDescendentsObserver to check for load of + // bridge and bridge rock category before doing anything! + uuid_vec_t cats; + cats.push_back(catID); + cats.push_back(libCatID); + FSLSLBridgeInventoryObserver *bridgeInventoryObserver = new FSLSLBridgeInventoryObserver(cats); gInventory.addObserver(bridgeInventoryObserver); + bridgeInventoryObserver->startFetch(); } // Gets called by the Init, when inventory loaded. void FSLSLBridge :: startCreation() { + llinfos << "startCreation called. gInventory.isInventoryUsable=" << gInventory.isInventoryUsable() << llendl; + //if bridge object doesn't exist - create and attach it, update script. LLUUID catID = findFSCategory(); @@ -306,10 +333,17 @@ void FSLSLBridge :: startCreation() mpBridge = fsBridge; if (!isItemAttached(mpBridge->getUUID())) { - //Is this a valid bridge - wear it. - LLAttachmentsMgr::instance().addAttachment(mpBridge->getUUID(), BRIDGE_POINT, FALSE, TRUE); - llinfos << "Bridge found in inventory, reattaching..." << llendl; - //from here, the attach shoould report to ProcessAttach and make sure bridge is valid. + if (!LLAppearanceMgr::instance().getIsInCOF(mpBridge->getUUID())) + { + //Is this a valid bridge - wear it. + LLAttachmentsMgr::instance().addAttachment(mpBridge->getUUID(), BRIDGE_POINT, FALSE, TRUE); + llinfos << "Bridge not attached but found in inventory, reattaching..." << llendl; + //from here, the attach shoould report to ProcessAttach and make sure bridge is valid. + } + else + { + llinfos << "Bridge not found but in CoF. Waiting for automatic attach..." << llendl; + } } } } @@ -320,13 +354,6 @@ void FSLSLBridge :: initCreationStep() //announce yourself reportToNearbyChat("Creating the bridge. This might take a few moments, please wait"); - if (gSavedSettings.getBOOL("NoInventoryLibrary")) - { - llwarns << "Asked to create bridge, but we don't have a library. Aborting." << llendl; - reportToNearbyChat("Firestorm could not create an LSL bridge. Please enable your library and relog"); - mBridgeCreating = false; - return; - } createNewBridge(); } @@ -349,12 +376,15 @@ void FSLSLBridge :: createNewBridge() else { llwarns << "Bridge container not found in the Library!" << llendl; + // AH: Set to false or we won't be able to start another bridge creation + // process in this session! + mBridgeCreating = false; } } void FSLSLBridge :: processAttach(LLViewerObject *object, const LLViewerJointAttachment *attachment) { - llinfos << "Entering processAttach, checking the bridge container..." << llendl; + llinfos << "Entering processAttach, checking the bridge container - gInventory.isInventoryUsable=" << gInventory.isInventoryUsable()<< llendl; if ((!gAgentAvatarp->isSelf()) || (attachment->getName() != "Bridge")) { @@ -428,52 +458,89 @@ void FSLSLBridge :: processAttach(LLViewerObject *object, const LLViewerJointAtt if (!mBridgeCreating) //just an attach. See what it is { - //are we attaching the right thing? Check size and script - LLInventoryObject::object_list_t inventory_objects; - object->getInventoryContents(inventory_objects); - - if (object->flagInventoryEmpty()) - { - llinfos << "Empty bridge detected- re-enter creation process" << llendl; - mBridgeCreating = true; - } - else if (inventory_objects.size() > 0) - { - LLInventoryObject::object_list_t::iterator it = inventory_objects.begin(); - LLInventoryObject::object_list_t::iterator end = inventory_objects.end(); - bool isOurScript = false; - for ( ; it != end; ++it) - { - LLInventoryItem* item = ((LLInventoryItem*)((LLInventoryObject*)(*it))); - if (item->getType() == LLAssetType::AT_LSL_TEXT) - { - if (item->getCreatorUUID() == gAgent.getID()) - isOurScript = true; - else //problem, not our script - llwarns << "The bridge inventory contains a script not created by user." << llendl; - } - } - if ((inventory_objects.size() == 1) && isOurScript) //We attached a valid bridge. Run along. - return; - else - { - reportToNearbyChat("The bridge inventory contains unexpected items."); - llwarns << "The bridge inventory contains items other than bridge script." << llendl; - if (!isOurScript) //some junk but no valid script? Unlikely to happen, but lets add script anyway. - mBridgeCreating = true; - else //Let the script disable competitors - { - return; - } - } - } - else - llwarns << "Bridge not empty, but we're unable to retrieve contents." << llendl; + // AH: We need to request objects inventory first before we can + // do anything with it! + llinfos << "Requesting bridge inventory contents..." << llendl; + object->registerInventoryListener(this, NULL); + object->requestInventory(); } - - //modify the rock size and texture - if ((object != NULL) && (mBridgeCreating)) + else { + configureBridgePrim(object); + } +} + +void FSLSLBridge::inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void* user_data) +{ + object->removeInventoryListener(this); + + llinfos << "Received object inventory for existing bridge prim. Checking contents..." << llendl; + + //are we attaching the right thing? Check size and script + LLInventoryObject::object_list_t inventory_objects; + object->getInventoryContents(inventory_objects); + + if (object->flagInventoryEmpty()) + { + llinfos << "Empty bridge detected- re-enter creation process" << llendl; + mBridgeCreating = true; + } + else if (inventory_objects.size() > 0) + { + S32 count(0); + + LLInventoryObject::object_list_t::iterator it = inventory_objects.begin(); + LLInventoryObject::object_list_t::iterator end = inventory_objects.end(); + bool isOurScript = false; + for ( ; it != end; ++it) + { + LLInventoryItem* item = ((LLInventoryItem*)((LLInventoryObject*)(*it))); + + // AH: Somehow always contains a wonky object item with creator + // UUID = NULL UUID and asset type AT_NONE - don't count it + if (item->getType() != LLAssetType::AT_NONE) + { + count++; + } + + if (item->getType() == LLAssetType::AT_LSL_TEXT) + { + if (item->getCreatorUUID() == gAgent.getID()) + isOurScript = true; + else //problem, not our script + llwarns << "The bridge inventory contains a script not created by user." << llendl; + } + } + if (count == 1 && isOurScript) //We attached a valid bridge. Run along. + return; + else + { + reportToNearbyChat("The bridge inventory contains unexpected items."); + llwarns << "The bridge inventory contains items other than bridge script." << llendl; + if (!isOurScript) //some junk but no valid script? Unlikely to happen, but lets add script anyway. + mBridgeCreating = true; + else //Let the script disable competitors + { + return; + } + } + } + else + llwarns << "Bridge not empty, but we're unable to retrieve contents." << llendl; + + //modify the rock size and texture + if (mBridgeCreating) + { + configureBridgePrim(object); + } +} + +void FSLSLBridge::configureBridgePrim(LLViewerObject* object) +{ + //modify the rock size and texture llinfos << "Bridge container found after second attachment, resizing..." << llendl; setupBridgePrim(object); @@ -487,7 +554,6 @@ void FSLSLBridge :: processAttach(LLViewerObject *object, const LLViewerJointAtt //add bridge script to object llinfos << "Creating bridge script..." << llendl; create_script_inner(object); - } } void FSLSLBridge :: processDetach(LLViewerObject *object, const LLViewerJointAttachment *attachment) @@ -820,6 +886,59 @@ LLUUID FSLSLBridge :: findFSCategory() return mBridgeFolderID; } + +LLUUID FSLSLBridge::findFSBridgeContainerCategory() +{ + llinfos << "Retrieving FSBridge container category (" << FS_BRIDGE_CONTAINER_FOLDER << ")" << llendl; + if (mBridgeContainerFolderID.notNull()) + { + llinfos << "Returning FSBridge container category UUID from instance: " << mBridgeContainerFolderID << llendl; + return mBridgeContainerFolderID; + } + + LLUUID LibRootID = gInventory.getLibraryRootFolderID(); + if (LibRootID.notNull()) + { + LLInventoryModel::item_array_t* items; + LLInventoryModel::cat_array_t* cats; + gInventory.getDirectDescendentsOf(LibRootID, cats, items); + if (cats) + { + S32 count = cats->count(); + for(S32 i = 0; i < count; ++i) + { + if (cats->get(i)->getName() == "Objects") + { + LLUUID LibObjectsCatID = cats->get(i)->getUUID(); + if (LibObjectsCatID.notNull()) + { + LLInventoryModel::item_array_t* objects_items; + LLInventoryModel::cat_array_t* objects_cats; + gInventory.getDirectDescendentsOf(LibObjectsCatID, objects_cats, objects_items); + if (objects_cats) + { + S32 objects_count = objects_cats->count(); + for (S32 j = 0; j < objects_count; ++j) + { + if (objects_cats->get(j)->getName() == FS_BRIDGE_CONTAINER_FOLDER) + { + mBridgeContainerFolderID = objects_cats->get(j)->getUUID(); + llinfos << "FSBridge container category found in library. UUID: " << mBridgeContainerFolderID << llendl; + gInventory.fetchDescendentsOf(mBridgeContainerFolderID); + return mBridgeContainerFolderID; + } + } + } + } + } + } + } + } + + llwarns << "FSBridge container category not found in library!" << llendl; + return LLUUID(); +} + LLViewerInventoryItem* FSLSLBridge :: findInvObject(std::string obj_name, LLUUID catID, LLAssetType::EType type) { LLViewerInventoryCategory::cat_array_t cats; diff --git a/indra/newview/fslslbridge.h b/indra/newview/fslslbridge.h index 7ecab03b3d..ce87dc8447 100644 --- a/indra/newview/fslslbridge.h +++ b/indra/newview/fslslbridge.h @@ -34,12 +34,13 @@ #include "llviewerinventory.h" #include "llinventoryobserver.h" #include "lleventtimer.h" +#include "llvoinventorylistener.h" // //-TT Client LSL Bridge File // -class FSLSLBridge : public LLSingleton, public LLHTTPClient::Responder //, public LLVOInventoryListener +class FSLSLBridge : public LLSingleton, public LLHTTPClient::Responder, public LLVOInventoryListener { static const U8 BRIDGE_POINT = 127; @@ -74,6 +75,12 @@ public: LLUUID getBridgeFolder() { return mBridgeFolderID; } + // from LLVOInventoryListener + virtual void inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void* user_data); + private: std::string mCurrentURL; bool mBridgeCreating; @@ -82,12 +89,14 @@ private: std::string mCurrentFullName; LLUUID mScriptItemID; //internal script ID LLUUID mBridgeFolderID; + LLUUID mBridgeContainerFolderID; bool mIsFirstCallDone; //initialization conversation protected: LLViewerInventoryItem* findInvObject(std::string obj_name, LLUUID catID, LLAssetType::EType type); LLUUID findFSCategory(); + LLUUID findFSBridgeContainerCategory(); bool isItemAttached(LLUUID iID); void createNewBridge(); @@ -103,11 +112,7 @@ protected: void finishBridge(); void cleanUpOldVersions(); void detachOtherBridges(); - - /*virtual*/ void inventoryChanged(LLViewerObject* obj, - LLInventoryObject::object_list_t* inv, - S32 serial_num, - void* queue); + void configureBridgePrim(LLViewerObject* object); }; @@ -136,6 +141,7 @@ class FSLSLBridgeInventoryObserver : public LLInventoryFetchDescendentsObserver { public: FSLSLBridgeInventoryObserver(const LLUUID& cat_id = LLUUID::null):LLInventoryFetchDescendentsObserver(cat_id) {} + FSLSLBridgeInventoryObserver(const uuid_vec_t& cat_ids):LLInventoryFetchDescendentsObserver(cat_ids) {} /*virtual*/ void done() { gInventory.removeObserver(this); FSLSLBridge::instance().startCreation(); } protected: