diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 472c7a03d2..4a88394ce4 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -344,6 +344,12 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd prefix += mDirDelimiter; prefix += "character"; break; + + case LL_PATH_FS_RESOURCES: + prefix = getAppRODataDir(); + prefix += mDirDelimiter; + prefix += "fs_resources"; + break; case LL_PATH_HELP: prefix = "help"; diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index d6de0f0af3..82ec675993 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -54,6 +54,7 @@ typedef enum ELLPath LL_PATH_DEFAULT_SKIN = 17, LL_PATH_FONTS = 18, LL_PATH_TOP_SKINTHEME = 19, // KB - Catznip Viewer-Skins + LL_PATH_FS_RESOURCES = 20, // TT - Firestorm data LL_PATH_LAST } ELLPath; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 45bc1c1e6d..a76a1c9b3e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -80,6 +80,8 @@ set(viewer_SOURCE_FILES fsareasearch.cpp fsdata.cpp fskeywords.cpp + fslslbridge.cpp + fslslbridgerequest.cpp fsradarlistctrl.cpp llagent.cpp llagentaccess.cpp @@ -646,6 +648,8 @@ set(viewer_HEADER_FILES fsareasearch.h fsdata.h fskeywords.h + fslslbridge.h + fslslbridgerequest.h llagent.h llagentaccess.h llagentcamera.h diff --git a/indra/newview/aoengine.cpp b/indra/newview/aoengine.cpp index 0b06bbc3a1..b8e8f77e7c 100644 --- a/indra/newview/aoengine.cpp +++ b/indra/newview/aoengine.cpp @@ -34,16 +34,15 @@ #include "llanimationstates.h" #include "llassetstorage.h" #include "llcommon.h" -#include "llinventoryfunctions.h" +#include "llinventoryfunctions.h" // for ROOT_FIRESTORM_FOLDER #include "llinventorymodel.h" -#include "llinventoryobserver.h" +#include "llinventoryobserver.h" #include "llstring.h" #include "llvfs.h" #include "llviewercontrol.h" #include "llviewerinventory.h" -// is there a global define for this folder somewhere? -#define ROOT_FIRESTORM_FOLDER "#Firestorm" +//#define ROOT_FIRESTORM_FOLDER "#Firestorm" //moved to llinventoryfunctions.h #define ROOT_AO_FOLDER "#AO" #include diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 13da964d1e..bc1235e2bd 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12394,6 +12394,17 @@ Change of this parameter will affect the layout of buttons in notification toast LLSD Value + UseLSLBridge + + Comment + Use the client LSL bridge for lsl functionality + Persist + 1 + Type + Boolean + Value + 1 + VFSOldSize Comment diff --git a/indra/newview/fs_resources/EBEDD1D2-A320-43f5-88CF-DD47BBCA5DFB.lsltxt b/indra/newview/fs_resources/EBEDD1D2-A320-43f5-88CF-DD47BBCA5DFB.lsltxt new file mode 100644 index 0000000000..4ba3c1d325 --- /dev/null +++ b/indra/newview/fs_resources/EBEDD1D2-A320-43f5-88CF-DD47BBCA5DFB.lsltxt @@ -0,0 +1,233 @@ +//http bridge draft 0.1.7 +//Firestorm +//Tozh Taurog, Arrehn Oberlander + +// +// global Variables +// + + // Bridge platform + string bridgeURL; + string latestURL; + integer channel = 99; + integer debug = FALSE; //TRUE for verbose debugging + integer httpStatus = 200; + //key httpReqID; + + // for teleport + integer MAX_TIME_TO_TP = 10; //should be set to 10 for normal use + vector mttVector; // target for llMoveToTarget() teleport + integer startTimer; + + // for object details + vector opVector; // object position for llGetobjectDetails() + key opUUID; // key for llGetobjectDetails() + list opObjDetails; // result for llGetobjectDetails() + +// +// helper functions +// + + initBridge() + { + llRequestURL(); + debugOutput("rezzed"); + + if(llGetAttached() != 0) + { + llRequestPermissions(llGetOwner(),PERMISSION_TAKE_CONTROLS); + } + } + + saveNewURL(string url) + { + latestURL = url; + } + + parseCommand(key httpReqID, string msg) + { + debugOutput("Parsing original input: " + msg); + //remove the wrapper + integer end = llStringLength(msg) - llStringLength("") -1; + string inner = llGetSubString(msg, 6, end - 1); + + debugOutput("Parsing inner string: " + inner); + //remove the wrapper + end = llStringLength(inner) - llStringLength("") -1; + string msgClean = llGetSubString(inner, 8, end); + + debugOutput("Parsing final string: " + msgClean); + list commandList = llParseString2List(msgClean,["|"],[]); + //get command name + string cmd = llList2String(commandList,0); + + debugOutput("Parsing command: " + cmd); + + //Large If statement for command processing. Shame on you, LSL! + if (cmd == "llMoveToTarget") + { + // Get parameters + string params = "<" + llList2String(commandList,1) + ">"; + debugOutput("Parsing params: " + params); + + mttVector=(vector)params; + + debugOutput("Parsing vector: " + (string)mttVector); + + startTimer = llGetUnixTime(); + llSetTimerEvent(0.05); + + //llHTTPResponse(httpReqID, httpStatus, "test response from llMoveToTarget"); + }// "llMoveToTarget" + + else if (cmd == "llGetObjectDetails") + { + // Get parameters + opUUID = (key)llList2String(commandList, 1); + + //string opV = "<" + llList2String(commandList,2) + ">"; + //debugOutput("Parsing params: " + opV); + + //opVector=(vector)opV; + //debugOutput("Parsing vector: " + (string)opVector); + + opObjDetails = llGetObjectDetails(opUUID, ([OBJECT_POS])); + string body = "" + llList2String(opObjDetails,0) + ""; + llHTTPResponse(httpReqID, httpStatus, body); + + }// "llGetObjectDetails" + + } + + debugOutput(string msg) + { + if (debug) + { + llOwnerSay("BridgeDebug: " + msg); + } + } + +// +// main +// + +default +{ + state_entry() + { + initBridge(); + // make bridge inconspicuous + llSetTexture("757c276e-6409-ad54-a862-ca89c04e4940",ALL_SIDES); + llSetScale(<0.01,0.01,0.01>); + } + + on_rez(integer i) + { + initBridge(); + } + + touch_start(integer total_number) + { + debugOutput("touched"); + + if (bridgeURL != latestURL) + { + //just in case, since we probably aren't there anymore + llReleaseURL(bridgeURL); + + bridgeURL = latestURL; + llOwnerSay("" + bridgeURL + ""); + llRequestURL(); + } + } + + run_time_permissions(integer i) + { + if(i) + { + llTakeControls(1024,TRUE,TRUE); + } + } + + changed(integer change) + { + if (change & CHANGED_REGION) + { + llRequestURL(); + debugOutput("The region the bridge is in has changed."); + } + } + + timer() + { + llSetTimerEvent(0.0); + + vector loc = llGetPos(); // current position + + + vector targ = mttVector - loc; + //has to be less than 65m + float dist = llVecMag(targ); + + debugOutput("current: " + (string)loc + " target: " + (string)targ + " tp distance: " + (string)dist); + + //if we are out of time or distance - stop + if((dist < 2.0) || (llGetUnixTime() - MAX_TIME_TO_TP > startTimer) || (mttVector == loc)) + { + llStopMoveToTarget(); + //llHTTPResponse(httpReqID, httpStatus, "Test MoveToTarget body"); + + return; + } + + if (dist < 65) + { + debugOutput("One jump to :" + (string)mttVector); + llMoveToTarget(mttVector, 0.05); + } + else + { + debugOutput("Multiple jump to :" + (string)(loc+llVecNorm(targ)*60)); + llMoveToTarget(loc+llVecNorm(targ)*60, 0.05); + } + + // try again. + llSetTimerEvent(.05); + } + + http_request(key ID, string Method, string Body) + { + //httpReqID = ID; + debugOutput("Received HTTP " + Method + " message. Command body: " + Body); + + if (Method == URL_REQUEST_GRANTED) + { + saveNewURL(Body); + + //Saying URL to owner + llOwnerSay("" + latestURL+ ""); + } + else if (Method == URL_REQUEST_DENIED) + { + saveNewURL(""); + + debugOutput("No URLs free !"); + //keep trying? + llRequestURL(); + } + else if (Method == "GET") + { + parseCommand(ID, Body); + llHTTPResponse(ID, httpStatus, " command=\"GET\" text=\"get - Hello Bridge!"); + } + else if (Method == "PUT") + { + llHTTPResponse(ID, httpStatus, "PUT - Hello Bridge!"); + } + else if (Method == "POST") + { + parseCommand(ID, Body); + llHTTPResponse(ID, httpStatus, "POST - Hello Bridge!"); + } + } +} \ No newline at end of file diff --git a/indra/newview/fslslbridge.cpp b/indra/newview/fslslbridge.cpp new file mode 100644 index 0000000000..fa83d31a53 --- /dev/null +++ b/indra/newview/fslslbridge.cpp @@ -0,0 +1,424 @@ +/** + * @fslslbridge.cpp + * @FSLSLBridge implementation + * + * $LicenseInfo:firstyear=2011&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2011, The Phoenix Viewer Project, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * The Phoenix Viewer Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "fslslbridge.h" +#include "fslslbridgerequest.h" +#include "llxmlnode.h" +#include "llbufferstream.h" +#include "llsdserialize.h" +#include "llviewerinventory.h" +#include "llagent.h" +#include "llvoavatar.h" +#include "llattachmentsmgr.h" +#include "llinventorymodel.h" +#include "llinventoryfunctions.h" +#include "llviewerassettype.h" +#include "llfloaterreg.h" +#include "llinventorybridge.h" +#include "llpreviewscript.h" +#include "llselectmgr.h" +#include "llinventorydefines.h" +#include "llselectmgr.h" +#include "llviewerregion.h" +#include "llfoldertype.h" +#include "llhttpclient.h" +#include "llassetuploadresponders.h" + +#define phoenix_bridge_name "#LSL<->Client Bridge v0.12" +#define phoenix_folder_name "#Phoenix" + +#define LIB_ROCK_NAME "Rock - medium, round" + +//#define ROOT_FIRESTORM_FOLDER "#Firestorm" //moved to llinventoryfunctions to synch with the AO object +#define FS_BRIDGE_NAME "#Firestorm LSL Bridge v" +#define FS_BRIDGE_MAJOR_VERSION 1 +#define FS_BRIDGE_MINOR_VERSION 7 + +const std::string UPLOAD_SCRIPT_1_7 = "EBEDD1D2-A320-43f5-88CF-DD47BBCA5DFB.lsltxt"; + +static const U8 BRIDGE_POINT = 127; + +// +//-TT Client LSL Bridge File +// +class NameCollectFunctor : public LLInventoryCollectFunctor +{ +public: + NameCollectFunctor(std::string name) + { + sName = name; + } + virtual ~NameCollectFunctor() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) + { + if(item) + { + return (item->getName() == sName); + } + return false; + } +private: + std::string sName; +}; + +// +// +// Bridge functionality +// +FSLSLBridge :: FSLSLBridge(): + mBridgeAttaching(false), + mpBridge(NULL) +{ + std::stringstream sstr; + + sstr << FS_BRIDGE_NAME; + sstr << FS_BRIDGE_MAJOR_VERSION; + sstr << "."; + sstr << FS_BRIDGE_MINOR_VERSION; + + mCurrentFullName = sstr.str(); + + //mBridgeAttaching = false; + //mpBridge = NULL; +} + +FSLSLBridge :: ~FSLSLBridge() +{ +} + +bool FSLSLBridge :: lslToViewer(std::string message, LLUUID fromID, LLUUID ownerID) +{ + if (!gSavedSettings.getBOOL("UseLSLBridge")) + return false; + + llinfos << message << llendl; + + std::string tag = message.substr(0,11); + + if (tag == "") + { + if (mpBridge == NULL) + { + LLUUID catID = findFSCategory(); + LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT); + + if (fsBridge != NULL) + mpBridge = fsBridge; + } + + // get the content of the message, between and + mCurrentURL = message.substr(tag.length(), message.length() - ((tag.length() * 2) + 1)); + llinfos << "New URL is: " << mCurrentURL << llendl; + //TODO need to check if bridge finished attaching + return true; + } + return false; +} + +bool FSLSLBridge :: viewerToLSL(std::string message, FSLSLBridgeRequestResponder *responder) +{ + if (!gSavedSettings.getBOOL("UseLSLBridge")) + return false; + + if (responder == NULL) + responder = new FSLSLBridgeRequestResponder(); + LLHTTPClient::post(mCurrentURL, LLSD(message), responder); + + return true; +} + +// +//Bridge initialization +// +void FSLSLBridge :: initBridge() +{ + if (!gSavedSettings.getBOOL("UseLSLBridge")) + return; + + //are we already in conversation with a bridge? + if (mpBridge != NULL) + { + return; + } + + //if bridge object doesn't exist - create and attach it, update script. + LLUUID rootID = gInventory.getRootFolderID(); + LLUUID catID = findFSCategory(); + + LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT); + if (fsBridge == NULL) + { + mBridgeAttaching = true; + createNewBridge(); + } + else + { + //TODO need versioning - see isOldBridgeVersion() + mpBridge = fsBridge; + if (!isItemAttached(mpBridge->getUUID())) + LLAttachmentsMgr::instance().addAttachment(mpBridge->getUUID(), BRIDGE_POINT, FALSE, TRUE); + } +} + +void FSLSLBridge :: createNewBridge() +{ + //check if user has a bridge + LLUUID rootID = gInventory.getRootFolderID(); + LLUUID catID = findFSCategory(); + + //attach the Linden rock from the library (can we resize from here?) + LLUUID libID = gInventory.getLibraryRootFolderID(); + LLViewerInventoryItem* libRock = findInvObject(LIB_ROCK_NAME, libID, LLAssetType::AT_OBJECT); + //shouldn't happen but just in case + if (libRock != NULL) + { + //copy the library item to inventory and put it on + LLPointer cb = new FSLSLBridgeRezCallback(); + copy_inventory_item(gAgent.getID(),libRock->getPermissions().getOwner(),libRock->getUUID(),catID,mCurrentFullName,cb); + } +} + +void FSLSLBridge :: processAttach(LLViewerObject *object, const LLViewerJointAttachment *attachment) +{ + if ((mpBridge == NULL) || (!mBridgeAttaching) || (!gAgentAvatarp->isSelf())) + return; + LLViewerInventoryItem *fsObject = gInventory.getItem(object->getAttachmentItemID()); + if (fsObject->getUUID() != mpBridge->getUUID()) + return; + + mpBridge->setDescription(mCurrentFullName); + + //add bridge script to object + if (object) + { + create_script_inner(object); + } +} + +void FSLSLBridge :: create_script_inner(LLViewerObject* object) +{ + LLUUID catID = findFSCategory(); + + LLPointer cb = new FSLSLBridgeScriptCallback(); + create_inventory_item(gAgent.getID(), + gAgent.getSessionID(), + catID, //LLUUID::null, + LLTransactionID::tnull, + mCurrentFullName, + mCurrentFullName, + LLAssetType::AT_LSL_TEXT, + LLInventoryType::IT_LSL, + NOT_WEARABLE, + mpBridge->getPermissions().getMaskNextOwner(), + cb); + +} + +// +// Bridge rez callback +// +FSLSLBridgeRezCallback :: FSLSLBridgeRezCallback() +{ +} +FSLSLBridgeRezCallback :: ~FSLSLBridgeRezCallback() +{ +} + +void FSLSLBridgeRezCallback :: fire(const LLUUID& inv_item) +{ + if (inv_item.isNull()) + return; + + //detach from default and put on the right point + LLVOAvatarSelf::detachAttachmentIntoInventory(inv_item); + LLAttachmentsMgr::instance().addAttachment(inv_item, BRIDGE_POINT, FALSE, TRUE); + + LLViewerInventoryItem *item = gInventory.getItem(inv_item); + FSLSLBridge::instance().setBridge(item); +} + + +// +// Bridge script creation callback +// +FSLSLBridgeScriptCallback :: FSLSLBridgeScriptCallback() +{ +} +FSLSLBridgeScriptCallback :: ~FSLSLBridgeScriptCallback() +{ +} + +void FSLSLBridgeScriptCallback::fire(const LLUUID& inv_item) +{ + if (inv_item.isNull()) + return; + + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (!item) + { + return; + } + gInventory.updateItem(item); + gInventory.notifyObservers(); + + LLViewerObject* obj = gAgentAvatarp->getWornAttachment(FSLSLBridge::instance().getBridge()->getUUID()); + + //caps import + std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); + std::string isMono = "lsl2"; //could also be "mono" + if (!url.empty()) + { + const std::string fName = prepUploadFile(); + LLLiveLSLEditor::uploadAssetViaCapsStatic(url, fName, + obj->getID(), inv_item, isMono, true); + } + else + { + //can't complete bridge creation - detach and remove object, remove script + LLVOAvatarSelf::detachAttachmentIntoInventory(FSLSLBridge::instance().getBridge()->getUUID()); + + LLViewerInventoryItem* bridgeItem = FSLSLBridge::instance().getBridge(); + gInventory.deleteObject(bridgeItem->getUUID()); + bridgeItem->removeFromServer(); + + gInventory.deleteObject(item->getUUID()); + item->removeFromServer(); + + gInventory.notifyObservers(); + } + llinfos << "updating script ID for bridge" << llendl; + FSLSLBridge::instance().mScriptItemID = inv_item; +} + +std::string FSLSLBridgeScriptCallback::prepUploadFile() +{ + std::string fName = gDirUtilp->getExpandedFilename(LL_PATH_FS_RESOURCES, UPLOAD_SCRIPT_1_7); + std::string fNew = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,UPLOAD_SCRIPT_1_7); + + //open script text file + typedef std::istream_iterator istream_iterator; + std::ifstream file(fName.c_str()); + + typedef std::ostream_iterator ostream_iterator; + std::ofstream tempFile(fNew.c_str()); + + file >> std::noskipws; + std::copy(istream_iterator(file), istream_iterator(), ostream_iterator(tempFile)); + + return fNew; +} + +void FSLSLBridge :: checkBridgeScriptName(std::string fileName) +{ + if ((fileName.length() == 0) || !mBridgeAttaching) + return; + //need to parse out the last length of a GUID and compare to saved possible names. + std::string fileOnly = fileName.substr(fileName.length()-UPLOAD_SCRIPT_1_7.length(), UPLOAD_SCRIPT_1_7.length()); + + if (fileOnly == UPLOAD_SCRIPT_1_7) + { + //this is our script upload + LLViewerObject* obj = gAgentAvatarp->getWornAttachment(mpBridge->getUUID()); + obj->saveScript(gInventory.getItem(mScriptItemID), TRUE, false); + mBridgeAttaching = false; + } +} + + +// +// Helper functions +/// +bool FSLSLBridge :: isItemAttached(LLUUID iID) +{ + return (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(iID)); +} + +LLUUID FSLSLBridge :: findFSCategory() +{ + LLUUID catID; + catID = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER); + if(catID.isNull()) + { + catID = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, ROOT_FIRESTORM_FOLDER); + } + return catID; +} +LLViewerInventoryItem* FSLSLBridge :: findInvObject(std::string obj_name, LLUUID catID, LLAssetType::EType type) +{ + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + + //gInventory.findCategoryByName + LLUUID itemID; + NameCollectFunctor namefunctor(obj_name); + + gInventory.collectDescendentsIf(catID,cats,items,FALSE,namefunctor); + + for (S32 iIndex = 0; iIndex < items.count(); iIndex++) + { + const LLViewerInventoryItem* itemp = items.get(iIndex); + if (!itemp->getIsLinkType() && (itemp->getType() == LLAssetType::AT_OBJECT)) + { + itemID = itemp->getUUID(); + break; + } + } + + if (itemID.notNull()) + { + LLViewerInventoryItem* item = gInventory.getItem(itemID); + return item; + } + return NULL; +} + +bool FSLSLBridge :: isOldBridgeVersion(LLInventoryItem *item) +{ +// if (!item) +// return; +// if (!boost::regex_match(item->getName(), BridgePattern)) +// +// std::string str = item->getName(); +// +// (item) && boost::regex_match(item->getName(), AnyBridgePattern); +// +// std::string tmpl = FS_BRIDGE_NAME; +// +// string::size_type found = str.find_first_of("."); +// +// while( found != string::npos ) {} +// +// std::string sMajor = str.substr(strlen(tmpl.c_str)-1, dotPos); +// std::string sMinor = str.substr(strlen(tmpl.c_str)+strlen(sMajor)); +// +// int iMajor = atoi(sMajor); +// float fMinor = atof(sMinor); + + return false; +} + diff --git a/indra/newview/fslslbridge.h b/indra/newview/fslslbridge.h new file mode 100644 index 0000000000..b3da744723 --- /dev/null +++ b/indra/newview/fslslbridge.h @@ -0,0 +1,105 @@ +/** + * @fslslbridge.h + * @FSLSLBridge header + * + * $LicenseInfo:firstyear=2011&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2011, The Phoenix Viewer Project, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * The Phoenix Viewer Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * $/LicenseInfo$ + */ +#ifndef FS_LSLBRIDGE_H +#define FS_LSLBRIDGE_H + +#include "llviewerprecompiledheaders.h" +#include "llchat.h" +#include "llhttpclient.h" +#include "llinventorymodel.h" +#include "fslslbridgerequest.h" +#include "llviewerinventory.h" + +// +//-TT Client LSL Bridge File +// + +class FSLSLBridge : public LLSingleton, public LLHTTPClient::Responder +{ + friend class FSLSLBridgeScriptCallback; + friend class FSLSLBridgeRezCallback; + +public: + FSLSLBridge(); + ~FSLSLBridge(); + + bool lslToViewer(std::string message, LLUUID fromID, LLUUID ownerID); + bool viewerToLSL(std::string message, FSLSLBridgeRequestResponder *responder = NULL); + void initBridge(); + void processAttach(LLViewerObject *object, const LLViewerJointAttachment *attachment); + bool bridgeAttaching(bool status) {return mBridgeAttaching = status; }; + void setBridge(LLViewerInventoryItem* item) { mpBridge = item; }; + LLViewerInventoryItem* getBridge() { return mpBridge; }; + void checkBridgeScriptName(std::string fileName); + +protected: + + /*virtual*/ void inventoryChanged(LLViewerObject* obj, + LLInventoryObject::object_list_t* inv, + S32 serial_num, + void* queue); + LLUUID mScriptItemID; //internal script ID + +private: + std::string mCurrentURL; + int mCurrentChannel; + bool mBridgeAttaching; + LLViewerInventoryItem* mpBridge; + std::string mCurrentFullName; + +private: + LLViewerInventoryItem* findInvObject(std::string obj_name, LLUUID catID, LLAssetType::EType type); + LLUUID findFSCategory(); + bool isItemAttached(LLUUID iID); + void createNewBridge(); + void create_script_inner(LLViewerObject* object); + bool isOldBridgeVersion(LLInventoryItem *item); +}; + + +class FSLSLBridgeRezCallback : public LLInventoryCallback +{ +public: + FSLSLBridgeRezCallback(); + void fire(const LLUUID& inv_item); + +protected: + ~FSLSLBridgeRezCallback(); +}; + +class FSLSLBridgeScriptCallback : public LLInventoryCallback +{ +public: + FSLSLBridgeScriptCallback(); + void fire(const LLUUID& inv_item); + std::string prepUploadFile(); + +protected: + ~FSLSLBridgeScriptCallback(); +}; + + +#endif // FS_LSLBRIDGE_H diff --git a/indra/newview/fslslbridgerequest.cpp b/indra/newview/fslslbridgerequest.cpp new file mode 100644 index 0000000000..d779710db3 --- /dev/null +++ b/indra/newview/fslslbridgerequest.cpp @@ -0,0 +1,84 @@ +/** + * @fslslbridgerequest.cpp + * @FSLSLBridgerequest implementation + * + * $LicenseInfo:firstyear=2011&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2011, The Phoenix Viewer Project, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * The Phoenix Viewer Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "fslslbridgerequest.h" +#include "fslslbridge.h" +#include "llagent.h" // for gAgent +#include "llhttpclient.h" + +#ifdef LL_STANDALONE +#include +#else +#include "expat/expat.h" +#endif + +// +//-TT Client LSL Bridge File +// + +FSLSLBridgeRequestManager::FSLSLBridgeRequestManager() +{ +} + +FSLSLBridgeRequestManager::~FSLSLBridgeRequestManager() +{ +} + +void FSLSLBridgeRequestManager::initSingleton() +{ +} +void FSLSLBridgeRequestManager::processBridgeCall(const LLSD& content) +{ + std::string strContent = content.asString(); + llinfos << "Got info: " << strContent << llendl; + +} + +FSLSLBridgeRequestResponder::FSLSLBridgeRequestResponder() +{ + //FSLSLBridgeRequestManager::instance().initSingleton(); +} +//If we get back a normal response, handle it here +void FSLSLBridgeRequestResponder::result(const LLSD& content) +{ + //FSLSLBridgeRequestManager::instance().processBridgeCall(content); + std::string strContent = content.asString(); + llinfos << "Got info: " << strContent << llendl; + + //do not use - infinite loop, only here for testing. + //FSLSLBridge::instance().viewerToLSL("Response_to_response|" + strContent); +} + +//If we get back an error (not found, etc...), handle it here +void FSLSLBridgeRequestResponder::error(U32 status, const std::string& reason) +{ + llwarns << "FSLSLBridgeRequest::error(" + << status << ": " << reason << ")" << llendl; +} + + + diff --git a/indra/newview/fslslbridgerequest.h b/indra/newview/fslslbridgerequest.h new file mode 100644 index 0000000000..c9cf24120b --- /dev/null +++ b/indra/newview/fslslbridgerequest.h @@ -0,0 +1,63 @@ +/** + * @fslslbridgerequest.h + * @FSLSLBridgerequest header + * + * $LicenseInfo:firstyear=2011&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2011, The Phoenix Viewer Project, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * The Phoenix Viewer Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * $/LicenseInfo$ + */ + +#ifndef FS_LSLBRIDGEREQUEST_H +#define FS_LSLBRIDGEREQUEST_H + +#include "llviewerprecompiledheaders.h" +#include "llhttpclient.h" + +// +//-TT Client LSL Bridge File +// + +class FSLSLBridgeRequestManager //: public LLSingleton +{ +public: + FSLSLBridgeRequestManager(); + ~FSLSLBridgeRequestManager(); + + void processBridgeCall(const LLSD& content); + /* virtual */ void initSingleton(); +private: + LLSD mBridgeCalls; + + //friend class LLSingleton; + +}; + + +class FSLSLBridgeRequestResponder : public LLHTTPClient::Responder +{ +public: + FSLSLBridgeRequestResponder(); + //If we get back a normal response, handle it here + virtual void result(const LLSD& content); + //If we get back an error (not found, etc...), handle it here + virtual void error(U32 status, const std::string& reason); +}; + +#endif // FS_LSLBRIDGEREQUEST_H diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 1d1444c7db..e1f0b4c15d 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -80,6 +80,9 @@ // [RLVa:KB] - Checked: 2010-03-07 (RLVa-1.2.0c) #include "rlvhandler.h" // [/RLVa:KB] +//-TT Client LSL Bridge +#include "fslslbridge.h" +//-TT #include "kcwlinterface.h" using namespace LLVOAvatarDefines; @@ -3377,6 +3380,25 @@ void LLAgent::clearVisualParams(void *data) //--------------------------------------------------------------------------- // Teleport //--------------------------------------------------------------------------- +//-TT Client LSL Bridge +bool LLAgent::teleportBridgeLocal(LLVector3& pos_local) +{ + std::stringstream msgstream; + msgstream << std::setiosflags(std::ios::fixed) << std::setprecision(6); + msgstream << pos_local.mV[VX] << ", " << pos_local.mV[VY] << ", " << pos_local.mV[VZ]; + + return FSLSLBridge::instance().viewerToLSL("llMoveToTarget|" + msgstream.str()); +} + +bool LLAgent::teleportBridgeGlobal(const LLVector3d& pos_global) +{ + U64 region_handle = to_region_handle(pos_global); + LLVector3 pos_local = (LLVector3)(pos_global - from_region_handle(region_handle)); + + return teleportBridgeLocal(pos_local); + +} +//-TT Client LSL Bridge // teleportCore() - stuff to do on any teleport // protected @@ -3583,6 +3605,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) LLViewerRegion* regionp = getRegion(); U64 handle = to_region_handle(pos_global); + bool isLocal = (regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY])); LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); if(regionp && info) { @@ -3593,8 +3616,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) (F32)(pos_global.mdV[VZ])); teleportRequest(handle, pos_local); } - else if(regionp && - teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY]))) + else if(regionp && teleportCore(isLocal)) { llwarns << "Using deprecated teleportlocationrequest." << llendl; // send the message @@ -3618,6 +3640,12 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) msg->addVector3Fast(_PREHASH_LookAt, pos); sendReliableMessage(); } +//-TT Client LSL Bridge + if (gSavedSettings.getBOOL("UseLSLBridge") && isLocal) + { + teleportBridgeGlobal(pos_global); + } +//-TT } // Teleport to global position, but keep facing in the same direction @@ -3638,6 +3666,14 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) U64 region_handle = to_region_handle(pos_global); LLVector3 pos_local = (LLVector3)(pos_global - from_region_handle(region_handle)); teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); + +//-TT Client LSL Bridge + if (gSavedSettings.getBOOL("UseLSLBridge")) + { + if (region_handle == to_region_handle(getPositionGlobal())) + teleportBridgeLocal(pos_local); + } +//-TT } void LLAgent::setTeleportState(ETeleportState state) diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index fd56dba589..36ac0e1604 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -551,9 +551,14 @@ public: void teleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation void teleportCancel(); // May or may not be allowed by server bool getTeleportKeepsLookAt() { return mbTeleportKeepsLookAt; } // Whether look-at reset after teleport +//-TT Client LSL Bridge + bool teleportBridgeLocal(LLVector3& pos_local); // Teleport using LSL Bridge + bool teleportBridgeGlobal(const LLVector3d& pos_global); // Teleport using LSL Bridge +//-TT protected: bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed + //-------------------------------------------------------------------- // Teleport State //-------------------------------------------------------------------- diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index f25c3e2c25..65620d8e9e 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -51,6 +51,9 @@ #include "llviewerwindow.h" #include "lltexlayer.h" #include "lltrans.h" +//-TT Client LSL Bridge +#include "fslslbridge.h" +//-TT // library includes #include "lldir.h" @@ -466,6 +469,10 @@ void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content) preview->callbackLSLCompileFailed(content["errors"]); } } +//-TT Client LSL Bridge + if (gSavedSettings.getBOOL("UseLSLBridge")) + FSLSLBridge::instance().checkBridgeScriptName(mFileName); +//-TT break; } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index cfe1747fd4..7e94451551 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -32,6 +32,10 @@ #include "llfolderview.h" #include "llfolderviewitem.h" +//-TT - Firestorm folder name for use by AO, bridge and possibly others +#define ROOT_FIRESTORM_FOLDER "#Firestorm" +//-TT + /******************************************************************************** ** ** ** MISCELLANEOUS GLOBAL FUNCTIONS diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index e892e90842..5875850f04 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2081,6 +2081,23 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/) } } +//-TT //AO Custom Update Agent Inventory via capability +void LLLiveLSLEditor::uploadAssetViaCapsStatic(const std::string& url, + const std::string& filename, + const LLUUID& task_id, + const LLUUID& item_id, + const std::string& is_mono, + BOOL is_running) +{ + LLSD body; + body["item_id"] = item_id; + body["target"] = "lsl2"; + llinfos << "Upload caps body=" << body << " url=" << url << " id= " << item_id << llendl; + LLHTTPClient::post(url, body, + new LLUpdateAgentInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT)); +} +//-TT + void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, const std::string& filename, const LLUUID& task_id, diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index f86be615c4..d3a2841889 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -222,7 +222,15 @@ public: /*virtual*/ BOOL postBuild(); void setIsNew() { mIsNew = TRUE; } - +//-TT Client LSL Bridge + static void uploadAssetViaCapsStatic(const std::string& url, + const std::string& filename, + const LLUUID& task_id, + const LLUUID& item_id, + const std::string& is_mono, + BOOL is_running); +//-TT + private: virtual BOOL canClose(); void closeIfNeeded(); @@ -256,7 +264,6 @@ private: static void onReset(void* userdata); void loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type); - static void onErrorList(LLUICtrl*, void* user_data); static void* createScriptEdPanel(void* userdata); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index cfd3544dde..2c0e863789 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -190,6 +190,9 @@ // [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0a) #include "rlvhandler.h" // [/RLVa:KB] +//-TT Bridge +#include "fslslbridge.h" +//-TT #include "lllogin.h" #include "llevents.h" @@ -2023,6 +2026,11 @@ bool idle_startup() { set_startup_status(1.0, "", ""); +//-TT Client LSL Bridge + if (gSavedSettings.getBOOL("UseLSLBridge")) + FSLSLBridge::instance().initBridge(); +//-TT + // Let the map know about the inventory. LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); if(floater_world_map) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index ecd6cd1d4f..80c330ab5a 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -111,6 +111,9 @@ #include "rlvinventory.h" #include "rlvui.h" // [/RLVa:KB] +//-TT Client LSL Bridge +#include "fslslbridge.h" +//-TT #include "fsareasearch.h" #include "fsdata.h" @@ -3625,6 +3628,14 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) verb = LLTrans::getString("whisper") + " "; break; case CHAT_TYPE_OWNER: +//-TT Client LSL Bridge + llinfos << "CHAT_TYPE_OWNER: " << mesg << llendl; + if (gSavedSettings.getBOOL("UseLSLBridge")) + { + if(FSLSLBridge::instance().lslToViewer(mesg, from_id, owner_id)) + return; + } +//-TT // [RLVa:KB] - Checked: 2010-02-XX (RLVa-1.2.0a) | Modified: RLVa-1.1.0f // TODO-RLVa: [RLVa-1.2.0] consider rewriting this before a RLVa-1.2.0 release if ( (rlv_handler_t::isEnabled()) && (mesg.length() > 3) && (RLV_CMD_PREFIX == mesg[0]) && (CHAT_TYPE_OWNER == chat.mChatType) ) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 78ac3c1b79..d056dd7b32 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -59,6 +59,9 @@ // [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0a) #include "rlvhandler.h" // [/RLVa:KB] +//-TT Client LSL Bridge +#include "fslslbridge.h" +//-TT #if LL_MSVC // disable boost::lexical_cast warning @@ -1176,7 +1179,13 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view gRlvAttachmentLocks.updateLockedHUD(); } // [/RLVa:KB] +//-TT Patch: ReplaceWornItemsOnly gInventory.wearAttachmentsOnAvatarCheckRemove(viewer_object, attachment); +//-TT +//-TT Client LSL Bridge + if (gSavedSettings.getBOOL("UseLSLBridge")) + FSLSLBridge::instance().processAttach(viewer_object, attachment); +//-TT } return attachment; diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index a4cf3879ad..df3ffa14b5 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -88,6 +88,7 @@ class ViewerManifest(LLManifest): if self.prefix(src="fs_resources"): self.path("*.txt") self.path("*.lsl") + self.path("*.lsltxt") self.end_prefix("fs_resources"); # skins