diff options
author | Dave Simmons <simon@lindenlab.com> | 2009-03-20 20:00:47 +0000 |
---|---|---|
committer | Dave Simmons <simon@lindenlab.com> | 2009-03-20 20:00:47 +0000 |
commit | 24b26d71ee01211aa796b8061b66ec06a133e4ce (patch) | |
tree | 96bffcd019c933ad3ebbfd5f096968108b22aab5 | |
parent | 5dfd435872e36445dcc82f99443dfc5a7ee0805a (diff) |
svn merge -r113004:115000 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.26
Merge latest 1.26 into trunk
56 files changed, 1686 insertions, 250 deletions
diff --git a/etc/message.xml b/etc/message.xml index 406235ff73..ddfd3e982e 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -474,8 +474,16 @@ <key>trusted-sender</key> <boolean>true</boolean> </map> - - <key>CrossedRegion</key> + + <key>TeleportFailed</key> + <map> + <key>flavor</key> + <string>llsd</string> + <key>trusted-sender</key> + <boolean>true</boolean> + </map> + + <key>CrossedRegion</key> <map> <key>flavor</key> <string>llsd</string> @@ -524,14 +532,6 @@ <boolean>false</boolean> </map> - <key>EstateOwnerMessage</key> - <map> - <key>flavor</key> - <string>llsd</string> - <key>trusted-sender</key> - <boolean>false</boolean> - </map> - <key>RpcScriptRequestInboundForward</key> <map> <key>flavor</key> diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 918a90e982..08151bc732 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -88,10 +88,11 @@ MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files) GET_TARGET_PROPERTY(TEST_EXE ${name}_test LOCATION) SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}_test_ok.txt) - SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) - IF (wrapper) - SET(TEST_CMD ${PYTHON_EXECUTABLE} ${wrapper} ${TEST_CMD}) - ENDIF (wrapper) + IF ("${wrapper}" STREQUAL "") + SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) + ELSE ("${wrapper}" STREQUAL "") + SET(TEST_CMD ${PYTHON_EXECUTABLE} ${wrapper} ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) + ENDIF ("${wrapper}" STREQUAL "") #MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_cmd = ${TEST_CMD}") SET(TEST_SCRIPT_CMD @@ -103,11 +104,11 @@ MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files) #MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_script = ${TEST_SCRIPT_CMD}") ADD_CUSTOM_COMMAND( - OUTPUT ${TEST_OUTPUT} - COMMAND ${TEST_SCRIPT_CMD} - DEPENDS ${name}_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - ) + OUTPUT ${TEST_OUTPUT} + COMMAND ${TEST_SCRIPT_CMD} + DEPENDS ${name}_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) ADD_CUSTOM_TARGET(${name}_test_ok ALL DEPENDS ${TEST_OUTPUT}) IF (${parent}) diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 4109eade19..ae7863d100 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -244,12 +244,11 @@ const F32 DEFAULT_WATER_HEIGHT = 20.0f; // Maturity ratings for simulators const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG -const U8 SIM_ACCESS_TRIAL = 7; const U8 SIM_ACCESS_PG = 13; const U8 SIM_ACCESS_MATURE = 21; const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only const U8 SIM_ACCESS_DOWN = 254; -const U8 SIM_ACCESS_MAX = SIM_ACCESS_MATURE; +const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; // group constants const S32 MAX_AGENT_GROUPS = 25; @@ -360,6 +359,8 @@ const U32 MAP_ITEM_POPULAR = 0x04; const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06; const U32 MAP_ITEM_LAND_FOR_SALE = 0x07; const U32 MAP_ITEM_CLASSIFIED = 0x08; +const U32 MAP_ITEM_ADULT_EVENT = 0x09; +const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a; // Crash reporter behavior const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml"; diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 36c14a7c7c..32825b18dc 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -55,7 +55,7 @@ public: LLDate(); /** - * @brief Construct a date equal the source date. + * @brief Construct a date equal to the source date. */ LLDate(const LLDate& date); diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 7e0fb27d60..cd53e701d2 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -197,8 +197,9 @@ LLQueuedThread::handle_t LLQueuedThread::generateHandle() { mNextHandle++; } + const LLQueuedThread::handle_t res = mNextHandle++; unlockData(); - return mNextHandle++; + return res; } // MAIN thread diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 8915890e18..99a9b9e269 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -40,9 +40,10 @@ #include <wchar.h> #endif +#include <string.h> + #if LL_SOLARIS // stricmp and strnicmp do not exist on Solaris: -#include <string.h> #define stricmp strcasecmp #define strnicmp strncasecmp #endif diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 776f2b1535..1e6584a085 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -566,6 +566,7 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb if(id.isNull()) { callback(id, CN_NOBODY, "", is_group, user_data); + return; } LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id ); diff --git a/indra/llmessage/llclassifiedflags.cpp b/indra/llmessage/llclassifiedflags.cpp index 62415cde5f..da608e490b 100644 --- a/indra/llmessage/llclassifiedflags.cpp +++ b/indra/llmessage/llclassifiedflags.cpp @@ -41,18 +41,35 @@ #include "linden_common.h" #include "llclassifiedflags.h" - -ClassifiedFlags pack_classified_flags(BOOL is_mature, BOOL auto_renew) + +ClassifiedFlags pack_classified_flags_request(BOOL auto_renew, BOOL inc_pg, BOOL inc_mature, BOOL inc_adult) +{ + U8 rv = 0; + if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG; + if(inc_mature) rv |= CLASSIFIED_QUERY_INC_MATURE; + if (inc_pg && !inc_mature) rv |= CLASSIFIED_FLAG_MATURE; + if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT; + if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW; + return rv; +} + +ClassifiedFlags pack_classified_flags(BOOL auto_renew, BOOL inc_pg, BOOL inc_mature, BOOL inc_adult) { U8 rv = 0; - if(is_mature) rv |= CLASSIFIED_FLAG_MATURE; + if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG; + if(inc_mature) + { + rv |= CLASSIFIED_QUERY_INC_MATURE; + rv |= CLASSIFIED_FLAG_MATURE; + } + if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT; if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW; return rv; } bool is_cf_mature(ClassifiedFlags flags) { - return ((flags & CLASSIFIED_FLAG_MATURE) != 0); + return ((flags & CLASSIFIED_FLAG_MATURE) != 0) || ((flags & CLASSIFIED_QUERY_INC_MATURE) != 0); } // Deprecated, but leaving commented out because someday we might diff --git a/indra/llmessage/llclassifiedflags.h b/indra/llmessage/llclassifiedflags.h index 1205112d41..9d3e49b90c 100644 --- a/indra/llmessage/llclassifiedflags.h +++ b/indra/llmessage/llclassifiedflags.h @@ -43,12 +43,23 @@ const U8 CLASSIFIED_FLAG_UPDATE_TIME= 1 << 4; const U8 CLASSIFIED_FLAG_AUTO_RENEW = 1 << 5; const U8 CLASSIFIED_QUERY_FILTER_MATURE = 1 << 1; -const U8 CLASSIFIED_QUERY_FILTER_ENABLED = 1 << 2; -const U8 CLASSIFIED_QUERY_FILTER_PRICE = 1 << 3; +//const U8 CLASSIFIED_QUERY_FILTER_ENABLED = 1 << 2; +//const U8 CLASSIFIED_QUERY_FILTER_PRICE = 1 << 3; + +// These are new with Adult-enabled viewers (1.23 and later) +const U8 CLASSIFIED_QUERY_INC_PG = 1 << 2; +const U8 CLASSIFIED_QUERY_INC_MATURE = 1 << 3; +const U8 CLASSIFIED_QUERY_INC_ADULT = 1 << 6; +const U8 CLASSIFIED_QUERY_INC_NEW_VIEWER = (CLASSIFIED_QUERY_INC_PG | CLASSIFIED_QUERY_INC_MATURE | CLASSIFIED_QUERY_INC_ADULT); const S32 MAX_CLASSIFIEDS = 100; -ClassifiedFlags pack_classified_flags(BOOL is_mature, BOOL auto_renew); +// This function is used in AO viewers to pack old query flags into the request +// so that they can talk to old dataservers properly. When the AO servers are deployed on agni +// we can revert back to ClassifiedFlags pack_classified_flags and get rider of this one. +ClassifiedFlags pack_classified_flags_request(BOOL auto_renew, BOOL is_pg, BOOL is_mature, BOOL is_adult); + +ClassifiedFlags pack_classified_flags(BOOL auto_renew, BOOL is_pg, BOOL is_mature, BOOL is_adult); bool is_cf_mature(ClassifiedFlags flags); //bool is_cf_enabled(ClassifiedFlags flags); bool is_cf_update_time(ClassifiedFlags flags); diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp index 7ce3d11be4..bb7c833b49 100644 --- a/indra/llmessage/lldispatcher.cpp +++ b/indra/llmessage/lldispatcher.cpp @@ -111,14 +111,40 @@ bool LLDispatcher::unpackMessage( LLUUID& invoice, LLDispatcher::sparam_t& parameters) { + char buf[MAX_STRING]; /*Flawfinder: ignore*/ msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method); msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice); + S32 size; S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList); for (S32 i = 0; i < count; ++i) { - std::string parameter; - msg->getStringFast(_PREHASH_ParamList,_PREHASH_Parameter, parameter, i); - parameters.push_back(parameter); + // we treat the SParam as binary data (since it might be an + // LLUUID in compressed form which may have embedded \0's,) + size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter); + msg->getBinaryDataFast( + _PREHASH_ParamList, _PREHASH_Parameter, + buf, size, i, MAX_STRING-1); + + // If the last byte of the data is 0x0, this is either a normally + // packed string, or a binary packed UUID (which for these messages + // are packed with a 17th byte 0x0). Unpack into a std::string + // without the trailing \0, so "abc\0" becomes std::string("abc", 3) + // which matches const char* "abc". + if (size > 0 + && buf[size-1] == 0x0) + { + // special char*/size constructor because UUIDs may have embedded + // 0x0 bytes. + std::string binary_data(buf, size-1); + parameters.push_back(binary_data); + } + else + { + // This is either a NULL string, or a string that was packed + // incorrectly as binary data, without the usual trailing '\0'. + std::string string_data(buf, size); + parameters.push_back(string_data); + } } return true; } diff --git a/indra/llmessage/lleventflags.h b/indra/llmessage/lleventflags.h index 8d4d08be63..965d978a5c 100644 --- a/indra/llmessage/lleventflags.h +++ b/indra/llmessage/lleventflags.h @@ -37,5 +37,6 @@ const U32 EVENT_FLAG_NONE = 0x0000; // set for mature events const U32 EVENT_FLAG_MATURE = 0x0001; +const U32 EVENT_FLAG_ADULT = 0x0002; #endif diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 884ec1309d..a6041b4139 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -402,6 +402,14 @@ LLSD LLHTTPClient::blockingGet(const std::string& url) curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); curl_easy_setopt(curlp, CURLOPT_FAILONERROR, 1); + struct curl_slist *header_list = NULL; + header_list = curl_slist_append(header_list, "Accept: application/llsd+xml"); + CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, header_list); + if ( curl_result != CURLE_OK ) + { + llinfos << "Curl is hosed - can't add Accept header for llsd+xml" << llendl; + } + LLSD response = LLSD::emptyMap(); S32 curl_success = curl_easy_perform(curlp); @@ -423,6 +431,12 @@ LLSD LLHTTPClient::blockingGet(const std::string& url) response["body"] = http_buffer.asLLSD(); } + if(header_list) + { // free the header list + curl_slist_free_all(header_list); + header_list = NULL; + } + curl_easy_cleanup(curlp); return response; diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp index f0e7654646..bbb56960df 100644 --- a/indra/llmessage/llhttpclientadapter.cpp +++ b/indra/llmessage/llhttpclientadapter.cpp @@ -38,12 +38,19 @@ LLHTTPClientAdapter::~LLHTTPClientAdapter() void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder) { - LLHTTPClient::get(url, responder); + LLSD empty_pragma_header; + // Pragma is required to stop curl adding "no-cache" + // Space is required to stop llurlrequest from turnning off proxying + empty_pragma_header["Pragma"] = " "; + LLHTTPClient::get(url, responder, empty_pragma_header); } void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) { - LLHTTPClient::get(url, responder, headers); + LLSD empty_pragma_header = headers; + // as above + empty_pragma_header["Pragma"] = " "; + LLHTTPClient::get(url, responder, empty_pragma_header); } void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) diff --git a/indra/llmessage/llqueryflags.h b/indra/llmessage/llqueryflags.h index d0496cc077..960d7777a7 100644 --- a/indra/llmessage/llqueryflags.h +++ b/indra/llmessage/llqueryflags.h @@ -65,6 +65,13 @@ const U32 DFQ_LIMIT_BY_AREA = 0x1 << 21; const U32 DFQ_FILTER_MATURE = 0x1 << 22; const U32 DFQ_PG_PARCELS_ONLY = 0x1 << 23; +const U32 DFQ_INC_PG = 0x1 << 24; // Flags appear in 1.23 viewer or later +const U32 DFQ_INC_MATURE = 0x1 << 25; +const U32 DFQ_INC_ADULT = 0x1 << 26; +const U32 DFQ_INC_NEW_VIEWER = (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT); // Indicates 1.23 viewer or later + +const U32 DFQ_ADULT_SIMS_ONLY = 0x1 << 27; + // Sell Type flags const U32 ST_AUCTION = 0x1 << 1; const U32 ST_NEWBIE = 0x1 << 2; @@ -73,4 +80,29 @@ const U32 ST_ESTATE = 0x1 << 4; const U32 ST_ALL = 0xFFFFFFFF; +// status flags embedded in search replay messages of classifieds, events, groups, and places. +// Places +const U32 STATUS_SEARCH_PLACES_NONE = 0x0; +const U32 STATUS_SEARCH_PLACES_BANNEDWORD = 0x1 << 0; +const U32 STATUS_SEARCH_PLACES_SHORTSTRING = 0x1 << 1; +const U32 STATUS_SEARCH_PLACES_FOUNDNONE = 0x1 << 2; +const U32 STATUS_SEARCH_PLACES_SEARCHDISABLED = 0x1 << 3; +const U32 STATUS_SEARCH_PLACES_ESTATEEMPTY = 0x1 << 4; +// Events +const U32 STATUS_SEARCH_EVENTS_NONE = 0x0; +const U32 STATUS_SEARCH_EVENTS_BANNEDWORD = 0x1 << 0; +const U32 STATUS_SEARCH_EVENTS_SHORTSTRING = 0x1 << 1; +const U32 STATUS_SEARCH_EVENTS_FOUNDNONE = 0x1 << 2; +const U32 STATUS_SEARCH_EVENTS_SEARCHDISABLED = 0x1 << 3; +const U32 STATUS_SEARCH_EVENTS_NODATEOFFSET = 0x1 << 4; +const U32 STATUS_SEARCH_EVENTS_NOCATEGORY = 0x1 << 5; +const U32 STATUS_SEARCH_EVENTS_NOQUERY = 0x1 << 6; + +//Classifieds +const U32 STATUS_SEARCH_CLASSIFIEDS_NONE = 0x0; +const U32 STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD = 0x1 << 0; +const U32 STATUS_SEARCH_CLASSIFIEDS_SHORTSTRING = 0x1 << 1; +const U32 STATUS_SEARCH_CLASSIFIEDS_FOUNDNONE = 0x1 << 2; +const U32 STATUS_SEARCH_CLASSIFIEDS_SEARCHDISABLED = 0x1 << 3; + #endif diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp index c47d4b78bc..e699ec9e28 100755 --- a/indra/llmessage/llsdmessagereader.cpp +++ b/indra/llmessage/llsdmessagereader.cpp @@ -108,6 +108,12 @@ void LLSDMessageReader::getBinaryData(const char *block, const char *var, data_size = max_size; } + // Calls to memcpy will fail if data_size is not positive. + // Phoenix 2009-02-27 + if(data_size <= 0) + { + return; + } memcpy(datap, &(data[0]), data_size); } diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 8ab12ce991..78af35bf65 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -923,6 +923,28 @@ LLSD LLMessageSystem::wrapReceivedTemplateData() const } } +LLSD LLMessageSystem::wrapBuiltTemplateData() const +{ + LLSD result; + if (mLLSDMessageBuilder == mMessageBuilder) + { + result = getBuiltMessageLLSD(); + } + else + { + U8 buffer[MAX_BUFFER_SIZE]; + const U8 offset_to_data = 0; + U32 size = mTemplateMessageBuilder->buildMessage( + buffer, MAX_BUFFER_SIZE, + offset_to_data); + std::vector<U8> binary_data(buffer, buffer+size); + LLSD wrapped_data = LLSD::emptyMap(); + wrapped_data["binary-template-data"] = binary_data; + result = wrapped_data; + } + return result; +} + LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const { const std::string& name = mMessageReader->getMessageName(); @@ -934,7 +956,7 @@ LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const LLStoredMessagePtr LLMessageSystem::getBuiltMessage() const { const std::string& name = mMessageBuilder->getMessageName(); - LLSD message = getBuiltMessageLLSD(); + LLSD message = wrapBuiltTemplateData(); return LLStoredMessagePtr(new LLStoredMessage(name, message)); } @@ -1131,7 +1153,7 @@ LLHTTPClient::ResponderPtr LLMessageSystem::createResponder(const std::string& n return new LLFnPtrResponder( NULL, NULL, - mMessageBuilder->getMessageName()); + name); } } diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 4fda8f01d7..b25b27eb0f 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -395,6 +395,7 @@ private: // but while the unsafe code is run in old processes, this // method should be used to forward unsafe messages. LLSD wrapReceivedTemplateData() const; + LLSD wrapBuiltTemplateData() const; public: diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index d554ec2f34..716d895334 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -314,6 +314,7 @@ char* _PREHASH_TextColor = LLMessageStringTable::getInstance()->getString("TextC char* _PREHASH_SlaveID = LLMessageStringTable::getInstance()->getString("SlaveID"); char* _PREHASH_Charter = LLMessageStringTable::getInstance()->getString("Charter"); char* _PREHASH_AlertData = LLMessageStringTable::getInstance()->getString("AlertData"); +char* _PREHASH_AlertInfo = LLMessageStringTable::getInstance()->getString("AlertInfo"); char* _PREHASH_TargetBlock = LLMessageStringTable::getInstance()->getString("TargetBlock"); char* _PREHASH_CheckParcelAuctions = LLMessageStringTable::getInstance()->getString("CheckParcelAuctions"); char* _PREHASH_ParcelAuctions = LLMessageStringTable::getInstance()->getString("ParcelAuctions"); @@ -1375,4 +1376,6 @@ char* _PREHASH_AgeVerificationBlock = LLMessageStringTable::getInstance()->getSt char* _PREHASH_UCoord = LLMessageStringTable::getInstance()->getString("UCoord"); char* _PREHASH_VCoord = LLMessageStringTable::getInstance()->getString("VCoord"); char* _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex"); +char* _PREHASH_StatusData = LLMessageStringTable::getInstance()->getString("StatusData"); + diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index e71518c6d6..c7bb7fff26 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -314,6 +314,7 @@ extern char * _PREHASH_TextColor; extern char * _PREHASH_SlaveID; extern char * _PREHASH_Charter; extern char * _PREHASH_AlertData; +extern char * _PREHASH_AlertInfo; extern char * _PREHASH_TargetBlock; extern char * _PREHASH_CheckParcelAuctions; extern char * _PREHASH_ParcelAuctions; @@ -1375,5 +1376,6 @@ extern char * _PREHASH_AgeVerificationBlock; extern char * _PREHASH_UCoord; extern char * _PREHASH_VCoord; extern char * _PREHASH_FaceIndex; +extern char * _PREHASH_StatusData; #endif diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index 8c0ea5fd14..e5ffce4ffc 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -232,7 +232,7 @@ struct LLVFSFileBlock_less const S32 LLVFSFileBlock::SERIAL_SIZE = 34; - + LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash) : mRemoveAfterCrash(remove_after_crash) { @@ -400,6 +400,12 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename mDataFP = NULL; LLFile::remove( mDataFilename ); + LL_WARNS("VFS") << "Deleted corrupt VFS files " + << mDataFilename + << " and " + << mIndexFilename + << LL_ENDL; + mValid = VFSVALID_BAD_CORRUPT; return; } @@ -505,6 +511,13 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename << " ID " << cur_file_block->mFileID << " type " << cur_file_block->mFileType << LL_ENDL; + + LL_WARNS("VFS") << "Deleted corrupt VFS files " + << mDataFilename + << " and " + << mIndexFilename + << LL_ENDL; + mValid = VFSVALID_BAD_CORRUPT; return; } @@ -718,8 +731,14 @@ S32 LLVFS::getMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type BOOL LLVFS::checkAvailable(S32 max_size) { + lockData(); + blocks_length_map_t::iterator iter = mFreeBlocksByLength.lower_bound(max_size); // first entry >= size - return (iter == mFreeBlocksByLength.end()) ? FALSE : TRUE; + const BOOL res(iter == mFreeBlocksByLength.end() ? FALSE : TRUE); + + unlockData(); + + return res; } BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type, S32 max_size) @@ -825,13 +844,20 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type if (free_block) { + // Save location where data is going, useFreeSpace will move free_block->mLocation; + U32 new_data_location = free_block->mLocation; + + //mark the free block as used so it does not + //interfere with other operations such as addFreeBlock + useFreeSpace(free_block, max_size); // useFreeSpace takes ownership (and may delete) free_block + if (block->mLength > 0) { // create a new free block where this file used to be LLVFSBlock *new_free_block = new LLVFSBlock(block->mLocation, block->mLength); addFreeBlock(new_free_block); - + if (block->mSize > 0) { // move the file into the new block @@ -839,7 +865,7 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type fseek(mDataFP, block->mLocation, SEEK_SET); if (fread(buffer, block->mSize, 1, mDataFP) == 1) { - fseek(mDataFP, free_block->mLocation, SEEK_SET); + fseek(mDataFP, new_data_location, SEEK_SET); if (fwrite(buffer, block->mSize, 1, mDataFP) != 1) { llwarns << "Short write" << llendl; @@ -852,13 +878,10 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type } } - block->mLocation = free_block->mLocation; + block->mLocation = new_data_location; block->mLength = max_size; - // Must call useFreeSpace before sync(), as sync() - // unlocks data structures. - useFreeSpace(free_block, max_size); sync(block); @@ -1073,14 +1096,14 @@ S32 LLVFS::getData(const LLUUID &file_id, const LLAssetType::EType file_type, U8 } } - unlockData(); - if (do_read) { fseek(mDataFP, location, SEEK_SET); bytesread = (S32)fread(buffer, 1, length, mDataFP); } + unlockData(); + return bytesread; } @@ -1145,8 +1168,6 @@ S32 LLVFS::storeData(const LLUUID &file_id, const LLAssetType::EType file_type, } U32 file_location = location + block->mLocation; - unlockData(); - fseek(mDataFP, file_location, SEEK_SET); S32 write_len = (S32)fwrite(buffer, 1, length, mDataFP); if (write_len != length) @@ -1155,7 +1176,6 @@ S32 LLVFS::storeData(const LLUUID &file_id, const LLAssetType::EType file_type, } // fflush(mDataFP); - lockData(); if (location + length > block->mSize) { block->mSize = location + write_len; @@ -1404,7 +1424,7 @@ void LLVFS::addFreeBlock(LLVFSBlock *block) // } //} - +// length bytes from free_block are going to be used (so they are no longer free) void LLVFS::useFreeSpace(LLVFSBlock *free_block, S32 length) { if (free_block->mLength == length) @@ -1487,8 +1507,6 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove) block->serialize(buffer); } - unlockData(); - // If set_index_to_end, file pointer is already at seek_pos // and we don't need to do anything. Only seek if not at end. if (!set_index_to_end) @@ -1500,11 +1518,10 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove) { llwarns << "Short write" << llendl; } - + + // *NOTE: Why was this commented out? // fflush(mIndexFP); - lockData(); - return; } diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt index 9febd9775d..487c5b9a8a 100644 --- a/indra/llxml/CMakeLists.txt +++ b/indra/llxml/CMakeLists.txt @@ -23,6 +23,7 @@ set(llxml_HEADER_FILES CMakeLists.txt llcontrol.h + llcontrolgroupreader.h llxmlnode.h llxmlparser.h llxmltree.h diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 9bf1d122bc..d9ed45ab9d 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -102,11 +102,12 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b) LLControlVariable::LLControlVariable(const std::string& name, eControlType type, LLSD initial, const std::string& comment, - bool persist) + bool persist, bool hidefromsettingseditor) : mName(name), mComment(comment), mType(type), - mPersist(persist) + mPersist(persist), + mHideFromSettingsEditor(hidefromsettingseditor) { if (mPersist && mComment.empty()) { @@ -213,6 +214,11 @@ void LLControlVariable::setPersist(bool state) mPersist = state; } +void LLControlVariable::setHiddenFromSettingsEditor(bool hide) +{ + mHideFromSettingsEditor = hide; +} + void LLControlVariable::setComment(const std::string& comment) { mComment = comment; @@ -296,17 +302,27 @@ std::string LLControlGroup::typeEnumToString(eControlType typeenum) return mTypeString[typeenum]; } -BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist) +BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor) { - if(mNameTable.find(name) != mNameTable.end()) - { - llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl; - mNameTable[name]->setValue(initial_val); - return TRUE; + LLControlVariable* existing_control = getControl(name); + if (existing_control) + { + if (persist && existing_control->isType(type)) + { + // Sometimes we need to declare a control *after* it has been loaded from a settings file. + LLSD cur_value = existing_control->getValue(); // get the current value + existing_control->setDefaultValue(initial_val); // set the default to the declared value + existing_control->setValue(cur_value); // now set to the loaded value + } + else + { + llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl; + } + return TRUE; } // if not, create the control and add it to the name table - LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist); + LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor); mNameTable[name] = control; return TRUE; } @@ -1043,7 +1059,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v } U32 validitems = 0; - bool persist = false; + bool persist = true; + bool hidefromsettingseditor = false; for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr) { name = (*itr).first; @@ -1054,6 +1071,18 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v persist = control_map["Persist"].asInteger(); } + // Sometimes we want to use the settings system to provide cheap persistence, but we + // don't want the settings themselves to be easily manipulated in the UI because + // doing so can cause support problems. So we have this option: + if(control_map.has("HideFromEditor")) + { + hidefromsettingseditor = control_map["HideFromEditor"].asInteger(); + } + else + { + hidefromsettingseditor = false; + } + // If the control exists just set the value from the input file. LLControlVariable* existing_control = getControl(name); if(existing_control) @@ -1067,6 +1096,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v { existing_control->setDefaultValue(control_map["Value"]); existing_control->setPersist(persist); + existing_control->setHiddenFromSettingsEditor(hidefromsettingseditor); existing_control->setComment(control_map["Comment"].asString()); } else @@ -1090,7 +1120,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v typeStringToEnum(control_map["Type"].asString()), control_map["Value"], control_map["Comment"].asString(), - persist + persist, + hidefromsettingseditor ); } diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 3be781ef78..ba0a1c7cbf 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -39,6 +39,8 @@ #include "llstring.h" #include "llrect.h" +#include "llcontrolgroupreader.h" + #include <vector> // *NOTE: boost::visit_each<> generates warning 4675 on .net 2003 @@ -93,7 +95,8 @@ private: std::string mName; std::string mComment; eControlType mType; - bool mPersist; + bool mPersist; + bool mHideFromSettingsEditor; std::vector<LLSD> mValues; signal_t mSignal; @@ -101,7 +104,7 @@ private: public: LLControlVariable(const std::string& name, eControlType type, LLSD initial, const std::string& comment, - bool persist = true); + bool persist = true, bool hidefromsettingseditor = false); virtual ~LLControlVariable(); @@ -118,6 +121,7 @@ public: bool isDefault() { return (mValues.size() == 1); } bool isSaveValueDefault(); bool isPersisted() { return mPersist; } + bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; } LLSD get() const { return getValue(); } LLSD getValue() const { return mValues.back(); } LLSD getDefault() const { return mValues.front(); } @@ -127,6 +131,7 @@ public: void setValue(const LLSD& value, bool saved_value = TRUE); void setDefaultValue(const LLSD& value); void setPersist(bool state); + void setHiddenFromSettingsEditor(bool hide); void setComment(const std::string& comment); void firePropertyChanged() @@ -140,7 +145,7 @@ private: }; //const U32 STRING_CACHE_SIZE = 10000; -class LLControlGroup +class LLControlGroup : public LLControlGroupReader { protected: typedef std::map<std::string, LLPointer<LLControlVariable> > ctrl_name_table_t; @@ -164,7 +169,7 @@ public: }; void applyToAll(ApplyFunctor* func); - BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist); + BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE); BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE); BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE); BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE); diff --git a/indra/llxml/llcontrolgroupreader.h b/indra/llxml/llcontrolgroupreader.h new file mode 100644 index 0000000000..960b19036e --- /dev/null +++ b/indra/llxml/llcontrolgroupreader.h @@ -0,0 +1,51 @@ +/** + * @file llcontrolgroupreader.h + * @brief Interface providing readonly access to LLControlGroup (intended for unit testing) + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * Copyright (c) 2001-2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONTROLGROUPREADER_H +#define LL_LLCONTROLGROUPREADER_H + +#include "stdtypes.h" +#include <string> + +// Many of the types below are commented out because for the purposes of the early testing we're doing, +// we don't need them and we don't want to pull in all the machinery to support them. +// But the model is here for future unit test extensions. + +class LLControlGroupReader +{ +public: + LLControlGroupReader() {} + virtual ~LLControlGroupReader() {} + + virtual std::string getString(const std::string& name) = 0; + //virtual LLWString getWString(const std::string& name) = 0; + virtual std::string getText(const std::string& name) = 0; + //virtual LLVector3 getVector3(const std::string& name) = 0; + //virtual LLVector3d getVector3d(const std::string& name) = 0; + //virtual LLRect getRect(const std::string& name) = 0; + virtual BOOL getBOOL(const std::string& name) = 0; + virtual S32 getS32(const std::string& name) = 0; + virtual F32 getF32(const std::string& name) = 0; + virtual U32 getU32(const std::string& name) = 0; + //virtual LLSD getLLSD(const std::string& name) = 0; + + //virtual LLColor4 getColor(const std::string& name) = 0; + //virtual LLColor4U getColor4U(const std::string& name) = 0; + //virtual LLColor4 getColor4(const std::string& name) = 0; + //virtual LLColor3 getColor3(const std::string& name) = 0; +}; + +#endif /* LL_LLCONTROLGROUPREADER_H */ + + + + + + + diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1ca1b4f915..ac05a7dbd7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -11,6 +11,7 @@ include(ELFIO) include(FMOD) include(OPENAL) include(FindOpenGL) +include(LLAddBuildTest) include(LLAudio) include(LLCharacter) include(LLCommon) @@ -64,6 +65,7 @@ include_directories( set(viewer_SOURCE_FILES llagent.cpp + llagentaccess.cpp llagentdata.cpp llagentlanguage.cpp llagentpilot.cpp @@ -466,6 +468,7 @@ set(viewer_HEADER_FILES ViewerInstall.cmake llagent.h + llagentaccess.h llagentdata.h llagentlanguage.h llagentpilot.h @@ -1566,3 +1569,5 @@ endif (DARWIN) if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) + +ADD_VIEWER_BUILD_TEST(llagentaccess viewer) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 41120522d5..d90882fb96 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4867,18 +4867,18 @@ <key>Value</key> <real>0.0</real> </map> - <key>InstallLanguage</key> - <map> - <key>Comment</key> - <string>Language passed from installer (for UI)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>default</string> - </map> - <key>InventoryAutoOpenDelay</key> + <key>InstallLanguage</key> + <map> + <key>Comment</key> + <string>Language passed from installer (for UI)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>default</string> + </map> + <key>InventoryAutoOpenDelay</key> <map> <key>Comment</key> <string>Seconds before automatically opening inventory when mouse is over inventory button when performing inventory drag and drop</string> @@ -6410,6 +6410,17 @@ <key>Value</key> <real>6.0</real> </map> + <key>PreferredMaturity</key> + <map> + <key>Comment</key> + <string>Setting for the user's preferred maturity level.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>13</integer> + </map> <key>PreviewAnimRect</key> <map> <key>Comment</key> @@ -7966,10 +7977,12 @@ <string>URL to load for empty searches</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>String</string> <key>Value</key> - <string>http://secondlife.com/app/search/index.php?</string> + <string>http://search.secondlife.com/client_search.php?</string> </map> <key>SearchURLQuery</key> <map> @@ -7977,10 +7990,12 @@ <string>URL to use for searches</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>String</string> <key>Value</key> - <string>http://secondlife.com/app/search/search_proxy.php?q=[QUERY]&s=[COLLECTION]&</string> + <string>http://search.secondlife.com/client_search.php?q=[QUERY]&s=[COLLECTION]&</string> </map> <key>SearchURLSuffix2</key> <map> @@ -7988,10 +8003,12 @@ <string>Parameters added to end of search queries</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>String</string> <key>Value</key> - <string>lang=[LANG]&m=[MATURE]&t=[TEEN]&region=[REGION]&x=[X]&y=[Y]&z=[Z]&session=[SESSION]</string> + <string>lang=[LANG]&mat=[MATURITY]&t=[TEEN]&region=[REGION]&x=[X]&y=[Y]&z=[Z]&session=[SESSION]</string> </map> <key>SelectMovableOnly</key> <map> @@ -8301,45 +8318,209 @@ <key>Value</key> <integer>0</integer> </map> + <key>ShowPGSearchAll</key> + <map> + <key>Comment</key> + <string>Display results of search All that are flagged as PG</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureSearchAll</key> + <map> + <key>Comment</key> + <string>Display results of search All that are flagged as mature</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowAdultSearchAll</key> + <map> + <key>Comment</key> + <string>Display results of search All that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowPGGroups</key> + <map> + <key>Comment</key> + <string>Display results of find groups that are flagged as PG</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureGroups</key> + <map> + <key>Comment</key> + <string>Display results of find groups that are flagged as mature</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowAdultGroups</key> + <map> + <key>Comment</key> + <string>Display results of find groups that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowPGClassifieds</key> + <map> + <key>Comment</key> + <string>Display results of find classifieds that are flagged as PG</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>ShowMatureClassifieds</key> <map> <key>Comment</key> <string>Display results of find classifieds that are flagged as mature</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowAdultClassifieds</key> + <map> + <key>Comment</key> + <string>Display results of find classifieds that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> <integer>0</integer> </map> + <key>ShowPGEvents</key> + <map> + <key>Comment</key> + <string>Display results of find events that are flagged as PG</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>ShowMatureEvents</key> <map> <key>Comment</key> <string>Display results of find events that are flagged as mature</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> <integer>0</integer> </map> - <key>ShowMatureFindAll</key> + <key>ShowAdultEvents</key> <map> <key>Comment</key> - <string>Display results of find all that are in mature sims</string> + <string>Display results of find events that are flagged as adult</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> <integer>0</integer> </map> - <key>ShowMatureGroups</key> + <key>ShowPGLand</key> <map> <key>Comment</key> - <string>Display results of find groups that are in flagged as mature</string> + <string>Display results of find land sales that are flagged as PG</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureLand</key> + <map> + <key>Comment</key> + <string>Display results of find land sales that are flagged as mature</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowAdultLand</key> + <map> + <key>Comment</key> + <string>Display results of find land sales that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowPGSims</key> + <map> + <key>Comment</key> + <string>Display results of find places or find popular that are in PG sims</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> @@ -8351,6 +8532,21 @@ <string>Display results of find places or find popular that are in mature sims</string> <key>Persist</key> <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowAdultSims</key> + <map> + <key>Comment</key> + <string>Display results of find places or find popular that are in adult sims</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 858855fe18..a894bca619 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -283,7 +283,7 @@ LLAgent::LLAgent() : mbAlwaysRun(false), mbRunning(false), - mAccess(SIM_ACCESS_PG), + mAgentAccess(gSavedSettings), mTeleportState( TELEPORT_NONE ), mRegionp(NULL), @@ -387,9 +387,7 @@ LLAgent::LLAgent() : mHaveHomePosition(FALSE), mHomeRegionHandle( 0 ), mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f), - mAdminOverride(FALSE), - mGodLevel( GOD_NOT ), mNextFidgetTime(0.f), mCurrentFidget(0), mFirstLogin(FALSE), @@ -4820,41 +4818,132 @@ void LLAgent::onAnimStop(const LLUUID& id) BOOL LLAgent::isGodlike() const { -#ifdef HACKED_GODLIKE_VIEWER - return TRUE; -#else - if(mAdminOverride) return TRUE; - return mGodLevel > GOD_NOT; -#endif + return mAgentAccess.isGodlike(); } U8 LLAgent::getGodLevel() const { -#ifdef HACKED_GODLIKE_VIEWER - return GOD_MAINTENANCE; -#else - if(mAdminOverride) return GOD_FULL; - return mGodLevel; -#endif + return mAgentAccess.getGodLevel(); +} + +bool LLAgent::wantsPGOnly() const +{ + return mAgentAccess.wantsPGOnly(); +} + +bool LLAgent::canAccessMature() const +{ + return mAgentAccess.canAccessMature(); +} + +bool LLAgent::canAccessAdult() const +{ + return mAgentAccess.canAccessAdult(); +} + +bool LLAgent::prefersPG() const +{ + return mAgentAccess.prefersPG(); +} + +bool LLAgent::prefersMature() const +{ + return mAgentAccess.prefersMature(); +} + +bool LLAgent::prefersAdult() const +{ + return mAgentAccess.prefersAdult(); } bool LLAgent::isTeen() const { - return mAccess < SIM_ACCESS_MATURE; + return mAgentAccess.isTeen(); +} + +bool LLAgent::isMature() const +{ + return mAgentAccess.isMature(); +} + +bool LLAgent::isAdult() const +{ + return mAgentAccess.isAdult(); } void LLAgent::setTeen(bool teen) { - if (teen) - { - mAccess = SIM_ACCESS_PG; - } - else + mAgentAccess.setTeen(teen); +} + +//static +int LLAgent::convertTextToMaturity(char text) +{ + return LLAgentAccess::convertTextToMaturity(text); +} + +bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) +{ + // Update agent access preference on the server + std::string url = getRegion()->getCapability("UpdateAgentInformation"); + if (!url.empty()) { - mAccess = SIM_ACCESS_MATURE; + // Set new access preference + LLSD access_prefs = LLSD::emptyMap(); + if (preferredMaturity == SIM_ACCESS_PG) + { + access_prefs["max"] = "PG"; + } + else if (preferredMaturity == SIM_ACCESS_MATURE) + { + access_prefs["max"] = "M"; + } + if (preferredMaturity == SIM_ACCESS_ADULT) + { + access_prefs["max"] = "A"; + } + + LLSD body = LLSD::emptyMap(); + body["access_prefs"] = access_prefs; + llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: " + << url << llendl; + LLHTTPClient::post(url, body, new LLHTTPClient::Responder()); // Ignore response + return true; } + return false; +} + +BOOL LLAgent::getAdminOverride() const +{ + return mAgentAccess.getAdminOverride(); } +void LLAgent::setMaturity(char text) +{ + mAgentAccess.setMaturity(text); +} + +void LLAgent::setAdminOverride(BOOL b) +{ + mAgentAccess.setAdminOverride(b); +} + +void LLAgent::setGodLevel(U8 god_level) +{ + mAgentAccess.setGodLevel(god_level); +} + +void LLAgent::setAOTransition() +{ + mAgentAccess.setTransition(); +} + +const LLAgentAccess& LLAgent::getAgentAccess() +{ + return mAgentAccess; +} + + void LLAgent::buildFullname(std::string& name) const { if (mAvatarObject.notNull()) diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 9d08c94150..fefb2a1d0b 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -40,6 +40,7 @@ #include "llcontrol.h" #include "llcoordframe.h" #include "llevent.h" +#include "llagentaccess.h" #include "llagentconstants.h" #include "llanimationstates.h" #include "lldbstrings.h" @@ -223,8 +224,8 @@ public: void clearBusy(); BOOL getBusy() const; - void setAdminOverride(BOOL b) { mAdminOverride = b; } - void setGodLevel(U8 god_level) { mGodLevel = god_level; } + void setAdminOverride(BOOL b); + void setGodLevel(U8 god_level); void setFirstLogin(BOOL b) { mFirstLogin = b; } void setGenderChosen(BOOL b) { mGenderChosen = b; } @@ -250,8 +251,29 @@ public: BOOL isGodlike() const; U8 getGodLevel() const; + // note: this is a prime candidate for pulling out into a Maturity class + // rather than just expose the preference setting, we're going to actually + // expose what the client code cares about -- what the user should see + // based on a combination of the is* and prefers* flags, combined with God bit. + bool wantsPGOnly() const; + bool canAccessMature() const; + bool canAccessAdult() const; + bool prefersPG() const; + bool prefersMature() const; + bool prefersAdult() const; bool isTeen() const; + bool isMature() const; + bool isAdult() const; void setTeen(bool teen); + void setMaturity(char text); + static int convertTextToMaturity(char text); + bool sendMaturityPreferenceToServer(int preferredMaturity); + + const LLAgentAccess& getAgentAccess(); + + // This function can go away after the AO transition (see llstartup.cpp) + void setAOTransition(); + BOOL isGroupTitleHidden() const { return mHideGroupTitle; } BOOL isGroupMember() const { return !mGroupID.isNull(); } // This is only used for building titles! const LLUUID &getGroupID() const { return mGroupID; } @@ -261,7 +283,7 @@ public: F32 getFocusObjectDist() const { return mFocusObjectDist; } BOOL inPrelude(); BOOL canManageEstate() const; - BOOL getAdminOverride() const { return mAdminOverride; } + BOOL getAdminOverride() const; LLUUID getLastChatter() const { return mLastChatterID; } bool getAlwaysRun() const { return mbAlwaysRun; } @@ -741,8 +763,8 @@ private: bool mbAlwaysRun; // should the avatar run by default rather than walk bool mbRunning; // is the avatar trying to run right now - // Access or "maturity" level - U8 mAccess; // SIM_ACCESS_MATURE or SIM_ACCESS_PG + LLAgentAccess mAgentAccess; + ETeleportState mTeleportState; std::string mTeleportMessage; @@ -865,10 +887,7 @@ private: LLFrameTimer mChatTimer; LLUUID mLastChatterID; F32 mNearChatRadius; - BOOL mAdminOverride; - // See indra_constants.h for values. - U8 mGodLevel; LLFrameTimer mFidgetTimer; LLFrameTimer mFocusObjectFadeTimer; F32 mNextFidgetTime; diff --git a/indra/newview/llagentaccess.cpp b/indra/newview/llagentaccess.cpp new file mode 100644 index 0000000000..a4fbc04855 --- /dev/null +++ b/indra/newview/llagentaccess.cpp @@ -0,0 +1,154 @@ +/** + * @file llagentaccess.cpp + * @brief LLAgentAccess class implementation - manages maturity and godmode info + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * Copyright (c) 2001-2009, Linden Research, Inc. + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llagentaccess.h" +#include "indra_constants.h" +#include "llcontrolgroupreader.h" + +LLAgentAccess::LLAgentAccess(LLControlGroupReader& savedSettings) : + mSavedSettings(savedSettings), + mAccess(SIM_ACCESS_PG), + mAdminOverride(false), + mGodLevel(GOD_NOT), + mAOTransition(false) +{ +} + +bool LLAgentAccess::getAdminOverride() const +{ + return mAdminOverride; +} + +void LLAgentAccess::setAdminOverride(bool b) +{ + mAdminOverride = b; +} + +void LLAgentAccess::setGodLevel(U8 god_level) +{ + mGodLevel = god_level; +} + +bool LLAgentAccess::isGodlike() const +{ +#ifdef HACKED_GODLIKE_VIEWER + return true; +#else + if(mAdminOverride) return true; + return mGodLevel > GOD_NOT; +#endif +} + +U8 LLAgentAccess::getGodLevel() const +{ +#ifdef HACKED_GODLIKE_VIEWER + return GOD_MAINTENANCE; +#else + if(mAdminOverride) return GOD_FULL; + return mGodLevel; +#endif +} + +bool LLAgentAccess::wantsPGOnly() const +{ + return (prefersPG() || isTeen()) && !isGodlike(); +} + +bool LLAgentAccess::canAccessMature() const +{ + // if you prefer mature, you're either mature or adult, and + // therefore can access all mature content + return isGodlike() || (prefersMature() && !isTeen()); +} + +bool LLAgentAccess::canAccessAdult() const +{ + // if you prefer adult, you must BE adult. + return isGodlike() || (prefersAdult() && isAdult()); +} + +bool LLAgentAccess::prefersPG() const +{ + U32 access = mSavedSettings.getU32("PreferredMaturity"); + return access < SIM_ACCESS_MATURE; +} + +bool LLAgentAccess::prefersMature() const +{ + U32 access = mSavedSettings.getU32("PreferredMaturity"); + return access >= SIM_ACCESS_MATURE; +} + +bool LLAgentAccess::prefersAdult() const +{ + U32 access = mSavedSettings.getU32("PreferredMaturity"); + return access >= SIM_ACCESS_ADULT; +} + +bool LLAgentAccess::isTeen() const +{ + return mAccess < SIM_ACCESS_MATURE; +} + +bool LLAgentAccess::isMature() const +{ + return mAccess >= SIM_ACCESS_MATURE; +} + +bool LLAgentAccess::isAdult() const +{ + return mAccess >= SIM_ACCESS_ADULT; +} + +void LLAgentAccess::setTeen(bool teen) +{ + if (teen) + { + mAccess = SIM_ACCESS_PG; + } + else + { + mAccess = SIM_ACCESS_MATURE; + } +} + +//static +int LLAgentAccess::convertTextToMaturity(char text) +{ + if ('A' == text) + { + return SIM_ACCESS_ADULT; + } + else if ('M'== text) + { + return SIM_ACCESS_MATURE; + } + else if ('P'== text) + { + return SIM_ACCESS_PG; + } + return SIM_ACCESS_MIN; +} + +void LLAgentAccess::setMaturity(char text) +{ + mAccess = LLAgentAccess::convertTextToMaturity(text); +} + +void LLAgentAccess::setTransition() +{ + mAOTransition = true; +} + +bool LLAgentAccess::isInTransition() const +{ + return mAOTransition; +} + diff --git a/indra/newview/llagentaccess.h b/indra/newview/llagentaccess.h new file mode 100644 index 0000000000..dec0d76cc9 --- /dev/null +++ b/indra/newview/llagentaccess.h @@ -0,0 +1,69 @@ +/** + * @file llagentaccess.h + * @brief LLAgentAccess class implementation - manages maturity and godmode info + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * Copyright (c) 2001-2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#ifndef LL_LLAGENTACCESS_H +#define LL_LLAGENTACCESS_H + +#include "stdtypes.h" + +// forward declaration so that we don't have to include the whole class +class LLControlGroupReader; + +class LLAgentAccess +{ +public: + LLAgentAccess(LLControlGroupReader& savedSettings); + + bool getAdminOverride() const; + void setAdminOverride(bool b); + + void setGodLevel(U8 god_level); + bool isGodlike() const; + U8 getGodLevel() const; + + + // rather than just expose the preference setting, we're going to actually + // expose what the client code cares about -- what the user should see + // based on a combination of the is* and prefers* flags, combined with God bit. + bool wantsPGOnly() const; + bool canAccessMature() const; + bool canAccessAdult() const; + bool prefersPG() const; + bool prefersMature() const; + bool prefersAdult() const; + bool isTeen() const; + bool isMature() const; + bool isAdult() const; + + void setTeen(bool teen); + void setMaturity(char text); + + static int convertTextToMaturity(char text); + + void setTransition(); // sets the transition bit, which defaults to false + bool isInTransition() const; + +private: + U8 mAccess; // SIM_ACCESS_MATURE etc + U8 mGodLevel; + bool mAdminOverride; + + // this should be deleted after the 60-day AO transition. + // It should be safe to remove it in Viewer 2009 + // It's set by a special short-term flag in login.cgi + // called ao_transition. When that's gone, this can go, along with + // all of the code that depends on it. + bool mAOTransition; + + // we want this to be const but the getters for it aren't, so we're + // overriding it for now + /* const */ LLControlGroupReader& mSavedSettings; +}; + +#endif // LL_LLAGENTACCESS_H diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index ff63aa1837..8e2d44911c 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -529,6 +529,12 @@ void LLFloaterBuyLandUI::updateCovenantInfo() region_name->setText(region->getName()); } + LLTextBox* region_type = getChild<LLTextBox>("region_type_text"); + if (region_type) + { + region_type->setText(region->getSimProductName()); + } + LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause"); if (resellable_clause) { diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index e0396e070c..dc18369bb6 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -41,6 +41,7 @@ #include "llfocusmgr.h" #include "llparcel.h" #include "message.h" +#include "lluserauth.h" #include "llagent.h" #include "llfloateravatarpicker.h" @@ -319,7 +320,9 @@ BOOL LLPanelLandGeneral::postBuild() mTextSalePending = getChild<LLTextBox>("SalePending"); mTextOwnerLabel = getChild<LLTextBox>("Owner:"); mTextOwner = getChild<LLTextBox>("OwnerText"); - + + mContentRating = getChild<LLTextBox>("ContentRatingText"); + mLandType = getChild<LLTextBox>("LandTypeText"); mBtnProfile = getChild<LLButton>("Profile..."); mBtnProfile->setClickedCallback(onClickProfile, this); @@ -445,6 +448,8 @@ void LLPanelLandGeneral::refresh() mCheckContributeWithDeed->setEnabled(FALSE); mTextOwner->setText(LLStringUtil::null); + mContentRating->setText(LLStringUtil::null); + mLandType->setText(LLStringUtil::null); mBtnProfile->setLabel(getString("profile_text")); mBtnProfile->setEnabled(FALSE); @@ -479,6 +484,12 @@ void LLPanelLandGeneral::refresh() { region_xfer = TRUE; } + + if (regionp) + { + mContentRating->setText(regionp->getSimAccessString()); + mLandType->setText(regionp->getSimProductName()); + } // estate owner/manager cannot edit other parts of the parcel BOOL estate_manager_sellable = !parcel->getAuctionID() @@ -1768,8 +1779,7 @@ BOOL LLPanelLandOptions::postBuild() mPublishHelpButton = getChild<LLButton>("?"); mPublishHelpButton->setClickedCallback(onClickPublishHelp, this); - - if (gAgent.isTeen()) + if (gAgent.wantsPGOnly()) { // Disable these buttons if they are PG (Teen) users mPublishHelpButton->setVisible(FALSE); @@ -1777,26 +1787,14 @@ BOOL LLPanelLandOptions::postBuild() mMatureCtrl->setVisible(FALSE); mMatureCtrl->setEnabled(FALSE); } - - // Load up the category list - //now in xml file - /* - S32 i; - for (i = 0; i < LLParcel::C_COUNT; i++) + + if (!gAgent.getAgentAccess().isInTransition()) { - LLParcel::ECategory cat = (LLParcel::ECategory)i; - - // Selecting Linden Location when you're not a god - // is also blocked on the server. - BOOL enabled = TRUE; - if (!gAgent.isGodlike() - && i == LLParcel::C_LINDEN) - { - enabled = FALSE; - } - - mCategoryCombo->add( LLParcel::getCategoryUIString(cat), ADD_BOTTOM, enabled ); - }*/ + // remove category for adult if we're post-transition + // (this code can go away, and the category can be removed from the xml, + // once we've completed the transition period for adult) + mCategoryCombo->remove(getString("adult_land_category_label")); + } mSnapshotCtrl = getChild<LLTextureCtrl>("snapshot_ctrl"); @@ -1969,11 +1967,9 @@ void LLPanelLandOptions::refresh() mSetBtn->setEnabled( can_change_landing_point ); mClearBtn->setEnabled( can_change_landing_point ); - mMatureCtrl->set(parcel->getMaturePublish()); - mMatureCtrl->setEnabled( can_change_identity ); mPublishHelpButton->setEnabled( can_change_identity ); - if (gAgent.isTeen()) + if (gAgent.wantsPGOnly()) { // Disable these buttons if they are PG (Teen) users mPublishHelpButton->setVisible(FALSE); @@ -1981,6 +1977,34 @@ void LLPanelLandOptions::refresh() mMatureCtrl->setVisible(FALSE); mMatureCtrl->setEnabled(FALSE); } + else + { + // not teen so fill in the data for the maturity control + mMatureCtrl->setVisible(TRUE); + mMatureCtrl->setLabel(getString("mature_check_mature")); + // they can see the checkbox, but its disposition depends on the + // state of the region + LLViewerRegion* regionp = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + if (regionp) + { + if (regionp->getSimAccess() == SIM_ACCESS_PG) + { + mMatureCtrl->setEnabled(FALSE); + mMatureCtrl->set(FALSE); + } + else if (regionp->getSimAccess() == SIM_ACCESS_MATURE) + { + mMatureCtrl->setEnabled(can_change_identity); + mMatureCtrl->set(parcel->getMaturePublish()); + } + else if (regionp->getSimAccess() == SIM_ACCESS_ADULT) + { + mMatureCtrl->setEnabled(FALSE); + mMatureCtrl->set(TRUE); + mMatureCtrl->setLabel(getString("mature_check_adult")); + } + } + } } } @@ -2749,6 +2773,18 @@ void LLPanelLandCovenant::refresh() region_name->setText(region->getName()); } + LLTextBox* region_landtype = getChild<LLTextBox>("region_landtype_text"); + if (region_landtype) + { + region_landtype->setText(region->getSimProductName()); + } + + LLTextBox* region_maturity = getChild<LLTextBox>("region_maturity_text"); + if (region_maturity) + { + region_maturity->setText(region->getSimAccessString()); + } + LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause"); if (resellable_clause) { diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 520ed4147e..4c3de65d71 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -186,6 +186,9 @@ protected: LLTextBox* mTextOwnerLabel; LLTextBox* mTextOwner; LLButton* mBtnProfile; + + LLTextBox* mContentRating; + LLTextBox* mLandType; LLTextBox* mTextGroup; LLTextBox* mTextGroupLabel; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 86bc8221d9..588df7b43b 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -295,6 +295,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) // extract message std::string sim_name; + std::string sim_type = "(unknown)"; U32 region_flags; U8 agent_limit; F32 object_bonus_factor; @@ -315,10 +316,18 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) msg->getBOOL("RegionInfo", "UseEstateSun", use_estate_sun); // actually the "last set" sun hour, not the current sun hour. JC msg->getF32("RegionInfo", "SunHour", sun_hour); + // the only reasonable way to decide if we actually have any data is to + // check to see if any of these fields have nonzero sizes + if (msg->getSize("RegionInfo2", "ProductSKU") || + msg->getSize("RegionInfo2", "ProductName")) + { + msg->getString("RegionInfo2", "ProductName", sim_type); + } // GENERAL PANEL panel = tab->getChild<LLPanel>("General"); panel->childSetValue("region_text", LLSD(sim_name)); + panel->childSetValue("region_type", LLSD(sim_type)); panel->childSetValue("version_channel_text", gLastVersionChannel); panel->childSetValue("block_terraform_check", (region_flags & REGION_FLAGS_BLOCK_TERRAFORM) ? TRUE : FALSE ); @@ -330,7 +339,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->childSetValue("block_parcel_search_check", (region_flags & REGION_FLAGS_BLOCK_PARCEL_SEARCH) ? TRUE : FALSE ); panel->childSetValue("agent_limit_spin", LLSD((F32)agent_limit) ); panel->childSetValue("object_bonus_spin", LLSD(object_bonus_factor) ); - panel->childSetValue("access_combo", LLSD(LLViewerRegion::accessToString(sim_access)) ); + panel->childSetValue("access_combo", LLSD(sim_access) ); // detect teen grid for maturity @@ -718,7 +727,7 @@ void LLPanelRegionGeneralInfo::onClickManageTelehub(void* data) // strings[3] = 'Y' - allow land sale, 'N' - not // strings[4] = agent limit // strings[5] = object bonus -// strings[6] = sim access (0 = unknown, 13 = PG, 21 = Mature) +// strings[6] = sim access (0 = unknown, 13 = PG, 21 = Mature, 42 = Adult) // strings[7] = restrict pushobject // strings[8] = 'Y' - allow parcel subdivide, 'N' - not // strings[9] = 'Y' - block parcel search, 'N' - allow @@ -739,7 +748,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate() body["prim_bonus"] = childGetValue("object_bonus_spin"); // the combo box stores strings "Mature" and "PG", but we have to convert back to a number, // because the sim doesn't know from strings for this stuff - body["sim_access"] = LLViewerRegion::stringToAccess(childGetValue("access_combo").asString()); + body["sim_access"] = childGetValue("access_combo"); body["restrict_pushobject"] = childGetValue("restrict_pushobject"); body["allow_parcel_changes"] = childGetValue("allow_parcel_changes_check"); body["block_parcel_search"] = childGetValue("block_parcel_search_check"); @@ -771,7 +780,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate() buffer = llformat("%f", value); strings.push_back(strings_t::value_type(buffer)); - U8 access = LLViewerRegion::stringToAccess(childGetValue("access_combo").asString()); + U8 access = childGetValue("access_combo").asInteger(); buffer = llformat("%d", (S32)access); strings.push_back(strings_t::value_type(buffer)); diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index f6002653ab..2677467611 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -61,7 +61,10 @@ BOOL LLFloaterSettingsDebug::postBuild() f(LLComboBox* c) : combo(c) {} virtual void apply(const std::string& name, LLControlVariable* control) { - combo->add(name, (void*)control); + if (!control->isHiddenFromSettingsEditor()) + { + combo->add(name, (void*)control); + } } } func(settings_combo); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index d59f513925..e2e71f51fa 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -429,9 +429,19 @@ void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent void LLFloaterWorldMap::draw() { // Hide/Show Mature Events controls - childSetVisible("events_mature_icon", !gAgent.isTeen()); - childSetVisible("events_mature_label", !gAgent.isTeen()); - childSetVisible("event_mature_chk", !gAgent.isTeen()); + childSetVisible("events_mature_icon", gAgent.canAccessMature()); + childSetVisible("events_mature_label", gAgent.canAccessMature()); + childSetVisible("event_mature_chk", gAgent.canAccessMature()); + + childSetVisible("events_adult_icon", gAgent.canAccessMature()); + childSetVisible("events_adult_label", gAgent.canAccessMature()); + childSetVisible("event_adult_chk", gAgent.canAccessMature()); + bool adult_enabled = gAgent.canAccessAdult(); + if (!adult_enabled) + { + childSetValue("event_adult_chk", FALSE); + } + childSetEnabled("event_adult_chk", adult_enabled); // On orientation island, users don't have a home location yet, so don't // let them teleport "home". It dumps them in an often-crowed welcome @@ -1315,6 +1325,7 @@ void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data) LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; if(!self) return; self->childSetEnabled("event_mature_chk", self->childGetValue("event_chk")); + self->childSetEnabled("event_adult_chk", self->childGetValue("event_chk")); } // protected diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 0c60357dfb..e6639a2da5 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -223,6 +223,7 @@ void LLPanelClassified::reset() mPosGlobal.clearVec(); clearCtrls(); + resetDirty(); } @@ -285,7 +286,7 @@ BOOL LLPanelClassified::postBuild() mMatureCombo->setCurrentByIndex(0); mMatureCombo->setCommitCallback(onCommitAny); mMatureCombo->setCallbackUserData(this); - if (gAgent.isTeen()) + if (gAgent.wantsPGOnly()) { // Teens don't get to set mature flag. JC mMatureCombo->setVisible(FALSE); @@ -308,6 +309,7 @@ BOOL LLPanelClassified::postBuild() mClickThroughText = getChild<LLTextBox>("click_through_text"); } + resetDirty(); return TRUE; } @@ -540,7 +542,10 @@ void LLPanelClassified::sendClassifiedInfoUpdate() { auto_renew = mAutoRenewCheck->get(); } - U8 flags = pack_classified_flags(mature, auto_renew); + // These flags doesn't matter here. + const bool adult_enabled = false; + const bool is_pg = false; + U8 flags = pack_classified_flags_request(auto_renew, is_pg, mature, adult_enabled); msg->addU8Fast(_PREHASH_ClassifiedFlags, flags); msg->addS32("PriceForListing", mPriceForListing); gAgent.sendReliableMessage(); @@ -678,6 +683,7 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void ** self->resetDirty(); + // I don't know if a second call is deliberate or a bad merge, so I'm leaving it here. self->resetDirty(); } } diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index a4013f104c..47ed72aa77 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -294,9 +294,14 @@ void LLPanelPlace::processParcelInfoReply(LLMessageSystem *msg, void **) self->mInfoEditor->setText(info_text); } - // HACK: Flag 0x1 == mature region, otherwise assume PG + // HACK: Flag 0x2 == adult region, + // Flag 0x1 == mature region, otherwise assume PG std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG); - if (flags & 0x1) + if (flags & 0x2) + { + rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT); + } + else if (flags & 0x1) { rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE); } diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index cdcd68de38..86f590a0f0 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -89,8 +89,7 @@ BOOL LLProgressView::postBuild() getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle())); - getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage); - getChild<LLTextBox>("message_text")->setCallbackUserData(this); + getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage, this); sInstance = this; return TRUE; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5f96fc7da0..bd2e157779 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1361,14 +1361,32 @@ bool idle_startup() LLStartUp::deletePasswordFromDisk(); } - text = LLUserAuth::getInstance()->getResponse("agent_access"); - if(!text.empty() && (text[0] == 'M')) + // this is their actual ability to access content + text = LLUserAuth::getInstance()->getResponse("agent_access_max"); + if (!text.empty()) { - gAgent.setTeen(false); + // agent_access can be 'A', 'M', and 'PG'. + gAgent.setMaturity(text[0]); } - else + + // this is the value of their preference setting for that content + // which will always be <= agent_access_max + text = LLUserAuth::getInstance()->getResponse("agent_region_access"); + if (!text.empty()) + { + int preferredMaturity = LLAgent::convertTextToMaturity(text[0]); + gSavedSettings.setU32("PreferredMaturity", preferredMaturity); + } + // During the AO transition, this flag will be true. Then the flag will + // go away. After the AO transition, this code and all the code that + // uses it can be deleted. + text = LLUserAuth::getInstance()->getResponse("ao_transition"); + if (!text.empty()) { - gAgent.setTeen(true); + if (text == "1") + { + gAgent.setAOTransition(); + } } text = LLUserAuth::getInstance()->getResponse("start_location"); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 50e5b4e90c..96a4f74927 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -470,7 +470,6 @@ BOOL enable_grab_texture(void*); void handle_dump_region_object_cache(void*); BOOL menu_ui_enabled(void *user_data); -void check_toggle_control( LLUICtrl *, void* user_data ); BOOL menu_check_control( void* user_data); void menu_toggle_variable( void* user_data ); BOOL menu_check_variable( void* user_data); @@ -1025,6 +1024,11 @@ extern BOOL gDebugSelectMgr; void init_debug_ui_menu(LLMenuGL* menu) { + menu->append(new LLMenuItemCheckGL("Rotate Mini-Map", menu_toggle_control, NULL, menu_check_control, (void*)"MiniMapRotate")); + menu->append(new LLMenuItemCheckGL("Use default system color picker", menu_toggle_control, NULL, menu_check_control, (void*)"UseDefaultColorPicker")); + menu->append(new LLMenuItemCheckGL("Show search panel in overlay bar", menu_toggle_control, NULL, menu_check_control, (void*)"ShowSearchBar")); + menu->appendSeparator(); + menu->append(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test)); menu->append(new LLMenuItemCallGL("Buy Currency Test", &handle_buy_currency_test)); menu->append(new LLMenuItemCallGL("Editable UI", &edit_ui)); @@ -6182,13 +6186,6 @@ class LLToggleControl : public view_listener_t } }; -// As above, but can be a callback from a LLCheckboxCtrl -void check_toggle_control( LLUICtrl *, void* user_data ) -{ - BOOL checked = gSavedSettings.getBOOL( static_cast<char*>(user_data) ); - gSavedSettings.setBOOL( static_cast<char*>(user_data), !checked ); -} - BOOL menu_check_control( void* user_data) { return gSavedSettings.getBOOL((char*)user_data); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index a82e4a9a4d..e9fedf37d8 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -80,7 +80,6 @@ BOOL is_agent_friend(const LLUUID& agent_id); BOOL is_agent_mappable(const LLUUID& agent_id); void menu_toggle_control( void* user_data ); -void check_toggle_control( LLUICtrl *, void* user_data ); void confirm_replace_attachment(S32 option, void* user_data); void handle_detach_from_avatar(void* user_data); void attach_label(std::string& label, void* user_data); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dae3529319..6ffb19bcdf 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4118,29 +4118,158 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) } } -void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data) +bool handle_special_notification_callback(const LLSD& notification, const LLSD& response) { - std::string buffer; - msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); - BOOL modal = FALSE; - msgsystem->getBOOL("AlertData", "Modal", modal); - process_alert_core(buffer, modal); + S32 option = LLNotification::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); + + } + + return false; } -void process_alert_message(LLMessageSystem *msgsystem, void **user_data) +// some of the server notifications need special handling. This is where we do that. +bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) { - std::string buffer; - msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); - BOOL modal = FALSE; - process_alert_core(buffer, modal); + int regionAccess = llsdBlock["_region_access"].asInteger(); + llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess); + + // we're going to throw the LLSD in there in case anyone ever wants to use it + LLNotifications::instance().add(notificationID+"_Notify", llsdBlock); + + if (regionAccess == SIM_ACCESS_MATURE) + { + if (gAgent.isTeen()) + { + LLNotifications::instance().add(notificationID+"_KB", llsdBlock); + return true; + } + else if (gAgent.prefersPG()) + { + LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); + return true; + } + } + else if (regionAccess == SIM_ACCESS_ADULT) + { + if (!gAgent.isAdult()) + { + LLNotifications::instance().add(notificationID+"_KB", llsdBlock); + return true; + } + else if (gAgent.prefersPG() || gAgent.prefersMature()) + { + LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); + return true; + } + } + return false; } -void process_alert_core(const std::string& message, BOOL modal) +bool attempt_standard_notification(LLMessageSystem* msgsystem) +{ + // if we have additional alert data + if (msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0) + { + // notification was specified using the new mechanism, so we can just handle it here + std::string notificationID; + std::string llsdRaw; + LLSD llsdBlock; + msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID); + msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsdRaw); + if (llsdRaw.length()) + { + std::istringstream llsdData(llsdRaw); + if (!LLSDSerialize::deserialize(llsdBlock, llsdData, llsdRaw.length())) + { + llwarns << "attempt_standard_notification: Attempted to read notification parameter data into LLSD but failed:" << llsdRaw << llendl; + } + } + + if ( + (notificationID == "RegionEntryAccessBlocked") || + (notificationID == "LandClaimAccessBlocked") || + (notificationID == "LandBuyAccessBlocked") + ) + { + /*--------------------------------------------------------------------- + (Commented so a grep will find the notification strings, since + we construct them on the fly; if you add additional notifications, + please update the comment.) + + Could throw any of the following notifications: + + RegionEntryAccessBlocked + RegionEntryAccessBlocked_Notify + RegionEntryAccessBlocked_Change + RegionEntryAccessBlocked_KB + LandClaimAccessBlocked + LandClaimAccessBlocked_Notify + LandClaimAccessBlocked_Change + LandClaimAccessBlocked_KB + LandBuyAccessBlocked + LandBuyAccessBlocked_Notify + LandBuyAccessBlocked_Change + LandBuyAccessBlocked_KB + + -----------------------------------------------------------------------*/ + if (handle_special_notification(notificationID, llsdBlock)) + { + return true; + } + } + + LLNotifications::instance().add(notificationID, llsdBlock); + return true; + } + return false; +} + + +void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data) +{ + // make sure the cursor is back to the usual default since the + // alert is probably due to some kind of error. + gViewerWindow->getWindow()->resetBusyCount(); + + if (!attempt_standard_notification(msgsystem)) + { + BOOL modal = FALSE; + msgsystem->getBOOL("AlertData", "Modal", modal); + std::string buffer; + msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); + process_alert_core(buffer, modal); + } +} + +// The only difference between this routine and the previous is the fact that +// for this routine, the modal parameter is always false. Sadly, for the message +// handled by this routine, there is no "Modal" parameter on the message, and +// there's no API to tell if a message has the given parameter or not. +// So we can't handle the messages with the same handler. +void process_alert_message(LLMessageSystem *msgsystem, void **user_data) { // make sure the cursor is back to the usual default since the // alert is probably due to some kind of error. gViewerWindow->getWindow()->resetBusyCount(); + + if (!attempt_standard_notification(msgsystem)) + { + BOOL modal = FALSE; + std::string buffer; + msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); + process_alert_core(buffer, modal); + } +} +void process_alert_core(const std::string& message, BOOL modal) +{ // HACK -- handle callbacks for specific alerts if ( message == "You died and have been teleported to your home location") { @@ -4732,17 +4861,63 @@ std::string formatted_time(const time_t& the_time) void process_teleport_failed(LLMessageSystem *msg, void**) { std::string reason; - msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason); - + std::string big_reason; LLSD args; - std::string big_reason = LLAgent::sTeleportErrorMessages[reason]; - if ( big_reason.size() > 0 ) - { // Substitute verbose reason from the local map - args["REASON"] = big_reason; + + // if we have additional alert data + if (msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0) + { + // Get the message ID + msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, reason); + big_reason = LLAgent::sTeleportErrorMessages[reason]; + if ( big_reason.size() > 0 ) + { // Substitute verbose reason from the local map + args["REASON"] = big_reason; + } + else + { // Nothing found in the map - use what the server returned in the original message block + msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason); + args["REASON"] = reason; + } + + LLSD llsd_block; + std::string llsd_raw; + msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsd_raw); + if (llsd_raw.length()) + { + std::istringstream llsd_data(llsd_raw); + if (!LLSDSerialize::deserialize(llsd_block, llsd_data, llsd_raw.length())) + { + llwarns << "process_teleport_failed: Attempted to read alert parameter data into LLSD but failed:" << llsd_raw << llendl; + } + else + { + // change notification name in this special case + if (handle_special_notification("RegionEntryAccessBlocked", llsd_block)) + { + if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) + { + gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + } + return; + } + } + } + } else - { // Nothing found in the map - use what the server returned - args["REASON"] = reason; + { + msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason); + + big_reason = LLAgent::sTeleportErrorMessages[reason]; + if ( big_reason.size() > 0 ) + { // Substitute verbose reason from the local map + args["REASON"] = big_reason; + } + else + { // Nothing found in the map - use what the server returned + args["REASON"] = reason; + } } LLNotifications::instance().add("CouldNotTeleportReason", args); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index bf40ccce49..e7a4303a8e 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -107,6 +107,7 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/); void process_money_balance_reply(LLMessageSystem* msg_system, void**); void process_adjust_balance(LLMessageSystem* msg_system, void**); +bool attempt_standard_notification(LLMessageSystem* msg); void process_alert_message(LLMessageSystem* msg, void**); void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data); void process_alert_core(const std::string& message, BOOL modal); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 87b6652056..750151ea2d 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -56,6 +56,7 @@ #include "llhttpnode.h" #include "llsdutil.h" #include "llstartup.h" +#include "lltrans.h" #include "llviewerobjectlist.h" #include "llviewerparceloverlay.h" #include "llvlmanager.h" @@ -162,6 +163,11 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mSimAccess( SIM_ACCESS_MIN ), mBillableFactor(1.0), mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), + mClassID(0), + mCPURatio(0), + mColoName("unknown"), + mProductSKU("unknown"), + mProductName("unknown"), mCacheLoaded(FALSE), mCacheEntriesCount(0), mCacheID(), @@ -539,56 +545,30 @@ std::string LLViewerRegion::regionFlagsToString(U32 flags) return result; } -// *TODO:Translate -const char* SIM_ACCESS_STR[] = { "Free Trial", - "PG", - "Mature", - "Offline", - "Unknown" }; - // static std::string LLViewerRegion::accessToString(U8 sim_access) { switch(sim_access) { - case SIM_ACCESS_TRIAL: - return SIM_ACCESS_STR[0]; - case SIM_ACCESS_PG: - return SIM_ACCESS_STR[1]; + return LLTrans::getString("SIM_ACCESS_PG"); case SIM_ACCESS_MATURE: - return SIM_ACCESS_STR[2]; + return LLTrans::getString("SIM_ACCESS_MATURE"); + + case SIM_ACCESS_ADULT: + return LLTrans::getString("SIM_ACCESS_ADULT"); case SIM_ACCESS_DOWN: - return SIM_ACCESS_STR[3]; + return LLTrans::getString("SIM_ACCESS_DOWN"); case SIM_ACCESS_MIN: default: - return SIM_ACCESS_STR[4]; + return LLTrans::getString("SIM_ACCESS_MIN"); } } // static -U8 LLViewerRegion::stringToAccess(const std::string& access_str) -{ - U8 sim_access = SIM_ACCESS_MIN; - if (access_str == SIM_ACCESS_STR[0]) - { - sim_access = SIM_ACCESS_TRIAL; - } - else if (access_str == SIM_ACCESS_STR[1]) - { - sim_access = SIM_ACCESS_PG; - } - else if (access_str == SIM_ACCESS_STR[2]) - { - sim_access = SIM_ACCESS_MATURE; - } - return sim_access; -} - -// static std::string LLViewerRegion::accessToShortString(U8 sim_access) { switch(sim_access) /* Flawfinder: ignore */ @@ -596,12 +576,12 @@ std::string LLViewerRegion::accessToShortString(U8 sim_access) case SIM_ACCESS_PG: return "PG"; - case SIM_ACCESS_TRIAL: - return "TR"; - case SIM_ACCESS_MATURE: return "M"; + case SIM_ACCESS_ADULT: + return "A"; + case SIM_ACCESS_MIN: default: return "U"; @@ -1315,6 +1295,32 @@ void LLViewerRegion::unpackRegionHandshake() LLUUID region_id; msg->getUUID("RegionInfo2", "RegionID", region_id); setRegionID(region_id); + + // Retrieve the CR-53 (Homestead/Land SKU) information + S32 classID = 0; + S32 cpuRatio = 0; + std::string coloName; + std::string productSKU; + std::string productName; + + // the only reasonable way to decide if we actually have any data is to + // check to see if any of these fields have nonzero sizes + if (msg->getSize("RegionInfo3", "ColoName") || + msg->getSize("RegionInfo3", "ProductSKU") || + msg->getSize("RegionInfo3", "ProductName")) + { + msg->getS32 ("RegionInfo3", "CPUClassID", classID); + msg->getS32 ("RegionInfo3", "CPURatio", cpuRatio); + msg->getString ("RegionInfo3", "ColoName", coloName); + msg->getString ("RegionInfo3", "ProductSKU", productSKU); + msg->getString ("RegionInfo3", "ProductName", productName); + + mClassID = classID; + mCPURatio = cpuRatio; + mColoName = coloName; + mProductSKU = productSKU; + mProductName = productName; + } LLVLComposition *compp = getComposition(); if (compp) @@ -1420,6 +1426,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("ServerReleaseNotes"); capabilityNames.append("StartGroupProposal"); capabilityNames.append("UntrustedSimulatorMessage"); + capabilityNames.append("UpdateAgentInformation"); capabilityNames.append("UpdateAgentLanguage"); capabilityNames.append("UpdateGestureAgentInventory"); capabilityNames.append("UpdateNotecardAgentInventory"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 6b71ea07bb..b0a98a99b8 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -182,18 +182,24 @@ public: void setSimAccess(U8 sim_access) { mSimAccess = sim_access; } U8 getSimAccess() const { return mSimAccess; } const std::string getSimAccessString() const; + + // Homestead-related getters; there are no setters as nobody should be + // setting them other than the individual message handler which is a member + S32 getSimClassID() const { return mClassID; } + S32 getSimCPURatio() const { return mCPURatio; } + const std::string& getSimColoName() const { return mColoName; } + const std::string& getSimProductSKU() const { return mProductSKU; } + const std::string& getSimProductName() const { return mProductName; } // Returns "Sandbox", "Expensive", etc. static std::string regionFlagsToString(U32 flags); - // Returns "Mature", "PG", etc. + // Returns translated version of "Mature", "PG", "Adult", etc. static std::string accessToString(U8 sim_access); - static U8 stringToAccess(const std::string& access_str); - - // Returns "M", "PG", etc. + // Returns "M", "PG", "A" etc. static std::string accessToShortString(U8 sim_access); - + // helper function which just makes sure all interested parties // can process the message. static void processRegionInfo(LLMessageSystem* msg, void**); @@ -357,6 +363,14 @@ private: U32 mMaxTasks; // max prim count F32 mCameraDistanceSquared; // updated once per frame + // Information for Homestead / CR-53 + S32 mClassID; + S32 mCPURatio; + std::string mColoName; + std::string mProductSKU; + std::string mProductName; + + // Maps local ids to cache entries. // Regions can have order 10,000 objects, so assume // a structure of size 2^14 = 16,000 diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 44d9a72868..71406d268d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2450,9 +2450,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } } - // Debugging view for unified notifications + // Debugging view for unified notifications -- we need Ctrl+Shift+Alt to get it + // since Ctrl+Shift maps to Nighttime under windlight. if ((MASK_SHIFT & mask) && (MASK_CONTROL & mask) + && (MASK_ALT & mask) && ('N' == key || 'n' == key)) { LLFloaterNotificationConsole::showInstance(); diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index c9a3bd2112..572f31f566 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -186,6 +186,7 @@ void LLWorldMap::eraseItems() mInfohubs.clear(); mPGEvents.clear(); mMatureEvents.clear(); + mAdultEvents.clear(); mLandForSale.clear(); } // mAgentLocationsMap.clear(); // persists @@ -311,11 +312,23 @@ void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) sendItemRequest(MAP_ITEM_MATURE_EVENT); } + if (mAdultEvents.size() == 0) + { + // Request for events (adult) + sendItemRequest(MAP_ITEM_ADULT_EVENT); + } + if (mLandForSale.size() == 0) { // Request for Land For Sale sendItemRequest(MAP_ITEM_LAND_FOR_SALE); } + + if (mLandForSaleAdult.size() == 0) + { + // Request for Land For Sale + sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT); + } clearImageRefs(); clearSimFlags(); @@ -742,6 +755,7 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) } case MAP_ITEM_PG_EVENT: // events case MAP_ITEM_MATURE_EVENT: + case MAP_ITEM_ADULT_EVENT: { struct tm* timep; // Convert to Pacific, based on server's opinion of whether @@ -762,16 +776,29 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) { LLWorldMap::getInstance()->mPGEvents.push_back(new_item); } - else + else if (type == MAP_ITEM_MATURE_EVENT) { LLWorldMap::getInstance()->mMatureEvents.push_back(new_item); } + else if (type == MAP_ITEM_ADULT_EVENT) + { + LLWorldMap::getInstance()->mAdultEvents.push_back(new_item); + } + break; } case MAP_ITEM_LAND_FOR_SALE: // land for sale + case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale { new_item.mToolTip = llformat("%d sq. m. L$%d", new_item.mExtra, new_item.mExtra2); - LLWorldMap::getInstance()->mLandForSale.push_back(new_item); + if (type == MAP_ITEM_LAND_FOR_SALE) + { + LLWorldMap::getInstance()->mLandForSale.push_back(new_item); + } + else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT) + { + LLWorldMap::getInstance()->mLandForSaleAdult.push_back(new_item); + } break; } case MAP_ITEM_CLASSIFIED: // classifieds diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index 423af6a289..6ce66ffab0 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -192,7 +192,9 @@ public: item_info_list_t mInfohubs; item_info_list_t mPGEvents; item_info_list_t mMatureEvents; + item_info_list_t mAdultEvents; item_info_list_t mLandForSale; + item_info_list_t mLandForSaleAdult; std::map<U64,S32> mNumAgents; diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 9ff94751d0..7f8f4cc026 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -83,12 +83,14 @@ LLUIImagePtr LLWorldMapView::sInfohubImage = NULL; LLUIImagePtr LLWorldMapView::sHomeImage = NULL; LLUIImagePtr LLWorldMapView::sEventImage = NULL; LLUIImagePtr LLWorldMapView::sEventMatureImage = NULL; +LLUIImagePtr LLWorldMapView::sEventAdultImage = NULL; LLUIImagePtr LLWorldMapView::sTrackCircleImage = NULL; LLUIImagePtr LLWorldMapView::sTrackArrowImage = NULL; LLUIImagePtr LLWorldMapView::sClassifiedsImage = NULL; LLUIImagePtr LLWorldMapView::sForSaleImage = NULL; +LLUIImagePtr LLWorldMapView::sForSaleAdultImage = NULL; F32 LLWorldMapView::sThresholdA = 48.f; F32 LLWorldMapView::sThresholdB = 96.f; @@ -125,11 +127,15 @@ void LLWorldMapView::initClass() sInfohubImage = LLUI::getUIImage("map_infohub.tga"); sEventImage = LLUI::getUIImage("map_event.tga"); sEventMatureImage = LLUI::getUIImage("map_event_mature.tga"); + // To Do: update the image resource for adult events. + sEventAdultImage = LLUI::getUIImage("map_event_adult.tga"); sTrackCircleImage = LLUI::getUIImage("map_track_16.tga"); sTrackArrowImage = LLUI::getUIImage("direction_arrow.tga"); sClassifiedsImage = LLUI::getUIImage("icon_top_pick.tga"); sForSaleImage = LLUI::getUIImage("icon_for_sale.tga"); + // To Do: update the image resource for adult lands on sale. + sForSaleAdultImage = LLUI::getUIImage("icon_for_sale_adult.tga"); sStringsMap["loading"] = LLTrans::getString("texture_loading"); sStringsMap["offline"] = LLTrans::getString("worldmap_offline"); @@ -149,11 +155,13 @@ void LLWorldMapView::cleanupClass() sHomeImage = NULL; sEventImage = NULL; sEventMatureImage = NULL; + sEventAdultImage = NULL; sTrackCircleImage = NULL; sTrackArrowImage = NULL; sClassifiedsImage = NULL; sForSaleImage = NULL; + sForSaleAdultImage = NULL; } LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) @@ -332,12 +340,11 @@ void LLWorldMapView::draw() } LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx]; LLViewerImage *current_image = layer->LayerImage; -#if 1 || LL_RELEASE_FOR_DOWNLOAD + if (current_image->isMissingAsset()) { continue; // better to draw nothing than the missing asset image } -#endif LLVector3d origin_global((F64)layer->LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer->LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f); @@ -419,7 +426,7 @@ void LLWorldMapView::draw() gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); -#if 1 + // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code? F32 sim_alpha = 1.f; // Draw one image per region, centered on the camera position. @@ -633,7 +640,11 @@ void LLWorldMapView::draw() gGL.end(); } - // If this is mature, and you are not, draw a line across it + // As part of the AO project, we no longer want to draw access indicators; + // it's too complicated to get all the rules straight and will only + // cause confusion. + /********************** + // If this is mature, and you are not, draw a line across it if (info->mAccess != SIM_ACCESS_DOWN && info->mAccess > SIM_ACCESS_PG && gAgent.isTeen()) @@ -649,6 +660,7 @@ void LLWorldMapView::draw() gGL.vertex2f(right, top); gGL.end(); } + **********************/ // Draw the region name in the lower left corner LLFontGL* font = LLFontGL::getFontSansSerifSmall(); @@ -705,10 +717,10 @@ void LLWorldMapView::draw() } } } -#endif + // #endif used to be here -#if 1 + // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code? // Draw background rectangle LLGLSUIDefault gls_ui; { @@ -744,8 +756,15 @@ void LLWorldMapView::draw() if (gSavedSettings.getBOOL("MapShowLandForSale")) { drawGenericItems(LLWorldMap::getInstance()->mLandForSale, sForSaleImage); + // for 1.23, we're showing normal land and adult land in the same UI; you don't + // get a choice about which ones you want. If you're currently asking for adult + // content and land you'll get the adult land. + if (gAgent.canAccessAdult()) + { + drawGenericItems(LLWorldMap::getInstance()->mLandForSaleAdult, sForSaleAdultImage); + } } - + if (gSavedSettings.getBOOL("MapShowEvents")) { drawEvents(); @@ -809,7 +828,7 @@ void LLWorldMapView::draw() drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Loading...", ""); } } -#endif + // #endif used to be here // turn off the scissor LLGLDisable no_scissor(GL_SCISSOR_TEST); @@ -943,7 +962,11 @@ void LLWorldMapView::drawAgents() void LLWorldMapView::drawEvents() { - BOOL show_mature = gSavedSettings.getBOOL("ShowMatureEvents"); + bool mature_enabled = gAgent.canAccessMature(); + bool adult_enabled = gAgent.canAccessAdult(); + + BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents"); + BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents"); // First the non-selected events LLWorldMap::item_info_list_t::const_iterator e; @@ -964,7 +987,16 @@ void LLWorldMapView::drawEvents() } } } - + if (show_adult) + { + for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e) + { + if (!e->mSelected) + { + drawGenericItem(*e, sEventAdultImage); + } + } + } // Then the selected events for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e) { @@ -983,6 +1015,16 @@ void LLWorldMapView::drawEvents() } } } + if (show_adult) + { + for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e) + { + if (e->mSelected) + { + drawGenericItem(*e, sEventAdultImage); + } + } + } } @@ -1572,6 +1614,10 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, { (*it).mSelected = FALSE; } + for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) + { + (*it).mSelected = FALSE; + } for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) { (*it).mSelected = FALSE; @@ -1607,6 +1653,21 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, } } } + if (gSavedSettings.getBOOL("ShowAdultEvents")) + { + for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) + { + LLItemInfo& event = *it; + + if (checkItemHit(x, y, event, id, false)) + { + *hit_type = MAP_ITEM_ADULT_EVENT; + mItemPicked = TRUE; + gFloaterWorldMap->trackEvent(event); + return; + } + } + } } if (gSavedSettings.getBOOL("MapShowLandForSale")) @@ -1622,8 +1683,19 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, return; } } - } + + for (it = LLWorldMap::getInstance()->mLandForSaleAdult.begin(); it != LLWorldMap::getInstance()->mLandForSaleAdult.end(); ++it) + { + LLItemInfo& land = *it; + if (checkItemHit(x, y, land, id, true)) + { + *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT; + mItemPicked = TRUE; + return; + } + } + } // If we get here, we haven't clicked on an icon gFloaterWorldMap->trackLocation(pos_global); @@ -1803,6 +1875,7 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) { case MAP_ITEM_PG_EVENT: case MAP_ITEM_MATURE_EVENT: + case MAP_ITEM_ADULT_EVENT: { gFloaterWorldMap->close(); // This is an ungainly hack @@ -1815,6 +1888,7 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) break; } case MAP_ITEM_LAND_FOR_SALE: + case MAP_ITEM_LAND_FOR_SALE_ADULT: { gFloaterWorldMap->close(); LLFloaterDirectory::showLandForSale(id); diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 980ddf9c73..1717b76beb 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -148,10 +148,12 @@ public: static LLUIImagePtr sHomeImage; static LLUIImagePtr sEventImage; static LLUIImagePtr sEventMatureImage; + static LLUIImagePtr sEventAdultImage; static LLUIImagePtr sTrackCircleImage; static LLUIImagePtr sTrackArrowImage; static LLUIImagePtr sClassifiedsImage; static LLUIImagePtr sForSaleImage; + static LLUIImagePtr sForSaleAdultImage; static F32 sThresholdA; static F32 sThresholdB; diff --git a/indra/newview/skins/default/textures/icon_event_adult.tga b/indra/newview/skins/default/textures/icon_event_adult.tga Binary files differnew file mode 100644 index 0000000000..c344fb1e78 --- /dev/null +++ b/indra/newview/skins/default/textures/icon_event_adult.tga diff --git a/indra/newview/skins/default/textures/icon_for_sale_adult.tga b/indra/newview/skins/default/textures/icon_for_sale_adult.tga Binary files differnew file mode 100644 index 0000000000..6a99188f87 --- /dev/null +++ b/indra/newview/skins/default/textures/icon_for_sale_adult.tga diff --git a/indra/newview/skins/default/textures/map_event_adult.tga b/indra/newview/skins/default/textures/map_event_adult.tga Binary files differnew file mode 100644 index 0000000000..c344fb1e78 --- /dev/null +++ b/indra/newview/skins/default/textures/map_event_adult.tga diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp new file mode 100644 index 0000000000..fc18f10e7d --- /dev/null +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -0,0 +1,234 @@ +/** + * @file llagentaccess_test.cpp + * @brief LLAgentAccess tests + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * Copyright (c) 2001-2009, Linden Research, Inc. + * $/LicenseInfo$ + */ +#include "../test/lltut.h" + +#include "../llagentaccess.h" + +#include "llcontrolgroupreader.h" +#include "indra_constants.h" + +#include <iostream> + +class LLControlGroupReader_Test : public LLControlGroupReader +{ +public: + LLControlGroupReader_Test() : test_preferred_maturity(SIM_ACCESS_PG) {} + + virtual std::string getString(const std::string& name) + { + return ""; + } + virtual std::string getText(const std::string& name) + { + return ""; + } + virtual BOOL getBOOL(const std::string& name) + { + return false; + } + virtual S32 getS32(const std::string& name) + { + return 0; + } + virtual F32 getF32(const std::string& name) + { + return 0; + } + virtual U32 getU32(const std::string& name) + { + return test_preferred_maturity; + } + + //-------------------------------------- + // Everything from here down is test code and not part of the interface + void setPreferredMaturity(U32 m) + { + test_preferred_maturity = m; + } +private: + U32 test_preferred_maturity; + +}; + +namespace tut +{ + struct agentaccess + { + }; + + typedef test_group<agentaccess> agentaccess_t; + typedef agentaccess_t::object agentaccess_object_t; + tut::agentaccess_t tut_agentaccess("agentaccess"); + + template<> template<> + void agentaccess_object_t::test<1>() + { + LLControlGroupReader_Test cgr; + LLAgentAccess aa(cgr); + + cgr.setPreferredMaturity(SIM_ACCESS_PG); + ensure("1 prefersPG", aa.prefersPG()); + ensure("1 prefersMature", !aa.prefersMature()); + ensure("1 prefersAdult", !aa.prefersAdult()); + + cgr.setPreferredMaturity(SIM_ACCESS_MATURE); + ensure("2 prefersPG", !aa.prefersPG()); + ensure("2 prefersMature", aa.prefersMature()); + ensure("2 prefersAdult", !aa.prefersAdult()); + + cgr.setPreferredMaturity(SIM_ACCESS_ADULT); + ensure("3 prefersPG", !aa.prefersPG()); + ensure("3 prefersMature", aa.prefersMature()); + ensure("3 prefersAdult", aa.prefersAdult()); + } + + template<> template<> + void agentaccess_object_t::test<2>() + { + LLControlGroupReader_Test cgr; + LLAgentAccess aa(cgr); + + // make sure default is PG + ensure("1 isTeen", aa.isTeen()); + ensure("1 isMature", !aa.isMature()); + ensure("1 isAdult", !aa.isAdult()); + + // this is kinda bad -- setting this forces maturity to MATURE but !teen != Mature anymore + aa.setTeen(false); + ensure("2 isTeen", !aa.isTeen()); + ensure("2 isMature", aa.isMature()); + ensure("2 isAdult", !aa.isAdult()); + + // have to flip it back and make sure it still works + aa.setTeen(true); + ensure("3 isTeen", aa.isTeen()); + ensure("3 isMature", !aa.isMature()); + ensure("3 isAdult", !aa.isAdult()); + + // check the conversion routine + ensure_equals("1 conversion", SIM_ACCESS_PG, aa.convertTextToMaturity('P')); + ensure_equals("2 conversion", SIM_ACCESS_MATURE, aa.convertTextToMaturity('M')); + ensure_equals("3 conversion", SIM_ACCESS_ADULT, aa.convertTextToMaturity('A')); + ensure_equals("4 conversion", SIM_ACCESS_MIN, aa.convertTextToMaturity('Q')); + + // now try the other method of setting it - PG + aa.setMaturity('P'); + ensure("4 isTeen", aa.isTeen()); + ensure("4 isMature", !aa.isMature()); + ensure("4 isAdult", !aa.isAdult()); + + // Mature + aa.setMaturity('M'); + ensure("5 isTeen", !aa.isTeen()); + ensure("5 isMature", aa.isMature()); + ensure("5 isAdult", !aa.isAdult()); + + // Adult + aa.setMaturity('A'); + ensure("6 isTeen", !aa.isTeen()); + ensure("6 isMature", aa.isMature()); + ensure("6 isAdult", aa.isAdult()); + + } + + template<> template<> + void agentaccess_object_t::test<3>() + { + LLControlGroupReader_Test cgr; + LLAgentAccess aa(cgr); + + ensure("starts normal", !aa.isGodlike()); + aa.setGodLevel(GOD_NOT); + ensure("stays normal", !aa.isGodlike()); + aa.setGodLevel(GOD_FULL); + ensure("sets full", aa.isGodlike()); + aa.setGodLevel(GOD_NOT); + ensure("resets normal", !aa.isGodlike()); + aa.setAdminOverride(true); + ensure("admin true", aa.getAdminOverride()); + ensure("overrides 1", aa.isGodlike()); + aa.setGodLevel(GOD_FULL); + ensure("overrides 2", aa.isGodlike()); + aa.setAdminOverride(false); + ensure("admin false", !aa.getAdminOverride()); + ensure("overrides 3", aa.isGodlike()); + } + + template<> template<> + void agentaccess_object_t::test<4>() + { + LLControlGroupReader_Test cgr; + LLAgentAccess aa(cgr); + + ensure("1 pg to start", aa.wantsPGOnly()); + ensure("2 pg to start", !aa.canAccessMature()); + ensure("3 pg to start", !aa.canAccessAdult()); + + aa.setGodLevel(GOD_FULL); + ensure("1 full god", !aa.wantsPGOnly()); + ensure("2 full god", aa.canAccessMature()); + ensure("3 full god", aa.canAccessAdult()); + + aa.setGodLevel(GOD_NOT); + aa.setAdminOverride(true); + ensure("1 admin mode", !aa.wantsPGOnly()); + ensure("2 admin mode", aa.canAccessMature()); + ensure("3 admin mode", aa.canAccessAdult()); + + aa.setAdminOverride(false); + aa.setMaturity('M'); + // preferred is still pg by default + ensure("1 mature pref pg", aa.wantsPGOnly()); + ensure("2 mature pref pg", !aa.canAccessMature()); + ensure("3 mature pref pg", !aa.canAccessAdult()); + + cgr.setPreferredMaturity(SIM_ACCESS_MATURE); + ensure("1 mature", !aa.wantsPGOnly()); + ensure("2 mature", aa.canAccessMature()); + ensure("3 mature", !aa.canAccessAdult()); + + cgr.setPreferredMaturity(SIM_ACCESS_PG); + ensure("1 mature pref pg", aa.wantsPGOnly()); + ensure("2 mature pref pg", !aa.canAccessMature()); + ensure("3 mature pref pg", !aa.canAccessAdult()); + + aa.setMaturity('A'); + ensure("1 adult pref pg", aa.wantsPGOnly()); + ensure("2 adult pref pg", !aa.canAccessMature()); + ensure("3 adult pref pg", !aa.canAccessAdult()); + + cgr.setPreferredMaturity(SIM_ACCESS_ADULT); + ensure("1 adult", !aa.wantsPGOnly()); + ensure("2 adult", aa.canAccessMature()); + ensure("3 adult", aa.canAccessAdult()); + + // make sure that even if pref is high, if access is low we block access + // this shouldn't occur in real life but we want to be safe + cgr.setPreferredMaturity(SIM_ACCESS_ADULT); + aa.setMaturity('P'); + ensure("1 pref adult, actual pg", aa.wantsPGOnly()); + ensure("2 pref adult, actual pg", !aa.canAccessMature()); + ensure("3 pref adult, actual pg", !aa.canAccessAdult()); + + } + + template<> template<> + void agentaccess_object_t::test<5>() + { + LLControlGroupReader_Test cgr; + LLAgentAccess aa(cgr); + + ensure("1 transition starts false", !aa.isInTransition()); + aa.setTransition(); + ensure("2 transition now true", aa.isInTransition()); + } + +} + + diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index c6d42cf882..22752ef33c 100644 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -723,6 +723,10 @@ version 2.0 { Auction BOOL } { Dwell F32 } } + { + StatusData Variable + { Status U32 } + } } // DirPeopleReply @@ -767,6 +771,10 @@ version 2.0 { UnixTime U32 } { EventFlags U32 } } + { + StatusData Variable + { Status U32 } + } } // DirGroupsReply @@ -852,6 +860,10 @@ version 2.0 { ExpirationDate U32 } { PriceForListing S32 } } + { + StatusData Variable + { Status U32 } + } } @@ -1465,7 +1477,7 @@ version 2.0 } } -// TeleportFailed somehwere->sim->viewer +// TeleportFailed somewhere->sim->viewer // announce failure of teleport request { TeleportFailed Low 74 Trusted Unencoded @@ -1474,6 +1486,11 @@ version 2.0 { AgentID LLUUID } { Reason Variable 1 } // string } + { + AlertInfo Variable + { Message Variable 1 } // string id + { ExtraParams Variable 1 } // llsd extra parameters + } } @@ -2810,6 +2827,11 @@ version 2.0 AlertData Single { Message Variable 1 } } + { + AlertInfo Variable + { Message Variable 1 } + { ExtraParams Variable 1 } + } } // Send an AlertMessage to the named agent. |