void FSLSLBridge :: initCreationStep()
{
	mBridgeCreating = true;
	//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" << llendl;
		reportToNearbyChat("Firestorm could not create an LSL bridge. Please enable your library and relog");
		return;
	}
	createNewBridge();
}
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(LLTrans::getString("fsbridge_no_library"));
		mBridgeCreating = false;
		return;
	}

	LLUUID catID = findFSCategory();
	LLUUID libCatID = findFSBridgeContainerCategory();

	//check for inventory load
	// 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();
}
void FSLSLBridge::initCreationStep()
{
	mBridgeCreating = true;
	//announce yourself
	reportToNearbyChat(LLTrans::getString("fsbridge_creating"));

	createNewBridge();
}
void FSLSLBridge :: finishBridge()
{
	//announce yourself
	reportToNearbyChat("Bridge created.");

	mBridgeCreating = false;
	//removeVOInventoryListener();
	cleanUpBridgeFolder();
}
void FSLSLBridge :: cleanUpBridge()
{
	//something unexpected went wrong. Try to clean up and not crash.
	reportToNearbyChat("Bridge object not found. Can't proceed with creation, exiting.");
	gInventory.purgeObject(mpBridge->getUUID());
	gInventory.notifyObservers();
	mpBridge = NULL;
	mBridgeCreating = false;
}
void FSLSLBridge::finishBridge()
{
	//announce yourself
	llinfos << "Bridge created." << llendl;
	reportToNearbyChat(LLTrans::getString("fsbridge_created"));

	mBridgeCreating = false;
	mIsFirstCallDone = false;
	//removeVOInventoryListener();
	cleanUpOldVersions();
	cleanUpBridgeFolder();
}
void FSLSLBridge::processDetach(LLViewerObject* object, const LLViewerJointAttachment* attachment)
{
	llinfos << "Entering processDetach" << llendl;

	if (gAgentAvatarp.isNull() || (!gAgentAvatarp->isSelf()) || (attachment == NULL) || (attachment->getName() != "Bridge"))
	{
		llwarns << "Couldn't detach bridge, object has wrong name or avatar wasn't self." << llendl;
		return;
	}

	LLViewerInventoryItem* fsObject = gInventory.getItem(object->getAttachmentItemID());
	if (fsObject == NULL) //just in case
	{
		llwarns << "Couldn't detach bridge. inventory object was NULL." << llendl;
		return;
	}
	//is it in the right place?
	LLUUID catID = findFSCategory();
	if (catID != fsObject->getParentUUID())
	{
		//that was in the wrong place. It's not ours.
		llwarns << "Bridge seems to be the wrong inventory category. Aborting detachment." << llendl;
		return;
	}
	if (mpBridge != NULL && mpBridge->getUUID() == fsObject->getUUID()) 
	{
		mpBridge = NULL;
		reportToNearbyChat(LLTrans::getString("fsbridge_detached"));
		mIsFirstCallDone = false;
		if (mBridgeCreating)
		{
			reportToNearbyChat(LLTrans::getString("fsbridge_warning_not_finished"));
			mBridgeCreating = false; //in case we interrupted the creation
		}
	}

	llinfos << "processDetach Finished" << llendl;
}
//
//Bridge initialization
//
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(LLTrans::getString("fsbridge_no_library"));
		mBridgeCreating = false;
		return;
	}

	if (mBridgeCreating)
	{
		llwarns << "Bridge creation already in progress, aborting new attempt." << llendl;
		reportToNearbyChat(LLTrans::getString("fsbridge_already_creating"));
		return;
	}

	LLUUID catID = findFSCategory();

	LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);
	if (fsBridge != NULL)
	{
		if (get_is_item_worn(fsBridge->getUUID()))
		{
			LLVOAvatarSelf::detachAttachmentIntoInventory(fsBridge->getUUID());
		}
	}
	// clear the stored bridge ID - we are starting over.
	mpBridge = 0; //the object itself will get cleaned up when new one is created.

	initCreationStep();
}
void FSLSLBridge::cleanUpBridge()
{
	//something unexpected went wrong. Try to clean up and not crash.
	llwarns << "Bridge object not found. Can't proceed with creation, exiting." << llendl;
	reportToNearbyChat(LLTrans::getString("fsbridge_failure_not_found"));

	if (isBridgeValid())
	{
		gInventory.purgeObject(mpBridge->getUUID());
	}

	gInventory.notifyObservers();
	mpBridge = NULL;
	mBridgeCreating = false;
}
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(LLTrans::getString("fsbridge_warning_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::processAttach(LLViewerObject* object, const LLViewerJointAttachment* attachment)
{
	llinfos << "Entering processAttach, checking the bridge container - gInventory.isInventoryUsable=" << gInventory.isInventoryUsable()<< llendl;

	if ((!gAgentAvatarp->isSelf()) || (attachment->getName() != "Bridge"))
	{
		llwarns << "Bridge not created. Our bridge container attachment isn't named correctly." << llendl;
		if (mBridgeCreating)
		{
			reportToNearbyChat(LLTrans::getString("fsbridge_failure_creation_bad_name"));
			mBridgeCreating = false; //in case we interrupted the creation
		}
		return;
	}

	LLViewerInventoryItem* fsObject = gInventory.getItem(object->getAttachmentItemID());
	if (fsObject == NULL) //just in case
	{
		llwarns << "Bridge container is still NULL in inventory. Aborting." << llendl;
		if (mBridgeCreating)
		{
			reportToNearbyChat(LLTrans::getString("fsbridge_failure_creation_null"));
			mBridgeCreating = false; //in case we interrupted the creation
		}
		return;
	}
	if (mpBridge == NULL) //user is attaching an existing bridge?
	{
		//is it the right version?
		if (fsObject->getName() != mCurrentFullName)
		{
			LLVOAvatarSelf::detachAttachmentIntoInventory(fsObject->getUUID());
			llwarns << "Attempt to attach to bridge point an object other than current bridge" << llendl;
			reportToNearbyChat(LLTrans::getString("fsbridge_failure_attach_wrong_object"));
			if (mBridgeCreating)
			{
				mBridgeCreating = false; //in case we interrupted the creation
			}
			return;
		}
		//is it in the right place?
		LLUUID catID = findFSCategory();
		if (catID != fsObject->getParentUUID())
		{
			//the object is not where we think it is. Kick it off.
			LLVOAvatarSelf::detachAttachmentIntoInventory(fsObject->getUUID());
			llwarns << "Bridge container isn't in the correct inventory location. Detaching it and aborting." << llendl;
			if (mBridgeCreating)
			{
				reportToNearbyChat(LLTrans::getString("fs_bridge_failure_attach_wrong_location"));
				mBridgeCreating = false; //in case we interrupted the creation
			}
			return;
		}
		mpBridge = fsObject;
	}

	lldebugs << "Bridge container is attached, mpBridge not NULL, avatar is self, point is bridge, all is good." << llendl;


	if (fsObject->getUUID() != mpBridge->getUUID())
	{
		//something odd just got attached to bridge?
		llwarns << "Something unknown just got attached to bridge point, detaching and aborting." << llendl;
		if (mBridgeCreating)
		{
			reportToNearbyChat(LLTrans::getString("fsbridge_failure_attach_point_in_use"));
			mBridgeCreating = false; //in case we interrupted the creation
		}
		LLVOAvatarSelf::detachAttachmentIntoInventory(mpBridge->getUUID());
		return;
	}
	lldebugs << "Bridge container found is the same bridge we saved, id matched." << llendl;

	if (!mBridgeCreating) //just an attach. See what it is
	{
		// 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();
	}
	else
	{
		configureBridgePrim(object);
	}
}
void FSExport::addPrim(LLViewerObject* object, bool root)
{
	LLSD prim;
	LLUUID object_id = object->getID();
	bool default_prim = true;

	struct f : public LLSelectedNodeFunctor
	{
		LLUUID mID;
		f(const LLUUID& id) : mID(id) {}
		virtual bool apply(LLSelectNode* node)
		{
			return (node->getObject() && node->getObject()->mID == mID);
		}
	} func(object_id);
	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func);
	if (node)
	{
		if ((LLGridManager::getInstance()->isInSecondLife())
			&& object->permYouOwner()
			&& (gAgentID == node->mPermissions->getCreator() || megaPrimCheck(node->mPermissions->getCreator(), object)))
		{
			default_prim = false;
		}
#if OPENSIM
		if (LLGridManager::getInstance()->isInOpenSim()
		      && object->permYouOwner()
		      && object->permModify()
		      && object->permCopy()
		      && object->permTransfer())
		{
			default_prim = false;
		}
#endif
	}
	else
	{
		LL_WARNS("export") << "LLSelect node for " << object_id.asString() << " not found. Using default prim instead." << LL_ENDL;
		default_prim = true;
	}

	if (root)
	{
		if (object->isAttachment())
		{
			prim["attachment_point"] = ATTACHMENT_ID_FROM_STATE(object->getState());
		}
	}
	else
	{
		LLViewerObject* parent_object = (LLViewerObject*)object->getParent();
		prim["parent"] = parent_object->getID();
	}
	prim["position"] = object->getPosition().getValue();
	prim["scale"] = object->getScale().getValue();
	prim["rotation"] = ll_sd_from_quaternion(object->getRotation());

	if (default_prim)
	{
		LL_DEBUGS("export") << object_id.asString() << " failed export check. Using default prim" << LL_ENDL;
		prim["flags"] = ll_sd_from_U32((U32)0);
		prim["volume"]["path"] = LLPathParams().asLLSD();
		prim["volume"]["profile"] = LLProfileParams().asLLSD();
		prim["material"] = (S32)LL_MCODE_WOOD;
	}
	else
	{
		mExported = true;
		prim["flags"] = ll_sd_from_U32(object->getFlags());
		prim["volume"]["path"] = object->getVolume()->getParams().getPathParams().asLLSD();
		prim["volume"]["profile"] = object->getVolume()->getParams().getProfileParams().asLLSD();
		prim["material"] = (S32)object->getMaterial();
		if (object->getClickAction() != 0)
		{
			prim["clickaction"] = (S32)object->getClickAction();
		}

		LLVOVolume *volobjp = NULL;
		if (object->getPCode() == LL_PCODE_VOLUME)
		{
			volobjp = (LLVOVolume *)object;
		}
		if(volobjp)
		{
			if(volobjp->isSculpted())
			{
				const LLSculptParams *sculpt_params = (const LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
				if (sculpt_params)
				{
					if(volobjp->isMesh())
					{
						if (!mAborted)
						{
							reportToNearbyChat(LLTrans::getString("export_fail_no_mesh"));
							mAborted = true;
						}
						return;
					}
					else
					{
						if (exportTexture(sculpt_params->getSculptTexture()))
						{
							prim["sculpt"] = sculpt_params->asLLSD();
						}
						else
						{
							LLSculptParams default_sculpt;
							prim["sculpt"] = default_sculpt.asLLSD();
						}
					}
				}
			}

			if(volobjp->isFlexible())
			{
				const LLFlexibleObjectData *flexible_param_block = (const LLFlexibleObjectData *)object->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
				if (flexible_param_block)
				{
					prim["flexible"] = flexible_param_block->asLLSD();
				}
			}

			if (volobjp->getIsLight())
			{
				const LLLightParams *light_param_block = (const LLLightParams *)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT);
				if (light_param_block)
				{
					prim["light"] = light_param_block->asLLSD();
				}
			}

			if (volobjp->hasLightTexture())
			{
				const LLLightImageParams* light_image_param_block = (const LLLightImageParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
				if (light_image_param_block)
				{
					prim["light_texture"] = light_image_param_block->asLLSD();
				}
			}
			
		}

		if(object->isParticleSource())
		{
			LLViewerPartSourceScript* partSourceScript = object->getPartSourceScript();
			prim["particle"] = partSourceScript->mPartSysData.asLLSD();
			if (!exportTexture(partSourceScript->mPartSysData.mPartImageID))
			{
				prim["particle"]["PartImageID"] = LLUUID::null.asString();
			}
		}

		U8 texture_count = object->getNumTEs();
		for(U8 i = 0; i < texture_count; ++i)
		{
			if (exportTexture(object->getTE(i)->getID()))
			{
				prim["texture"].append(object->getTE(i)->asLLSD());
			}
			else
			{
				LLTextureEntry te(LL_DEFAULT_WOOD_UUID); // TODO: use user option of default texture.
				prim["texture"].append(te.asLLSD());
			}
		}

		if (!object->getPhysicsShapeUnknown())
		{
			prim["ExtraPhysics"]["PhysicsShapeType"] = (S32)object->getPhysicsShapeType();
			prim["ExtraPhysics"]["Density"] = (F64)object->getPhysicsDensity();
			prim["ExtraPhysics"]["Friction"] = (F64)object->getPhysicsFriction();
			prim["ExtraPhysics"]["Restitution"] = (F64)object->getPhysicsRestitution();
			prim["ExtraPhysics"]["GravityMultiplier"] = (F64)object->getPhysicsGravity();
		}

		prim["name"] = node->mName;
		prim["description"] = node->mDescription;
		prim["creation_date"] = ll_sd_from_U64(node->mCreationDate);

		LLAvatarName avatar_name;
		LLUUID creator_id = node->mPermissions->getCreator();
		if (creator_id.notNull())
		{
			prim["creator_id"] = creator_id;
			if (LLAvatarNameCache::get(creator_id, &avatar_name))
			{
				prim["creator_name"] = avatar_name.asLLSD();
			}
		}
		LLUUID owner_id = node->mPermissions->getOwner();
		if (owner_id.notNull())
		{
			prim["owner_id"] = owner_id;
			if (LLAvatarNameCache::get(owner_id, &avatar_name))
			{
				prim["owner_name"] = avatar_name.asLLSD();
			}
		}
		LLUUID group_id = node->mPermissions->getGroup();
		if (group_id.notNull())
		{
			prim["group_id"] = group_id;
			if (LLAvatarNameCache::get(group_id, &avatar_name))
			{
				prim["group_name"] = avatar_name.asLLSD();
			}
		}
		LLUUID last_owner_id = node->mPermissions->getLastOwner();
		if (last_owner_id.notNull())
		{
			prim["last_owner_id"] = last_owner_id;
			if (LLAvatarNameCache::get(last_owner_id, &avatar_name))
			{
				prim["last_owner_name"] = avatar_name.asLLSD();
			}
		}
		prim["base_mask"] = ll_sd_from_U32(node->mPermissions->getMaskBase());
		prim["owner_mask"] = ll_sd_from_U32(node->mPermissions->getMaskOwner());
		prim["group_mask"] = ll_sd_from_U32(node->mPermissions->getMaskGroup());
		prim["everyone_mask"] = ll_sd_from_U32(node->mPermissions->getMaskEveryone());
		prim["next_owner_mask"] = ll_sd_from_U32(node->mPermissions->getMaskNextOwner());
		
		prim["sale_info"] = node->mSaleInfo.asLLSD();
		prim["touch_name"] = node->mTouchName;
		prim["sit_name"] = node->mSitName;

		mInventoryRequests.push_back(object_id);
		object->registerInventoryListener(this, NULL);
		object->dirtyInventory();
		object->requestInventory();
	}

	mFile["prim"][object_id.asString()] = prim;
}