00001
00008 #include "llviewerprecompiledheaders.h"
00009
00010 #include "llavatarconstants.h"
00011 #include "llfloateravatarlist.h"
00012
00013 #include "llvieweruictrlfactory.h"
00014 #include "llviewerwindow.h"
00015 #include "llscrolllistctrl.h"
00016
00017 #include "llvoavatar.h"
00018 #include "llimview.h"
00019 #include "llfloateravatarinfo.h"
00020 #include "llregionflags.h"
00021 #include "llfloaterreporter.h"
00022 #include "llagent.h"
00023 #include "llviewerregion.h"
00024 #include "lltracker.h"
00025 #include "llviewercontrol.h"
00026 #include "llviewerstats.h"
00027 #include "llerror.h"
00028 #include "llchat.h"
00029 #include "llviewermessage.h"
00030 #include "llweb.h"
00031 #include "llviewerobjectlist.h"
00032 #include "llmutelist.h"
00033
00034 #include <time.h>
00035 #include <string.h>
00036
00037 #include <map>
00038
00039
00040
00044 const F32 ACTIVITY_TIMEOUT = 1.0f;
00045
00046
00052 const F32 MIN_REQUEST_INTERVAL = 1.0f;
00053
00057 const F32 FIRST_REQUEST_TIMEOUT = 16.0f;
00058
00062 const F32 MAX_REQUEST_TIMEOUT = 2048.0f;
00063
00069 const F32 REQUEST_FAIL_TIMEOUT = 15.0f;
00070
00076 const F32 DEAD_KEEP_TIME = 10.0f;
00077
00083 const F32 CLEANUP_TIMEOUT = 3600.0f;
00084
00085
00090 const S32 TRUSTNET_CHANNEL = 0x44470002;
00091
00092
00093 extern U32 gFrameCount;
00094
00095
00096 LLAvListTrustNetScore::LLAvListTrustNetScore(LLString type, F32 score)
00097 {
00098 Score = score;
00099 Type = type;
00100 }
00101
00102
00103 LLAvatarInfo::LLAvatarInfo()
00104 {
00105 }
00106
00107 LLAvatarInfo::LLAvatarInfo(PAYMENT_TYPE payment, ACCOUNT_TYPE account, struct tm birth)
00108 {
00109 Payment = payment;
00110 Account = account;
00111 BirthDate = birth;
00112 }
00113
00114 S32 LLAvatarInfo::getAge()
00115 {
00116 time_t birth = mktime(&BirthDate);
00117 time_t now = time(NULL);
00118 return(S32)(difftime(now,birth) / (60*60*24));
00119 }
00120
00121 void LLAvatarListEntry::setPosition(LLVector3d position)
00122 {
00123 if ( mPosition != position )
00124 {
00125 setActivity(ACTIVITY_MOVING);
00126 }
00127
00128 mPosition = position;
00129 mFrame = gFrameCount;
00130 mUpdateTimer.start();
00131 }
00132
00133 LLVector3d LLAvatarListEntry::getPosition()
00134 {
00135 return mPosition;
00136 }
00137
00138 U32 LLAvatarListEntry::getEntryAgeFrames()
00139 {
00140 return (gFrameCount - mFrame);
00141 }
00142
00143 F32 LLAvatarListEntry::getEntryAgeSeconds()
00144 {
00145 return mUpdateTimer.getElapsedTimeF32();
00146 }
00147
00148 void LLAvatarListEntry::setName(LLString name)
00149 {
00150 if ( name.empty() || (name.compare(" ") == 0))
00151 {
00152 llwarns << "Trying to set empty name" << llendl;
00153 }
00154 mName = name;
00155 }
00156
00157 LLString LLAvatarListEntry::getName()
00158 {
00159 return mName;
00160 }
00161
00162 LLUUID LLAvatarListEntry::getID()
00163 {
00164 return mID;
00165 }
00166
00167 void LLAvatarListEntry::setID(LLUUID id)
00168 {
00169 if ( id.isNull() )
00170 {
00171 llwarns << "Trying to set null id" << llendl;
00172 }
00173 mID = id;
00174 }
00175
00176 BOOL LLAvatarListEntry::getIsLinden()
00177 {
00178
00179
00180 return ( mIsLinden || ( mAvatarInfo.getValue().Account == ACCOUNT_EMPLOYEE ) );
00181 }
00182
00183 void LLAvatarListEntry::setAccountCustomTitle(LLString &title)
00184 {
00185 mAccountTitle = title;
00186 mAvatarInfo.getValue().Account = ACCOUNT_CUSTOM;
00187 }
00188
00189 LLString LLAvatarListEntry::getAccountCustomTitle()
00190 {
00191 return mAccountTitle;
00192 }
00193
00194
00195
00196 void LLAvatarListEntry::setActivity(ACTIVITY_TYPE activity)
00197 {
00198 if ( activity >= mActivityType || mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT )
00199 {
00200 mActivityType = activity;
00201 mActivityTimer.start();
00202 }
00203 }
00204
00205 ACTIVITY_TYPE LLAvatarListEntry::getActivity()
00206 {
00207 if ( mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT )
00208 {
00209 mActivityType = ACTIVITY_NONE;
00210 }
00211
00212 return mActivityType;
00213 }
00214
00215 void LLAvatarListEntry::toggleMark()
00216 {
00217 mMarked = !mMarked;
00218 }
00219
00220 BOOL LLAvatarListEntry::isMarked()
00221 {
00222 return mMarked;
00223 }
00224
00225 BOOL LLAvatarListEntry::isDead()
00226 {
00227 return getEntryAgeSeconds() > DEAD_KEEP_TIME;
00228 }
00229
00230
00231 LLFloaterAvatarList* gFloaterAvatarList = NULL;
00232
00233
00234
00235
00236 LLFloaterAvatarList::LLFloaterAvatarList() : LLFloater("avatar list")
00237 {
00238
00239
00240 mTracking = FALSE;
00241 mTrackByLocation = FALSE;
00242 mARLastFrame = 0;
00243
00244
00245 gUICtrlFactory->buildFloater(this, "floater_avatar_scanner.xml");
00246
00247
00248 setVisible(FALSE);
00249
00250
00251
00252 childSetAction("profile_btn", onClickProfile, this);
00253 childSetAction("im_btn", onClickIM, this);
00254 childSetAction("track_btn", onClickTrack, this);
00255 childSetAction("mark_btn", onClickMark, this);
00256
00257 childSetAction("gowarn_btn", onClickGohomerWarn, this);
00258 childSetAction("goeject_btn", onClickGohomerEject, this);
00259 childSetAction("goaway_btn", onClickGohomerSendAway, this);
00260 childSetAction("gohome_btn", onClickGohomerSendHome, this);
00261 childSetAction("gohomeoff_btn", onClickGohomerOff, this);
00262 childSetAction("gokey_btn", onClickGohomerSendHomeByKey, this);
00263
00264 childSetAction("prev_in_list_btn", onClickPrevInList, this);
00265 childSetAction("next_in_list_btn", onClickNextInList, this);
00266 childSetAction("prev_marked_btn", onClickPrevMarked, this);
00267 childSetAction("next_marked_btn", onClickNextMarked, this);
00268
00269 childSetAction("get_key_btn", onClickGetKey, this);
00270
00271 childSetAction("tn_rate_btn", onClickTrustNetRate, this);
00272 childSetAction("tn_explain_btn", onClickTrustNetExplain, this);
00273 childSetAction("tn_website_btn", onClickTrustNetWebsite, this);
00274 childSetAction("tn_password_btn", onClickTrustNetGetPassword, this);
00275 childSetAction("tn_renew_btn", onClickTrustNetRenew, this);
00276
00277 childSetAction("freeze_btn", onClickFreeze, this);
00278 childSetAction("eject_btn", onClickEject, this);
00279
00280
00281 childSetAction("mute_btn", onClickMute, this);
00282
00283 childSetAction("ar_btn", onClickAR, this);
00284 childSetAction("teleport_btn", onClickTeleport, this);
00285 childSetAction("estate_eject_btn", onClickEjectFromEstate, this);
00286
00287 setDefaultBtn("refresh_btn");
00288
00289
00290 mAvatarList = LLUICtrlFactory::getScrollListByName(this, "avatar_list");
00291
00292 mAvatarList->setCallbackUserData(this);
00293 mAvatarList->setDoubleClickCallback(onDoubleClick);
00294 mAvatarList->sortByColumn("distance", TRUE);
00295 mDataRequestTimer.start();
00296 refreshAvatarList();
00297
00298 LLMessageSystem *msg = gMessageSystem;
00299 msg->addHandlerFunc("AvatarPropertiesReply", processAvatarPropertiesReply);
00300 }
00301
00302 LLFloaterAvatarList::~LLFloaterAvatarList()
00303 {
00304 LLMessageSystem *msg = gMessageSystem;
00305 if ( msg )
00306 {
00307 msg->delHandlerFunc("AvatarPropertiesReply", processAvatarPropertiesReply);
00308 }
00309 }
00310
00311
00312 void LLFloaterAvatarList::show()
00313 {
00314
00315 open();
00316 }
00317
00318
00319 void LLFloaterAvatarList::toggle(void*) {
00320 if (!gFloaterAvatarList) {
00321 llinfos << "No avatar list!" << llendl;
00322 return;
00323 }
00324
00325 if (gFloaterAvatarList->getVisible())
00326 {
00327 gFloaterAvatarList->close();
00328 }
00329 else
00330 {
00331 gFloaterAvatarList->show();
00332 }
00333 }
00334
00335
00336 BOOL LLFloaterAvatarList::visible(void*)
00337 {
00338 return (gFloaterAvatarList && gFloaterAvatarList->getVisible());
00339 }
00340
00341
00342 void LLFloaterAvatarList::updateAvatarList()
00343 {
00344
00345
00346
00347
00348
00349 LLCheckboxCtrl* check;
00350 check = LLUICtrlFactory::getCheckBoxByName(this, "update_enabled_cb");
00351
00352 if ( !check->getValue() )
00353 {
00354 return;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
00369 iter != LLCharacter::sInstances.end(); ++iter)
00370 {
00371 LLVOAvatar* avatarp = (LLVOAvatar*) *iter;
00372
00373
00374
00375 if (avatarp->isDead() || avatarp->isSelf())
00376 {
00377 continue;
00378 }
00379
00380
00381 LLVector3d position = gAgent.getPosGlobalFromAgent(avatarp->getCharacterPosition());
00382 LLUUID avid = avatarp->getID();
00383 LLString name = avatarp->getFullname();
00384
00385
00386
00387
00388 if (name.empty() || (name.compare(" ") == 0))
00389 {
00390 llinfos << "Name empty for avatar " << avid << llendl;
00391 continue;
00392 }
00393
00394 if (avid.isNull())
00395 {
00396 llinfos << "Key empty for avatar " << name << llendl;
00397 continue;
00398 }
00399
00400 if ( mAvatars.count( avid ) > 0 )
00401 {
00402
00403 mAvatars[avid].setPosition(position);
00404 }
00405 else
00406 {
00407
00408 BOOL isLinden = ( avatarp->getNVPair("LastName")->getString() == "Linden" );
00409
00410 LLAvatarListEntry entry(avid, name, position, isLinden);
00411 mAvatars[avid] = entry;
00412
00413
00414 llinfos << "avatar list refresh: adding " << name << llendl;
00415
00416 }
00417
00418 }
00419
00420
00421
00422 expireAvatarList();
00423 refreshAvatarList();
00424 checkTrackingStatus();
00425 processARQueue();
00426 }
00427
00428 void LLFloaterAvatarList::processARQueue()
00429 {
00430 if ( mARQueue.empty() ) return;
00431
00432 LLUUID avatar_id = mARQueue.front();
00433
00434 if ( 0 == mARLastFrame )
00435 {
00436
00437
00438 gAgent.lookAtObject(avatar_id, CAMERA_POSITION_OBJECT);
00439 mARLastFrame = gFrameCount;
00440 return;
00441 }
00442
00443 if ( gFrameCount - mARLastFrame >= 10 )
00444 {
00445
00446 LLFloaterReporter *report = LLFloaterReporter::showFromObject(avatar_id, false);
00447 report->setMinimized(TRUE);
00448
00449 mARReporterQueue.push(report);
00450
00451 mARQueue.pop();
00452 mARLastFrame = 0;
00453
00454 if ( mARQueue.empty() )
00455 {
00456
00457
00458 while( !mARReporterQueue.empty() )
00459 {
00460 LLFloaterReporter *r = mARReporterQueue.front();
00461 mARReporterQueue.pop();
00462
00463 r->open();
00464 r->setMinimized(FALSE);
00465 }
00466 }
00467 }
00468 }
00469
00470 void LLFloaterAvatarList::expireAvatarList()
00471 {
00472
00473 std::map<LLUUID, LLAvatarListEntry>::iterator iter;
00474 std::queue<LLUUID> delete_queue;
00475
00476 for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
00477 {
00478 LLAvatarListEntry *ent = &iter->second;
00479
00480 if ( ent->getEntryAgeFrames() >= 2 )
00481 {
00482 ent->setActivity(ACTIVITY_DEAD);
00483 }
00484
00485
00486 if ( ent->getEntryAgeSeconds() > CLEANUP_TIMEOUT )
00487 {
00488 llinfos << "avatar list: expiring avatar " << ent->getName() << llendl;
00489 LLUUID av_id = ent->getID();
00490 delete_queue.push(av_id);
00491 }
00492 }
00493
00494 while(!delete_queue.empty())
00495 {
00496 mAvatars.erase(delete_queue.front());
00497 delete_queue.pop();
00498 }
00499 }
00500
00506 void LLFloaterAvatarList::refreshAvatarList()
00507 {
00508
00509
00510
00511
00512 if (!LLFloaterAvatarList::visible(NULL))
00513 {
00514 return;
00515 }
00516
00517
00518 LLCheckboxCtrl* fetch_data;
00519 fetch_data = LLUICtrlFactory::getCheckBoxByName(this, "fetch_avdata_enabled_cb");
00520
00521 BOOL db_enabled = gSavedSettings.getBOOL("DBEnabled");
00522 LLString db_avatar = gSavedPerAccountSettings.getString("DBAvatarName");
00523 if ( db_avatar.empty() )
00524 {
00525 db_enabled = FALSE;
00526 }
00527
00528
00529
00530
00531
00532
00533 LLDynamicArray<LLUUID> selected = mAvatarList->getSelectedIDs();
00534 S32 scrollpos = mAvatarList->getScrollPos();
00535
00536 mAvatarList->deleteAllItems();
00537
00538 LLVector3d mypos = gAgent.getPositionGlobal();
00539
00540
00541 std::map<LLUUID, LLAvatarListEntry>::iterator iter;
00542 for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
00543 {
00544 LLSD element;
00545 LLUUID av_id;
00546
00547
00548 LLAvatarListEntry *ent = &iter->second;
00549
00550
00551 if ( ent->isDead() )
00552 {
00553 continue;
00554 }
00555
00556 av_id = ent->getID();
00557
00558
00559 LLAvatarInfo avinfo = ent->mAvatarInfo.getValue();
00560 LLAvListTrustNetScore avscore = ent->mTrustNetScore.getValue();
00561
00562 DATA_STATUS avinfo_status = ent->mAvatarInfo.getStatus();
00563 DATA_STATUS avscore_status = ent->mTrustNetScore.getStatus();
00564
00565 LLVector3d position = ent->getPosition();
00566 LLVector3d delta = position - mypos;
00567 F32 distance = (F32)delta.magVec();
00568
00569 LLString icon = "";
00570
00571
00572
00573
00574
00575 if ( distance > 1024 )
00576 {
00577 continue;
00578 }
00579
00580 if ( av_id.isNull() )
00581 {
00582 llwarns << "Avatar with null key somehow got into the list!" << llendl;
00583 continue;
00584 }
00585
00586
00587
00588
00589
00590 element["id"] = av_id;
00591
00592 element["columns"][LIST_AVATAR_ICON]["column"] = "avatar_icon";
00593 element["columns"][LIST_AVATAR_ICON]["type"] = "text";
00594 if ( ent->isMarked() )
00595 {
00596 element["columns"][LIST_AVATAR_ICON]["type"] = "icon";
00597 element["columns"][LIST_AVATAR_ICON]["value"] = gViewerArt.getString("flag_blue.tga");
00598 }
00599
00600
00601 if ( ent->getIsLinden() )
00602 {
00603 element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD";
00604 }
00605
00606 if ( ent->isFocused() )
00607 {
00608 element["columns"][LIST_AVATAR_NAME]["color"] = LLColor4::cyan.getValue();
00609 }
00610
00611
00612 element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name";
00613 element["columns"][LIST_AVATAR_NAME]["type"] = "text";
00614 element["columns"][LIST_AVATAR_NAME]["value"] = ent->getName().c_str();
00615
00616 char temp[32];
00617 snprintf(temp, sizeof(temp), "%.2f", distance);
00618
00619 element["columns"][LIST_DISTANCE]["column"] = "distance";
00620 element["columns"][LIST_DISTANCE]["type"] = "text";
00621 element["columns"][LIST_DISTANCE]["value"] = temp;
00622 element["columns"][LIST_DISTANCE]["color"] = getAvatarColor(ent, distance, CT_DISTANCE).getValue();
00623
00624
00625 if ( avinfo_status == DATA_RETRIEVED )
00626 {
00627 element["columns"][LIST_AGE]["column"] = "age";
00628 element["columns"][LIST_AGE]["type"] = "text";
00629 element["columns"][LIST_AGE]["value"] = avinfo.getAge();
00630 element["columns"][LIST_AGE]["color"] = getAvatarColor(ent, distance, CT_AGE).getValue();
00631 }
00632
00633 element["columns"][LIST_SCORE]["column"] = "score";
00634 element["columns"][LIST_SCORE]["type"] = "text";
00635
00636 icon = "";
00637 switch(avscore_status)
00638 {
00639 case DATA_UNKNOWN:
00640 icon = gViewerArt.getString("info_unknown.tga");
00641 break;
00642 case DATA_REQUESTING:
00643 icon = gViewerArt.getString("info_fetching.tga");
00644 break;
00645 case DATA_ERROR:
00646 icon = gViewerArt.getString("info_error.tga");
00647 case DATA_RETRIEVED:
00648 element["columns"][LIST_SCORE]["value"] = avscore.Score;
00649 element["columns"][LIST_SCORE]["color"] = getAvatarColor(ent, distance, CT_SCORE).getValue();
00650 break;
00651 }
00652
00653 if (!icon.empty() )
00654 {
00655 element["columns"][LIST_SCORE].erase("color");
00656 element["columns"][LIST_SCORE]["type"] = "icon";
00657 element["columns"][LIST_SCORE]["value"] = icon;
00658 }
00659
00660
00661
00662
00663
00664 icon = "";
00665
00666 switch(avinfo_status)
00667 {
00668 case DATA_UNKNOWN:
00669 icon = gViewerArt.getString("info_unknown.tga");
00670 break;
00671 case DATA_REQUESTING:
00672 icon = gViewerArt.getString("info_fetching.tga");
00673 break;
00674 case DATA_ERROR:
00675 icon = gViewerArt.getString("info_error.tga");
00676 break;
00677 case DATA_RETRIEVED:
00678 switch(avinfo.Payment)
00679 {
00680 case PAYMENT_NONE:
00681 break;
00682 case PAYMENT_ON_FILE:
00683 icon = gViewerArt.getString("payment_info_filled.tga");
00684 break;
00685 case PAYMENT_USED:
00686 icon = gViewerArt.getString("payment_info_used.tga");
00687 break;
00688 case PAYMENT_LINDEN:
00689
00690 icon = gViewerArt.getString("icon_top_pick.tga");
00691 break;
00692 }
00693 break;
00694 }
00695
00696 element["columns"][LIST_PAYMENT]["column"] = "payment_data";
00697 element["columns"][LIST_PAYMENT]["type"] = "text";
00698
00699
00700
00701 if ( !icon.empty() )
00702 {
00703 element["columns"][LIST_PAYMENT].erase("color");
00704 element["columns"][LIST_PAYMENT]["type"] = "icon";
00705 element["columns"][LIST_PAYMENT]["value"] = icon;
00706
00707 }
00708
00709
00710 ACTIVITY_TYPE activity = ent->getActivity();
00711 icon = "";
00712 switch( activity )
00713 {
00714 case ACTIVITY_NONE:
00715 break;
00716 case ACTIVITY_MOVING:
00717 icon = gViewerArt.getString("inv_item_animation.tga");
00718 break;
00719 case ACTIVITY_GESTURING:
00720 icon = gViewerArt.getString("inv_item_gesture.tga");
00721 break;
00722 case ACTIVITY_SOUND:
00723 icon = gViewerArt.getString("inv_item_sound.tga");
00724 break;
00725 case ACTIVITY_REZZING:
00726 icon = gViewerArt.getString("ff_edit_theirs.tga");
00727 break;
00728 case ACTIVITY_PARTICLES:
00729
00730 icon = gViewerArt.getString("account_id_blue.tga");
00731 break;
00732 case ACTIVITY_NEW:
00733 icon = gViewerArt.getString("avatar_new.tga");
00734 break;
00735 case ACTIVITY_TYPING:
00736 icon = gViewerArt.getString("avatar_typing.tga");
00737 break;
00738 case ACTIVITY_DEAD:
00739
00740 icon = gViewerArt.getString("avatar_gone.tga");
00741 break;
00742 }
00743
00744 element["columns"][LIST_ACTIVITY]["column"] = "activity";
00745 element["columns"][LIST_ACTIVITY]["type"] = "text";
00746
00747 if (!icon.empty() )
00748 {
00749 element["columns"][LIST_ACTIVITY]["type"] = "icon";
00750 element["columns"][LIST_ACTIVITY]["value"] = icon;
00751
00752 }
00753
00754
00755
00756 mAvatarList->addElement(element, ADD_BOTTOM);
00757
00758
00759 if ( fetch_data->getValue() && ent->mAvatarInfo.requestIfNeeded() )
00760 {
00761 sendAvatarPropertiesRequest(av_id);
00762 llinfos << "Data for avatar " << ent->getName() << " didn't arrive yet, retrying" << llendl;
00763 }
00764
00765 if ( ent->mTrustNetScore.requestIfNeeded() )
00766 {
00767 requestTrustNetScore(av_id, ent->getName(), "behavior");
00768 llinfos << "Requesting TrustNet score for " << ent->getName() << llendl;
00769 }
00770
00771 if ( db_enabled && ent->mMiscInfo.requestIfNeeded() )
00772 {
00773 requestMiscInfo(av_id, ent->getName());
00774 llinfos << "Requesting misc info for " << ent->getName() << llendl;
00775 }
00776 }
00777
00778
00779 mAvatarList->sort();
00780 mAvatarList->selectMultiple(selected);
00781 mAvatarList->setScrollPos(scrollpos);
00782
00783
00784
00785 }
00786
00787
00788 void LLFloaterAvatarList::onClickIM(void* userdata)
00789 {
00790
00791 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
00792
00793 LLDynamicArray<LLUUID> ids = avlist->mAvatarList->getSelectedIDs();
00794 if(ids.size() > 0)
00795 {
00796 if(ids.size() == 1)
00797 {
00798
00799 LLUUID agent_id = ids[0];
00800
00801 char buffer[MAX_STRING];
00802 snprintf(buffer, MAX_STRING, "%s", avlist->mAvatars[agent_id].getName().c_str());
00803 gIMMgr->setFloaterOpen(TRUE);
00804 gIMMgr->addSession(
00805 buffer,
00806 IM_NOTHING_SPECIAL,
00807 agent_id);
00808 }
00809 else
00810 {
00811
00812 LLUUID session_id;
00813 session_id.generate();
00814 gIMMgr->setFloaterOpen(TRUE);
00815 gIMMgr->addSession("Avatars Conference", IM_SESSION_CONFERENCE_START, ids[0], ids);
00816 }
00817 }
00818 }
00819
00820 void LLFloaterAvatarList::onClickTrack(void *userdata)
00821 {
00822 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
00823
00824 LLScrollListItem *item = avlist->mAvatarList->getFirstSelected();
00825 if (!item) return;
00826
00827 LLUUID agent_id = item->getUUID();
00828
00829 if ( avlist->mTracking && avlist->mTrackedAvatar == agent_id ) {
00830 LLTracker::stopTracking(NULL);
00831 avlist->mTracking = FALSE;
00832 }
00833 else
00834 {
00835 avlist->mTracking = TRUE;
00836 avlist->mTrackByLocation = FALSE;
00837 avlist->mTrackedAvatar = agent_id;
00838 LLTracker::trackAvatar(agent_id, avlist->mAvatars[agent_id].getName());
00839 }
00840 }
00841
00842 void LLFloaterAvatarList::sendAvatarPropertiesRequest(LLUUID avid)
00843 {
00844
00845
00846 lldebugs << "LLPanelAvatar::sendAvatarPropertiesRequest()" << llendl;
00847 LLMessageSystem *msg = gMessageSystem;
00848
00849 msg->newMessageFast(_PREHASH_AvatarPropertiesRequest);
00850 msg->nextBlockFast( _PREHASH_AgentData);
00851 msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() );
00852 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00853 msg->addUUIDFast( _PREHASH_AvatarID, avid);
00854 gAgent.sendReliableMessage();
00855
00856 mAvatars[avid].mAvatarInfo.requestStarted();
00857 }
00858
00859
00860 void LLFloaterAvatarList::processAvatarPropertiesReply(LLMessageSystem *msg, void**)
00861 {
00862
00863
00864 LLFloaterAvatarList* self = NULL;
00865 LLAvatarInfo avinfo;
00866
00867 BOOL identified = FALSE;
00868 BOOL transacted = FALSE;
00869
00870 LLUUID agent_id;
00871 LLUUID avatar_id;
00872 U32 flags = 0x0;
00873 char born_on[DB_BORN_BUF_SIZE];
00874 S32 charter_member_size = 0;
00875
00876 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
00877 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id );
00878
00879
00880 self = gFloaterAvatarList;
00881
00882
00883 if ( self->mAvatarList->getItemIndex(avatar_id) < 0 )
00884 {
00885 return;
00886 }
00887
00888 LLAvatarListEntry *entry = &self->mAvatars[avatar_id];
00889
00890 msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_BornOn, DB_BORN_BUF_SIZE, born_on);
00891 msg->getU32Fast(_PREHASH_PropertiesData, _PREHASH_Flags, flags);
00892
00893 identified = (flags & AVATAR_IDENTIFIED);
00894 transacted = (flags & AVATAR_TRANSACTED);
00895
00896
00897
00898
00899
00900
00901 U8 caption_index = 0;
00902 LLString caption_text;
00903 charter_member_size = msg->getSize("PropertiesData", "CharterMember");
00904
00905 if(1 == charter_member_size)
00906 {
00907 msg->getBinaryData("PropertiesData", "CharterMember", &caption_index, 1);
00908 }
00909 else if(1 < charter_member_size)
00910 {
00911 char caption[MAX_STRING];
00912 msg->getString("PropertiesData", "CharterMember", MAX_STRING, caption);
00913
00914 caption_text = caption;
00915 entry->setAccountCustomTitle(caption_text);
00916 }
00917
00918
00919 if(caption_text.empty())
00920 {
00921
00922 const enum ACCOUNT_TYPE ACCT_TYPE[] = {
00923 ACCOUNT_RESIDENT,
00924 ACCOUNT_TRIAL,
00925 ACCOUNT_CHARTER_MEMBER,
00926 ACCOUNT_EMPLOYEE
00927 };
00928
00929
00930 avinfo.Account = ACCT_TYPE[llclamp(caption_index, (U8)0, (U8)(sizeof(ACCT_TYPE)/sizeof(ACCT_TYPE[0])-1))];
00931
00932
00933
00934 if ( avinfo.Account != ACCOUNT_EMPLOYEE )
00935 {
00936 if ( transacted )
00937 {
00938 avinfo.Payment = PAYMENT_USED;
00939 }
00940 else if ( identified )
00941 {
00942 avinfo.Payment = PAYMENT_ON_FILE;
00943 }
00944 else
00945 {
00946 avinfo.Payment = PAYMENT_NONE;
00947 }
00948 }
00949 else
00950 {
00951 avinfo.Payment = PAYMENT_LINDEN;
00952 }
00953 }
00954
00955
00956
00957 memset(&avinfo.BirthDate, 0, sizeof(avinfo.BirthDate));
00958
00959 int num_read = sscanf(born_on, "%d/%d/%d", &avinfo.BirthDate.tm_mon,
00960 &avinfo.BirthDate.tm_mday,
00961 &avinfo.BirthDate.tm_year);
00962
00963 if ( num_read == 3 && avinfo.BirthDate.tm_mon <= 12 )
00964 {
00965 avinfo.BirthDate.tm_year -= 1900;
00966 avinfo.BirthDate.tm_mon--;
00967 }
00968 else
00969 {
00970
00971 memset(&avinfo.BirthDate, 0, sizeof(avinfo.BirthDate));
00972 llwarns << "Error parsing birth date: " << born_on << llendl;
00973 }
00974
00975 entry->mAvatarInfo.setValue(avinfo);
00976 }
00977
00978 void LLFloaterAvatarList::checkTrackingStatus()
00979 {
00980
00981 if ( mTracking && LLTracker::getTrackedPositionGlobal().isExactlyZero() )
00982 {
00983
00984 if ( mAvatars.count( mTrackedAvatar ) > 0 && !mTrackByLocation )
00985 {
00986 llinfos << "Switching to location-based tracking" << llendl;
00987 mTrackByLocation = TRUE;
00988 }
00989 else
00990 {
00991
00992 llinfos << "Stopping tracking avatar, server-side didn't work, and not in list anymore." << llendl;
00993 LLTracker::stopTracking(NULL);
00994 mTracking = FALSE;
00995 }
00996 }
00997
00998 if ( mTracking && mTrackByLocation )
00999 {
01000 LLString name = mAvatars[mTrackedAvatar].getName();
01001 LLString tooltip = "Tracking last known position";
01002 name += " (near)";
01003 LLTracker::trackLocation(mAvatars[mTrackedAvatar].getPosition(), name, tooltip);
01004 }
01005
01006
01007
01008 }
01009
01010
01011 BOOL LLFloaterAvatarList::avatarIsInList(LLUUID avatar)
01012 {
01013 return ( mAvatars.count( avatar ) > 0 );
01014 }
01015
01016 LLAvatarListEntry * LLFloaterAvatarList::getAvatarEntry(LLUUID avatar)
01017 {
01018 if ( avatar.isNull() )
01019 {
01020 return NULL;
01021 }
01022
01023 std::map<LLUUID, LLAvatarListEntry>::iterator iter;
01024
01025 iter = mAvatars.find(avatar);
01026 if ( iter == mAvatars.end() )
01027 {
01028 return NULL;
01029 }
01030
01031 return &iter->second;
01032
01033
01034
01035
01036
01037
01038
01039 }
01040
01041 void LLFloaterAvatarList::speakText(S32 channel, EChatType type, LLString text)
01042 {
01043 LLMessageSystem* msg = gMessageSystem;
01044
01045 msg->newMessageFast(_PREHASH_ChatFromViewer);
01046 msg->nextBlockFast(_PREHASH_AgentData);
01047 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01048 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01049 msg->nextBlockFast(_PREHASH_ChatData);
01050 msg->addStringFast(_PREHASH_Message, text);
01051 msg->addU8Fast(_PREHASH_Type, type);
01052 msg->addS32("Channel", channel);
01053
01054 gAgent.sendReliableMessage();
01055
01056 gViewerStats->incStat(LLViewerStats::ST_CHAT_COUNT);
01057 }
01058
01059
01060 void LLFloaterAvatarList::requestTrustNetScore(LLUUID avatar, const LLString name, const LLString type)
01061 {
01062 char *temp = new char[UUID_STR_LENGTH];
01063 avatar.toString(temp);
01064
01065 LLString text = "GetScore|" + name + "|" + temp + "|" + type;
01066 speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, text);
01067 }
01068
01069
01070 void LLFloaterAvatarList::replaceVars(LLString &str, LLUUID avatar, const LLString& name)
01071 {
01072 char *temp = new char[UUID_STR_LENGTH];
01073 avatar.toString(temp);
01074
01075 LLString vars[][2] = {
01076 {"$NAME", name},
01077 {"$KEY", temp},
01078 };
01079
01080 BOOL replaced = TRUE;
01081
01082 while( replaced )
01083 {
01084 replaced = FALSE;
01085 for(U32 i=0;i<sizeof(vars)/sizeof(vars[0]);i++)
01086 {
01087 U32 pos = str.find(vars[i][0]);
01088 if ( pos != std::string::npos )
01089 {
01090 str.replace(pos, vars[i][0].size(), vars[i][1]);
01091 replaced = TRUE;
01092 }
01093 }
01094 }
01095
01096 }
01097
01098 void LLFloaterAvatarList::requestMiscInfo(LLUUID avatar, const LLString name)
01099 {
01100 LLUUID db_av_key;
01101
01102 LLString message = gSavedPerAccountSettings.getString("DBSendPattern");
01103 LLString db_av_name = gSavedPerAccountSettings.getString("DBAvatarName");
01104 db_av_key.set(gSavedPerAccountSettings.getString("DBAvatarKey"));
01105
01106
01107 llinfos << "Requesting info " << llendl;
01108 replaceVars(message, avatar, name);
01109
01110 llinfos << "Request string: " << message << llendl;
01111 send_simple_im(db_av_key, message.c_str());
01112 }
01113
01114
01115 BOOL LLFloaterAvatarList::handleIM(LLUUID from_id, const LLString message)
01116 {
01117 LLUUID db_av_key;
01118 db_av_key.set(gSavedPerAccountSettings.getString("DBAvatarKey"));
01119
01120 if ( db_av_key == from_id )
01121 {
01122 std::map<LLUUID, LLAvatarListEntry>::iterator iter;
01123
01124 for(iter = gFloaterAvatarList->mAvatars.begin(); iter != gFloaterAvatarList->mAvatars.end(); iter++)
01125 {
01126 LLAvatarListEntry *ent = &iter->second;
01127
01128
01129
01130 if ( message.find(ent->getID().asString()) != std::string::npos
01131 || message.find(ent->getName().c_str()) == 0 )
01132 {
01133 LLMiscDBInfo info;
01134 info.data = message;
01135
01136 llinfos << "Database reply arrived for avatar " << ent->getName() << llendl;
01137 ent->mMiscInfo.setValue(info);
01138 }
01139 }
01140
01141 return TRUE;
01142 }
01143 return FALSE;
01144 }
01145
01146
01147 void LLFloaterAvatarList::processTrustNetReply(char *reply)
01148 {
01149 char *tokens[10];
01150 char *tmp = &reply[0];
01151 U32 count = 0;
01152
01153 llinfos << "TrustNet reply: " << reply << llendl;
01154
01155
01156
01157 while( (NULL != (tmp = strtok(tmp, "|"))) && count < (sizeof(tokens)/sizeof(tokens[0])) )
01158 {
01159 tokens[count++] = tmp;
01160 llinfos << "token: " << tmp << llendl;
01161 tmp = NULL;
01162 }
01163
01164 llinfos << "Got " << count << " tokens" << llendl;
01165
01166 if ( count >= 1 )
01167 {
01168 if (!strcmp(tokens[0], "Score") && count >= 4)
01169 {
01170
01171 LLUUID avatar(tokens[1]);
01172 LLString type = tokens[2];
01173 F32 score = (F32)strtod(tokens[3], NULL);
01174
01175 LLAvatarListEntry *ent = gFloaterAvatarList->getAvatarEntry(avatar);
01176 if ( ent != NULL )
01177 {
01178 LLAvListTrustNetScore s(type, score);
01179 ent->mTrustNetScore.setValue(s);
01180 llinfos << "Score arrived for avatar " << avatar << ": " << score << llendl;
01181 }
01182 else
01183 {
01184 llinfos << "Score arrived for avatar " << avatar << ", but it wasn't in the list anymore" << llendl;
01185 }
01186 }
01187 else if (!strcmp(tokens[0], "WebAuthToken") && count >= 2)
01188 {
01189 LLString URL = LLWeb::escapeURL(llformat("http://trustnet.daleglass.net/?session=%s", tokens[1]));
01190 LLWeb::loadURL(URL);
01191 }
01192 else if (!strcmp(tokens[0], "WebPassword") && count >= 2)
01193 {
01194 LLString password = tokens[1];
01195 gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(password));
01196 }
01197 else
01198 {
01199 llwarns << "Unrecognized TrustNet reply " << tokens[0] << llendl;
01200 }
01201 }
01202 }
01203
01204 void LLFloaterAvatarList::luskwoodCommand(LLString cmd)
01205 {
01206 LLDynamicArray<LLUUID> ids = mAvatarList->getSelectedIDs();
01207
01208 for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
01209 {
01210 LLUUID avid = *itr;
01211 LLAvatarListEntry *ent = getAvatarEntry(avid);
01212 if ( ent != NULL )
01213 {
01214
01215
01216 speakText(0, CHAT_TYPE_SHOUT, cmd + " " + ( cmd == "gokey" ? ent->getID().asString() : ent->getName() ) );
01217 }
01218 }
01219 }
01220
01221
01222 void LLFloaterAvatarList::onClickMark(void *userdata)
01223 {
01224 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01225 LLDynamicArray<LLUUID> ids = avlist->mAvatarList->getSelectedIDs();
01226
01227 for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
01228 {
01229 LLUUID avid = *itr;
01230 LLAvatarListEntry *ent = avlist->getAvatarEntry(avid);
01231 if ( ent != NULL )
01232 {
01233 ent->toggleMark();
01234 }
01235 }
01236 }
01237
01238 void LLFloaterAvatarList::handleLuskwoodDialog(S32 option, void* data)
01239 {
01240 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01241 if ( 0 == option )
01242 {
01243 self->luskwoodCommand(self->mLuskwoodCommand);
01244 }
01245 }
01246
01247 void LLFloaterAvatarList::handleLuskwoodGohomerOffDialog(S32 option, void* data)
01248 {
01249 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01250 if ( 0 == option )
01251 {
01252 self->speakText(0, CHAT_TYPE_SHOUT, "gohome off");
01253 }
01254 }
01255
01256
01257 void LLFloaterAvatarList::onClickGohomerWarn(void *data)
01258 {
01259 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01260
01261 self->mLuskwoodCommand = "gowarn";
01262 gViewerWindow->alertXml("LuskwoodGohomerWarn", handleLuskwoodDialog, self);
01263
01264 }
01265
01266
01267 void LLFloaterAvatarList::onClickGohomerEject(void *data)
01268 {
01269 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01270
01271 self->mLuskwoodCommand = "goeject";
01272 gViewerWindow->alertXml("LuskwoodGohomerEject", handleLuskwoodDialog, self);
01273 }
01274
01275
01276 void LLFloaterAvatarList::onClickGohomerSendAway(void *data)
01277 {
01278 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01279
01280 self->mLuskwoodCommand = "goaway";
01281 gViewerWindow->alertXml("LuskwoodGohomerKeepAway", handleLuskwoodDialog, self);
01282 }
01283
01284
01285 void LLFloaterAvatarList::onClickGohomerSendHome(void *data)
01286 {
01287 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01288
01289 self->mLuskwoodCommand = "gohome";
01290 gViewerWindow->alertXml("LuskwoodGohomerSendHome", handleLuskwoodDialog, self);
01291 }
01292
01293
01294 void LLFloaterAvatarList::onClickGohomerSendHomeByKey(void *data)
01295 {
01296 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01297
01298 self->mLuskwoodCommand = "gokey";
01299 gViewerWindow->alertXml("LuskwoodGohomerSendHome", handleLuskwoodDialog, self);
01300 }
01301
01302
01303
01304 void LLFloaterAvatarList::onClickGohomerOff(void *data)
01305 {
01306 LLFloaterAvatarList *self = (LLFloaterAvatarList*)data;
01307
01308 gViewerWindow->alertXml("LuskwoodGohomerOff", handleLuskwoodGohomerOffDialog, self);
01309 }
01310
01311 LLColor4 LLFloaterAvatarList::getAvatarColor(LLAvatarListEntry *ent, F32 distance, e_coloring_type type)
01312 {
01313 F32 r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f;
01314
01315 switch(type)
01316 {
01317 case CT_NONE:
01318 return LLColor4::black;
01319 break;
01320 case CT_DISTANCE:
01321 if ( distance <= 10.0f )
01322 {
01323
01324 g = 0.7f - ( distance / 20.0f );
01325 }
01326 else if ( distance > 10.0f && distance <= 20.0f )
01327 {
01328
01329 g = 0.7f - ( (distance - 10.0f) / 20.0f );
01330 b = g;
01331 }
01332 else if ( distance > 20.0f && distance <= 96.0f )
01333 {
01334
01335 r = 0.7f - ( (distance - 20.0f) / 192.0f );
01336 b = r;
01337 }
01338 else
01339 {
01340
01341 r = 1.0;
01342 }
01343 break;
01344 case CT_AGE:
01345 if ( ent->mAvatarInfo.getStatus() == DATA_RETRIEVED )
01346 {
01347 S32 age = ent->mAvatarInfo.getValue().getAge();
01348 if ( age < 14 )
01349 {
01350 r = 0.7f - ( age / 28 );
01351 }
01352 else if ( age > 14 && age <= 30 )
01353 {
01354 r = 0.7f - ( (age-14) / 32 );
01355 g = r;
01356 }
01357 else if ( age > 30 && age < 90 )
01358 {
01359 g = 0.7f - ( (age-30) / 120 );
01360 }
01361 else
01362 {
01363 b = 1.0f;
01364 }
01365 }
01366 break;
01367 case CT_SCORE:
01368 if ( ent->mTrustNetScore.getStatus() == DATA_RETRIEVED )
01369 {
01370 F32 score = ent->mTrustNetScore.getValue().Score;
01371
01372 if ( score == 0.0 )
01373 {
01374 b = 1.0f;
01375 }
01376 else if ( score == 10.0f )
01377 {
01378 g = 1.0f;
01379 }
01380 else if ( score == -10.0f )
01381 {
01382 r = 1.0f;
01383 }
01384 else if ( score > 0.0f )
01385 {
01386 g = 0.2f + ( score / 20.0f );
01387 }
01388 else if ( score < 0.0f )
01389 {
01390 r = 0.2f + ( score / 20.0f );
01391 }
01392 }
01393 break;
01394 case CT_PAYMENT:
01395 break;
01396 }
01397
01398 return LLColor4(r,g,b,a);
01399 }
01400
01401 void LLFloaterAvatarList::onDoubleClick(void *userdata)
01402 {
01403 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01404 LLScrollListItem *item = self->mAvatarList->getFirstSelected();
01405 LLUUID agent_id = item->getUUID();
01406
01407 gAgent.lookAtObject(agent_id, CAMERA_POSITION_OBJECT);
01408 }
01409
01410 void LLFloaterAvatarList::removeFocusFromAll()
01411 {
01412 std::map<LLUUID, LLAvatarListEntry>::iterator iter;
01413
01414 for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
01415 {
01416 LLAvatarListEntry *ent = &iter->second;
01417 ent->setFocus(FALSE);
01418 }
01419 }
01420
01421 void LLFloaterAvatarList::focusOnPrev(BOOL marked_only)
01422 {
01423 std::map<LLUUID, LLAvatarListEntry>::iterator iter;
01424 LLAvatarListEntry *prev = NULL;
01425 LLAvatarListEntry *ent;
01426
01427 if ( mAvatars.size() == 0 )
01428 {
01429 return;
01430 }
01431
01432 for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
01433 {
01434 ent = &iter->second;
01435
01436 if ( ent->isDead() )
01437 continue;
01438
01439 if ( (ent->getID() == mFocusedAvatar) && (prev != NULL) )
01440 {
01441 removeFocusFromAll();
01442 prev->setFocus(TRUE);
01443 mFocusedAvatar = prev->getID();
01444 gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
01445 return;
01446 }
01447
01448 if ( (!marked_only) || ent->isMarked() )
01449 {
01450 prev = ent;
01451 }
01452 }
01453
01454 if (prev != NULL && ((!marked_only) || prev->isMarked()) )
01455 {
01456 removeFocusFromAll();
01457 prev->setFocus(TRUE);
01458 mFocusedAvatar = prev->getID();
01459 gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
01460 }
01461 }
01462
01463 void LLFloaterAvatarList::focusOnNext(BOOL marked_only)
01464 {
01465
01466
01467 std::map<LLUUID, LLAvatarListEntry>::iterator iter;
01468 BOOL found = FALSE;
01469 LLAvatarListEntry *first = NULL;
01470 LLAvatarListEntry *ent;
01471
01472 if ( mAvatars.size() == 0 )
01473 {
01474 return;
01475 }
01476
01477 for(iter = mAvatars.begin(); iter != mAvatars.end(); iter++)
01478 {
01479 ent = &iter->second;
01480
01481 if ( ent->isDead() )
01482 continue;
01483
01484 if ( NULL == first && ((!marked_only) || ent->isMarked()))
01485 {
01486 first = ent;
01487 }
01488
01489 if ( found && ((!marked_only) || ent->isMarked()) )
01490 {
01491 removeFocusFromAll();
01492 ent->setFocus(TRUE);
01493 mFocusedAvatar = ent->getID();
01494 gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
01495 return;
01496 }
01497
01498 if ( ent->getID() == mFocusedAvatar )
01499 {
01500 found = TRUE;
01501 }
01502 }
01503
01504 if (first != NULL && ((!marked_only) || first->isMarked()))
01505 {
01506 removeFocusFromAll();
01507 first->setFocus(TRUE);
01508 mFocusedAvatar = first->getID();
01509 gAgent.lookAtObject(mFocusedAvatar, CAMERA_POSITION_OBJECT);
01510 }
01511 }
01512
01513 void LLFloaterAvatarList::onClickPrevInList(void *userdata)
01514 {
01515 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01516 self->focusOnPrev(FALSE);
01517 }
01518
01519
01520 void LLFloaterAvatarList::onClickNextInList(void *userdata)
01521 {
01522 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01523 self->focusOnNext(FALSE);
01524 }
01525
01526
01527 void LLFloaterAvatarList::onClickPrevMarked(void *userdata)
01528 {
01529 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01530 self->focusOnPrev(TRUE);
01531 }
01532
01533
01534 void LLFloaterAvatarList::onClickNextMarked(void *userdata)
01535 {
01536 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01537 self->focusOnNext(TRUE);
01538 }
01539
01540
01541 void LLFloaterAvatarList::onClickTrustNetRate(void *userdata)
01542 {
01543
01544 llinfos << "Ratings not implemented yet" << llendl;
01545 }
01546
01547
01548 void LLFloaterAvatarList::onClickTrustNetExplain(void *userdata)
01549 {
01550 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01551 LLScrollListItem *item = self->mAvatarList->getFirstSelected();
01552
01553 if ( item != NULL )
01554 {
01555 LLAvatarListEntry *ent = self->getAvatarEntry(item->getUUID());
01556 self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "Explain|" + ent->getName() + "|" + ent->getID().asString());
01557 }
01558 }
01559
01560
01561 void LLFloaterAvatarList::onClickTrustNetWebsite(void *userdata)
01562 {
01563 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01564
01565 self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "GetWebAuthToken");
01566 }
01567
01568
01569 void LLFloaterAvatarList::onClickTrustNetGetPassword(void *userdata)
01570 {
01571 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01572
01573 self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "GetWebPassword");
01574 }
01575
01576
01577 void LLFloaterAvatarList::onClickTrustNetRenew(void *userdata)
01578 {
01579 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01580 self->speakText(TRUSTNET_CHANNEL, CHAT_TYPE_WHISPER, "RenewSubscription");
01581 }
01582
01583
01584 void LLFloaterAvatarList::onClickGetKey(void *userdata)
01585 {
01586 LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
01587 LLScrollListItem *item = self->mAvatarList->getFirstSelected();
01588
01589 if ( NULL == item ) return;
01590
01591 LLUUID agent_id = item->getUUID();
01592
01593 char buffer[UUID_STR_LENGTH];
01594 agent_id.toString(buffer);
01595
01596 gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
01597 }
01598
01599
01600 static void send_freeze(const LLUUID& avatar_id, bool freeze)
01601 {
01602 U32 flags = 0x0;
01603 if (!freeze)
01604 {
01605
01606 flags |= 0x1;
01607 }
01608
01609 LLMessageSystem* msg = gMessageSystem;
01610 LLViewerObject* avatar = gObjectList.findObject(avatar_id);
01611
01612 if (avatar)
01613 {
01614 msg->newMessage("FreezeUser");
01615 msg->nextBlock("AgentData");
01616 msg->addUUID("AgentID", gAgent.getID());
01617 msg->addUUID("SessionID", gAgent.getSessionID());
01618 msg->nextBlock("Data");
01619 msg->addUUID("TargetID", avatar_id );
01620 msg->addU32("Flags", flags );
01621 msg->sendReliable( avatar->getRegion()->getHost() );
01622 }
01623 }
01624
01625 static void send_eject(const LLUUID& avatar_id, bool ban)
01626 {
01627 LLMessageSystem* msg = gMessageSystem;
01628 LLViewerObject* avatar = gObjectList.findObject(avatar_id);
01629
01630 if (avatar)
01631 {
01632 U32 flags = 0x0;
01633 if ( ban )
01634 {
01635
01636 flags |= 0x1;
01637 }
01638
01639 msg->newMessage("EjectUser");
01640 msg->nextBlock("AgentData");
01641 msg->addUUID("AgentID", gAgent.getID() );
01642 msg->addUUID("SessionID", gAgent.getSessionID() );
01643 msg->nextBlock("Data");
01644 msg->addUUID("TargetID", avatar_id );
01645 msg->addU32("Flags", flags );
01646 msg->sendReliable( avatar->getRegion()->getHost() );
01647 }
01648 }
01649
01650 static void send_estate_message(
01651 const char* request,
01652 const LLUUID &target)
01653 {
01654
01655 LLMessageSystem* msg = gMessageSystem;
01656 LLUUID invoice;
01657
01658
01659
01660 invoice.generate();
01661
01662 llinfos << "Sending estate request '" << request << "'" << llendl;
01663 msg->newMessage("EstateOwnerMessage");
01664 msg->nextBlockFast(_PREHASH_AgentData);
01665 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01666 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01667 msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null);
01668 msg->nextBlock("MethodData");
01669 msg->addString("Method", request);
01670 msg->addUUID("Invoice", invoice);
01671
01672
01673 msg->nextBlock("ParamList");
01674 msg->addString("Parameter", gAgent.getID().asString().c_str());
01675
01676
01677 msg->nextBlock("ParamList");
01678 msg->addString("Parameter", target.asString().c_str());
01679
01680 msg->sendReliable(gAgent.getRegion()->getHost());
01681 }
01682
01683 static void send_estate_ban(const LLUUID& agent)
01684 {
01685 LLUUID invoice;
01686 U32 flags = ESTATE_ACCESS_BANNED_AGENT_ADD;
01687
01688 invoice.generate();
01689
01690 LLMessageSystem* msg = gMessageSystem;
01691 msg->newMessage("EstateOwnerMessage");
01692 msg->nextBlockFast(_PREHASH_AgentData);
01693 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01694 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01695 msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null);
01696
01697 msg->nextBlock("MethodData");
01698 msg->addString("Method", "estateaccessdelta");
01699 msg->addUUID("Invoice", invoice);
01700
01701 char buf[MAX_STRING];
01702 gAgent.getID().toString(buf);
01703 msg->nextBlock("ParamList");
01704 msg->addString("Parameter", buf);
01705
01706 snprintf(buf, MAX_STRING, "%u", flags);
01707 msg->nextBlock("ParamList");
01708 msg->addString("Parameter", buf);
01709
01710 agent.toString(buf);
01711 msg->nextBlock("ParamList");
01712 msg->addString("Parameter", buf);
01713
01714 gAgent.sendReliableMessage();
01715 }
01716
01717 static void cmd_freeze(const LLUUID& avatar, const LLString &name) { send_freeze(avatar, true); }
01718 static void cmd_unfreeze(const LLUUID& avatar, const LLString &name) { send_freeze(avatar, false); }
01719 static void cmd_eject(const LLUUID& avatar, const LLString &name) { send_eject(avatar, false); }
01720 static void cmd_ban(const LLUUID& avatar, const LLString &name) { send_eject(avatar, true); }
01721 static void cmd_profile(const LLUUID& avatar, const LLString &name) { LLFloaterAvatarInfo::showFromDirectory(avatar); }
01722 static void cmd_mute(const LLUUID&avatar, const LLString &name) { gMuteListp->add(LLMute(avatar, name, LLMute::AGENT)); }
01723 static void cmd_unmute(const LLUUID&avatar, const LLString &name) { gMuteListp->remove(LLMute(avatar, name, LLMute::AGENT)); }
01724 static void cmd_estate_eject(const LLUUID &avatar, const LLString &name){ send_estate_message("teleporthomeuser", avatar); }
01725 static void cmd_estate_ban(const LLUUID &avatar, const LLString &name)
01726 {
01727 send_estate_message("teleporthomeuser", avatar);
01728 send_estate_ban(avatar);
01729 }
01730
01731 void LLFloaterAvatarList::doCommand(void (*func)(const LLUUID &avatar, const LLString &name))
01732 {
01733 LLDynamicArray<LLUUID> ids = mAvatarList->getSelectedIDs();
01734
01735 for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
01736 {
01737 LLUUID avid = *itr;
01738 LLAvatarListEntry *ent = getAvatarEntry(avid);
01739 if ( ent != NULL )
01740 {
01741 llinfos << "Executing command on " << ent->getName() << llendl;
01742 func(avid, ent->getName());
01743 }
01744 }
01745 }
01746
01747 LLString LLFloaterAvatarList::getSelectedNames(const LLString& separator)
01748 {
01749 LLString ret = "";
01750
01751 LLDynamicArray<LLUUID> ids = mAvatarList->getSelectedIDs();
01752 for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
01753 {
01754 LLUUID avid = *itr;
01755 LLAvatarListEntry *ent = getAvatarEntry(avid);
01756 if ( ent != NULL )
01757 {
01758 if (!ret.empty()) ret += separator;
01759 ret += ent->getName();
01760 }
01761 }
01762
01763 return ret;
01764 }
01765
01766
01767 void LLFloaterAvatarList::callbackFreeze(S32 option, void *userdata) {
01768 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01769
01770 if ( option == 0 )
01771 {
01772 avlist->doCommand(cmd_freeze);
01773 }
01774 else if ( option == 1 )
01775 {
01776 avlist->doCommand(cmd_unfreeze);
01777 }
01778 }
01779
01780
01781 void LLFloaterAvatarList::callbackEject(S32 option, void *userdata) {
01782 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01783
01784 if ( option == 0 )
01785 {
01786 avlist->doCommand(cmd_eject);
01787 }
01788 else if ( option == 1 )
01789 {
01790 avlist->doCommand(cmd_ban);
01791 }
01792 }
01793
01794
01795 void LLFloaterAvatarList::callbackMute(S32 option, void *userdata) {
01796 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01797
01798 if ( option == 0 )
01799 {
01800 avlist->doCommand(cmd_mute);
01801 }
01802 else if ( option == 1 )
01803 {
01804 avlist->doCommand(cmd_unmute);
01805 }
01806 }
01807
01808
01809 void LLFloaterAvatarList::callbackEjectFromEstate(S32 option, void *userdata) {
01810 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01811
01812 if ( option == 0 )
01813 {
01814 avlist->doCommand(cmd_estate_eject);
01815 }
01816 else if ( option == 1 )
01817 {
01818 avlist->doCommand(cmd_estate_ban);
01819 }
01820 }
01821
01822
01823 void LLFloaterAvatarList::onClickFreeze(void *userdata)
01824 {
01825 LLStringBase<char>::format_map_t args;
01826 args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
01827 gViewerWindow->alertXml("AvatarListFreezeAvatars", args, callbackFreeze, userdata);
01828 }
01829
01830
01831 void LLFloaterAvatarList::onClickEject(void *userdata)
01832 {
01833 LLStringBase<char>::format_map_t args;
01834 args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
01835 gViewerWindow->alertXml("AvatarListEjectAvatars", args, callbackEject, userdata);
01836 }
01837
01838
01839 void LLFloaterAvatarList::onClickMute(void *userdata)
01840 {
01841 LLStringBase<char>::format_map_t args;
01842 args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
01843 gViewerWindow->alertXml("AvatarListMuteAvatars", args, callbackMute, userdata);
01844 }
01845
01846
01847 void LLFloaterAvatarList::onClickEjectFromEstate(void *userdata)
01848 {
01849 LLStringBase<char>::format_map_t args;
01850 args["[NAMES]"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames();
01851 gViewerWindow->alertXml("AvatarListEjectAvatarsFromEstate", args, callbackEjectFromEstate, userdata);
01852 }
01853
01854
01855
01856
01857 void LLFloaterAvatarList::onClickAR(void *userdata)
01858 {
01859 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01860 LLDynamicArray<LLUUID> ids = avlist->mAvatarList->getSelectedIDs();
01861
01862 for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
01863 {
01864 LLUUID avid = *itr;
01865 llinfos << "Adding " << avid << " to AR queue" << llendl;
01866 avlist->mARQueue.push( avid );
01867 }
01868 }
01869
01870
01871 void LLFloaterAvatarList::onClickProfile(void* userdata)
01872 {
01873 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01874 avlist->doCommand(cmd_profile);
01875 }
01876
01877
01878 void LLFloaterAvatarList::onClickTeleport(void* userdata)
01879 {
01880 LLFloaterAvatarList *avlist = (LLFloaterAvatarList*)userdata;
01881 LLScrollListItem *item = avlist->mAvatarList->getFirstSelected();
01882
01883 if ( item )
01884 {
01885 LLUUID agent_id = item->getUUID();
01886 LLAvatarListEntry *ent = avlist->getAvatarEntry(agent_id);
01887
01888 if ( ent )
01889 {
01890 llinfos << "Trying to teleport to " << ent->getName() << " at " << ent->getPosition() << llendl;
01891 gAgent.teleportViaLocation( ent->getPosition() );
01892 }
01893 }
01894 }