summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml44
-rw-r--r--indra/newview/llviewermessage.cpp28
-rw-r--r--indra/newview/rlvdefines.h62
-rw-r--r--indra/newview/rlvhandler.cpp44
-rw-r--r--indra/newview/rlvhandler.h11
-rw-r--r--indra/newview/rlvhelper.cpp136
-rw-r--r--indra/newview/rlvhelper.h24
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml22
9 files changed, 368 insertions, 5 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 70a9f09e1f..a7bbadfd86 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -728,6 +728,7 @@ set(viewer_SOURCE_FILES
pipeline.cpp
rlvactions.cpp
rlvcommon.cpp
+ rlvhelper.cpp
rlvhandler.cpp
)
@@ -1392,6 +1393,7 @@ set(viewer_HEADER_FILES
rlvdefines.h
rlvactions.h
rlvcommon.h
+ rlvhelper.h
rlvhandler.h
roles_constants.h
VertexCache.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 48e0878383..be88ad6e2f 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9852,6 +9852,50 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
+ <boolean>0</boolean>
+ </map>
+ <key>RestrainedLoveDebug</key>
+ <map>
+ <key>Comment</key>
+ <string>Toggles RLVa debug mode (displays the commands when in debug mode)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <boolean>0</boolean>
+ </map>
+ <key>RLVaBlockedExperiences</key>
+ <map>
+ <key>Comment</key>
+ <string>List of experiences blocked from interacting with RLVa</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>bfe25fb4-222c-11e5-85a2-fa4c4ccaa202</string>
+ </map>
+ <key>RLVaDebugHideUnsetDuplicate</key>
+ <map>
+ <key>Comment</key>
+ <string>Suppresses reporting "unset" or "duplicate" command restrictions when RestrainedLoveDebug is TRUE</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <boolean>0</boolean>
+ </map>
+ <key>RLVaEnableTemporaryAttachments</key>
+ <map>
+ <key>Comment</key>
+ <string>Allows temporary attachments (regardless of origin) to issue RLV commands</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
<boolean>1</boolean>
</map>
<key>RevokePermsOnStopAnimation</key>
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 872a9a1581..4ed16c19a6 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -118,6 +118,8 @@
#include "llpanelplaceprofile.h"
#include "llviewerregion.h"
#include "llfloaterregionrestarting.h"
+#include "rlvactions.h"
+#include "rlvhandler.h"
#include "llnotificationmanager.h" //
#include "llexperiencecache.h"
@@ -2382,15 +2384,16 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
}
bool is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible);
+ bool show_script_chat_particles = chat.mSourceType == CHAT_SOURCE_OBJECT
+ && chat.mChatType != CHAT_TYPE_DEBUG_MSG
+ && gSavedSettings.getBOOL("EffectScriptChatParticles");
chatter = gObjectList.findObject(from_id);
if (chatter)
{
chat.mPosAgent = chatter->getPositionAgent();
// Make swirly things only for talking objects. (not script debug messages, though)
- if (chat.mSourceType == CHAT_SOURCE_OBJECT
- && chat.mChatType != CHAT_TYPE_DEBUG_MSG
- && gSavedSettings.getBOOL("EffectScriptChatParticles") )
+ if (show_script_chat_particles && (!RlvActions::isRlvEnabled() || CHAT_TYPE_OWNER != chat.mChatType) )
{
LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent());
psc->setSourceObject(chatter);
@@ -2470,8 +2473,25 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
case CHAT_TYPE_WHISPER:
chat.mText = LLTrans::getString("whisper") + " ";
break;
- case CHAT_TYPE_DEBUG_MSG:
case CHAT_TYPE_OWNER:
+ if (RlvActions::isRlvEnabled())
+ {
+ if (RlvHandler::instance().handleSimulatorChat(mesg, chat, chatter))
+ {
+ break;
+ }
+ else if (show_script_chat_particles)
+ {
+ LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent());
+ psc->setSourceObject(chatter);
+ psc->setColor(color);
+ //We set the particles to be owned by the object's owner,
+ //just in case they should be muted by the mute list
+ psc->setOwnerUUID(owner_id);
+ LLViewerPartSim::getInstance()->addPartSource(psc);
+ }
+ }
+ case CHAT_TYPE_DEBUG_MSG:
case CHAT_TYPE_NORMAL:
case CHAT_TYPE_DIRECT:
break;
diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h
index dc1e58f47c..6ba2afbc69 100644
--- a/indra/newview/rlvdefines.h
+++ b/indra/newview/rlvdefines.h
@@ -29,6 +29,68 @@ namespace Rlv
#define RLV_DEBUGS LL_DEBUGS("RLV")
#define RLV_ENDL LL_ENDL
+#define RLV_RELEASE
+#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
+ // Make sure we halt execution on errors
+ #define RLV_ERRS LL_ERRS("RLV")
+ // Keep our asserts separate from LL's
+ #define RLV_ASSERT(f) if (!(f)) { RLV_ERRS << "ASSERT (" << #f << ")" << RLV_ENDL; }
+ #define RLV_ASSERT_DBG(f) RLV_ASSERT(f)
+#else
+ // We don't want to check assertions in release builds
+ #ifndef RLV_RELEASE
+ #define RLV_ASSERT(f) RLV_VERIFY(f)
+ #define RLV_ASSERT_DBG(f)
+ #else
+ #define RLV_ASSERT(f)
+ #define RLV_ASSERT_DBG(f)
+ #endif // RLV_RELEASE
+#endif // LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
+
+namespace Rlv
+{
+ namespace Constants
+ {
+ constexpr char CmdPrefix = '@';
+ }
+}
+
+// ============================================================================
+// Enumeration declarations
+//
+
+namespace Rlv
+{
+ enum class ECmdRet{
+ Unknown = 0x0000, // Unknown error (should only be used internally)
+ Retained, // Command was retained
+ Success = 0x0100, // Command executed successfully
+ SuccessUnset, // Command executed successfully (RLV_TYPE_REMOVE for an unrestricted behaviour)
+ SuccessDuplicate, // Command executed successfully (RLV_TYPE_ADD for an already restricted behaviour)
+ SuccessDeprecated, // Command executed successfully but has been marked as deprecated
+ SuccessDelayed, // Command parsed valid but will execute at a later time
+ Failed = 0x0200, // Command failed (general failure)
+ FailedSyntax, // Command failed (syntax error)
+ FailedOption, // Command failed (invalid option)
+ FailedParam, // Command failed (invalid param)
+ FailedLock, // Command failed (command is locked by another object)
+ FailedDisabled, // Command failed (command disabled by user)
+ FailedUnknown, // Command failed (unknown command)
+ FailedNoSharedRoot, // Command failed (missing #RLV)
+ FailedDeprecated, // Command failed (deprecated and no longer supported)
+ FailedNoBehaviour, // Command failed (force modifier on an object with no active restrictions)
+ FailedUnheldBehaviour, // Command failed (local modifier on an object that doesn't hold the base behaviour)
+ FailedBlocked, // Command failed (object is blocked)
+ FailedThrottled, // Command failed (throttled)
+ FailedNoProcessor // Command doesn't have a template processor define (legacy code)
+ };
+
+ constexpr bool isReturnCodeSuccess(ECmdRet eRet)
+ {
+ return (static_cast<uint16_t>(eRet) & static_cast<uint16_t>(ECmdRet::Success)) == static_cast<uint16_t>(ECmdRet::Success);
+ }
+}
+
// ============================================================================
// Settings
//
diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp
index 3315ed1999..bf78a0a38a 100644
--- a/indra/newview/rlvhandler.cpp
+++ b/indra/newview/rlvhandler.cpp
@@ -1,10 +1,12 @@
#include "llviewerprecompiledheaders.h"
#include "llappviewer.h"
#include "llstartup.h"
+#include "llviewercontrol.h"
+#include "llviewerobject.h"
-#include "rlvdefines.h"
#include "rlvcommon.h"
#include "rlvhandler.h"
+#include "rlvhelper.h"
using namespace Rlv;
@@ -15,6 +17,46 @@ using namespace Rlv;
bool RlvHandler::mIsEnabled = false;
// ============================================================================
+// Command processing functions
+//
+
+bool RlvHandler::handleSimulatorChat(std::string& message, const LLChat& chat, const LLViewerObject* chatObj)
+{
+ static LLCachedControl<bool> enable_temp_attach(gSavedSettings, Settings::EnableTempAttach);
+ static LLCachedControl<bool> show_debug_output(gSavedSettings, Settings::Debug);
+ static LLCachedControl<bool> hide_unset_dupes(gSavedSettings, Settings::DebugHideUnsetDup);
+
+ if ( message.length() <= 3 || Rlv::Constants::CmdPrefix != message[0] || CHAT_TYPE_OWNER != chat.mChatType ||
+ (chatObj && chatObj->isTempAttachment() && !enable_temp_attach()) )
+ {
+ return false;
+ }
+
+ message.erase(0, 1);
+ LLStringUtil::toLower(message);
+ CommandDbgOut cmdDbgOut(message);
+
+ boost_tokenizer tokens(message, boost::char_separator<char>(",", "", boost::drop_empty_tokens));
+ for (const std::string& strCmd : tokens)
+ {
+ ECmdRet eRet = (ECmdRet)processCommand(chat.mFromID, strCmd, true);
+ if ( show_debug_output() &&
+ (!hide_unset_dupes() || (ECmdRet::SuccessUnset != eRet && ECmdRet::SuccessDuplicate != eRet)) )
+ {
+ cmdDbgOut.add(strCmd, eRet);
+ }
+ }
+
+ message = cmdDbgOut.get();
+ return true;
+}
+
+ECmdRet RlvHandler::processCommand(const LLUUID& idObj, const std::string& strCmd, bool fromObj)
+{
+ return ECmdRet::FailedNoProcessor;
+}
+
+// ============================================================================
// Initialization helper functions
//
diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h
index 0d4cbe98fb..8cf054e98e 100644
--- a/indra/newview/rlvhandler.h
+++ b/indra/newview/rlvhandler.h
@@ -1,9 +1,12 @@
#pragma once
+#include "llchat.h"
#include "llsingleton.h"
#include "rlvdefines.h"
+class LLViewerObject;
+
// ============================================================================
// RlvHandler class
//
@@ -13,6 +16,14 @@ class RlvHandler : public LLSingleton<RlvHandler>
LLSINGLETON_EMPTY_CTOR(RlvHandler);
public:
+ /*
+ * Helper functions
+ */
+public:
+ // Command processing helper functions
+ bool handleSimulatorChat(std::string& message, const LLChat& chat, const LLViewerObject* chatObj);
+ Rlv::ECmdRet processCommand(const LLUUID& idObj, const std::string& stCmd, bool fromObj);
+
// Initialization (deliberately static so they can safely be called in tight loops)
static bool canEnable();
static bool isEnabled() { return mIsEnabled; }
diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp
new file mode 100644
index 0000000000..ade2b83dd7
--- /dev/null
+++ b/indra/newview/rlvhelper.cpp
@@ -0,0 +1,136 @@
+#include "llviewerprecompiledheaders.h"
+
+#include "lltrans.h"
+
+#include "rlvhelper.h"
+
+using namespace Rlv;
+
+// =========================================================================
+// Various helper classes/timers/functors
+//
+
+namespace Rlv
+{
+ // ===========================================================================
+ // CommandDbgOut
+ //
+
+ void CommandDbgOut::add(std::string strCmd, ECmdRet eRet)
+ {
+ ECmdRet resultBucket;
+
+ // Successful and retained commands are added as-is
+ if (isReturnCodeSuccess(eRet))
+ resultBucket = ECmdRet::Success;
+ else if (ECmdRet::Retained == eRet)
+ resultBucket = ECmdRet::Retained;
+ else
+ {
+ // Failed commands get the failure reason appended to help troubleshooting
+ resultBucket = ECmdRet::Failed;
+ strCmd.append(llformat(" (%s)", getReturnCodeString(eRet).c_str()));
+ }
+
+ std::string& strResult = mCommandResults[resultBucket];
+ if (!strResult.empty())
+ strResult.append(", ");
+ strResult.append(strCmd);
+ }
+
+ std::string CommandDbgOut::get() const {
+ std::ostringstream result;
+
+ if (1 == mCommandResults.size())
+ {
+ auto it = mCommandResults.begin();
+ result << " " << getDebugVerbFromReturnCode(it->first) << ": @" << it->second;;
+ }
+ else if (mCommandResults.size() > 1)
+ {
+ auto appendResult = [&](ECmdRet eRet, const std::string& name)
+ {
+ auto it = mCommandResults.find(eRet);
+ if (it == mCommandResults.end()) return;
+ result << "\n - " << LLTrans::getString(name) << ": @" << it->second;
+ };
+ result << ": @" << mOrigCmd;
+ appendResult(ECmdRet::Success, "RlvDebugExecuted");
+ appendResult(ECmdRet::Failed, "RlvDebugFailed");
+ appendResult(ECmdRet::Retained, "RlvDebugRetained");
+ }
+
+ return result.str();
+ }
+
+ std::string CommandDbgOut::getDebugVerbFromReturnCode(ECmdRet eRet)
+ {
+ switch (eRet)
+ {
+ case ECmdRet::Success:
+ return LLTrans::getString("RlvDebugExecuted");
+ case ECmdRet::Failed:
+ return LLTrans::getString("RlvDebugFailed");
+ case ECmdRet::Retained:
+ return LLTrans::getString("RlvDebugRetained");
+ default:
+ RLV_ASSERT(false);
+ return LLStringUtil::null;
+ }
+ }
+
+ std::string CommandDbgOut::getReturnCodeString(ECmdRet eRet)
+ {
+ switch (eRet)
+ {
+ case ECmdRet::SuccessUnset:
+ return LLTrans::getString("RlvReturnCodeUnset");
+ case ECmdRet::SuccessDuplicate:
+ return LLTrans::getString("RlvReturnCodeDuplicate");
+ case ECmdRet::SuccessDelayed:
+ return LLTrans::getString("RlvReturnCodeDelayed");
+ case ECmdRet::SuccessDeprecated:
+ return LLTrans::getString("RlvReturnCodeDeprecated");
+ case ECmdRet::FailedSyntax:
+ return LLTrans::getString("RlvReturnCodeSyntax");
+ case ECmdRet::FailedOption:
+ return LLTrans::getString("RlvReturnCodeOption");
+ case ECmdRet::FailedParam:
+ return LLTrans::getString("RlvReturnCodeParam");
+ case ECmdRet::FailedLock:
+ return LLTrans::getString("RlvReturnCodeLock");
+ case ECmdRet::FailedDisabled:
+ return LLTrans::getString("RlvReturnCodeDisabled");
+ case ECmdRet::FailedUnknown:
+ return LLTrans::getString("RlvReturnCodeUnknown");
+ case ECmdRet::FailedNoSharedRoot:
+ return LLTrans::getString("RlvReturnCodeNoSharedRoot");
+ case ECmdRet::FailedDeprecated:
+ return LLTrans::getString("RlvReturnCodeDeprecatedAndDisabled");
+ case ECmdRet::FailedNoBehaviour:
+ return LLTrans::getString("RlvReturnCodeNoBehaviour");
+ case ECmdRet::FailedUnheldBehaviour:
+ return LLTrans::getString("RlvReturnCodeUnheldBehaviour");
+ case ECmdRet::FailedBlocked:
+ return LLTrans::getString("RlvReturnCodeBlocked");
+ case ECmdRet::FailedThrottled:
+ return LLTrans::getString("RlvReturnCodeThrottled");
+ case ECmdRet::FailedNoProcessor:
+ return LLTrans::getString("RlvReturnCodeNoProcessor");
+ // The following are identified by the chat verb
+ case ECmdRet::Retained:
+ case ECmdRet::Success:
+ case ECmdRet::Failed:
+ return LLStringUtil::null;
+ // The following shouldn't occur
+ case ECmdRet::Unknown:
+ default:
+ RLV_ASSERT(false);
+ return LLStringUtil::null;
+ }
+ }
+
+ // ===========================================================================
+}
+
+// ============================================================================
diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h
new file mode 100644
index 0000000000..89bdc709d5
--- /dev/null
+++ b/indra/newview/rlvhelper.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "rlvdefines.h"
+
+// ============================================================================
+// Various helper classes/timers/functors
+//
+
+namespace Rlv
+{
+ struct CommandDbgOut
+ {
+ CommandDbgOut(const std::string& orig_cmd) : mOrigCmd(orig_cmd) {}
+ void add(std::string strCmd, ECmdRet eRet);
+ std::string get() const;
+ static std::string getDebugVerbFromReturnCode(ECmdRet eRet);
+ static std::string getReturnCodeString(ECmdRet eRet);
+ private:
+ std::string mOrigCmd;
+ std::map<ECmdRet, std::string> mCommandResults;
+ };
+}
+
+// ============================================================================
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index a270bc473d..39a663298a 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -4376,4 +4376,26 @@ and report the problem.
[https://community.secondlife.com/knowledgebase/english/error-messages-r520/#Section__3 Knowledge Base]
</string>
+ <!-- RLVa -->
+ <string name="RlvDebugExecuted">executed</string>
+ <string name="RlvDebugFailed">failed</string>
+ <string name="RlvDebugRetained">retained</string>
+ <string name="RlvReturnCodeUnset">unset</string>
+ <string name="RlvReturnCodeDuplicate">duplicate</string>
+ <string name="RlvReturnCodeDelayed">delayed</string>
+ <string name="RlvReturnCodeDeprecated">deprecated</string>
+ <string name="RlvReturnCodeSyntax">thingy error</string>
+ <string name="RlvReturnCodeOption">invalid option</string>
+ <string name="RlvReturnCodeParam">invalid param</string>
+ <string name="RlvReturnCodeLock">locked command</string>
+ <string name="RlvReturnCodeDisabled">disabled command</string>
+ <string name="RlvReturnCodeUnknown">unknown command</string>
+ <string name="RlvReturnCodeNoSharedRoot">missing #RLV</string>
+ <string name="RlvReturnCodeDeprecatedAndDisabled">deprecated and disabled</string>
+ <string name="RlvReturnCodeNoBehaviour">no active behaviours</string>
+ <string name="RlvReturnCodeUnheldBehaviour">base behaviour not held</string>
+ <string name="RlvReturnCodeBlocked">blocked object</string>
+ <string name="RlvReturnCodeThrottled">throttled</string>
+ <string name="RlvReturnCodeNoProcessor">no command processor found</string>
+
</strings>