aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/rlvhelper.h
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/rlvhelper.h')
-rw-r--r--linden/indra/newview/rlvhelper.h579
1 files changed, 579 insertions, 0 deletions
diff --git a/linden/indra/newview/rlvhelper.h b/linden/indra/newview/rlvhelper.h
new file mode 100644
index 0000000..a0e040e
--- /dev/null
+++ b/linden/indra/newview/rlvhelper.h
@@ -0,0 +1,579 @@
1#ifndef RLV_HELPER_H
2#define RLV_HELPER_H
3
4#include "llboost.h"
5#include "llinventorymodel.h"
6#include "llselectmgr.h"
7#include "llviewercontrol.h"
8#include "llviewerobjectlist.h"
9#include "llwlparamset.h"
10
11#include "rlvmultistringsearch.h"
12
13// ============================================================================
14// Extensions
15//
16
17// Comment out if you don't want the Advanced / RLVa menu (may prevent enabling some extensions or experimental features - see below)
18#define RLV_ADVANCED_MENU
19// Comment out if you provide your own way to enable/disable RLVa
20#define RLV_ADVANCED_TOGGLE_RLVA
21
22// Provides access to "advanced" feature through the RLVa debug menu
23#define RLV_EXTENSION_ENABLE_WEAR // "Enable Wear"
24#define RLV_EXTENSION_HIDELOCKED // "Hide locked layers", "Hide locked attachments" and "Hide locked inventory"
25#define RLV_EXTENSION_FLOATER_RESTRICTIONS // Enables the Advanced / RLVa / Restrictions... floater
26
27// Extensions
28#define RLV_EXTENSION_CMD_GETSETDEBUG_EX // Extends the debug variables accessible through @getdebug_xxx/@setdebug_xxx
29#define RLV_EXTENSION_CMD_FINDFOLDERS // @findfolders:<option>=<channel> - @findfolder with multiple results
30#define RLV_EXTENSION_FLAG_NOSTRIP // Layers and attachments marked as "nostrip" are exempt from @detach/@remoutfit
31#define RLV_EXTENSION_STARTLOCATION // Reenables "Start Location" at login if not @tploc=n or @unsit=n restricted at last logoff
32#define RLV_EXPERIMENTAL // Enables/disables experimental features en masse
33
34// Experimental features
35#ifdef RLV_EXPERIMENTAL
36 // Stable (will mature to RLV_EXTENSION_XXX in next release if no bugs are found)
37 #define RLV_EXPERIMENTAL_FARTOUCH_FEEDBACK // Enables "cleaner" UI responses when fartouch blocks something
38
39 // Under testing (stable, but requires further testing - safe for public release but may be quirky)
40
41 // Under development (don't include in public release)
42 #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
43 #endif // LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
44#endif // RLV_EXPERIMENTAL
45
46// ============================================================================
47// Defines
48//
49
50// Version of the specifcation we support
51const S32 RLV_VERSION_MAJOR = 1;
52const S32 RLV_VERSION_MINOR = 20;
53const S32 RLV_VERSION_PATCH = 0;
54
55// Implementation version
56const S32 RLVa_VERSION_MAJOR = 1;
57const S32 RLVa_VERSION_MINOR = 0;
58const S32 RLVa_VERSION_PATCH = 1;
59const S32 RLVa_VERSION_BUILD = 7;
60
61// The official viewer version we're patching against
62#define RLV_MAKE_TARGET(x, y, z) ((x << 16) | (y << 8) | z)
63#define RLV_TARGET RLV_MAKE_TARGET(1, 22, 11)
64
65// Defining these makes it easier if we ever need to change our tag
66#define RLV_WARNS LL_WARNS("RLV")
67#define RLV_INFOS LL_INFOS("RLV")
68#define RLV_DEBUGS LL_DEBUGS("RLV")
69
70#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
71 // Turn on extended debugging information
72 #define RLV_DEBUG
73 // Make sure we halt execution on errors
74 #define RLV_ERRS LL_ERRS("RLV")
75 // Uncomment to enable the Advanced / RLVa / Unit Tests menu (non-public)
76 //#define RLV_DEBUG_TESTS
77#else
78 // Uncomment if you want extended debugging information on release builds
79 //#define RLV_DEBUG
80 // Don't halt execution on errors in release
81 #define RLV_ERRS LL_WARNS("RLV")
82#endif // LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
83
84#define RLV_ROOT_FOLDER "#RLV"
85#define RLV_CMD_PREFIX '@'
86#define RLV_PUTINV_PREFIX "#RLV/~"
87#define RLV_SETROT_OFFSET F_PI_BY_TWO // @setrot is off by 90° with the rest of SL
88
89#define RLV_FOLDER_FLAG_NOSTRIP "nostrip"
90#define RLV_FOLDER_PREFIX_HIDDEN '.'
91#define RLV_FOLDER_PREFIX_PUTINV '~'
92
93// ============================================================================
94// Enumeration declarations
95//
96
97// NOTE: * any changes to this enumeration should be reflected in initLookupTable()
98// * only uncomment the ones we actually use in a switch() to keep the size of the lookup table down
99enum ERlvBehaviour {
100 RLV_BHVR_VERSION = 0, // "version"
101 RLV_BHVR_DETACH, // "detach"
102// RLV_BHVR_SENDCHAT, // "sendchat"
103// RLV_BHVR_EMOTE, // "emote"
104// RLV_BHVR_CHATSHOUT, // "chatshout"
105// RLV_BHVR_CHATNORMAL, // "chatnormal"
106// RLV_BHVR_CHATWHISPER, // "chatwhisper"
107 RLV_BHVR_REDIRCHAT, // "redirchat"
108 RLV_BHVR_REDIREMOTE, // "rediremote"
109 RLV_BHVR_SENDIM, // "sendim"
110 RLV_BHVR_RECVCHAT, // "recvchat"
111 RLV_BHVR_RECVEMOTE, // "recvemote"
112 RLV_BHVR_RECVIM, // "recvim"
113// RLV_BHVR_TPLM, // "tplm"
114 RLV_BHVR_TPLOC, // "tploc"
115 RLV_BHVR_TPLURE, // "tplure"
116 RLV_BHVR_SITTP, // "sittp"
117// RLV_BHVR_CLEAR, // "clear"
118 RLV_BHVR_EDIT, // "edit"
119 RLV_BHVR_REZ, // "rez"
120 RLV_BHVR_ADDOUTFIT, // "addoutfit"
121 RLV_BHVR_REMOUTFIT, // "remoutfit"
122 RLV_BHVR_GETOUTFIT, // "getoutfit"
123 RLV_BHVR_GETATTACH, // "getattach"
124 RLV_BHVR_SHOWINV, // "showinv"
125// RLV_BHVR_VIEWNOTE, // "viewnote"
126 RLV_BHVR_UNSIT, // "unsit"
127 RLV_BHVR_SIT, // "sit"
128// RLV_BHVR_SENDCHANNEL, // "sendchannel"
129 RLV_BHVR_GETSTATUS, // "getstatus"
130 RLV_BHVR_GETSTATUSALL, // "getstatusall"
131 RLV_BHVR_GETINV, // "getinv"
132 RLV_BHVR_GETINVWORN, // "getinvworn"
133 RLV_BHVR_FINDFOLDER, // "findfolder"
134 RLV_BHVR_FINDFOLDERS, // "findfolders"
135 RLV_BHVR_ATTACH, // "attach"
136 RLV_BHVR_ATTACHALL, // "attachall"
137 RLV_BHVR_DETACHALL, // "detachall"
138 RLV_BHVR_GETPATH, // "getpath"
139 RLV_BHVR_ATTACHTHIS, // "attachthis"
140 RLV_BHVR_ATTACHALLTHIS, // "attachallthis"
141 RLV_BHVR_DETACHTHIS, // "detachthis"
142 RLV_BHVR_DETACHALLTHIS, // "detachallthis"
143 RLV_BHVR_FARTOUCH, // "fartouch"
144 RLV_BHVR_SHOWWORLDMAP, // "showworldmap"
145 RLV_BHVR_SHOWMINIMAP, // "showminimap"
146 RLV_BHVR_SHOWLOC, // "showloc"
147 RLV_BHVR_TPTO, // "tpto"
148 RLV_BHVR_ACCEPTTP, // "accepttp"
149 RLV_BHVR_SHOWNAMES, // "shownames"
150 RLV_BHVR_FLY, // "fly"
151 RLV_BHVR_GETSITID, // "getsitid"
152 RLV_BHVR_SETDEBUG, // "setdebug"
153 RLV_BHVR_SETENV, // "setenv"
154 RLV_BHVR_DETACHME, // "detachme"
155 RLV_BHVR_SHOWHOVERTEXTALL, // "showhovertextall"
156 RLV_BHVR_SHOWHOVERTEXTWORLD, // "showhovertextworld"
157 RLV_BHVR_SHOWHOVERTEXTHUD, // "showhovertexthud"
158 RLV_BHVR_SHOWHOVERTEXT, // "showhovertext"
159 RLV_BHVR_NOTIFY, // "notify"
160
161 RLV_BHVR_COUNT,
162 RLV_BHVR_UNKNOWN
163};
164
165enum ERlvParamType {
166 RLV_TYPE_UNKNOWN,
167 RLV_TYPE_ADD, // <param> == "n"|"add"
168 RLV_TYPE_REMOVE, // <param> == "y"|"rem"
169 RLV_TYPE_FORCE, // <param> == "force"
170 RLV_TYPE_REPLY // <param> == <number>
171};
172
173enum ERlvCmdRet {
174 RLV_RET_NOERROR, // Command executed succesfully
175 RLV_RET_RETAINED, // Command was retained
176 RLV_RET_FAILED, // Command failed (general failure)
177 RLV_RET_FAILED_SYNTAX, // Command failed (syntax error)
178 RLV_RET_FAILED_UNSET, // Command failed (unset restriction)
179 RLV_RET_FAILED_DUPLICATE, // Command failed (duplicate)
180 RLV_RET_FAILED_OPTION, // Command failed (invalid option)
181 RLV_RET_UNKNOWN // Command unkown
182};
183
184// ============================================================================
185/*
186 * RlvCommand
187 * ==========
188 * Encapsulates an "RLV command" (duh :p)
189 *
190 */
191
192class RlvCommand
193{
194public:
195 /*
196 * Constructors
197 */
198 explicit RlvCommand(const std::string& strCommand);
199 RlvCommand(const RlvCommand& rlvCmd);
200
201 /*
202 * Accessors
203 */
204 BOOL isValid() const { return m_fValid; }
205
206 const std::string& getBehaviour() const { return m_strBehaviour; }
207 ERlvBehaviour getBehaviourType() const { return m_eBehaviour; }
208 const std::string& getOption() const { return m_strOption; }
209 const std::string& getParam() const { return m_strParam; }
210 ERlvParamType getParamType() const { return m_eParamType; }
211
212 std::string asString() const;
213
214 /*
215 * Operators
216 */
217 bool operator ==(const RlvCommand&) const;
218
219 // Parses an RLV command into its "tokens"
220 static BOOL parseCommand(/*[in]*/ const std::string& strCommand,
221 /*[out]*/ std::string& strBehaviour, /*[out]*/ std::string& strOption, /*[out]*/ std::string& strParam);
222 static void initLookupTable();
223
224 /*
225 * Member variables
226 */
227protected:
228 BOOL m_fValid;
229 std::string m_strBehaviour;
230 ERlvBehaviour m_eBehaviour;
231 std::string m_strOption;
232 std::string m_strParam;
233 ERlvParamType m_eParamType;
234
235 static RlvMultiStringSearch m_BhvrLookup;
236 friend class RlvHandler;
237};
238
239// ============================================================================
240/*
241 * RlvObject
242 * =========
243 * Encapsulates an "RLV Object" (= an object that has issued an RLV command)
244 *
245 */
246
247typedef std::list<RlvCommand> rlv_command_list_t;
248
249class RlvObject
250{
251public:
252 RlvObject(const LLUUID& uuid) : m_UUID(uuid), m_nLookupMisses(0) { m_fLookup = (NULL != gObjectList.findObject(uuid)); }
253
254 BOOL addCommand(const RlvCommand& rlvCmd);
255 BOOL removeCommand(const RlvCommand& rlvCmd);
256
257 BOOL hasBehaviour(ERlvBehaviour eBehaviour) const;
258 BOOL hasBehaviour(const std::string& strBehaviour) const;
259 BOOL hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const;
260 BOOL hasBehaviour(const std::string& strBehaviour, const std::string& strOption) const;
261
262 std::string getStatusString(const std::string& strMatch) const;
263
264 const rlv_command_list_t* getCommandList() const { return &m_Commands; }
265protected:
266 LLUUID m_UUID; // The object's UUID
267 bool m_fLookup; // TRUE if the object existed in gObjectList at one point in time
268 S16 m_nLookupMisses; // Count of unsuccessful lookups in gObjectList by the GC
269 rlv_command_list_t m_Commands; // List of behaviours held by this object (in the order they were received)
270
271 friend class RlvHandler;
272};
273
274// ============================================================================
275/*
276 * RlvCriteriaCategoryCollector
277 * ============================
278 * Criteria based folder matching filter used by @findfolder and @findfolders
279 *
280 */
281
282class RlvCriteriaCategoryCollector : public LLInventoryCollectFunctor
283{
284public:
285 RlvCriteriaCategoryCollector(const std::string& strCriteria)
286 {
287 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
288 boost::char_separator<char> sep("&&", "", boost::drop_empty_tokens);
289 tokenizer tokens(strCriteria, sep);
290 for (tokenizer::iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken)
291 m_Criteria.push_back(*itToken);
292 }
293 virtual ~RlvCriteriaCategoryCollector() {}
294
295 virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem)
296 {
297 if ( (!pFolder) || (m_Criteria.empty()) ) // We're only interested in matching folders, we don't care about items
298 return false; // (if there are no criteria then we don't want to return a match)
299
300 std::string strFolderName = pFolder->getName();
301 LLStringUtil::toLower(strFolderName);
302
303 if ( (strFolderName.empty()) || (RLV_FOLDER_PREFIX_HIDDEN == strFolderName[0]) )
304 return false;
305
306 for (std::list<std::string>::const_iterator itCrit = m_Criteria.begin(); itCrit != m_Criteria.end(); ++itCrit)
307 if (-1 == strFolderName.find(*itCrit)) // Return false on the first mismatch
308 return false;
309 return true;
310 }
311
312protected:
313 std::list<std::string> m_Criteria;
314};
315
316// ============================================================================
317/*
318 * RlvWearableItemCollector
319 * ========================
320 * Inventory item filter used by attach/detach/attachall/detachall/getinvworn (also used by "Add/Replace Outfit" and "Take Off Items")
321 *
322 */
323
324class RlvWearableItemCollector : public LLInventoryCollectFunctor
325{
326public:
327 RlvWearableItemCollector(const LLUUID& idFolder, bool fAttach, bool fMatchAll)
328 : m_idFolder(idFolder), m_fAttach(fAttach), m_fMatchAll(fMatchAll)
329 {
330 m_Wearable.push_back(idFolder);
331 }
332 virtual ~RlvWearableItemCollector() {}
333
334 virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem);
335
336 const LLUUID& getFoldedParent(const LLUUID& idFolder) const;
337protected:
338 bool m_fAttach;
339 bool m_fMatchAll;
340 const LLUUID m_idFolder;
341
342 bool onCollectFolder(const LLInventoryCategory* pFolder);
343 bool onCollectItem(const LLInventoryItem* pItem);
344
345 std::list<LLUUID> m_Tentative;
346 std::list<LLUUID> m_Wearable;
347
348 std::map<LLUUID, LLUUID> m_Folding;
349};
350
351// ============================================================================
352/*
353 * RlvRetainedCommand
354 * ==================
355 *
356 */
357
358struct RlvRetainedCommand
359{
360public:
361 std::string strObject;
362 LLUUID idObject;
363 std::string strCmd;
364
365 RlvRetainedCommand(const std::string obj, const LLUUID& uuid, const std::string& cmd) : strObject(obj), idObject(uuid), strCmd(cmd) {}
366private:
367 RlvRetainedCommand();
368};
369typedef std::list<RlvRetainedCommand> rlv_retained_list_t;
370
371// ============================================================================
372/*
373 * RlvWLSnapshot
374 * =============
375 *
376 */
377
378struct RlvWLSnapshot
379{
380public:
381 static void restoreSnapshot(const RlvWLSnapshot* pWLSnapshot);
382 static RlvWLSnapshot* takeSnapshot();
383private:
384 RlvWLSnapshot() {}
385
386 bool fIsRunning;
387 bool fUseLindenTime;
388 LLWLParamSet WLParams;
389};
390
391// ============================================================================
392/*
393 * RlvSettings
394 * ===========
395 *
396 */
397
398#define RLV_SETTING_MAIN "RestrainedLife"
399#define RLV_SETTING_DEBUG "RestrainedLifeDebug"
400#define RLV_SETTING_NOSETENV "RestrainedLifeNoSetEnv"
401#define RLV_SETTING_FORBIDGIVETORLV "RestrainedLifeForbidGiveToRLV"
402
403#define RLV_SETTING_ENABLEWEAR "RLVaEnableWear"
404#define RLV_SETTING_ENABLELEGACYNAMING "RLVaEnableLegacyNaming"
405#define RLV_SETTING_HIDELOCKEDLAYER "RLVaHideLockedLayers"
406#define RLV_SETTING_HIDELOCKEDATTACH "RLVaHideLockedAttachments"
407#define RLV_SETTING_HIDELOCKEDINVENTORY "RLVaHideLockedInventory"
408#define RLV_SETTING_LOGINLASTLOCATION "RLVaLoginLastLocation"
409#define RLV_SETTING_SHOWNAMETAGS "RLVaShowNameTags"
410
411inline BOOL rlvGetSettingBOOL(const std::string& strSetting, BOOL fDefault)
412{
413 return (gSavedSettings.controlExists(strSetting)) ? gSavedSettings.getBOOL(strSetting) : fDefault;
414}
415inline BOOL rlvGetPerUserSettingsBOOL(const std::string& strSetting, BOOL fDefault)
416{
417 return (gSavedPerAccountSettings.controlExists(strSetting)) ? gSavedPerAccountSettings.getBOOL(strSetting) : fDefault;
418}
419
420class RlvSettings
421{
422public:
423 static BOOL getDebug() { return rlvGetSettingBOOL(RLV_SETTING_DEBUG, FALSE); }
424 static BOOL getForbidGiveToRLV() { return rlvGetSettingBOOL(RLV_SETTING_FORBIDGIVETORLV, TRUE); }
425
426 static BOOL getEnableWear() { return rlvGetSettingBOOL(RLV_SETTING_ENABLEWEAR, FALSE); }
427 static BOOL getHideLockedLayers() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDLAYER, FALSE); }
428 static BOOL getHideLockedAttach() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDATTACH, FALSE); }
429 static BOOL getHideLockedInventory() { return rlvGetSettingBOOL(RLV_SETTING_HIDELOCKEDINVENTORY, FALSE); }
430
431 #ifdef RLV_EXTENSION_STARTLOCATION
432 static BOOL getLoginLastLocation() { return rlvGetPerUserSettingsBOOL(RLV_SETTING_LOGINLASTLOCATION, TRUE); }
433 static void updateLoginLastLocation();
434 #endif // RLV_EXTENSION_STARTLOCATION
435
436 static BOOL fShowNameTags;
437};
438
439// ============================================================================
440/*
441 * State keeping classes/structure
442 *
443 */
444
445struct RlvRedirInfo
446{
447 S16 nRedirChat;
448 S16 nRedirEmote;
449
450 RlvRedirInfo() : nRedirChat(0), nRedirEmote(0) {}
451 bool isActive() { return (nRedirChat + nRedirEmote) != 0; }
452};
453
454struct RlvReattachInfo
455{
456 LLUUID idItem;
457 bool fInInventory;
458 bool fAssetSaved;
459
460 RlvReattachInfo() : idItem(), fInInventory(false), fAssetSaved(false) {}
461};
462
463// ============================================================================
464/*
465 * Various helper classes/timers/functors
466 *
467 */
468
469class RlvGCTimer : public LLEventTimer
470{
471public:
472 RlvGCTimer() : LLEventTimer(30.0) {}
473 virtual BOOL tick();
474};
475
476class RlvCurrentlyWorn : public LLInventoryFetchObserver
477{
478public:
479 RlvCurrentlyWorn() {}
480 ~RlvCurrentlyWorn() {}
481 virtual void done() {}
482
483 static void fetchWorn();
484 void fetchItem(const LLUUID& idItem);
485};
486
487struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor
488{
489 virtual bool apply(LLSelectNode* pNode);
490};
491
492struct RlvSelectIsOwnedByOrGroupOwned : public LLSelectedNodeFunctor
493{
494 RlvSelectIsOwnedByOrGroupOwned(const LLUUID& uuid) : m_idAgent(uuid) {}
495 virtual bool apply(LLSelectNode* pNode);
496 LLUUID m_idAgent;
497};
498
499struct RlvSelectIsSittingOn : public LLSelectedNodeFunctor
500{
501 RlvSelectIsSittingOn(LLXform* pObject) : m_pObject(pObject) {}
502 virtual bool apply(LLSelectNode* pNode);
503 LLXform* m_pObject;
504};
505
506// ============================================================================
507/*
508 * Various helper functions
509 *
510 */
511
512BOOL rlvAttachToEnabler(void* pParam);
513bool rlvCanDeleteOrReturn();
514S32 rlvGetDirectDescendentsCount(const LLInventoryCategory* pFolder, LLAssetType::EType type);
515bool rlvIsEmote(const std::string& strUTF8Text);
516bool rlvIsValidChannel(S32 nChannel);
517bool rlvIsWearingItem(const LLInventoryItem* pItem);
518
519void rlvForceDetach(LLViewerJointAttachment* pAttachPt);
520void rlvSendBusyMessage(const LLUUID& idTo, const std::string& strMsg, const LLUUID& idSession = LLUUID::null);
521bool rlvSendChatReply(const std::string& strChannel, const std::string& strReply);
522bool rlvSendChatReply(S32 nChannel, const std::string& strReply);
523
524void rlvStringReplace(std::string& strText, std::string strFrom, const std::string& strTo);
525std::string rlvGetFirstParenthesisedText(const std::string& strText, std::string::size_type* pidxMatch = NULL);
526std::string rlvGetLastParenthesisedText(const std::string& strText, std::string::size_type* pidxStart = NULL);
527
528#ifdef RLV_ADVANCED_TOGGLE_RLVA
529 // "Advanced / RLVa / Enable RLV" menu option
530 void rlvDbgToggleEnabled(void*);
531 BOOL rlvDbgGetEnabled(void*);
532#endif // RLV_ADVANCED_TOGGLE_RLVA
533
534// ============================================================================
535// Inlined class member functions
536//
537
538inline bool RlvCommand::operator ==(const RlvCommand& rhs) const
539{
540 // The specification notes that "@detach=n" is semantically identical to "@detach=add" (same for "y" and "rem"
541 return (m_strBehaviour == rhs.m_strBehaviour) && (m_strOption == rhs.m_strOption) &&
542 ( (RLV_TYPE_UNKNOWN != m_eParamType) ? (m_eParamType == rhs.m_eParamType) : (m_strParam == rhs.m_strParam) );
543}
544
545inline void RlvCurrentlyWorn::fetchItem(const LLUUID& idItem)
546{
547 if (idItem.notNull())
548 {
549 LLInventoryFetchObserver::item_ref_t idItems;
550 idItems.push_back(idItem);
551 fetchItems(idItems);
552 }
553}
554
555// ============================================================================
556// Inlined helper functions
557//
558
559inline bool rlvIsEmote(const std::string& strUTF8Text)
560{
561 return (strUTF8Text.length() > 4) && ( (strUTF8Text.compare(0, 4, "/me ") == 0) || (strUTF8Text.compare(0, 4, "/me'") == 0) );
562}
563
564// Checked: 2009-08-05 (RLVa-1.0.1e) | Added: RLVa-1.0.0e
565inline bool rlvIsValidChannel(S32 nChannel)
566{
567 return (nChannel >= 0) && (CHAT_CHANNEL_DEBUG != nChannel);
568}
569
570// Checked: 2009-08-05 (RLVa-1.0.1e) | Added: RLVa-1.0.0e
571inline bool rlvSendChatReply(const std::string& strChannel, const std::string& strReply)
572{
573 S32 nChannel;
574 return (LLStringUtil::convertToS32(strChannel, nChannel)) ? rlvSendChatReply(nChannel, strReply) : false;
575}
576
577// ============================================================================
578
579#endif // RLV_HELPER_H