diff options
Diffstat (limited to 'linden/indra/newview/llstartup.cpp')
-rw-r--r-- | linden/indra/newview/llstartup.cpp | 3939 |
1 files changed, 3939 insertions, 0 deletions
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp new file mode 100644 index 0000000..5eabad3 --- /dev/null +++ b/linden/indra/newview/llstartup.cpp | |||
@@ -0,0 +1,3939 @@ | |||
1 | /** | ||
2 | * @file llstartup.cpp | ||
3 | * @brief startup routines. | ||
4 | * | ||
5 | * Copyright (c) 2004-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "llstartup.h" | ||
31 | |||
32 | #if LL_WINDOWS | ||
33 | # include <process.h> // _spawnl() | ||
34 | #else | ||
35 | # include <sys/stat.h> // mkdir() | ||
36 | #endif | ||
37 | |||
38 | #include "audioengine.h" | ||
39 | |||
40 | #if LL_FMOD | ||
41 | #include "audioengine_fmod.h" | ||
42 | #endif | ||
43 | |||
44 | #include "audiosettings.h" | ||
45 | #include "llcachename.h" | ||
46 | #include "llviewercontrol.h" | ||
47 | #include "llcrypto.h" | ||
48 | #include "lldir.h" | ||
49 | #include "lleconomy.h" | ||
50 | #include "llfiltersd2xmlrpc.h" | ||
51 | #include "llfocusmgr.h" | ||
52 | #include "imageids.h" | ||
53 | #include "lllandmark.h" | ||
54 | #include "llloginflags.h" | ||
55 | #include "llmd5.h" | ||
56 | #include "llmemorystream.h" | ||
57 | #include "llregionhandle.h" | ||
58 | #include "llsd.h" | ||
59 | #include "llsdserialize.h" | ||
60 | #include "llsdutil.h" | ||
61 | #include "llsecondlifeurls.h" | ||
62 | #include "llstring.h" | ||
63 | #include "lluserrelations.h" | ||
64 | #include "llversion.h" | ||
65 | #include "llvfs.h" | ||
66 | #include "llwindow.h" // for shell_open | ||
67 | #include "message.h" | ||
68 | #include "v3math.h" | ||
69 | |||
70 | #include "llagent.h" | ||
71 | #include "llagentpilot.h" | ||
72 | #include "llasynchostbyname.h" | ||
73 | #include "llfloateravatarpicker.h" | ||
74 | #include "llcallbacklist.h" | ||
75 | #include "llcallingcard.h" | ||
76 | #include "llcolorscheme.h" | ||
77 | #include "llconsole.h" | ||
78 | #include "llcontainerview.h" | ||
79 | #include "lldebugview.h" | ||
80 | #include "lldrawable.h" | ||
81 | #include "lleventnotifier.h" | ||
82 | #include "llface.h" | ||
83 | #include "llfeaturemanager.h" | ||
84 | #include "llfloateraccounthistory.h" | ||
85 | #include "llfloaterchat.h" | ||
86 | #include "llfloatergesture.h" | ||
87 | #include "llfloaterland.h" | ||
88 | #include "llfloatertopobjects.h" | ||
89 | #include "llfloaterrate.h" | ||
90 | #include "llfloatertos.h" | ||
91 | #include "llfloaterworldmap.h" | ||
92 | #include "llframestats.h" | ||
93 | #include "llframestatview.h" | ||
94 | #include "llgesturemgr.h" | ||
95 | #include "llgroupmgr.h" | ||
96 | #include "llhudeffecttrail.h" | ||
97 | #include "llhudmanager.h" | ||
98 | #include "llhttpclient.h" | ||
99 | #include "llimagebmp.h" | ||
100 | #include "llinventorymodel.h" | ||
101 | #include "llinventoryview.h" | ||
102 | #include "llkeyboard.h" | ||
103 | #include "llpanellogin.h" | ||
104 | #include "llmutelist.h" | ||
105 | #include "llnotify.h" | ||
106 | #include "llpanelavatar.h" | ||
107 | #include "llpaneldirbrowser.h" | ||
108 | #include "llpaneldirland.h" | ||
109 | #include "llpanelevent.h" | ||
110 | #include "llpanelclassified.h" | ||
111 | #include "llpanelpick.h" | ||
112 | #include "llpanelplace.h" | ||
113 | #include "llpanelgrouplandmoney.h" | ||
114 | #include "llpanelgroupnotices.h" | ||
115 | #include "llpreview.h" | ||
116 | #include "llpreviewscript.h" | ||
117 | #include "llselectmgr.h" | ||
118 | #include "llsky.h" | ||
119 | #include "llstatview.h" | ||
120 | #include "llsurface.h" | ||
121 | #include "lltoolmgr.h" | ||
122 | #include "llui.h" | ||
123 | #include "llurlwhitelist.h" | ||
124 | #include "lluserauth.h" | ||
125 | #include "llviewerassetstorage.h" | ||
126 | #include "llviewercamera.h" | ||
127 | #include "llviewerdisplay.h" | ||
128 | #include "llviewergesture.h" | ||
129 | #include "llviewerimagelist.h" | ||
130 | #include "llviewermenu.h" | ||
131 | #include "llviewermessage.h" | ||
132 | #include "llviewernetwork.h" | ||
133 | #include "llviewerobjectlist.h" | ||
134 | #include "llviewerparcelmgr.h" | ||
135 | #include "llviewerregion.h" | ||
136 | #include "llviewerstats.h" | ||
137 | #include "llviewerthrottle.h" | ||
138 | #include "llviewerwindow.h" | ||
139 | #include "llvoavatar.h" | ||
140 | #include "llvoclouds.h" | ||
141 | #include "llworld.h" | ||
142 | #include "llworldmap.h" | ||
143 | #include "llxfermanager.h" | ||
144 | #include "pipeline.h" | ||
145 | #include "viewer.h" | ||
146 | #include "llmediaengine.h" | ||
147 | #include "llfasttimerview.h" | ||
148 | #include "llmozlib.h" | ||
149 | #include "llweb.h" | ||
150 | #include "llfloaterhtml.h" | ||
151 | |||
152 | #if LL_WINDOWS | ||
153 | #include "llwindebug.h" | ||
154 | #include "lldxhardware.h" | ||
155 | #endif | ||
156 | |||
157 | #if LL_QUICKTIME_ENABLED | ||
158 | #if LL_DARWIN | ||
159 | #include <QuickTime/QuickTime.h> | ||
160 | #else | ||
161 | // quicktime specific includes | ||
162 | #include "MacTypes.h" | ||
163 | #include "QTML.h" | ||
164 | #include "Movies.h" | ||
165 | #include "FixMath.h" | ||
166 | #endif | ||
167 | #endif | ||
168 | |||
169 | // | ||
170 | // exported globals | ||
171 | // | ||
172 | |||
173 | // HACK: Allow server to change sun and moon IDs. | ||
174 | // I can't figure out how to pass the appropriate | ||
175 | // information into the LLVOSky constructor. JC | ||
176 | LLUUID gSunTextureID = IMG_SUN; | ||
177 | LLUUID gMoonTextureID = IMG_MOON; | ||
178 | LLUUID gCloudTextureID = IMG_CLOUD_POOF; | ||
179 | |||
180 | const char* SCREEN_HOME_FILENAME = "screen_home.bmp"; | ||
181 | const char* SCREEN_LAST_FILENAME = "screen_last.bmp"; | ||
182 | |||
183 | // | ||
184 | // Imported globals | ||
185 | // | ||
186 | extern LLPointer<LLImageGL> gStartImageGL; | ||
187 | extern S32 gStartImageWidth; | ||
188 | extern S32 gStartImageHeight; | ||
189 | extern std::string gSerialNumber; | ||
190 | |||
191 | // | ||
192 | // local globals | ||
193 | // | ||
194 | |||
195 | static LLHost gAgentSimHost; | ||
196 | static BOOL gSkipOptionalUpdate = FALSE; | ||
197 | |||
198 | bool gQuickTimeInitialized = false; | ||
199 | static bool gGotUseCircuitCodeAck = false; | ||
200 | LLString gInitialOutfit; | ||
201 | LLString gInitialOutfitGender; // "male" or "female" | ||
202 | |||
203 | |||
204 | // | ||
205 | // local function declaration | ||
206 | // | ||
207 | |||
208 | void login_show(); | ||
209 | void login_callback(S32 option, void* userdata); | ||
210 | LLString load_password_from_disk(); | ||
211 | void save_password_to_disk(const char* hashed_password); | ||
212 | BOOL is_hex_string(U8* str, S32 len); | ||
213 | void show_first_run_dialog(); | ||
214 | void first_run_dialog_callback(S32 option, void* userdata); | ||
215 | void set_startup_status(const F32 frac, const char* string, const char* msg); | ||
216 | void on_userserver_name_resolved( BOOL success, const LLString& host_name, U32 ip, void* userdata ); | ||
217 | void login_alert_status(S32 option, void* user_data); | ||
218 | void update_app(BOOL mandatory, const std::string& message); | ||
219 | void update_dialog_callback(S32 option, void *userdata); | ||
220 | void login_packet_failed(void**, S32 result); | ||
221 | void use_circuit_callback(void**, S32 result); | ||
222 | void register_viewer_callbacks(LLMessageSystem* msg); | ||
223 | void init_stat_view(); | ||
224 | void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32); | ||
225 | void dialog_choose_gender_first_start(); | ||
226 | void callback_choose_gender(S32 option, void* userdata); | ||
227 | void init_start_screen(S32 location_id); | ||
228 | void release_start_screen(); | ||
229 | void process_connect_to_userserver(LLMessageSystem* msg, void**); | ||
230 | |||
231 | |||
232 | // | ||
233 | // exported functionality | ||
234 | // | ||
235 | |||
236 | // | ||
237 | // local classes | ||
238 | // | ||
239 | class LLGestureInventoryFetchObserver : public LLInventoryFetchObserver | ||
240 | { | ||
241 | public: | ||
242 | LLGestureInventoryFetchObserver() {} | ||
243 | virtual void done() | ||
244 | { | ||
245 | // we've downloaded all the items, so repaint the dialog | ||
246 | LLFloaterGesture::refreshAll(); | ||
247 | |||
248 | gInventory.removeObserver(this); | ||
249 | delete this; | ||
250 | } | ||
251 | }; | ||
252 | |||
253 | |||
254 | |||
255 | // Returns FALSE to skip other idle processing. Should only return | ||
256 | // TRUE when all initialization done. | ||
257 | BOOL idle_startup() | ||
258 | { | ||
259 | LLMemType mt1(LLMemType::MTYPE_STARTUP); | ||
260 | |||
261 | const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay"); | ||
262 | const F32 TIMEOUT_SECONDS = 5.f; | ||
263 | const S32 MAX_TIMEOUT_COUNT = 3; | ||
264 | static LLTimer timeout; | ||
265 | static S32 timeout_count = 0; | ||
266 | |||
267 | static LLTimer login_time; | ||
268 | |||
269 | // until this is encapsulated, this little hack for the | ||
270 | // auth/transform loop will do. | ||
271 | static F32 progress = 0.10f; | ||
272 | |||
273 | static std::string auth_uri; | ||
274 | static std::string auth_method; | ||
275 | static std::string auth_desc; | ||
276 | static std::string auth_message; | ||
277 | static LLString firstname; | ||
278 | static LLString lastname; | ||
279 | static LLString password; | ||
280 | static std::vector<const char*> requested_options; | ||
281 | |||
282 | static U32 region_size = 256; | ||
283 | static F32 region_scale = 1.f; | ||
284 | static U64 first_sim_handle = 0; | ||
285 | static LLHost first_sim; | ||
286 | static std::string first_sim_seed_cap; | ||
287 | |||
288 | static LLVector3 initial_sun_direction(1.f, 0.f, 0.f); | ||
289 | static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server | ||
290 | static LLVector3 agent_start_look_at(1.0f, 0.f, 0.f); | ||
291 | static std::string agent_start_location = "safe"; | ||
292 | |||
293 | // last location by default | ||
294 | static S32 agent_location_id = START_LOCATION_ID_LAST; | ||
295 | static S32 location_which = START_LOCATION_ID_LAST; | ||
296 | |||
297 | static BOOL show_connect_box = TRUE; | ||
298 | static BOOL remember_password = TRUE; | ||
299 | |||
300 | static BOOL stipend_since_login = FALSE; | ||
301 | |||
302 | static BOOL samename = FALSE; | ||
303 | |||
304 | static BOOL did_precache = FALSE; | ||
305 | |||
306 | BOOL do_normal_idle = FALSE; | ||
307 | |||
308 | // HACK: These are things from the main loop that usually aren't done | ||
309 | // until initialization is complete, but need to be done here for things | ||
310 | // to work. | ||
311 | gIdleCallbacks.callFunctions(); | ||
312 | gViewerWindow->handlePerFrameHover(); | ||
313 | LLMortician::updateClass(); | ||
314 | |||
315 | if (gNoRender) | ||
316 | { | ||
317 | // HACK, skip optional updates if you're running drones | ||
318 | gSkipOptionalUpdate = TRUE; | ||
319 | } | ||
320 | else | ||
321 | { | ||
322 | // Update images? | ||
323 | gImageList.updateImages(0.01f); | ||
324 | } | ||
325 | |||
326 | if (STATE_FIRST == gStartupState) | ||
327 | { | ||
328 | gViewerWindow->showCursor(); | ||
329 | gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); | ||
330 | |||
331 | ///////////////////////////////////////////////// | ||
332 | // | ||
333 | // Initialize stuff that doesn't need data from userserver/simulators | ||
334 | // | ||
335 | |||
336 | if (gFeatureManagerp->isSafe()) | ||
337 | { | ||
338 | gViewerWindow->alertXml("DisplaySetToSafe"); | ||
339 | } | ||
340 | else if (gSavedSettings.getS32("LastFeatureVersion") < gFeatureManagerp->getVersion()) | ||
341 | { | ||
342 | if (gSavedSettings.getS32("LastFeatureVersion") != 0) | ||
343 | { | ||
344 | gViewerWindow->alertXml("DisplaySetToRecommended"); | ||
345 | } | ||
346 | } | ||
347 | gSavedSettings.setS32("LastFeatureVersion", gFeatureManagerp->getVersion()); | ||
348 | |||
349 | LLString xml_file = LLUI::locateSkin("xui_version.xml"); | ||
350 | LLXMLNodePtr root; | ||
351 | bool xml_ok = false; | ||
352 | if (LLXMLNode::parseFile(xml_file, root, NULL)) | ||
353 | { | ||
354 | if( (root->hasName("xui_version") ) ) | ||
355 | { | ||
356 | LLString value = root->getValue(); | ||
357 | F32 version = 0.0f; | ||
358 | LLString::convertToF32(value, version); | ||
359 | if (version >= 1.0f) | ||
360 | { | ||
361 | xml_ok = true; | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | if (!xml_ok) | ||
366 | { | ||
367 | // XUI:translate (maybe - very unlikely error message) | ||
368 | // Note: alerts.xml may be invalid - if this gets translated it will need to be in the code | ||
369 | LLString bad_xui_msg = "An error occured while updating Second Life. Please download the latest version from www.secondlife.com."; | ||
370 | app_early_exit(bad_xui_msg); | ||
371 | } | ||
372 | // | ||
373 | // Statistics stuff | ||
374 | // | ||
375 | |||
376 | // Load autopilot and stats stuff | ||
377 | gAgentPilot.load(gSavedSettings.getString("StatsPilotFile").c_str()); | ||
378 | gFrameStats.setFilename(gSavedSettings.getString("StatsFile")); | ||
379 | gFrameStats.setSummaryFilename(gSavedSettings.getString("StatsSummaryFile")); | ||
380 | |||
381 | //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps")); | ||
382 | |||
383 | // Load the throttle settings | ||
384 | gViewerThrottle.load(); | ||
385 | |||
386 | // | ||
387 | // Initialize messaging system | ||
388 | // | ||
389 | llinfos << "Initializing messaging system..." << llendl; | ||
390 | |||
391 | std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); | ||
392 | |||
393 | FILE* found_template = NULL; | ||
394 | found_template = LLFile::fopen(message_template_path.c_str(), "r"); | ||
395 | if (found_template) | ||
396 | { | ||
397 | fclose(found_template); | ||
398 | |||
399 | if(!start_messaging_system( | ||
400 | message_template_path, | ||
401 | gAgent.mViewerPort, | ||
402 | LL_VERSION_MAJOR, | ||
403 | LL_VERSION_MINOR, | ||
404 | LL_VERSION_PATCH, | ||
405 | FALSE, | ||
406 | std::string())) | ||
407 | { | ||
408 | std::string msg = llformat("Unable to start networking, error %d", gMessageSystem->getErrorCode()); | ||
409 | app_early_exit(msg); | ||
410 | } | ||
411 | } | ||
412 | else | ||
413 | { | ||
414 | app_early_exit("Unable to initialize communications."); | ||
415 | } | ||
416 | |||
417 | if(gMessageSystem && gMessageSystem->isOK()) | ||
418 | { | ||
419 | // Initialize all of the callbacks in case of bad message | ||
420 | // system data | ||
421 | LLMessageSystem* msg = gMessageSystem; | ||
422 | msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE, | ||
423 | invalid_message_callback, | ||
424 | NULL); | ||
425 | msg->setExceptionFunc(MX_PACKET_TOO_SHORT, | ||
426 | invalid_message_callback, | ||
427 | NULL); | ||
428 | msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET, | ||
429 | invalid_message_callback, | ||
430 | NULL); | ||
431 | msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE, | ||
432 | invalid_message_callback, | ||
433 | NULL); | ||
434 | |||
435 | gErrorStream.setUTCTimestamp(gLogUTC); | ||
436 | if (gSavedSettings.getBOOL("LogMessages") || gLogMessages) | ||
437 | { | ||
438 | llinfos << "Message logging activated!" << llendl; | ||
439 | msg->startLogging(); | ||
440 | } | ||
441 | |||
442 | // start the xfer system. by default, choke the downloads | ||
443 | // a lot... | ||
444 | const S32 VIEWER_MAX_XFER = 3; | ||
445 | start_xfer_manager(gVFS); | ||
446 | gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER); | ||
447 | F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle"); | ||
448 | if (xfer_throttle_bps > 1.f) | ||
449 | { | ||
450 | gXferManager->setUseAckThrottling(TRUE); | ||
451 | gXferManager->setAckThrottleBPS(xfer_throttle_bps); | ||
452 | } | ||
453 | gAssetStorage = new LLViewerAssetStorage(msg, gXferManager, gVFS, gUserServer); | ||
454 | |||
455 | msg->mPacketRing.setDropPercentage(gPacketDropPercentage); | ||
456 | if (gInBandwidth != 0.f) | ||
457 | { | ||
458 | llinfos << "Setting packetring incoming bandwidth to " << gInBandwidth << llendl; | ||
459 | msg->mPacketRing.setUseInThrottle(TRUE); | ||
460 | msg->mPacketRing.setInBandwidth(gInBandwidth); | ||
461 | } | ||
462 | if (gOutBandwidth != 0.f) | ||
463 | { | ||
464 | llinfos << "Setting packetring outgoing bandwidth to " << gOutBandwidth << llendl; | ||
465 | msg->mPacketRing.setUseOutThrottle(TRUE); | ||
466 | msg->mPacketRing.setOutBandwidth(gOutBandwidth); | ||
467 | } | ||
468 | } | ||
469 | |||
470 | // initialize the economy | ||
471 | gGlobalEconomy = new LLGlobalEconomy(); | ||
472 | |||
473 | //--------------------------------------------------------------------- | ||
474 | // LibXUL (Mozilla) initialization | ||
475 | //--------------------------------------------------------------------- | ||
476 | #if LL_LIBXUL_ENABLED | ||
477 | set_startup_status(0.48f, "Initializing embedded web browser...", gAgent.mMOTD.c_str()); | ||
478 | display_startup(); | ||
479 | |||
480 | #if LL_DARWIN | ||
481 | // For Mac OS, we store both the shared libraries and the runtime files (chrome/, plugins/, etc) in | ||
482 | // Second Life.app/Contents/MacOS/. This matches the way Firefox is distributed on the Mac. | ||
483 | std::string profileBaseDir(gDirUtilp->getExecutableDir()); | ||
484 | #else | ||
485 | std::string profileBaseDir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); | ||
486 | profileBaseDir += gDirUtilp->getDirDelimiter(); | ||
487 | #ifdef LL_DEBUG | ||
488 | profileBaseDir += "mozilla_debug"; | ||
489 | #else | ||
490 | profileBaseDir += "mozilla"; | ||
491 | #endif | ||
492 | #endif | ||
493 | LLMozLib::getInstance()->init( profileBaseDir, gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) ); | ||
494 | |||
495 | std::ostringstream codec; | ||
496 | codec << "[Second Life " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << "." << LL_VERSION_BUILD << "]"; | ||
497 | LLMozLib::getInstance()->setBrowserAgentId( codec.str() ); | ||
498 | #endif | ||
499 | |||
500 | //------------------------------------------------- | ||
501 | // Init audio, which may be needed for prefs dialog | ||
502 | // or audio cues in connection UI. | ||
503 | //------------------------------------------------- | ||
504 | |||
505 | if (gUseAudio) | ||
506 | { | ||
507 | #if LL_FMOD | ||
508 | gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD(); | ||
509 | #else | ||
510 | gAudiop = NULL; | ||
511 | #endif | ||
512 | |||
513 | if (gAudiop) | ||
514 | { | ||
515 | #if LL_WINDOWS | ||
516 | // FMOD on Windows needs the window handle to stop playing audio | ||
517 | // when window is minimized. JC | ||
518 | void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); | ||
519 | #else | ||
520 | void* window_handle = NULL; | ||
521 | #endif | ||
522 | BOOL init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle); | ||
523 | if(!init) | ||
524 | { | ||
525 | llwarns << "Unable to initialize audio engine" << llendl; | ||
526 | } | ||
527 | gAudiop->setMuted(TRUE); | ||
528 | } | ||
529 | } | ||
530 | |||
531 | if (LLTimer::knownBadTimer()) | ||
532 | { | ||
533 | llwarns << "Unreliable timers detected (may be bad PCI chipset)!!" << llendl; | ||
534 | } | ||
535 | |||
536 | // Get ready to show the login dialog | ||
537 | if (!gConnectToSomething) | ||
538 | { | ||
539 | // Don't use a session token, and generate a random user id | ||
540 | gAgentID.generate(); | ||
541 | gAgentSessionID = LLUUID::null; | ||
542 | |||
543 | gStartupState = STATE_WORLD_INIT; | ||
544 | return do_normal_idle; | ||
545 | } | ||
546 | else if (!gRunLocal) | ||
547 | { | ||
548 | // | ||
549 | // Log on to userserver | ||
550 | // | ||
551 | if( !gCmdLineFirstName.empty() | ||
552 | && !gCmdLineLastName.empty() | ||
553 | && !gCmdLinePassword.empty()) | ||
554 | { | ||
555 | firstname = gCmdLineFirstName; | ||
556 | lastname = gCmdLineLastName; | ||
557 | |||
558 | LLMD5 pass((unsigned char*)gCmdLinePassword.c_str()); | ||
559 | char md5pass[33]; | ||
560 | pass.hex_digest(md5pass); | ||
561 | password = md5pass; | ||
562 | |||
563 | remember_password = gSavedSettings.getBOOL("RememberPassword"); | ||
564 | show_connect_box = FALSE; | ||
565 | } | ||
566 | else if (gAutoLogin || gSavedSettings.getBOOL("AutoLogin")) | ||
567 | { | ||
568 | firstname = gSavedSettings.getString("FirstName"); | ||
569 | lastname = gSavedSettings.getString("LastName"); | ||
570 | password = load_password_from_disk(); | ||
571 | remember_password = TRUE; | ||
572 | show_connect_box = FALSE; | ||
573 | } | ||
574 | else | ||
575 | { | ||
576 | // if not automatically logging in, display login dialog | ||
577 | // until a valid userserver is selected | ||
578 | firstname = gSavedSettings.getString("FirstName"); | ||
579 | lastname = gSavedSettings.getString("LastName"); | ||
580 | password = load_password_from_disk(); | ||
581 | remember_password = gSavedSettings.getBOOL("RememberPassword"); | ||
582 | show_connect_box = TRUE; | ||
583 | } | ||
584 | |||
585 | // Go to the next startup state | ||
586 | gStartupState++; | ||
587 | return do_normal_idle; | ||
588 | } | ||
589 | else | ||
590 | { | ||
591 | gStartupState++; | ||
592 | return do_normal_idle; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | if (STATE_LOGIN_SHOW == gStartupState) | ||
597 | { | ||
598 | gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); | ||
599 | // Push our window frontmost | ||
600 | gViewerWindow->getWindow()->show(); | ||
601 | |||
602 | timeout_count = 0; | ||
603 | |||
604 | if (gConnectToSomething && !gRunLocal) | ||
605 | { | ||
606 | if (show_connect_box) | ||
607 | { | ||
608 | if (gNoRender) | ||
609 | { | ||
610 | llerrs << "Need to autologin or use command line with norender!" << llendl; | ||
611 | } | ||
612 | // Make sure the process dialog doesn't hide things | ||
613 | gViewerWindow->setShowProgress(FALSE); | ||
614 | |||
615 | // Show the login dialog | ||
616 | login_show(); | ||
617 | |||
618 | // connect dialog is already shown, so fill in the names | ||
619 | LLPanelLogin::setFields( firstname, lastname, password, remember_password ); | ||
620 | LLPanelLogin::giveFocus(); | ||
621 | |||
622 | gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); | ||
623 | |||
624 | gStartupState++; | ||
625 | } | ||
626 | else | ||
627 | { | ||
628 | // skip directly to message template verification | ||
629 | gStartupState = STATE_LOGIN_CLEANUP; | ||
630 | } | ||
631 | } | ||
632 | else | ||
633 | { | ||
634 | gMessageSystem->setCircuitProtection(FALSE); | ||
635 | gStartupState = STATE_LOGIN_CLEANUP; | ||
636 | } | ||
637 | |||
638 | timeout.reset(); | ||
639 | return do_normal_idle; | ||
640 | } | ||
641 | |||
642 | if (STATE_LOGIN_WAIT == gStartupState) | ||
643 | { | ||
644 | // Don't do anything. Wait for the login view to call the login_callback, | ||
645 | // which will push us to the next state. | ||
646 | |||
647 | // Sleep so we don't spin the CPU | ||
648 | ms_sleep(1); | ||
649 | return do_normal_idle; | ||
650 | } | ||
651 | |||
652 | if (STATE_LOGIN_CLEANUP == gStartupState) | ||
653 | { | ||
654 | if (show_connect_box) | ||
655 | { | ||
656 | // Load all the name information out of the login view | ||
657 | LLPanelLogin::getFields(firstname, lastname, password, remember_password); | ||
658 | |||
659 | // HACK: Try to make not jump on login | ||
660 | gKeyboard->resetKeys(); | ||
661 | } | ||
662 | |||
663 | if (!firstname.empty() && !lastname.empty()) | ||
664 | { | ||
665 | gSavedSettings.setString("FirstName", firstname); | ||
666 | gSavedSettings.setString("LastName", lastname); | ||
667 | |||
668 | llinfos << "Attempting login as: " << firstname << " " << lastname << llendl; | ||
669 | write_debug("Attempting login as: "); | ||
670 | write_debug(firstname); | ||
671 | write_debug(" "); | ||
672 | write_debug(lastname); | ||
673 | write_debug("\n"); | ||
674 | } | ||
675 | |||
676 | // create necessary directories | ||
677 | // *FIX: these mkdir's should error check | ||
678 | gDirUtilp->setLindenUserDir(firstname.c_str(), lastname.c_str()); | ||
679 | |||
680 | |||
681 | LLFile::mkdir(gDirUtilp->getLindenUserDir().c_str()); | ||
682 | |||
683 | // the mute list is loaded in the llmutelist class. | ||
684 | |||
685 | gSavedSettings.loadFromFile(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,"overrides.xml")); | ||
686 | |||
687 | // handle the per account settings setup | ||
688 | strcpy(gPerAccountSettingsFileName, gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, DEFAULT_SETTINGS_FILE).c_str()); | ||
689 | |||
690 | // per account settings. Set defaults here if not found. If we get a bunch of these, eventually move to a function. | ||
691 | gSavedPerAccountSettings.loadFromFile(gPerAccountSettingsFileName); | ||
692 | |||
693 | // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation | ||
694 | // and startup time is close enough if we don't have a real value. | ||
695 | if (gSavedPerAccountSettings.getU32("LastLogoff") == 0) | ||
696 | { | ||
697 | gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); | ||
698 | } | ||
699 | |||
700 | //Default the path if one isn't set. | ||
701 | if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty()) | ||
702 | { | ||
703 | gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir()); | ||
704 | gSavedPerAccountSettings.setString("InstantMessageLogPath",gDirUtilp->getChatLogsDir()); | ||
705 | } | ||
706 | else | ||
707 | { | ||
708 | gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath")); | ||
709 | } | ||
710 | |||
711 | gDirUtilp->setPerAccountChatLogsDir(firstname.c_str(), lastname.c_str()); | ||
712 | |||
713 | LLFile::mkdir(gDirUtilp->getChatLogsDir().c_str()); | ||
714 | LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir().c_str()); | ||
715 | |||
716 | |||
717 | #if LL_WINDOWS | ||
718 | if (gSavedSettings.getBOOL("UseDebugLogin") && show_connect_box) | ||
719 | #else | ||
720 | if (show_connect_box) | ||
721 | #endif | ||
722 | { | ||
723 | LLString server_label; | ||
724 | S32 domain_name_index; | ||
725 | LLPanelLogin::getServer( server_label, domain_name_index ); | ||
726 | gUserServerChoice = (EUserServerDomain) domain_name_index; | ||
727 | gSavedSettings.setS32("ServerChoice", gUserServerChoice); | ||
728 | if (gUserServerChoice == USERSERVER_OTHER) | ||
729 | { | ||
730 | gUserServer.setHostByName( server_label.c_str() ); | ||
731 | snprintf(gUserServerName, MAX_STRING, "%s", server_label.c_str()); | ||
732 | } | ||
733 | } | ||
734 | |||
735 | if (show_connect_box) | ||
736 | { | ||
737 | LLString location; | ||
738 | LLPanelLogin::getLocation( location ); | ||
739 | LLURLSimString::setString( location ); | ||
740 | LLPanelLogin::close(); | ||
741 | } | ||
742 | |||
743 | //For HTML parsing in text boxes. | ||
744 | LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") ); | ||
745 | LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &process_secondlife_url ); | ||
746 | |||
747 | //------------------------------------------------- | ||
748 | // Handle startup progress screen | ||
749 | //------------------------------------------------- | ||
750 | |||
751 | // on startup the user can request to go to their home, | ||
752 | // their last location, or some URL "-url //sim/x/y[/z]" | ||
753 | // All accounts have both a home and a last location, and we don't support | ||
754 | // more locations than that. Choose the appropriate one. JC | ||
755 | if (LLURLSimString::parse()) | ||
756 | { | ||
757 | // a startup URL was specified | ||
758 | agent_location_id = START_LOCATION_ID_TELEHUB; | ||
759 | |||
760 | // doesn't really matter what location_which is, since | ||
761 | // agent_start_look_at will be overwritten when the | ||
762 | // UserLoginLocationReply arrives | ||
763 | location_which = START_LOCATION_ID_LAST; | ||
764 | } | ||
765 | else if (gSavedSettings.getBOOL("LoginLastLocation")) | ||
766 | { | ||
767 | agent_location_id = START_LOCATION_ID_LAST; // last location | ||
768 | location_which = START_LOCATION_ID_LAST; | ||
769 | } | ||
770 | else | ||
771 | { | ||
772 | agent_location_id = START_LOCATION_ID_HOME; // home | ||
773 | location_which = START_LOCATION_ID_HOME; | ||
774 | } | ||
775 | |||
776 | gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); | ||
777 | |||
778 | if (!gNoRender) | ||
779 | { | ||
780 | init_start_screen(agent_location_id); | ||
781 | } | ||
782 | |||
783 | // Display the startup progress bar. | ||
784 | gViewerWindow->setShowProgress(TRUE); | ||
785 | gViewerWindow->setProgressCancelButtonVisible(TRUE, "Quit"); | ||
786 | |||
787 | // Poke the VFS, which could potentially block for a while if | ||
788 | // Windows XP is acting up | ||
789 | set_startup_status(0.05f, "Verifying cache files (can take 60-90 seconds)...", NULL); | ||
790 | display_startup(); | ||
791 | |||
792 | gVFS->pokeFiles(); | ||
793 | |||
794 | // color init must be after saved settings loaded | ||
795 | init_colors(); | ||
796 | |||
797 | // Request userserver domain name | ||
798 | set_startup_status(0.05f, "Finding Server Domain Name...", NULL); | ||
799 | |||
800 | // We're prematurely switching out of this state because the | ||
801 | // userserver name resolver can potentiallly occur before reaching the end of the | ||
802 | // switch statement. Also, if it's done at the bottom, sometimes we will | ||
803 | // skip the userserver resolved step (in the local cases) - djs 09/24/03 | ||
804 | gStartupState++; | ||
805 | timeout.reset(); | ||
806 | |||
807 | switch( gUserServerChoice ) | ||
808 | { | ||
809 | case USERSERVER_AGNI: | ||
810 | gInProductionGrid = TRUE; | ||
811 | case USERSERVER_DMZ: | ||
812 | case USERSERVER_ADITI: | ||
813 | case USERSERVER_SIVA: | ||
814 | case USERSERVER_SHAKTI: | ||
815 | case USERSERVER_DURGA: | ||
816 | case USERSERVER_SOMA: | ||
817 | case USERSERVER_GANGA: | ||
818 | case USERSERVER_UMA: | ||
819 | { | ||
820 | const char* host_name = gUserServerDomainName[gUserServerChoice].mName; | ||
821 | sprintf(gUserServerName,"%s", host_name); | ||
822 | llinfos << "Resolving " << | ||
823 | gUserServerDomainName[gUserServerChoice].mLabel << | ||
824 | " userserver domain name " << host_name << llendl; | ||
825 | |||
826 | BOOL requested_domain_name = gAsyncHostByName.startRequest( host_name, on_userserver_name_resolved, NULL ); | ||
827 | if( !requested_domain_name ) | ||
828 | //BOOL resolved_domain_name = gUserServer.setHostByName( host_name ); | ||
829 | //if( !resolved_domain_name ) | ||
830 | { | ||
831 | llwarns << "setHostByName failed" << llendl; | ||
832 | |||
833 | LLStringBase<char>::format_map_t args; | ||
834 | args["[HOST_NAME]"] = host_name; | ||
835 | |||
836 | gViewerWindow->alertXml("UnableToConnect", args, login_alert_done ); | ||
837 | gStartupState = STATE_LOGIN_SHOW; | ||
838 | return FALSE; | ||
839 | } | ||
840 | break; | ||
841 | } | ||
842 | |||
843 | case USERSERVER_LOCAL: | ||
844 | llinfos << "Using local userserver" << llendl; | ||
845 | gUserServer.setAddress( LOOPBACK_ADDRESS_STRING ); | ||
846 | gStartupState = STATE_USERSERVER_RESOLVED; | ||
847 | break; | ||
848 | |||
849 | case USERSERVER_OTHER: | ||
850 | llinfos << "Userserver set explicitly" << llendl; | ||
851 | gStartupState = STATE_USERSERVER_RESOLVED; | ||
852 | break; | ||
853 | |||
854 | case USERSERVER_NONE: | ||
855 | default: | ||
856 | llerrs << "No userserver IP address specified" << llendl; | ||
857 | break; | ||
858 | } | ||
859 | return do_normal_idle; | ||
860 | } | ||
861 | |||
862 | if (STATE_RESOLVING_USERSERVER == gStartupState) | ||
863 | { | ||
864 | // Don't do anything. Wait for LL_WM_HOST_RESOLVED which is handled by LLAsyncHostByName, | ||
865 | // which calls on_userserver_name_resolved, which will push us to the next state. | ||
866 | if (timeout.getElapsedTimeF32() > TIMEOUT_SECONDS*3.f) | ||
867 | { | ||
868 | // Cancel the pending asynchostbyname request | ||
869 | |||
870 | gViewerWindow->alertXml("CanNotFindServer", | ||
871 | login_alert_status, NULL); | ||
872 | |||
873 | // Back up to login screen | ||
874 | gStartupState = STATE_LOGIN_SHOW; | ||
875 | gViewerStats->incStat(LLViewerStats::ST_LOGIN_TIMEOUT_COUNT); | ||
876 | } | ||
877 | ms_sleep(1); | ||
878 | return do_normal_idle; | ||
879 | } | ||
880 | |||
881 | if (STATE_USERSERVER_RESOLVED == gStartupState) | ||
882 | { | ||
883 | if (!gUserServer.isOk()) | ||
884 | { | ||
885 | LLStringBase<char>::format_map_t args; | ||
886 | args["[IP_ADDRESS]"] = u32_to_ip_string( gUserServer.getAddress() ); | ||
887 | |||
888 | gViewerWindow->alertXml("PleaseSelectServer", args, login_alert_done ); | ||
889 | |||
890 | gStartupState = STATE_LOGIN_SHOW; | ||
891 | return FALSE; | ||
892 | } | ||
893 | |||
894 | write_debug("Userserver: "); | ||
895 | char tmp_str[256]; | ||
896 | gUserServer.getIPString(tmp_str, 256); | ||
897 | write_debug(tmp_str); | ||
898 | write_debug("\n"); | ||
899 | |||
900 | gStartupState++; | ||
901 | } | ||
902 | |||
903 | if (STATE_MESSAGE_TEMPLATE_SEND == gStartupState) | ||
904 | { | ||
905 | set_startup_status(0.10f, "Verifying protocol version...", NULL); | ||
906 | |||
907 | LLHost mt_host; | ||
908 | if (!gRunLocal) | ||
909 | { | ||
910 | // open up user server circuit (trusted) | ||
911 | gMessageSystem->enableCircuit(gUserServer, TRUE); | ||
912 | mt_host = gUserServer; | ||
913 | } | ||
914 | else | ||
915 | { | ||
916 | mt_host = gAgentSimHost; | ||
917 | } | ||
918 | |||
919 | llinfos << "Verifying message template..." << llendl; | ||
920 | |||
921 | // register with the message system so it knows we're | ||
922 | // expecting this message | ||
923 | LLMessageSystem* msg = gMessageSystem; | ||
924 | msg->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, null_message_callback, NULL); | ||
925 | msg->newMessageFast(_PREHASH_SecuredTemplateChecksumRequest); | ||
926 | msg->nextBlockFast(_PREHASH_TokenBlock); | ||
927 | lldebugs << "random token: " << gTemplateToken << llendl; | ||
928 | msg->addUUIDFast(_PREHASH_Token, gTemplateToken); | ||
929 | msg->sendReliable(mt_host); | ||
930 | |||
931 | timeout.reset(); | ||
932 | gStartupState++; | ||
933 | return do_normal_idle; | ||
934 | } | ||
935 | |||
936 | if (STATE_MESSAGE_TEMPLATE_WAIT == gStartupState) | ||
937 | { | ||
938 | U32 remote_template_checksum = 0; | ||
939 | |||
940 | U8 major_version = 0; | ||
941 | U8 minor_version = 0; | ||
942 | U8 patch_version = 0; | ||
943 | U8 server_version = 0; | ||
944 | U32 flags = 0x0; | ||
945 | |||
946 | LLMessageSystem* msg = gMessageSystem; | ||
947 | while (msg->checkMessages(gFrameCount)) | ||
948 | { | ||
949 | if (msg->isMessageFast(_PREHASH_TemplateChecksumReply)) | ||
950 | { | ||
951 | LLUUID token; | ||
952 | msg->getUUID("TokenBlock", "Token", token); | ||
953 | if(token != gTemplateToken) | ||
954 | { | ||
955 | llwarns << "Incorrect token in template checksum reply: " | ||
956 | << token << llendl; | ||
957 | return do_normal_idle; | ||
958 | } | ||
959 | msg->getU32("DataBlock", "Checksum", remote_template_checksum); | ||
960 | msg->getU8 ("DataBlock", "MajorVersion", major_version); | ||
961 | msg->getU8 ("DataBlock", "MinorVersion", minor_version); | ||
962 | msg->getU8 ("DataBlock", "PatchVersion", patch_version); | ||
963 | msg->getU8 ("DataBlock", "ServerVersion", server_version); | ||
964 | msg->getU32("DataBlock", "Flags", flags); | ||
965 | |||
966 | BOOL update_available = FALSE; | ||
967 | BOOL mandatory = FALSE; | ||
968 | |||
969 | if (remote_template_checksum != msg->mMessageFileChecksum) | ||
970 | { | ||
971 | llinfos << "Message template out of sync" << llendl; | ||
972 | // Mandatory update -- message template checksum doesn't match | ||
973 | update_available = TRUE; | ||
974 | mandatory = TRUE; | ||
975 | } | ||
976 | |||
977 | BOOL quit = FALSE; | ||
978 | if (update_available) | ||
979 | { | ||
980 | if (show_connect_box) | ||
981 | { | ||
982 | update_app(mandatory, ""); | ||
983 | gStartupState = STATE_UPDATE_CHECK; | ||
984 | return FALSE; | ||
985 | } | ||
986 | else | ||
987 | { | ||
988 | quit = TRUE; | ||
989 | } | ||
990 | } | ||
991 | // Bail out and clean up circuit | ||
992 | if (quit) | ||
993 | { | ||
994 | msg->newMessageFast(_PREHASH_CloseCircuit); | ||
995 | msg->sendMessage( msg->getSender() ); | ||
996 | app_force_quit(NULL); | ||
997 | return FALSE; | ||
998 | } | ||
999 | |||
1000 | // If we get here, we've got a compatible message template | ||
1001 | |||
1002 | if (!mandatory) | ||
1003 | { | ||
1004 | llinfos << "Message template is current!" << llendl; | ||
1005 | } | ||
1006 | gStartupState = STATE_LOGIN_AUTH_INIT; | ||
1007 | timeout.reset(); | ||
1008 | // unregister with the message system so it knows we're no longer expecting this message | ||
1009 | msg->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, NULL, NULL); | ||
1010 | |||
1011 | msg->newMessageFast(_PREHASH_CloseCircuit); | ||
1012 | msg->sendMessage(gUserServer); | ||
1013 | msg->disableCircuit(gUserServer); | ||
1014 | if (gRunLocal) | ||
1015 | { | ||
1016 | msg->enableCircuit(gAgentSimHost, TRUE); | ||
1017 | |||
1018 | // Don't use a session token, and generate a random user id | ||
1019 | gAgentID.generate(); | ||
1020 | gAgentSessionID = LLUUID::null; | ||
1021 | |||
1022 | // Skip userserver queries. | ||
1023 | gStartupState = STATE_WORLD_INIT; | ||
1024 | } | ||
1025 | } | ||
1026 | } | ||
1027 | gMessageSystem->processAcks(); | ||
1028 | |||
1029 | if (timeout.getElapsedTimeF32() > TIMEOUT_SECONDS) | ||
1030 | { | ||
1031 | if (timeout_count > MAX_TIMEOUT_COUNT) | ||
1032 | { | ||
1033 | gViewerWindow->alertXml("SystemMayBeDown", | ||
1034 | login_alert_status, | ||
1035 | NULL); | ||
1036 | |||
1037 | // Back up to login screen | ||
1038 | gStartupState = STATE_LOGIN_SHOW; | ||
1039 | gViewerStats->incStat(LLViewerStats::ST_LOGIN_TIMEOUT_COUNT); | ||
1040 | } | ||
1041 | else | ||
1042 | { | ||
1043 | llinfos << "Resending on timeout" << llendl; | ||
1044 | gStartupState--; | ||
1045 | timeout_count++; | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | return do_normal_idle; | ||
1050 | } | ||
1051 | |||
1052 | if (STATE_UPDATE_CHECK == gStartupState) | ||
1053 | { | ||
1054 | return do_normal_idle; | ||
1055 | } | ||
1056 | |||
1057 | if(STATE_LOGIN_AUTH_INIT == gStartupState) | ||
1058 | { | ||
1059 | //#define LL_MINIMIAL_REQUESTED_OPTIONS | ||
1060 | lldebugs << "STATE_LOGIN_AUTH_INIT" << llendl; | ||
1061 | if (!gUserAuthp) | ||
1062 | { | ||
1063 | gUserAuthp = new LLUserAuth(); | ||
1064 | } | ||
1065 | requested_options.clear(); | ||
1066 | requested_options.push_back("inventory-root"); | ||
1067 | requested_options.push_back("inventory-skeleton"); | ||
1068 | //requested_options.push_back("inventory-meat"); | ||
1069 | //requested_options.push_back("inventory-skel-targets"); | ||
1070 | #if (!defined LL_MINIMIAL_REQUESTED_OPTIONS) | ||
1071 | if(gRequestInventoryLibrary) | ||
1072 | { | ||
1073 | requested_options.push_back("inventory-lib-root"); | ||
1074 | requested_options.push_back("inventory-lib-owner"); | ||
1075 | requested_options.push_back("inventory-skel-lib"); | ||
1076 | // requested_options.push_back("inventory-meat-lib"); | ||
1077 | } | ||
1078 | |||
1079 | requested_options.push_back("initial-outfit"); | ||
1080 | requested_options.push_back("gestures"); | ||
1081 | requested_options.push_back("event_categories"); | ||
1082 | requested_options.push_back("event_notifications"); | ||
1083 | requested_options.push_back("classified_categories"); | ||
1084 | //requested_options.push_back("inventory-targets"); | ||
1085 | requested_options.push_back("buddy-list"); | ||
1086 | requested_options.push_back("ui-config"); | ||
1087 | #endif | ||
1088 | requested_options.push_back("login-flags"); | ||
1089 | requested_options.push_back("global-textures"); | ||
1090 | if(gGodConnect) | ||
1091 | { | ||
1092 | gSavedSettings.setBOOL("UseDebugMenus", TRUE); | ||
1093 | requested_options.push_back("god-connect"); | ||
1094 | } | ||
1095 | auth_uri = getLoginURI(); | ||
1096 | auth_method = "login_to_simulator"; | ||
1097 | auth_desc = "Logging in. "; | ||
1098 | auth_desc += gSecondLife; | ||
1099 | auth_desc += " may appear frozen. Please wait."; | ||
1100 | ++gStartupState; | ||
1101 | } | ||
1102 | |||
1103 | if (STATE_LOGIN_AUTHENTICATE == gStartupState) | ||
1104 | { | ||
1105 | lldebugs << "STATE_LOGIN_AUTHENTICATE" << llendl; | ||
1106 | set_startup_status(progress, auth_desc.c_str(), auth_message.c_str()); | ||
1107 | progress += 0.02f; | ||
1108 | display_startup(); | ||
1109 | |||
1110 | std::stringstream start; | ||
1111 | if (LLURLSimString::parse()) | ||
1112 | { | ||
1113 | // a startup URL was specified | ||
1114 | std::stringstream unescaped_start; | ||
1115 | unescaped_start << "uri:" | ||
1116 | << LLURLSimString::sInstance.mSimName << "&" | ||
1117 | << LLURLSimString::sInstance.mX << "&" | ||
1118 | << LLURLSimString::sInstance.mY << "&" | ||
1119 | << LLURLSimString::sInstance.mZ; | ||
1120 | start << xml_escape_string(unescaped_start.str().c_str()); | ||
1121 | } | ||
1122 | else if (gSavedSettings.getBOOL("LoginLastLocation")) | ||
1123 | { | ||
1124 | start << "last"; | ||
1125 | } | ||
1126 | else | ||
1127 | { | ||
1128 | start << "home"; | ||
1129 | } | ||
1130 | |||
1131 | char hashed_mac_string[MD5HEX_STR_SIZE]; | ||
1132 | LLMD5 hashed_mac; | ||
1133 | hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); | ||
1134 | hashed_mac.finalize(); | ||
1135 | hashed_mac.hex_digest(hashed_mac_string); | ||
1136 | |||
1137 | gUserAuthp->authenticate( | ||
1138 | auth_uri.c_str(), | ||
1139 | auth_method.c_str(), | ||
1140 | firstname.c_str(), | ||
1141 | lastname.c_str(), | ||
1142 | password.c_str(), | ||
1143 | start.str().c_str(), | ||
1144 | gSkipOptionalUpdate, | ||
1145 | gAcceptTOS, | ||
1146 | gAcceptCriticalMessage, | ||
1147 | gViewerDigest, | ||
1148 | gLastExecFroze, | ||
1149 | requested_options, | ||
1150 | hashed_mac_string, | ||
1151 | gSerialNumber); | ||
1152 | // reset globals | ||
1153 | gAcceptTOS = FALSE; | ||
1154 | gAcceptCriticalMessage = FALSE; | ||
1155 | ++gStartupState; | ||
1156 | return do_normal_idle; | ||
1157 | } | ||
1158 | |||
1159 | if(STATE_LOGIN_NO_DATA_YET == gStartupState) | ||
1160 | { | ||
1161 | //lldebugs << "STATE_LOGIN_NO_DATA_YET" << llendl; | ||
1162 | if (!gUserAuthp) | ||
1163 | { | ||
1164 | llerrs << "No userauth in STATE_LOGIN_NO_DATA_YET!" << llendl; | ||
1165 | } | ||
1166 | // Process messages to keep from dropping circuit. | ||
1167 | LLMessageSystem* msg = gMessageSystem; | ||
1168 | while (msg->checkMessages(gFrameCount)) | ||
1169 | { | ||
1170 | } | ||
1171 | msg->processAcks(); | ||
1172 | LLUserAuth::UserAuthcode error = gUserAuthp->authResponse(); | ||
1173 | if(LLUserAuth::E_NO_RESPONSE_YET == error) | ||
1174 | { | ||
1175 | //llinfos << "waiting..." << llendl; | ||
1176 | return do_normal_idle; | ||
1177 | } | ||
1178 | ++gStartupState; | ||
1179 | progress += 0.01f; | ||
1180 | set_startup_status(progress, auth_desc.c_str(), auth_message.c_str()); | ||
1181 | return do_normal_idle; | ||
1182 | } | ||
1183 | |||
1184 | if(STATE_LOGIN_DOWNLOADING == gStartupState) | ||
1185 | { | ||
1186 | lldebugs << "STATE_LOGIN_DOWNLOADING" << llendl; | ||
1187 | if (!gUserAuthp) | ||
1188 | { | ||
1189 | llerrs << "No userauth in STATE_LOGIN_DOWNLOADING!" << llendl; | ||
1190 | } | ||
1191 | // Process messages to keep from dropping circuit. | ||
1192 | LLMessageSystem* msg = gMessageSystem; | ||
1193 | while (msg->checkMessages(gFrameCount)) | ||
1194 | { | ||
1195 | } | ||
1196 | msg->processAcks(); | ||
1197 | LLUserAuth::UserAuthcode error = gUserAuthp->authResponse(); | ||
1198 | if(LLUserAuth::E_DOWNLOADING == error) | ||
1199 | { | ||
1200 | //llinfos << "downloading..." << llendl; | ||
1201 | return do_normal_idle; | ||
1202 | } | ||
1203 | ++gStartupState; | ||
1204 | progress += 0.01f; | ||
1205 | set_startup_status(progress, "Processing Response...", auth_message.c_str()); | ||
1206 | return do_normal_idle; | ||
1207 | } | ||
1208 | |||
1209 | if(STATE_LOGIN_PROCESS_RESPONSE == gStartupState) | ||
1210 | { | ||
1211 | lldebugs << "STATE_LOGIN_PROCESS_RESPONSE" << llendl; | ||
1212 | std::ostringstream emsg; | ||
1213 | BOOL quit = FALSE; | ||
1214 | const char* login_response = NULL; | ||
1215 | const char* reason_response = NULL; | ||
1216 | const char* message_response = NULL; | ||
1217 | BOOL successful_login = FALSE; | ||
1218 | LLUserAuth::UserAuthcode error = gUserAuthp->authResponse(); | ||
1219 | // reset globals | ||
1220 | gAcceptTOS = FALSE; | ||
1221 | gAcceptCriticalMessage = FALSE; | ||
1222 | switch(error) | ||
1223 | { | ||
1224 | case LLUserAuth::E_OK: | ||
1225 | login_response = gUserAuthp->getResponse("login"); | ||
1226 | if(login_response && (0 == strcmp(login_response, "true"))) | ||
1227 | { | ||
1228 | // Yay, login! | ||
1229 | successful_login = TRUE; | ||
1230 | } | ||
1231 | else if(login_response && (0 == strcmp(login_response, "indeterminate"))) | ||
1232 | { | ||
1233 | llinfos << "Indeterminate login..." << llendl; | ||
1234 | auth_uri = gUserAuthp->getResponse("next_url"); | ||
1235 | auth_method = gUserAuthp->getResponse("next_method"); | ||
1236 | auth_message = gUserAuthp->getResponse("message"); | ||
1237 | if(auth_method.substr(0, 5) == "login") | ||
1238 | { | ||
1239 | auth_desc.assign("Authenticating..."); | ||
1240 | } | ||
1241 | else | ||
1242 | { | ||
1243 | auth_desc.assign("Performing account maintenance..."); | ||
1244 | } | ||
1245 | // ignoring the duration & options array for now. | ||
1246 | // Go back to authenticate. | ||
1247 | gStartupState = STATE_LOGIN_AUTHENTICATE; | ||
1248 | return do_normal_idle; | ||
1249 | } | ||
1250 | else | ||
1251 | { | ||
1252 | emsg << "Login failed.\n"; | ||
1253 | reason_response = gUserAuthp->getResponse("reason"); | ||
1254 | message_response = gUserAuthp->getResponse("message"); | ||
1255 | |||
1256 | if (gHideLinks && reason_response && (0 == strcmp(reason_response, "disabled"))) | ||
1257 | { | ||
1258 | emsg << gDisabledMessage; | ||
1259 | } | ||
1260 | else if (message_response) | ||
1261 | { | ||
1262 | emsg << message_response; | ||
1263 | } | ||
1264 | |||
1265 | if(reason_response && (0 == strcmp(reason_response, "tos"))) | ||
1266 | { | ||
1267 | if (show_connect_box) | ||
1268 | { | ||
1269 | llinfos << "Need tos agreement" << llendl; | ||
1270 | gStartupState = STATE_UPDATE_CHECK; | ||
1271 | LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS, | ||
1272 | message_response); | ||
1273 | tos_dialog->startModal(); | ||
1274 | // LLFloaterTOS deletes itself. | ||
1275 | return FALSE; | ||
1276 | } | ||
1277 | else | ||
1278 | { | ||
1279 | quit = TRUE; | ||
1280 | } | ||
1281 | } | ||
1282 | if(reason_response && (0 == strcmp(reason_response, "critical"))) | ||
1283 | { | ||
1284 | if (show_connect_box) | ||
1285 | { | ||
1286 | llinfos << "Need critical message" << llendl; | ||
1287 | gStartupState = STATE_UPDATE_CHECK; | ||
1288 | LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE, | ||
1289 | message_response); | ||
1290 | tos_dialog->startModal(); | ||
1291 | // LLFloaterTOS deletes itself. | ||
1292 | return FALSE; | ||
1293 | } | ||
1294 | else | ||
1295 | { | ||
1296 | quit = TRUE; | ||
1297 | } | ||
1298 | } | ||
1299 | if(reason_response && (0 == strcmp(reason_response, "key"))) | ||
1300 | { | ||
1301 | // Couldn't login because user/password is wrong | ||
1302 | // Clear the password | ||
1303 | password = ""; | ||
1304 | } | ||
1305 | if(reason_response && (0 == strcmp(reason_response, "update"))) | ||
1306 | { | ||
1307 | auth_message = gUserAuthp->getResponse("message"); | ||
1308 | if (show_connect_box) | ||
1309 | { | ||
1310 | update_app(TRUE, auth_message); | ||
1311 | gStartupState = STATE_UPDATE_CHECK; | ||
1312 | return FALSE; | ||
1313 | } | ||
1314 | else | ||
1315 | { | ||
1316 | quit = TRUE; | ||
1317 | } | ||
1318 | } | ||
1319 | if(reason_response && (0 == strcmp(reason_response, "optional"))) | ||
1320 | { | ||
1321 | llinfos << "Login got optional update" << llendl; | ||
1322 | auth_message = gUserAuthp->getResponse("message"); | ||
1323 | if (show_connect_box) | ||
1324 | { | ||
1325 | update_app(FALSE, auth_message); | ||
1326 | gStartupState = STATE_UPDATE_CHECK; | ||
1327 | gSkipOptionalUpdate = TRUE; | ||
1328 | return FALSE; | ||
1329 | } | ||
1330 | } | ||
1331 | } | ||
1332 | break; | ||
1333 | case LLUserAuth::E_COULDNT_RESOLVE_HOST: | ||
1334 | case LLUserAuth::E_SSL_PEER_CERTIFICATE: | ||
1335 | case LLUserAuth::E_UNHANDLED_ERROR: | ||
1336 | default: | ||
1337 | emsg << "Unable to connect to " << gSecondLife << ".\n"; | ||
1338 | emsg << gUserAuthp->errorMessage(); | ||
1339 | break; | ||
1340 | case LLUserAuth::E_SSL_CACERT: | ||
1341 | case LLUserAuth::E_SSL_CONNECT_ERROR: | ||
1342 | emsg << "Unable to establish a secure connection to the login server.\n"; | ||
1343 | emsg << gUserAuthp->errorMessage(); | ||
1344 | break; | ||
1345 | } | ||
1346 | |||
1347 | // Version update and we're not showing the dialog | ||
1348 | if(quit) | ||
1349 | { | ||
1350 | delete gUserAuthp; | ||
1351 | gUserAuthp = NULL; | ||
1352 | app_force_quit(NULL); | ||
1353 | return FALSE; | ||
1354 | } | ||
1355 | |||
1356 | if(successful_login) | ||
1357 | { | ||
1358 | if (!gUserAuthp) | ||
1359 | { | ||
1360 | llerrs << "No userauth on successful login!" << llendl; | ||
1361 | } | ||
1362 | |||
1363 | // unpack login data needed by the application | ||
1364 | const char* text; | ||
1365 | text = gUserAuthp->getResponse("agent_id"); | ||
1366 | if(text) gAgentID.set(text); | ||
1367 | write_debug("AgentID: "); | ||
1368 | write_debug(text); | ||
1369 | write_debug("\n"); | ||
1370 | |||
1371 | text = gUserAuthp->getResponse("session_id"); | ||
1372 | if(text) gAgentSessionID.set(text); | ||
1373 | write_debug("SessionID: "); | ||
1374 | write_debug(text); | ||
1375 | write_debug("\n"); | ||
1376 | |||
1377 | text = gUserAuthp->getResponse("secure_session_id"); | ||
1378 | if(text) gAgent.mSecureSessionID.set(text); | ||
1379 | |||
1380 | text = gUserAuthp->getResponse("first_name"); | ||
1381 | if(text) | ||
1382 | { | ||
1383 | // Remove quotes from string. Login.cgi sends these to force | ||
1384 | // names that look like numbers into strings. | ||
1385 | firstname.assign(text); | ||
1386 | LLString::replaceChar(firstname, '"', ' '); | ||
1387 | LLString::trim(firstname); | ||
1388 | } | ||
1389 | text = gUserAuthp->getResponse("last_name"); | ||
1390 | if(text) lastname.assign(text); | ||
1391 | gSavedSettings.setString("FirstName", firstname); | ||
1392 | gSavedSettings.setString("LastName", lastname); | ||
1393 | if (remember_password) | ||
1394 | { | ||
1395 | save_password_to_disk(password.c_str()); | ||
1396 | } | ||
1397 | else | ||
1398 | { | ||
1399 | save_password_to_disk(NULL); | ||
1400 | } | ||
1401 | gSavedSettings.setBOOL("RememberPassword", remember_password); | ||
1402 | gSavedSettings.setBOOL("LoginLastLocation", gSavedSettings.getBOOL("LoginLastLocation")); | ||
1403 | gSavedSettings.setBOOL("LoggedIn", TRUE); | ||
1404 | |||
1405 | text = gUserAuthp->getResponse("agent_access"); | ||
1406 | if(text && (text[0] == 'M')) | ||
1407 | { | ||
1408 | gAgent.mAccess = SIM_ACCESS_MATURE; | ||
1409 | } | ||
1410 | else | ||
1411 | { | ||
1412 | gAgent.mAccess = SIM_ACCESS_PG; | ||
1413 | } | ||
1414 | |||
1415 | text = gUserAuthp->getResponse("start_location"); | ||
1416 | if(text) agent_start_location.assign(text); | ||
1417 | text = gUserAuthp->getResponse("circuit_code"); | ||
1418 | if(text) | ||
1419 | { | ||
1420 | gMessageSystem->mOurCircuitCode = strtoul(text, NULL, 10); | ||
1421 | } | ||
1422 | const char* sim_ip_str = gUserAuthp->getResponse("sim_ip"); | ||
1423 | const char* sim_port_str = gUserAuthp->getResponse("sim_port"); | ||
1424 | if(sim_ip_str && sim_port_str) | ||
1425 | { | ||
1426 | U32 sim_port = strtoul(sim_port_str, NULL, 10); | ||
1427 | first_sim.set(sim_ip_str, sim_port); | ||
1428 | if (first_sim.isOk()) | ||
1429 | { | ||
1430 | gMessageSystem->enableCircuit(first_sim, TRUE); | ||
1431 | } | ||
1432 | } | ||
1433 | const char* region_x_str = gUserAuthp->getResponse("region_x"); | ||
1434 | const char* region_y_str = gUserAuthp->getResponse("region_y"); | ||
1435 | if(region_x_str && region_y_str) | ||
1436 | { | ||
1437 | U32 region_x = strtoul(region_x_str, NULL, 10); | ||
1438 | U32 region_y = strtoul(region_y_str, NULL, 10); | ||
1439 | first_sim_handle = to_region_handle(region_x, region_y); | ||
1440 | } | ||
1441 | |||
1442 | const char* look_at_str = gUserAuthp->getResponse("look_at"); | ||
1443 | if (look_at_str) | ||
1444 | { | ||
1445 | LLMemoryStream mstr((U8*)look_at_str, strlen(look_at_str)); | ||
1446 | LLSD sd = LLSDNotationParser::parse(mstr); | ||
1447 | agent_start_look_at = ll_vector3_from_sd(sd); | ||
1448 | } | ||
1449 | |||
1450 | text = gUserAuthp->getResponse("seed_capability"); | ||
1451 | if (text) first_sim_seed_cap = text; | ||
1452 | |||
1453 | text = gUserAuthp->getResponse("seconds_since_epoch"); | ||
1454 | if(text) | ||
1455 | { | ||
1456 | U32 server_utc_time = strtoul(text, NULL, 10); | ||
1457 | if(server_utc_time) | ||
1458 | { | ||
1459 | time_t now = time(NULL); | ||
1460 | gUTCOffset = (server_utc_time - now); | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1464 | const char* home_location = gUserAuthp->getResponse("home"); | ||
1465 | if(home_location) | ||
1466 | { | ||
1467 | LLMemoryStream mstr((U8*)home_location, strlen(home_location)); | ||
1468 | LLSD sd = LLSDNotationParser::parse(mstr); | ||
1469 | S32 region_x = sd["region_handle"][0].asInteger(); | ||
1470 | S32 region_y = sd["region_handle"][1].asInteger(); | ||
1471 | U64 region_handle = to_region_handle(region_x, region_y); | ||
1472 | LLVector3 position = ll_vector3_from_sd(sd["position"]); | ||
1473 | gAgent.setHomePosRegion(region_handle, position); | ||
1474 | } | ||
1475 | |||
1476 | gAgent.mMOTD.assign(gUserAuthp->getResponse("message")); | ||
1477 | LLUserAuth::options_t options; | ||
1478 | if(gUserAuthp->getOptions("inventory-root", options)) | ||
1479 | { | ||
1480 | LLUserAuth::response_t::iterator it; | ||
1481 | it = options[0].find("folder_id"); | ||
1482 | if(it != options[0].end()) | ||
1483 | { | ||
1484 | gAgent.mInventoryRootID.set((*it).second.c_str()); | ||
1485 | //gInventory.mock(gAgent.getInventoryRootID()); | ||
1486 | } | ||
1487 | } | ||
1488 | |||
1489 | options.clear(); | ||
1490 | if(gUserAuthp->getOptions("login-flags", options)) | ||
1491 | { | ||
1492 | LLUserAuth::response_t::iterator it; | ||
1493 | LLUserAuth::response_t::iterator no_flag = options[0].end(); | ||
1494 | it = options[0].find("ever_logged_in"); | ||
1495 | if(it != no_flag) | ||
1496 | { | ||
1497 | if((*it).second == "N") gAgent.setFirstLogin(TRUE); | ||
1498 | else gAgent.setFirstLogin(FALSE); | ||
1499 | } | ||
1500 | it = options[0].find("stipend_since_login"); | ||
1501 | if(it != no_flag) | ||
1502 | { | ||
1503 | if((*it).second == "Y") stipend_since_login = TRUE; | ||
1504 | } | ||
1505 | it = options[0].find("gendered"); | ||
1506 | if(it != no_flag) | ||
1507 | { | ||
1508 | if((*it).second == "Y") gAgent.setGenderChosen(TRUE); | ||
1509 | } | ||
1510 | it = options[0].find("daylight_savings"); | ||
1511 | if(it != no_flag) | ||
1512 | { | ||
1513 | if((*it).second == "Y") gPacificDaylightTime = TRUE; | ||
1514 | else gPacificDaylightTime = FALSE; | ||
1515 | } | ||
1516 | } | ||
1517 | options.clear(); | ||
1518 | if (gUserAuthp->getOptions("initial-outfit", options) | ||
1519 | && !options.empty()) | ||
1520 | { | ||
1521 | LLUserAuth::response_t::iterator it; | ||
1522 | LLUserAuth::response_t::iterator it_end = options[0].end(); | ||
1523 | it = options[0].find("folder_name"); | ||
1524 | if(it != it_end) | ||
1525 | { | ||
1526 | gInitialOutfit = (*it).second; | ||
1527 | } | ||
1528 | it = options[0].find("gender"); | ||
1529 | if (it != it_end) | ||
1530 | { | ||
1531 | gInitialOutfitGender = (*it).second; | ||
1532 | } | ||
1533 | } | ||
1534 | |||
1535 | options.clear(); | ||
1536 | if(gUserAuthp->getOptions("global-textures", options)) | ||
1537 | { | ||
1538 | // Extract sun and moon texture IDs. These are used | ||
1539 | // in the LLVOSky constructor, but I can't figure out | ||
1540 | // how to pass them in. JC | ||
1541 | LLUserAuth::response_t::iterator it; | ||
1542 | LLUserAuth::response_t::iterator no_texture = options[0].end(); | ||
1543 | it = options[0].find("sun_texture_id"); | ||
1544 | if(it != no_texture) | ||
1545 | { | ||
1546 | gSunTextureID.set((*it).second.c_str()); | ||
1547 | } | ||
1548 | it = options[0].find("moon_texture_id"); | ||
1549 | if(it != no_texture) | ||
1550 | { | ||
1551 | gMoonTextureID.set((*it).second.c_str()); | ||
1552 | } | ||
1553 | it = options[0].find("cloud_texture_id"); | ||
1554 | if(it != no_texture) | ||
1555 | { | ||
1556 | gCloudTextureID.set((*it).second.c_str()); | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | |||
1561 | // JC: gesture loading done below, when we have an asset system | ||
1562 | // in place. Don't delete/clear user_credentials until then. | ||
1563 | |||
1564 | if(gAgentID.notNull() | ||
1565 | && gAgentSessionID.notNull() | ||
1566 | && gMessageSystem->mOurCircuitCode | ||
1567 | && first_sim.isOk() | ||
1568 | && gAgent.mInventoryRootID.notNull()) | ||
1569 | { | ||
1570 | ++gStartupState; | ||
1571 | } | ||
1572 | else | ||
1573 | { | ||
1574 | if (gNoRender) | ||
1575 | { | ||
1576 | llinfos << "Bad login - missing return values" << llendl; | ||
1577 | llinfos << emsg << llendl; | ||
1578 | exit(0); | ||
1579 | } | ||
1580 | // Bounce back to the login screen. | ||
1581 | LLStringBase<char>::format_map_t args; | ||
1582 | args["[ERROR_MESSAGE]"] = emsg.str(); | ||
1583 | gViewerWindow->alertXml("ErrorMessage", args, login_alert_done); | ||
1584 | gStartupState = STATE_LOGIN_SHOW; | ||
1585 | } | ||
1586 | } | ||
1587 | else | ||
1588 | { | ||
1589 | if (gNoRender) | ||
1590 | { | ||
1591 | llinfos << "Failed to login!" << llendl; | ||
1592 | llinfos << emsg << llendl; | ||
1593 | exit(0); | ||
1594 | } | ||
1595 | // Bounce back to the login screen. | ||
1596 | LLStringBase<char>::format_map_t args; | ||
1597 | args["[ERROR_MESSAGE]"] = emsg.str(); | ||
1598 | gViewerWindow->alertXml("ErrorMessage", args, login_alert_done); | ||
1599 | gStartupState = STATE_LOGIN_SHOW; | ||
1600 | } | ||
1601 | return do_normal_idle; | ||
1602 | } | ||
1603 | |||
1604 | //--------------------------------------------------------------------- | ||
1605 | // World Init | ||
1606 | //--------------------------------------------------------------------- | ||
1607 | if (STATE_WORLD_INIT == gStartupState) | ||
1608 | { | ||
1609 | set_startup_status(0.40f, "Initializing World...", gAgent.mMOTD.c_str()); | ||
1610 | display_startup(); | ||
1611 | // We should have an agent id by this point. | ||
1612 | llassert(!(gAgentID == LLUUID::null)); | ||
1613 | |||
1614 | // Finish agent initialization. (Requires gSavedSettings, builds camera) | ||
1615 | gAgent.init(); | ||
1616 | |||
1617 | // Since we connected, save off the settings so the user doesn't have to | ||
1618 | // type the name/password again if we crash. | ||
1619 | gSavedSettings.saveToFile(gSettingsFileName, TRUE); | ||
1620 | |||
1621 | // Create selection manager | ||
1622 | // Must be done before menus created, because many enabled callbacks | ||
1623 | // require its existance. | ||
1624 | gSelectMgr = new LLSelectMgr(); | ||
1625 | gParcelMgr = new LLViewerParcelMgr(); | ||
1626 | gHUDManager = new LLHUDManager(); | ||
1627 | gMuteListp = new LLMuteList(); | ||
1628 | |||
1629 | // | ||
1630 | // Initialize classes w/graphics stuff. | ||
1631 | // | ||
1632 | LLSurface::initClasses(); | ||
1633 | |||
1634 | LLFace::initClass(); | ||
1635 | |||
1636 | LLDrawable::initClass(); | ||
1637 | |||
1638 | // RN: don't initialize VO classes in drone mode, they are too closely tied to rendering | ||
1639 | LLViewerObject::initVOClasses(); | ||
1640 | |||
1641 | display_startup(); | ||
1642 | |||
1643 | // World initialization must be done after above window init | ||
1644 | gWorldp = new LLWorld(region_size, region_scale); | ||
1645 | |||
1646 | // User might have overridden far clip | ||
1647 | gWorldp->setLandFarClip( gAgent.mDrawDistance ); | ||
1648 | |||
1649 | if (!gRunLocal) | ||
1650 | { | ||
1651 | // Before we create the first region, we need to set the agent's mOriginGlobal | ||
1652 | // This is necessary because creating objects before this is set will result in a | ||
1653 | // bad mPositionAgent cache. | ||
1654 | |||
1655 | gAgent.initOriginGlobal(from_region_handle(first_sim_handle)); | ||
1656 | |||
1657 | gWorldp->addRegion(first_sim_handle, first_sim); | ||
1658 | |||
1659 | LLViewerRegion *regionp = gWorldp->getRegionFromHandle(first_sim_handle); | ||
1660 | llinfos << "Adding initial simulator " << regionp->getOriginGlobal() << llendl; | ||
1661 | |||
1662 | regionp->setSeedCapability(first_sim_seed_cap); | ||
1663 | |||
1664 | // Set agent's initial region to be the one we just created. | ||
1665 | gAgent.setRegion(regionp); | ||
1666 | |||
1667 | // Set agent's initial position, which will be read by LLVOAvatar when the avatar | ||
1668 | // object is created. I think this must be done after setting the region. JC | ||
1669 | gAgent.setPositionAgent(agent_start_position_region); | ||
1670 | } | ||
1671 | else | ||
1672 | { | ||
1673 | // With one simulator, assume region is at 0,0, hence has regionHandle 0 | ||
1674 | // VEFFECT: Login | ||
1675 | gWorldp->addRegion(0, gAgentSimHost); | ||
1676 | gAgent.setRegion(gWorldp->getRegionFromHandle(0)); | ||
1677 | } | ||
1678 | |||
1679 | display_startup(); | ||
1680 | |||
1681 | // Initialize UI | ||
1682 | if (!gNoRender) | ||
1683 | { | ||
1684 | // Initialize all our tools. Must be done after saved settings loaded. | ||
1685 | gToolMgr = new LLToolMgr(); | ||
1686 | gToolMgr->initTools(); | ||
1687 | // Quickly get something onscreen to look at. | ||
1688 | gViewerWindow->initWorldUI(); | ||
1689 | |||
1690 | // Move the progress view in front of the UI | ||
1691 | gViewerWindow->moveProgressViewToFront(); | ||
1692 | |||
1693 | gErrorStream.setFixedBuffer(gDebugView->mDebugConsolep); | ||
1694 | // set initial visibility of debug console | ||
1695 | gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); | ||
1696 | gDebugView->mStatViewp->setVisible(gSavedSettings.getBOOL("ShowDebugStats")); | ||
1697 | } | ||
1698 | |||
1699 | // | ||
1700 | // Set message handlers | ||
1701 | // | ||
1702 | llinfos << "Initializing communications..." << llendl; | ||
1703 | |||
1704 | // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted | ||
1705 | register_viewer_callbacks(gMessageSystem); | ||
1706 | |||
1707 | // Debugging info parameters | ||
1708 | gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms | ||
1709 | |||
1710 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
1711 | gMessageSystem->setTimeDecodes( TRUE ); // Time the decode of each msg | ||
1712 | gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode | ||
1713 | #endif | ||
1714 | |||
1715 | gXferManager->registerCallbacks(gMessageSystem); | ||
1716 | |||
1717 | gCacheName = new LLCacheName(gMessageSystem); | ||
1718 | gCacheName->addObserver(callback_cache_name); | ||
1719 | |||
1720 | // Load stored cache if possible | ||
1721 | load_name_cache(); | ||
1722 | |||
1723 | // Data storage for map of world. | ||
1724 | gWorldMap = new LLWorldMap(); | ||
1725 | |||
1726 | // register null callbacks for audio until the audio system is initialized | ||
1727 | gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL); | ||
1728 | gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL); | ||
1729 | |||
1730 | //reset statistics | ||
1731 | gViewerStats->resetStats(); | ||
1732 | |||
1733 | if (!gNoRender) | ||
1734 | { | ||
1735 | // | ||
1736 | // Set up all of our statistics UI stuff. | ||
1737 | // | ||
1738 | init_stat_view(); | ||
1739 | } | ||
1740 | |||
1741 | display_startup(); | ||
1742 | // | ||
1743 | // Set up region and surface defaults | ||
1744 | // | ||
1745 | |||
1746 | |||
1747 | // Sets up the parameters for the first simulator | ||
1748 | |||
1749 | llinfos << "Initializing camera..." << llendl; | ||
1750 | gFrameTime = totalTime(); | ||
1751 | F32 last_time = gFrameTimeSeconds; | ||
1752 | gFrameTimeSeconds = (S64)(gFrameTime - gStartTime)/SEC_TO_MICROSEC; | ||
1753 | |||
1754 | gFrameIntervalSeconds = gFrameTimeSeconds - last_time; | ||
1755 | if (gFrameIntervalSeconds < 0.f) | ||
1756 | { | ||
1757 | gFrameIntervalSeconds = 0.f; | ||
1758 | } | ||
1759 | |||
1760 | // Make sure agent knows correct aspect ratio | ||
1761 | gCamera->setViewHeightInPixels(gViewerWindow->getWindowDisplayHeight()); | ||
1762 | if (gViewerWindow->mWindow->getFullscreen()) | ||
1763 | { | ||
1764 | gCamera->setAspect(gViewerWindow->getDisplayAspectRatio()); | ||
1765 | } | ||
1766 | else | ||
1767 | { | ||
1768 | gCamera->setAspect( (F32) gViewerWindow->getWindowWidth() / (F32) gViewerWindow->getWindowHeight()); | ||
1769 | } | ||
1770 | |||
1771 | // Move agent to starting location. The position handed to us by | ||
1772 | // the space server is in global coordinates, but the agent frame | ||
1773 | // is in region local coordinates. Therefore, we need to adjust | ||
1774 | // the coordinates handed to us to fit in the local region. | ||
1775 | |||
1776 | gAgent.setPositionAgent(agent_start_position_region); | ||
1777 | gAgent.resetAxes(agent_start_look_at); | ||
1778 | gAgent.stopCameraAnimation(); | ||
1779 | gAgent.resetCamera(); | ||
1780 | |||
1781 | // Initialize global class data needed for surfaces (i.e. textures) | ||
1782 | if (!gNoRender) | ||
1783 | { | ||
1784 | llinfos << "Initializing sky..." << llendl; | ||
1785 | // Initialize all of the viewer object classes for the first time (doing things like texture fetches. | ||
1786 | gSky.init(initial_sun_direction); | ||
1787 | } | ||
1788 | |||
1789 | set_startup_status(0.45f, "Decoding UI images...", gAgent.mMOTD.c_str()); | ||
1790 | display_startup(); | ||
1791 | llinfos << "Decoding images..." << llendl; | ||
1792 | // For all images pre-loaded into viewer cache, decode them. | ||
1793 | // Need to do this AFTER we init the sky | ||
1794 | gImageList.decodeAllImages(); | ||
1795 | gStartupState++; | ||
1796 | |||
1797 | // JC - Do this as late as possible to increase likelihood Purify | ||
1798 | // will run. | ||
1799 | if (!gRunLocal) | ||
1800 | { | ||
1801 | LLMessageSystem* msg = gMessageSystem; | ||
1802 | if (!msg->mOurCircuitCode) | ||
1803 | { | ||
1804 | llwarns << "Attempting to connect to simulator with a zero circuit code!" << llendl; | ||
1805 | } | ||
1806 | msg->enableCircuit(first_sim, TRUE); | ||
1807 | // now, use the circuit info to tell simulator about us! | ||
1808 | llinfos << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << llendl; | ||
1809 | msg->newMessageFast(_PREHASH_UseCircuitCode); | ||
1810 | msg->nextBlockFast(_PREHASH_CircuitCode); | ||
1811 | msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode); | ||
1812 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
1813 | msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); | ||
1814 | msg->sendReliable( | ||
1815 | first_sim, | ||
1816 | MAX_TIMEOUT_COUNT, | ||
1817 | FALSE, | ||
1818 | TIMEOUT_SECONDS, | ||
1819 | use_circuit_callback, | ||
1820 | NULL); | ||
1821 | } | ||
1822 | |||
1823 | timeout.reset(); | ||
1824 | if (!gConnectToSomething) | ||
1825 | { | ||
1826 | gStartupState = STATE_MISC; | ||
1827 | } | ||
1828 | |||
1829 | return do_normal_idle; | ||
1830 | } | ||
1831 | |||
1832 | //--------------------------------------------------------------------- | ||
1833 | // LLMediaEngine Init | ||
1834 | //--------------------------------------------------------------------- | ||
1835 | if (STATE_QUICKTIME_INIT == gStartupState) | ||
1836 | { | ||
1837 | if (gViewerWindow) | ||
1838 | { | ||
1839 | if (gSavedSettings.getBOOL("MuteAudio")) | ||
1840 | { | ||
1841 | LLMediaEngine::updateClass( 0.0f ); | ||
1842 | } | ||
1843 | else | ||
1844 | { | ||
1845 | LLMediaEngine::updateClass( gSavedSettings.getF32( "MediaAudioVolume" ) ); | ||
1846 | } | ||
1847 | } | ||
1848 | |||
1849 | #if LL_QUICKTIME_ENABLED // windows only right now but will be ported to mac | ||
1850 | if (!gQuickTimeInitialized) | ||
1851 | { | ||
1852 | // initialize quicktime libraries (fails gracefully if quicktime not installed ($QUICKTIME) | ||
1853 | llinfos << "Initializing QuickTime...." << llendl; | ||
1854 | set_startup_status(0.47f, "Initializing QuickTime...", gAgent.mMOTD.c_str()); | ||
1855 | display_startup(); | ||
1856 | #if LL_WINDOWS | ||
1857 | // Only necessary/available on Windows. | ||
1858 | if ( InitializeQTML ( 0L ) != noErr ) | ||
1859 | { | ||
1860 | // quicktime init failed - turn off media engine support | ||
1861 | LLMediaEngine::getInstance ()->setAvailable ( FALSE ); | ||
1862 | llinfos << "...not found - unable to initialize." << llendl; | ||
1863 | set_startup_status(0.47f, "QuickTime not found - unable to initialize.", gAgent.mMOTD.c_str()); | ||
1864 | } | ||
1865 | else | ||
1866 | { | ||
1867 | llinfos << ".. initialized successfully." << llendl; | ||
1868 | set_startup_status(0.47f, "QuickTime initialized successfully.", gAgent.mMOTD.c_str()); | ||
1869 | }; | ||
1870 | #endif | ||
1871 | EnterMovies (); | ||
1872 | gQuickTimeInitialized = true; | ||
1873 | } | ||
1874 | #endif | ||
1875 | |||
1876 | gStartupState++; | ||
1877 | return do_normal_idle; | ||
1878 | } | ||
1879 | |||
1880 | //--------------------------------------------------------------------- | ||
1881 | // Agent Send | ||
1882 | //--------------------------------------------------------------------- | ||
1883 | if(STATE_WORLD_WAIT == gStartupState) | ||
1884 | { | ||
1885 | //llinfos << "Waiting for simulator ack...." << llendl; | ||
1886 | set_startup_status(0.49f, "Waiting for region handshake...", gAgent.mMOTD.c_str()); | ||
1887 | if(gGotUseCircuitCodeAck) | ||
1888 | { | ||
1889 | ++gStartupState; | ||
1890 | } | ||
1891 | LLMessageSystem* msg = gMessageSystem; | ||
1892 | while (msg->checkMessages(gFrameCount)) | ||
1893 | { | ||
1894 | } | ||
1895 | msg->processAcks(); | ||
1896 | return do_normal_idle; | ||
1897 | } | ||
1898 | |||
1899 | //--------------------------------------------------------------------- | ||
1900 | // Agent Send | ||
1901 | //--------------------------------------------------------------------- | ||
1902 | if (STATE_AGENT_SEND == gStartupState) | ||
1903 | { | ||
1904 | llinfos << "Connecting to region..." << llendl; | ||
1905 | set_startup_status(0.50f, "Connecting to region...", gAgent.mMOTD.c_str()); | ||
1906 | // register with the message system so it knows we're | ||
1907 | // expecting this message | ||
1908 | LLMessageSystem* msg = gMessageSystem; | ||
1909 | msg->setHandlerFuncFast( | ||
1910 | _PREHASH_AgentMovementComplete, | ||
1911 | process_agent_movement_complete, | ||
1912 | NULL); | ||
1913 | LLViewerRegion* regionp = gAgent.getRegion(); | ||
1914 | if(!gRunLocal && regionp) | ||
1915 | { | ||
1916 | send_complete_agent_movement(regionp->getHost()); | ||
1917 | gAssetStorage->setUpstream(regionp->getHost()); | ||
1918 | gCacheName->setUpstream(regionp->getHost()); | ||
1919 | msg->newMessageFast(_PREHASH_EconomyDataRequest); | ||
1920 | gAgent.sendReliableMessage(); | ||
1921 | } | ||
1922 | else | ||
1923 | { | ||
1924 | gStartupState++; | ||
1925 | } | ||
1926 | |||
1927 | // Create login effect | ||
1928 | // But not on first login, because you can't see your avatar then | ||
1929 | if (!gAgent.isFirstLogin()) | ||
1930 | { | ||
1931 | LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); | ||
1932 | effectp->setPositionGlobal(gAgent.getPositionGlobal()); | ||
1933 | effectp->setColor(LLColor4U(gAgent.getEffectColor())); | ||
1934 | gHUDManager->sendEffects(); | ||
1935 | } | ||
1936 | |||
1937 | gStartupState++; | ||
1938 | |||
1939 | timeout.reset(); | ||
1940 | return do_normal_idle; | ||
1941 | } | ||
1942 | |||
1943 | //--------------------------------------------------------------------- | ||
1944 | // Agent Wait | ||
1945 | //--------------------------------------------------------------------- | ||
1946 | if (STATE_AGENT_WAIT == gStartupState) | ||
1947 | { | ||
1948 | LLMessageSystem* msg = gMessageSystem; | ||
1949 | while (msg->checkMessages(gFrameCount)) | ||
1950 | { | ||
1951 | if (msg->isMessageFast(_PREHASH_AgentMovementComplete)) | ||
1952 | { | ||
1953 | gStartupState++; | ||
1954 | // Sometimes we have more than one message in the | ||
1955 | // queue. break out of this loop and continue | ||
1956 | // processing. If we don't, then this could skip one | ||
1957 | // or more login steps. | ||
1958 | break; | ||
1959 | } | ||
1960 | else | ||
1961 | { | ||
1962 | //llinfos << "Awaiting AvatarInitComplete, got " | ||
1963 | //<< msg->getMessageName() << llendl; | ||
1964 | } | ||
1965 | } | ||
1966 | msg->processAcks(); | ||
1967 | return do_normal_idle; | ||
1968 | } | ||
1969 | |||
1970 | //--------------------------------------------------------------------- | ||
1971 | // Inventory Send | ||
1972 | //--------------------------------------------------------------------- | ||
1973 | if (STATE_INVENTORY_SEND == gStartupState) | ||
1974 | { | ||
1975 | if (!gUserAuthp) | ||
1976 | { | ||
1977 | llerrs << "No userauth in STATE_INVENTORY_SEND!" << llendl; | ||
1978 | } | ||
1979 | |||
1980 | if (gConnectToSomething && !gRunLocal) | ||
1981 | { | ||
1982 | // unpack thin inventory | ||
1983 | LLUserAuth::options_t options; | ||
1984 | options.clear(); | ||
1985 | //bool dump_buffer = false; | ||
1986 | |||
1987 | if(gUserAuthp->getOptions("inventory-lib-root", options) | ||
1988 | && !options.empty()) | ||
1989 | { | ||
1990 | // should only be one | ||
1991 | LLUserAuth::response_t::iterator it; | ||
1992 | it = options[0].find("folder_id"); | ||
1993 | if(it != options[0].end()) | ||
1994 | { | ||
1995 | gInventoryLibraryRoot.set((*it).second.c_str()); | ||
1996 | } | ||
1997 | } | ||
1998 | options.clear(); | ||
1999 | if(gUserAuthp->getOptions("inventory-lib-owner", options) | ||
2000 | && !options.empty()) | ||
2001 | { | ||
2002 | // should only be one | ||
2003 | LLUserAuth::response_t::iterator it; | ||
2004 | it = options[0].find("agent_id"); | ||
2005 | if(it != options[0].end()) | ||
2006 | { | ||
2007 | gInventoryLibraryOwner.set((*it).second.c_str()); | ||
2008 | } | ||
2009 | } | ||
2010 | options.clear(); | ||
2011 | if(gUserAuthp->getOptions("inventory-skel-lib", options) | ||
2012 | && gInventoryLibraryOwner.notNull()) | ||
2013 | { | ||
2014 | if(!gInventory.loadSkeleton(options, gInventoryLibraryOwner)) | ||
2015 | { | ||
2016 | llwarns << "Problem loading inventory-skel-lib" << llendl; | ||
2017 | } | ||
2018 | } | ||
2019 | options.clear(); | ||
2020 | if(gUserAuthp->getOptions("inventory-skeleton", options)) | ||
2021 | { | ||
2022 | if(!gInventory.loadSkeleton(options, gAgent.getID())) | ||
2023 | { | ||
2024 | llwarns << "Problem loading inventory-skel-targets" | ||
2025 | << llendl; | ||
2026 | } | ||
2027 | } | ||
2028 | |||
2029 | options.clear(); | ||
2030 | if(gUserAuthp->getOptions("buddy-list", options)) | ||
2031 | { | ||
2032 | LLUserAuth::options_t::iterator it = options.begin(); | ||
2033 | LLUserAuth::options_t::iterator end = options.end(); | ||
2034 | LLAvatarTracker::buddy_map_t list; | ||
2035 | LLUUID agent_id; | ||
2036 | S32 has_rights = 0, given_rights = 0; | ||
2037 | for (; it != end; ++it) | ||
2038 | { | ||
2039 | LLUserAuth::response_t::const_iterator option_it; | ||
2040 | option_it = (*it).find("buddy_id"); | ||
2041 | if(option_it != (*it).end()) | ||
2042 | { | ||
2043 | agent_id.set((*option_it).second.c_str()); | ||
2044 | } | ||
2045 | option_it = (*it).find("buddy_rights_has"); | ||
2046 | if(option_it != (*it).end()) | ||
2047 | { | ||
2048 | has_rights = atoi((*option_it).second.c_str()); | ||
2049 | } | ||
2050 | option_it = (*it).find("buddy_rights_given"); | ||
2051 | if(option_it != (*it).end()) | ||
2052 | { | ||
2053 | given_rights = atoi((*option_it).second.c_str()); | ||
2054 | } | ||
2055 | list[agent_id] = new LLRelationship(given_rights, has_rights, false); | ||
2056 | } | ||
2057 | LLAvatarTracker::instance().addBuddyList(list); | ||
2058 | } | ||
2059 | |||
2060 | options.clear(); | ||
2061 | if(gUserAuthp->getOptions("ui-config", options)) | ||
2062 | { | ||
2063 | LLUserAuth::options_t::iterator it = options.begin(); | ||
2064 | LLUserAuth::options_t::iterator end = options.end(); | ||
2065 | for (; it != end; ++it) | ||
2066 | { | ||
2067 | LLUserAuth::response_t::const_iterator option_it; | ||
2068 | option_it = (*it).find("allow_first_life"); | ||
2069 | if(option_it != (*it).end()) | ||
2070 | { | ||
2071 | if (option_it->second == "Y") | ||
2072 | { | ||
2073 | LLPanelAvatar::sAllowFirstLife = TRUE; | ||
2074 | } | ||
2075 | } | ||
2076 | } | ||
2077 | } | ||
2078 | |||
2079 | options.clear(); | ||
2080 | if(gUserAuthp->getOptions("event_categories", options)) | ||
2081 | { | ||
2082 | LLEventInfo::loadCategories(options); | ||
2083 | } | ||
2084 | if(gUserAuthp->getOptions("event_notifications", options)) | ||
2085 | { | ||
2086 | gEventNotifier.load(options); | ||
2087 | } | ||
2088 | options.clear(); | ||
2089 | if(gUserAuthp->getOptions("classified_categories", options)) | ||
2090 | { | ||
2091 | LLClassifiedInfo::loadCategories(options); | ||
2092 | } | ||
2093 | gInventory.buildParentChildMap(); | ||
2094 | gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); | ||
2095 | gInventory.notifyObservers(); | ||
2096 | |||
2097 | // set up callbacks | ||
2098 | LLMessageSystem* msg = gMessageSystem; | ||
2099 | LLInventoryModel::registerCallbacks(msg); | ||
2100 | LLAvatarTracker::instance().registerCallbacks(msg); | ||
2101 | LLLandmark::registerCallbacks(msg); | ||
2102 | |||
2103 | // request mute list | ||
2104 | gMuteListp->requestFromServer(gAgent.getID()); | ||
2105 | |||
2106 | // Get money and ownership credit information | ||
2107 | msg->newMessageFast(_PREHASH_MoneyBalanceRequest); | ||
2108 | msg->nextBlockFast(_PREHASH_AgentData); | ||
2109 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
2110 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
2111 | msg->nextBlockFast(_PREHASH_MoneyData); | ||
2112 | msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); | ||
2113 | gAgent.sendReliableMessage(); | ||
2114 | |||
2115 | // request all group information | ||
2116 | // *FIX: This will not do the right thing if the message | ||
2117 | // gets there before the requestuserserverconnection | ||
2118 | // circuit is completed. | ||
2119 | gAgent.sendAgentDataUpdateRequest(); | ||
2120 | |||
2121 | |||
2122 | // NOTE: removed as part of user-privacy | ||
2123 | // enhancements. this information should be available from | ||
2124 | // login. 2006-10-16 Phoenix. | ||
2125 | // get the users that have been granted modify powers | ||
2126 | //msg->newMessageFast(_PREHASH_RequestGrantedProxies); | ||
2127 | //msg->nextBlockFast(_PREHASH_AgentData); | ||
2128 | //msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
2129 | //msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
2130 | //gAgent.sendReliableMessage(); | ||
2131 | |||
2132 | BOOL shown_at_exit = gSavedSettings.getBOOL("ShowInventory"); | ||
2133 | |||
2134 | // Create the inventory views | ||
2135 | LLInventoryView::showAgentInventory(); | ||
2136 | |||
2137 | // Hide the inventory if it wasn't shown at exit | ||
2138 | if(!shown_at_exit) | ||
2139 | { | ||
2140 | LLInventoryView::toggleVisibility(NULL); | ||
2141 | } | ||
2142 | } | ||
2143 | gStartupState++; | ||
2144 | return do_normal_idle; | ||
2145 | } | ||
2146 | |||
2147 | //--------------------------------------------------------------------- | ||
2148 | // Assert agent to userserver | ||
2149 | //--------------------------------------------------------------------- | ||
2150 | if (STATE_CONNECT_USERSERVER == gStartupState) | ||
2151 | { | ||
2152 | LLMessageSystem* msg = gMessageSystem; | ||
2153 | msg->enableCircuit(gUserServer, TRUE); | ||
2154 | msg->newMessage("ConnectAgentToUserserver"); | ||
2155 | msg->nextBlockFast(_PREHASH_AgentData); | ||
2156 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
2157 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
2158 | msg->sendReliable(gUserServer); | ||
2159 | gStartupState++; | ||
2160 | return do_normal_idle; | ||
2161 | } | ||
2162 | |||
2163 | //--------------------------------------------------------------------- | ||
2164 | // Misc | ||
2165 | //--------------------------------------------------------------------- | ||
2166 | if (STATE_MISC == gStartupState) | ||
2167 | { | ||
2168 | // Create a few objects if we don't actually have a world | ||
2169 | if (!gConnectToSomething) | ||
2170 | { | ||
2171 | // could add them here | ||
2172 | } | ||
2173 | |||
2174 | // We have a region, and just did a big inventory download. | ||
2175 | // We can estimate the user's connection speed, and set their | ||
2176 | // max bandwidth accordingly. JC | ||
2177 | if (gSavedSettings.getBOOL("FirstLoginThisInstall") | ||
2178 | && gUserAuthp) | ||
2179 | { | ||
2180 | // This is actually a pessimistic computation, because TCP may not have enough | ||
2181 | // time to ramp up on the (small) default inventory file to truly measure max | ||
2182 | // bandwidth. JC | ||
2183 | F64 rate_bps = gUserAuthp->getLastTransferRateBPS(); | ||
2184 | const F32 FAST_RATE_BPS = 600.f * 1024.f; | ||
2185 | const F32 FASTER_RATE_BPS = 750.f * 1024.f; | ||
2186 | F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); | ||
2187 | if (rate_bps > FASTER_RATE_BPS | ||
2188 | && rate_bps > max_bandwidth) | ||
2189 | { | ||
2190 | llinfos << "Fast network connection, increasing max bandwidth to " | ||
2191 | << FASTER_RATE_BPS/1024.f | ||
2192 | << " Kbps" << llendl; | ||
2193 | gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f); | ||
2194 | } | ||
2195 | else if (rate_bps > FAST_RATE_BPS | ||
2196 | && rate_bps > max_bandwidth) | ||
2197 | { | ||
2198 | llinfos << "Fast network connection, increasing max bandwidth to " | ||
2199 | << FAST_RATE_BPS/1024.f | ||
2200 | << " Kbps" << llendl; | ||
2201 | gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f); | ||
2202 | } | ||
2203 | } | ||
2204 | |||
2205 | // We're successfully logged in. | ||
2206 | gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE); | ||
2207 | |||
2208 | |||
2209 | // based on the comments, we've successfully logged in so we can delete the 'forced' | ||
2210 | // URL that the updater set in settings.ini (in a mostly paranoid fashion) | ||
2211 | LLString nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" ); | ||
2212 | if ( nextLoginLocation.length() ) | ||
2213 | { | ||
2214 | // clear it | ||
2215 | gSavedSettings.setString( "NextLoginLocation", "" ); | ||
2216 | |||
2217 | // and make sure it's saved | ||
2218 | gSavedSettings.saveToFile( gSettingsFileName, TRUE ); | ||
2219 | }; | ||
2220 | |||
2221 | if (!gNoRender) | ||
2222 | { | ||
2223 | // JC: Initializing audio requests many sounds for download. | ||
2224 | init_audio(); | ||
2225 | |||
2226 | // JC: Initialize "active" gestures. This may also trigger | ||
2227 | // many gesture downloads, if this is the user's first | ||
2228 | // time on this machine or -purge has been run. | ||
2229 | LLUserAuth::options_t gesture_options; | ||
2230 | if (gUserAuthp->getOptions("gestures", gesture_options)) | ||
2231 | { | ||
2232 | llinfos << "Gesture Manager loading " << gesture_options.size() | ||
2233 | << llendl; | ||
2234 | std::vector<LLUUID> item_ids; | ||
2235 | LLUserAuth::options_t::iterator resp_it; | ||
2236 | for (resp_it = gesture_options.begin(); | ||
2237 | resp_it != gesture_options.end(); | ||
2238 | ++resp_it) | ||
2239 | { | ||
2240 | const LLUserAuth::response_t& response = *resp_it; | ||
2241 | LLUUID item_id; | ||
2242 | LLUUID asset_id; | ||
2243 | LLUserAuth::response_t::const_iterator option_it; | ||
2244 | |||
2245 | option_it = response.find("item_id"); | ||
2246 | if (option_it != response.end()) | ||
2247 | { | ||
2248 | const std::string& uuid_string = (*option_it).second; | ||
2249 | item_id.set(uuid_string.c_str()); | ||
2250 | } | ||
2251 | option_it = response.find("asset_id"); | ||
2252 | if (option_it != response.end()) | ||
2253 | { | ||
2254 | const std::string& uuid_string = (*option_it).second; | ||
2255 | asset_id.set(uuid_string.c_str()); | ||
2256 | } | ||
2257 | |||
2258 | if (item_id.notNull() && asset_id.notNull()) | ||
2259 | { | ||
2260 | // Could schedule and delay these for later. | ||
2261 | const BOOL no_inform_server = FALSE; | ||
2262 | const BOOL no_deactivate_similar = FALSE; | ||
2263 | gGestureManager.activateGestureWithAsset(item_id, asset_id, | ||
2264 | no_inform_server, | ||
2265 | no_deactivate_similar); | ||
2266 | // We need to fetch the inventory items for these gestures | ||
2267 | // so we have the names to populate the UI. | ||
2268 | item_ids.push_back(item_id); | ||
2269 | } | ||
2270 | } | ||
2271 | |||
2272 | LLGestureInventoryFetchObserver* fetch = new LLGestureInventoryFetchObserver(); | ||
2273 | fetch->fetchItems(item_ids); | ||
2274 | // deletes itself when done | ||
2275 | gInventory.addObserver(fetch); | ||
2276 | } | ||
2277 | } | ||
2278 | gDisplaySwapBuffers = TRUE; | ||
2279 | |||
2280 | LLMessageSystem* msg = gMessageSystem; | ||
2281 | msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger); | ||
2282 | msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound); | ||
2283 | msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound); | ||
2284 | msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change); | ||
2285 | //msg->setHandlerFuncFast(_PREHASH_AttachedSoundCutoffRadius, process_attached_sound_cutoff_radius); | ||
2286 | msg->setHandlerFunc( | ||
2287 | "ConnectToUserserver", | ||
2288 | process_connect_to_userserver); | ||
2289 | |||
2290 | llinfos << "Initialization complete" << llendl; | ||
2291 | gInitializationComplete = TRUE; | ||
2292 | |||
2293 | gRenderStartTime.reset(); | ||
2294 | |||
2295 | // HACK: Inform simulator of window size. | ||
2296 | // Do this here so it's less likely to race with RegisterNewAgent. | ||
2297 | // TODO: Put this into RegisterNewAgent | ||
2298 | // JC - 7/20/2002 | ||
2299 | gViewerWindow->sendShapeToSim(); | ||
2300 | |||
2301 | // if needed, show the money history window | ||
2302 | if (stipend_since_login && !gNoRender) | ||
2303 | { | ||
2304 | LLFloaterAccountHistory::show(NULL); | ||
2305 | } | ||
2306 | |||
2307 | if (!gAgent.isFirstLogin()) | ||
2308 | { | ||
2309 | bool url_ok = LLURLSimString::sInstance.parse(); | ||
2310 | if (!((agent_start_location == "url" && url_ok) || | ||
2311 | (!url_ok && ((agent_start_location == "last" && gSavedSettings.getBOOL("LoginLastLocation")) || | ||
2312 | (agent_start_location == "home" && !gSavedSettings.getBOOL("LoginLastLocation")))))) | ||
2313 | { | ||
2314 | // The reason we show the alert is because we want to | ||
2315 | // reduce confusion for when you log in and your provided | ||
2316 | // location is not your expected location. So, if this is | ||
2317 | // your first login, then you do not have an expectation, | ||
2318 | // thus, do not show this alert. | ||
2319 | LLString::format_map_t args; | ||
2320 | if (url_ok) | ||
2321 | { | ||
2322 | args["[TYPE]"] = "desired"; | ||
2323 | args["[HELP]"] = " "; | ||
2324 | } | ||
2325 | else if (gSavedSettings.getBOOL("LoginLastLocation")) | ||
2326 | { | ||
2327 | args["[TYPE]"] = "last"; | ||
2328 | args["[HELP]"] = " \n "; | ||
2329 | } | ||
2330 | else | ||
2331 | { | ||
2332 | args["[TYPE]"] = "home"; | ||
2333 | args["[HELP]"] = " \nYou may want to set a new home location.\n "; | ||
2334 | } | ||
2335 | gViewerWindow->alertXml("AvatarMoved", args); | ||
2336 | } | ||
2337 | else | ||
2338 | { | ||
2339 | if (samename) | ||
2340 | { | ||
2341 | // restore old camera pos | ||
2342 | gAgent.setFocusOnAvatar(FALSE, FALSE); | ||
2343 | gAgent.setCameraPosAndFocusGlobal(gSavedSettings.getVector3d("CameraPosOnLogout"), gSavedSettings.getVector3d("FocusPosOnLogout"), LLUUID::null); | ||
2344 | BOOL limit_hit = FALSE; | ||
2345 | gAgent.calcCameraPositionTargetGlobal(&limit_hit); | ||
2346 | if (limit_hit) | ||
2347 | { | ||
2348 | gAgent.setFocusOnAvatar(TRUE, FALSE); | ||
2349 | } | ||
2350 | gAgent.stopCameraAnimation(); | ||
2351 | } | ||
2352 | } | ||
2353 | } | ||
2354 | |||
2355 | gStartupState++; | ||
2356 | timeout.reset(); | ||
2357 | return do_normal_idle; | ||
2358 | } | ||
2359 | |||
2360 | if (STATE_PRECACHE == gStartupState) | ||
2361 | { | ||
2362 | do_normal_idle = TRUE; | ||
2363 | if (!did_precache) | ||
2364 | { | ||
2365 | did_precache = TRUE; | ||
2366 | // Don't preload map information! The amount of data for all the | ||
2367 | // map items (icons for classifieds, avatar locations, etc.) is | ||
2368 | // huge, and not throttled. This overflows the downstream | ||
2369 | // pipe during startup, when lots of information is being sent. | ||
2370 | // The problem manifests itself as invisible avatars on login. JC | ||
2371 | //gWorldMap->setCurrentLayer(0); // pre-load layer 0 of the world map | ||
2372 | |||
2373 | gImageList.doPreloadImages(); // pre-load some images from static VFS | ||
2374 | } | ||
2375 | |||
2376 | F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY; | ||
2377 | // wait precache-delay and for agent's avatar or a lot longer. | ||
2378 | if(((timeout_frac > 1.f) && gAgent.getAvatarObject()) | ||
2379 | || (timeout_frac > 3.f)) | ||
2380 | { | ||
2381 | gStartupState++; | ||
2382 | } | ||
2383 | else | ||
2384 | { | ||
2385 | set_startup_status(0.50f + 0.50f * timeout_frac, "Precaching...", | ||
2386 | gAgent.mMOTD.c_str()); | ||
2387 | } | ||
2388 | |||
2389 | return do_normal_idle; | ||
2390 | } | ||
2391 | |||
2392 | if (STATE_WEARABLES_WAIT == gStartupState) | ||
2393 | { | ||
2394 | do_normal_idle = TRUE; | ||
2395 | |||
2396 | static LLFrameTimer wearables_timer; | ||
2397 | |||
2398 | const F32 wearables_time = wearables_timer.getElapsedTimeF32(); | ||
2399 | const F32 MAX_WEARABLES_TIME = 10.f; | ||
2400 | |||
2401 | if(gAgent.getWearablesLoaded() || !gAgent.isGenderChosen()) | ||
2402 | { | ||
2403 | gStartupState++; | ||
2404 | } | ||
2405 | else if (wearables_time > MAX_WEARABLES_TIME) | ||
2406 | { | ||
2407 | gViewerWindow->alertXml("ClothingLoading"); | ||
2408 | gViewerStats->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG); | ||
2409 | gStartupState++; | ||
2410 | } | ||
2411 | else | ||
2412 | { | ||
2413 | set_startup_status(0.f + 0.25f * wearables_time / MAX_WEARABLES_TIME, | ||
2414 | "Downloading clothing...", | ||
2415 | gAgent.mMOTD.c_str()); | ||
2416 | } | ||
2417 | return do_normal_idle; | ||
2418 | } | ||
2419 | |||
2420 | if (STATE_CLEANUP == gStartupState) | ||
2421 | { | ||
2422 | set_startup_status(1.0, "", NULL); | ||
2423 | |||
2424 | do_normal_idle = TRUE; | ||
2425 | |||
2426 | // Let the map know about the inventory. | ||
2427 | if(gFloaterWorldMap) | ||
2428 | { | ||
2429 | gFloaterWorldMap->observeInventory(&gInventory); | ||
2430 | gFloaterWorldMap->observeFriends(); | ||
2431 | } | ||
2432 | |||
2433 | gViewerWindow->showCursor(); | ||
2434 | gViewerWindow->getWindow()->resetBusyCount(); | ||
2435 | gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); | ||
2436 | //llinfos << "Done releasing bitmap" << llendl; | ||
2437 | gViewerWindow->setShowProgress(FALSE); | ||
2438 | gViewerWindow->setProgressCancelButtonVisible(FALSE, ""); | ||
2439 | |||
2440 | // We're not away from keyboard, even though login might have taken | ||
2441 | // a while. JC | ||
2442 | gAgent.clearAFK(); | ||
2443 | |||
2444 | // Have the agent start watching the friends list so we can update proxies | ||
2445 | gAgent.observeFriends(); | ||
2446 | if (gSavedSettings.getBOOL("LoginAsGod")) | ||
2447 | { | ||
2448 | gAgent.requestEnterGodMode(); | ||
2449 | } | ||
2450 | |||
2451 | // On first start, ask user for gender | ||
2452 | dialog_choose_gender_first_start(); | ||
2453 | |||
2454 | // Start automatic replay if the flag is set. | ||
2455 | if (gSavedSettings.getBOOL("StatsAutoRun")) | ||
2456 | { | ||
2457 | LLUUID id; | ||
2458 | llinfos << "Starting automatic playback" << llendl; | ||
2459 | gAgentPilot.startPlayback(); | ||
2460 | } | ||
2461 | |||
2462 | // ok, if we've gotten this far and have a startup URL | ||
2463 | if (LLURLSimString::sInstance.parse()) | ||
2464 | { | ||
2465 | // kick off request for landmark to startup URL | ||
2466 | if(gFloaterWorldMap) | ||
2467 | { | ||
2468 | LLVector3 pos = gAgent.getPositionAgent(); | ||
2469 | if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName() | ||
2470 | || LLURLSimString::sInstance.mX != llfloor(pos[VX]) | ||
2471 | || LLURLSimString::sInstance.mY != llfloor(pos[VY]) ) | ||
2472 | { | ||
2473 | LLFloaterWorldMap::show(NULL, TRUE); | ||
2474 | gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName, | ||
2475 | LLURLSimString::sInstance.mX, | ||
2476 | LLURLSimString::sInstance.mY, | ||
2477 | LLURLSimString::sInstance.mZ); | ||
2478 | } | ||
2479 | } | ||
2480 | } | ||
2481 | |||
2482 | // Clean up the userauth stuff. | ||
2483 | if (gUserAuthp) | ||
2484 | { | ||
2485 | delete gUserAuthp; | ||
2486 | gUserAuthp = NULL; | ||
2487 | } | ||
2488 | |||
2489 | gStartupState++; | ||
2490 | //RN: unmute audio now that we are entering world | ||
2491 | //JC: But only if the user wants audio working. | ||
2492 | if (gAudiop) | ||
2493 | { | ||
2494 | BOOL mute = gSavedSettings.getBOOL("MuteAudio"); | ||
2495 | gAudiop->setMuted(mute); | ||
2496 | } | ||
2497 | |||
2498 | // reset keyboard focus to sane state of pointing at world | ||
2499 | gFocusMgr.setKeyboardFocus(NULL, NULL); | ||
2500 | |||
2501 | #if 0 // sjb: enable for auto-enabling timer display | ||
2502 | gDebugView->mFastTimerView->setVisible(TRUE); | ||
2503 | #endif | ||
2504 | return do_normal_idle; | ||
2505 | } | ||
2506 | |||
2507 | llwarns << "Reached end of idle_startup for state " << gStartupState << llendl; | ||
2508 | return do_normal_idle; | ||
2509 | } | ||
2510 | |||
2511 | // | ||
2512 | // local function definition | ||
2513 | // | ||
2514 | |||
2515 | void unsupported_graphics_callback(S32 option, void* userdata) | ||
2516 | { | ||
2517 | if (0 == option) | ||
2518 | { | ||
2519 | llinfos << "User cancelled after driver check" << llendl; | ||
2520 | std::string help_path; | ||
2521 | help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP, | ||
2522 | "unsupported_card.html"); | ||
2523 | app_force_quit( help_path.c_str() ); | ||
2524 | } | ||
2525 | |||
2526 | LLPanelLogin::giveFocus(); | ||
2527 | } | ||
2528 | |||
2529 | void check_driver_callback(S32 option, void* userdata) | ||
2530 | { | ||
2531 | if (0 == option) | ||
2532 | { | ||
2533 | llinfos << "User cancelled after driver check" << llendl; | ||
2534 | std::string help_path; | ||
2535 | help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP, | ||
2536 | "graphics_driver_update.html"); | ||
2537 | app_force_quit( help_path.c_str() ); | ||
2538 | } | ||
2539 | |||
2540 | LLPanelLogin::giveFocus(); | ||
2541 | } | ||
2542 | |||
2543 | void login_show() | ||
2544 | { | ||
2545 | LLPanelLogin::show( gViewerWindow->getVirtualWindowRect(), | ||
2546 | gSavedSettings.getBOOL("UseDebugLogin"), | ||
2547 | login_callback, NULL ); | ||
2548 | |||
2549 | // Make sure all the UI textures are present and decoded. | ||
2550 | gImageList.decodeAllImages(); | ||
2551 | |||
2552 | if( USERSERVER_OTHER == gUserServerChoice ) | ||
2553 | { | ||
2554 | LLPanelLogin::addServer( gUserServerName, USERSERVER_OTHER ); | ||
2555 | } | ||
2556 | else | ||
2557 | { | ||
2558 | LLPanelLogin::addServer( gUserServerDomainName[gUserServerChoice].mLabel, gUserServerChoice ); | ||
2559 | } | ||
2560 | |||
2561 | // Arg! We hate loops! | ||
2562 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_DMZ].mLabel, USERSERVER_DMZ ); | ||
2563 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_LOCAL].mLabel, USERSERVER_LOCAL ); | ||
2564 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_AGNI].mLabel, USERSERVER_AGNI ); | ||
2565 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_ADITI].mLabel, USERSERVER_ADITI ); | ||
2566 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SIVA].mLabel, USERSERVER_SIVA ); | ||
2567 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_DURGA].mLabel, USERSERVER_DURGA ); | ||
2568 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SHAKTI].mLabel, USERSERVER_SHAKTI ); | ||
2569 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_GANGA].mLabel, USERSERVER_GANGA ); | ||
2570 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_UMA].mLabel, USERSERVER_UMA ); | ||
2571 | LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SOMA].mLabel, USERSERVER_SOMA ); | ||
2572 | } | ||
2573 | |||
2574 | // Callback for when login screen is closed. Option 0 = connect, option 1 = quit. | ||
2575 | void login_callback(S32 option, void *userdata) | ||
2576 | { | ||
2577 | const S32 CONNECT_OPTION = 0; | ||
2578 | const S32 QUIT_OPTION = 1; | ||
2579 | |||
2580 | if (CONNECT_OPTION == option) | ||
2581 | { | ||
2582 | gStartupState++; | ||
2583 | return; | ||
2584 | } | ||
2585 | else if (QUIT_OPTION == option) | ||
2586 | { | ||
2587 | // Make sure we don't save the password if the user is trying to clear it. | ||
2588 | LLString first, last, password; | ||
2589 | BOOL remember = TRUE; | ||
2590 | LLPanelLogin::getFields(first, last, password, remember); | ||
2591 | if (!remember) | ||
2592 | { | ||
2593 | // turn off the setting and write out to disk | ||
2594 | gSavedSettings.setBOOL("RememberPassword", FALSE); | ||
2595 | gSavedSettings.saveToFile(gSettingsFileName, TRUE); | ||
2596 | |||
2597 | // stomp the saved password on disk | ||
2598 | save_password_to_disk(NULL); | ||
2599 | } | ||
2600 | |||
2601 | LLPanelLogin::close(); | ||
2602 | |||
2603 | // Next iteration through main loop should shut down the app cleanly. | ||
2604 | gQuit = TRUE; | ||
2605 | |||
2606 | return; | ||
2607 | } | ||
2608 | else | ||
2609 | { | ||
2610 | llwarns << "Unknown login button clicked" << llendl; | ||
2611 | } | ||
2612 | } | ||
2613 | |||
2614 | LLString load_password_from_disk() | ||
2615 | { | ||
2616 | LLString hashed_password(""); | ||
2617 | |||
2618 | // Look for legacy "marker" password from settings.ini | ||
2619 | hashed_password = gSavedSettings.getString("Marker"); | ||
2620 | if (!hashed_password.empty()) | ||
2621 | { | ||
2622 | // Stomp the Marker entry. | ||
2623 | gSavedSettings.setString("Marker", ""); | ||
2624 | |||
2625 | // Return that password. | ||
2626 | return hashed_password; | ||
2627 | } | ||
2628 | |||
2629 | std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, | ||
2630 | "password.dat"); | ||
2631 | FILE* fp = LLFile::fopen(filepath.c_str(), "rb"); | ||
2632 | if (!fp) | ||
2633 | { | ||
2634 | return hashed_password; | ||
2635 | } | ||
2636 | |||
2637 | // UUID is 16 bytes, written into ASCII is 32 characters | ||
2638 | // without trailing \0 | ||
2639 | const S32 HASHED_LENGTH = 32; | ||
2640 | U8 buffer[HASHED_LENGTH+1]; | ||
2641 | |||
2642 | if (1 != fread(buffer, HASHED_LENGTH, 1, fp)) | ||
2643 | { | ||
2644 | return hashed_password; | ||
2645 | } | ||
2646 | |||
2647 | fclose(fp); | ||
2648 | |||
2649 | // Decipher with MAC address | ||
2650 | LLXORCipher cipher(gMACAddress, 6); | ||
2651 | cipher.decrypt(buffer, HASHED_LENGTH); | ||
2652 | |||
2653 | buffer[HASHED_LENGTH] = '\0'; | ||
2654 | |||
2655 | // Check to see if the mac address generated a bad hashed | ||
2656 | // password. It should be a hex-string or else the mac adress has | ||
2657 | // changed. This is a security feature to make sure that if you | ||
2658 | // get someone's password.dat file, you cannot hack their account. | ||
2659 | if(is_hex_string(buffer, HASHED_LENGTH)) | ||
2660 | { | ||
2661 | hashed_password.assign((char*)buffer); | ||
2662 | } | ||
2663 | |||
2664 | return hashed_password; | ||
2665 | } | ||
2666 | |||
2667 | void save_password_to_disk(const char* hashed_password) | ||
2668 | { | ||
2669 | std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, | ||
2670 | "password.dat"); | ||
2671 | if (!hashed_password) | ||
2672 | { | ||
2673 | // No password, remove the file. | ||
2674 | LLFile::remove(filepath.c_str()); | ||
2675 | } | ||
2676 | else | ||
2677 | { | ||
2678 | FILE* fp = LLFile::fopen(filepath.c_str(), "wb"); | ||
2679 | if (!fp) | ||
2680 | { | ||
2681 | return; | ||
2682 | } | ||
2683 | |||
2684 | // Encipher with MAC address | ||
2685 | const S32 HASHED_LENGTH = 32; | ||
2686 | U8 buffer[HASHED_LENGTH+1]; | ||
2687 | |||
2688 | LLString::copy((char*)buffer, hashed_password, HASHED_LENGTH+1); | ||
2689 | |||
2690 | LLXORCipher cipher(gMACAddress, 6); | ||
2691 | cipher.encrypt(buffer, HASHED_LENGTH); | ||
2692 | |||
2693 | fwrite(buffer, HASHED_LENGTH, 1, fp); | ||
2694 | |||
2695 | fclose(fp); | ||
2696 | } | ||
2697 | } | ||
2698 | |||
2699 | BOOL is_hex_string(U8* str, S32 len) | ||
2700 | { | ||
2701 | BOOL rv = TRUE; | ||
2702 | U8* c = str; | ||
2703 | while(rv && len--) | ||
2704 | { | ||
2705 | switch(*c) | ||
2706 | { | ||
2707 | case '0': | ||
2708 | case '1': | ||
2709 | case '2': | ||
2710 | case '3': | ||
2711 | case '4': | ||
2712 | case '5': | ||
2713 | case '6': | ||
2714 | case '7': | ||
2715 | case '8': | ||
2716 | case '9': | ||
2717 | case 'a': | ||
2718 | case 'b': | ||
2719 | case 'c': | ||
2720 | case 'd': | ||
2721 | case 'e': | ||
2722 | case 'f': | ||
2723 | ++c; | ||
2724 | break; | ||
2725 | default: | ||
2726 | rv = FALSE; | ||
2727 | break; | ||
2728 | } | ||
2729 | } | ||
2730 | return rv; | ||
2731 | } | ||
2732 | |||
2733 | void show_first_run_dialog() | ||
2734 | { | ||
2735 | gViewerWindow->alertXml("FirstRun", first_run_dialog_callback, NULL); | ||
2736 | } | ||
2737 | |||
2738 | void first_run_dialog_callback(S32 option, void* userdata) | ||
2739 | { | ||
2740 | if (0 == option) | ||
2741 | { | ||
2742 | llinfos << "First run dialog cancelling" << llendl; | ||
2743 | LLWeb::loadURL( CREATE_ACCOUNT_URL ); | ||
2744 | } | ||
2745 | |||
2746 | LLPanelLogin::giveFocus(); | ||
2747 | } | ||
2748 | |||
2749 | |||
2750 | |||
2751 | void set_startup_status(const F32 frac, const char *string, const char* msg) | ||
2752 | { | ||
2753 | gViewerWindow->setProgressPercent(frac*100); | ||
2754 | gViewerWindow->setProgressString(string); | ||
2755 | |||
2756 | gViewerWindow->setProgressMessage(msg); | ||
2757 | } | ||
2758 | |||
2759 | void on_userserver_name_resolved( BOOL success, const LLString& host_name, U32 ip, void* userdata ) | ||
2760 | { | ||
2761 | if( STATE_RESOLVING_USERSERVER != gStartupState ) | ||
2762 | { | ||
2763 | llwarns << "Userserver name callback returned during invalid state!" << llendl; | ||
2764 | return; | ||
2765 | } | ||
2766 | |||
2767 | if( success ) | ||
2768 | { | ||
2769 | gUserServer.setAddress( ip ); | ||
2770 | llinfos << "...Userserver resolved to " << gUserServer << llendl; | ||
2771 | gStartupState = STATE_USERSERVER_RESOLVED; | ||
2772 | } | ||
2773 | else | ||
2774 | { | ||
2775 | llwarns << "setHostByName failed" << llendl; | ||
2776 | |||
2777 | LLStringBase<char>::format_map_t args; | ||
2778 | args["[HOST_NAME]"] = host_name; | ||
2779 | gViewerWindow->alertXml("SetByHostFail", args, login_alert_done ); | ||
2780 | gStartupState = STATE_LOGIN_SHOW; | ||
2781 | } | ||
2782 | } | ||
2783 | |||
2784 | void login_alert_status(S32 option, void* user_data) | ||
2785 | { | ||
2786 | if (0 == option) | ||
2787 | { | ||
2788 | // OK button | ||
2789 | } | ||
2790 | else if (1 == option) | ||
2791 | { | ||
2792 | // Help button | ||
2793 | std::string help_path; | ||
2794 | help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP, "unable_to_connect.html"); | ||
2795 | load_url_local_file(help_path.c_str() ); | ||
2796 | } | ||
2797 | |||
2798 | LLPanelLogin::giveFocus(); | ||
2799 | } | ||
2800 | |||
2801 | void update_app(BOOL mandatory, const std::string& auth_msg) | ||
2802 | { | ||
2803 | // store off config state, as we might quit soon | ||
2804 | gSavedSettings.saveToFile(gSettingsFileName, TRUE); | ||
2805 | |||
2806 | std::ostringstream message; | ||
2807 | |||
2808 | //XUI:translate | ||
2809 | std::string msg; | ||
2810 | if (!auth_msg.empty()) | ||
2811 | { | ||
2812 | msg = "(" + auth_msg + ") \n"; | ||
2813 | } | ||
2814 | LLStringBase<char>::format_map_t args; | ||
2815 | args["[MESSAGE]"] = msg; | ||
2816 | |||
2817 | BOOL *mandatoryp = new BOOL(mandatory); | ||
2818 | |||
2819 | #if LL_WINDOWS | ||
2820 | if (mandatory) | ||
2821 | { | ||
2822 | gViewerWindow->alertXml("DownloadWindowsMandatory", args, | ||
2823 | update_dialog_callback, | ||
2824 | (void *)mandatoryp); | ||
2825 | } | ||
2826 | else | ||
2827 | { | ||
2828 | #if LL_RELEASE_FOR_DOWNLOAD | ||
2829 | gViewerWindow->alertXml("DownloadWindowsReleaseForDownload", args, | ||
2830 | update_dialog_callback, | ||
2831 | (void *)mandatoryp); | ||
2832 | #else | ||
2833 | gViewerWindow->alertXml("DownloadWindows", args, | ||
2834 | update_dialog_callback, | ||
2835 | (void *)mandatoryp); | ||
2836 | #endif | ||
2837 | } | ||
2838 | #else | ||
2839 | if (mandatory) | ||
2840 | { | ||
2841 | gViewerWindow->alertXml("DownloadMacMandatory", args, | ||
2842 | update_dialog_callback, | ||
2843 | (void *)mandatoryp); | ||
2844 | } | ||
2845 | else | ||
2846 | { | ||
2847 | #if LL_RELEASE_FOR_DOWNLOAD | ||
2848 | gViewerWindow->alertXml("DownloadMacReleaseForDownload", args, | ||
2849 | update_dialog_callback, | ||
2850 | (void *)mandatoryp); | ||
2851 | #else | ||
2852 | gViewerWindow->alertXml("DownloadMac", args, | ||
2853 | update_dialog_callback, | ||
2854 | (void *)mandatoryp); | ||
2855 | #endif | ||
2856 | } | ||
2857 | #endif | ||
2858 | |||
2859 | } | ||
2860 | |||
2861 | |||
2862 | void update_dialog_callback(S32 option, void *userdata) | ||
2863 | { | ||
2864 | std::string update_exe_path; | ||
2865 | BOOL mandatory = *(BOOL *)userdata; | ||
2866 | |||
2867 | #if !LL_RELEASE_FOR_DOWNLOAD | ||
2868 | if (option == 2) | ||
2869 | { | ||
2870 | gStartupState++; | ||
2871 | return; | ||
2872 | } | ||
2873 | #endif | ||
2874 | |||
2875 | if (option == 1) | ||
2876 | { | ||
2877 | // ...user doesn't want to do it | ||
2878 | if (mandatory) | ||
2879 | { | ||
2880 | app_force_quit(); | ||
2881 | // Bump them back to the login screen. | ||
2882 | //gStartupState = STATE_LOGIN_SHOW; | ||
2883 | } | ||
2884 | else | ||
2885 | { | ||
2886 | gStartupState++; | ||
2887 | } | ||
2888 | return; | ||
2889 | } | ||
2890 | |||
2891 | #if LL_WINDOWS | ||
2892 | char ip[MAX_STRING]; | ||
2893 | |||
2894 | update_exe_path = gDirUtilp->getTempFilename(); | ||
2895 | if (update_exe_path.empty()) | ||
2896 | { | ||
2897 | // We're hosed, bail | ||
2898 | llwarns << "LLDir::getTempFilename() failed" << llendl; | ||
2899 | app_force_quit(NULL); | ||
2900 | return; | ||
2901 | } | ||
2902 | |||
2903 | update_exe_path += ".exe"; | ||
2904 | |||
2905 | std::string updater_source = gDirUtilp->getAppRODataDir(); | ||
2906 | updater_source += gDirUtilp->getDirDelimiter(); | ||
2907 | updater_source += "updater.exe"; | ||
2908 | |||
2909 | llinfos << "Calling CopyFile source: " << updater_source.c_str() | ||
2910 | << " dest: " << update_exe_path | ||
2911 | << llendl; | ||
2912 | |||
2913 | |||
2914 | if (!CopyFileA(updater_source.c_str(), update_exe_path.c_str(), FALSE)) | ||
2915 | { | ||
2916 | llinfos << "Unable to copy the updater!" << llendl; | ||
2917 | app_force_quit(NULL); | ||
2918 | return; | ||
2919 | } | ||
2920 | u32_to_ip_string(gUserServer.getAddress(), ip); | ||
2921 | |||
2922 | std::ostringstream params; | ||
2923 | params << "-userserver " << gUserServerName; | ||
2924 | |||
2925 | // if a sim name was passed in via command line parameter (typically through a SLURL) | ||
2926 | if ( LLURLSimString::sInstance.mSimString.length() ) | ||
2927 | { | ||
2928 | // record the location to start at next time | ||
2929 | gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); | ||
2930 | }; | ||
2931 | |||
2932 | if (gHideLinks) | ||
2933 | { | ||
2934 | // Figure out the program name. | ||
2935 | const char* data_dir = gDirUtilp->getAppRODataDir().c_str(); | ||
2936 | // Roll back from the end, stopping at the first '\' | ||
2937 | const char* program_name = data_dir + strlen(data_dir); | ||
2938 | while ( (data_dir != --program_name) && | ||
2939 | *(program_name) != '\\'); | ||
2940 | |||
2941 | if ( *(program_name) == '\\') | ||
2942 | { | ||
2943 | // We found a '\'. | ||
2944 | program_name++; | ||
2945 | } | ||
2946 | else | ||
2947 | { | ||
2948 | // Oops. | ||
2949 | program_name = "SecondLife"; | ||
2950 | } | ||
2951 | |||
2952 | params << " -silent -name \"" << gSecondLife << "\" -program \"" << program_name << "\""; | ||
2953 | } | ||
2954 | |||
2955 | llinfos << "Calling updater: " << update_exe_path << " " << params.str() << llendl; | ||
2956 | |||
2957 | remove_marker_file(); // In case updater fails | ||
2958 | |||
2959 | // Use spawn() to run asynchronously | ||
2960 | int retval = _spawnl(_P_NOWAIT, update_exe_path.c_str(), update_exe_path.c_str(), params.str().c_str(), NULL); | ||
2961 | llinfos << "Spawn returned " << retval << llendl; | ||
2962 | |||
2963 | #elif LL_DARWIN | ||
2964 | // if a sim name was passed in via command line parameter (typically through a SLURL) | ||
2965 | if ( LLURLSimString::sInstance.mSimString.length() ) | ||
2966 | { | ||
2967 | // record the location to start at next time | ||
2968 | gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); | ||
2969 | }; | ||
2970 | |||
2971 | update_exe_path = "'"; | ||
2972 | update_exe_path += gDirUtilp->getAppRODataDir(); | ||
2973 | update_exe_path += "/AutoUpdater.app/Contents/MacOS/AutoUpdater' -userserver "; | ||
2974 | update_exe_path += gUserServerName; | ||
2975 | update_exe_path += " -name \""; | ||
2976 | update_exe_path += gSecondLife; | ||
2977 | update_exe_path += "\" &"; | ||
2978 | |||
2979 | llinfos << "Calling updater: " << update_exe_path << llendl; | ||
2980 | |||
2981 | remove_marker_file(); // In case updater fails | ||
2982 | |||
2983 | // Run the auto-updater. | ||
2984 | system(update_exe_path.c_str()); | ||
2985 | |||
2986 | #elif LL_LINUX | ||
2987 | OSMessageBox("Automatic updating is not yet implemented for Linux.\n" | ||
2988 | "Please download the latest version from www.secondlife.com.", | ||
2989 | NULL, OSMB_OK); | ||
2990 | remove_marker_file(); | ||
2991 | |||
2992 | #endif | ||
2993 | app_force_quit(NULL); | ||
2994 | } | ||
2995 | |||
2996 | void use_circuit_callback(void**, S32 result) | ||
2997 | { | ||
2998 | // bail if we're quitting. | ||
2999 | if(gQuit) return; | ||
3000 | static bool called = false; | ||
3001 | if(!called) | ||
3002 | { | ||
3003 | called = true; | ||
3004 | if (result) | ||
3005 | { | ||
3006 | // Make sure user knows something bad happened. JC | ||
3007 | llinfos << "Backing up to login screen!" << llendl; | ||
3008 | gViewerWindow->alertXml("LoginPacketNeverReceived", | ||
3009 | login_alert_status, NULL); | ||
3010 | gStartupState = STATE_LOGIN_SHOW; | ||
3011 | } | ||
3012 | else | ||
3013 | { | ||
3014 | gGotUseCircuitCodeAck = true; | ||
3015 | } | ||
3016 | } | ||
3017 | } | ||
3018 | |||
3019 | void register_viewer_callbacks(LLMessageSystem* msg) | ||
3020 | { | ||
3021 | msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data ); | ||
3022 | msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImage::receiveImage ); | ||
3023 | msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImage::receiveImagePacket ); | ||
3024 | msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update ); | ||
3025 | msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update ); | ||
3026 | msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update ); | ||
3027 | msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved ); | ||
3028 | msg->setHandlerFunc("SimStats", process_sim_stats); | ||
3029 | msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message ); | ||
3030 | msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data); | ||
3031 | msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo); | ||
3032 | |||
3033 | msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator); | ||
3034 | msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL); | ||
3035 | msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL); | ||
3036 | msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator); | ||
3037 | msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator); | ||
3038 | msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL); | ||
3039 | |||
3040 | msg->setHandlerFunc("CrossedRegion", process_crossed_region); | ||
3041 | msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish); | ||
3042 | |||
3043 | msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message); | ||
3044 | msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message); | ||
3045 | msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL); | ||
3046 | msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message); | ||
3047 | |||
3048 | msg->setHandlerFuncFast(_PREHASH_RequestAvatarInfo, process_avatar_info_request); | ||
3049 | msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value); | ||
3050 | msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value); | ||
3051 | msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation); | ||
3052 | msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance); | ||
3053 | msg->setHandlerFunc("AgentCachedTextureResponse", LLAgent::processAgentCachedTextureResponse); | ||
3054 | msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatar::processRebakeAvatarTextures); | ||
3055 | msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint); | ||
3056 | msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response); | ||
3057 | msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties); | ||
3058 | msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties); | ||
3059 | |||
3060 | msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im); | ||
3061 | msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question); | ||
3062 | msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL); | ||
3063 | msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL); | ||
3064 | msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect); | ||
3065 | |||
3066 | msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL); | ||
3067 | msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL); | ||
3068 | msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL); | ||
3069 | msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL); | ||
3070 | msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply, | ||
3071 | &LLLiveLSLEditor::processScriptRunningReply); | ||
3072 | |||
3073 | msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack); | ||
3074 | |||
3075 | msg->setHandlerFunc("LogoutReply", process_logout_reply); | ||
3076 | |||
3077 | //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility, | ||
3078 | // &LLAgent::processAddModifyAbility); | ||
3079 | //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility, | ||
3080 | // &LLAgent::processRemoveModifyAbility); | ||
3081 | msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate, | ||
3082 | &LLAgent::processAgentDataUpdate); | ||
3083 | msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate, | ||
3084 | &LLAgent::processAgentGroupDataUpdate); | ||
3085 | msg->setHandlerFunc("AgentDropGroup", | ||
3086 | &LLAgent::processAgentDropGroup); | ||
3087 | // land ownership messages | ||
3088 | msg->setHandlerFuncFast(_PREHASH_ParcelOverlay, | ||
3089 | LLViewerParcelMgr::processParcelOverlay); | ||
3090 | msg->setHandlerFuncFast(_PREHASH_ParcelProperties, | ||
3091 | LLViewerParcelMgr::processParcelProperties); | ||
3092 | msg->setHandlerFunc("ParcelAccessListReply", | ||
3093 | LLViewerParcelMgr::processParcelAccessListReply); | ||
3094 | msg->setHandlerFunc("ParcelDwellReply", | ||
3095 | LLViewerParcelMgr::processParcelDwellReply); | ||
3096 | |||
3097 | msg->setHandlerFunc("AvatarPropertiesReply", | ||
3098 | LLPanelAvatar::processAvatarPropertiesReply); | ||
3099 | msg->setHandlerFunc("AvatarInterestsReply", | ||
3100 | LLPanelAvatar::processAvatarInterestsReply); | ||
3101 | msg->setHandlerFunc("AvatarGroupsReply", | ||
3102 | LLPanelAvatar::processAvatarGroupsReply); | ||
3103 | msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply, | ||
3104 | LLPanelAvatar::processAvatarStatisticsReply); | ||
3105 | msg->setHandlerFunc("AvatarNotesReply", | ||
3106 | LLPanelAvatar::processAvatarNotesReply); | ||
3107 | msg->setHandlerFunc("AvatarPicksReply", | ||
3108 | LLPanelAvatar::processAvatarPicksReply); | ||
3109 | msg->setHandlerFunc("AvatarClassifiedReply", | ||
3110 | LLPanelAvatar::processAvatarClassifiedReply); | ||
3111 | |||
3112 | msg->setHandlerFuncFast(_PREHASH_CreateGroupReply, | ||
3113 | LLGroupMgr::processCreateGroupReply); | ||
3114 | msg->setHandlerFuncFast(_PREHASH_JoinGroupReply, | ||
3115 | LLGroupMgr::processJoinGroupReply); | ||
3116 | msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply, | ||
3117 | LLGroupMgr::processEjectGroupMemberReply); | ||
3118 | msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply, | ||
3119 | LLGroupMgr::processLeaveGroupReply); | ||
3120 | msg->setHandlerFuncFast(_PREHASH_GroupProfileReply, | ||
3121 | LLGroupMgr::processGroupPropertiesReply); | ||
3122 | |||
3123 | msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, | ||
3124 | LLFloaterRate::processReputationIndividualReply); | ||
3125 | |||
3126 | msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate, | ||
3127 | LLAgent::processAgentInitialWearablesUpdate ); | ||
3128 | |||
3129 | msg->setHandlerFunc("ScriptControlChange", | ||
3130 | LLAgent::processScriptControlChange ); | ||
3131 | |||
3132 | msg->setHandlerFuncFast(_PREHASH_GestureUpdate, | ||
3133 | LLViewerGestureList::processGestureUpdate); | ||
3134 | |||
3135 | msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect); | ||
3136 | |||
3137 | msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers); | ||
3138 | |||
3139 | msg->setHandlerFuncFast(_PREHASH_MoneySummaryReply, | ||
3140 | LLFloaterAccountHistory::processMoneySummaryReply); | ||
3141 | msg->setHandlerFuncFast(_PREHASH_MoneyDetailsReply, | ||
3142 | LLFloaterAccountHistory::processMoneyDetailsReply); | ||
3143 | msg->setHandlerFuncFast(_PREHASH_MoneyTransactionsReply, | ||
3144 | LLFloaterAccountHistory::processMoneyTransactionsReply); | ||
3145 | |||
3146 | // ASDF | ||
3147 | msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply, | ||
3148 | LLGroupMoneyPlanningTabEventHandler::processGroupAccountSummaryReply); | ||
3149 | msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply, | ||
3150 | LLGroupMoneyDetailsTabEventHandler::processGroupAccountDetailsReply); | ||
3151 | msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply, | ||
3152 | LLGroupMoneySalesTabEventHandler::processGroupAccountTransactionsReply); | ||
3153 | |||
3154 | msg->setHandlerFuncFast(_PREHASH_UserInfoReply, | ||
3155 | process_user_info_reply); | ||
3156 | |||
3157 | msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL); | ||
3158 | |||
3159 | msg->setHandlerFunc("TeleportStart", process_teleport_start ); | ||
3160 | msg->setHandlerFunc("TeleportProgress", process_teleport_progress); | ||
3161 | msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL); | ||
3162 | msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL); | ||
3163 | |||
3164 | msg->setHandlerFunc("ImageNotInDatabase", LLViewerImageList::processImageNotInDatabase, NULL); | ||
3165 | |||
3166 | msg->setHandlerFuncFast(_PREHASH_GroupMembersReply, | ||
3167 | LLGroupMgr::processGroupMembersReply); | ||
3168 | msg->setHandlerFunc("GroupRoleDataReply", | ||
3169 | LLGroupMgr::processGroupRoleDataReply); | ||
3170 | msg->setHandlerFunc("GroupRoleMembersReply", | ||
3171 | LLGroupMgr::processGroupRoleMembersReply); | ||
3172 | msg->setHandlerFunc("GroupTitlesReply", | ||
3173 | LLGroupMgr::processGroupTitlesReply); | ||
3174 | // Special handler as this message is sometimes used for group land. | ||
3175 | msg->setHandlerFunc("PlacesReply", process_places_reply); | ||
3176 | msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply); | ||
3177 | |||
3178 | msg->setHandlerFunc("DirPlacesReply", LLPanelDirBrowser::processDirPlacesReply); | ||
3179 | msg->setHandlerFunc("DirPeopleReply", LLPanelDirBrowser::processDirPeopleReply); | ||
3180 | msg->setHandlerFunc("DirEventsReply", LLPanelDirBrowser::processDirEventsReply); | ||
3181 | msg->setHandlerFunc("DirGroupsReply", LLPanelDirBrowser::processDirGroupsReply); | ||
3182 | //msg->setHandlerFunc("DirPicksReply", LLPanelDirBrowser::processDirPicksReply); | ||
3183 | msg->setHandlerFunc("DirClassifiedReply", LLPanelDirBrowser::processDirClassifiedReply); | ||
3184 | msg->setHandlerFunc("DirLandReply", LLPanelDirBrowser::processDirLandReply); | ||
3185 | msg->setHandlerFunc("DirPopularReply",LLPanelDirBrowser::processDirPopularReply); | ||
3186 | |||
3187 | msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); | ||
3188 | |||
3189 | msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply); | ||
3190 | msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply); | ||
3191 | msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply); | ||
3192 | |||
3193 | msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply); | ||
3194 | msg->setHandlerFunc("PickInfoReply", LLPanelPick::processPickInfoReply); | ||
3195 | msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply); | ||
3196 | msg->setHandlerFunc("ParcelInfoReply", LLPanelPlace::processParcelInfoReply); | ||
3197 | msg->setHandlerFunc("ScriptDialog", process_script_dialog); | ||
3198 | msg->setHandlerFunc("LoadURL", process_load_url); | ||
3199 | msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request); | ||
3200 | msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply); | ||
3201 | |||
3202 | // calling cards | ||
3203 | msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard); | ||
3204 | msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard); | ||
3205 | msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard); | ||
3206 | |||
3207 | msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply); | ||
3208 | |||
3209 | // Reponse to the "Refresh" button on land objects floater. | ||
3210 | if (gSavedSettings.getBOOL("AudioStreamingVideo")) | ||
3211 | { | ||
3212 | msg->setHandlerFunc("ParcelMediaCommandMessage", LLMediaEngine::process_parcel_media); | ||
3213 | msg->setHandlerFunc ( "ParcelMediaUpdate", LLMediaEngine::process_parcel_media_update ); | ||
3214 | } | ||
3215 | else | ||
3216 | { | ||
3217 | msg->setHandlerFunc("ParcelMediaCommandMessage", null_message_callback); | ||
3218 | gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", null_message_callback ); | ||
3219 | } | ||
3220 | |||
3221 | msg->setHandlerFunc("InitiateDownload", process_initiate_download); | ||
3222 | msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply); | ||
3223 | msg->setHandlerFunc("GenericMessage", process_generic_message); | ||
3224 | |||
3225 | msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message); | ||
3226 | } | ||
3227 | |||
3228 | |||
3229 | void init_stat_view() | ||
3230 | { | ||
3231 | LLFrameStatView *frameviewp = gDebugView->mFrameStatView; | ||
3232 | frameviewp->setup(gFrameStats); | ||
3233 | frameviewp->mShowPercent = FALSE; | ||
3234 | |||
3235 | LLRect rect; | ||
3236 | LLStatBar *stat_barp; | ||
3237 | rect = gDebugView->mStatViewp->getRect(); | ||
3238 | |||
3239 | // | ||
3240 | // Viewer advanced stats | ||
3241 | // | ||
3242 | LLStatView *stat_viewp = NULL; | ||
3243 | |||
3244 | // | ||
3245 | // Viewer Basic | ||
3246 | // | ||
3247 | stat_viewp = new LLStatView("basic stat view", "Basic", "OpenDebugStatBasic", rect); | ||
3248 | gDebugView->mStatViewp->addChildAtEnd(stat_viewp); | ||
3249 | |||
3250 | stat_barp = stat_viewp->addStat("FPS", &(gViewerStats->mFPSStat)); | ||
3251 | stat_barp->setUnitLabel(" fps"); | ||
3252 | stat_barp->mMinBar = 0.f; | ||
3253 | stat_barp->mMaxBar = 45.f; | ||
3254 | stat_barp->mTickSpacing = 7.5f; | ||
3255 | stat_barp->mLabelSpacing = 15.f; | ||
3256 | stat_barp->mPrecision = 1; | ||
3257 | stat_barp->mDisplayBar = TRUE; | ||
3258 | stat_barp->mDisplayHistory = TRUE; | ||
3259 | |||
3260 | stat_barp = stat_viewp->addStat("Bandwidth", &(gViewerStats->mKBitStat)); | ||
3261 | stat_barp->setUnitLabel(" kbps"); | ||
3262 | stat_barp->mMinBar = 0.f; | ||
3263 | stat_barp->mMaxBar = 900.f; | ||
3264 | stat_barp->mTickSpacing = 100.f; | ||
3265 | stat_barp->mLabelSpacing = 300.f; | ||
3266 | stat_barp->mDisplayBar = TRUE; | ||
3267 | stat_barp->mDisplayHistory = FALSE; | ||
3268 | |||
3269 | stat_barp = stat_viewp->addStat("Packet Loss", &(gViewerStats->mPacketsLostPercentStat)); | ||
3270 | stat_barp->setUnitLabel(" %%"); | ||
3271 | stat_barp->mMinBar = 0.f; | ||
3272 | stat_barp->mMaxBar = 5.f; | ||
3273 | stat_barp->mTickSpacing = 1.f; | ||
3274 | stat_barp->mLabelSpacing = 1.f; | ||
3275 | stat_barp->mDisplayBar = FALSE; | ||
3276 | stat_barp->mPerSec = FALSE; | ||
3277 | stat_barp->mDisplayMean = TRUE; | ||
3278 | stat_barp->mPrecision = 1; | ||
3279 | |||
3280 | stat_barp = stat_viewp->addStat("Ping Sim", &(gViewerStats->mSimPingStat)); | ||
3281 | stat_barp->setUnitLabel(" msec"); | ||
3282 | stat_barp->mMinBar = 0.f; | ||
3283 | stat_barp->mMaxBar = 1000.f; | ||
3284 | stat_barp->mTickSpacing = 100.f; | ||
3285 | stat_barp->mLabelSpacing = 200.f; | ||
3286 | stat_barp->mDisplayBar = FALSE; | ||
3287 | stat_barp->mPerSec = FALSE; | ||
3288 | stat_barp->mDisplayMean = FALSE; | ||
3289 | |||
3290 | stat_barp = stat_viewp->addStat("Ping User", &(gViewerStats->mUserserverPingStat)); | ||
3291 | stat_barp->setUnitLabel(" msec"); | ||
3292 | stat_barp->mMinBar = 0.f; | ||
3293 | stat_barp->mMaxBar = 1000.f; | ||
3294 | stat_barp->mTickSpacing = 100.f; | ||
3295 | stat_barp->mLabelSpacing = 200.f; | ||
3296 | stat_barp->mDisplayBar = FALSE; | ||
3297 | stat_barp->mPerSec = FALSE; | ||
3298 | stat_barp->mDisplayMean = FALSE; | ||
3299 | |||
3300 | |||
3301 | stat_viewp = new LLStatView("advanced stat view", "Advanced", "OpenDebugStatAdvanced", rect); | ||
3302 | gDebugView->mStatViewp->addChildAtEnd(stat_viewp); | ||
3303 | |||
3304 | |||
3305 | LLStatView *render_statviewp; | ||
3306 | render_statviewp = new LLStatView("render stat view", "Render", "OpenDebugStatRender", rect); | ||
3307 | stat_viewp->addChildAtEnd(render_statviewp); | ||
3308 | |||
3309 | stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat)); | ||
3310 | stat_barp->setUnitLabel("/fr"); | ||
3311 | stat_barp->mMinBar = 0.f; | ||
3312 | stat_barp->mMaxBar = 500.f; | ||
3313 | stat_barp->mTickSpacing = 100.f; | ||
3314 | stat_barp->mLabelSpacing = 500.f; | ||
3315 | stat_barp->mPrecision = 1; | ||
3316 | stat_barp->mPerSec = FALSE; | ||
3317 | |||
3318 | stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat)); | ||
3319 | stat_barp->setUnitLabel("/sec"); | ||
3320 | stat_barp->mMinBar = 0.f; | ||
3321 | stat_barp->mMaxBar = 3000.f; | ||
3322 | stat_barp->mTickSpacing = 250.f; | ||
3323 | stat_barp->mLabelSpacing = 1000.f; | ||
3324 | stat_barp->mPrecision = 1; | ||
3325 | |||
3326 | stat_barp = render_statviewp->addStat("Total Objs", &(gObjectList.mNumObjectsStat)); | ||
3327 | stat_barp->mMinBar = 0.f; | ||
3328 | stat_barp->mMaxBar = 10000.f; | ||
3329 | stat_barp->mTickSpacing = 2500.f; | ||
3330 | stat_barp->mLabelSpacing = 5000.f; | ||
3331 | stat_barp->mPerSec = FALSE; | ||
3332 | stat_barp->mDisplayBar = FALSE; | ||
3333 | |||
3334 | stat_barp = render_statviewp->addStat("New Objs", &(gObjectList.mNumNewObjectsStat)); | ||
3335 | stat_barp->setLabel("New Objs"); | ||
3336 | stat_barp->setUnitLabel("/sec"); | ||
3337 | stat_barp->mMinBar = 0.f; | ||
3338 | stat_barp->mMaxBar = 1000.f; | ||
3339 | stat_barp->mTickSpacing = 100.f; | ||
3340 | stat_barp->mLabelSpacing = 500.f; | ||
3341 | stat_barp->mPerSec = TRUE; | ||
3342 | stat_barp->mDisplayBar = FALSE; | ||
3343 | |||
3344 | |||
3345 | // Pipeline statistics | ||
3346 | LLStatView *pipeline_statviewp; | ||
3347 | pipeline_statviewp = new LLStatView("pipeline stat view", "Pipeline", "", rect); | ||
3348 | render_statviewp->addChildAtEnd(pipeline_statviewp); | ||
3349 | |||
3350 | stat_barp = pipeline_statviewp->addStat("Visible Drawables", &(gPipeline.mNumVisibleDrawablesStat)); | ||
3351 | stat_barp->setUnitLabel(""); | ||
3352 | stat_barp->mMinBar = 0.f; | ||
3353 | stat_barp->mMaxBar = 10000.f; | ||
3354 | stat_barp->mTickSpacing = 1000.f; | ||
3355 | stat_barp->mLabelSpacing = 5000.f; | ||
3356 | stat_barp->mPerSec = FALSE; | ||
3357 | |||
3358 | stat_barp = pipeline_statviewp->addStat("Visible Faces", &(gPipeline.mNumVisibleFacesStat)); | ||
3359 | stat_barp->setUnitLabel(""); | ||
3360 | stat_barp->mMinBar = 0.f; | ||
3361 | stat_barp->mMaxBar = 40000.f; | ||
3362 | stat_barp->mTickSpacing = 5000.f; | ||
3363 | stat_barp->mLabelSpacing = 10000.f; | ||
3364 | stat_barp->mPerSec = FALSE; | ||
3365 | |||
3366 | stat_barp = pipeline_statviewp->addStat("DirtyGeom", &(gPipeline.mGeometryChangesStat)); | ||
3367 | stat_barp->setUnitLabel("/fr"); | ||
3368 | stat_barp->mMinBar = 0.f; | ||
3369 | stat_barp->mMaxBar = 1000.f; | ||
3370 | stat_barp->mTickSpacing = 100.f; | ||
3371 | stat_barp->mLabelSpacing = 500.f; | ||
3372 | stat_barp->mPerSec = FALSE; | ||
3373 | |||
3374 | stat_barp = pipeline_statviewp->addStat("DirtyLight", &(gPipeline.mLightingChangesStat)); | ||
3375 | stat_barp->setUnitLabel("/fr"); | ||
3376 | stat_barp->mMinBar = 0.f; | ||
3377 | stat_barp->mMaxBar = 1000.f; | ||
3378 | stat_barp->mTickSpacing = 100.f; | ||
3379 | stat_barp->mLabelSpacing = 500.f; | ||
3380 | stat_barp->mPerSec = FALSE; | ||
3381 | |||
3382 | stat_barp = pipeline_statviewp->addStat("MoveList", &(gPipeline.mMoveChangesStat)); | ||
3383 | stat_barp->setUnitLabel("dr"); | ||
3384 | stat_barp->mMinBar = 0.f; | ||
3385 | stat_barp->mMaxBar = 1000.f; | ||
3386 | stat_barp->mTickSpacing = 100.f; | ||
3387 | stat_barp->mLabelSpacing = 500.f; | ||
3388 | stat_barp->mPerSec = FALSE; | ||
3389 | |||
3390 | stat_barp = pipeline_statviewp->addStat("Compiles", &(gPipeline.mCompilesStat)); | ||
3391 | stat_barp->setUnitLabel("/fr"); | ||
3392 | stat_barp->mMinBar = 0.f; | ||
3393 | stat_barp->mMaxBar = 1000.f; | ||
3394 | stat_barp->mTickSpacing = 100.f; | ||
3395 | stat_barp->mLabelSpacing = 500.f; | ||
3396 | stat_barp->mPerSec = FALSE; | ||
3397 | |||
3398 | stat_barp = pipeline_statviewp->addStat("Verts Relit", &(gPipeline.mVerticesRelitStat)); | ||
3399 | stat_barp->setUnitLabel("/fr"); | ||
3400 | stat_barp->mMinBar = 0.f; | ||
3401 | stat_barp->mMaxBar = 40000.f; | ||
3402 | stat_barp->mTickSpacing = 10000.f; | ||
3403 | stat_barp->mLabelSpacing = 20000.f; | ||
3404 | stat_barp->mPerSec = FALSE; | ||
3405 | |||
3406 | // Texture statistics | ||
3407 | LLStatView *texture_statviewp; | ||
3408 | texture_statviewp = new LLStatView("texture stat view", "Texture", "", rect); | ||
3409 | render_statviewp->addChildAtEnd(texture_statviewp); | ||
3410 | |||
3411 | stat_barp = texture_statviewp->addStat("Count", &(gImageList.sNumImagesStat)); | ||
3412 | stat_barp->setUnitLabel(""); | ||
3413 | stat_barp->mMinBar = 0.f; | ||
3414 | stat_barp->mMaxBar = 8000.f; | ||
3415 | stat_barp->mTickSpacing = 2000.f; | ||
3416 | stat_barp->mLabelSpacing = 4000.f; | ||
3417 | stat_barp->mPerSec = FALSE; | ||
3418 | stat_barp->mDisplayBar = FALSE; | ||
3419 | |||
3420 | stat_barp = texture_statviewp->addStat("Raw Count", &(gImageList.sNumRawImagesStat)); | ||
3421 | stat_barp->setUnitLabel(""); | ||
3422 | stat_barp->mMinBar = 0.f; | ||
3423 | stat_barp->mMaxBar = 8000.f; | ||
3424 | stat_barp->mTickSpacing = 2000.f; | ||
3425 | stat_barp->mLabelSpacing = 4000.f; | ||
3426 | stat_barp->mPerSec = FALSE; | ||
3427 | stat_barp->mDisplayBar = FALSE; | ||
3428 | |||
3429 | stat_barp = texture_statviewp->addStat("GL Mem", &(gImageList.sGLTexMemStat)); | ||
3430 | stat_barp->setUnitLabel(""); | ||
3431 | stat_barp->mMinBar = 0.f; | ||
3432 | stat_barp->mMaxBar = 400.f; | ||
3433 | stat_barp->mTickSpacing = 100.f; | ||
3434 | stat_barp->mLabelSpacing = 200.f; | ||
3435 | stat_barp->mPrecision = 1; | ||
3436 | stat_barp->mPerSec = FALSE; | ||
3437 | |||
3438 | stat_barp = texture_statviewp->addStat("Formatted Mem", &(gImageList.sFormattedMemStat)); | ||
3439 | stat_barp->setUnitLabel(""); | ||
3440 | stat_barp->mMinBar = 0.f; | ||
3441 | stat_barp->mMaxBar = 400.f; | ||
3442 | stat_barp->mTickSpacing = 100.f; | ||
3443 | stat_barp->mLabelSpacing = 200.f; | ||
3444 | stat_barp->mPrecision = 1; | ||
3445 | stat_barp->mPerSec = FALSE; | ||
3446 | |||
3447 | stat_barp = texture_statviewp->addStat("Raw Mem", &(gImageList.sRawMemStat)); | ||
3448 | stat_barp->setUnitLabel(""); | ||
3449 | stat_barp->mMinBar = 0.f; | ||
3450 | stat_barp->mMaxBar = 400.f; | ||
3451 | stat_barp->mTickSpacing = 100.f; | ||
3452 | stat_barp->mLabelSpacing = 200.f; | ||
3453 | stat_barp->mPrecision = 1; | ||
3454 | stat_barp->mPerSec = FALSE; | ||
3455 | |||
3456 | stat_barp = texture_statviewp->addStat("Bound Mem", &(gImageList.sGLBoundMemStat)); | ||
3457 | stat_barp->setUnitLabel(""); | ||
3458 | stat_barp->mMinBar = 0.f; | ||
3459 | stat_barp->mMaxBar = 400.f; | ||
3460 | stat_barp->mTickSpacing = 100.f; | ||
3461 | stat_barp->mLabelSpacing = 200.f; | ||
3462 | stat_barp->mPrecision = 1; | ||
3463 | stat_barp->mPerSec = FALSE; | ||
3464 | |||
3465 | |||
3466 | // Network statistics | ||
3467 | LLStatView *net_statviewp; | ||
3468 | net_statviewp = new LLStatView("network stat view", "Network", "OpenDebugStatNet", rect); | ||
3469 | stat_viewp->addChildAtEnd(net_statviewp); | ||
3470 | |||
3471 | stat_barp = net_statviewp->addStat("Packets In", &(gViewerStats->mPacketsInStat)); | ||
3472 | stat_barp->setUnitLabel("/sec"); | ||
3473 | stat_barp->mDisplayBar = FALSE; | ||
3474 | |||
3475 | stat_barp = net_statviewp->addStat("Packets Out", &(gViewerStats->mPacketsOutStat)); | ||
3476 | stat_barp->setUnitLabel("/sec"); | ||
3477 | stat_barp->mDisplayBar = FALSE; | ||
3478 | |||
3479 | stat_barp = net_statviewp->addStat("Objects", &(gViewerStats->mObjectKBitStat)); | ||
3480 | stat_barp->setUnitLabel(" kbps"); | ||
3481 | stat_barp->mDisplayBar = FALSE; | ||
3482 | |||
3483 | stat_barp = net_statviewp->addStat("Texture", &(gViewerStats->mTextureKBitStat)); | ||
3484 | stat_barp->setUnitLabel(" kbps"); | ||
3485 | stat_barp->mDisplayBar = FALSE; | ||
3486 | |||
3487 | stat_barp = net_statviewp->addStat("Asset", &(gViewerStats->mAssetKBitStat)); | ||
3488 | stat_barp->setUnitLabel(" kbps"); | ||
3489 | stat_barp->mDisplayBar = FALSE; | ||
3490 | |||
3491 | stat_barp = net_statviewp->addStat("Layers", &(gViewerStats->mLayersKBitStat)); | ||
3492 | stat_barp->setUnitLabel(" kbps"); | ||
3493 | stat_barp->mDisplayBar = FALSE; | ||
3494 | |||
3495 | stat_barp = net_statviewp->addStat("Actual In", &(gViewerStats->mActualInKBitStat)); | ||
3496 | stat_barp->setUnitLabel(" kbps"); | ||
3497 | stat_barp->mMinBar = 0.f; | ||
3498 | stat_barp->mMaxBar = 1024.f; | ||
3499 | stat_barp->mTickSpacing = 128.f; | ||
3500 | stat_barp->mLabelSpacing = 256.f; | ||
3501 | stat_barp->mDisplayBar = TRUE; | ||
3502 | stat_barp->mDisplayHistory = FALSE; | ||
3503 | |||
3504 | stat_barp = net_statviewp->addStat("Actual Out", &(gViewerStats->mActualOutKBitStat)); | ||
3505 | stat_barp->setUnitLabel(" kbps"); | ||
3506 | stat_barp->mMinBar = 0.f; | ||
3507 | stat_barp->mMaxBar = 512.f; | ||
3508 | stat_barp->mTickSpacing = 128.f; | ||
3509 | stat_barp->mLabelSpacing = 256.f; | ||
3510 | stat_barp->mDisplayBar = TRUE; | ||
3511 | stat_barp->mDisplayHistory = FALSE; | ||
3512 | |||
3513 | stat_barp = net_statviewp->addStat("VFS Pending Ops", &(gViewerStats->mVFSPendingOperations)); | ||
3514 | stat_barp->setUnitLabel(" "); | ||
3515 | stat_barp->mPerSec = FALSE; | ||
3516 | stat_barp->mDisplayBar = FALSE; | ||
3517 | |||
3518 | |||
3519 | // Simulator stats | ||
3520 | LLStatView *sim_statviewp = new LLStatView("sim stat view", "Simulator", "OpenDebugStatSim", rect); | ||
3521 | gDebugView->mStatViewp->addChildAtEnd(sim_statviewp); | ||
3522 | |||
3523 | stat_barp = sim_statviewp->addStat("Time Dilation", &(gViewerStats->mSimTimeDilation)); | ||
3524 | stat_barp->mPrecision = 2; | ||
3525 | stat_barp->mMinBar = 0.f; | ||
3526 | stat_barp->mMaxBar = 1.f; | ||
3527 | stat_barp->mTickSpacing = 0.25f; | ||
3528 | stat_barp->mLabelSpacing = 0.5f; | ||
3529 | stat_barp->mPerSec = FALSE; | ||
3530 | stat_barp->mDisplayBar = FALSE; | ||
3531 | stat_barp->mDisplayMean = FALSE; | ||
3532 | |||
3533 | stat_barp = sim_statviewp->addStat("Sim FPS", &(gViewerStats->mSimFPS)); | ||
3534 | stat_barp->mMinBar = 0.f; | ||
3535 | stat_barp->mMaxBar = 200.f; | ||
3536 | stat_barp->mTickSpacing = 20.f; | ||
3537 | stat_barp->mLabelSpacing = 100.f; | ||
3538 | stat_barp->mPerSec = FALSE; | ||
3539 | stat_barp->mDisplayBar = FALSE; | ||
3540 | stat_barp->mDisplayMean = FALSE; | ||
3541 | |||
3542 | stat_barp = sim_statviewp->addStat("Physics FPS", &(gViewerStats->mSimPhysicsFPS)); | ||
3543 | stat_barp->mPrecision = 1; | ||
3544 | stat_barp->mMinBar = 0.f; | ||
3545 | stat_barp->mMaxBar = 66.f; | ||
3546 | stat_barp->mTickSpacing = 33.f; | ||
3547 | stat_barp->mLabelSpacing = 33.f; | ||
3548 | stat_barp->mPerSec = FALSE; | ||
3549 | stat_barp->mDisplayBar = FALSE; | ||
3550 | stat_barp->mDisplayMean = FALSE; | ||
3551 | |||
3552 | stat_barp = sim_statviewp->addStat("Agent Updates/Sec", &(gViewerStats->mSimAgentUPS)); | ||
3553 | stat_barp->mPrecision = 1; | ||
3554 | stat_barp->mMinBar = 0.f; | ||
3555 | stat_barp->mMaxBar = 100.f; | ||
3556 | stat_barp->mTickSpacing = 25.f; | ||
3557 | stat_barp->mLabelSpacing = 50.f; | ||
3558 | stat_barp->mPerSec = FALSE; | ||
3559 | stat_barp->mDisplayBar = FALSE; | ||
3560 | stat_barp->mDisplayMean = FALSE; | ||
3561 | |||
3562 | stat_barp = sim_statviewp->addStat("Main Agents", &(gViewerStats->mSimMainAgents)); | ||
3563 | stat_barp->mPrecision = 0; | ||
3564 | stat_barp->mMinBar = 0.f; | ||
3565 | stat_barp->mMaxBar = 80.f; | ||
3566 | stat_barp->mTickSpacing = 10.f; | ||
3567 | stat_barp->mLabelSpacing = 40.f; | ||
3568 | stat_barp->mPerSec = FALSE; | ||
3569 | stat_barp->mDisplayBar = FALSE; | ||
3570 | stat_barp->mDisplayMean = FALSE; | ||
3571 | |||
3572 | stat_barp = sim_statviewp->addStat("Child Agents", &(gViewerStats->mSimChildAgents)); | ||
3573 | stat_barp->mPrecision = 0; | ||
3574 | stat_barp->mMinBar = 0.f; | ||
3575 | stat_barp->mMaxBar = 40.f; | ||
3576 | stat_barp->mTickSpacing = 5.f; | ||
3577 | stat_barp->mLabelSpacing = 10.f; | ||
3578 | stat_barp->mPerSec = FALSE; | ||
3579 | stat_barp->mDisplayBar = FALSE; | ||
3580 | stat_barp->mDisplayMean = FALSE; | ||
3581 | |||
3582 | stat_barp = sim_statviewp->addStat("Objects", &(gViewerStats->mSimObjects)); | ||
3583 | stat_barp->mPrecision = 0; | ||
3584 | stat_barp->mMinBar = 0.f; | ||
3585 | stat_barp->mMaxBar = 30000.f; | ||
3586 | stat_barp->mTickSpacing = 5000.f; | ||
3587 | stat_barp->mLabelSpacing = 10000.f; | ||
3588 | stat_barp->mPerSec = FALSE; | ||
3589 | stat_barp->mDisplayBar = FALSE; | ||
3590 | stat_barp->mDisplayMean = FALSE; | ||
3591 | |||
3592 | stat_barp = sim_statviewp->addStat("Active Objects", &(gViewerStats->mSimActiveObjects)); | ||
3593 | stat_barp->mPrecision = 0; | ||
3594 | stat_barp->mMinBar = 0.f; | ||
3595 | stat_barp->mMaxBar = 800.f; | ||
3596 | stat_barp->mTickSpacing = 100.f; | ||
3597 | stat_barp->mLabelSpacing = 200.f; | ||
3598 | stat_barp->mPerSec = FALSE; | ||
3599 | stat_barp->mDisplayBar = FALSE; | ||
3600 | stat_barp->mDisplayMean = FALSE; | ||
3601 | |||
3602 | stat_barp = sim_statviewp->addStat("Active Scripts", &(gViewerStats->mSimActiveScripts)); | ||
3603 | stat_barp->mPrecision = 0; | ||
3604 | stat_barp->mMinBar = 0.f; | ||
3605 | stat_barp->mMaxBar = 800.f; | ||
3606 | stat_barp->mTickSpacing = 100.f; | ||
3607 | stat_barp->mLabelSpacing = 200.f; | ||
3608 | stat_barp->mPerSec = FALSE; | ||
3609 | stat_barp->mDisplayBar = FALSE; | ||
3610 | stat_barp->mDisplayMean = FALSE; | ||
3611 | |||
3612 | stat_barp = sim_statviewp->addStat("Script Perf", &(gViewerStats->mSimLSLIPS)); | ||
3613 | stat_barp->setUnitLabel(" ips"); | ||
3614 | stat_barp->mPrecision = 0; | ||
3615 | stat_barp->mMinBar = 0.f; | ||
3616 | stat_barp->mMaxBar = 100000.f; | ||
3617 | stat_barp->mTickSpacing = 25000.f; | ||
3618 | stat_barp->mLabelSpacing = 50000.f; | ||
3619 | stat_barp->mPerSec = FALSE; | ||
3620 | stat_barp->mDisplayBar = FALSE; | ||
3621 | stat_barp->mDisplayMean = FALSE; | ||
3622 | |||
3623 | stat_barp = sim_statviewp->addStat("Packets In", &(gViewerStats->mSimInPPS)); | ||
3624 | stat_barp->setUnitLabel(" pps"); | ||
3625 | stat_barp->mPrecision = 0; | ||
3626 | stat_barp->mMinBar = 0.f; | ||
3627 | stat_barp->mMaxBar = 2000.f; | ||
3628 | stat_barp->mTickSpacing = 250.f; | ||
3629 | stat_barp->mLabelSpacing = 1000.f; | ||
3630 | stat_barp->mPerSec = FALSE; | ||
3631 | stat_barp->mDisplayBar = FALSE; | ||
3632 | stat_barp->mDisplayMean = FALSE; | ||
3633 | |||
3634 | stat_barp = sim_statviewp->addStat("Packets Out", &(gViewerStats->mSimOutPPS)); | ||
3635 | stat_barp->setUnitLabel(" pps"); | ||
3636 | stat_barp->mPrecision = 0; | ||
3637 | stat_barp->mMinBar = 0.f; | ||
3638 | stat_barp->mMaxBar = 2000.f; | ||
3639 | stat_barp->mTickSpacing = 250.f; | ||
3640 | stat_barp->mLabelSpacing = 1000.f; | ||
3641 | stat_barp->mPerSec = FALSE; | ||
3642 | stat_barp->mDisplayBar = FALSE; | ||
3643 | stat_barp->mDisplayMean = FALSE; | ||
3644 | |||
3645 | stat_barp = sim_statviewp->addStat("Pending Downloads", &(gViewerStats->mSimPendingDownloads)); | ||
3646 | stat_barp->mPrecision = 0; | ||
3647 | stat_barp->mMinBar = 0.f; | ||
3648 | stat_barp->mMaxBar = 800.f; | ||
3649 | stat_barp->mTickSpacing = 100.f; | ||
3650 | stat_barp->mLabelSpacing = 200.f; | ||
3651 | stat_barp->mPerSec = FALSE; | ||
3652 | stat_barp->mDisplayBar = FALSE; | ||
3653 | stat_barp->mDisplayMean = FALSE; | ||
3654 | |||
3655 | stat_barp = sim_statviewp->addStat("Pending Uploads", &(gViewerStats->mSimPendingUploads)); | ||
3656 | stat_barp->mPrecision = 0; | ||
3657 | stat_barp->mMinBar = 0.f; | ||
3658 | stat_barp->mMaxBar = 100.f; | ||
3659 | stat_barp->mTickSpacing = 25.f; | ||
3660 | stat_barp->mLabelSpacing = 50.f; | ||
3661 | stat_barp->mPerSec = FALSE; | ||
3662 | stat_barp->mDisplayBar = FALSE; | ||
3663 | stat_barp->mDisplayMean = FALSE; | ||
3664 | |||
3665 | stat_barp = sim_statviewp->addStat("Total Unacked Bytes", &(gViewerStats->mSimTotalUnackedBytes)); | ||
3666 | stat_barp->setUnitLabel(" kb"); | ||
3667 | stat_barp->mPrecision = 0; | ||
3668 | stat_barp->mMinBar = 0.f; | ||
3669 | stat_barp->mMaxBar = 100000.f; | ||
3670 | stat_barp->mTickSpacing = 25000.f; | ||
3671 | stat_barp->mLabelSpacing = 50000.f; | ||
3672 | stat_barp->mPerSec = FALSE; | ||
3673 | stat_barp->mDisplayBar = FALSE; | ||
3674 | stat_barp->mDisplayMean = FALSE; | ||
3675 | |||
3676 | LLStatView *sim_time_viewp; | ||
3677 | sim_time_viewp = new LLStatView("sim perf view", "Time (ms)", "", rect); | ||
3678 | sim_statviewp->addChildAtEnd(sim_time_viewp); | ||
3679 | |||
3680 | stat_barp = sim_time_viewp->addStat("Total Frame Time", &(gViewerStats->mSimFrameMsec)); | ||
3681 | stat_barp->setUnitLabel("ms"); | ||
3682 | stat_barp->mPrecision = 1; | ||
3683 | stat_barp->mMinBar = 0.f; | ||
3684 | stat_barp->mMaxBar = 40.f; | ||
3685 | stat_barp->mTickSpacing = 10.f; | ||
3686 | stat_barp->mLabelSpacing = 20.f; | ||
3687 | stat_barp->mPerSec = FALSE; | ||
3688 | stat_barp->mDisplayBar = FALSE; | ||
3689 | stat_barp->mDisplayMean = FALSE; | ||
3690 | |||
3691 | stat_barp = sim_time_viewp->addStat("Net Time", &(gViewerStats->mSimNetMsec)); | ||
3692 | stat_barp->setUnitLabel("ms"); | ||
3693 | stat_barp->mPrecision = 1; | ||
3694 | stat_barp->mMinBar = 0.f; | ||
3695 | stat_barp->mMaxBar = 40.f; | ||
3696 | stat_barp->mTickSpacing = 10.f; | ||
3697 | stat_barp->mLabelSpacing = 20.f; | ||
3698 | stat_barp->mPerSec = FALSE; | ||
3699 | stat_barp->mDisplayBar = FALSE; | ||
3700 | stat_barp->mDisplayMean = FALSE; | ||
3701 | |||
3702 | stat_barp = sim_time_viewp->addStat("Sim Time (Physics)", &(gViewerStats->mSimSimPhysicsMsec)); | ||
3703 | stat_barp->setUnitLabel("ms"); | ||
3704 | stat_barp->mPrecision = 1; | ||
3705 | stat_barp->mMinBar = 0.f; | ||
3706 | stat_barp->mMaxBar = 40.f; | ||
3707 | stat_barp->mTickSpacing = 10.f; | ||
3708 | stat_barp->mLabelSpacing = 20.f; | ||
3709 | stat_barp->mPerSec = FALSE; | ||
3710 | stat_barp->mDisplayBar = FALSE; | ||
3711 | stat_barp->mDisplayMean = FALSE; | ||
3712 | |||
3713 | stat_barp = sim_time_viewp->addStat("Sim Time (Other)", &(gViewerStats->mSimSimOtherMsec)); | ||
3714 | stat_barp->setUnitLabel("ms"); | ||
3715 | stat_barp->mPrecision = 1; | ||
3716 | stat_barp->mMinBar = 0.f; | ||
3717 | stat_barp->mMaxBar = 40.f; | ||
3718 | stat_barp->mTickSpacing = 10.f; | ||
3719 | stat_barp->mLabelSpacing = 20.f; | ||
3720 | stat_barp->mPerSec = FALSE; | ||
3721 | stat_barp->mDisplayBar = FALSE; | ||
3722 | stat_barp->mDisplayMean = FALSE; | ||
3723 | |||
3724 | stat_barp = sim_time_viewp->addStat("Agent Time", &(gViewerStats->mSimAgentMsec)); | ||
3725 | stat_barp->setUnitLabel("ms"); | ||
3726 | stat_barp->mPrecision = 1; | ||
3727 | stat_barp->mMinBar = 0.f; | ||
3728 | stat_barp->mMaxBar = 40.f; | ||
3729 | stat_barp->mTickSpacing = 10.f; | ||
3730 | stat_barp->mLabelSpacing = 20.f; | ||
3731 | stat_barp->mPerSec = FALSE; | ||
3732 | stat_barp->mDisplayBar = FALSE; | ||
3733 | stat_barp->mDisplayMean = FALSE; | ||
3734 | |||
3735 | stat_barp = sim_time_viewp->addStat("Images Time", &(gViewerStats->mSimImagesMsec)); | ||
3736 | stat_barp->setUnitLabel("ms"); | ||
3737 | stat_barp->mPrecision = 1; | ||
3738 | stat_barp->mMinBar = 0.f; | ||
3739 | stat_barp->mMaxBar = 40.f; | ||
3740 | stat_barp->mTickSpacing = 10.f; | ||
3741 | stat_barp->mLabelSpacing = 20.f; | ||
3742 | stat_barp->mPerSec = FALSE; | ||
3743 | stat_barp->mDisplayBar = FALSE; | ||
3744 | stat_barp->mDisplayMean = FALSE; | ||
3745 | |||
3746 | stat_barp = sim_time_viewp->addStat("Script Time", &(gViewerStats->mSimScriptMsec)); | ||
3747 | stat_barp->setUnitLabel("ms"); | ||
3748 | stat_barp->mPrecision = 1; | ||
3749 | stat_barp->mMinBar = 0.f; | ||
3750 | stat_barp->mMaxBar = 40.f; | ||
3751 | stat_barp->mTickSpacing = 10.f; | ||
3752 | stat_barp->mLabelSpacing = 20.f; | ||
3753 | stat_barp->mPerSec = FALSE; | ||
3754 | stat_barp->mDisplayBar = FALSE; | ||
3755 | stat_barp->mDisplayMean = FALSE; | ||
3756 | |||
3757 | LLRect r = gDebugView->mStatViewp->getRect(); | ||
3758 | |||
3759 | // Reshape based on the parameters we set. | ||
3760 | gDebugView->mStatViewp->reshape(r.getWidth(), r.getHeight()); | ||
3761 | } | ||
3762 | |||
3763 | void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32) | ||
3764 | { | ||
3765 | // nothing | ||
3766 | } | ||
3767 | |||
3768 | // *HACK: Must match name in Library or agent inventory | ||
3769 | const char* COMMON_GESTURES_FOLDER = "Common Gestures"; | ||
3770 | const char* MALE_GESTURES_FOLDER = "Male Gestures"; | ||
3771 | const char* FEMALE_GESTURES_FOLDER = "Female Gestures"; | ||
3772 | const char* MALE_OUTFIT_FOLDER = "Male Shape & Outfit"; | ||
3773 | const char* FEMALE_OUTFIT_FOLDER = "Female Shape & Outfit"; | ||
3774 | const S32 OPT_USE_INITIAL_OUTFIT = -2; | ||
3775 | const S32 OPT_CLOSED_WINDOW = -1; | ||
3776 | const S32 OPT_MALE = 0; | ||
3777 | const S32 OPT_FEMALE = 1; | ||
3778 | |||
3779 | void callback_choose_gender(S32 option, void* userdata) | ||
3780 | { | ||
3781 | S32 gender = OPT_FEMALE; | ||
3782 | const char* outfit = FEMALE_OUTFIT_FOLDER; | ||
3783 | const char* gestures = FEMALE_GESTURES_FOLDER; | ||
3784 | const char* common_gestures = COMMON_GESTURES_FOLDER; | ||
3785 | if (!gInitialOutfit.empty()) | ||
3786 | { | ||
3787 | outfit = gInitialOutfit.c_str(); | ||
3788 | if (gInitialOutfitGender == "male") | ||
3789 | { | ||
3790 | gender = OPT_MALE; | ||
3791 | gestures = MALE_GESTURES_FOLDER; | ||
3792 | } | ||
3793 | else | ||
3794 | { | ||
3795 | gender = OPT_FEMALE; | ||
3796 | gestures = FEMALE_GESTURES_FOLDER; | ||
3797 | } | ||
3798 | } | ||
3799 | else | ||
3800 | { | ||
3801 | switch(option) | ||
3802 | { | ||
3803 | case OPT_MALE: | ||
3804 | gender = OPT_MALE; | ||
3805 | outfit = MALE_OUTFIT_FOLDER; | ||
3806 | gestures = MALE_GESTURES_FOLDER; | ||
3807 | break; | ||
3808 | |||
3809 | case OPT_FEMALE: | ||
3810 | case OPT_CLOSED_WINDOW: | ||
3811 | default: | ||
3812 | gender = OPT_FEMALE; | ||
3813 | outfit = FEMALE_OUTFIT_FOLDER; | ||
3814 | gestures = FEMALE_GESTURES_FOLDER; | ||
3815 | break; | ||
3816 | } | ||
3817 | } | ||
3818 | |||
3819 | // try to find the outfit - if not there, create some default | ||
3820 | // wearables. | ||
3821 | LLInventoryModel::cat_array_t cat_array; | ||
3822 | LLInventoryModel::item_array_t item_array; | ||
3823 | LLNameCategoryCollector has_name(outfit); | ||
3824 | gInventory.collectDescendentsIf(LLUUID::null, | ||
3825 | cat_array, | ||
3826 | item_array, | ||
3827 | LLInventoryModel::EXCLUDE_TRASH, | ||
3828 | has_name); | ||
3829 | if (0 == cat_array.count()) | ||
3830 | { | ||
3831 | gAgent.createStandardWearables(gender); | ||
3832 | } | ||
3833 | else | ||
3834 | { | ||
3835 | wear_outfit_by_name(outfit); | ||
3836 | } | ||
3837 | wear_outfit_by_name(gestures); | ||
3838 | wear_outfit_by_name(common_gestures); | ||
3839 | |||
3840 | typedef std::map<LLUUID, LLMultiGesture*> item_map_t; | ||
3841 | item_map_t::iterator gestureIterator; | ||
3842 | |||
3843 | // Must be here so they aren't invisible if they close the window. | ||
3844 | gAgent.setGenderChosen(TRUE); | ||
3845 | } | ||
3846 | |||
3847 | // XUI:translate | ||
3848 | void dialog_choose_gender_first_start() | ||
3849 | { | ||
3850 | if (!gNoRender | ||
3851 | && (!gAgent.isGenderChosen())) | ||
3852 | { | ||
3853 | if (!gInitialOutfit.empty()) | ||
3854 | { | ||
3855 | gViewerWindow->alertXml("WelcomeNoClothes", | ||
3856 | callback_choose_gender, NULL); | ||
3857 | } | ||
3858 | else | ||
3859 | { | ||
3860 | gViewerWindow->alertXml("WelcomeChooseSex", | ||
3861 | callback_choose_gender, NULL); | ||
3862 | |||
3863 | } | ||
3864 | } | ||
3865 | } | ||
3866 | |||
3867 | // Loads a bitmap to display during load | ||
3868 | // location_id = 0 => last position | ||
3869 | // location_id = 1 => home position | ||
3870 | void init_start_screen(S32 location_id) | ||
3871 | { | ||
3872 | if (gStartImageGL) | ||
3873 | { | ||
3874 | gStartImageGL = NULL; | ||
3875 | llinfos << "re-initializing start screen" << llendl; | ||
3876 | } | ||
3877 | |||
3878 | llinfos << "Loading startup bitmap..." << llendl; | ||
3879 | |||
3880 | LLString temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter(); | ||
3881 | |||
3882 | if ((S32)START_LOCATION_ID_LAST == location_id) | ||
3883 | { | ||
3884 | temp_str += SCREEN_LAST_FILENAME; | ||
3885 | } | ||
3886 | else | ||
3887 | { | ||
3888 | temp_str += SCREEN_HOME_FILENAME; | ||
3889 | } | ||
3890 | |||
3891 | LLPointer<LLImageBMP> start_image_bmp = new LLImageBMP; | ||
3892 | if( !start_image_bmp->load(temp_str) ) | ||
3893 | { | ||
3894 | llinfos << "Bitmap load failed" << llendl; | ||
3895 | return; | ||
3896 | } | ||
3897 | |||
3898 | gStartImageGL = new LLImageGL(FALSE); | ||
3899 | gStartImageWidth = start_image_bmp->getWidth(); | ||
3900 | gStartImageHeight = start_image_bmp->getHeight(); | ||
3901 | LLPointer<LLImageRaw> raw = new LLImageRaw; | ||
3902 | if (!start_image_bmp->decode(raw)) | ||
3903 | { | ||
3904 | llinfos << "Bitmap decode failed" << llendl; | ||
3905 | gStartImageGL = NULL; | ||
3906 | return; | ||
3907 | } | ||
3908 | |||
3909 | raw->expandToPowerOfTwo(); | ||
3910 | gStartImageGL->createGLTexture(0, raw); | ||
3911 | } | ||
3912 | |||
3913 | |||
3914 | // frees the bitmap | ||
3915 | void release_start_screen() | ||
3916 | { | ||
3917 | //llinfos << "Releasing bitmap..." << llendl; | ||
3918 | gStartImageGL = NULL; | ||
3919 | } | ||
3920 | |||
3921 | void process_connect_to_userserver(LLMessageSystem* msg, void**) | ||
3922 | { | ||
3923 | // Sent unreliably since if we've become disconnected, the | ||
3924 | // userserver will get back to us eventually. By sending reliable, | ||
3925 | // we also may accidently induce two separate validations under | ||
3926 | // conditions where the userserver is already lagged. | ||
3927 | msg->newMessage("ConnectAgentToUserserver"); | ||
3928 | msg->nextBlockFast(_PREHASH_AgentData); | ||
3929 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
3930 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
3931 | msg->sendMessage(gUserServer); | ||
3932 | } | ||
3933 | |||
3934 | bool LLStartUp::canGoFullscreen() | ||
3935 | { | ||
3936 | return gStartupState >= STATE_WORLD_INIT; | ||
3937 | } | ||
3938 | |||
3939 | |||