diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 71807aa897..3f00675778 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -323,6 +323,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("region_restarting", "floater_region_restarting.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); // [RLVa:KB] - Checked: 2010-03-11 (RLVa-1.2.0e) | Added: RLVa-1.2.0a LLFloaterReg::add("rlv_behaviours", "floater_rlv_behaviours.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("rlv_console", "floater_rlv_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("rlv_locks", "floater_rlv_locks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("rlv_strings", "floater_rlv_strings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); // [/RLVa:KB] diff --git a/indra/newview/rlvcommon.h b/indra/newview/rlvcommon.h index dab0f99ba3..fd52640290 100644 --- a/indra/newview/rlvcommon.h +++ b/indra/newview/rlvcommon.h @@ -169,7 +169,7 @@ public: static void notifyFailedAssertion(const std::string& strAssert, const std::string& strFile, int nLine); static void sendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null); - static bool isValidReplyChannel(S32 nChannel); + static bool isValidReplyChannel(S32 nChannel, bool fLoopback = false); static bool sendChatReply(S32 nChannel, const std::string& strUTF8Text); static bool sendChatReply(const std::string& strChannel, const std::string& strUTF8Text); @@ -299,9 +299,9 @@ inline bool RlvUtil::isEmote(const std::string& strUTF8Text) } // Checked: 2010-03-09 (RLVa-1.2.0b) | Added: RLVa-1.0.2a -inline bool RlvUtil::isValidReplyChannel(S32 nChannel) +inline bool RlvUtil::isValidReplyChannel(S32 nChannel, bool fLoopback /*=false*/) { - return (nChannel > 0) && (CHAT_CHANNEL_DEBUG != nChannel); + return (nChannel > ((!fLoopback) ? 0 : -1)) && (CHAT_CHANNEL_DEBUG != nChannel); } // Checked: 2009-08-05 (RLVa-1.0.1e) | Added: RLVa-1.0.0e diff --git a/indra/newview/rlvfloaters.cpp b/indra/newview/rlvfloaters.cpp index a22fa70005..8c4ae4c5e7 100644 --- a/indra/newview/rlvfloaters.cpp +++ b/indra/newview/rlvfloaters.cpp @@ -16,6 +16,7 @@ #include "llviewerprecompiledheaders.h" +#include "llagent.h" #include "llappearancemgr.h" #include "llavatarnamecache.h" #include "llclipboard.h" @@ -672,3 +673,99 @@ void RlvFloaterStrings::refresh() } // ============================================================================ +// RlvFloaterConsole +// + +static const char s_strRlvConsolePrompt[] = "> "; +static const char s_strRlvConsoleDisabled[] = "RLVa is disabled"; +static const char s_strRlvConsoleInvalid[] = "Invalid command"; + +RlvFloaterConsole::RlvFloaterConsole(const LLSD& sdKey) + : LLFloater(sdKey), m_pOutputText(nullptr) +{ +} + +RlvFloaterConsole::~RlvFloaterConsole() +{ +} + +BOOL RlvFloaterConsole::postBuild() +{ + LLLineEditor* pInputEdit = getChild("console_input"); + pInputEdit->setEnableLineHistory(true); + pInputEdit->setCommitCallback(boost::bind(&RlvFloaterConsole::onInput, this, _1, _2)); + pInputEdit->setFocus(true); + pInputEdit->setCommitOnFocusLost(false); + + m_pOutputText = getChild("console_output"); + m_pOutputText->appendText(s_strRlvConsolePrompt, false); + + return TRUE; +} + +void RlvFloaterConsole::addCommandReply(const std::string& strCommand, const std::string& strReply) +{ + m_pOutputText->appendText(llformat("%s: %s", strCommand.c_str(), strReply.c_str()), true); +} + +void RlvFloaterConsole::onInput(LLUICtrl* pCtrl, const LLSD& sdParam) +{ + LLLineEditor* pInputEdit = static_cast(pCtrl); + std::string strInput = pInputEdit->getText(); + + m_pOutputText->appendText(strInput, false); + pInputEdit->clear(); + + if (!rlv_handler_t::isEnabled()) + { + m_pOutputText->appendText(s_strRlvConsoleDisabled, true); + } + else if ( (strInput.length() <= 3) || (RLV_CMD_PREFIX != strInput[0]) ) + { + m_pOutputText->appendText(s_strRlvConsoleInvalid, true); + } + else + { + strInput.erase(0, 1); + LLStringUtil::toLower(strInput); + + std::string strExecuted, strFailed, strRetained, *pstr; + + boost_tokenizer tokens(strInput, boost::char_separator(",", "", boost::drop_empty_tokens)); + for (std::string strCmd : tokens) + { + ERlvCmdRet eRet = gRlvHandler.processCommand(gAgent.getID(), strCmd, true); + if ( RLV_RET_SUCCESS == (eRet & RLV_RET_SUCCESS) ) + pstr = &strExecuted; + else if ( RLV_RET_FAILED == (eRet & RLV_RET_FAILED) ) + pstr = &strFailed; + else if (RLV_RET_RETAINED == eRet) + pstr = &strRetained; + else + { + RLV_ASSERT(false); + pstr = &strFailed; + } + + if (const char* pstrSuffix = RlvStrings::getStringFromReturnCode(eRet)) + strCmd.append(" (").append(pstrSuffix).append(")"); + else if (RLV_RET_SUCCESS == (eRet & RLV_RET_SUCCESS)) + strCmd.clear(); // Only show feedback on successful commands when there's an informational notice + + if (!pstr->empty()) + pstr->push_back(','); + pstr->append(strCmd); + } + + if (!strExecuted.empty()) + m_pOutputText->appendText("INFO: @" + strExecuted, true); + if (!strFailed.empty()) + m_pOutputText->appendText("ERR: @" + strFailed, true); + if (!strRetained.empty()) + m_pOutputText->appendText("RET: @" + strRetained, true); + } + + m_pOutputText->appendText(s_strRlvConsolePrompt, true); +} + +// ============================================================================ diff --git a/indra/newview/rlvfloaters.h b/indra/newview/rlvfloaters.h index 11a029be50..683464694f 100644 --- a/indra/newview/rlvfloaters.h +++ b/indra/newview/rlvfloaters.h @@ -22,6 +22,12 @@ #include "rlvdefines.h" #include "rlvcommon.h" +// ============================================================================ +// Foward declarations +// +class LLComboBox; +class LLTextEditor; + // ============================================================================ // RlvFloaterLocks class declaration // @@ -118,6 +124,39 @@ protected: LLSD m_sdStringsInfo; }; +// ============================================================================ +// RlvFloaterConsole - debug console to allow command execution without the need for a script +// + +class RlvFloaterConsole : public LLFloater +{ + friend class LLFloaterReg; + template friend struct RlvCommandHandlerBaseImpl; + friend class RlvHandler; +private: + RlvFloaterConsole(const LLSD& sdKey); + ~RlvFloaterConsole() override; + + /* + * LLFloater overrides + */ +public: + BOOL postBuild() override; + + /* + * Member functions + */ +protected: + void addCommandReply(const std::string& strCommand, const std::string& strReply); + void onInput(LLUICtrl* ctrl, const LLSD& param); + + /* + * Member variables + */ +protected: + LLTextEditor* m_pOutputText; +}; + // ============================================================================ #endif // RLV_FLOATERS_H diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 729d2c2989..0085efbf2a 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -27,6 +27,7 @@ #include "llviewerparcelmgr.h" #include "llviewerregion.h" +#include "rlvfloaters.h" #include "rlvhandler.h" #include "rlvhelper.h" #include "rlvinventory.h" @@ -1837,7 +1838,7 @@ ERlvCmdRet RlvCommandHandlerBaseImpl::processCommand(const RlvCo { // Sanity check - should specify a - valid - reply channel S32 nChannel; - if ( (!LLStringUtil::convertToS32(rlvCmd.getParam(), nChannel)) || (!RlvUtil::isValidReplyChannel(nChannel)) ) + if ( (!LLStringUtil::convertToS32(rlvCmd.getParam(), nChannel)) || (!RlvUtil::isValidReplyChannel(nChannel, rlvCmd.getObjectID() == gAgent.getID())) ) return RLV_RET_FAILED_PARAM; std::string strReply; @@ -1846,7 +1847,13 @@ ERlvCmdRet RlvCommandHandlerBaseImpl::processCommand(const RlvCo // If we made it this far then: // - the command was handled successfully so we send off the response // - the command failed but we still send off an - empty - response to keep the issuing script from blocking - RlvUtil::sendChatReply(nChannel, strReply); + if (nChannel != 0) + RlvUtil::sendChatReply(nChannel, strReply); + else + { + if (RlvFloaterConsole* pConsole = LLFloaterReg::findTypedInstance("rlv_console")) + pConsole->addCommandReply(rlvCmd.getBehaviour(), strReply); + } return eRet; } @@ -1865,7 +1872,7 @@ ERlvCmdRet RlvHandler::processReplyCommand(const RlvCommand& rlvCmd) const // Sanity check - should specify a - valid - reply channel S32 nChannel; - if ( (!LLStringUtil::convertToS32(rlvCmd.getParam(), nChannel)) || (!RlvUtil::isValidReplyChannel(nChannel)) ) + if ( (!LLStringUtil::convertToS32(rlvCmd.getParam(), nChannel)) || (!RlvUtil::isValidReplyChannel(nChannel, rlvCmd.getObjectID() == gAgent.getID())) ) return RLV_RET_FAILED_PARAM; // Process the command the legacy way @@ -1969,7 +1976,13 @@ ERlvCmdRet RlvHandler::processReplyCommand(const RlvCommand& rlvCmd) const // If we made it this far then: // - the command was handled successfully so we send off the response // - the command failed but we still send off an - empty - response to keep the issuing script from blocking - RlvUtil::sendChatReply(nChannel, strReply); + if (nChannel > 0) + RlvUtil::sendChatReply(nChannel, strReply); + else + { + if (RlvFloaterConsole* pConsole = LLFloaterReg::findTypedInstance("rlv_console")) + pConsole->addCommandReply(rlvCmd.getBehaviour(), strReply); + } return eRet; } diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index 5ea49154ba..6219133d01 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -217,7 +217,7 @@ public: bool isBlocked() const { return (m_pBhvrInfo) ? m_pBhvrInfo->isBlocked() : false; } bool isStrict() const { return m_fStrict; } bool isValid() const { return m_fValid; } - ERlvCmdRet processCommand() const { return (m_pBhvrInfo) ? m_pBhvrInfo->processCommand(*this) : RLV_RET_UNKNOWN; } + ERlvCmdRet processCommand() const { return (m_pBhvrInfo) ? m_pBhvrInfo->processCommand(*this) : RLV_RET_FAILED_UNKNOWN; } protected: static bool parseCommand(const std::string& strCommand, std::string& strBehaviour, std::string& strOption, std::string& strParam); diff --git a/indra/newview/skins/default/xui/en/floater_rlv_console.xml b/indra/newview/skins/default/xui/en/floater_rlv_console.xml new file mode 100644 index 0000000000..30f2e15800 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_rlv_console.xml @@ -0,0 +1,43 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b2f6a8f7e1..2bce8488f4 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1664,6 +1664,16 @@ parameter="RLVaWearReplaceUnlocked" /> + + + +