diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llworld.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llworld.cpp')
-rw-r--r-- | linden/indra/newview/llworld.cpp | 1160 |
1 files changed, 1160 insertions, 0 deletions
diff --git a/linden/indra/newview/llworld.cpp b/linden/indra/newview/llworld.cpp new file mode 100644 index 0000000..18d4e48 --- /dev/null +++ b/linden/indra/newview/llworld.cpp | |||
@@ -0,0 +1,1160 @@ | |||
1 | /** | ||
2 | * @file llworld.cpp | ||
3 | * @brief Initial test structure to organize viewer regions | ||
4 | * | ||
5 | * Copyright (c) 2001-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 "llworld.h" | ||
31 | |||
32 | #include "indra_constants.h" | ||
33 | |||
34 | #include "llagent.h" | ||
35 | #include "llviewercontrol.h" | ||
36 | #include "lldrawpool.h" | ||
37 | #include "llglheaders.h" | ||
38 | #include "llregionhandle.h" | ||
39 | #include "llsurface.h" | ||
40 | #include "llviewercamera.h" | ||
41 | #include "llviewerimage.h" | ||
42 | #include "llviewerimagelist.h" | ||
43 | #include "llviewernetwork.h" | ||
44 | #include "llviewerobjectlist.h" | ||
45 | #include "llviewerparceloverlay.h" | ||
46 | #include "llviewerregion.h" | ||
47 | #include "llviewerstats.h" | ||
48 | #include "llvlcomposition.h" | ||
49 | #include "llvoavatar.h" | ||
50 | #include "llvowater.h" | ||
51 | #include "message.h" | ||
52 | #include "pipeline.h" | ||
53 | #include "viewer.h" // for do_disconnect() | ||
54 | |||
55 | // | ||
56 | // Globals | ||
57 | // | ||
58 | LLWorld* gWorldp = NULL; | ||
59 | U32 gAgentPauseSerialNum = 0; | ||
60 | |||
61 | // | ||
62 | // Constants | ||
63 | // | ||
64 | const S32 MAX_NUMBER_OF_CLOUDS = 750; | ||
65 | const F32 MIN_IDLE_UPDATE_TIME = 0.025f; | ||
66 | const S32 WORLD_PATCH_SIZE = 16; | ||
67 | |||
68 | extern LLColor4U MAX_WATER_COLOR; | ||
69 | |||
70 | // | ||
71 | // Functions | ||
72 | // | ||
73 | |||
74 | // allocate the stack | ||
75 | LLWorld::LLWorld(const U32 grids_per_region, const F32 meters_per_grid) | ||
76 | : mWidth(grids_per_region), | ||
77 | mScale(meters_per_grid), | ||
78 | mWidthInMeters( grids_per_region * meters_per_grid ) | ||
79 | { | ||
80 | mSpaceTimeUSec = 0; | ||
81 | mLastPacketsIn = 0; | ||
82 | mLastPacketsOut = 0; | ||
83 | mLastPacketsLost = 0; | ||
84 | mLandFarClip = DEFAULT_FAR_PLANE; | ||
85 | mIdleUpdateTime = MIN_IDLE_UPDATE_TIME; | ||
86 | |||
87 | if (gNoRender) | ||
88 | { | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | for (S32 i = 0; i < 8; i++) | ||
93 | { | ||
94 | mEdgeWaterObjects[i] = NULL; | ||
95 | } | ||
96 | |||
97 | LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4); | ||
98 | U8 *default_texture = raw->getData(); | ||
99 | *(default_texture++) = MAX_WATER_COLOR.mV[0]; | ||
100 | *(default_texture++) = MAX_WATER_COLOR.mV[1]; | ||
101 | *(default_texture++) = MAX_WATER_COLOR.mV[2]; | ||
102 | *(default_texture++) = MAX_WATER_COLOR.mV[3]; | ||
103 | |||
104 | mDefaultWaterTexturep = new LLViewerImage(raw, FALSE); | ||
105 | mDefaultWaterTexturep->bind(); | ||
106 | mDefaultWaterTexturep->setClamp(TRUE, TRUE); | ||
107 | |||
108 | } | ||
109 | |||
110 | |||
111 | LLWorld::~LLWorld() | ||
112 | { | ||
113 | gObjectList.killAllObjects(); | ||
114 | |||
115 | mRegionList.deleteAllData(); | ||
116 | } | ||
117 | |||
118 | |||
119 | LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) | ||
120 | { | ||
121 | LLMemType mt(LLMemType::MTYPE_REGIONS); | ||
122 | |||
123 | LLViewerRegion *regionp = getRegionFromHandle(region_handle); | ||
124 | if (regionp) | ||
125 | { | ||
126 | LLHost old_host = regionp->getHost(); | ||
127 | // region already exists! | ||
128 | if (host == old_host && regionp->mAlive) | ||
129 | { | ||
130 | // This is a duplicate for the same host and it's alive, don't bother. | ||
131 | return regionp; | ||
132 | } | ||
133 | |||
134 | if (host != old_host) | ||
135 | { | ||
136 | llwarns << "LLWorld::addRegion exists, but old host " << old_host | ||
137 | << " does not match new host " << host << llendl; | ||
138 | } | ||
139 | if (!regionp->mAlive) | ||
140 | { | ||
141 | llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl; | ||
142 | } | ||
143 | |||
144 | // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host | ||
145 | // matches, because all the agent state for the new camera is completely different. | ||
146 | removeRegion(old_host); | ||
147 | } | ||
148 | |||
149 | U32 iindex = 0; | ||
150 | U32 jindex = 0; | ||
151 | from_region_handle(region_handle, &iindex, &jindex); | ||
152 | S32 x = (S32)(iindex/mWidth); | ||
153 | S32 y = (S32)(jindex/mWidth); | ||
154 | llinfos << "Adding new region (" << x << ":" << y << ")" << llendl; | ||
155 | llinfos << "Host: " << host << llendl; | ||
156 | |||
157 | LLVector3d origin_global; | ||
158 | |||
159 | origin_global = from_region_handle(region_handle); | ||
160 | |||
161 | regionp = new LLViewerRegion(region_handle, | ||
162 | host, | ||
163 | mWidth, | ||
164 | WORLD_PATCH_SIZE, | ||
165 | getRegionWidthInMeters() ); | ||
166 | if (!regionp) | ||
167 | { | ||
168 | llerrs << "Unable to create new region!" << llendl; | ||
169 | } | ||
170 | |||
171 | regionp->mCloudLayer.create(regionp); | ||
172 | regionp->mCloudLayer.setWidth((F32)mWidth); | ||
173 | regionp->mCloudLayer.setWindPointer(®ionp->mWind); | ||
174 | |||
175 | mRegionList.addData(regionp); | ||
176 | mActiveRegionList.addData(regionp); | ||
177 | mCulledRegionList.addData(regionp); | ||
178 | |||
179 | |||
180 | // Find all the adjacent regions, and attach them. | ||
181 | // Generate handles for all of the adjacent regions, and attach them in the correct way. | ||
182 | // connect the edges | ||
183 | F32 adj_x = 0.f; | ||
184 | F32 adj_y = 0.f; | ||
185 | F32 region_x = 0.f; | ||
186 | F32 region_y = 0.f; | ||
187 | U64 adj_handle = 0; | ||
188 | |||
189 | F32 width = getRegionWidthInMeters(); | ||
190 | |||
191 | LLViewerRegion *neighborp; | ||
192 | from_region_handle(region_handle, ®ion_x, ®ion_y); | ||
193 | |||
194 | // Iterate through all directions, and connect neighbors if there. | ||
195 | S32 dir; | ||
196 | for (dir = 0; dir < 8; dir++) | ||
197 | { | ||
198 | adj_x = region_x + width * gDirAxes[dir][0]; | ||
199 | adj_y = region_y + width * gDirAxes[dir][1]; | ||
200 | to_region_handle(adj_x, adj_y, &adj_handle); | ||
201 | |||
202 | neighborp = getRegionFromHandle(adj_handle); | ||
203 | if (neighborp) | ||
204 | { | ||
205 | //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl; | ||
206 | regionp->connectNeighbor(neighborp, dir); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | updateWaterObjects(); | ||
211 | |||
212 | return regionp; | ||
213 | } | ||
214 | |||
215 | |||
216 | void LLWorld::removeRegion(const LLHost &host) | ||
217 | { | ||
218 | F32 x, y; | ||
219 | |||
220 | LLViewerRegion *regionp = getRegion(host); | ||
221 | if (!regionp) | ||
222 | { | ||
223 | llwarns << "Trying to remove region that doesn't exist!" << llendl; | ||
224 | return; | ||
225 | } | ||
226 | |||
227 | if (regionp == gAgent.getRegion()) | ||
228 | { | ||
229 | LLViewerRegion *reg; | ||
230 | for (reg = mRegionList.getFirstData(); reg; reg = mRegionList.getNextData()) | ||
231 | { | ||
232 | llwarns << "RegionDump: " << reg->getName() | ||
233 | << " " << reg->getHost() | ||
234 | << " " << reg->getOriginGlobal() | ||
235 | << llendl; | ||
236 | } | ||
237 | |||
238 | llwarns << "Agent position global " << gAgent.getPositionGlobal() | ||
239 | << " agent " << gAgent.getPositionAgent() | ||
240 | << llendl; | ||
241 | |||
242 | llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl; | ||
243 | |||
244 | llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl; | ||
245 | |||
246 | llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl; | ||
247 | do_disconnect("You have been disconnected from the region you were in."); | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | from_region_handle(regionp->getHandle(), &x, &y); | ||
252 | llinfos << "Removing region " << x << ":" << y << llendl; | ||
253 | |||
254 | // This code can probably be blitzed now... | ||
255 | if (!mRegionList.removeData(regionp)) | ||
256 | { | ||
257 | for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) | ||
258 | { | ||
259 | llwarns << "RegionDump: " << regionp->getName() | ||
260 | << " " << regionp->getHost() | ||
261 | << " " << regionp->getOriginGlobal() | ||
262 | << llendl; | ||
263 | } | ||
264 | |||
265 | llerrs << "Region list is broken" << llendl; | ||
266 | } | ||
267 | |||
268 | if (!mActiveRegionList.removeData(regionp)) | ||
269 | { | ||
270 | llwarns << "LLWorld.mActiveRegionList is broken." << llendl; | ||
271 | } | ||
272 | if (!mCulledRegionList.removeData(regionp)) | ||
273 | { | ||
274 | if (!mVisibleRegionList.removeData(regionp)) | ||
275 | { | ||
276 | llwarns << "LLWorld.mCulled/mVisibleRegionList are broken" << llendl;; | ||
277 | } | ||
278 | } | ||
279 | delete regionp; | ||
280 | |||
281 | updateWaterObjects(); | ||
282 | } | ||
283 | |||
284 | |||
285 | LLViewerRegion *LLWorld::getRegion(const LLHost &host) | ||
286 | { | ||
287 | LLViewerRegion *regionp; | ||
288 | for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) | ||
289 | { | ||
290 | if (regionp->getHost() == host) | ||
291 | { | ||
292 | return regionp; | ||
293 | } | ||
294 | } | ||
295 | return NULL; | ||
296 | } | ||
297 | |||
298 | LLViewerRegion *LLWorld::getRegionFromPosAgent(const LLVector3 &pos) | ||
299 | { | ||
300 | return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos)); | ||
301 | } | ||
302 | |||
303 | LLViewerRegion *LLWorld::getRegionFromPosGlobal(const LLVector3d &pos) | ||
304 | { | ||
305 | LLViewerRegion *regionp; | ||
306 | for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) | ||
307 | { | ||
308 | if (regionp->pointInRegionGlobal(pos)) | ||
309 | { | ||
310 | return regionp; | ||
311 | } | ||
312 | } | ||
313 | return NULL; | ||
314 | } | ||
315 | |||
316 | |||
317 | LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) | ||
318 | { | ||
319 | if (positionRegionValidGlobal(end_pos)) | ||
320 | { | ||
321 | return end_pos; | ||
322 | } | ||
323 | |||
324 | LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); | ||
325 | if (!regionp) | ||
326 | { | ||
327 | return start_pos; | ||
328 | } | ||
329 | |||
330 | LLVector3d delta_pos = end_pos - start_pos; | ||
331 | LLVector3d delta_pos_abs; | ||
332 | delta_pos_abs.setVec(delta_pos); | ||
333 | delta_pos_abs.abs(); | ||
334 | |||
335 | LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); | ||
336 | F64 clip_factor = 1.0; | ||
337 | F32 region_width = regionp->getWidth(); | ||
338 | if (region_coord.mV[VX] < 0.f) | ||
339 | { | ||
340 | if (region_coord.mV[VY] < region_coord.mV[VX]) | ||
341 | { | ||
342 | // clip along y - | ||
343 | clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); | ||
344 | } | ||
345 | else | ||
346 | { | ||
347 | // clip along x - | ||
348 | clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); | ||
349 | } | ||
350 | } | ||
351 | else if (region_coord.mV[VX] > region_width) | ||
352 | { | ||
353 | if (region_coord.mV[VY] > region_coord.mV[VX]) | ||
354 | { | ||
355 | // clip along y + | ||
356 | clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; | ||
357 | } | ||
358 | else | ||
359 | { | ||
360 | //clip along x + | ||
361 | clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; | ||
362 | } | ||
363 | } | ||
364 | else if (region_coord.mV[VY] < 0.f) | ||
365 | { | ||
366 | // clip along y - | ||
367 | clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); | ||
368 | } | ||
369 | else if (region_coord.mV[VY] > region_width) | ||
370 | { | ||
371 | // clip along y + | ||
372 | clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; | ||
373 | } | ||
374 | |||
375 | // clamp to < 256 to stay in sim | ||
376 | LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); | ||
377 | final_region_pos.clamp(0.0, 255.999); | ||
378 | return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); | ||
379 | } | ||
380 | |||
381 | LLViewerRegion *LLWorld::getRegionFromHandle(const U64 &handle) | ||
382 | { | ||
383 | LLViewerRegion *regionp; | ||
384 | for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) | ||
385 | { | ||
386 | if (regionp->getHandle() == handle) | ||
387 | { | ||
388 | return regionp; | ||
389 | } | ||
390 | } | ||
391 | return NULL; | ||
392 | } | ||
393 | |||
394 | |||
395 | void LLWorld::updateAgentOffset(const LLVector3d &offset_global) | ||
396 | { | ||
397 | #if 0 | ||
398 | LLViewerRegion *regionp; | ||
399 | for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) | ||
400 | { | ||
401 | regionp->setAgentOffset(offset_global); | ||
402 | } | ||
403 | #endif | ||
404 | } | ||
405 | |||
406 | |||
407 | BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global) | ||
408 | { | ||
409 | LLViewerRegion *regionp; | ||
410 | for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) | ||
411 | { | ||
412 | if (regionp->pointInRegionGlobal(pos_global)) | ||
413 | { | ||
414 | return TRUE; | ||
415 | } | ||
416 | } | ||
417 | return FALSE; | ||
418 | } | ||
419 | |||
420 | |||
421 | // Allow objects to go up to their radius underground. | ||
422 | F32 LLWorld::getMinAllowedZ(LLViewerObject* object) | ||
423 | { | ||
424 | F32 land_height = resolveLandHeightGlobal(object->getPositionGlobal()); | ||
425 | F32 radius = 0.5f * object->getScale().magVec(); | ||
426 | return land_height - radius; | ||
427 | } | ||
428 | |||
429 | |||
430 | LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global) | ||
431 | { | ||
432 | LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); | ||
433 | |||
434 | if (regionp) | ||
435 | { | ||
436 | pos_region = regionp->getPosRegionFromGlobal(pos_global); | ||
437 | return regionp; | ||
438 | } | ||
439 | |||
440 | return NULL; | ||
441 | } | ||
442 | |||
443 | |||
444 | LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent) | ||
445 | { | ||
446 | LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); | ||
447 | LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); | ||
448 | |||
449 | if (regionp) | ||
450 | { | ||
451 | pos_region = regionp->getPosRegionFromGlobal(pos_global); | ||
452 | return regionp; | ||
453 | } | ||
454 | |||
455 | return NULL; | ||
456 | } | ||
457 | |||
458 | |||
459 | F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent) | ||
460 | { | ||
461 | LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); | ||
462 | return resolveLandHeightGlobal(pos_global); | ||
463 | } | ||
464 | |||
465 | |||
466 | F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global) | ||
467 | { | ||
468 | LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); | ||
469 | if (regionp) | ||
470 | { | ||
471 | return regionp->getLand().resolveHeightGlobal(pos_global); | ||
472 | } | ||
473 | return 0.0f; | ||
474 | } | ||
475 | |||
476 | |||
477 | // Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a) | ||
478 | // point where the the line intersects an object or the land surface. Stores the results | ||
479 | // in "intersection" and "intersection_normal" and returns a scalar value that represents | ||
480 | // the normalized distance along the line from "point_a" to "intersection". | ||
481 | // | ||
482 | // Currently assumes point_a and point_b only differ in z-direction, | ||
483 | // but it may eventually become more general. | ||
484 | F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b, | ||
485 | LLVector3d &intersection, LLVector3 &intersection_normal, | ||
486 | LLViewerObject **viewerObjectPtr) | ||
487 | { | ||
488 | // initialize return value to null | ||
489 | if (viewerObjectPtr) | ||
490 | { | ||
491 | *viewerObjectPtr = NULL; | ||
492 | } | ||
493 | |||
494 | LLViewerRegion *regionp = getRegionFromPosGlobal(point_a); | ||
495 | if (!regionp) | ||
496 | { | ||
497 | // We're outside the world | ||
498 | intersection = 0.5f * (point_a + point_b); | ||
499 | intersection_normal.setVec(0.0f, 0.0f, 1.0f); | ||
500 | return 0.5f; | ||
501 | } | ||
502 | |||
503 | // calculate the length of the segment | ||
504 | F32 segment_length = (F32)((point_a - point_b).magVec()); | ||
505 | if (0.0f == segment_length) | ||
506 | { | ||
507 | intersection = point_a; | ||
508 | intersection_normal.setVec(0.0f, 0.0f, 1.0f); | ||
509 | return segment_length; | ||
510 | } | ||
511 | |||
512 | // get land height | ||
513 | // Note: we assume that the line is parallel to z-axis here | ||
514 | LLVector3d land_intersection = point_a; | ||
515 | F32 normalized_land_distance; | ||
516 | |||
517 | land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a); | ||
518 | normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length; | ||
519 | |||
520 | if (avatarp && !avatarp->mFootPlane.isExactlyClear()) | ||
521 | { | ||
522 | LLVector3 foot_plane_normal(avatarp->mFootPlane.mV); | ||
523 | LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a); | ||
524 | // added 0.05 meters to compensate for error in foot plane reported by Havok | ||
525 | F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f; | ||
526 | norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f); | ||
527 | if (norm_dist_from_plane < normalized_land_distance) | ||
528 | { | ||
529 | normalized_land_distance = norm_dist_from_plane; | ||
530 | intersection = point_a; | ||
531 | intersection.mdV[VZ] -= norm_dist_from_plane * segment_length; | ||
532 | intersection_normal = foot_plane_normal; | ||
533 | } | ||
534 | } | ||
535 | else | ||
536 | { | ||
537 | intersection = land_intersection; | ||
538 | intersection_normal = resolveLandNormalGlobal(land_intersection); | ||
539 | } | ||
540 | |||
541 | return normalized_land_distance; | ||
542 | } | ||
543 | |||
544 | |||
545 | LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global) | ||
546 | { | ||
547 | // returns a pointer to the patch at this location | ||
548 | LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); | ||
549 | if (!regionp) | ||
550 | { | ||
551 | return NULL; | ||
552 | } | ||
553 | |||
554 | return regionp->getLand().resolvePatchGlobal(pos_global); | ||
555 | } | ||
556 | |||
557 | |||
558 | LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global) | ||
559 | { | ||
560 | LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); | ||
561 | if (!regionp) | ||
562 | { | ||
563 | return LLVector3::z_axis; | ||
564 | } | ||
565 | |||
566 | return regionp->getLand().resolveNormalGlobal(pos_global); | ||
567 | } | ||
568 | |||
569 | |||
570 | void LLWorld::updateVisibilities() | ||
571 | { | ||
572 | F32 cur_far_clip = gCamera->getFar(); | ||
573 | |||
574 | gCamera->setFar(mLandFarClip); | ||
575 | |||
576 | LLViewerRegion *regionp; | ||
577 | |||
578 | F32 diagonal_squared = F_SQRT2 * F_SQRT2 * mWidth * mWidth; | ||
579 | // Go through the culled list and check for visible regions | ||
580 | for (regionp = mCulledRegionList.getFirstData(); | ||
581 | regionp; | ||
582 | regionp = mCulledRegionList.getNextData()) | ||
583 | { | ||
584 | F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); | ||
585 | F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); | ||
586 | if (!regionp->getLand().hasZData() | ||
587 | || gCamera->sphereInFrustum(regionp->getCenterAgent(), radius)) | ||
588 | { | ||
589 | mCulledRegionList.removeCurrentData(); | ||
590 | mVisibleRegionList.addDataAtEnd(regionp); | ||
591 | } | ||
592 | } | ||
593 | |||
594 | F32 last_dist_squared = 0.0f; | ||
595 | F32 dist_squared; | ||
596 | |||
597 | // Update all of the visible regions and make single bubble-sort pass | ||
598 | for (regionp = mVisibleRegionList.getFirstData(); | ||
599 | regionp; | ||
600 | regionp = mVisibleRegionList.getNextData()) | ||
601 | { | ||
602 | if (!regionp->getLand().hasZData()) | ||
603 | { | ||
604 | continue; | ||
605 | } | ||
606 | |||
607 | F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); | ||
608 | F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); | ||
609 | if (gCamera->sphereInFrustum(regionp->getCenterAgent(), radius)) | ||
610 | { | ||
611 | if (!gNoRender) | ||
612 | { | ||
613 | regionp->getLand().updatePatchVisibilities(gAgent); | ||
614 | } | ||
615 | |||
616 | // sort by distance... closer regions to the front | ||
617 | // Note: regions use absolute frame so we use the agent's center | ||
618 | dist_squared = (F32)(gAgent.getCameraPositionGlobal() - regionp->getCenterGlobal()).magVecSquared(); | ||
619 | if (dist_squared < last_dist_squared) | ||
620 | { | ||
621 | mVisibleRegionList.swapCurrentWithPrevious(); | ||
622 | } | ||
623 | else | ||
624 | { | ||
625 | last_dist_squared = dist_squared; | ||
626 | } | ||
627 | } | ||
628 | else | ||
629 | { | ||
630 | mVisibleRegionList.removeCurrentData(); | ||
631 | mCulledRegionList.addData(regionp); | ||
632 | } | ||
633 | } | ||
634 | |||
635 | gCamera->setFar(cur_far_clip); | ||
636 | } | ||
637 | |||
638 | |||
639 | void LLWorld::updateRegions() | ||
640 | { | ||
641 | LLViewerRegion *regionp; | ||
642 | LLTimer update_timer; | ||
643 | |||
644 | // Perform idle time updates for the regions (and associated surfaces) | ||
645 | for (regionp = mRegionList.getFirstData(); | ||
646 | regionp; | ||
647 | regionp = mRegionList.getNextData()) | ||
648 | { | ||
649 | update_timer.reset(); | ||
650 | if (!regionp->idleUpdate(update_timer, mIdleUpdateTime)) | ||
651 | { | ||
652 | // Didn't finish all the updates. Slightly increase the idle update time. | ||
653 | mIdleUpdateTime *= 1.05f; | ||
654 | } | ||
655 | else | ||
656 | { | ||
657 | mIdleUpdateTime *= 0.9f; | ||
658 | if (mIdleUpdateTime < MIN_IDLE_UPDATE_TIME) | ||
659 | { | ||
660 | mIdleUpdateTime = MIN_IDLE_UPDATE_TIME; | ||
661 | } | ||
662 | } | ||
663 | } | ||
664 | } | ||
665 | |||
666 | void LLWorld::updateParticles() | ||
667 | { | ||
668 | mPartSim.updateSimulation(); | ||
669 | } | ||
670 | |||
671 | void LLWorld::updateClouds(const F32 dt) | ||
672 | { | ||
673 | if (gSavedSettings.getBOOL("FreezeTime")) | ||
674 | { | ||
675 | // don't move clouds in snapshot mode | ||
676 | return; | ||
677 | } | ||
678 | LLViewerRegion *regionp; | ||
679 | if (mActiveRegionList.getLength()) | ||
680 | { | ||
681 | // Update all the cloud puff positions, and timer based stuff | ||
682 | // such as death decay | ||
683 | for (regionp = mActiveRegionList.getFirstData(); | ||
684 | regionp; | ||
685 | regionp = mActiveRegionList.getNextData()) | ||
686 | { | ||
687 | regionp->mCloudLayer.updatePuffs(dt); | ||
688 | } | ||
689 | |||
690 | // Reshuffle who owns which puffs | ||
691 | for (regionp = mActiveRegionList.getFirstData(); | ||
692 | regionp; | ||
693 | regionp = mActiveRegionList.getNextData()) | ||
694 | { | ||
695 | regionp->mCloudLayer.updatePuffOwnership(); | ||
696 | } | ||
697 | |||
698 | // Add new puffs | ||
699 | for (regionp = mActiveRegionList.getFirstData(); | ||
700 | regionp; | ||
701 | regionp = mActiveRegionList.getNextData()) | ||
702 | { | ||
703 | regionp->mCloudLayer.updatePuffCount(); | ||
704 | } | ||
705 | } | ||
706 | } | ||
707 | |||
708 | LLCloudGroup *LLWorld::findCloudGroup(const LLCloudPuff &puff) | ||
709 | { | ||
710 | LLViewerRegion *regionp; | ||
711 | if (mActiveRegionList.getLength()) | ||
712 | { | ||
713 | // Update all the cloud puff positions, and timer based stuff | ||
714 | // such as death decay | ||
715 | for (regionp = mActiveRegionList.getFirstData(); | ||
716 | regionp; | ||
717 | regionp = mActiveRegionList.getNextData()) | ||
718 | { | ||
719 | LLCloudGroup *groupp = regionp->mCloudLayer.findCloudGroup(puff); | ||
720 | if (groupp) | ||
721 | { | ||
722 | return groupp; | ||
723 | } | ||
724 | } | ||
725 | } | ||
726 | return NULL; | ||
727 | } | ||
728 | |||
729 | |||
730 | void LLWorld::renderPropertyLines() | ||
731 | { | ||
732 | S32 region_count = 0; | ||
733 | S32 vertex_count = 0; | ||
734 | |||
735 | LLViewerRegion* region; | ||
736 | for (region = mVisibleRegionList.getFirstData(); region; region = mVisibleRegionList.getNextData() ) | ||
737 | { | ||
738 | region_count++; | ||
739 | vertex_count += region->renderPropertyLines(); | ||
740 | } | ||
741 | } | ||
742 | |||
743 | |||
744 | void LLWorld::updateNetStats() | ||
745 | { | ||
746 | F32 bits = 0.f; | ||
747 | U32 packets = 0; | ||
748 | LLViewerRegion *regionp; | ||
749 | |||
750 | for (regionp = mActiveRegionList.getFirstData(); regionp; regionp = mActiveRegionList.getNextData()) | ||
751 | { | ||
752 | regionp->updateNetStats(); | ||
753 | bits += regionp->mBitStat.getCurrent(); | ||
754 | packets += llfloor( regionp->mPacketsStat.getCurrent() ); | ||
755 | } | ||
756 | |||
757 | S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn; | ||
758 | S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut; | ||
759 | S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost; | ||
760 | |||
761 | S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits(); | ||
762 | S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits(); | ||
763 | gViewerStats->mActualInKBitStat.addValue(actual_in_bits/1024.f); | ||
764 | gViewerStats->mActualOutKBitStat.addValue(actual_out_bits/1024.f); | ||
765 | gViewerStats->mKBitStat.addValue(bits/1024.f); | ||
766 | gViewerStats->mPacketsInStat.addValue(packets_in); | ||
767 | gViewerStats->mPacketsOutStat.addValue(packets_out); | ||
768 | gViewerStats->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets); | ||
769 | if (packets_in) | ||
770 | { | ||
771 | gViewerStats->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in)); | ||
772 | } | ||
773 | else | ||
774 | { | ||
775 | gViewerStats->mPacketsLostPercentStat.addValue(0.f); | ||
776 | } | ||
777 | |||
778 | mLastPacketsIn = gMessageSystem->mPacketsIn; | ||
779 | mLastPacketsOut = gMessageSystem->mPacketsOut; | ||
780 | mLastPacketsLost = gMessageSystem->mDroppedPackets; | ||
781 | } | ||
782 | |||
783 | |||
784 | void LLWorld::printPacketsLost() | ||
785 | { | ||
786 | LLViewerRegion *regionp; | ||
787 | |||
788 | llinfos << "Simulators:" << llendl; | ||
789 | llinfos << "----------" << llendl; | ||
790 | |||
791 | LLCircuitData *cdp = NULL; | ||
792 | for (regionp = mActiveRegionList.getFirstData(); | ||
793 | regionp; | ||
794 | regionp = mActiveRegionList.getNextData()) | ||
795 | { | ||
796 | cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost()); | ||
797 | if (cdp) | ||
798 | { | ||
799 | LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal(); | ||
800 | |||
801 | llinfos << regionp->getHost() << ", range: " << range.magVec() << | ||
802 | " packets lost: " << | ||
803 | cdp->getPacketsLost() << llendl; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | llinfos << "UserServer:" << llendl; | ||
808 | llinfos << "-----------" << llendl; | ||
809 | |||
810 | cdp = gMessageSystem->mCircuitInfo.findCircuit(gUserServer); | ||
811 | if (cdp) | ||
812 | { | ||
813 | llinfos << gUserServer << " packets lost: " << cdp->getPacketsLost() << llendl; | ||
814 | } | ||
815 | } | ||
816 | |||
817 | void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data) | ||
818 | { | ||
819 | LLViewerRegion* region = NULL; | ||
820 | region = gWorldp->getRegion(msg->getSender()); | ||
821 | if( region ) region->updateCoarseLocations(msg); | ||
822 | } | ||
823 | |||
824 | F32 LLWorld::getLandFarClip() const | ||
825 | { | ||
826 | return mLandFarClip; | ||
827 | } | ||
828 | |||
829 | void LLWorld::setLandFarClip(const F32 far_clip) | ||
830 | { | ||
831 | mLandFarClip = far_clip; | ||
832 | } | ||
833 | |||
834 | |||
835 | void LLWorld::updateWaterObjects() | ||
836 | { | ||
837 | //llinfos << "Start water update" << llendl; | ||
838 | if (!gAgent.getRegion()) | ||
839 | { | ||
840 | return; | ||
841 | } | ||
842 | S32 min_x, min_y, max_x, max_y; | ||
843 | U32 region_x, region_y; | ||
844 | |||
845 | S32 rwidth = llfloor(getRegionWidthInMeters()); | ||
846 | |||
847 | // First, determine the min and max "box" of water objects | ||
848 | LLViewerRegion *regionp; | ||
849 | regionp = mRegionList.getFirstData(); | ||
850 | |||
851 | if (!regionp) | ||
852 | { | ||
853 | llwarns << "No regions!" << llendl; | ||
854 | return; | ||
855 | } | ||
856 | |||
857 | from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); | ||
858 | min_x = max_x = region_x; | ||
859 | min_y = max_y = region_y; | ||
860 | |||
861 | LLVOWater *waterp; | ||
862 | |||
863 | for (; regionp; regionp = mRegionList.getNextData()) | ||
864 | { | ||
865 | from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); | ||
866 | min_x = llmin(min_x, (S32)region_x); | ||
867 | min_y = llmin(min_y, (S32)region_y); | ||
868 | max_x = llmax(max_x, (S32)region_x); | ||
869 | max_y = llmax(max_y, (S32)region_y); | ||
870 | waterp = regionp->getLand().getWaterObj(); | ||
871 | if (waterp) | ||
872 | { | ||
873 | gObjectList.updateActive(waterp); | ||
874 | } | ||
875 | } | ||
876 | |||
877 | for (waterp = mHoleWaterObjects.getFirstData(); waterp; waterp = mHoleWaterObjects.getNextData()) | ||
878 | { | ||
879 | gObjectList.killObject(waterp); | ||
880 | } | ||
881 | mHoleWaterObjects.removeAllNodes(); | ||
882 | |||
883 | // We only want to fill in holes for stuff that's near us, say, within 512m | ||
884 | regionp = gAgent.getRegion(); | ||
885 | from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); | ||
886 | |||
887 | min_x = llmax((S32)region_x - 512, min_x); | ||
888 | min_y = llmax((S32)region_y - 512, min_y); | ||
889 | max_x = llmin((S32)region_x + 512, max_x); | ||
890 | max_y = llmin((S32)region_y + 512, max_y); | ||
891 | |||
892 | // Now, get a list of the holes | ||
893 | S32 x, y; | ||
894 | for (x = min_x; x <= max_x; x += rwidth) | ||
895 | { | ||
896 | for (y = min_y; y <= max_y; y += rwidth) | ||
897 | { | ||
898 | U64 region_handle = to_region_handle(x, y); | ||
899 | if (!getRegionFromHandle(region_handle)) | ||
900 | { | ||
901 | waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); | ||
902 | waterp->setUseTexture(FALSE); | ||
903 | gPipeline.addObject(waterp); | ||
904 | waterp->setPositionGlobal(LLVector3d(x + rwidth/2, | ||
905 | y + rwidth/2, | ||
906 | DEFAULT_WATER_HEIGHT)); | ||
907 | waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 0.f)); | ||
908 | mHoleWaterObjects.addData(waterp); | ||
909 | } | ||
910 | } | ||
911 | } | ||
912 | |||
913 | // Update edge water objects | ||
914 | S32 wx, wy; | ||
915 | S32 center_x, center_y; | ||
916 | wx = (max_x - min_x) + rwidth; | ||
917 | wy = (max_y - min_y) + rwidth; | ||
918 | center_x = min_x + (wx >> 1); | ||
919 | center_y = min_y + (wy >> 1); | ||
920 | |||
921 | |||
922 | |||
923 | S32 add_boundary[4] = { | ||
924 | 512 - (max_x - region_x), | ||
925 | 512 - (max_y - region_y), | ||
926 | 512 - (region_x - min_x), | ||
927 | 512 - (region_y - min_y) }; | ||
928 | |||
929 | |||
930 | S32 dir; | ||
931 | for (dir = 0; dir < 8; dir++) | ||
932 | { | ||
933 | S32 dim[2] = { 0 }; | ||
934 | switch (gDirAxes[dir][0]) | ||
935 | { | ||
936 | case -1: dim[0] = add_boundary[2]; break; | ||
937 | case 0: dim[0] = wx; break; | ||
938 | default: dim[0] = add_boundary[0]; break; | ||
939 | } | ||
940 | switch (gDirAxes[dir][1]) | ||
941 | { | ||
942 | case -1: dim[1] = add_boundary[3]; break; | ||
943 | case 0: dim[1] = wy; break; | ||
944 | default: dim[1] = add_boundary[1]; break; | ||
945 | } | ||
946 | |||
947 | if (dim[0] == 0 || dim[1] == 0) | ||
948 | { | ||
949 | continue; | ||
950 | } | ||
951 | |||
952 | // Resize and reshape the water objects | ||
953 | const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]); | ||
954 | const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]); | ||
955 | |||
956 | |||
957 | waterp = mEdgeWaterObjects[dir]; | ||
958 | if (!waterp || waterp->isDead()) | ||
959 | { | ||
960 | // The edge water objects can be dead because they're attached to the region that the | ||
961 | // agent was in when they were originally created. | ||
962 | mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, | ||
963 | gAgent.getRegion()); | ||
964 | waterp = mEdgeWaterObjects[dir]; | ||
965 | waterp->setUseTexture(FALSE); | ||
966 | gPipeline.addObject(waterp); | ||
967 | } | ||
968 | |||
969 | waterp->setRegion(gAgent.getRegion()); | ||
970 | LLVector3d water_pos(water_center_x, water_center_y, | ||
971 | DEFAULT_WATER_HEIGHT); | ||
972 | waterp->setPositionGlobal(water_pos); | ||
973 | waterp->setScale(LLVector3((F32)dim[0], (F32)dim[1], 0.f)); | ||
974 | gObjectList.updateActive(waterp); | ||
975 | /*if (!gNoRender) | ||
976 | { | ||
977 | gPipeline.markMoved(waterp->mDrawable); | ||
978 | }*/ | ||
979 | } | ||
980 | |||
981 | |||
982 | //llinfos << "End water update" << llendl; | ||
983 | } | ||
984 | |||
985 | LLViewerImage *LLWorld::getDefaultWaterTexture() | ||
986 | { | ||
987 | return mDefaultWaterTexturep; | ||
988 | } | ||
989 | |||
990 | void LLWorld::setSpaceTimeUSec(const U64 space_time_usec) | ||
991 | { | ||
992 | mSpaceTimeUSec = space_time_usec; | ||
993 | } | ||
994 | |||
995 | U64 LLWorld::getSpaceTimeUSec() const | ||
996 | { | ||
997 | return mSpaceTimeUSec; | ||
998 | } | ||
999 | |||
1000 | void LLWorld::requestCacheMisses() | ||
1001 | { | ||
1002 | for(LLViewerRegion* regionp = mRegionList.getFirstData(); | ||
1003 | regionp; | ||
1004 | regionp = mRegionList.getNextData()) | ||
1005 | { | ||
1006 | regionp->requestCacheMisses(); | ||
1007 | } | ||
1008 | } | ||
1009 | |||
1010 | LLString LLWorld::getInfoString() | ||
1011 | { | ||
1012 | LLString info_string("World Info:\n"); | ||
1013 | for (LLViewerRegion* regionp = mRegionList.getFirstData(); | ||
1014 | regionp; | ||
1015 | regionp = mRegionList.getNextData()) | ||
1016 | { | ||
1017 | info_string += regionp->getInfoString(); | ||
1018 | } | ||
1019 | return info_string; | ||
1020 | } | ||
1021 | |||
1022 | void LLWorld::disconnectRegions() | ||
1023 | { | ||
1024 | LLMessageSystem* msg = gMessageSystem; | ||
1025 | for(LLViewerRegion* regionp = mRegionList.getFirstData(); | ||
1026 | regionp; | ||
1027 | regionp = mRegionList.getNextData()) | ||
1028 | { | ||
1029 | if (regionp == gAgent.getRegion()) | ||
1030 | { | ||
1031 | // Skip the main agent | ||
1032 | continue; | ||
1033 | } | ||
1034 | |||
1035 | llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl; | ||
1036 | msg->newMessageFast(_PREHASH_AgentQuitCopy); | ||
1037 | msg->nextBlockFast(_PREHASH_AgentData); | ||
1038 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
1039 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
1040 | msg->nextBlockFast(_PREHASH_FuseBlock); | ||
1041 | msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode); | ||
1042 | msg->sendMessage(regionp->getHost()); | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | void process_enable_simulator(LLMessageSystem *msg, void **user_data) | ||
1048 | { | ||
1049 | // enable the appropriate circuit for this simulator and | ||
1050 | // add its values into the gSimulator structure | ||
1051 | U64 handle; | ||
1052 | U32 ip_u32; | ||
1053 | U16 port; | ||
1054 | |||
1055 | msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle); | ||
1056 | msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32); | ||
1057 | msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port); | ||
1058 | |||
1059 | // which simulator should we modify? | ||
1060 | LLHost sim(ip_u32, port); | ||
1061 | |||
1062 | // Viewer trusts the simulator. | ||
1063 | msg->enableCircuit(sim, TRUE); | ||
1064 | gWorldp->addRegion(handle, sim); | ||
1065 | |||
1066 | // give the simulator a message it can use to get ip and port | ||
1067 | llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl; | ||
1068 | msg->newMessageFast(_PREHASH_UseCircuitCode); | ||
1069 | msg->nextBlockFast(_PREHASH_CircuitCode); | ||
1070 | msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode()); | ||
1071 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
1072 | msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); | ||
1073 | msg->sendReliable(sim); | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | // disable the circuit to this simulator | ||
1078 | // Called in response to "DisableSimulator" message. | ||
1079 | void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data) | ||
1080 | { | ||
1081 | LLHost host = mesgsys->getSender(); | ||
1082 | |||
1083 | //llinfos << "Disabling simulator with message from " << host << llendl; | ||
1084 | gWorldp->removeRegion(host); | ||
1085 | |||
1086 | mesgsys->disableCircuit(host); | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | void process_region_handshake(LLMessageSystem* msg, void** user_data) | ||
1091 | { | ||
1092 | LLHost host = msg->getSender(); | ||
1093 | LLViewerRegion* regionp = gWorldp->getRegion(host); | ||
1094 | if (!regionp) | ||
1095 | { | ||
1096 | llwarns << "Got region handshake for unknown region " | ||
1097 | << host << llendl; | ||
1098 | return; | ||
1099 | } | ||
1100 | |||
1101 | regionp->unpackRegionHandshake(); | ||
1102 | } | ||
1103 | |||
1104 | |||
1105 | void send_agent_pause() | ||
1106 | { | ||
1107 | // world not initialized yet | ||
1108 | if (!gWorldp) return; | ||
1109 | |||
1110 | gMessageSystem->newMessageFast(_PREHASH_AgentPause); | ||
1111 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | ||
1112 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); | ||
1113 | gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); | ||
1114 | |||
1115 | gAgentPauseSerialNum++; | ||
1116 | gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); | ||
1117 | |||
1118 | LLViewerRegion *regionp; | ||
1119 | for (regionp = gWorldp->mActiveRegionList.getFirstData(); | ||
1120 | regionp; | ||
1121 | regionp = gWorldp->mActiveRegionList.getNextData()) | ||
1122 | { | ||
1123 | gMessageSystem->sendReliable(regionp->getHost()); | ||
1124 | } | ||
1125 | |||
1126 | gMessageSystem->sendReliable(gUserServer); | ||
1127 | |||
1128 | gObjectList.mWasPaused = TRUE; | ||
1129 | } | ||
1130 | |||
1131 | |||
1132 | void send_agent_resume() | ||
1133 | { | ||
1134 | // world not initialized yet | ||
1135 | if (!gWorldp) return; | ||
1136 | |||
1137 | gMessageSystem->newMessageFast(_PREHASH_AgentResume); | ||
1138 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | ||
1139 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); | ||
1140 | gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); | ||
1141 | |||
1142 | gAgentPauseSerialNum++; | ||
1143 | gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); | ||
1144 | |||
1145 | |||
1146 | LLViewerRegion *regionp; | ||
1147 | for (regionp = gWorldp->mActiveRegionList.getFirstData(); | ||
1148 | regionp; | ||
1149 | regionp = gWorldp->mActiveRegionList.getNextData()) | ||
1150 | { | ||
1151 | gMessageSystem->sendReliable(regionp->getHost()); | ||
1152 | } | ||
1153 | |||
1154 | gMessageSystem->sendReliable(gUserServer); | ||
1155 | |||
1156 | // Reset the FPS counter to avoid an invalid fps | ||
1157 | gViewerStats->mFPSStat.start(); | ||
1158 | } | ||
1159 | |||
1160 | |||