Experiences shouldn't have limitless access to RLVa by default

--HG--
branch : RLVa
meow-7.2.2
Kitty Barnett 2018-06-17 13:46:52 +02:00
parent cc0f1a61aa
commit 8940db0e19
4 changed files with 157 additions and 2 deletions

View File

@ -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:

View File

@ -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)

View File

@ -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();
}

View File

@ -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