/indra/newview/llviewermessage.cpp
C++ | 2181 lines | 1546 code | 231 blank | 404 comment | 190 complexity | 8f1f020fd1913110055cba2576d7da61 MD5 | raw file
Possible License(s): LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /**
- * @file llviewermessage.cpp
- * @brief Dumping ground for viewer-side message system callbacks.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llviewermessage.h"
- #include "boost/lexical_cast.hpp"
- // Linden libraries
- #include "llanimationstates.h"
- #include "llaudioengine.h"
- #include "llavataractions.h"
- #include "llavatarnamecache.h" // IDEVO HACK
- #include "lscript_byteformat.h"
- #include "lleconomy.h"
- #include "lleventtimer.h"
- #include "llfloaterreg.h"
- #include "llfolderview.h"
- #include "llfollowcamparams.h"
- #include "llinventorydefines.h"
- #include "lllslconstants.h"
- #include "llregionhandle.h"
- #include "llsdserialize.h"
- #include "llteleportflags.h"
- #include "lltransactionflags.h"
- #include "llvfile.h"
- #include "llvfs.h"
- #include "llxfermanager.h"
- #include "mean_collision_data.h"
- #include "llagent.h"
- #include "llagentcamera.h"
- #include "llcallingcard.h"
- #include "llbuycurrencyhtml.h"
- #include "llfirstuse.h"
- #include "llfloaterbuyland.h"
- #include "llfloaterland.h"
- #include "llfloaterregioninfo.h"
- #include "llfloaterlandholdings.h"
- #include "llfloaterpreference.h"
- #include "llfloatersidepanelcontainer.h"
- #include "llfloatersnapshot.h"
- #include "llhudeffecttrail.h"
- #include "llhudmanager.h"
- #include "llinventoryfunctions.h"
- #include "llinventoryobserver.h"
- #include "llinventorypanel.h"
- #include "llnearbychat.h"
- #include "llnotifications.h"
- #include "llnotificationsutil.h"
- #include "llpanelgrouplandmoney.h"
- #include "llrecentpeople.h"
- #include "llscriptfloater.h"
- #include "llselectmgr.h"
- #include "llstartup.h"
- #include "llsky.h"
- #include "llslurl.h"
- #include "llstatenums.h"
- #include "llstatusbar.h"
- #include "llimview.h"
- #include "llspeakers.h"
- #include "lltrans.h"
- #include "lltranslate.h"
- #include "llviewerfoldertype.h"
- #include "llvoavatar.h" // IDEVO HACK
- #include "lluri.h"
- #include "llviewergenericmessage.h"
- #include "llviewermenu.h"
- #include "llviewerinventory.h"
- #include "llviewerjoystick.h"
- #include "llviewerobjectlist.h"
- #include "llviewerparcelmgr.h"
- #include "llviewerstats.h"
- #include "llviewertexteditor.h"
- #include "llviewerthrottle.h"
- #include "llviewerwindow.h"
- #include "llvlmanager.h"
- #include "llvoavatarself.h"
- #include "llworld.h"
- #include "pipeline.h"
- #include "llfloaterworldmap.h"
- #include "llviewerdisplay.h"
- #include "llkeythrottle.h"
- #include "llgroupactions.h"
- #include "llagentui.h"
- #include "llpanelblockedlist.h"
- #include "llpanelplaceprofile.h"
- #include <boost/algorithm/string/split.hpp> //
- #include <boost/regex.hpp>
- #include "llnotificationmanager.h" //
- #if LL_MSVC
- // disable boost::lexical_cast warning
- #pragma warning (disable:4702)
- #endif
- //
- // Constants
- //
- const F32 BIRD_AUDIBLE_RADIUS = 32.0f;
- const F32 SIT_DISTANCE_FROM_TARGET = 0.25f;
- const F32 CAMERA_POSITION_THRESHOLD_SQUARED = 0.001f * 0.001f;
- static const F32 LOGOUT_REPLY_TIME = 3.f; // Wait this long after LogoutReply before quitting.
- // Determine how quickly residents' scripts can issue question dialogs
- // Allow bursts of up to 5 dialogs in 10 seconds. 10*2=20 seconds recovery if throttle kicks in
- static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests
- static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds
- extern BOOL gDebugClicks;
- // function prototypes
- bool check_offer_throttle(const std::string& from_name, bool check_only);
- static void process_money_balance_reply_extended(LLMessageSystem* msg);
- //inventory offer throttle globals
- LLFrameTimer gThrottleTimer;
- const U32 OFFER_THROTTLE_MAX_COUNT=5; //number of items per time period
- const F32 OFFER_THROTTLE_TIME=10.f; //time period in seconds
- //script permissions
- const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] =
- {
- "ScriptTakeMoney",
- "ActOnControlInputs",
- "RemapControlInputs",
- "AnimateYourAvatar",
- "AttachToYourAvatar",
- "ReleaseOwnership",
- "LinkAndDelink",
- "AddAndRemoveJoints",
- "ChangePermissions",
- "TrackYourCamera",
- "ControlYourCamera"
- };
- const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =
- {
- TRUE, // ScriptTakeMoney,
- FALSE, // ActOnControlInputs
- FALSE, // RemapControlInputs
- FALSE, // AnimateYourAvatar
- FALSE, // AttachToYourAvatar
- FALSE, // ReleaseOwnership,
- FALSE, // LinkAndDelink,
- FALSE, // AddAndRemoveJoints
- FALSE, // ChangePermissions
- FALSE, // TrackYourCamera,
- FALSE // ControlYourCamera
- };
- bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
- {
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- LLMessageSystem* msg = gMessageSystem;
- const LLSD& payload = notification["payload"];
- // add friend to recent people list
- LLRecentPeople::instance().add(payload["from_id"]);
- switch(option)
- {
- case 0:
- {
- // accept
- LLAvatarTracker::formFriendship(payload["from_id"]);
- const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
- // This will also trigger an onlinenotification if the user is online
- msg->newMessageFast(_PREHASH_AcceptFriendship);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]);
- msg->nextBlockFast(_PREHASH_FolderData);
- msg->addUUIDFast(_PREHASH_FolderID, fid);
- msg->sendReliable(LLHost(payload["sender"].asString()));
- LLSD payload = notification["payload"];
- payload["SUPPRESS_TOAST"] = true;
- LLNotificationsUtil::add("FriendshipAcceptedByMe",
- notification["substitutions"], payload);
- break;
- }
- case 1: // Decline
- {
- LLSD payload = notification["payload"];
- payload["SUPPRESS_TOAST"] = true;
- LLNotificationsUtil::add("FriendshipDeclinedByMe",
- notification["substitutions"], payload);
- }
- // fall-through
- case 2: // Send IM - decline and start IM session
- {
- // decline
- // We no longer notify other viewers, but we DO still send
- // the rejection to the simulator to delete the pending userop.
- msg->newMessageFast(_PREHASH_DeclineFriendship);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]);
- msg->sendReliable(LLHost(payload["sender"].asString()));
- // start IM session
- if(2 == option)
- {
- LLAvatarActions::startIM(payload["from_id"].asUUID());
- }
- }
- default:
- // close button probably, possibly timed out
- break;
- }
- return false;
- }
- static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback);
- static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("OfferFriendshipNoMessage", friendship_offer_callback);
- //const char BUSY_AUTO_RESPONSE[] = "The Resident you messaged is in 'busy mode' which means they have "
- // "requested not to be disturbed. Your message will still be shown in their IM "
- // "panel for later viewing.";
- //
- // Functions
- //
- void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group,
- S32 trx_type, const std::string& desc)
- {
- if(0 == amount || !region) return;
- amount = abs(amount);
- LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")"<< LL_ENDL;
- if(can_afford_transaction(amount))
- {
- // gStatusBar->debitBalance(amount);
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_MoneyTransferRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_MoneyData);
- msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_DestID, uuid);
- msg->addU8Fast(_PREHASH_Flags, pack_transaction_flags(FALSE, is_group));
- msg->addS32Fast(_PREHASH_Amount, amount);
- msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY);
- msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY);
- msg->addS32Fast(_PREHASH_TransactionType, trx_type );
- msg->addStringFast(_PREHASH_Description, desc);
- msg->sendReliable(region->getHost());
- }
- else
- {
- LLStringUtil::format_map_t args;
- args["AMOUNT"] = llformat("%d", amount);
- LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("giving", args), amount );
- }
- }
- void send_complete_agent_movement(const LLHost& sim_host)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_CompleteAgentMovement);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addU32Fast(_PREHASH_CircuitCode, msg->mOurCircuitCode);
- msg->sendReliable(sim_host);
- }
- void process_logout_reply(LLMessageSystem* msg, void**)
- {
- // The server has told us it's ok to quit.
- LL_DEBUGS("Messaging") << "process_logout_reply" << LL_ENDL;
- LLUUID agent_id;
- msg->getUUID("AgentData", "AgentID", agent_id);
- LLUUID session_id;
- msg->getUUID("AgentData", "SessionID", session_id);
- if((agent_id != gAgent.getID()) || (session_id != gAgent.getSessionID()))
- {
- LL_WARNS("Messaging") << "Bogus Logout Reply" << LL_ENDL;
- }
- LLInventoryModel::update_map_t parents;
- S32 count = msg->getNumberOfBlocksFast( _PREHASH_InventoryData );
- for(S32 i = 0; i < count; ++i)
- {
- LLUUID item_id;
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i);
- if( (1 == count) && item_id.isNull() )
- {
- // Detect dummy item. Indicates an empty list.
- break;
- }
- // We do not need to track the asset ids, just account for an
- // updated inventory version.
- LL_INFOS("Messaging") << "process_logout_reply itemID=" << item_id << LL_ENDL;
- LLInventoryItem* item = gInventory.getItem( item_id );
- if( item )
- {
- parents[item->getParentUUID()] = 0;
- gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id);
- }
- else
- {
- LL_INFOS("Messaging") << "process_logout_reply item not found: " << item_id << LL_ENDL;
- }
- }
- LLAppViewer::instance()->forceQuit();
- }
- void process_layer_data(LLMessageSystem *mesgsys, void **user_data)
- {
- LLViewerRegion *regionp = LLWorld::getInstance()->getRegion(mesgsys->getSender());
- if(!regionp)
- {
- llwarns << "Invalid region for layer data." << llendl;
- return;
- }
- S32 size;
- S8 type;
- mesgsys->getS8Fast(_PREHASH_LayerID, _PREHASH_Type, type);
- size = mesgsys->getSizeFast(_PREHASH_LayerData, _PREHASH_Data);
- if (0 == size)
- {
- LL_WARNS("Messaging") << "Layer data has zero size." << LL_ENDL;
- return;
- }
- if (size < 0)
- {
- // getSizeFast() is probably trying to tell us about an error
- LL_WARNS("Messaging") << "getSizeFast() returned negative result: "
- << size
- << LL_ENDL;
- return;
- }
- U8 *datap = new U8[size];
- mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size);
- LLVLData *vl_datap = new LLVLData(regionp, type, datap, size);
- if (mesgsys->getReceiveCompressedSize())
- {
- gVLManager.addLayerData(vl_datap, mesgsys->getReceiveCompressedSize());
- }
- else
- {
- gVLManager.addLayerData(vl_datap, mesgsys->getReceiveSize());
- }
- }
- // S32 exported_object_count = 0;
- // S32 exported_image_count = 0;
- // S32 current_object_count = 0;
- // S32 current_image_count = 0;
- // extern LLNotifyBox *gExporterNotify;
- // extern LLUUID gExporterRequestID;
- // extern std::string gExportDirectory;
- // extern LLUploadDialog *gExportDialog;
- // std::string gExportedFile;
- // std::map<LLUUID, std::string> gImageChecksums;
- // void export_complete()
- // {
- // LLUploadDialog::modalUploadFinished();
- // gExporterRequestID.setNull();
- // gExportDirectory = "";
- // LLFILE* fXML = LLFile::fopen(gExportedFile, "rb"); /* Flawfinder: ignore */
- // fseek(fXML, 0, SEEK_END);
- // long length = ftell(fXML);
- // fseek(fXML, 0, SEEK_SET);
- // U8 *buffer = new U8[length + 1];
- // size_t nread = fread(buffer, 1, length, fXML);
- // if (nread < (size_t) length)
- // {
- // LL_WARNS("Messaging") << "Short read" << LL_ENDL;
- // }
- // buffer[nread] = '\0';
- // fclose(fXML);
- // char *pos = (char *)buffer;
- // while ((pos = strstr(pos+1, "<sl:image ")) != 0)
- // {
- // char *pos_check = strstr(pos, "checksum=\"");
- // if (pos_check)
- // {
- // char *pos_uuid = strstr(pos_check, "\">");
- // if (pos_uuid)
- // {
- // char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */
- // memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */
- // image_uuid_str[UUID_STR_SIZE-1] = 0;
-
- // LLUUID image_uuid(image_uuid_str);
- // LL_INFOS("Messaging") << "Found UUID: " << image_uuid << LL_ENDL;
- // std::map<LLUUID, std::string>::iterator itor = gImageChecksums.find(image_uuid);
- // if (itor != gImageChecksums.end())
- // {
- // LL_INFOS("Messaging") << "Replacing with checksum: " << itor->second << LL_ENDL;
- // if (!itor->second.empty())
- // {
- // memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */
- // }
- // }
- // }
- // }
- // }
- // LLFILE* fXMLOut = LLFile::fopen(gExportedFile, "wb"); /* Flawfinder: ignore */
- // if (fwrite(buffer, 1, length, fXMLOut) != length)
- // {
- // LL_WARNS("Messaging") << "Short write" << LL_ENDL;
- // }
- // fclose(fXMLOut);
- // delete [] buffer;
- // }
- // void exported_item_complete(const LLTSCode status, void *user_data)
- // {
- // //std::string *filename = (std::string *)user_data;
- // if (status < LLTS_OK)
- // {
- // LL_WARNS("Messaging") << "Export failed!" << LL_ENDL;
- // }
- // else
- // {
- // ++current_object_count;
- // if (current_image_count == exported_image_count && current_object_count == exported_object_count)
- // {
- // LL_INFOS("Messaging") << "*** Export complete ***" << LL_ENDL;
- // export_complete();
- // }
- // else
- // {
- // gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count));
- // }
- // }
- // }
- // struct exported_image_info
- // {
- // LLUUID image_id;
- // std::string filename;
- // U32 image_num;
- // };
- // void exported_j2c_complete(const LLTSCode status, void *user_data)
- // {
- // exported_image_info *info = (exported_image_info *)user_data;
- // LLUUID image_id = info->image_id;
- // U32 image_num = info->image_num;
- // std::string filename = info->filename;
- // delete info;
- // if (status < LLTS_OK)
- // {
- // LL_WARNS("Messaging") << "Image download failed!" << LL_ENDL;
- // }
- // else
- // {
- // LLFILE* fIn = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
- // if (fIn)
- // {
- // LLPointer<LLImageJ2C> ImageUtility = new LLImageJ2C;
- // LLPointer<LLImageTGA> TargaUtility = new LLImageTGA;
- // fseek(fIn, 0, SEEK_END);
- // S32 length = ftell(fIn);
- // fseek(fIn, 0, SEEK_SET);
- // U8 *buffer = ImageUtility->allocateData(length);
- // if (fread(buffer, 1, length, fIn) != length)
- // {
- // LL_WARNS("Messaging") << "Short read" << LL_ENDL;
- // }
- // fclose(fIn);
- // LLFile::remove(filename);
- // // Convert to TGA
- // LLPointer<LLImageRaw> image = new LLImageRaw();
- // ImageUtility->updateData();
- // ImageUtility->decode(image, 100000.0f);
-
- // TargaUtility->encode(image);
- // U8 *data = TargaUtility->getData();
- // S32 data_size = TargaUtility->getDataSize();
- // std::string file_path = gDirUtilp->getDirName(filename);
-
- // std::string output_file = llformat("%s/image-%03d.tga", file_path.c_str(), image_num);//filename;
- // //S32 name_len = output_file.length();
- // //strcpy(&output_file[name_len-3], "tga");
- // LLFILE* fOut = LLFile::fopen(output_file, "wb"); /* Flawfinder: ignore */
- // char md5_hash_string[33]; /* Flawfinder: ignore */
- // strcpy(md5_hash_string, "00000000000000000000000000000000"); /* Flawfinder: ignore */
- // if (fOut)
- // {
- // if (fwrite(data, 1, data_size, fOut) != data_size)
- // {
- // LL_WARNS("Messaging") << "Short write" << LL_ENDL;
- // }
- // fseek(fOut, 0, SEEK_SET);
- // fclose(fOut);
- // fOut = LLFile::fopen(output_file, "rb"); /* Flawfinder: ignore */
- // LLMD5 my_md5_hash(fOut);
- // my_md5_hash.hex_digest(md5_hash_string);
- // }
- // gImageChecksums.insert(std::pair<LLUUID, std::string>(image_id, md5_hash_string));
- // }
- // }
- // ++current_image_count;
- // if (current_image_count == exported_image_count && current_object_count == exported_object_count)
- // {
- // LL_INFOS("Messaging") << "*** Export textures complete ***" << LL_ENDL;
- // export_complete();
- // }
- // else
- // {
- // gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count));
- // }
- //}
- void process_derez_ack(LLMessageSystem*, void**)
- {
- if(gViewerWindow) gViewerWindow->getWindow()->decBusyCount();
- }
- void process_places_reply(LLMessageSystem* msg, void** data)
- {
- LLUUID query_id;
- msg->getUUID("AgentData", "QueryID", query_id);
- if (query_id.isNull())
- {
- LLFloaterLandHoldings::processPlacesReply(msg, data);
- }
- else if(gAgent.isInGroup(query_id))
- {
- LLPanelGroupLandMoney::processPlacesReply(msg, data);
- }
- else
- {
- LL_WARNS("Messaging") << "Got invalid PlacesReply message" << LL_ENDL;
- }
- }
- void send_sound_trigger(const LLUUID& sound_id, F32 gain)
- {
- if (sound_id.isNull() || gAgent.getRegion() == NULL)
- {
- // disconnected agent or zero guids don't get sent (no sound)
- return;
- }
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_SoundTrigger);
- msg->nextBlockFast(_PREHASH_SoundData);
- msg->addUUIDFast(_PREHASH_SoundID, sound_id);
- // Client untrusted, ids set on sim
- msg->addUUIDFast(_PREHASH_OwnerID, LLUUID::null );
- msg->addUUIDFast(_PREHASH_ObjectID, LLUUID::null );
- msg->addUUIDFast(_PREHASH_ParentID, LLUUID::null );
- msg->addU64Fast(_PREHASH_Handle, gAgent.getRegion()->getHandle());
- LLVector3 position = gAgent.getPositionAgent();
- msg->addVector3Fast(_PREHASH_Position, position);
- msg->addF32Fast(_PREHASH_Gain, gain);
- gAgent.sendMessage();
- }
- bool join_group_response(const LLSD& notification, const LLSD& response)
- {
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- BOOL delete_context_data = TRUE;
- bool accept_invite = false;
- LLUUID group_id = notification["payload"]["group_id"].asUUID();
- LLUUID transaction_id = notification["payload"]["transaction_id"].asUUID();
- std::string name = notification["payload"]["name"].asString();
- std::string message = notification["payload"]["message"].asString();
- S32 fee = notification["payload"]["fee"].asInteger();
- if (option == 2 && !group_id.isNull())
- {
- LLGroupActions::show(group_id);
- LLSD args;
- args["MESSAGE"] = message;
- LLNotificationsUtil::add("JoinGroup", args, notification["payload"]);
- return false;
- }
- if(option == 0 && !group_id.isNull())
- {
- // check for promotion or demotion.
- S32 max_groups = gMaxAgentGroups;
- if(gAgent.isInGroup(group_id)) ++max_groups;
- if(gAgent.mGroups.count() < max_groups)
- {
- accept_invite = true;
- }
- else
- {
- delete_context_data = FALSE;
- LLSD args;
- args["NAME"] = name;
- LLNotificationsUtil::add("JoinedTooManyGroupsMember", args, notification["payload"]);
- }
- }
- if (accept_invite)
- {
- // If there is a fee to join this group, make
- // sure the user is sure they want to join.
- if (fee > 0)
- {
- delete_context_data = FALSE;
- LLSD args;
- args["COST"] = llformat("%d", fee);
- // Set the fee for next time to 0, so that we don't keep
- // asking about a fee.
- LLSD next_payload = notification["payload"];
- next_payload["fee"] = 0;
- LLNotificationsUtil::add("JoinGroupCanAfford",
- args,
- next_payload);
- }
- else
- {
- send_improved_im(group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_ACCEPT,
- transaction_id);
- }
- }
- else
- {
- send_improved_im(group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_DECLINE,
- transaction_id);
- }
- return false;
- }
- static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
- {
- if (NULL == inventory_panel) return;
- for (std::vector<LLUUID>::const_iterator item_iter = items.begin();
- item_iter != items.end();
- ++item_iter)
- {
- const LLUUID& item_id = (*item_iter);
- if(!highlight_offered_object(item_id))
- {
- continue;
- }
- LLInventoryObject* item = gInventory.getObject(item_id);
- llassert(item);
- if (!item) {
- continue;
- }
- LL_DEBUGS("Inventory_Move") << "Highlighting inventory item: " << item->getName() << ", " << item_id << LL_ENDL;
- LLFolderView* fv = inventory_panel->getRootFolder();
- if (fv)
- {
- LLFolderViewItem* fv_item = fv->getItemByID(item_id);
- if (fv_item)
- {
- LLFolderViewItem* fv_folder = fv_item->getParentFolder();
- if (fv_folder)
- {
- // Parent folders can be different in case of 2 consecutive drag and drop
- // operations when the second one is started before the first one completes.
- LL_DEBUGS("Inventory_Move") << "Open folder: " << fv_folder->getName() << LL_ENDL;
- fv_folder->setOpen(TRUE);
- if (fv_folder->isSelected())
- {
- fv->changeSelection(fv_folder, FALSE);
- }
- }
- fv->changeSelection(fv_item, TRUE);
- }
- }
- }
- }
- static LLNotificationFunctorRegistration jgr_1("JoinGroup", join_group_response);
- static LLNotificationFunctorRegistration jgr_2("JoinedTooManyGroupsMember", join_group_response);
- static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_response);
- //-----------------------------------------------------------------------------
- // Instant Message
- //-----------------------------------------------------------------------------
- class LLOpenAgentOffer : public LLInventoryFetchItemsObserver
- {
- public:
- LLOpenAgentOffer(const LLUUID& object_id,
- const std::string& from_name) :
- LLInventoryFetchItemsObserver(object_id),
- mFromName(from_name) {}
- /*virtual*/ void startFetch()
- {
- for (uuid_vec_t::const_iterator it = mIDs.begin(); it < mIDs.end(); ++it)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if (cat)
- {
- mComplete.push_back((*it));
- }
- }
- LLInventoryFetchItemsObserver::startFetch();
- }
- /*virtual*/ void done()
- {
- open_inventory_offer(mComplete, mFromName);
- gInventory.removeObserver(this);
- delete this;
- }
- private:
- std::string mFromName;
- };
- /**
- * Class to observe adding of new items moved from the world to user's inventory to select them in inventory.
- *
- * We can't create it each time items are moved because "drop" event is sent separately for each
- * element even while multi-dragging. We have to have the only instance of the observer. See EXT-4347.
- */
- class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetObserver
- {
- public:
- LLViewerInventoryMoveFromWorldObserver()
- : LLInventoryAddItemByAssetObserver()
- {
- }
- void setMoveIntoFolderID(const LLUUID& into_folder_uuid) {mMoveIntoFolderID = into_folder_uuid; }
- private:
- /*virtual */void onAssetAdded(const LLUUID& asset_id)
- {
- // Store active Inventory panel.
- if (LLInventoryPanel::getActiveInventoryPanel())
- {
- mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
- }
- // Store selected items (without destination folder)
- mSelectedItems.clear();
- if (LLInventoryPanel::getActiveInventoryPanel())
- {
- mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList();
- }
- mSelectedItems.erase(mMoveIntoFolderID);
- }
- /**
- * Selects added inventory items watched by their Asset UUIDs if selection was not changed since
- * all items were started to watch (dropped into a folder).
- */
- void done()
- {
- LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
- // if selection is not changed since watch started lets hightlight new items.
- if (active_panel && !isSelectionChanged())
- {
- LL_DEBUGS("Inventory_Move") << "Selecting new items..." << LL_ENDL;
- active_panel->clearSelection();
- highlight_inventory_objects_in_panel(mAddedItems, active_panel);
- }
- }
- /**
- * Returns true if selected inventory items were changed since moved inventory items were started to watch.
- */
- bool isSelectionChanged()
- {
- LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
- if (NULL == active_panel)
- {
- return true;
- }
- // get selected items (without destination folder)
- selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList();
- selected_items.erase(mMoveIntoFolderID);
- // compare stored & current sets of selected items
- selected_items_t different_items;
- std::set_symmetric_difference(mSelectedItems.begin(), mSelectedItems.end(),
- selected_items.begin(), selected_items.end(), std::inserter(different_items, different_items.begin()));
- LL_DEBUGS("Inventory_Move") << "Selected firstly: " << mSelectedItems.size()
- << ", now: " << selected_items.size() << ", difference: " << different_items.size() << LL_ENDL;
- return different_items.size() > 0;
- }
- LLHandle<LLPanel> mActivePanel;
- typedef std::set<LLUUID> selected_items_t;
- selected_items_t mSelectedItems;
- /**
- * UUID of FolderViewFolder into which watched items are moved.
- *
- * Destination FolderViewFolder becomes selected while mouse hovering (when dragged items are dropped).
- *
- * If mouse is moved out it set unselected and number of selected items is changed
- * even if selected items in Inventory stay the same.
- * So, it is used to update stored selection list.
- *
- * @see onAssetAdded()
- * @see isSelectionChanged()
- */
- LLUUID mMoveIntoFolderID;
- };
- LLViewerInventoryMoveFromWorldObserver* gInventoryMoveObserver = NULL;
- void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid)
- {
- start_new_inventory_observer();
- gInventoryMoveObserver->setMoveIntoFolderID(into_folder_uuid);
- gInventoryMoveObserver->watchAsset(inv_item->getAssetUUID());
- }
- /**
- * Class to observe moving of items and to select them in inventory.
- *
- * Used currently for dragging from inbox to regular inventory folders
- */
- class LLViewerInventoryMoveObserver : public LLInventoryObserver
- {
- public:
- LLViewerInventoryMoveObserver(const LLUUID& object_id)
- : LLInventoryObserver()
- , mObjectID(object_id)
- {
- if (LLInventoryPanel::getActiveInventoryPanel())
- {
- mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
- }
- }
- virtual ~LLViewerInventoryMoveObserver() {}
- virtual void changed(U32 mask);
-
- private:
- LLUUID mObjectID;
- LLHandle<LLPanel> mActivePanel;
- };
- void LLViewerInventoryMoveObserver::changed(U32 mask)
- {
- LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
- if (NULL == active_panel)
- {
- gInventory.removeObserver(this);
- return;
- }
- if((mask & (LLInventoryObserver::STRUCTURE)) != 0)
- {
- const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
- std::set<LLUUID>::const_iterator id_it = changed_items.begin();
- std::set<LLUUID>::const_iterator id_end = changed_items.end();
- for (;id_it != id_end; ++id_it)
- {
- if ((*id_it) == mObjectID)
- {
- active_panel->clearSelection();
- std::vector<LLUUID> items;
- items.push_back(mObjectID);
- highlight_inventory_objects_in_panel(items, active_panel);
- active_panel->getRootFolder()->scrollToShowSelection();
-
- gInventory.removeObserver(this);
- break;
- }
- }
- }
- }
- void set_dad_inbox_object(const LLUUID& object_id)
- {
- LLViewerInventoryMoveObserver* move_observer = new LLViewerInventoryMoveObserver(object_id);
- gInventory.addObserver(move_observer);
- }
- //unlike the FetchObserver for AgentOffer, we only make one
- //instance of the AddedObserver for TaskOffers
- //and it never dies. We do this because we don't know the UUID of
- //task offers until they are accepted, so we don't wouldn't
- //know what to watch for, so instead we just watch for all additions.
- class LLOpenTaskOffer : public LLInventoryAddedObserver
- {
- protected:
- /*virtual*/ void done()
- {
- for (uuid_vec_t::iterator it = mAdded.begin(); it != mAdded.end();)
- {
- const LLUUID& item_uuid = *it;
- bool was_moved = false;
- LLInventoryObject* added_object = gInventory.getObject(item_uuid);
- if (added_object)
- {
- // cast to item to get Asset UUID
- LLInventoryItem* added_item = dynamic_cast<LLInventoryItem*>(added_object);
- if (added_item)
- {
- const LLUUID& asset_uuid = added_item->getAssetUUID();
- if (gInventoryMoveObserver->isAssetWatched(asset_uuid))
- {
- LL_DEBUGS("Inventory_Move") << "Found asset UUID: " << asset_uuid << LL_ENDL;
- was_moved = true;
- }
- }
- }
- if (was_moved)
- {
- it = mAdded.erase(it);
- }
- else ++it;
- }
- open_inventory_offer(mAdded, "");
- mAdded.clear();
- }
- };
- class LLOpenTaskGroupOffer : public LLInventoryAddedObserver
- {
- protected:
- /*virtual*/ void done()
- {
- open_inventory_offer(mAdded, "group_offer");
- mAdded.clear();
- gInventory.removeObserver(this);
- delete this;
- }
- };
- //one global instance to bind them
- LLOpenTaskOffer* gNewInventoryObserver=NULL;
- class LLNewInventoryHintObserver : public LLInventoryAddedObserver
- {
- protected:
- /*virtual*/ void done()
- {
- LLFirstUse::newInventory();
- }
- };
- LLNewInventoryHintObserver* gNewInventoryHintObserver=NULL;
- void start_new_inventory_observer()
- {
- if (!gNewInventoryObserver) //task offer observer
- {
- // Observer is deleted by gInventory
- gNewInventoryObserver = new LLOpenTaskOffer;
- gInventory.addObserver(gNewInventoryObserver);
- }
- if (!gInventoryMoveObserver) //inventory move from the world observer
- {
- // Observer is deleted by gInventory
- gInventoryMoveObserver = new LLViewerInventoryMoveFromWorldObserver;
- gInventory.addObserver(gInventoryMoveObserver);
- }
- if (!gNewInventoryHintObserver)
- {
- // Observer is deleted by gInventory
- gNewInventoryHintObserver = new LLNewInventoryHintObserver();
- gInventory.addObserver(gNewInventoryHintObserver);
- }
- }
- 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 void done()
- {
- LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << 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).
- LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID));
- gInventory.removeObserver(this);
- delete this;
- }
- protected:
- LLUUID mFolderID;
- LLUUID mObjectID;
- };
- //Returns TRUE if we are OK, FALSE if we are throttled
- //Set check_only true if you want to know the throttle status
- //without registering a hit
- bool check_offer_throttle(const std::string& from_name, bool check_only)
- {
- static U32 throttle_count;
- static bool throttle_logged;
- LLChat chat;
- std::string log_message;
- if (!gSavedSettings.getBOOL("ShowNewInventory"))
- return false;
- if (check_only)
- {
- return gThrottleTimer.hasExpired();
- }
-
- if(gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME))
- {
- LL_DEBUGS("Messaging") << "Throttle Expired" << LL_ENDL;
- throttle_count=1;
- throttle_logged=false;
- return true;
- }
- else //has not expired
- {
- LL_DEBUGS("Messaging") << "Throttle Not Expired, Count: " << throttle_count << LL_ENDL;
- // When downloading the initial inventory we get a lot of new items
- // coming in and can't tell that from spam.
- if (LLStartUp::getStartupState() >= STATE_STARTED
- && throttle_count >= OFFER_THROTTLE_MAX_COUNT)
- {
- if (!throttle_logged)
- {
- // Use the name of the last item giver, who is probably the person
- // spamming you.
- LLStringUtil::format_map_t arg;
- std::string log_msg;
- std::ostringstream time ;
- time<<OFFER_THROTTLE_TIME;
- arg["APP_NAME"] = LLAppViewer::instance()->getSecondLifeTitle();
- arg["TIME"] = time.str();
- if (!from_name.empty())
- {
- arg["FROM_NAME"] = from_name;
- log_msg = LLTrans::getString("ItemsComingInTooFastFrom", arg);
- }
- else
- {
- log_msg = LLTrans::getString("ItemsComingInTooFast", arg);
- }
-
- //this is kinda important, so actually put it on screen
- LLSD args;
- args["MESSAGE"] = log_msg;
- LLNotificationsUtil::add("SystemMessage", args);
- throttle_logged=true;
- }
- return false;
- }
- else
- {
- throttle_count++;
- return true;
- }
- }
- }
-
- void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name)
- {
- for (uuid_vec_t::const_iterator obj_iter = objects.begin();
- obj_iter != objects.end();
- ++obj_iter)
- {
- const LLUUID& obj_id = (*obj_iter);
- if(!highlight_offered_object(obj_id))
- {
- continue;
- }
- const LLInventoryObject *obj = gInventory.getObject(obj_id);
- if (!obj)
- {
- llwarns << "Cannot find object [ itemID:" << obj_id << " ] to open." << llendl;
- continue;
- }
- const LLAssetType::EType asset_type = obj->getActualType();
- // Either an inventory item or a category.
- const LLInventoryItem* item = dynamic_cast<const LLInventoryItem*>(obj);
- if (item)
- {
- ////////////////////////////////////////////////////////////////////////////////
- // Special handling for various types.
- if (check_offer_throttle(from_name, false)) // If we are throttled, don't display
- {
- LL_DEBUGS("Messaging") << "Highlighting inventory item: " << item->getUUID() << LL_ENDL;
- // If we opened this ourselves, focus it
- const BOOL take_focus = from_name.empty() ? TAKE_FOCUS_YES : TAKE_FOCUS_NO;
- switch(asset_type)
- {
- case LLAssetType::AT_NOTECARD:
- {
- LLFloaterReg::showInstance("preview_notecard", LLSD(obj_id), take_focus);
- break;
- }
- case LLAssetType::AT_LANDMARK:
- {
- LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID());
- if ("inventory_handler" == from_name)
- {
- LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "landmark").with("id", item->getUUID()));
- }
- else if("group_offer" == from_name)
- {
- // "group_offer" is passed by LLOpenTaskGroupOffer
- // Notification about added landmark will be generated under the "from_name.empty()" called from LLOpenTaskOffer::done().
- LLSD args;
- args["type"] = "landmark";
- args["id"] = obj_id;
- LLFloaterSidePanelContainer::showPanel("places", args);
- continue;
- }
- else if(from_name.empty())
- {
- std::string folder_name;
- if (parent_folder)
- {
- // Localize folder name.
- // *TODO: share this code?
- folder_name = parent_folder->getName();
- if (LLFolderType::lookupIsProtectedType(parent_folder->getPreferredType()))
- {
- LLTrans::findString(folder_name, "InvFolder " + folder_name);
- }
- }
- else
- {
- folder_name = LLTrans::getString("Unknown");
- }
- // we receive a message from LLOpenTaskOffer, it mean that new landmark has been added.
- LLSD args;
- args["LANDMARK_NAME"] = item->getName();
- args["FOLDER_NAME"] = folder_name;
- LLNotificationsUtil::add("LandmarkCreated", args);
- }
- }
- break;
- case LLAssetType::AT_TEXTURE:
- {
- LLFloaterReg::showInstance("preview_texture", LLSD(obj_id), take_focus);
- break;
- }
- case LLAssetType::AT_ANIMATION:
- LLFloaterReg::showInstance("preview_anim", LLSD(obj_id), take_focus);
- break;
- case LLAssetType::AT_SCRIPT:
- LLFloaterReg::showInstance("preview_script", LLSD(obj_id), take_focus);
- break;
- case LLAssetType::AT_SOUND:
- LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus);
- break;
- default:
- break;
- }
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- // Highlight item
- 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::openInventoryPanelAndSetSelection(auto_open, obj_id);
- }
- }
- bool highlight_offered_object(const LLUUID& obj_id)
- {
- const LLInventoryObject* obj = gInventory.getObject(obj_id);
- if(!obj)
- {
- LL_WARNS("Messaging") << "Unable to show inventory item: " << obj_id << LL_ENDL;
- return false;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // Don't highlight if it's in certain "quiet" folders which don't need UI
- // notification (e.g. trash, cof, lost-and-found).
- if(!gAgent.getAFK())
- {
- const LLViewerInventoryCategory *parent = gInventory.getFirstNondefaultParent(obj_id);
- if (parent)
- {
- const LLFolderType::EType parent_type = parent->getPreferredType();
- if (LLViewerFolderType::lookupIsQuietType(parent_type))
- {
- return false;
- }
- }
- }
- return true;
- }
- void inventory_offer_mute_callback(const LLUUID& blocked_id,
- const std::string& full_name,
- bool is_group)
- {
- // *NOTE: blocks owner if the offer came from an object
- LLMute::EType mute_type = is_group ? LLMute::GROUP : LLMute::AGENT;
- LLMute mute(blocked_id, full_name, mute_type);
- if (LLMuteList::getInstance()->add(mute))
- {
- LLPanelBlockedList::showPanelAndSelect(blocked_id);
- }
- // purge the message queue of any previously queued inventory offers from the same source.
- class OfferMatcher : public LLNotificationsUI::LLScreenChannel::Matcher
- {
- public:
- OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {}
- bool matches(const LLNotificationPtr notification) const
- {
- if(notification->getName() == "ObjectGiveItem"
- || notification->getName() == "OwnObjectGiveItem"
- || notification->getName() == "UserGiveItem")
- {
- return (notification->getPayload()["from_id"].asUUID() == blocked_id);
- }
- return FALSE;
- }
- private:
- const LLUUID& blocked_id;
- };
- LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID(
- gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id));
- }
- LLOfferInfo::LLOfferInfo()
- : LLNotificationResponderInterface()
- , mFromGroup(FALSE)
- , mFromObject(FALSE)
- , mIM(IM_NOTHING_SPECIAL)
- , mType(LLAssetType::AT_NONE)
- , mPersist(false)
- {
- }
- LLOfferInfo::LLOfferInfo(const LLSD& sd)
- {
- mIM = (EInstantMessage)sd["im_type"].asInteger();
- mFromID = sd["from_id"].asUUID();
- mFromGroup = sd["from_group"].asBoolean();
- mFromObject = sd["from_object"].asBoolean();
- mTransactionID = sd["transaction_id"].asUUID();
- mFolderID = sd["folder_id"].asUUID();
- mObjectID = sd["object_id"].asUUID();
- mType = LLAssetType::lookup(sd["type"].asString().c_str());
- mFromName = sd["from_name"].asString();
- mDesc = sd["description"].asString();
- mHost = LLHost(sd["sender"].asString());
- mPersist = sd["persist"].asBoolean();
- }
- LLOfferInfo::LLOfferInfo(const LLOfferInfo& info)
- {
- mIM = info.mIM;
- mFromID = info.mFromID;
- mFromGroup = info.mFromGroup;
- mFromObject = info.mFromObject;
- mTransactionID = info.mTransactionID;
- mFolderID = info.mFolderID;
- mObjectID = info.mObjectID;
- mType = info.mType;
- mFromName = info.mFromName;
- mDesc = info.mDesc;
- mHost = info.mHost;
- mPersist = info.mPersist;
- }
- LLSD LLOfferInfo::asLLSD()
- {
- LLSD sd;
- sd["im_type"] = mIM;
- sd["from_id"] = mFromID;
- sd["from_group"] = mFromGroup;
- sd["from_object"] = mFromObject;
- sd["transaction_id"] = mTransactionID;
- sd["folder_id"] = mFolderID;
- sd["object_id"] = mObjectID;
- sd["type"] = LLAssetType::lookup(mType);
- sd["from_name"] = mFromName;
- sd["description"] = mDesc;
- sd["sender"] = mHost.getIPandPort();
- sd["persist"] = mPersist;
- return sd;
- }
- void LLOfferInfo::fromLLSD(const LLSD& params)
- {
- *this = params;
- }
- void LLOfferInfo::send_auto_receive_response(void)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_MessageBlock);
- msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
- msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
- msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
- msg->addUUIDFast(_PREHASH_ID, mTransactionID);
- msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
- std::string name;
- LLAgentUI::buildFullname(name);
- msg->addStringFast(_PREHASH_FromAgentName, name);
- msg->addStringFast(_PREHASH_Message, "");
- msg->addU32Fast(_PREHASH_ParentEstateID, 0);
- msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
- msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
-
- // Auto Receive Message. The math for the dialog works, because the accept
- // for inventory_offered, task_inventory_offer or
- // group_notice_inventory is 1 greater than the offer integer value.
- // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
- // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
- sizeof(mFolderID.mData));
- // send the message
- msg->sendReliable(mHost);
-
- if(IM_INVENTORY_OFFERED == mIM)
- {
- // add buddy to recent people list
- LLRecentPeople::instance().add(mFromID);
- }
- }
- void LLOfferInfo::handleRespond(const LLSD& notification, const LLSD& response)
- {
- initRespondFunctionMap();
- const std::string name = notification["name"].asString();
- if(mRespondFunctions.find(name) == mRespondFunctions.end())
- {
- llwarns << "Unexpected notification name : " << name << llendl;
- llassert(!"Unexpected notification name");
- return;
- }
- mRespondFunctions[name](notification, response);
- }
- bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response)
- {
- LLChat chat;
- std::string log_message;
- S32 button = LLNotificationsUtil::getSelectedOption(notification, response);
- LLInventoryObserver* opener = NULL;
- LLViewerInventoryCategory* catp = NULL;
- catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID);
- LLViewerInventoryItem* itemp = NULL;
- if(!catp)
- {
- itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);
- }
-
- // For muting, we need to add the mute, then decline the offer.
- // This must be done here because:
- // * callback may be called immediately,
- // * adding the mute sends a message,
- // * we can't build two messages at once.
- if (2 == button) // Block
- {
- LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());
- llassert(notification_ptr != NULL);
- if (notification_ptr != NULL)
- {
- gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3));
- }
- }
- std::string from_string; // Used in the pop-up.
- std::string chatHistory_string; // Used in chat history.
-
- // 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 = gAgent.getBusy();
-
- switch(button)
- {
- case IOR_SHOW:
- // we will want to open this item when it comes back.
- LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
- << LL_ENDL;
- switch (mIM)
- {
- case IM_INVENTORY_OFFERED:
- {
- // This is an offer from an agent. In this case, the back
- // end has already copied the items into your inventory,
- // so we can fetch it out of our inventory.
- if (gSavedSettings.getBOOL("ShowOfferedInventory"))
- {
- LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(mObjectID, from_string);
- open_agent_offer->startFetch();
- if(catp || (itemp && itemp->isFinished()))
- {
- open_agent_offer->done();
- }
- else
- {
- opener = open_agent_offer;
- }
- }
- }
- break;
- case IM_GROUP_NOTICE:
- opener = new LLOpenTaskGroupOffer;
- send_auto_receive_response();
- break;
- case IM_TASK_INVENTORY_OFFERED:
- case IM_GROUP_NOTICE_REQUESTED:
- // This is an offer from a task or group.
- // We don't use a new instance of an opener
- // We instead use the singular observer gOpenTaskOffer
- // Since it already exists, we don't need to actually do anything
- break;
- default:
- LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
- break;
- }
- break;
- // end switch (mIM)
-
- case IOR_ACCEPT:
- //don't spam them if they are getting flooded
- if (check_offer_throttle(mFromName, true))
- {
- log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
- LLSD args;
- args["MESSAGE"] = log_message;
- LLNotificationsUtil::add("SystemMessageTip", args);
- }
- break;
- case IOR_MUTE:
- // MUTE falls through to decline
- case IOR_DECLINE:
- {
- {
- LLStringUtil::format_map_t log_message_args;
- log_message_args["DESC"] = mDesc;
- log_message_args["NAME"] = mFromName;
- log_message = LLTrans::getString("InvOfferDecline", log_message_args);
- }
- chat.mText = log_message;
- if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
- {
- chat.mMuted = TRUE;
- }
- // *NOTE dzaporozhan
- // Disabled logging to old chat floater to fix crash in group notices - EXT-4149
- // LLFloaterChat::addChatHistory(chat);
-
- LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
- discard_agent_offer->startFetch();
- if (catp || (itemp && itemp->isFinished()))
- {
- discard_agent_offer->done();
- }
- else
- {
- opener = discard_agent_offer;
- }
-
-
- if (busy && (!mFromGroup && !mFromObject))
- {
- busy_message(gMessageSystem, mFromID);
- }
- break;
- }
- default:
- // close button probably
- // The item has already been fetched and is in your inventory, we simply won't highlight it
- // OR delete it if the notification gets killed, since we don't want that to be a vector for
- // losing inventory offers.
- break;
- }
- if(opener)
- {
- gInventory.addObserver(opener);
- }
- if(!mPersist)
- {
- delete this;
- }
- return false;
- }
- bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const LLSD& response)
- {
- LLChat chat;
- std::string log_message;
- S32 button = LLNotification::getSelectedOption(notification, response);
-
- // For muting, we need to add the mute, then decline the offer.
- // This must be done here because:
- // * callback may be called immediately,
- // * adding the mute sends a message,
- // * we can't build two messages at once.
- if (2 == button)
- {
- LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());
- llassert(notification_ptr != NULL);
- if (notification_ptr != NULL)
- {
- gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3));
- }
- }
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_MessageBlock);
- msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
- msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
- msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
- msg->addUUIDFast(_PREHASH_ID, mTransactionID);
- msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
- std::string name;
- LLAgentUI::buildFullname(name);
- msg->addStringFast(_PREHASH_FromAgentName, name);
- msg->addStringFast(_PREHASH_Message, "");
- msg->addU32Fast(_PREHASH_ParentEstateID, 0);
- msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
- msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
- LLInventoryObserver* opener = NULL;
-
- std::string from_string; // Used in the pop-up.
- std::string chatHistory_string; // Used in chat history.
- if (mFromObject == TRUE)
- {
- if (mFromGroup)
- {
- std::string group_name;
- if (gCacheName->getGroupName(mFromID, group_name))
- {
- from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
- + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup")
- + " "+ "'" + group_name + "'";
-
- chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup")
- + " " + group_name + "'";
- }
- else
- {
- from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
- + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
- chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwn…
Large files files are truncated, but you can click here to view the full file