summaryrefslogtreecommitdiff
path: root/indra/newview/llviewermessage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewermessage.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llviewermessage.cpp799
1 files changed, 612 insertions, 187 deletions
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e934c38c22..903f4437a7 100644..100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -42,6 +42,7 @@
#include "llinventorydefines.h"
#include "lllslconstants.h"
#include "llregionhandle.h"
+#include "llsd.h"
#include "llsdserialize.h"
#include "llteleportflags.h"
#include "lltransactionflags.h"
@@ -59,8 +60,9 @@
#include "llfloaterland.h"
#include "llfloaterregioninfo.h"
#include "llfloaterlandholdings.h"
-#include "llfloaterpostcard.h"
#include "llfloaterpreference.h"
+#include "llfloatersidepanelcontainer.h"
+#include "llfloatersnapshot.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llinventoryfunctions.h"
@@ -73,7 +75,6 @@
#include "llrecentpeople.h"
#include "llscriptfloater.h"
#include "llselectmgr.h"
-#include "llsidetray.h"
#include "llstartup.h"
#include "llsky.h"
#include "llslurl.h"
@@ -107,6 +108,7 @@
#include "llagentui.h"
#include "llpanelblockedlist.h"
#include "llpanelplaceprofile.h"
+#include "llviewerregion.h"
#include <boost/algorithm/string/split.hpp> //
#include <boost/regex.hpp>
@@ -132,9 +134,11 @@ static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests
static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds
extern BOOL gDebugClicks;
+extern bool gShiftFrame;
// function prototypes
bool check_offer_throttle(const std::string& from_name, bool check_only);
+bool check_asset_previewable(const LLAssetType::EType asset_type);
static void process_money_balance_reply_extended(LLMessageSystem* msg);
//inventory offer throttle globals
@@ -155,7 +159,8 @@ const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] =
"AddAndRemoveJoints",
"ChangePermissions",
"TrackYourCamera",
- "ControlYourCamera"
+ "ControlYourCamera",
+ "TeleportYourAgent"
};
const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =
@@ -170,7 +175,8 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =
FALSE, // AddAndRemoveJoints
FALSE, // ChangePermissions
FALSE, // TrackYourCamera,
- FALSE // ControlYourCamera
+ FALSE, // ControlYourCamera
+ FALSE // TeleportYourAgent
};
bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
@@ -1049,48 +1055,28 @@ void start_new_inventory_observer()
class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver
{
LOG_CLASS(LLDiscardAgentOffer);
+
public:
LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) :
LLInventoryFetchItemsObserver(object_id),
mFolderID(folder_id),
mObjectID(object_id) {}
- virtual ~LLDiscardAgentOffer() {}
+
virtual void done()
{
LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL;
- const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
- bool notify = false;
- if(trash_id.notNull() && mObjectID.notNull())
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(mFolderID, -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
- gInventory.moveObject(mObjectID, trash_id);
- LLInventoryObject* obj = gInventory.getObject(mObjectID);
- if(obj)
- {
- // no need to restamp since this is already a freshly
- // stamped item.
- obj->updateParentOnServer(FALSE);
- notify = true;
- }
- }
- else
- {
- LL_WARNS("Messaging") << "DiscardAgentOffer unable to find: "
- << (trash_id.isNull() ? "trash " : "")
- << (mObjectID.isNull() ? "object" : "") << LL_ENDL;
- }
+
+ // We're invoked from LLInventoryModel::notifyObservers().
+ // If we now try to remove the inventory item, it will cause a nested
+ // notifyObservers() call, which won't work.
+ // So defer moving the item to trash until viewer gets idle (in a moment).
+ // Use removeObject() rather than removeItem() because at this level,
+ // the object could be either an item or a folder.
+ LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeObject, &gInventory, mObjectID));
gInventory.removeObserver(this);
- if(notify)
- {
- gInventory.notifyObservers();
- }
delete this;
}
+
protected:
LLUUID mFolderID;
LLUUID mObjectID;
@@ -1169,7 +1155,18 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)
}
}
}
-
+
+// Return "true" if we have a preview method for that asset type, "false" otherwise
+bool check_asset_previewable(const LLAssetType::EType asset_type)
+{
+ return (asset_type == LLAssetType::AT_NOTECARD) ||
+ (asset_type == LLAssetType::AT_LANDMARK) ||
+ (asset_type == LLAssetType::AT_TEXTURE) ||
+ (asset_type == LLAssetType::AT_ANIMATION) ||
+ (asset_type == LLAssetType::AT_SCRIPT) ||
+ (asset_type == LLAssetType::AT_SOUND);
+}
+
void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name)
{
for (uuid_vec_t::const_iterator obj_iter = objects.begin();
@@ -1193,7 +1190,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
// Either an inventory item or a category.
const LLInventoryItem* item = dynamic_cast<const LLInventoryItem*>(obj);
- if (item)
+ if (item && check_asset_previewable(asset_type))
{
////////////////////////////////////////////////////////////////////////////////
// Special handling for various types.
@@ -1214,9 +1211,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID());
if ("inventory_handler" == from_name)
{
- //we have to filter inventory_handler messages to avoid notification displaying
- LLSideTray::getInstance()->showPanel("panel_places",
- LLSD().with("type", "landmark").with("id", item->getUUID()));
+ LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "landmark").with("id", item->getUUID()));
}
else if("group_offer" == from_name)
{
@@ -1225,7 +1220,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
LLSD args;
args["type"] = "landmark";
args["id"] = obj_id;
- LLSideTray::getInstance()->showPanel("panel_places", args);
+ LLFloaterSidePanelContainer::showPanel("places", args);
continue;
}
@@ -1270,6 +1265,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus);
break;
default:
+ LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type) << LL_ENDL;
break;
}
}
@@ -1280,14 +1276,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
const BOOL auto_open =
gSavedSettings.getBOOL("ShowInInventory") && // don't open if showininventory is false
!from_name.empty(); // don't open if it's not from anyone.
- LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open);
- if(active_panel)
- {
- LL_DEBUGS("Messaging") << "Highlighting" << obj_id << LL_ENDL;
- LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
- active_panel->setSelection(obj_id, TAKE_FOCUS_NO);
- gFocusMgr.setKeyboardFocus(focus_ctrl);
- }
+ LLInventoryPanel::openInventoryPanelAndSetSelection(auto_open, obj_id);
}
}
@@ -1321,29 +1310,12 @@ bool highlight_offered_object(const LLUUID& obj_id)
void inventory_offer_mute_callback(const LLUUID& blocked_id,
const std::string& full_name,
- bool is_group,
- boost::shared_ptr<LLNotificationResponderInterface> offer_ptr)
+ bool is_group)
{
- LLOfferInfo* offer = dynamic_cast<LLOfferInfo*>(offer_ptr.get());
-
- std::string from_name = full_name;
- LLMute::EType type;
- if (is_group)
- {
- type = LLMute::GROUP;
- }
- else if(offer && offer->mFromObject)
- {
- //we have to block object by name because blocked_id is an id of owner
- type = LLMute::BY_NAME;
- }
- else
- {
- type = LLMute::AGENT;
- }
+ // *NOTE: blocks owner if the offer came from an object
+ LLMute::EType mute_type = is_group ? LLMute::GROUP : LLMute::AGENT;
- // id should be null for BY_NAME mute, see LLMuteList::add for details
- LLMute mute(type == LLMute::BY_NAME ? LLUUID::null : blocked_id, from_name, type);
+ LLMute mute(blocked_id, full_name, mute_type);
if (LLMuteList::getInstance()->add(mute))
{
LLPanelBlockedList::showPanelAndSelect(blocked_id);
@@ -1357,6 +1329,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,
bool matches(const LLNotificationPtr notification) const
{
if(notification->getName() == "ObjectGiveItem"
+ || notification->getName() == "OwnObjectGiveItem"
|| notification->getName() == "UserGiveItem")
{
return (notification->getPayload()["from_id"].asUUID() == blocked_id);
@@ -1495,7 +1468,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
LLChat chat;
std::string log_message;
S32 button = LLNotificationsUtil::getSelectedOption(notification, response);
-
+
LLInventoryObserver* opener = NULL;
LLViewerInventoryCategory* catp = NULL;
catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID);
@@ -1517,7 +1490,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
llassert(notification_ptr != NULL);
if (notification_ptr != NULL)
{
- gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,notification_ptr->getResponderPtr()));
+ gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3));
}
}
@@ -1527,7 +1500,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:
from_string = chatHistory_string = mFromName;
- bool busy=FALSE;
+ bool busy = gAgent.getBusy();
switch(button)
{
@@ -1586,9 +1559,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
}
break;
- case IOR_BUSY:
- //Busy falls through to decline. Says to make busy message.
- busy=TRUE;
case IOR_MUTE:
// MUTE falls through to decline
case IOR_DECLINE:
@@ -1665,7 +1635,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
llassert(notification_ptr != NULL);
if (notification_ptr != NULL)
{
- gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,notification_ptr->getResponderPtr()));
+ gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3));
}
}
@@ -1734,7 +1704,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
from_string = chatHistory_string = mFromName;
}
- bool busy=FALSE;
+ bool busy = gAgent.getBusy();
switch(button)
{
@@ -1780,9 +1750,6 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
} // end switch (mIM)
break;
- case IOR_BUSY:
- //Busy falls through to decline. Says to make busy message.
- busy=TRUE;
case IOR_MUTE:
// MUTE falls through to decline
case IOR_DECLINE:
@@ -1846,22 +1813,18 @@ void LLOfferInfo::initRespondFunctionMap()
if(mRespondFunctions.empty())
{
mRespondFunctions["ObjectGiveItem"] = boost::bind(&LLOfferInfo::inventory_task_offer_callback, this, _1, _2);
+ mRespondFunctions["OwnObjectGiveItem"] = boost::bind(&LLOfferInfo::inventory_task_offer_callback, this, _1, _2);
mRespondFunctions["UserGiveItem"] = boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2);
}
}
void inventory_offer_handler(LLOfferInfo* info)
{
- //Until throttling is implmented, busy mode should reject inventory instead of silently
- //accepting it. SEE SL-39554
- if (gAgent.getBusy())
- {
- info->forceResponse(IOR_BUSY);
- return;
- }
-
- //If muted, don't even go through the messaging stuff. Just curtail the offer here.
- if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName))
+ // If muted, don't even go through the messaging stuff. Just curtail the offer here.
+ // Passing in a null UUID handles the case of where you have muted one of your own objects by_name.
+ // The solution for STORM-1297 seems to handle the cases where the object is owned by someone else.
+ if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName) ||
+ LLMuteList::getInstance()->isMuted(LLUUID::null, info->mFromName))
{
info->forceResponse(IOR_MUTE);
return;
@@ -1941,7 +1904,7 @@ void inventory_offer_handler(LLOfferInfo* info)
std::string verb = "select?name=" + LLURI::escape(msg);
args["ITEM_SLURL"] = LLSLURL("inventory", info->mObjectID, verb.c_str()).getSLURLString();
- LLNotification::Params p("ObjectGiveItem");
+ LLNotification::Params p;
// Object -> Agent Inventory Offer
if (info->mFromObject)
@@ -1951,7 +1914,10 @@ void inventory_offer_handler(LLOfferInfo* info)
// Note: sets inventory_task_offer_callback as the callback
p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info));
info->mPersist = true;
- p.name = "ObjectGiveItem";
+
+ // Offers from your own objects need a special notification template.
+ p.name = info->mFromID == gAgentID ? "OwnObjectGiveItem" : "ObjectGiveItem";
+
// Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory.
LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, info->mFromGroup == TRUE);
}
@@ -2029,6 +1995,46 @@ bool lure_callback(const LLSD& notification, const LLSD& response)
}
static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback);
+bool mature_lure_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = 0;
+ if (response.isInteger())
+ {
+ option = response.asInteger();
+ }
+ else
+ {
+ option = LLNotificationsUtil::getSelectedOption(notification, response);
+ }
+
+ LLUUID from_id = notification["payload"]["from_id"].asUUID();
+ LLUUID lure_id = notification["payload"]["lure_id"].asUUID();
+ BOOL godlike = notification["payload"]["godlike"].asBoolean();
+ U8 region_access = static_cast<U8>(notification["payload"]["region_maturity"].asInteger());
+
+ switch(option)
+ {
+ case 0:
+ {
+ // accept
+ gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(region_access));
+ gAgent.setMaturityRatingChangeDuringTeleport(region_access);
+ gAgent.teleportViaLure(lure_id, godlike);
+ }
+ break;
+ case 1:
+ default:
+ // decline
+ send_simple_im(from_id,
+ LLStringUtil::null,
+ IM_LURE_DECLINED,
+ lure_id);
+ break;
+ }
+ return false;
+}
+static LLNotificationFunctorRegistration mature_lure_callback_reg("TeleportOffered_MaturityExceeded", mature_lure_callback);
+
bool goto_url_callback(const LLSD& notification, const LLSD& response)
{
std::string url = notification["payload"]["url"].asString();
@@ -2238,7 +2244,7 @@ void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string m
// Treat like a system message and put in chat history.
chat.mText = av_name.getCompleteName() + ": " + message;
- LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
if(nearby_chat)
{
nearby_chat->addMessage(chat);
@@ -2289,6 +2295,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
name = LLTrans::getString("Unnamed");
}
+
+ // Preserve the unaltered name for use in group notice mute checking.
+ std::string original_name = name;
+
// IDEVO convert new-style "Resident" names for display
name = clean_name_from_im(name, dialog);
@@ -2410,8 +2420,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
bool mute_im = is_muted;
- if(accept_im_from_only_friend&&!is_friend)
+ if (accept_im_from_only_friend && !is_friend)
{
+ if (!gIMMgr->isNonFriendSessionNotified(session_id))
+ {
+ std::string message = LLTrans::getString("IM_unblock_only_groups_friends");
+ gIMMgr->addMessage(session_id, from_id, name, message);
+ gIMMgr->addNotifiedNonFriendSessionID(session_id);
+ }
+
mute_im = true;
}
if (!mute_im || is_linden)
@@ -2495,6 +2512,26 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
break;
}
+ // The group notice packet does not have an AgentID. Obtain one from the name cache.
+ // If last name is "Resident" strip it out so the cache name lookup works.
+ U32 index = original_name.find(" Resident");
+ if (index != std::string::npos)
+ {
+ original_name = original_name.substr(0, index);
+ }
+ std::string legacy_name = gCacheName->buildLegacyName(original_name);
+ LLUUID agent_id;
+ gCacheName->getUUID(legacy_name, agent_id);
+
+ if (agent_id.isNull())
+ {
+ LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL;
+ }
+ else if (LLMuteList::getInstance()->isMuted(agent_id))
+ {
+ break;
+ }
+
notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0];
U8 has_inventory = notice_bin_bucket->header.has_inventory;
U8 asset_type = notice_bin_bucket->header.asset_type;
@@ -2630,8 +2667,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];
info->mType = (LLAssetType::EType) bucketp->asset_type;
info->mObjectID = bucketp->object_id;
+ info->mFromObject = FALSE;
}
- else
+ else // IM_TASK_INVENTORY_OFFERED
{
if (sizeof(S8) != binary_bucket_size)
{
@@ -2641,6 +2679,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
info->mType = (LLAssetType::EType) binary_bucket[0];
info->mObjectID = LLUUID::null;
+ info->mFromObject = TRUE;
}
info->mIM = dialog;
@@ -2649,14 +2688,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
info->mTransactionID = session_id;
info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
- if (dialog == IM_TASK_INVENTORY_OFFERED)
- {
- info->mFromObject = TRUE;
- }
- else
- {
- info->mFromObject = FALSE;
- }
info->mFromName = name;
info->mDesc = message;
info->mHost = msg->getSender();
@@ -2671,6 +2702,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// Same as closing window
info->forceResponse(IOR_DECLINE);
}
+ else if (is_busy && dialog != IM_TASK_INVENTORY_OFFERED) // busy mode must not affect interaction with objects (STORM-565)
+ {
+ // Until throttling is implemented, busy mode should reject inventory instead of silently
+ // accepting it. SEE SL-39554
+ info->forceResponse(IOR_DECLINE);
+ }
else
{
inventory_offer_handler(info);
@@ -2712,7 +2749,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
case IM_SESSION_SEND:
{
- if (!is_linden && is_busy)
+ if (is_busy)
{
return;
}
@@ -2776,7 +2813,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
chat.mSourceType = CHAT_SOURCE_OBJECT;
- if(SYSTEM_FROM == name)
+ // To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not
+ // enough to check only from name (i.e. fromName = "Second Life"). For example
+ // source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM.
+ bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull();
+ if(chat_from_system)
{
// System's UUID is NULL (fixes EXT-4766)
chat.mFromID = LLUUID::null;
@@ -2800,8 +2841,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// Note: lie to Nearby Chat, pretending that this is NOT an IM, because
// IMs from obejcts don't open IM sessions.
- LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
- if(SYSTEM_FROM != name && nearby_chat)
+ LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
+ if(!chat_from_system && nearby_chat)
{
chat.mOwnerID = from_id;
LLSD args;
@@ -2820,7 +2861,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
//Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590)
- if (SYSTEM_FROM != name) break;
+ if (!chat_from_system) break;
LLSD substitutions;
substitutions["NAME"] = name;
@@ -2884,16 +2925,55 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
else
{
LLVector3 pos, look_at;
- U64 region_handle;
- U8 region_access;
+ U64 region_handle(0);
+ U8 region_access(SIM_ACCESS_MIN);
std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size);
std::string region_access_str = LLStringUtil::null;
std::string region_access_icn = LLStringUtil::null;
+ std::string region_access_lc = LLStringUtil::null;
+
+ bool canUserAccessDstRegion = true;
+ bool doesUserRequireMaturityIncrease = false;
if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))
{
region_access_str = LLViewerRegion::accessToString(region_access);
region_access_icn = LLViewerRegion::getAccessIcon(region_access);
+ region_access_lc = region_access_str;
+ LLStringUtil::toLower(region_access_lc);
+
+ if (!gAgent.isGodlike())
+ {
+ switch (region_access)
+ {
+ case SIM_ACCESS_MIN :
+ case SIM_ACCESS_PG :
+ break;
+ case SIM_ACCESS_MATURE :
+ if (gAgent.isTeen())
+ {
+ canUserAccessDstRegion = false;
+ }
+ else if (gAgent.prefersPG())
+ {
+ doesUserRequireMaturityIncrease = true;
+ }
+ break;
+ case SIM_ACCESS_ADULT :
+ if (!gAgent.isAdult())
+ {
+ canUserAccessDstRegion = false;
+ }
+ else if (!gAgent.prefersAdult())
+ {
+ doesUserRequireMaturityIncrease = true;
+ }
+ break;
+ default :
+ llassert(0);
+ break;
+ }
+ }
}
LLSD args;
@@ -2902,28 +2982,130 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
args["MESSAGE"] = message;
args["MATURITY_STR"] = region_access_str;
args["MATURITY_ICON"] = region_access_icn;
+ args["REGION_CONTENT_MATURITY"] = region_access_lc;
LLSD payload;
payload["from_id"] = from_id;
payload["lure_id"] = session_id;
payload["godlike"] = FALSE;
+ payload["region_maturity"] = region_access;
+
+ if (!canUserAccessDstRegion)
+ {
+ LLNotification::Params params("TeleportOffered_MaturityBlocked");
+ params.substitutions = args;
+ params.payload = payload;
+ LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false);
+ send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id);
+ send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id);
+ }
+ else if (doesUserRequireMaturityIncrease)
+ {
+ LLNotification::Params params("TeleportOffered_MaturityExceeded");
+ params.substitutions = args;
+ params.payload = payload;
+ LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false);
+ }
+ else
+ {
+ LLNotification::Params params("TeleportOffered");
+ params.substitutions = args;
+ params.payload = payload;
+ LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false);
+ }
- LLNotification::Params params("TeleportOffered");
- params.substitutions = args;
- params.payload = payload;
- LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false);
}
}
break;
case IM_GODLIKE_LURE_USER:
{
+ LLVector3 pos, look_at;
+ U64 region_handle(0);
+ U8 region_access(SIM_ACCESS_MIN);
+ std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size);
+ std::string region_access_str = LLStringUtil::null;
+ std::string region_access_icn = LLStringUtil::null;
+ std::string region_access_lc = LLStringUtil::null;
+
+ bool canUserAccessDstRegion = true;
+ bool doesUserRequireMaturityIncrease = false;
+
+ if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))
+ {
+ region_access_str = LLViewerRegion::accessToString(region_access);
+ region_access_icn = LLViewerRegion::getAccessIcon(region_access);
+ region_access_lc = region_access_str;
+ LLStringUtil::toLower(region_access_lc);
+
+ if (!gAgent.isGodlike())
+ {
+ switch (region_access)
+ {
+ case SIM_ACCESS_MIN :
+ case SIM_ACCESS_PG :
+ break;
+ case SIM_ACCESS_MATURE :
+ if (gAgent.isTeen())
+ {
+ canUserAccessDstRegion = false;
+ }
+ else if (gAgent.prefersPG())
+ {
+ doesUserRequireMaturityIncrease = true;
+ }
+ break;
+ case SIM_ACCESS_ADULT :
+ if (!gAgent.isAdult())
+ {
+ canUserAccessDstRegion = false;
+ }
+ else if (!gAgent.prefersAdult())
+ {
+ doesUserRequireMaturityIncrease = true;
+ }
+ break;
+ default :
+ llassert(0);
+ break;
+ }
+ }
+ }
+
+ LLSD args;
+ // *TODO: Translate -> [FIRST] [LAST] (maybe)
+ args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
+ args["MESSAGE"] = message;
+ args["MATURITY_STR"] = region_access_str;
+ args["MATURITY_ICON"] = region_access_icn;
+ args["REGION_CONTENT_MATURITY"] = region_access_lc;
LLSD payload;
payload["from_id"] = from_id;
payload["lure_id"] = session_id;
payload["godlike"] = TRUE;
- // do not show a message box, because you're about to be
- // teleported.
- LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0);
+ payload["region_maturity"] = region_access;
+
+ if (!canUserAccessDstRegion)
+ {
+ LLNotification::Params params("TeleportOffered_MaturityBlocked");
+ params.substitutions = args;
+ params.payload = payload;
+ LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false);
+ send_simple_im(from_id, LLTrans::getString("TeleportMaturityExceeded"), IM_NOTHING_SPECIAL, session_id);
+ send_simple_im(from_id, LLStringUtil::null, IM_LURE_DECLINED, session_id);
+ }
+ else if (doesUserRequireMaturityIncrease)
+ {
+ LLNotification::Params params("TeleportOffered_MaturityExceeded");
+ params.substitutions = args;
+ params.payload = payload;
+ LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false);
+ }
+ else
+ {
+ // do not show a message box, because you're about to be
+ // teleported.
+ LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0);
+ }
}
break;
@@ -3168,7 +3350,7 @@ protected:
{
// filter out non-interesting responeses
if ( !translation.empty()
- && (m_toLang != detected_language)
+ && (mToLang != detected_language)
&& (LLStringUtil::compareInsensitive(translation, m_origMesg) != 0) )
{
m_chat.mText += " (" + translation + ")";
@@ -3177,10 +3359,13 @@ protected:
LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
}
- void handleFailure()
+ void handleFailure(int status, const std::string& err_msg)
{
- LLTranslate::TranslationReceiver::handleFailure();
- m_chat.mText += " (?)";
+ llwarns << "Translation failed for mesg " << m_origMesg << " toLang " << mToLang << " fromLang " << mFromLang << llendl;
+
+ std::string msg = LLTrans::getString("TranslationFailed", LLSD().with("[REASON]", err_msg));
+ LLStringUtil::replaceString(msg, "\n", " "); // we want one-line error messages
+ m_chat.mText += " (" + msg + ")";
LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
}
@@ -3418,7 +3603,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
const std::string from_lang = ""; // leave empty to trigger autodetect
const std::string to_lang = LLTranslate::getTranslateLanguage();
- LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
+ LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
LLTranslate::translateMessage(result, from_lang, to_lang, mesg);
}
else
@@ -3444,6 +3629,9 @@ void process_teleport_start(LLMessageSystem *msg, void**)
LL_DEBUGS("Messaging") << "Got TeleportStart with TeleportFlags=" << teleport_flags << ". gTeleportDisplay: " << gTeleportDisplay << ", gAgent.mTeleportState: " << gAgent.getTeleportState() << LL_ENDL;
+ // *NOTE: The server sends two StartTeleport packets when you are teleporting to a LM
+ LLViewerMessage::getInstance()->mTeleportStartedSignal();
+
if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL)
{
gViewerWindow->setProgressCancelButtonVisible(FALSE);
@@ -3463,11 +3651,17 @@ void process_teleport_start(LLMessageSystem *msg, void**)
make_ui_sound("UISndTeleportOut");
LL_INFOS("Messaging") << "Teleport initiated by remote TeleportStart message with TeleportFlags: " << teleport_flags << LL_ENDL;
+
// Don't call LLFirstUse::useTeleport here because this could be
// due to being killed, which would send you home, not to a Telehub
}
}
+boost::signals2::connection LLViewerMessage::setTeleportStartedCallback(teleport_started_callback_t cb)
+{
+ return mTeleportStartedSignal.connect(cb);
+}
+
void process_teleport_progress(LLMessageSystem* msg, void**)
{
LLUUID agent_id;
@@ -3689,6 +3883,9 @@ void process_teleport_finish(LLMessageSystem* msg, void**)
gCacheName->setUpstream(sim);
*/
+ // Make sure we're standing
+ gAgent.standUp();
+
// now, use the circuit info to tell simulator about us!
LL_INFOS("Messaging") << "process_teleport_finish() Enabling "
<< sim_host << " with code " << msg->mOurCircuitCode << LL_ENDL;
@@ -3734,6 +3931,7 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**)
void process_agent_movement_complete(LLMessageSystem* msg, void**)
{
+ gShiftFrame = true;
gAgentMovementCompleted = true;
LLUUID agent_id;
@@ -4064,6 +4262,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
head_rot_chg = dot(last_head_rot, head_rotation);
+ //static S32 msg_number = 0; // Used for diagnostic log messages
+
if (force_send ||
(cam_center_chg.magVec() > TRANSLATE_THRESHOLD) ||
(head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) ||
@@ -4072,19 +4272,20 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
control_flag_change != 0 ||
flag_change != 0)
{
-/*
+ /* Diagnotics to show why we send the AgentUpdate message. Also un-commment the msg_number code above and below this block
+ msg_number += 1;
if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT)
{
- //LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL;
- LL_INFOS("Messaging") << "head_rot_chg = " << head_rot_chg << LL_ENDL;
+ //LL_INFOS("Messaging") << " head rot " << head_rotation << LL_ENDL;
+ LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", head_rot_chg " << head_rot_chg << LL_ENDL;
}
if (cam_rot_chg.magVec() > ROTATION_THRESHOLD)
{
- LL_INFOS("Messaging") << "cam rot " << cam_rot_chg.magVec() << LL_ENDL;
+ LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam rot " << cam_rot_chg.magVec() << LL_ENDL;
}
if (cam_center_chg.magVec() > TRANSLATE_THRESHOLD)
{
- LL_INFOS("Messaging") << "cam center " << cam_center_chg.magVec() << LL_ENDL;
+ LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam center " << cam_center_chg.magVec() << LL_ENDL;
}
// if (drag_delta_chg.magVec() > TRANSLATE_THRESHOLD)
// {
@@ -4092,9 +4293,9 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
// }
if (control_flag_change)
{
- LL_INFOS("Messaging") << "dcf = " << control_flag_change << LL_ENDL;
+ LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", dcf = " << control_flag_change << LL_ENDL;
}
-*/
+ */
duplicate_count = 0;
}
@@ -4129,6 +4330,26 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
if (duplicate_count < DUP_MSGS && !gDisconnected)
{
+ /* More diagnostics to count AgentUpdate messages
+ static S32 update_sec = 0;
+ static S32 update_count = 0;
+ static S32 max_update_count = 0;
+ S32 cur_sec = lltrunc( LLTimer::getTotalSeconds() );
+ update_count += 1;
+ if (cur_sec != update_sec)
+ {
+ if (update_sec != 0)
+ {
+ update_sec = cur_sec;
+ //msg_number = 0;
+ max_update_count = llmax(max_update_count, update_count);
+ llinfos << "Sent " << update_count << " AgentUpdate messages per second, max is " << max_update_count << llendl;
+ }
+ update_sec = cur_sec;
+ update_count = 0;
+ }
+ */
+
LLFastTimer t(FTM_AGENT_UPDATE_SEND);
// Build the message
msg->newMessageFast(_PREHASH_AgentUpdate);
@@ -4297,8 +4518,6 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL;
}
- LLSelectMgr::getInstance()->removeObjectFromSelections(id);
-
// ...don't kill the avatar
if (!(id == gAgentID))
{
@@ -4321,6 +4540,12 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
gObjectList.mNumUnknownKills++;
}
}
+
+ // We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab,
+ // which is using the object, release the mouse capture correctly when the object dies.
+ // See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical().
+ LLSelectMgr::getInstance()->removeObjectFromSelections(id);
+
}
}
@@ -4630,6 +4855,18 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
case LL_SIM_STAT_IOPUMPTIME:
LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value);
break;
+ case LL_SIM_STAT_PCTSCRIPTSRUN:
+ LLViewerStats::getInstance()->mSimPctScriptsRun.addValue(stat_value);
+ break;
+ case LL_SIM_STAT_SIMAISTEPTIMEMS:
+ LLViewerStats::getInstance()->mSimSimAIStepMsec.addValue(stat_value);
+ break;
+ case LL_SIM_STAT_SKIPPEDAISILSTEPS_PS:
+ LLViewerStats::getInstance()->mSimSimSkippedSilhouetteSteps.addValue(stat_value);
+ break;
+ case LL_SIM_STAT_PCTSTEPPEDCHARACTERS:
+ LLViewerStats::getInstance()->mSimSimPctSteppedCharacters.addValue(stat_value);
+ break;
default:
// Used to be a commented out warning.
LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL;
@@ -4739,7 +4976,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
LLViewerObject* object = gObjectList.findObject(object_id);
if (object)
{
- object->mFlags |= FLAGS_ANIM_SOURCE;
+ object->setFlagsWithoutUpdate(FLAGS_ANIM_SOURCE, TRUE);
BOOL anim_found = FALSE;
LLVOAvatar::AnimSourceIterator anim_it = avatarp->mAnimationSources.find(object_id);
@@ -4886,7 +5123,7 @@ void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_dat
LLViewerObject* objectp = gObjectList.findObject(source_id);
if (objectp)
{
- objectp->mFlags |= FLAGS_CAMERA_SOURCE;
+ objectp->setFlagsWithoutUpdate(FLAGS_CAMERA_SOURCE, TRUE);
}
S32 num_objects = mesgsys->getNumberOfBlocks("CameraProperty");
@@ -5254,6 +5491,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
BOOL is_dest_group = FALSE;
S32 amount = 0;
std::string item_description;
+ BOOL success = FALSE;
msg->getS32("TransactionInfo", "TransactionType", transaction_type);
msg->getUUID("TransactionInfo", "SourceID", source_id);
@@ -5262,6 +5500,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
msg->getBOOL("TransactionInfo", "IsDestGroup", is_dest_group);
msg->getS32("TransactionInfo", "Amount", amount);
msg->getString("TransactionInfo", "ItemDescription", item_description);
+ msg->getBOOL("MoneyData", "TransactionSuccess", success);
LL_INFOS("Money") << "MoneyBalanceReply source " << source_id
<< " dest " << dest_id
<< " type " << transaction_type
@@ -5323,28 +5562,32 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
{
if (dest_id.notNull())
{
- message = LLTrans::getString("you_paid_ldollars", args);
+ message = success ? LLTrans::getString("you_paid_ldollars", args) :
+ LLTrans::getString("you_paid_failure_ldollars", args);
}
else
{
// transaction fee to the system, eg, to create a group
- message = LLTrans::getString("you_paid_ldollars_no_name", args);
+ message = success ? LLTrans::getString("you_paid_ldollars_no_name", args) :
+ LLTrans::getString("you_paid_failure_ldollars_no_name", args);
}
}
else
{
if (dest_id.notNull())
{
- message = LLTrans::getString("you_paid_ldollars_no_reason", args);
+ message = success ? LLTrans::getString("you_paid_ldollars_no_reason", args) :
+ LLTrans::getString("you_paid_failure_ldollars_no_reason", args);
}
else
{
// no target, no reason, you just paid money
- message = LLTrans::getString("you_paid_ldollars_no_info", args);
+ message = success ? LLTrans::getString("you_paid_ldollars_no_info", args) :
+ LLTrans::getString("you_paid_failure_ldollars_no_info", args);
}
}
final_args["MESSAGE"] = message;
- notification = "PaymentSent";
+ notification = success ? "PaymentSent" : "PaymentFailure";
}
else {
// ...someone paid you
@@ -5383,23 +5626,35 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
}
}
-
-
-bool handle_special_notification_callback(const LLSD& notification, const LLSD& response)
+bool handle_prompt_for_maturity_level_change_callback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
// set the preference to the maturity of the region we're calling
- int preferredMaturity = notification["payload"]["_region_access"].asInteger();
- gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
- gAgent.sendMaturityPreferenceToServer(preferredMaturity);
+ U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger());
+ gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity));
+ }
+
+ return false;
+}
- // notify user that the maturity preference has been changed
- LLSD args;
- args["RATING"] = LLViewerRegion::accessToString(preferredMaturity);
- LLNotificationsUtil::add("PreferredMaturityChanged", args);
+bool handle_prompt_for_maturity_level_change_and_reteleport_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (0 == option)
+ {
+ // set the preference to the maturity of the region we're calling
+ U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger());
+ gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity));
+ gAgent.setMaturityRatingChangeDuringTeleport(preferredMaturity);
+ gAgent.restartFailedTeleportRequest();
+ }
+ else
+ {
+ gAgent.clearTeleportRequest();
}
return false;
@@ -5408,39 +5663,148 @@ bool handle_special_notification_callback(const LLSD& notification, const LLSD&
// some of the server notifications need special handling. This is where we do that.
bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
{
- int regionAccess = llsdBlock["_region_access"].asInteger();
- llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess);
+ U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
+ std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
+ LLStringUtil::toLower(regionMaturity);
+ llsdBlock["REGIONMATURITY"] = regionMaturity;
- // we're going to throw the LLSD in there in case anyone ever wants to use it
- LLNotificationsUtil::add(notificationID+"_Notify", llsdBlock);
+ bool returnValue = false;
+ LLNotificationPtr maturityLevelNotification;
+ std::string notifySuffix = "_Notify";
+ if (regionAccess == SIM_ACCESS_MATURE)
+ {
+ if (gAgent.isTeen())
+ {
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
+ returnValue = true;
+
+ notifySuffix = "_NotifyAdultsOnly";
+ }
+ else if (gAgent.prefersPG())
+ {
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
+ returnValue = true;
+ }
+ else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
+ {
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
+ returnValue = true;
+ }
+ }
+ else if (regionAccess == SIM_ACCESS_ADULT)
+ {
+ if (!gAgent.isAdult())
+ {
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
+ returnValue = true;
+
+ notifySuffix = "_NotifyAdultsOnly";
+ }
+ else if (gAgent.prefersPG() || gAgent.prefersMature())
+ {
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
+ returnValue = true;
+ }
+ else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
+ {
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
+ returnValue = true;
+ }
+ }
+
+ if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored())
+ {
+ // Given a simple notification if no maturityLevelNotification is set or it is ignore
+ LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
+ }
+
+ return returnValue;
+}
+
+// some of the server notifications need special handling. This is where we do that.
+bool handle_teleport_access_blocked(LLSD& llsdBlock)
+{
+ std::string notificationID("TeleportEntryAccessBlocked");
+ U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
+ std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
+ LLStringUtil::toLower(regionMaturity);
+ llsdBlock["REGIONMATURITY"] = regionMaturity;
+ bool returnValue = false;
+ LLNotificationPtr maturityLevelNotification;
+ std::string notifySuffix = "_Notify";
if (regionAccess == SIM_ACCESS_MATURE)
{
if (gAgent.isTeen())
{
- LLNotificationsUtil::add(notificationID+"_KB", llsdBlock);
- return true;
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
+ returnValue = true;
+
+ notifySuffix = "_NotifyAdultsOnly";
}
else if (gAgent.prefersPG())
{
- LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
- return true;
+ if (gAgent.hasRestartableFailedTeleportRequest())
+ {
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
+ returnValue = true;
+ }
+ else
+ {
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
+ returnValue = true;
+ }
+ }
+ else
+ {
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
+ returnValue = true;
}
}
else if (regionAccess == SIM_ACCESS_ADULT)
{
if (!gAgent.isAdult())
{
- LLNotificationsUtil::add(notificationID+"_KB", llsdBlock);
- return true;
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
+ returnValue = true;
+
+ notifySuffix = "_NotifyAdultsOnly";
}
else if (gAgent.prefersPG() || gAgent.prefersMature())
{
- LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
- return true;
+ if (gAgent.hasRestartableFailedTeleportRequest())
+ {
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
+ returnValue = true;
+ }
+ else
+ {
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
+ returnValue = true;
+ }
+ }
+ else
+ {
+ gAgent.clearTeleportRequest();
+ maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
+ returnValue = true;
}
}
- return false;
+
+ if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored())
+ {
+ // Given a simple notification if no maturityLevelNotification is set or it is ignore
+ LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
+ }
+
+ return returnValue;
}
bool attempt_standard_notification(LLMessageSystem* msgsystem)
@@ -5484,16 +5848,20 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
RegionEntryAccessBlocked
RegionEntryAccessBlocked_Notify
+ RegionEntryAccessBlocked_NotifyAdultsOnly
RegionEntryAccessBlocked_Change
- RegionEntryAccessBlocked_KB
+ RegionEntryAccessBlocked_AdultsOnlyContent
+ RegionEntryAccessBlocked_ChangeAndReTeleport
LandClaimAccessBlocked
LandClaimAccessBlocked_Notify
+ LandClaimAccessBlocked_NotifyAdultsOnly
LandClaimAccessBlocked_Change
- LandClaimAccessBlocked_KB
+ LandClaimAccessBlocked_AdultsOnlyContent
LandBuyAccessBlocked
LandBuyAccessBlocked_Notify
+ LandBuyAccessBlocked_NotifyAdultsOnly
LandBuyAccessBlocked_Change
- LandBuyAccessBlocked_KB
+ LandBuyAccessBlocked_AdultsOnlyContent
-----------------------------------------------------------------------*/
if (handle_special_notification(notificationID, llsdBlock))
@@ -5545,6 +5913,30 @@ void process_alert_message(LLMessageSystem *msgsystem, void **user_data)
}
}
+bool handle_not_age_verified_alert(const std::string &pAlertName)
+{
+ LLNotificationPtr notification = LLNotificationsUtil::add(pAlertName);
+ if ((notification == NULL) || notification->isIgnored())
+ {
+ LLNotificationsUtil::add(pAlertName + "_Notify");
+ }
+
+ return true;
+}
+
+bool handle_special_alerts(const std::string &pAlertName)
+{
+ bool isHandled = false;
+
+ if (LLStringUtil::compareStrings(pAlertName, "NotAgeVerified") == 0)
+ {
+
+ isHandled = handle_not_age_verified_alert(pAlertName);
+ }
+
+ return isHandled;
+}
+
void process_alert_core(const std::string& message, BOOL modal)
{
// HACK -- handle callbacks for specific alerts. It also is localized in notifications.xml
@@ -5568,7 +5960,10 @@ void process_alert_core(const std::string& message, BOOL modal)
// Allow the server to spawn a named alert so that server alerts can be
// translated out of English.
std::string alert_name(message.substr(ALERT_PREFIX.length()));
- LLNotificationsUtil::add(alert_name);
+ if (!handle_special_alerts(alert_name))
+ {
+ LLNotificationsUtil::add(alert_name);
+ }
}
else if (message.find(NOTIFY_PREFIX) == 0)
{
@@ -5834,6 +6229,16 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
S32 orig = notification["payload"]["questions"].asInteger();
S32 new_questions = orig;
+ if (response["Details"])
+ {
+ // respawn notification...
+ LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]);
+
+ // ...with description on top
+ LLNotificationsUtil::add("DebitPermissionDetails");
+ return false;
+ }
+
// check whether permissions were granted or denied
BOOL allowed = TRUE;
// the "yes/accept" button is the first button in the template, making it button 0
@@ -5891,14 +6296,6 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(item_id));
}
- if (response["Details"])
- {
- // respawn notification...
- LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]);
-
- // ...with description on top
- LLNotificationsUtil::add("DebitPermissionDetails");
- }
return false;
}
static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb);
@@ -5968,16 +6365,21 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
args["OBJECTNAME"] = object_name;
args["NAME"] = LLCacheName::cleanFullName(owner_name);
+ BOOL has_not_only_debit = questions ^ LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_DEBIT];
// check the received permission flags against each permission
for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
{
if (questions & LSCRIPTRunTimePermissionBits[i])
{
count++;
- script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n";
// check whether permission question should cause special caution dialog
caution |= (SCRIPT_QUESTION_IS_CAUTION[i]);
+
+ if (("ScriptTakeMoney" == SCRIPT_QUESTIONS[i]) && has_not_only_debit)
+ continue;
+
+ script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n";
}
}
args["QUESTIONS"] = script_question;
@@ -5993,6 +6395,10 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
// check whether cautions are even enabled or not
if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
{
+ if (caution)
+ {
+ args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : "";
+ }
// display the caution permissions prompt
LLNotificationsUtil::add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload);
}
@@ -6143,6 +6549,9 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
std::string big_reason;
LLSD args;
+ // Let the interested parties know that teleport failed.
+ LLViewerParcelMgr::getInstance()->onTeleportFailed();
+
// if we have additional alert data
if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0)
{
@@ -6172,7 +6581,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
else
{
// change notification name in this special case
- if (handle_special_notification("RegionEntryAccessBlocked", llsd_block))
+ if (handle_teleport_access_blocked(llsd_block))
{
if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
{
@@ -6201,9 +6610,6 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
LLNotificationsUtil::add("CouldNotTeleportReason", args);
- // Let the interested parties know that teleport failed.
- LLViewerParcelMgr::getInstance()->onTeleportFailed();
-
if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
{
gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
@@ -6514,7 +6920,7 @@ void process_user_info_reply(LLMessageSystem* msg, void**)
msg->getString( "UserData", "DirectoryVisibility", dir_visibility);
LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email);
- LLFloaterPostcard::updateUserInfo(email);
+ LLFloaterSnapshot::setAgentEmail(email);
}
@@ -6546,8 +6952,24 @@ bool callback_script_dialog(const LLSD& notification, const LLSD& response)
rtn_text = LLNotification::getSelectedOptionName(response);
}
- // Didn't click "Ignore"
- if (button_idx != -1)
+ // Button -2 = Mute
+ // Button -1 = Ignore - no processing needed for this button
+ // Buttons 0 and above = dialog choices
+
+ if (-2 == button_idx)
+ {
+ std::string object_name = notification["payload"]["object_name"].asString();
+ LLUUID object_id = notification["payload"]["object_id"].asUUID();
+ LLMute mute(object_id, object_name, LLMute::OBJECT);
+ if (LLMuteList::getInstance()->add(mute))
+ {
+ // This call opens the sidebar, displays the block list, and highlights the newly blocked
+ // object in the list so the user can see that their block click has taken effect.
+ LLPanelBlockedList::showPanelAndSelect(object_id);
+ }
+ }
+
+ if (0 <= button_idx)
{
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("ScriptDialogReply");
@@ -6590,12 +7012,12 @@ void process_script_dialog(LLMessageSystem* msg, void**)
std::string message;
std::string first_name;
std::string last_name;
- std::string title;
+ std::string object_name;
S32 chat_channel;
msg->getString("Data", "FirstName", first_name);
msg->getString("Data", "LastName", last_name);
- msg->getString("Data", "ObjectName", title);
+ msg->getString("Data", "ObjectName", object_name);
msg->getString("Data", "Message", message);
msg->getS32("Data", "ChatChannel", chat_channel);
@@ -6606,6 +7028,7 @@ void process_script_dialog(LLMessageSystem* msg, void**)
payload["sender"] = msg->getSender().getIPandPort();
payload["object_id"] = object_id;
payload["chat_channel"] = chat_channel;
+ payload["object_name"] = object_name;
// build up custom form
S32 button_count = msg->getNumberOfBlocks("Buttons");
@@ -6624,7 +7047,7 @@ void process_script_dialog(LLMessageSystem* msg, void**)
}
LLSD args;
- args["TITLE"] = title;
+ args["TITLE"] = object_name;
args["MESSAGE"] = message;
LLNotificationPtr notification;
if (!first_name.empty())
@@ -6824,15 +7247,17 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelEstateCovenant::updateEstateName(estate_name);
LLPanelLandCovenant::updateEstateName(estate_name);
+ LLPanelEstateInfo::updateEstateName(estate_name);
LLFloaterBuyLand::updateEstateName(estate_name);
std::string owner_name =
LLSLURL("agent", estate_owner_id, "inspect").getSLURLString();
LLPanelEstateCovenant::updateEstateOwnerName(owner_name);
LLPanelLandCovenant::updateEstateOwnerName(owner_name);
+ LLPanelEstateInfo::updateEstateOwnerName(owner_name);
LLFloaterBuyLand::updateEstateOwnerName(owner_name);
- LLPanelPlaceProfile* panel = LLSideTray::getInstance()->getPanel<LLPanelPlaceProfile>("panel_place_profile");
+ LLPanelPlaceProfile* panel = LLFloaterSidePanelContainer::getPanel<LLPanelPlaceProfile>("places", "panel_place_profile");
if (panel)
{
panel->updateEstateName(estate_name);
@@ -6966,7 +7391,7 @@ void onCovenantLoadComplete(LLVFS *vfs,
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
- LLPanelPlaceProfile* panel = LLSideTray::getInstance()->getPanel<LLPanelPlaceProfile>("panel_place_profile");
+ LLPanelPlaceProfile* panel = LLFloaterSidePanelContainer::getPanel<LLPanelPlaceProfile>("places", "panel_place_profile");
if (panel)
{
panel->updateCovenantText(covenant_text);