/** * * Copyright (c) 2009-2016, Kitty Barnett * * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt * * By copying, modifying or distributing this software, you acknowledge that * you have read and understood your obligations described above, and agree to * abide by those obligations. * */ #include "llviewerprecompiledheaders.h" #include "llappearancemgr.h" #include "llattachmentsmgr.h" #include "llgesturemgr.h" #include "llnotificationsutil.h" #include "llviewerobjectlist.h" // FIRE-4453 bridge detached by the RLV command @remattach=force #include "fslslbridge.h" // FIRE-4453 #include "rlvcommon.h" #include "rlvhelper.h" #include "rlvhandler.h" #include "rlvinventory.h" #include // ============================================================================ // RlvBehaviourDictionary // /* * Processing of RLVa commands used to be a big switch/case loop with one function for each command type(addrem, reply * and force). This is slowly being replaced with templated command handling which might be more confusing intially * (also due to my poor naming schemes) but is actually far simpler and less error-prone than the old way. * * In the general case you just add a definition for the command below and then write the function body in rlvhandler.cpp * and you're done! Told you this was easy. * * Reply command * ============= * Definition: RlvReplyProcessor("commandname"[, ])); * Implement : ERlvCmdRet RlvReplyHandler::onCommand(const RlvCommand& rlvCmd, std::string& strReply) * * Force command * ============= * Definition: new RlvForceProcessor("commandname"[, ])); * Implement : ERlvCmdRet RlvForceProcessor::onCommand(const RlvCommand& rlvCmd) * * Behaviours * ========== * Behaviours come in many forms but the added complexity is only in the variety of choices. The implementation is as * easy as reply or force commands. * * For simple behaviours that only require recordkeeping and don't run code when set/unset (see ERlvBehaviourOptionType): * Definition: RlvBehaviourGenericProcessor("commandname", RLV_BHVR_COMMANDNAME) * Implement : nothing! (it automagically works) * For simple behaviours that only require recordkeeping and only run code when they toggle: * Definition: RlvBehaviourGenericToggleProcessor("commandname")) * Implement : void RlvBehaviourToggleHandler::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr) * For behaviours that require manual processing: * Definition: RlvBehaviourProcessor("commandname")) * Implement : ERlvCmdRet RlvBehaviourHandler::onCommand(const RlvCommand& rlvCmd, bool& fRefCount) * For behaviours that run code when their modifier changes: * Definition: addModifier(RLV_BHVR_COMMANDNAME, RLV_MODIFIER_COMMANDNAME, new RlvBehaviourModifierHandler(, , )); * Implement : void RlvBehaviourModifierHandler::onValueChanged() * */ RlvBehaviourDictionary::RlvBehaviourDictionary() { // Array auto-initialization to 0 is still not supported in VS2013 memset(m_BehaviourModifiers, 0, sizeof(RlvBehaviourModifier*) * RLV_MODIFIER_COUNT); // // Restrictions // addEntry(new RlvBehaviourGenericProcessor("acceptpermission", RLV_BHVR_ACCEPTPERMISSION)); addEntry(new RlvBehaviourGenericProcessor("accepttp", RLV_BHVR_ACCEPTTP, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourGenericProcessor("accepttprequest", RLV_BHVR_ACCEPTTPREQUEST, RlvBehaviourInfo::BHVR_STRICT | RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourProcessor("addattach")); addEntry(new RlvBehaviourInfo("addoutfit", RLV_BHVR_ADDOUTFIT, RLV_TYPE_ADDREM)); addEntry(new RlvBehaviourGenericProcessor("allowidle", RLV_BHVR_ALLOWIDLE, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourGenericProcessor("alwaysrun", RLV_BHVR_ALWAYSRUN)); addEntry(new RlvBehaviourInfo("attachthis", RLV_BHVR_ATTACHTHIS, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_NODE)); addEntry(new RlvBehaviourInfo("attachallthis", RLV_BHVR_ATTACHTHIS, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_SUBTREE)); addEntry(new RlvBehaviourInfo("attachthis_except", RLV_BHVR_ATTACHTHISEXCEPT, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_NODE)); addEntry(new RlvBehaviourInfo("attachallthis_except", RLV_BHVR_ATTACHTHISEXCEPT, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_SUBTREE)); addEntry(new RlvBehaviourGenericProcessor("chatwhisper", RLV_BHVR_CHATWHISPER)); addEntry(new RlvBehaviourGenericProcessor("chatnormal", RLV_BHVR_CHATNORMAL)); addEntry(new RlvBehaviourGenericProcessor("chatshout", RLV_BHVR_CHATSHOUT)); addEntry(new RlvBehaviourProcessor("detach")); addEntry(new RlvBehaviourInfo("detachthis", RLV_BHVR_DETACHTHIS, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_NODE)); addEntry(new RlvBehaviourInfo("detachallthis", RLV_BHVR_DETACHTHIS, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_SUBTREE)); addEntry(new RlvBehaviourInfo("detachthis_except", RLV_BHVR_DETACHTHISEXCEPT, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_NODE)); addEntry(new RlvBehaviourInfo("detachallthis_except", RLV_BHVR_DETACHTHISEXCEPT, RLV_TYPE_ADDREM, RlvBehaviourInfo::FORCEWEAR_SUBTREE)); addEntry(new RlvBehaviourGenericToggleProcessor("edit")); addEntry(new RlvBehaviourGenericProcessor("editobj", RLV_BHVR_EDITOBJ)); addEntry(new RlvBehaviourGenericProcessor("emote", RLV_BHVR_EMOTE)); addEntry(new RlvBehaviourGenericProcessor("fartouch", RLV_BHVR_FARTOUCH)); addModifier(RLV_BHVR_FARTOUCH, RLV_MODIFIER_FARTOUCHDIST, new RlvBehaviourModifier("Fartouch Distance", RLV_MODIFIER_FARTOUCH_DEFAULT, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericProcessor("fly", RLV_BHVR_FLY)); addEntry(new RlvBehaviourGenericProcessor("interact", RLV_BHVR_INTERACT, RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourInfo("notify", RLV_BHVR_NOTIFY, RLV_TYPE_ADDREM)); addEntry(new RlvBehaviourGenericProcessor("permissive", RLV_BHVR_PERMISSIVE)); addEntry(new RlvBehaviourGenericProcessor("recvchat", RLV_BHVR_RECVCHAT, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourGenericProcessor("recvchatfrom", RLV_BHVR_RECVCHATFROM, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourGenericProcessor("recvemote", RLV_BHVR_RECVEMOTE, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourGenericProcessor("recvemotefrom", RLV_BHVR_RECVEMOTEFROM, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourProcessor("recvim", RlvBehaviourInfo::BHVR_STRICT)); addModifier(RLV_BHVR_RECVIM, RLV_MODIFIER_RECVIMDISTMIN, new RlvBehaviourModifier("RecvIM Distance (Min)", F32_MAX, true, new RlvBehaviourModifier_CompMax)); addModifier(RLV_BHVR_RECVIM, RLV_MODIFIER_RECVIMDISTMAX, new RlvBehaviourModifier("RecvIM Distance (Max)", F32_MAX, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericProcessor("recvimfrom", RLV_BHVR_RECVIMFROM, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourInfo("redirchat", RLV_BHVR_REDIRCHAT, RLV_TYPE_ADDREM)); addEntry(new RlvBehaviourInfo("rediremote", RLV_BHVR_REDIREMOTE, RLV_TYPE_ADDREM)); addEntry(new RlvBehaviourProcessor("remattach")); addEntry(new RlvBehaviourInfo("remoutfit", RLV_BHVR_REMOUTFIT, RLV_TYPE_ADDREM)); addEntry(new RlvBehaviourGenericProcessor("rez", RLV_BHVR_REZ)); addEntry(new RlvBehaviourProcessor("sendchannel", RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourProcessor("sendchannel_except", RlvBehaviourInfo::BHVR_STRICT | RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourGenericProcessor("sendchat", RLV_BHVR_SENDCHAT)); addEntry(new RlvBehaviourToggleProcessor("sendim", RlvBehaviourInfo::BHVR_STRICT)); addModifier(RLV_BHVR_SENDIM, RLV_MODIFIER_SENDIMDISTMIN, new RlvBehaviourModifier("SendIM Distance (Min)", F32_MAX, true, new RlvBehaviourModifier_CompMax)); addModifier(RLV_BHVR_SENDIM, RLV_MODIFIER_SENDIMDISTMAX, new RlvBehaviourModifier("SendIM Distance (Max)", F32_MAX, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericProcessor("sendimto", RLV_BHVR_SENDIMTO, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourGenericProcessor("sendgesture", RLV_BHVR_SENDGESTURE, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourGenericToggleProcessor("setdebug")); addEntry(new RlvBehaviourGenericToggleProcessor("setenv")); addEntry(new RlvBehaviourGenericProcessor("setgroup", RLV_BHVR_SETGROUP)); addEntry(new RlvBehaviourInfo("sharedunwear", RLV_BHVR_SHAREDUNWEAR, RLV_TYPE_ADDREM, RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourInfo("sharedwear", RLV_BHVR_SHAREDWEAR, RLV_TYPE_ADDREM, RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourProcessor("showhovertext")); addEntry(new RlvBehaviourGenericProcessor("showhovertextall", RLV_BHVR_SHOWHOVERTEXTALL)); addEntry(new RlvBehaviourGenericProcessor("showhovertexthud", RLV_BHVR_SHOWHOVERTEXTHUD)); addEntry(new RlvBehaviourGenericProcessor("showhovertextworld", RLV_BHVR_SHOWHOVERTEXTWORLD)); addEntry(new RlvBehaviourGenericToggleProcessor("showinv")); addEntry(new RlvBehaviourGenericProcessor("showloc", RLV_BHVR_SHOWLOC)); addEntry(new RlvBehaviourGenericProcessor("showminimap", RLV_BHVR_SHOWMINIMAP)); addEntry(new RlvBehaviourToggleProcessor("shownames", RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourToggleProcessor("shownametags", RlvBehaviourInfo::BHVR_STRICT )); addEntry(new RlvBehaviourGenericToggleProcessor("shownearby", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourGenericToggleProcessor("showself", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourGenericToggleProcessor("showselfhead", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourGenericProcessor("showworldmap", RLV_BHVR_SHOWWORLDMAP)); addEntry(new RlvBehaviourGenericProcessor("sit", RLV_BHVR_SIT)); addEntry(new RlvBehaviourGenericProcessor("sittp", RLV_BHVR_SITTP)); addModifier(RLV_BHVR_SITTP, RLV_MODIFIER_SITTPDIST, new RlvBehaviourModifier("SitTp Distance", RLV_MODIFIER_SITTP_DEFAULT, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericProcessor("standtp", RLV_BHVR_STANDTP)); addEntry(new RlvBehaviourProcessor("startim", RlvBehaviourInfo::BHVR_STRICT)); addModifier(RLV_BHVR_STARTIM, RLV_MODIFIER_STARTIMDISTMIN, new RlvBehaviourModifier("StartIM Distance (Min)", F32_MAX, true, new RlvBehaviourModifier_CompMax)); addModifier(RLV_BHVR_STARTIM, RLV_MODIFIER_STARTIMDISTMAX, new RlvBehaviourModifier("StartIM Distance (Max)", F32_MAX, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericProcessor("startimto", RLV_BHVR_STARTIMTO, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourGenericProcessor("temprun", RLV_BHVR_TEMPRUN)); addEntry(new RlvBehaviourGenericProcessor("touchall", RLV_BHVR_TOUCHALL)); addEntry(new RlvBehaviourGenericProcessor("touchattach", RLV_BHVR_TOUCHATTACH)); addEntry(new RlvBehaviourGenericProcessor("touchattachother", RLV_BHVR_TOUCHATTACHOTHER)); addEntry(new RlvBehaviourGenericProcessor("touchattachself", RLV_BHVR_TOUCHATTACHSELF)); addEntry(new RlvBehaviourGenericProcessor("touchfar", RLV_BHVR_FARTOUCH, RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourGenericProcessor("touchhud", RLV_BHVR_TOUCHHUD, RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourGenericProcessor("touchme", RLV_BHVR_TOUCHME)); addEntry(new RlvBehaviourGenericProcessor("touchthis", RLV_BHVR_TOUCHTHIS)); addEntry(new RlvBehaviourGenericProcessor("touchworld", RLV_BHVR_TOUCHWORLD)); addEntry(new RlvBehaviourGenericProcessor("tplm", RLV_BHVR_TPLM)); addEntry(new RlvBehaviourGenericProcessor("tploc", RLV_BHVR_TPLOC)); addEntry(new RlvBehaviourGenericProcessor("tplocal", RLV_BHVR_TPLOCAL, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_TPLOCAL, RLV_MODIFIER_TPLOCALDIST, new RlvBehaviourModifier("Local Teleport Distance", RLV_MODIFIER_TPLOCAL_DEFAULT, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericProcessor("tplure", RLV_BHVR_TPLURE, RlvBehaviourInfo::BHVR_STRICT)); addEntry(new RlvBehaviourGenericProcessor("tprequest", RLV_BHVR_TPREQUEST, RlvBehaviourInfo::BHVR_STRICT | RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourInfo("unsharedunwear", RLV_BHVR_UNSHAREDUNWEAR, RLV_TYPE_ADDREM)); addEntry(new RlvBehaviourInfo("unsharedwear", RLV_BHVR_UNSHAREDWEAR, RLV_TYPE_ADDREM)); addEntry(new RlvBehaviourGenericProcessor("unsit", RLV_BHVR_UNSIT)); addEntry(new RlvBehaviourGenericProcessor("viewnote", RLV_BHVR_VIEWNOTE)); addEntry(new RlvBehaviourGenericProcessor("viewscript", RLV_BHVR_VIEWSCRIPT)); addEntry(new RlvBehaviourGenericProcessor("viewtexture", RLV_BHVR_VIEWTEXTURE)); // Camera addEntry(new RlvBehaviourGenericToggleProcessor("setcam")); addEntry(new RlvBehaviourGenericProcessor("setcam_avdistmin", RLV_BHVR_SETCAM_AVDISTMIN, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_SETCAM_AVDISTMIN, RLV_MODIFIER_SETCAM_AVDISTMIN, new RlvBehaviourModifierHandler("Camera - Avatar Distance (Min)", 0.0f, false, new RlvBehaviourModifier_CompMax())); addEntry(new RlvBehaviourGenericProcessor("setcam_avdistmax", RLV_BHVR_SETCAM_AVDISTMAX, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_SETCAM_AVDISTMAX, RLV_MODIFIER_SETCAM_AVDISTMAX, new RlvBehaviourModifier("Camera - Avatar Distance (Max)", F32_MAX, false, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericProcessor("setcam_origindistmin", RLV_BHVR_SETCAM_ORIGINDISTMIN, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_SETCAM_ORIGINDISTMIN, RLV_MODIFIER_SETCAM_ORIGINDISTMIN, new RlvBehaviourModifier("Camera - Focus Distance (Min)", 0.0f, true, new RlvBehaviourModifier_CompMax)); addEntry(new RlvBehaviourGenericProcessor("setcam_origindistmax", RLV_BHVR_SETCAM_ORIGINDISTMAX, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_SETCAM_ORIGINDISTMAX, RLV_MODIFIER_SETCAM_ORIGINDISTMAX, new RlvBehaviourModifier("Camera - Focus Distance (Max)", F32_MAX, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericToggleProcessor("setcam_eyeoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_SETCAM_EYEOFFSET, RLV_MODIFIER_SETCAM_EYEOFFSET, new RlvBehaviourModifierHandler("Camera - Eye Offset", LLVector3::zero, true, nullptr)); addEntry(new RlvBehaviourGenericToggleProcessor("setcam_focusoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addModifier(RLV_BHVR_SETCAM_FOCUSOFFSET, RLV_MODIFIER_SETCAM_FOCUSOFFSET, new RlvBehaviourModifierHandler("Camera - Focus Offset", LLVector3::zero, true, nullptr)); addEntry(new RlvBehaviourProcessor("setcam_fovmin")); addModifier(RLV_BHVR_SETCAM_FOVMIN, RLV_MODIFIER_SETCAM_FOVMIN, new RlvBehaviourModifierHandler("Camera - FOV (Min)", DEFAULT_FIELD_OF_VIEW, true, new RlvBehaviourModifier_CompMax)); addEntry(new RlvBehaviourProcessor("setcam_fovmax")); addModifier(RLV_BHVR_SETCAM_FOVMAX, RLV_MODIFIER_SETCAM_FOVMAX, new RlvBehaviourModifierHandler("Camera - FOV (Max)", DEFAULT_FIELD_OF_VIEW, true, new RlvBehaviourModifier_CompMin)); addEntry(new RlvBehaviourGenericToggleProcessor("setcam_mouselook")); addEntry(new RlvBehaviourGenericProcessor("setcam_textures", RLV_BHVR_SETCAM_TEXTURES)); addModifier(RLV_BHVR_SETCAM_TEXTURES, RLV_MODIFIER_SETCAM_TEXTURE, new RlvBehaviourModifierHandler("Camera - Forced Texture", IMG_DEFAULT, true, nullptr)); addEntry(new RlvBehaviourGenericToggleProcessor("setcam_unlock")); // Camera (compatibility shim - to be deprecated) addEntry(new RlvBehaviourGenericProcessor("camdistmin", RLV_BHVR_SETCAM_AVDISTMIN, RlvBehaviourInfo::BHVR_SYNONYM | RlvBehaviourInfo::BHVR_DEPRECATED)); addEntry(new RlvBehaviourGenericProcessor("camdistmax", RLV_BHVR_SETCAM_AVDISTMAX, RlvBehaviourInfo::BHVR_SYNONYM | RlvBehaviourInfo::BHVR_DEPRECATED)); addEntry(new RlvBehaviourGenericProcessor("camtextures", RLV_BHVR_SETCAM_TEXTURES, RlvBehaviourInfo::BHVR_SYNONYM | RlvBehaviourInfo::BHVR_DEPRECATED)); addEntry(new RlvBehaviourProcessor("camzoommin", RlvBehaviourInfo::BHVR_DEPRECATED)); addEntry(new RlvBehaviourProcessor("camzoommax", RlvBehaviourInfo::BHVR_DEPRECATED)); addEntry(new RlvBehaviourGenericToggleProcessor("camunlock", RlvBehaviourInfo::BHVR_SYNONYM | RlvBehaviourInfo::BHVR_DEPRECATED)); // // Force-wear // addEntry(new RlvBehaviourInfo("attach", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); addEntry(new RlvBehaviourInfo("attachall", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); addEntry(new RlvBehaviourInfo("attachover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); addEntry(new RlvBehaviourInfo("attachallover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); addEntry(new RlvBehaviourInfo("attachthis", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT)); addEntry(new RlvBehaviourInfo("attachallthis", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT)); addEntry(new RlvBehaviourInfo("attachthisover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT)); addEntry(new RlvBehaviourInfo("attachallthisover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT)); addEntry(new RlvForceProcessor("detach", RlvBehaviourInfo::FORCEWEAR_WEAR_REMOVE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); addEntry(new RlvBehaviourInfo("detachall", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REMOVE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); addEntry(new RlvBehaviourInfo("detachthis", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REMOVE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT)); addEntry(new RlvBehaviourInfo("detachallthis", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REMOVE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT)); addEntry(new RlvForceProcessor("remattach", RlvBehaviourInfo::FORCEWEAR_WEAR_REMOVE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); addEntry(new RlvForceProcessor("remoutfit", RlvBehaviourInfo::FORCEWEAR_WEAR_REMOVE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE)); // Synonyms (addoutfit* -> attach*) addEntry(new RlvBehaviourInfo("addoutfit", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("addoutfitall", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("addoutfitover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("addoutfitallover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("addoutfitthis", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("addoutfitallthis", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("addoutfitthisover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("addoutfitallthisover", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_ADD | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT | RlvBehaviourInfo::BHVR_SYNONYM)); // Synonyms (attach*overorreplace -> attach*) addEntry(new RlvBehaviourInfo("attachoverorreplace", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("attachalloverorreplace", RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_NONE | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("attachthisoverorreplace",RLV_CMD_FORCEWEAR, RLV_TYPE_FORCE, RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_NODE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT | RlvBehaviourInfo::BHVR_SYNONYM)); addEntry(new RlvBehaviourInfo("attachallthisoverorreplace",RLV_CMD_FORCEWEAR,RLV_TYPE_FORCE,RlvBehaviourInfo::FORCEWEAR_WEAR_REPLACE | RlvBehaviourInfo::FORCEWEAR_SUBTREE | RlvBehaviourInfo::FORCEWEAR_CONTEXT_OBJECT | RlvBehaviourInfo::BHVR_SYNONYM)); // // Force-only // addEntry(new RlvBehaviourInfo("adjustheight", RLV_BHVR_ADJUSTHEIGHT, RLV_TYPE_FORCE)); addEntry(new RlvForceProcessor("detachme")); addEntry(new RlvForceProcessor("setcam_focus", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvForceProcessor("setcam_eyeoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvForceProcessor("setcam_focusoffset", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvForceProcessor("setcam_fov", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvForceProcessor("setcam_mode", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvForceProcessor("setgroup")); addEntry(new RlvForceProcessor("sit")); addEntry(new RlvForceProcessor("tpto")); addEntry(new RlvBehaviourInfo("unsit", RLV_BHVR_UNSIT, RLV_TYPE_FORCE)); // // Reply-only // addEntry(new RlvBehaviourInfo("findfolder", RLV_BHVR_FINDFOLDER, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("findfolders", RLV_BHVR_FINDFOLDERS, RLV_TYPE_REPLY, RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourInfo("getaddattachnames", RLV_BHVR_GETADDATTACHNAMES, RLV_TYPE_REPLY, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourInfo("getaddoutfitnames", RLV_BHVR_GETADDOUTFITNAMES, RLV_TYPE_REPLY, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourInfo("getattach", RLV_BHVR_GETATTACH, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getattachnames", RLV_BHVR_GETATTACHNAMES, RLV_TYPE_REPLY, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcam_avdist", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcam_avdistmin", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcam_avdistmax", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcam_fov", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcam_fovmin", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcam_fovmax", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcam_textures", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvReplyProcessor("getcommand", RlvBehaviourInfo::BHVR_EXTENDED)); addEntry(new RlvBehaviourInfo("getgroup", RLV_BHVR_GETGROUP, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getinv", RLV_BHVR_GETINV, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getinvworn", RLV_BHVR_GETINVWORN, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getoutfit", RLV_BHVR_GETOUTFIT, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getoutfitnames", RLV_BHVR_GETOUTFITNAMES, RLV_TYPE_REPLY, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourInfo("getpath", RLV_BHVR_GETPATH, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getpathnew", RLV_BHVR_GETPATHNEW, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getremattachnames", RLV_BHVR_GETREMATTACHNAMES, RLV_TYPE_REPLY, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourInfo("getremoutfitnames", RLV_BHVR_GETREMOUTFITNAMES, RLV_TYPE_REPLY, RlvBehaviourInfo::BHVR_EXPERIMENTAL)); addEntry(new RlvBehaviourInfo("getsitid", RLV_BHVR_GETSITID, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getstatus", RLV_BHVR_GETSTATUS, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("getstatusall", RLV_BHVR_GETSTATUSALL, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("version", RLV_BHVR_VERSION, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("versionnew", RLV_BHVR_VERSIONNEW, RLV_TYPE_REPLY)); addEntry(new RlvBehaviourInfo("versionnum", RLV_BHVR_VERSIONNUM, RLV_TYPE_REPLY)); // Populate m_String2InfoMap (the tuple should be unique) for (const RlvBehaviourInfo* pBhvrInfo : m_BhvrInfoList) { RLV_VERIFY(m_String2InfoMap.insert(std::make_pair(std::make_pair(pBhvrInfo->getBehaviour(), (ERlvParamType)pBhvrInfo->getParamTypeMask()), pBhvrInfo)).second == true); } // Populate m_Bhvr2InfoMap (there can be multiple entries per ERlvBehaviour) for (const RlvBehaviourInfo* pBhvrInfo : m_BhvrInfoList) { if ( (pBhvrInfo->getParamTypeMask() & RLV_TYPE_ADDREM) && (!pBhvrInfo->isSynonym()) ) { #ifdef RLV_DEBUG for (const rlv_bhvr2info_map_t::value_type& itBhvr : boost::make_iterator_range(m_Bhvr2InfoMap.lower_bound(pBhvrInfo->getBehaviourType()), m_Bhvr2InfoMap.upper_bound(pBhvrInfo->getBehaviourType()))) { RLV_ASSERT( (itBhvr.first != pBhvrInfo->getBehaviourType()) || (itBhvr.second->getBehaviourFlags() != pBhvrInfo->getBehaviourFlags()) ); } #endif // RLV_DEBUG m_Bhvr2InfoMap.insert(std::pair(pBhvrInfo->getBehaviourType(), pBhvrInfo)); } } // Process blocked commands if (RlvSettings::getNoSetEnv()) toggleBehaviourFlag("setenv", RLV_TYPE_ADDREM, RlvBehaviourInfo::BHVR_BLOCKED, true); } RlvBehaviourDictionary::~RlvBehaviourDictionary() { for (const RlvBehaviourInfo* pBhvrInfo : m_BhvrInfoList) delete pBhvrInfo; m_BhvrInfoList.clear(); for (int idxBhvrMod = 0; idxBhvrMod < RLV_MODIFIER_COUNT; idxBhvrMod++) { delete m_BehaviourModifiers[idxBhvrMod]; m_BehaviourModifiers[idxBhvrMod] = nullptr; } } void RlvBehaviourDictionary::addEntry(const RlvBehaviourInfo* pEntry) { // Filter experimental commands (if disabled) static LLCachedControl sEnableExperimental(gSavedSettings, "RLVaExperimentalCommands"); if ( (!pEntry) || ((!sEnableExperimental) && (pEntry->isExperimental())) ) { return; } // Sanity check for duplicate entries #ifndef LL_RELEASE_FOR_DOWNLOAD std::for_each(m_BhvrInfoList.begin(), m_BhvrInfoList.end(), [&pEntry](const RlvBehaviourInfo* pBhvrInfo) { RLV_ASSERT_DBG( ((pBhvrInfo->getBehaviour()) != (pEntry->getBehaviour())) || ((pBhvrInfo->getParamTypeMask() & pEntry->getParamTypeMask()) == 0) ); }); #endif // LL_RELEASE_FOR_DOWNLOAD m_BhvrInfoList.push_back(pEntry); } void RlvBehaviourDictionary::addModifier(ERlvBehaviour eBhvr, ERlvBehaviourModifier eModifier, RlvBehaviourModifier* pModifierEntry) { if (eModifier < RLV_MODIFIER_COUNT) { m_BehaviourModifiers[eModifier] = pModifierEntry; m_Bhvr2ModifierMap.insert(std::make_pair(eBhvr, eModifier)); } } const RlvBehaviourInfo* RlvBehaviourDictionary::getBehaviourInfo(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict) const { bool fStrict = boost::algorithm::ends_with(strBhvr, "_sec"); if (pfStrict) *pfStrict = fStrict; rlv_string2info_map_t::const_iterator itBhvr = m_String2InfoMap.find(std::make_pair( (!fStrict) ? strBhvr : strBhvr.substr(0, strBhvr.size() - 4), (eParamType & RLV_TYPE_ADDREM) ? RLV_TYPE_ADDREM : eParamType)); return ( (itBhvr != m_String2InfoMap.end()) && ((!fStrict) || (itBhvr->second->hasStrict())) ) ? itBhvr->second : NULL; } ERlvBehaviour RlvBehaviourDictionary::getBehaviourFromString(const std::string& strBhvr, ERlvParamType eParamType, bool* pfStrict) const { const RlvBehaviourInfo* pBhvrInfo = getBehaviourInfo(strBhvr, eParamType, pfStrict); return (pBhvrInfo) ? pBhvrInfo->getBehaviourType() : RLV_BHVR_UNKNOWN; } bool RlvBehaviourDictionary::getCommands(const std::string& strMatch, ERlvParamType eParamType, std::list& cmdList) const { cmdList.clear(); for (const RlvBehaviourInfo* pBhvrInfo : m_BhvrInfoList) { if ( (pBhvrInfo->getParamTypeMask() & eParamType) || (RLV_TYPE_UNKNOWN == eParamType) ) { std::string strCmd = pBhvrInfo->getBehaviour(); if ( (std::string::npos != strCmd.find(strMatch)) || (strMatch.empty()) ) cmdList.push_back(strCmd); if ( (pBhvrInfo->hasStrict()) && ((std::string::npos != strCmd.append("_sec").find(strMatch)) || (strMatch.empty())) ) cmdList.push_back(strCmd); } } return !cmdList.empty(); } bool RlvBehaviourDictionary::getHasStrict(ERlvBehaviour eBhvr) const { for (const rlv_bhvr2info_map_t::value_type& itBhvr : boost::make_iterator_range(m_Bhvr2InfoMap.lower_bound(eBhvr), m_Bhvr2InfoMap.upper_bound(eBhvr))) { // Only restrictions can be strict if (RLV_TYPE_ADDREM != itBhvr.second->getParamTypeMask()) continue; return itBhvr.second->hasStrict(); } RLV_ASSERT(false); return false; } RlvBehaviourModifier* RlvBehaviourDictionary::getModifierFromBehaviour(ERlvBehaviour eBhvr) const { rlv_bhvr2mod_map_t::const_iterator itMod = m_Bhvr2ModifierMap.find(eBhvr); ERlvBehaviourModifier eBhvrMod = (m_Bhvr2ModifierMap.end() != itMod) ? itMod->second : RLV_MODIFIER_UNKNOWN; return (eBhvrMod < RLV_MODIFIER_UNKNOWN) ? m_BehaviourModifiers[eBhvrMod] : nullptr; } void RlvBehaviourDictionary::toggleBehaviourFlag(const std::string& strBhvr, ERlvParamType eParamType, RlvBehaviourInfo::EBehaviourFlags eBhvrFlag, bool fEnable) { rlv_string2info_map_t::const_iterator itBhvr = m_String2InfoMap.find(std::make_pair(strBhvr, (eParamType & RLV_TYPE_ADDREM) ? RLV_TYPE_ADDREM : eParamType)); if (m_String2InfoMap.end() != itBhvr) { const_cast(itBhvr->second)->toggleBehaviourFlag(eBhvrFlag, fEnable); } } // ============================================================================ // RlvBehaviourModifier // RlvBehaviourModifier::RlvBehaviourModifier(std::string strName, const RlvBehaviourModifierValue& defaultValue, bool fAddDefaultOnEmpty, RlvBehaviourModifier_Comp* pValueComparator) : m_strName(strName), m_DefaultValue(defaultValue), m_fAddDefaultOnEmpty(fAddDefaultOnEmpty), m_pValueComparator(pValueComparator) { m_pValueComparator = (pValueComparator) ? pValueComparator : new RlvBehaviourModifier_Comp(); } RlvBehaviourModifier::~RlvBehaviourModifier() { if (m_pValueComparator) { delete m_pValueComparator; m_pValueComparator = NULL; } } bool RlvBehaviourModifier::addValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject) { if (modValue.which() == m_DefaultValue.which()) { m_Values.insert((m_pValueComparator) ? std::lower_bound(m_Values.begin(), m_Values.end(), std::make_pair(modValue, idObject), boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)) : m_Values.end(), std::make_pair(modValue, idObject)); // NOTE: change signal needs to trigger before modifier handlers so cached values have a chance to update properly m_ChangeSignal(getValue()); onValueChange(); return true; } return false; } const LLUUID& RlvBehaviourModifier::getPrimaryObject() const { return (m_pValueComparator) ? m_pValueComparator->m_idPrimaryObject : LLUUID::null; } bool RlvBehaviourModifier::hasValue() const { // If no primary object is set this returns "any value set"; otherwise it returns "any value set by the primary object" if ( (!m_pValueComparator) || (m_pValueComparator->m_idPrimaryObject.isNull()) ) return !m_Values.empty(); return (!m_Values.empty()) ? m_Values.front().second == m_pValueComparator->m_idPrimaryObject : false; } void RlvBehaviourModifier::removeValue(const RlvBehaviourModifierValue& modValue, const LLUUID& idObject) { if ( (modValue.which() == m_DefaultValue.which()) ) { auto itValue = std::find(m_Values.begin(), m_Values.end(), std::make_pair(modValue, idObject)); if (m_Values.end() != itValue) { m_Values.erase(itValue); onValueChange(); m_ChangeSignal(getValue()); } } } void RlvBehaviourModifier::setPrimaryObject(const LLUUID& idPrimaryObject) { if (m_pValueComparator) { m_pValueComparator->m_idPrimaryObject = idPrimaryObject; m_Values.sort(boost::bind(&RlvBehaviourModifier_Comp::operator(), m_pValueComparator, _1, _2)); onValueChange(); m_ChangeSignal(getValue()); } } bool RlvBehaviourModifier::convertOptionValue(const std::string& optionValue, RlvBehaviourModifierValue& modValue) const { try { if (typeid(float) == m_DefaultValue.type()) { modValue = std::stof(optionValue); return true; } else if (typeid(int) == m_DefaultValue.type()) { modValue = std::stoi(optionValue); return true; } else if (typeid(LLVector3) == m_DefaultValue.type()) { LLVector3 vecOption; if (3 == sscanf(optionValue.c_str(), "%f/%f/%f", vecOption.mV + 0, vecOption.mV + 1, vecOption.mV + 2)) { modValue = vecOption; return true; } } else if (typeid(LLUUID) == m_DefaultValue.type()) { LLUUID idOption; if (LLUUID::parseUUID(optionValue, &idOption)) { modValue = idOption; return true; } } return false; } catch (const std::invalid_argument&) { return false; } } // ============================================================================ // RlvCommmand // RlvCommand::RlvCommand(const LLUUID& idObj, const std::string& strCommand) : m_fValid(false), m_idObj(idObj), m_pBhvrInfo(NULL), m_eParamType(RLV_TYPE_UNKNOWN), m_fStrict(false), m_fRefCounted(false) { if ((m_fValid = parseCommand(strCommand, m_strBehaviour, m_strOption, m_strParam))) { S32 nTemp = 0; if ( ("n" == m_strParam) || ("add" == m_strParam) ) m_eParamType = RLV_TYPE_ADD; else if ( ("y" == m_strParam) || ("rem" == m_strParam) ) m_eParamType = RLV_TYPE_REMOVE; else if (m_strBehaviour == "clear") // clear is the odd one out so just make it its own type m_eParamType = RLV_TYPE_CLEAR; else if ("force" == m_strParam) m_eParamType = RLV_TYPE_FORCE; else if (LLStringUtil::convertToS32(m_strParam, nTemp)) // Assume it's a reply command if we can convert to an S32 m_eParamType = RLV_TYPE_REPLY; else { m_eParamType = RLV_TYPE_UNKNOWN; m_fValid = false; } } if (!m_fValid) { m_strOption = m_strParam = ""; return; } m_pBhvrInfo = RlvBehaviourDictionary::instance().getBehaviourInfo(m_strBehaviour, m_eParamType, &m_fStrict); } RlvCommand::RlvCommand(const RlvCommand& rlvCmd, ERlvParamType eParamType) : m_fValid(rlvCmd.m_fValid), m_idObj(rlvCmd.m_idObj), m_strBehaviour(rlvCmd.m_strBehaviour), m_pBhvrInfo(rlvCmd.m_pBhvrInfo), m_eParamType( (RLV_TYPE_UNKNOWN == eParamType) ? rlvCmd.m_eParamType : eParamType),m_fStrict(rlvCmd.m_fStrict), m_strOption(rlvCmd.m_strOption), m_strParam(rlvCmd.m_strParam), m_fRefCounted(false) { } bool RlvCommand::parseCommand(const std::string& strCommand, std::string& strBehaviour, std::string& strOption, std::string& strParam) { // (See behaviour notes for the command parsing truth table) // Format: [: