Experiences shouldn't have limitless access to RLVa by default
--HG-- branch : RLVameow-7.2.2
parent
cc0f1a61aa
commit
8940db0e19
|
|
@ -374,6 +374,8 @@ const char* RlvStrings::getStringFromReturnCode(ERlvCmdRet eRet)
|
|||
return "deprecated and disabled";
|
||||
case RLV_RET_FAILED_NOBEHAVIOUR:
|
||||
return "no active behaviours";
|
||||
case RLV_RET_FAILED_BLOCKED:
|
||||
return "blocked object";
|
||||
// The following are identified by the chat verb
|
||||
case RLV_RET_RETAINED:
|
||||
case RLV_RET_SUCCESS:
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ enum ERlvCmdRet {
|
|||
RLV_RET_FAILED_NOSHAREDROOT, // Command failed (missing #RLV)
|
||||
RLV_RET_FAILED_DEPRECATED, // Command failed (deprecated and no longer supported)
|
||||
RLV_RET_FAILED_NOBEHAVIOUR, // Command failed (force modifier on an object with no active restrictions)
|
||||
RLV_RET_FAILED_BLOCKED, // Command failed (object is blocked)
|
||||
RLV_RET_NO_PROCESSOR // Command doesn't have a template processor define (legacy code)
|
||||
};
|
||||
#define RLV_RET_SUCCEEDED(eCmdRet) (((eCmdRet) & RLV_RET_SUCCESS) == RLV_RET_SUCCESS)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#include "llagent.h"
|
||||
#include "llappearancemgr.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llexperiencelog.h"
|
||||
#include "llgroupactions.h"
|
||||
#include "llhudtext.h"
|
||||
#include "llmoveview.h"
|
||||
|
|
@ -259,6 +261,78 @@ void RlvHandler::removeException(const LLUUID& idObj, ERlvBehaviour eBhvr, const
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Blocked object handling
|
||||
//
|
||||
|
||||
void RlvHandler::addBlockedObject(const LLUUID& idObj, const std::string& strName)
|
||||
{
|
||||
m_BlockedObjects.push_back(std::make_tuple(idObj, strName, LLTimer::getTotalSeconds()));
|
||||
}
|
||||
|
||||
bool RlvHandler::hasUnresolvedBlockedObject() const
|
||||
{
|
||||
return std::any_of(m_BlockedObjects.begin(), m_BlockedObjects.end(), [](const rlv_blocked_object_t& entry) { return std::get<0>(entry).isNull(); });
|
||||
}
|
||||
|
||||
bool RlvHandler::isBlockedObject(const LLUUID& idObj) const
|
||||
{
|
||||
return std::any_of(m_BlockedObjects.begin(), m_BlockedObjects.end(), [&idObj](const rlv_blocked_object_t& entry) { return std::get<0>(entry) == idObj; });
|
||||
}
|
||||
|
||||
void RlvHandler::removeBlockedObject(const LLUUID& idObj)
|
||||
{
|
||||
m_BlockedObjects.erase(std::remove_if(m_BlockedObjects.begin(), m_BlockedObjects.end(),
|
||||
[&idObj](const rlv_blocked_object_t& entry) {
|
||||
return (idObj.notNull()) ? std::get<0>(entry) == idObj : false;
|
||||
}), m_BlockedObjects.end());
|
||||
}
|
||||
|
||||
void RlvHandler::getAttachmentResourcesCoro(const std::string& strUrl)
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("RlvHandler::getAttachmentResourcesCoro", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
const LLSD sdResult = httpAdapter->getAndSuspend(httpRequest, strUrl);
|
||||
|
||||
const LLCore::HttpStatus httpStatus = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(sdResult[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]);
|
||||
if ( (httpStatus) && (sdResult.has("attachments")) )
|
||||
{
|
||||
const LLSD& sdAttachments = sdResult["attachments"];
|
||||
for (auto& itAttach = sdAttachments.beginArray(), endAttach = sdAttachments.endArray(); itAttach != endAttach; ++itAttach)
|
||||
{
|
||||
if (!itAttach->has("objects"))
|
||||
continue;
|
||||
|
||||
const LLSD& sdAttachObjects = itAttach->get("objects");
|
||||
for (auto& itAttachObj = sdAttachObjects.beginArray(), endAttachObj = sdAttachObjects.endArray(); itAttachObj != endAttachObj; ++itAttachObj)
|
||||
{
|
||||
const LLUUID idObj = itAttachObj->get("id").asUUID();
|
||||
const std::string& strObjName = itAttachObj->get("name").asStringRef();
|
||||
|
||||
// If it's an attachment, it should be a temporary one (NOTE: we might catch it before it's had a chance to attach)
|
||||
const LLViewerObject* pObj = gObjectList.findObject(idObj);
|
||||
if ( (pObj) && ((!pObj->isAttachment()) || (!pObj->isTempAttachment()) || (isBlockedObject(idObj))) )
|
||||
continue;
|
||||
|
||||
// Find it by object name
|
||||
auto itBlockedObj = std::find_if(m_BlockedObjects.begin(), m_BlockedObjects.end(),
|
||||
[&strObjName](const rlv_blocked_object_t& entry) {
|
||||
return (std::get<0>(entry).isNull()) && (std::get<1>(entry) == strObjName);
|
||||
});
|
||||
if (m_BlockedObjects.end() != itBlockedObj)
|
||||
{
|
||||
std::get<0>(*itBlockedObj) = idObj;
|
||||
|
||||
RLV_INFOS << "Clearing restrictions from blocked object " << idObj.asString() << RLV_ENDL;
|
||||
processCommand(idObj, "clear", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Command processing functions
|
||||
//
|
||||
|
|
@ -309,6 +383,11 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj)
|
|||
{
|
||||
RLV_DEBUGS << "[" << rlvCmd.getObjectID() << "]: " << rlvCmd.asString() << RLV_ENDL;
|
||||
|
||||
if ( (isBlockedObject(rlvCmd.getObjectID())) && (RLV_TYPE_REMOVE != rlvCmd.getParamType()) && (RLV_TYPE_CLEAR != rlvCmd.getParamType()) )
|
||||
{
|
||||
RLV_DEBUGS << "\t-> blocked object" << RLV_ENDL;
|
||||
return RLV_RET_FAILED_BLOCKED;
|
||||
}
|
||||
if (!rlvCmd.isValid())
|
||||
{
|
||||
RLV_DEBUGS << "\t-> invalid syntax" << RLV_ENDL;
|
||||
|
|
@ -794,6 +873,42 @@ void RlvHandler::onDetach(const LLViewerObject* pAttachObj, const LLViewerJointA
|
|||
RLV_INFOS << "\t-> done" << RLV_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pAttachObj->isTempAttachment())
|
||||
{
|
||||
removeBlockedObject(pAttachObj->getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RlvHandler::onExperienceAttach(const LLSD& sdExperience, const std::string& strObjName)
|
||||
{
|
||||
if (sdExperience["maturity"].asInteger() != SIM_ACCESS_ADULT)
|
||||
{
|
||||
addBlockedObject(LLUUID::null, strObjName);
|
||||
|
||||
const std::string strUrl = gAgent.getRegionCapability("AttachmentResources");
|
||||
if (!strUrl.empty())
|
||||
{
|
||||
LLCoros::instance().launch("RlvHandler::getAttachmentResourcesCoro", boost::bind(&RlvHandler::getAttachmentResourcesCoro, this, strUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RlvHandler::onExperienceEvent(const LLSD& sdEvent)
|
||||
{
|
||||
const int nPermission = sdEvent["Permission"].asInteger();
|
||||
switch (nPermission)
|
||||
{
|
||||
case 4: // Attach
|
||||
{
|
||||
const LLUUID& idExperience = sdEvent["public_id"].asUUID();
|
||||
const std::string strObjName = sdEvent["ObjectName"].asString();
|
||||
LLExperienceCache::instance().get(idExperience, boost::bind(&RlvHandler::onExperienceAttach, this, _1, strObjName));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -848,6 +963,23 @@ bool RlvHandler::onGC()
|
|||
|
||||
RLV_ASSERT(gRlvAttachmentLocks.verifyAttachmentLocks()); // Verify that we haven't leaked any attachment locks somehow
|
||||
|
||||
// Clean up pending temp attachments that we were never able to resolve
|
||||
rlv_blocked_object_list_t::const_iterator itBlocked = m_BlockedObjects.cbegin(), itCurBlocked;
|
||||
while (itBlocked != m_BlockedObjects.end())
|
||||
{
|
||||
itCurBlocked = itBlocked++;
|
||||
#ifdef RLV_DEBUG
|
||||
bool itBlocked = true;
|
||||
RLV_ASSERT(itBlocked);
|
||||
#endif // RLV_DEBUG
|
||||
|
||||
const LLUUID& idObj = std::get<0>(*itCurBlocked);
|
||||
if ( (idObj.notNull()) || (LLTimer::getTotalSeconds() - std::get<2>(*itCurBlocked) < 300.f) )
|
||||
continue;
|
||||
|
||||
m_BlockedObjects.erase(itCurBlocked);
|
||||
}
|
||||
|
||||
return (0 != m_Objects.size()); // GC will kill itself if it has nothing to do
|
||||
}
|
||||
|
||||
|
|
@ -881,8 +1013,9 @@ void RlvHandler::onLoginComplete()
|
|||
RlvInventory::instance().fetchSharedInventory();
|
||||
RlvSettings::updateLoginLastLocation();
|
||||
|
||||
LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&RlvHandler::onTeleportFailed, this));
|
||||
LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&RlvHandler::onTeleportFinished, this, _1));
|
||||
m_ExperienceEventConn = LLExperienceLog::instance().addUpdateSignal(boost::bind(&RlvHandler::onExperienceEvent, this, _1));
|
||||
m_TeleportFailedConn = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&RlvHandler::onTeleportFailed, this));
|
||||
m_TeleportFinishedConn = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&RlvHandler::onTeleportFinished, this, _1));
|
||||
|
||||
processRetainedCommands();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,16 @@ public:
|
|||
bool isHiddenCompositeItem(const LLUUID& idItem, const std::string& strItemType) const;
|
||||
#endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
|
||||
|
||||
public:
|
||||
// Adds a blocked object (= object that is blocked from issuing commands) by UUID (can be null) and/or name
|
||||
void addBlockedObject(const LLUUID& idObj, const std::string& strObjName);
|
||||
// Returns TRUE if there's an unresolved blocked object (known name but unknown UUID)
|
||||
bool hasUnresolvedBlockedObject() const;
|
||||
// Returns TRUE if the object with the specified UUID is blocked from issuing commands
|
||||
bool isBlockedObject(const LLUUID& idObj) const;
|
||||
// Removes a blocked object
|
||||
void removeBlockedObject(const LLUUID& idObj);
|
||||
|
||||
// --------------------------------
|
||||
|
||||
/*
|
||||
|
|
@ -163,6 +173,8 @@ public:
|
|||
void onActiveGroupChanged();
|
||||
void onAttach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt);
|
||||
void onDetach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt);
|
||||
void onExperienceAttach(const LLSD& sdExperience, const std::string& strObjName);
|
||||
void onExperienceEvent(const LLSD& sdEvent);
|
||||
bool onGC();
|
||||
void onLoginComplete();
|
||||
void onSitOrStand(bool fSitting);
|
||||
|
|
@ -170,6 +182,7 @@ public:
|
|||
void onTeleportFinished(const LLVector3d& posArrival);
|
||||
static void onIdleStartup(void* pParam);
|
||||
protected:
|
||||
void getAttachmentResourcesCoro(const std::string& strUrl);
|
||||
void onTeleportCallback(U64 hRegion, const LLVector3& posRegion, const LLVector3& vecLookAt, const LLUUID& idRlvObj);
|
||||
|
||||
/*
|
||||
|
|
@ -214,9 +227,12 @@ protected:
|
|||
*/
|
||||
public:
|
||||
typedef std::map<LLUUID, RlvObject> rlv_object_map_t;
|
||||
typedef std::tuple<LLUUID, std::string, double> rlv_blocked_object_t;
|
||||
typedef std::list<rlv_blocked_object_t> rlv_blocked_object_list_t;
|
||||
typedef std::multimap<ERlvBehaviour, RlvException> rlv_exception_map_t;
|
||||
protected:
|
||||
rlv_object_map_t m_Objects; // Map of objects that have active restrictions (idObj -> RlvObject)
|
||||
rlv_blocked_object_list_t m_BlockedObjects; // List of (attached) objects that can't issue commands
|
||||
rlv_exception_map_t m_Exceptions; // Map of currently active restriction exceptions (ERlvBehaviour -> RlvException)
|
||||
S16 m_Behaviours[RLV_BHVR_COUNT];
|
||||
|
||||
|
|
@ -230,6 +246,9 @@ protected:
|
|||
rlv_behaviour_signal_t m_OnBehaviourToggle;
|
||||
rlv_command_signal_t m_OnCommand;
|
||||
mutable std::list<RlvExtCommandHandler*> m_CommandHandlers;
|
||||
boost::signals2::scoped_connection m_ExperienceEventConn;
|
||||
boost::signals2::scoped_connection m_TeleportFailedConn;
|
||||
boost::signals2::scoped_connection m_TeleportFinishedConn;
|
||||
|
||||
static bool m_fEnabled; // Use setEnabled() to toggle this
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue