00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llviewerparcelmgr.h"
00035
00036
00037 #include "audioengine.h"
00038 #include "indra_constants.h"
00039 #include "llcachename.h"
00040 #include "llgl.h"
00041 #include "llmediaengine.h"
00042 #include "llparcel.h"
00043 #include "llsecondlifeurls.h"
00044 #include "message.h"
00045
00046
00047 #include "llagent.h"
00048 #include "llfloatergroupinfo.h"
00049 #include "llviewerwindow.h"
00050 #include "llviewercontrol.h"
00051 #include "llfirstuse.h"
00052 #include "llfloaterbuyland.h"
00053 #include "llfloatergroups.h"
00054
00055 #include "llfloatersellland.h"
00056 #include "llfloatertools.h"
00057 #include "llnotify.h"
00058 #include "llresmgr.h"
00059 #include "llstatusbar.h"
00060 #include "llui.h"
00061 #include "llviewerimagelist.h"
00062 #include "llviewermenu.h"
00063 #include "llviewerparceloverlay.h"
00064 #include "llviewerregion.h"
00065
00066 #include "llworld.h"
00067 #include "lloverlaybar.h"
00068 #include "roles_constants.h"
00069
00070 const F32 PARCEL_COLLISION_DRAW_SECS = 1.f;
00071
00072
00073
00074 LLViewerParcelMgr *gParcelMgr = NULL;
00075
00076 U8* LLViewerParcelMgr::sPackedOverlay = NULL;
00077
00078 LLUUID gCurrentMovieID = LLUUID::null;
00079
00080 static LLParcelSelection* get_null_parcel_selection();
00081 template<>
00082 const LLHandle<LLParcelSelection>::NullFunc
00083 LLHandle<LLParcelSelection>::sNullFunc = get_null_parcel_selection;
00084
00085
00086
00087 void optionally_start_music(const LLString& music_url);
00088 void callback_start_music(S32 option, void* data);
00089 void optionally_prepare_video(const LLParcel *parcelp);
00090 void callback_prepare_video(S32 option, void* data);
00091 void prepare_video(const LLParcel *parcelp);
00092 void start_video(const LLParcel *parcelp);
00093 void stop_video();
00094 void callback_god_force_owner(S32 option, void* user_data);
00095
00096 struct LLGodForceOwnerData
00097 {
00098 LLUUID mOwnerID;
00099 S32 mLocalID;
00100 LLHost mHost;
00101
00102 LLGodForceOwnerData(
00103 const LLUUID& owner_id,
00104 S32 local_parcel_id,
00105 const LLHost& host) :
00106 mOwnerID(owner_id),
00107 mLocalID(local_parcel_id),
00108 mHost(host) {}
00109 };
00110
00111
00112
00113
00114 LLViewerParcelMgr::LLViewerParcelMgr()
00115 : mSelected(FALSE),
00116 mWestSouth(),
00117 mEastNorth(),
00118 mSelectedDwell(0.f),
00119 mAgentParcelSequenceID(-1),
00120 mHoverWestSouth(),
00121 mHoverEastNorth(),
00122 mRenderCollision(FALSE),
00123 mRenderSelection(TRUE),
00124 mCollisionBanned(0),
00125 mCollisionTimer()
00126 {
00127 mCurrentParcel = new LLParcel();
00128 mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00129 mFloatingParcelSelection = new LLParcelSelection(mCurrentParcel);
00130
00131 mAgentParcel = new LLParcel();
00132 mHoverParcel = new LLParcel();
00133 mCollisionParcel = new LLParcel();
00134
00135 mParcelsPerEdge = S32( REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS );
00136 mHighlightSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
00137 resetSegments(mHighlightSegments);
00138
00139 mCollisionSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
00140 resetSegments(mCollisionSegments);
00141
00142 mBlockedImageID.set(gViewerArt.getString("noentrylines.tga"));
00143 mBlockedImage = gImageList.getImage(mBlockedImageID, TRUE, TRUE);
00144
00145 mPassImageID.set(gViewerArt.getString("noentrypasslines.tga"));
00146 mPassImage = gImageList.getImage(mPassImageID, TRUE, TRUE);
00147
00148 S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / PARCEL_OVERLAY_CHUNKS;
00149 sPackedOverlay = new U8[overlay_size];
00150
00151 mAgentParcelOverlay = new U8[mParcelsPerEdge * mParcelsPerEdge];
00152 S32 i;
00153 for (i = 0; i < mParcelsPerEdge * mParcelsPerEdge; i++)
00154 {
00155 mAgentParcelOverlay[i] = 0;
00156 }
00157 }
00158
00159
00160 LLViewerParcelMgr::~LLViewerParcelMgr()
00161 {
00162 mCurrentParcelSelection->setParcel(NULL);
00163 mCurrentParcelSelection = NULL;
00164
00165 mFloatingParcelSelection->setParcel(NULL);
00166 mFloatingParcelSelection = NULL;
00167
00168 delete mCurrentParcel;
00169 mCurrentParcel = NULL;
00170
00171 delete mAgentParcel;
00172 mAgentParcel = NULL;
00173
00174 delete mCollisionParcel;
00175 mCollisionParcel = NULL;
00176
00177 delete mHoverParcel;
00178 mHoverParcel = NULL;
00179
00180 delete[] mHighlightSegments;
00181 mHighlightSegments = NULL;
00182
00183 delete[] mCollisionSegments;
00184 mCollisionSegments = NULL;
00185
00186 delete[] sPackedOverlay;
00187 sPackedOverlay = NULL;
00188
00189 delete[] mAgentParcelOverlay;
00190 mAgentParcelOverlay = NULL;
00191 }
00192
00193 void LLViewerParcelMgr::dump()
00194 {
00195 llinfos << "Parcel Manager Dump" << llendl;
00196 llinfos << "mSelected " << S32(mSelected) << llendl;
00197 llinfos << "Selected parcel: " << llendl;
00198 llinfos << mWestSouth << " to " << mEastNorth << llendl;
00199 mCurrentParcel->dump();
00200 llinfos << "banning " << mCurrentParcel->mBanList.size() << llendl;
00201
00202 access_map_const_iterator cit = mCurrentParcel->mBanList.begin();
00203 access_map_const_iterator end = mCurrentParcel->mBanList.end();
00204 for ( ; cit != end; ++cit)
00205 {
00206 llinfos << "ban id " << (*cit).first << llendl;
00207 }
00208 llinfos << "Hover parcel:" << llendl;
00209 mHoverParcel->dump();
00210 llinfos << "Agent parcel:" << llendl;
00211 mAgentParcel->dump();
00212 }
00213
00214
00215 LLViewerRegion* LLViewerParcelMgr::getSelectionRegion()
00216 {
00217 if (!gWorldp) return NULL;
00218
00219 return gWorldp->getRegionFromPosGlobal( mWestSouth );
00220 }
00221
00222
00223 void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out,
00224 S32* rent_out,
00225 BOOL* for_sale_out,
00226 F32* dwell_out)
00227 {
00228 S32 area = 0;
00229 S32 price = 0;
00230 S32 rent = 0;
00231 BOOL for_sale = FALSE;
00232 F32 dwell = 0.f;
00233
00234 if (mSelected)
00235 {
00236 if (mCurrentParcelSelection->mSelectedMultipleOwners)
00237 {
00238 area = mCurrentParcelSelection->getClaimableArea();
00239 }
00240 else
00241 {
00242 area = getSelectedArea();
00243 }
00244
00245 if (mCurrentParcel->getForSale())
00246 {
00247 price = mCurrentParcel->getSalePrice();
00248 for_sale = TRUE;
00249 }
00250 else
00251 {
00252 price = area * mCurrentParcel->getClaimPricePerMeter();
00253 for_sale = FALSE;
00254 }
00255
00256 rent = mCurrentParcel->getTotalRent();
00257
00258 dwell = mSelectedDwell;
00259 }
00260
00261 *area_out = area;
00262 *claim_out = price;
00263 *rent_out = rent;
00264 *for_sale_out = for_sale;
00265 *dwell_out = dwell;
00266 }
00267
00268 void LLViewerParcelMgr::getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean)
00269 {
00270 if (mSelected && mCurrentParcel)
00271 {
00272 sw_max = mCurrentParcel->getSimWideMaxPrimCapacity();
00273 sw_total = mCurrentParcel->getSimWidePrimCount();
00274 max = llround(mCurrentParcel->getMaxPrimCapacity()*mCurrentParcel->getParcelPrimBonus());
00275 total = mCurrentParcel->getPrimCount();
00276 owner = mCurrentParcel->getOwnerPrimCount();
00277 group = mCurrentParcel->getGroupPrimCount();
00278 other = mCurrentParcel->getOtherPrimCount();
00279 selected = mCurrentParcel->getSelectedPrimCount();
00280 parcel_object_bonus = mCurrentParcel->getParcelPrimBonus();
00281 other_clean = mCurrentParcel->getCleanOtherTime();
00282 }
00283 }
00284
00285 S32 LLViewerParcelMgr::getSelectedArea() const
00286 {
00287 S32 rv = 0;
00288 if(mSelected && mCurrentParcel && mCurrentParcelSelection->mWholeParcelSelected)
00289 {
00290 rv = mCurrentParcel->getArea();
00291 }
00292 else if(mSelected)
00293 {
00294 F64 width = mEastNorth.mdV[VX] - mWestSouth.mdV[VX];
00295 F64 height = mEastNorth.mdV[VY] - mWestSouth.mdV[VY];
00296 F32 area = (F32)(width * height);
00297 rv = llround(area);
00298 }
00299 return rv;
00300 }
00301
00302 void LLViewerParcelMgr::resetSegments(U8* segments)
00303 {
00304 S32 i;
00305 S32 count = (mParcelsPerEdge+1)*(mParcelsPerEdge+1);
00306 for (i = 0; i < count; i++)
00307 {
00308 segments[i] = 0x0;
00309 }
00310 }
00311
00312
00313 void LLViewerParcelMgr::writeHighlightSegments(F32 west, F32 south, F32 east,
00314 F32 north)
00315 {
00316 S32 x, y;
00317 S32 min_x = llround( west / PARCEL_GRID_STEP_METERS );
00318 S32 max_x = llround( east / PARCEL_GRID_STEP_METERS );
00319 S32 min_y = llround( south / PARCEL_GRID_STEP_METERS );
00320 S32 max_y = llround( north / PARCEL_GRID_STEP_METERS );
00321
00322 const S32 STRIDE = mParcelsPerEdge+1;
00323
00324
00325 y = min_y;
00326 for (x = min_x; x < max_x; x++)
00327 {
00328
00329
00330 mHighlightSegments[x + y*STRIDE] ^= SOUTH_MASK;
00331 }
00332
00333
00334 x = min_x;
00335 for (y = min_y; y < max_y; y++)
00336 {
00337 mHighlightSegments[x + y*STRIDE] ^= WEST_MASK;
00338 }
00339
00340
00341
00342 y = max_y;
00343 for (x = min_x; x < max_x; x++)
00344 {
00345 mHighlightSegments[x + y*STRIDE] ^= SOUTH_MASK;
00346 }
00347
00348
00349 x = max_x;
00350 for (y = min_y; y < max_y; y++)
00351 {
00352 mHighlightSegments[x + y*STRIDE] ^= WEST_MASK;
00353 }
00354 }
00355
00356
00357 void LLViewerParcelMgr::writeSegmentsFromBitmap(U8* bitmap, U8* segments)
00358 {
00359 S32 x;
00360 S32 y;
00361 const S32 IN_STRIDE = mParcelsPerEdge;
00362 const S32 OUT_STRIDE = mParcelsPerEdge+1;
00363
00364 for (y = 0; y < IN_STRIDE; y++)
00365 {
00366 x = 0;
00367 while( x < IN_STRIDE )
00368 {
00369 U8 byte = bitmap[ (x + y*IN_STRIDE) / 8 ];
00370
00371 S32 bit;
00372 for (bit = 0; bit < 8; bit++)
00373 {
00374 if (byte & (1 << bit) )
00375 {
00376 S32 out = x+y*OUT_STRIDE;
00377
00378
00379 segments[out] ^= SOUTH_MASK;
00380 segments[out+OUT_STRIDE] ^= SOUTH_MASK;
00381
00382
00383 segments[out] ^= WEST_MASK;
00384 segments[out+1] ^= WEST_MASK;
00385 }
00386 x++;
00387 }
00388 }
00389 }
00390 }
00391
00392
00393 void LLViewerParcelMgr::writeAgentParcelFromBitmap(U8* bitmap)
00394 {
00395 S32 x;
00396 S32 y;
00397 const S32 IN_STRIDE = mParcelsPerEdge;
00398
00399 for (y = 0; y < IN_STRIDE; y++)
00400 {
00401 x = 0;
00402 while( x < IN_STRIDE )
00403 {
00404 U8 byte = bitmap[ (x + y*IN_STRIDE) / 8 ];
00405
00406 S32 bit;
00407 for (bit = 0; bit < 8; bit++)
00408 {
00409 if (byte & (1 << bit) )
00410 {
00411 mAgentParcelOverlay[x+y*IN_STRIDE] = 1;
00412 }
00413 else
00414 {
00415 mAgentParcelOverlay[x+y*IN_STRIDE] = 0;
00416 }
00417 x++;
00418 }
00419 }
00420 }
00421 }
00422
00423
00424
00425
00426 LLParcelSelectionHandle LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global)
00427 {
00428 LLVector3d southwest = pos_global;
00429 LLVector3d northeast = pos_global;
00430
00431 southwest -= LLVector3d( PARCEL_GRID_STEP_METERS/2, PARCEL_GRID_STEP_METERS/2, 0 );
00432 southwest.mdV[VX] = llround( southwest.mdV[VX], (F64)PARCEL_GRID_STEP_METERS );
00433 southwest.mdV[VY] = llround( southwest.mdV[VY], (F64)PARCEL_GRID_STEP_METERS );
00434
00435 northeast += LLVector3d( PARCEL_GRID_STEP_METERS/2, PARCEL_GRID_STEP_METERS/2, 0 );
00436 northeast.mdV[VX] = llround( northeast.mdV[VX], (F64)PARCEL_GRID_STEP_METERS );
00437 northeast.mdV[VY] = llround( northeast.mdV[VY], (F64)PARCEL_GRID_STEP_METERS );
00438
00439
00440 return selectLand( southwest, northeast, TRUE );
00441 }
00442
00443
00444
00445 LLParcelSelectionHandle LLViewerParcelMgr::selectParcelInRectangle()
00446 {
00447 return selectLand(mWestSouth, mEastNorth, TRUE);
00448 }
00449
00450
00451 void LLViewerParcelMgr::selectCollisionParcel()
00452 {
00453 if (!gWorldp)
00454 {
00455 return;
00456 }
00457
00458
00459 mWestSouth = gAgent.getRegion()->getOriginGlobal();
00460 mEastNorth = mWestSouth;
00461 mEastNorth += LLVector3d(PARCEL_GRID_STEP_METERS, PARCEL_GRID_STEP_METERS, 0.0);
00462
00463
00464 LLMessageSystem *msg = gMessageSystem;
00465 msg->newMessageFast(_PREHASH_ParcelPropertiesRequestByID);
00466 msg->nextBlockFast(_PREHASH_AgentID);
00467 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00468 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
00469 msg->nextBlockFast(_PREHASH_ParcelData);
00470 msg->addS32Fast(_PREHASH_SequenceID, SELECTED_PARCEL_SEQ_ID );
00471 msg->addS32Fast(_PREHASH_LocalID, mCollisionParcel->getLocalID() );
00472 gAgent.sendReliableMessage();
00473
00474 mRequestResult = PARCEL_RESULT_NO_DATA;
00475
00476
00477 mCurrentParcel->setName( mCollisionParcel->getName() );
00478 mCurrentParcel->setDesc( mCollisionParcel->getDesc() );
00479 mCurrentParcel->setPassPrice(mCollisionParcel->getPassPrice());
00480 mCurrentParcel->setPassHours(mCollisionParcel->getPassHours());
00481
00482
00483 resetSegments(mHighlightSegments);
00484
00485 mFloatingParcelSelection->setParcel(mCurrentParcel);
00486 mCurrentParcelSelection->setParcel(NULL);
00487 mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00488
00489 mSelected = TRUE;
00490 mCurrentParcelSelection->mWholeParcelSelected = TRUE;
00491 notifyObservers();
00492 return;
00493 }
00494
00495
00496
00497 LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &corner2,
00498 BOOL snap_selection)
00499 {
00500 if (!gWorldp)
00501 {
00502 return NULL;
00503 }
00504
00505 sanitize_corners( corner1, corner2, mWestSouth, mEastNorth );
00506
00507
00508 F32 delta_x = getSelectionWidth();
00509 if (delta_x * delta_x <= 1.f * 1.f)
00510 {
00511 mSelected = FALSE;
00512 notifyObservers();
00513 return NULL;
00514 }
00515
00516
00517 F32 delta_y = getSelectionHeight();
00518 if (delta_y * delta_y <= 1.f * 1.f)
00519 {
00520 mSelected = FALSE;
00521 notifyObservers();
00522 return NULL;
00523 }
00524
00525
00526
00527
00528 LLVector3d east_north_region_check( mEastNorth );
00529 east_north_region_check.mdV[VX] -= 0.5;
00530 east_north_region_check.mdV[VY] -= 0.5;
00531
00532 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal(mWestSouth);
00533 LLViewerRegion *region_other = gWorldp->getRegionFromPosGlobal( east_north_region_check );
00534
00535 if(!region)
00536 {
00537
00538 mSelected = FALSE;
00539 return NULL;
00540 }
00541
00542 if (region != region_other)
00543 {
00544 LLNotifyBox::showXml("CantSelectLandFromMultipleRegions");
00545 mSelected = FALSE;
00546 notifyObservers();
00547 return NULL;
00548 }
00549
00550
00551 LLVector3 wsb_region = region->getPosRegionFromGlobal( mWestSouth );
00552 LLVector3 ent_region = region->getPosRegionFromGlobal( mEastNorth );
00553
00554
00555 LLMessageSystem *msg = gMessageSystem;
00556 msg->newMessageFast(_PREHASH_ParcelPropertiesRequest);
00557 msg->nextBlockFast(_PREHASH_AgentData);
00558 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00559 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
00560 msg->nextBlockFast(_PREHASH_ParcelData);
00561 msg->addS32Fast(_PREHASH_SequenceID, SELECTED_PARCEL_SEQ_ID );
00562 msg->addF32Fast(_PREHASH_West, wsb_region.mV[VX] );
00563 msg->addF32Fast(_PREHASH_South, wsb_region.mV[VY] );
00564 msg->addF32Fast(_PREHASH_East, ent_region.mV[VX] );
00565 msg->addF32Fast(_PREHASH_North, ent_region.mV[VY] );
00566 msg->addBOOL("SnapSelection", snap_selection);
00567 msg->sendReliable( region->getHost() );
00568
00569 mRequestResult = PARCEL_RESULT_NO_DATA;
00570
00571
00572 resetSegments(mHighlightSegments);
00573
00574 mFloatingParcelSelection->setParcel(mCurrentParcel);
00575 mCurrentParcelSelection->setParcel(NULL);
00576 mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00577
00578 mSelected = TRUE;
00579 mCurrentParcelSelection->mWholeParcelSelected = snap_selection;
00580 notifyObservers();
00581 return mCurrentParcelSelection;
00582 }
00583
00584 void LLViewerParcelMgr::deselectUnused()
00585 {
00586
00587 if (mCurrentParcelSelection->getNumRefs() == 1 && mFloatingParcelSelection->getNumRefs() == 1)
00588 {
00589 deselectLand();
00590 }
00591 }
00592
00593 void LLViewerParcelMgr::deselectLand()
00594 {
00595 if (mSelected)
00596 {
00597 mSelected = FALSE;
00598
00599
00600 mCurrentParcel->setLocalID(-1);
00601 mCurrentParcel->mAccessList.clear();
00602 mCurrentParcel->mBanList.clear();
00603
00604
00605 mSelectedDwell = 0.f;
00606
00607 notifyObservers();
00608
00609
00610 mCurrentParcelSelection->setParcel(NULL);
00611 mFloatingParcelSelection->setParcel(NULL);
00612
00613 mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00614 }
00615 }
00616
00617
00618 void LLViewerParcelMgr::addObserver(LLParcelObserver* observer)
00619 {
00620 mObservers.put(observer);
00621 }
00622
00623
00624 void LLViewerParcelMgr::removeObserver(LLParcelObserver* observer)
00625 {
00626 mObservers.removeObj(observer);
00627 }
00628
00629
00630
00631
00632
00633 void LLViewerParcelMgr::notifyObservers()
00634 {
00635 LLDynamicArray<LLParcelObserver*> observers;
00636 S32 count = mObservers.count();
00637 S32 i;
00638 for(i = 0; i < count; ++i)
00639 {
00640 observers.put(mObservers.get(i));
00641 }
00642 for(i = 0; i < count; ++i)
00643 {
00644 observers.get(i)->changed();
00645 }
00646 }
00647
00648
00649
00650
00651
00652 BOOL LLViewerParcelMgr::selectionEmpty() const
00653 {
00654 return !mSelected;
00655 }
00656
00657
00658 LLParcelSelectionHandle LLViewerParcelMgr::getParcelSelection() const
00659 {
00660 return mCurrentParcelSelection;
00661 }
00662
00663 LLParcelSelectionHandle LLViewerParcelMgr::getFloatingParcelSelection() const
00664 {
00665 return mFloatingParcelSelection;
00666 }
00667
00668 LLParcel *LLViewerParcelMgr::getAgentParcel() const
00669 {
00670 return mAgentParcel;
00671 }
00672
00673
00674 BOOL LLViewerParcelMgr::agentCanBuild() const
00675 {
00676 if (mAgentParcel)
00677 {
00678 return (gAgent.isGodlike()
00679 || (mAgentParcel->allowModifyBy(
00680 gAgent.getID(),
00681 gAgent.getGroupID())));
00682 }
00683 else
00684 {
00685 return gAgent.isGodlike();
00686 }
00687 }
00688
00689 BOOL LLViewerParcelMgr::agentCanTakeDamage() const
00690 {
00691 return mAgentParcel->getAllowDamage();
00692 }
00693
00694 BOOL LLViewerParcelMgr::agentCanFly() const
00695 {
00696 return TRUE;
00697 }
00698
00699 F32 LLViewerParcelMgr::agentDrawDistance() const
00700 {
00701 return 512.f;
00702 }
00703
00704 BOOL LLViewerParcelMgr::isOwnedAt(const LLVector3d& pos_global) const
00705 {
00706 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00707 if (!region) return FALSE;
00708
00709 LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00710 if (!overlay) return FALSE;
00711
00712 LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00713
00714 return overlay->isOwned( pos_region );
00715 }
00716
00717 BOOL LLViewerParcelMgr::isOwnedSelfAt(const LLVector3d& pos_global) const
00718 {
00719 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00720 if (!region) return FALSE;
00721
00722 LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00723 if (!overlay) return FALSE;
00724
00725 LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00726
00727 return overlay->isOwnedSelf( pos_region );
00728 }
00729
00730 BOOL LLViewerParcelMgr::isOwnedOtherAt(const LLVector3d& pos_global) const
00731 {
00732 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00733 if (!region) return FALSE;
00734
00735 LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00736 if (!overlay) return FALSE;
00737
00738 LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00739
00740 return overlay->isOwnedOther( pos_region );
00741 }
00742
00743 BOOL LLViewerParcelMgr::isSoundLocal(const LLVector3d& pos_global) const
00744 {
00745 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00746 if (!region) return FALSE;
00747
00748 LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00749 if (!overlay) return FALSE;
00750
00751 LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00752
00753 return overlay->isSoundLocal( pos_region );
00754 }
00755
00756 BOOL LLViewerParcelMgr::canHearSound(const LLVector3d &pos_global) const
00757 {
00758 BOOL in_agent_parcel = inAgentParcel(pos_global);
00759
00760 if (in_agent_parcel)
00761 {
00762
00763 return TRUE;
00764 }
00765 else
00766 {
00767 if (gParcelMgr->getAgentParcel()->getSoundLocal())
00768 {
00769
00770 return FALSE;
00771 }
00772 else if (gParcelMgr->isSoundLocal(pos_global))
00773 {
00774
00775 return FALSE;
00776 }
00777 else
00778 {
00779
00780 return TRUE;
00781 }
00782 }
00783 }
00784
00785
00786 BOOL LLViewerParcelMgr::inAgentParcel(const LLVector3d &pos_global) const
00787 {
00788 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(pos_global);
00789 if (region != gAgent.getRegion())
00790 {
00791
00792 return FALSE;
00793 }
00794
00795 LLVector3 pos_region = gAgent.getRegion()->getPosRegionFromGlobal(pos_global);
00796 S32 row = S32(pos_region.mV[VY] / PARCEL_GRID_STEP_METERS);
00797 S32 column = S32(pos_region.mV[VX] / PARCEL_GRID_STEP_METERS);
00798
00799 if (mAgentParcelOverlay[row*mParcelsPerEdge + column])
00800 {
00801 return TRUE;
00802 }
00803 else
00804 {
00805 return FALSE;
00806 }
00807 }
00808
00809
00810 LLParcel* LLViewerParcelMgr::getHoverParcel() const
00811 {
00812 if (mHoverRequestResult == PARCEL_RESULT_SUCCESS)
00813 {
00814 return mHoverParcel;
00815 }
00816 else
00817 {
00818 return NULL;
00819 }
00820 }
00821
00822
00823 LLParcel* LLViewerParcelMgr::getCollisionParcel() const
00824 {
00825 if (mRenderCollision)
00826 {
00827 return mCollisionParcel;
00828 }
00829 else
00830 {
00831 return NULL;
00832 }
00833 }
00834
00835
00836
00837
00838
00839 void LLViewerParcelMgr::render()
00840 {
00841 if (mSelected && mRenderSelection)
00842 {
00843
00844
00845 LLViewerRegion *regionp = gWorldp->getRegionFromPosGlobal( mWestSouth );
00846 if (!regionp) return;
00847
00848 renderHighlightSegments(mHighlightSegments, regionp);
00849 }
00850 }
00851
00852
00853 void LLViewerParcelMgr::renderParcelCollision()
00854 {
00855
00856 if (mCollisionTimer.getElapsedTimeF32() > PARCEL_COLLISION_DRAW_SECS)
00857 {
00858 mRenderCollision = FALSE;
00859 }
00860
00861 if (mRenderCollision)
00862 {
00863 LLViewerRegion* regionp = gAgent.getRegion();
00864 BOOL use_pass = mCollisionParcel->getParcelFlag(PF_USE_PASS_LIST);
00865 renderCollisionSegments(mCollisionSegments, use_pass, regionp);
00866 }
00867 }
00868
00869
00870 void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
00871 {
00872 if (!mSelected)
00873 {
00874 return;
00875 }
00876
00877 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
00878 if (!region) return;
00879
00880 LLMessageSystem *msg = gMessageSystem;
00881
00882
00883 if (flags & AL_BAN)
00884 {
00885 mCurrentParcel->mBanList.clear();
00886 }
00887 if (flags & AL_ACCESS)
00888 {
00889 mCurrentParcel->mAccessList.clear();
00890 }
00891
00892
00893 msg->newMessageFast(_PREHASH_ParcelAccessListRequest);
00894 msg->nextBlockFast(_PREHASH_AgentData);
00895 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00896 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00897 msg->nextBlockFast(_PREHASH_Data);
00898 msg->addS32Fast(_PREHASH_SequenceID, 0);
00899 msg->addU32Fast(_PREHASH_Flags, flags);
00900 msg->addS32("LocalID", mCurrentParcel->getLocalID() );
00901 msg->sendReliable( region->getHost() );
00902 }
00903
00904
00905 void LLViewerParcelMgr::sendParcelDwellRequest()
00906 {
00907 if (!mSelected)
00908 {
00909 return;
00910 }
00911
00912 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
00913 if (!region) return;
00914
00915 LLMessageSystem *msg = gMessageSystem;
00916
00917
00918 msg->newMessage("ParcelDwellRequest");
00919 msg->nextBlock("AgentData");
00920 msg->addUUID("AgentID", gAgent.getID() );
00921 msg->addUUID("SessionID", gAgent.getSessionID());
00922 msg->nextBlock("Data");
00923 msg->addS32("LocalID", mCurrentParcel->getLocalID());
00924 msg->addUUID("ParcelID", LLUUID::null);
00925 msg->sendReliable( region->getHost() );
00926 }
00927
00928
00929 void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
00930 {
00931 if (!mSelected)
00932 {
00933 gViewerWindow->alertXml("CannotSetLandOwnerNothingSelected");
00934 return;
00935 }
00936
00937 llinfos << "Claiming " << mWestSouth << " to " << mEastNorth << llendl;
00938
00939
00940 LLVector3d east_north_region_check( mEastNorth );
00941 east_north_region_check.mdV[VX] -= 0.5;
00942 east_north_region_check.mdV[VY] -= 0.5;
00943
00944 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
00945 if (!region)
00946 {
00947
00948 gViewerWindow->alertXml("CannotContentifyNoRegion");
00949 return;
00950 }
00951
00952
00953 LLViewerRegion *region2 = gWorldp->getRegionFromPosGlobal( east_north_region_check );
00954 if (region != region2)
00955 {
00956 gViewerWindow->alertXml("CannotSetLandOwnerMultipleRegions");
00957 return;
00958 }
00959
00960 llinfos << "Region " << region->getOriginGlobal() << llendl;
00961
00962 LLGodForceOwnerData* data = new LLGodForceOwnerData(owner_id, mCurrentParcel->getLocalID(), region->getHost());
00963 if(mCurrentParcel->getAuctionID())
00964 {
00965 gViewerWindow->alertXml("ForceOwnerAuctionWarning",
00966 callback_god_force_owner,
00967 (void*)data);
00968 }
00969 else
00970 {
00971 callback_god_force_owner(0, (void*)data);
00972 }
00973 }
00974
00975 void callback_god_force_owner(S32 option, void* user_data)
00976 {
00977 LLGodForceOwnerData* data = (LLGodForceOwnerData*)user_data;
00978 if(data && (0 == option))
00979 {
00980 LLMessageSystem* msg = gMessageSystem;
00981 msg->newMessage("ParcelGodForceOwner");
00982 msg->nextBlock("AgentData");
00983 msg->addUUID("AgentID", gAgent.getID());
00984 msg->addUUID("SessionID", gAgent.getSessionID());
00985 msg->nextBlock("Data");
00986 msg->addUUID("OwnerID", data->mOwnerID);
00987 msg->addS32( "LocalID", data->mLocalID);
00988 msg->sendReliable(data->mHost);
00989 }
00990 delete data;
00991 }
00992
00993 void LLViewerParcelMgr::sendParcelGodForceToContent()
00994 {
00995 if (!mSelected)
00996 {
00997 gViewerWindow->alertXml("CannotContentifyNothingSelected");
00998 return;
00999 }
01000 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01001 if (!region)
01002 {
01003 gViewerWindow->alertXml("CannotContentifyNoRegion");
01004 return;
01005 }
01006
01007 LLMessageSystem* msg = gMessageSystem;
01008 msg->newMessage("ParcelGodMarkAsContent");
01009 msg->nextBlock("AgentData");
01010 msg->addUUID("AgentID", gAgent.getID());
01011 msg->addUUID("SessionID", gAgent.getSessionID());
01012 msg->nextBlock("ParcelData");
01013 msg->addS32("LocalID", mCurrentParcel->getLocalID());
01014 msg->sendReliable(region->getHost());
01015 }
01016
01017 void LLViewerParcelMgr::sendParcelRelease()
01018 {
01019 if (!mSelected)
01020 {
01021 gViewerWindow->alertXml("CannotReleaseLandNothingSelected");
01022 return;
01023 }
01024
01025 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01026 if (!region)
01027 {
01028 gViewerWindow->alertXml("CannotReleaseLandNoRegion");
01029 return;
01030 }
01031
01032
01033
01034
01035 LLMessageSystem* msg = gMessageSystem;
01036 msg->newMessage("ParcelRelease");
01037 msg->nextBlock("AgentData");
01038 msg->addUUID("AgentID", gAgent.getID() );
01039 msg->addUUID("SessionID", gAgent.getSessionID() );
01040 msg->nextBlock("Data");
01041 msg->addS32("LocalID", mCurrentParcel->getLocalID() );
01042
01043 msg->sendReliable( region->getHost() );
01044
01045
01046
01047 deselectLand();
01048 }
01049
01050 class LLViewerParcelMgr::ParcelBuyInfo
01051 {
01052 public:
01053 LLUUID mAgent;
01054 LLUUID mSession;
01055 LLUUID mGroup;
01056 BOOL mIsGroupOwned;
01057 BOOL mRemoveContribution;
01058 BOOL mIsClaim;
01059 LLHost mHost;
01060
01061
01062 S32 mParcelID;
01063 S32 mPrice;
01064 S32 mArea;
01065
01066
01067 F32 mWest;
01068 F32 mSouth;
01069 F32 mEast;
01070 F32 mNorth;
01071 };
01072
01073 LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
01074 const LLUUID& agent_id,
01075 const LLUUID& session_id,
01076 const LLUUID& group_id,
01077 BOOL is_group_owned,
01078 BOOL is_claim,
01079 BOOL remove_contribution)
01080 {
01081 if (!mSelected || !mCurrentParcel)
01082 {
01083 gViewerWindow->alertXml("CannotBuyLandNothingSelected");
01084 return NULL;
01085 }
01086
01087 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01088 if (!region)
01089 {
01090 gViewerWindow->alertXml("CannotBuyLandNoRegion");
01091 return NULL;
01092 }
01093
01094 if (is_claim)
01095 {
01096 llinfos << "Claiming " << mWestSouth << " to " << mEastNorth << llendl;
01097 llinfos << "Region " << region->getOriginGlobal() << llendl;
01098
01099
01100 LLVector3d east_north_region_check( mEastNorth );
01101 east_north_region_check.mdV[VX] -= 0.5;
01102 east_north_region_check.mdV[VY] -= 0.5;
01103
01104 LLViewerRegion *region2 = gWorldp->getRegionFromPosGlobal( east_north_region_check );
01105
01106 if (region != region2)
01107 {
01108 gViewerWindow->alertXml("CantBuyLandAcrossMultipleRegions");
01109 return NULL;
01110 }
01111 }
01112
01113
01114 ParcelBuyInfo* info = new ParcelBuyInfo;
01115
01116 info->mAgent = agent_id;
01117 info->mSession = session_id;
01118 info->mGroup = group_id;
01119 info->mIsGroupOwned = is_group_owned;
01120 info->mIsClaim = is_claim;
01121 info->mRemoveContribution = remove_contribution;
01122 info->mHost = region->getHost();
01123 info->mPrice = mCurrentParcel->getSalePrice();
01124 info->mArea = mCurrentParcel->getArea();
01125
01126 if (!is_claim)
01127 {
01128 info->mParcelID = mCurrentParcel->getLocalID();
01129 }
01130 else
01131 {
01132
01133 LLVector3 west_south_bottom_region = region->getPosRegionFromGlobal( mWestSouth );
01134 LLVector3 east_north_top_region = region->getPosRegionFromGlobal( mEastNorth );
01135
01136 info->mWest = west_south_bottom_region.mV[VX];
01137 info->mSouth = west_south_bottom_region.mV[VY];
01138 info->mEast = east_north_top_region.mV[VX];
01139 info->mNorth = east_north_top_region.mV[VY];
01140 }
01141
01142 return info;
01143 }
01144
01145 void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info)
01146 {
01147
01148 LLMessageSystem* msg = gMessageSystem;
01149 msg->newMessage(info->mIsClaim ? "ParcelClaim" : "ParcelBuy");
01150 msg->nextBlock("AgentData");
01151 msg->addUUID("AgentID", info->mAgent);
01152 msg->addUUID("SessionID", info->mSession);
01153 msg->nextBlock("Data");
01154 msg->addUUID("GroupID", info->mGroup);
01155 msg->addBOOL("IsGroupOwned", info->mIsGroupOwned);
01156 if (!info->mIsClaim)
01157 {
01158 msg->addBOOL("RemoveContribution", info->mRemoveContribution);
01159 msg->addS32("LocalID", info->mParcelID);
01160 }
01161 msg->addBOOL("Final", TRUE);
01162 if (info->mIsClaim)
01163 {
01164 msg->nextBlock("ParcelData");
01165 msg->addF32("West", info->mWest);
01166 msg->addF32("South", info->mSouth);
01167 msg->addF32("East", info->mEast);
01168 msg->addF32("North", info->mNorth);
01169 }
01170 else
01171 {
01172 msg->nextBlock("ParcelData");
01173 msg->addS32("Price",info->mPrice);
01174 msg->addS32("Area",info->mArea);
01175 }
01176 msg->sendReliable(info->mHost);
01177 }
01178
01179 void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info)
01180 {
01181 delete info;
01182 info = NULL;
01183 }
01184
01185 void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
01186 {
01187 if (!mSelected || !mCurrentParcel)
01188 {
01189 gViewerWindow->alertXml("CannotDeedLandNothingSelected");
01190 return;
01191 }
01192 if(group_id.isNull())
01193 {
01194 gViewerWindow->alertXml("CannotDeedLandNoGroup");
01195 return;
01196 }
01197 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01198 if (!region)
01199 {
01200 gViewerWindow->alertXml("CannotDeedLandNoRegion");
01201 return;
01202 }
01203
01204 LLMessageSystem* msg = gMessageSystem;
01205 msg->newMessage("ParcelDeedToGroup");
01206 msg->nextBlock("AgentData");
01207 msg->addUUID("AgentID", gAgent.getID() );
01208 msg->addUUID("SessionID", gAgent.getSessionID() );
01209 msg->nextBlock("Data");
01210 msg->addUUID("GroupID", group_id );
01211 msg->addS32("LocalID", mCurrentParcel->getLocalID() );
01212
01213 msg->sendReliable( region->getHost() );
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 const LLString& LLViewerParcelMgr::getAgentParcelName() const
01256 {
01257 return mAgentParcel->getName();
01258 }
01259
01260
01261 void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel)
01262 {
01263 if (!parcel) return;
01264
01265 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01266 if (!region) return;
01267
01268 LLMessageSystem *msg = gMessageSystem;
01269
01270 msg->newMessageFast(_PREHASH_ParcelPropertiesUpdate);
01271 msg->nextBlockFast(_PREHASH_AgentData);
01272 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
01273 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01274 msg->nextBlockFast(_PREHASH_ParcelData);
01275 msg->addS32Fast(_PREHASH_LocalID, parcel->getLocalID() );
01276
01277 U32 flags = 0x0;
01278
01279 flags |= 0x01;
01280 msg->addU32("Flags", flags);
01281
01282 parcel->packMessage(msg);
01283
01284 msg->sendReliable( region->getHost() );
01285 }
01286
01287
01288 void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos)
01289 {
01290 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( pos );
01291 if (!region)
01292 {
01293 return;
01294 }
01295
01296
01297
01298
01299 LLVector3 wsb_region = region->getPosRegionFromGlobal( pos );
01300
01301 F32 west = PARCEL_GRID_STEP_METERS * floor( wsb_region.mV[VX] / PARCEL_GRID_STEP_METERS );
01302 F32 south = PARCEL_GRID_STEP_METERS * floor( wsb_region.mV[VY] / PARCEL_GRID_STEP_METERS );
01303
01304 F32 east = west + PARCEL_GRID_STEP_METERS;
01305 F32 north = south + PARCEL_GRID_STEP_METERS;
01306
01307
01308 LLMessageSystem *msg = gMessageSystem;
01309 msg->newMessageFast(_PREHASH_ParcelPropertiesRequest);
01310 msg->nextBlockFast(_PREHASH_AgentData);
01311 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
01312 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
01313 msg->nextBlockFast(_PREHASH_ParcelData);
01314 msg->addS32Fast(_PREHASH_SequenceID, HOVERED_PARCEL_SEQ_ID );
01315 msg->addF32Fast(_PREHASH_West, west );
01316 msg->addF32Fast(_PREHASH_South, south );
01317 msg->addF32Fast(_PREHASH_East, east );
01318 msg->addF32Fast(_PREHASH_North, north );
01319 msg->addBOOL("SnapSelection", FALSE );
01320 msg->sendReliable( region->getHost() );
01321
01322 mHoverRequestResult = PARCEL_RESULT_NO_DATA;
01323 }
01324
01325
01326
01327 void LLViewerParcelMgr::processParcelOverlay(LLMessageSystem *msg, void **user)
01328 {
01329 if (gNoRender)
01330 {
01331 return;
01332 }
01333
01334
01335 S32 packed_overlay_size = msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_Data);
01336
01337 if (packed_overlay_size == 0)
01338 {
01339 llwarns << "Overlay size 0" << llendl;
01340 return;
01341 }
01342
01343 S32 parcels_per_edge = gParcelMgr->mParcelsPerEdge;
01344 S32 expected_size = parcels_per_edge * parcels_per_edge / PARCEL_OVERLAY_CHUNKS;
01345 if (packed_overlay_size != expected_size)
01346 {
01347 llwarns << "Got parcel overlay size " << packed_overlay_size
01348 << " expecting " << expected_size << llendl;
01349 return;
01350 }
01351
01352 S32 sequence_id;
01353 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id);
01354 msg->getBinaryDataFast(
01355 _PREHASH_ParcelData,
01356 _PREHASH_Data,
01357 sPackedOverlay,
01358 expected_size);
01359
01360 LLHost host = msg->getSender();
01361 LLViewerRegion *region = gWorldp->getRegion(host);
01362 if (region)
01363 {
01364 region->mParcelOverlay->uncompressLandOverlay( sequence_id, sPackedOverlay );
01365 }
01366 }
01367
01368
01369
01370 void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **user)
01371 {
01372 S32 request_result;
01373 S32 sequence_id;
01374 BOOL snap_selection = FALSE;
01375 S32 self_count = 0;
01376 S32 other_count = 0;
01377 S32 public_count = 0;
01378 S32 local_id;
01379 LLUUID owner_id;
01380 BOOL is_group_owned;
01381 U32 auction_id = 0;
01382 S32 claim_price_per_meter = 0;
01383 S32 rent_price_per_meter = 0;
01384 S32 claim_date = 0;
01385 LLVector3 aabb_min;
01386 LLVector3 aabb_max;
01387 S32 area = 0;
01388 S32 sw_max_prims = 0;
01389 S32 sw_total_prims = 0;
01390
01391 U8 status = 0;
01392 S32 max_prims = 0;
01393 S32 total_prims = 0;
01394 S32 owner_prims = 0;
01395 S32 group_prims = 0;
01396 S32 other_prims = 0;
01397 S32 selected_prims = 0;
01398 F32 parcel_prim_bonus = 1.f;
01399 BOOL region_push_override = false;
01400 BOOL region_deny_anonymous_override = false;
01401 BOOL region_deny_identified_override = false;
01402 BOOL region_deny_transacted_override = false;
01403
01404 S32 other_clean_time = 0;
01405
01406 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_RequestResult, request_result );
01407 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id );
01408
01409 if (request_result == PARCEL_RESULT_NO_DATA)
01410 {
01411
01412 llinfos << "no valid parcel data" << llendl;
01413 return;
01414 }
01415
01416
01417 LLParcel* parcel = NULL;
01418 if (sequence_id == SELECTED_PARCEL_SEQ_ID)
01419 {
01420
01421 gParcelMgr->mRequestResult = PARCEL_RESULT_SUCCESS;
01422 parcel = gParcelMgr->mCurrentParcel;
01423 }
01424 else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
01425 {
01426 gParcelMgr->mHoverRequestResult = PARCEL_RESULT_SUCCESS;
01427 parcel = gParcelMgr->mHoverParcel;
01428 }
01429 else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID ||
01430 sequence_id == COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID ||
01431 sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
01432 {
01433 gParcelMgr->mHoverRequestResult = PARCEL_RESULT_SUCCESS;
01434 parcel = gParcelMgr->mCollisionParcel;
01435 }
01436 else if (sequence_id == 0 || sequence_id > gParcelMgr->mAgentParcelSequenceID)
01437 {
01438
01439 gParcelMgr->mAgentParcelSequenceID = sequence_id;
01440 parcel = gParcelMgr->mAgentParcel;
01441 }
01442 else
01443 {
01444 llinfos << "out of order agent parcel sequence id " << sequence_id
01445 << " last good " << gParcelMgr->mAgentParcelSequenceID
01446 << llendl;
01447 return;
01448 }
01449
01450 msg->getBOOL("ParcelData", "SnapSelection", snap_selection);
01451 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SelfCount, self_count);
01452 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OtherCount, other_count);
01453 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_PublicCount, public_count);
01454 msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_LocalID, local_id );
01455 msg->getUUIDFast(_PREHASH_ParcelData, _PREHASH_OwnerID, owner_id);
01456 msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_IsGroupOwned, is_group_owned);
01457 msg->getU32Fast(_PREHASH_ParcelData, _PREHASH_AuctionID, auction_id);
01458 msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimDate, claim_date);
01459 msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimPrice, claim_price_per_meter);
01460 msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_RentPrice, rent_price_per_meter);
01461 msg->getVector3Fast(_PREHASH_ParcelData, _PREHASH_AABBMin, aabb_min);
01462 msg->getVector3Fast(_PREHASH_ParcelData, _PREHASH_AABBMax, aabb_max);
01463 msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_Area, area );
01464
01465 msg->getU8("ParcelData", "Status", status);
01466 msg->getS32("ParcelData", "SimWideMaxPrims", sw_max_prims );
01467 msg->getS32("ParcelData", "SimWideTotalPrims", sw_total_prims );
01468 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_MaxPrims, max_prims );
01469 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_TotalPrims, total_prims );
01470 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OwnerPrims, owner_prims );
01471 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_GroupPrims, group_prims );
01472 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OtherPrims, other_prims );
01473 msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SelectedPrims, selected_prims );
01474 msg->getF32Fast(_PREHASH_ParcelData, _PREHASH_ParcelPrimBonus, parcel_prim_bonus );
01475 msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionPushOverride, region_push_override );
01476 msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyAnonymous, region_deny_anonymous_override );
01477 msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyIdentified, region_deny_identified_override );
01478 msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyTransacted, region_deny_transacted_override );
01479
01480 msg->getS32("ParcelData", "OtherCleanTime", other_clean_time );
01481
01482
01483 if (parcel)
01484 {
01485 parcel->init(owner_id,
01486 FALSE, FALSE, FALSE,
01487 claim_date, claim_price_per_meter, rent_price_per_meter,
01488 area, other_prims, parcel_prim_bonus, is_group_owned);
01489 parcel->setLocalID(local_id);
01490 parcel->setAABBMin(aabb_min);
01491 parcel->setAABBMax(aabb_max);
01492
01493 parcel->setAuctionID(auction_id);
01494 parcel->setOwnershipStatus((LLParcel::EOwnershipStatus)status);
01495
01496 parcel->setSimWideMaxPrimCapacity(sw_max_prims);
01497 parcel->setSimWidePrimCount(sw_total_prims);
01498 parcel->setMaxPrimCapacity(max_prims);
01499 parcel->setOwnerPrimCount(owner_prims);
01500 parcel->setGroupPrimCount(group_prims);
01501 parcel->setOtherPrimCount(other_prims);
01502 parcel->setSelectedPrimCount(selected_prims);
01503 parcel->setParcelPrimBonus(parcel_prim_bonus);
01504
01505 parcel->setCleanOtherTime(other_clean_time);
01506 parcel->setRegionPushOverride(region_push_override);
01507 parcel->setRegionDenyAnonymousOverride(region_deny_anonymous_override);
01508 parcel->setRegionDenyIdentifiedOverride(region_deny_identified_override);
01509 parcel->setRegionDenyTransactedOverride(region_deny_transacted_override);
01510 parcel->unpackMessage(msg);
01511
01512 if (parcel == gParcelMgr->mAgentParcel)
01513 {
01514 S32 bitmap_size = gParcelMgr->mParcelsPerEdge
01515 * gParcelMgr->mParcelsPerEdge
01516 / 8;
01517 U8* bitmap = new U8[ bitmap_size ];
01518 msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
01519
01520 gParcelMgr->writeAgentParcelFromBitmap(bitmap);
01521 delete[] bitmap;
01522 }
01523 }
01524
01525
01526 if (sequence_id == SELECTED_PARCEL_SEQ_ID)
01527 {
01528
01529 gParcelMgr->mCurrentParcelSelection->mSelectedSelfCount = self_count;
01530 gParcelMgr->mCurrentParcelSelection->mSelectedOtherCount = other_count;
01531 gParcelMgr->mCurrentParcelSelection->mSelectedPublicCount = public_count;
01532
01533 gParcelMgr->mCurrentParcelSelection->mSelectedMultipleOwners =
01534 (request_result == PARCEL_RESULT_MULTIPLE);
01535
01536
01537 LLViewerRegion *region = gWorldp->getRegion( msg->getSender() );
01538 if (region)
01539 {
01540 if (!snap_selection)
01541 {
01542
01543
01544 LLVector3 west_south = region->getPosRegionFromGlobal(gParcelMgr->mWestSouth);
01545 LLVector3 east_north = region->getPosRegionFromGlobal(gParcelMgr->mEastNorth);
01546
01547 gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments);
01548 gParcelMgr->writeHighlightSegments(
01549 west_south.mV[VX],
01550 west_south.mV[VY],
01551 east_north.mV[VX],
01552 east_north.mV[VY] );
01553 gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = FALSE;
01554 }
01555 else if (0 == local_id)
01556 {
01557
01558 gParcelMgr->mWestSouth = region->getPosGlobalFromRegion( aabb_min );
01559 gParcelMgr->mEastNorth = region->getPosGlobalFromRegion( aabb_max );
01560
01561 gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments);
01562 gParcelMgr->writeHighlightSegments(
01563 aabb_min.mV[VX],
01564 aabb_min.mV[VY],
01565 aabb_max.mV[VX],
01566 aabb_max.mV[VY] );
01567 gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE;
01568 }
01569 else
01570 {
01571 gParcelMgr->mWestSouth = region->getPosGlobalFromRegion( aabb_min );
01572 gParcelMgr->mEastNorth = region->getPosGlobalFromRegion( aabb_max );
01573
01574
01575 S32 bitmap_size = gParcelMgr->mParcelsPerEdge
01576 * gParcelMgr->mParcelsPerEdge
01577 / 8;
01578 U8* bitmap = new U8[ bitmap_size ];
01579 msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
01580
01581 gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments);
01582 gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mHighlightSegments );
01583
01584 delete[] bitmap;
01585 bitmap = NULL;
01586
01587 gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE;
01588 }
01589
01590
01591 gParcelMgr->sendParcelAccessListRequest(AL_ACCESS | AL_BAN);
01592
01593
01594 gParcelMgr->mSelectedDwell = 0.f;
01595 if (0 != local_id)
01596 {
01597 gParcelMgr->sendParcelDwellRequest();
01598 }
01599
01600 gParcelMgr->mSelected = TRUE;
01601 gParcelMgr->notifyObservers();
01602 }
01603 }
01604 else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID ||
01605 sequence_id == COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID ||
01606 sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
01607 {
01608
01609 gParcelMgr->mRenderCollision = TRUE;
01610 gParcelMgr->mCollisionTimer.reset();
01611
01612
01613 if (sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
01614 {
01615 gParcelMgr->mCollisionBanned = BA_BANNED;
01616 }
01617 else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID)
01618 {
01619 gParcelMgr->mCollisionBanned = BA_NOT_IN_GROUP;
01620 }
01621 else
01622 {
01623 gParcelMgr->mCollisionBanned = BA_NOT_ON_LIST;
01624
01625 }
01626
01627 S32 bitmap_size = gParcelMgr->mParcelsPerEdge
01628 * gParcelMgr->mParcelsPerEdge
01629 / 8;
01630 U8* bitmap = new U8[ bitmap_size ];
01631 msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
01632
01633 gParcelMgr->resetSegments(gParcelMgr->mCollisionSegments);
01634 gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mCollisionSegments );
01635
01636 delete[] bitmap;
01637 bitmap = NULL;
01638
01639 }
01640 else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
01641 {
01642 LLViewerRegion *region = gWorldp->getRegion( msg->getSender() );
01643 if (region)
01644 {
01645 gParcelMgr->mHoverWestSouth = region->getPosGlobalFromRegion( aabb_min );
01646 gParcelMgr->mHoverEastNorth = region->getPosGlobalFromRegion( aabb_max );
01647 }
01648 else
01649 {
01650 gParcelMgr->mHoverWestSouth.clearVec();
01651 gParcelMgr->mHoverEastNorth.clearVec();
01652 }
01653 }
01654 else
01655 {
01656
01657 BOOL new_parcel = parcel ? FALSE : TRUE;
01658 if (parcel)
01659 {
01660 S32 parcelid = parcel->getLocalID();
01661 U64 regionid = gAgent.getRegion()->getHandle();
01662 if (parcelid != gParcelMgr->mMediaParcelId || regionid != gParcelMgr->mMediaRegionId)
01663 {
01664 gParcelMgr->mMediaParcelId = parcelid;
01665 gParcelMgr->mMediaRegionId = regionid;
01666 new_parcel = TRUE;
01667 }
01668 }
01669
01670 if (gAudiop)
01671 {
01672 if (parcel)
01673 {
01674 LLString music_url_raw = parcel->getMusicURL();
01675
01676
01677 LLString music_url = music_url_raw;
01678 LLString::trim(music_url);
01679
01680
01681
01682
01683 const char* stream_url = gAudiop->getInternetStreamURL();
01684
01685 if (music_url.empty() || music_url != stream_url)
01686 {
01687
01688 gAudiop->stopInternetStream();
01689
01690
01691 if (music_url.size() > 12)
01692 {
01693 if (music_url.substr(0,7) == "http://")
01694 {
01695 optionally_start_music(music_url);
01696 }
01697 }
01698 else if (gAudiop->getInternetStreamURL()[0])
01699 {
01700 llinfos << "Stopping parcel music" << llendl;
01701 gAudiop->startInternetStream(NULL);
01702 }
01703 }
01704 }
01705 else
01706 {
01707
01708 gAudiop->stopInternetStream();
01709 }
01710 }
01711
01712
01713 if (LLMediaEngine::getInstance ()->isAvailable ())
01714 {
01715
01716 if (parcel)
01717 {
01718
01719 std::string mediaUrl = std::string ( parcel->getMediaURL () );
01720 LLString::trim(mediaUrl);
01721
01722
01723 LLMediaEngine* me = LLMediaEngine::getInstance();
01724 if ( ( me->getUrl () != mediaUrl )
01725 || ( me->getImageUUID () != parcel->getMediaID () )
01726 || ( me->isAutoScaled () != parcel->getMediaAutoScale () ) )
01727 {
01728 BOOL video_was_playing = FALSE;
01729 LLMediaBase* renderer = me->getMediaRenderer();
01730 if (renderer && (renderer->isPlaying() || renderer->isLooping()))
01731 {
01732 video_was_playing = TRUE;
01733 }
01734
01735 stop_video();
01736
01737 if ( !mediaUrl.empty () )
01738 {
01739
01740
01741 if (!new_parcel
01742 && gSavedSettings.getBOOL("AudioStreamingVideo")
01743 && video_was_playing)
01744 {
01745 start_video(parcel);
01746 }
01747 else
01748 {
01749
01750 optionally_prepare_video(parcel);
01751 }
01752 }
01753 }
01754 }
01755 else
01756 {
01757 stop_video();
01758 }
01759 }
01760 else
01761 {
01762
01763 if (parcel)
01764 {
01765 std::string mediaUrl = std::string ( parcel->getMediaURL () );
01766 if (!mediaUrl.empty ())
01767 {
01768 if (gSavedSettings.getWarning("QuickTimeInstalled"))
01769 {
01770 gSavedSettings.setWarning("QuickTimeInstalled", FALSE);
01771
01772 LLNotifyBox::showXml("NoQuickTime" );
01773 };
01774 }
01775 }
01776 }
01777
01778 };
01779 }
01780
01781 void optionally_start_music(const LLString& music_url)
01782 {
01783 if (gSavedSettings.getWarning("FirstStreamingMusic"))
01784 {
01785 std::string* newstring = new std::string(music_url);
01786 gViewerWindow->alertXml("ParcelCanPlayMusic",
01787 callback_start_music,
01788 (void*)newstring);
01789
01790 }
01791 else if (gSavedSettings.getBOOL("AudioStreamingMusic"))
01792 {
01793
01794
01795
01796
01797
01798 if ( gOverlayBar && gOverlayBar->musicPlaying() )
01799 {
01800 LLOverlayBar::musicPlay(NULL);
01801 }
01802 }
01803 }
01804
01805
01806 void callback_start_music(S32 option, void* data)
01807 {
01808 std::string* music_url = (std::string*)data;
01809
01810 if (0 == option)
01811 {
01812 gSavedSettings.setBOOL("AudioStreamingMusic", TRUE);
01813 llinfos << "Starting first parcel music " << music_url << llendl;
01814 LLOverlayBar::musicPlay(NULL);
01815 }
01816 else
01817 {
01818 gSavedSettings.setBOOL("AudioStreamingMusic", FALSE);
01819 }
01820
01821 gSavedSettings.setWarning("FirstStreamingMusic", FALSE);
01822
01823 delete music_url;
01824 music_url = NULL;
01825 }
01826
01827 void prepare_video(const LLParcel *parcel)
01828 {
01829 std::string mediaUrl;
01830 if (parcel->getParcelFlag(PF_URL_RAW_HTML))
01831 {
01832 mediaUrl = std::string("data:");
01833 mediaUrl.append(parcel->getMediaURL());
01834 }
01835 else
01836 {
01837 mediaUrl = std::string ( parcel->getMediaURL () );
01838 }
01839 LLMediaEngine::getInstance ()->setUrl ( mediaUrl );
01840 LLMediaEngine::getInstance ()->setImageUUID ( parcel->getMediaID () );
01841 LLMediaEngine::getInstance ()->setAutoScaled ( parcel->getMediaAutoScale () ? TRUE : FALSE );
01842 }
01843
01844 void start_video(const LLParcel *parcel)
01845 {
01846 prepare_video(parcel);
01847 std::string path( "" );
01848 LLMediaEngine::getInstance ()->convertImageAndLoadUrl ( true, false, path);
01849 }
01850
01851 void stop_video()
01852 {
01853
01854 LLMediaEngine::getInstance ()->stop ();
01855 if (gOverlayBar)
01856 {
01857 gOverlayBar->refresh ();
01858 }
01859
01860 if (LLMediaEngine::getInstance ()->isLoaded())
01861 {
01862 LLMediaEngine::getInstance ()->unload ();
01863
01864 gImageList.updateMovieImage(LLUUID::null, FALSE);
01865 gCurrentMovieID.setNull();
01866 }
01867
01868 LLMediaEngine::getInstance ()->setUrl ( "" );
01869 LLMediaEngine::getInstance ()->setImageUUID ( LLUUID::null );
01870
01871 }
01872
01873 void optionally_prepare_video(const LLParcel *parcelp)
01874 {
01875 if (gSavedSettings.getWarning("FirstStreamingVideo"))
01876 {
01877 gViewerWindow->alertXml("ParcelCanPlayMedia",
01878 callback_prepare_video,
01879 (void*)parcelp);
01880 }
01881 else
01882 {
01883 llinfos << "Entering parcel " << parcelp->getLocalID() << " with video " << parcelp->getMediaURL() << llendl;
01884 prepare_video(parcelp);
01885 }
01886 }
01887
01888
01889 void callback_prepare_video(S32 option, void* data)
01890 {
01891 const LLParcel *parcelp = (const LLParcel *)data;
01892
01893 if (0 == option)
01894 {
01895 gSavedSettings.setBOOL("AudioStreamingVideo", TRUE);
01896 llinfos << "Starting parcel video " << parcelp->getMediaURL() << " on parcel " << parcelp->getLocalID() << llendl;
01897 gMessageSystem->setHandlerFunc("ParcelMediaCommandMessage", LLMediaEngine::process_parcel_media);
01898 gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", LLMediaEngine::process_parcel_media_update );
01899 prepare_video(parcelp);
01900 }
01901 else
01902 {
01903 gMessageSystem->setHandlerFunc("ParcelMediaCommandMessage", null_message_callback);
01904 gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", null_message_callback );
01905 gSavedSettings.setBOOL("AudioStreamingVideo", FALSE);
01906 }
01907
01908 gSavedSettings.setWarning("FirstStreamingVideo", FALSE);
01909 }
01910
01911
01912 void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void **user)
01913 {
01914 LLUUID agent_id;
01915 S32 sequence_id = 0;
01916 U32 message_flags = 0x0;
01917 S32 parcel_id = -1;
01918
01919 msg->getUUIDFast(_PREHASH_Data, _PREHASH_AgentID, agent_id);
01920 msg->getS32Fast( _PREHASH_Data, _PREHASH_SequenceID, sequence_id );
01921 msg->getU32Fast( _PREHASH_Data, _PREHASH_Flags, message_flags);
01922 msg->getS32Fast( _PREHASH_Data, _PREHASH_LocalID, parcel_id);
01923
01924 LLParcel* parcel = gParcelMgr->mCurrentParcel;
01925 if (!parcel) return;
01926
01927 if (parcel_id != parcel->getLocalID())
01928 {
01929 llwarns << "processParcelAccessListReply for parcel " << parcel_id
01930 << " which isn't the selected parcel " << parcel->getLocalID()<< llendl;
01931 return;
01932 }
01933
01934 if (message_flags & AL_ACCESS)
01935 {
01936 parcel->unpackAccessEntries(msg, &(parcel->mAccessList) );
01937 }
01938 else if (message_flags & AL_BAN)
01939 {
01940 parcel->unpackAccessEntries(msg, &(parcel->mBanList) );
01941 }
01942
01943
01944
01945
01946
01947 gParcelMgr->notifyObservers();
01948 }
01949
01950
01951
01952 void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**)
01953 {
01954 LLUUID agent_id;
01955 msg->getUUID("AgentData", "AgentID", agent_id);
01956
01957 S32 local_id;
01958 msg->getS32("Data", "LocalID", local_id);
01959
01960 LLUUID parcel_id;
01961 msg->getUUID("Data", "ParcelID", parcel_id);
01962
01963 F32 dwell;
01964 msg->getF32("Data", "Dwell", dwell);
01965
01966 if (local_id == gParcelMgr->mCurrentParcel->getLocalID())
01967 {
01968 gParcelMgr->mSelectedDwell = dwell;
01969 gParcelMgr->notifyObservers();
01970 }
01971 }
01972
01973
01974 void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
01975 {
01976
01977 LLUUID transactionUUID;
01978 transactionUUID.generate();
01979
01980 if (!mSelected)
01981 {
01982 return;
01983 }
01984
01985 LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01986 if (!region) return;
01987
01988 LLMessageSystem* msg = gMessageSystem;
01989
01990 LLParcel* parcel = mCurrentParcel;
01991 if (!parcel) return;
01992
01993 if (which & AL_ACCESS)
01994 {
01995 S32 count = parcel->mAccessList.size();
01996 S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
01997 S32 sequence_id = 1;
01998 BOOL start_message = TRUE;
01999 BOOL initial = TRUE;
02000
02001 access_map_const_iterator cit = parcel->mAccessList.begin();
02002 access_map_const_iterator end = parcel->mAccessList.end();
02003 while ( (cit != end) || initial )
02004 {
02005 if (start_message)
02006 {
02007 msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
02008 msg->nextBlockFast(_PREHASH_AgentData);
02009 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
02010 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
02011 msg->nextBlockFast(_PREHASH_Data);
02012 msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
02013 msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
02014 msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
02015 msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
02016 msg->addS32Fast(_PREHASH_Sections, num_sections);
02017 start_message = FALSE;
02018
02019 if (initial && (cit == end))
02020 {
02021
02022 msg->nextBlockFast(_PREHASH_List);
02023 msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
02024 msg->addS32Fast(_PREHASH_Time, 0 );
02025 msg->addU32Fast(_PREHASH_Flags, 0 );
02026 }
02027
02028 initial = FALSE;
02029 sequence_id++;
02030
02031 }
02032
02033 while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES))
02034 {
02035
02036 const LLAccessEntry& entry = (*cit).second;
02037
02038 msg->nextBlockFast(_PREHASH_List);
02039 msg->addUUIDFast(_PREHASH_ID, entry.mID );
02040 msg->addS32Fast(_PREHASH_Time, entry.mTime );
02041 msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
02042 ++cit;
02043 }
02044
02045 start_message = TRUE;
02046 msg->sendReliable( region->getHost() );
02047 }
02048 }
02049
02050 if (which & AL_BAN)
02051 {
02052 S32 count = parcel->mBanList.size();
02053 S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
02054 S32 sequence_id = 1;
02055 BOOL start_message = TRUE;
02056 BOOL initial = TRUE;
02057
02058 access_map_const_iterator cit = parcel->mBanList.begin();
02059 access_map_const_iterator end = parcel->mBanList.end();
02060 while ( (cit != end) || initial )
02061 {
02062 if (start_message)
02063 {
02064 msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
02065 msg->nextBlockFast(_PREHASH_AgentData);
02066 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
02067 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
02068 msg->nextBlockFast(_PREHASH_Data);
02069 msg->addU32Fast(_PREHASH_Flags, AL_BAN);
02070 msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
02071 msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
02072 msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
02073 msg->addS32Fast(_PREHASH_Sections, num_sections);
02074 start_message = FALSE;
02075
02076 if (initial && (cit == end))
02077 {
02078
02079 msg->nextBlockFast(_PREHASH_List);
02080 msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
02081 msg->addS32Fast(_PREHASH_Time, 0 );
02082 msg->addU32Fast(_PREHASH_Flags, 0 );
02083 }
02084
02085 initial = FALSE;
02086 sequence_id++;
02087
02088 }
02089
02090 while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES))
02091 {
02092 const LLAccessEntry& entry = (*cit).second;
02093
02094 msg->nextBlockFast(_PREHASH_List);
02095 msg->addUUIDFast(_PREHASH_ID, entry.mID );
02096 msg->addS32Fast(_PREHASH_Time, entry.mTime );
02097 msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
02098 ++cit;
02099 }
02100
02101 start_message = TRUE;
02102 msg->sendReliable( region->getHost() );
02103 }
02104 }
02105 }
02106
02107
02108 void LLViewerParcelMgr::deedLandToGroup()
02109 {
02110 char group_name[MAX_STRING];
02111 gCacheName->getGroupName(mCurrentParcel->getGroupID(), group_name);
02112 LLString::format_map_t args;
02113 args["[AREA]"] = llformat("%d", mCurrentParcel->getArea());
02114 args["[GROUP_NAME]"] = group_name;
02115 if(mCurrentParcel->getContributeWithDeed())
02116 {
02117 char first_name[DB_FIRST_NAME_BUF_SIZE];
02118 first_name[0] = '\0';
02119 char last_name[DB_FIRST_NAME_BUF_SIZE];
02120 last_name[0] = '\0';
02121 gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name);
02122 args["[FIRST_NAME]"] = first_name;
02123 args["[LAST_NAME]"] = last_name;
02124 gViewerWindow->alertXml("DeedLandToGroupWithContribution",args, deedAlertCB, NULL);
02125 }
02126 else
02127 {
02128 gViewerWindow->alertXml("DeedLandToGroup",args, deedAlertCB, NULL);
02129 }
02130 }
02131
02132
02133 void LLViewerParcelMgr::deedAlertCB(S32 option, void*)
02134 {
02135 if (option == 0)
02136 {
02137 LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel();
02138 LLUUID group_id;
02139 if(parcel)
02140 {
02141 group_id = parcel->getGroupID();
02142 }
02143 gParcelMgr->sendParcelDeed(group_id);
02144 }
02145 }
02146
02147
02148 void LLViewerParcelMgr::startReleaseLand()
02149 {
02150 if (!mSelected)
02151 {
02152 gViewerWindow->alertXml("CannotReleaseLandNothingSelected");
02153 return;
02154 }
02155
02156 if (mRequestResult == PARCEL_RESULT_NO_DATA)
02157 {
02158 gViewerWindow->alertXml("CannotReleaseLandWatingForServer");
02159 return;
02160 }
02161
02162 if (mRequestResult == PARCEL_RESULT_MULTIPLE)
02163 {
02164 gViewerWindow->alertXml("CannotReleaseLandSelected");
02165 return;
02166 }
02167
02168 if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE)
02169 && !(gAgent.canManageEstate()))
02170 {
02171 gViewerWindow->alertXml("CannotReleaseLandDontOwn");
02172 return;
02173 }
02174
02175 LLVector3d parcel_center = (mWestSouth + mEastNorth) / 2.0;
02176 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02177 if (!region)
02178 {
02179 gViewerWindow->alertXml("CannotReleaseLandRegionNotFound");
02180 return;
02181 }
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193 if (!mCurrentParcelSelection->mWholeParcelSelected)
02194 {
02195 gViewerWindow->alertXml("CannotReleaseLandPartialSelection");
02196 return;
02197 }
02198
02199
02200 LLStringBase<char>::format_map_t args;
02201 args["[AREA]"] = llformat("%d",mCurrentParcel->getArea());
02202 gViewerWindow->alertXml("ReleaseLandWarning", args,
02203 releaseAlertCB, this);
02204 }
02205
02206 bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
02207 {
02208 if (!parcel)
02209 {
02210 return false;
02211 }
02212
02213 if (mSelected && parcel == mCurrentParcel)
02214 {
02215 if (mRequestResult == PARCEL_RESULT_NO_DATA)
02216 {
02217 return false;
02218 }
02219 }
02220
02221 const LLUUID& parcelOwner = parcel->getOwnerID();
02222 const LLUUID& authorizeBuyer = parcel->getAuthorizedBuyerID();
02223
02224 if (parcel->isPublic())
02225 {
02226 return true;
02227 }
02228
02229 bool isForSale = parcel->getForSale()
02230 && ((parcel->getSalePrice() > 0) || (authorizeBuyer.notNull()));
02231
02232 bool isEmpowered
02233 = forGroup ? gAgent.hasPowerInActiveGroup(GP_LAND_DEED) == TRUE : true;
02234
02235 bool isOwner
02236 = parcelOwner == (forGroup ? gAgent.getGroupID() : gAgent.getID());
02237
02238 bool isAuthorized
02239 = (authorizeBuyer.isNull() || (gAgent.getID() == authorizeBuyer));
02240
02241 return isForSale && !isOwner && isAuthorized && isEmpowered;
02242 }
02243
02244
02245 void LLViewerParcelMgr::startBuyLand(BOOL is_for_group)
02246 {
02247 LLFloaterBuyLand::buyLand(getSelectionRegion(), mCurrentParcelSelection, is_for_group == TRUE);
02248 }
02249
02250 void LLViewerParcelMgr::startSellLand()
02251 {
02252 LLFloaterSellLand::sellLand(getSelectionRegion(), mCurrentParcelSelection);
02253 }
02254
02255 void LLViewerParcelMgr::startDivideLand()
02256 {
02257 if (!mSelected)
02258 {
02259 gViewerWindow->alertXml("CannotDivideLandNothingSelected");
02260 return;
02261 }
02262
02263 if (mCurrentParcelSelection->mWholeParcelSelected)
02264 {
02265 gViewerWindow->alertXml("CannotDivideLandPartialSelection");
02266 return;
02267 }
02268
02269 gViewerWindow->alertXml("LandDivideWarning",
02270 callbackDivideLand,
02271 this);
02272 }
02273
02274
02275 void LLViewerParcelMgr::callbackDivideLand(S32 option, void* data)
02276 {
02277 LLViewerParcelMgr* self = (LLViewerParcelMgr*)data;
02278
02279 LLVector3d parcel_center = (self->mWestSouth + self->mEastNorth) / 2.0;
02280 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02281 if (!region)
02282 {
02283 gViewerWindow->alertXml("CannotDivideLandNoRegion");
02284 return;
02285 }
02286
02287 if (0 == option)
02288 {
02289 LLVector3 west_south = region->getPosRegionFromGlobal(self->mWestSouth);
02290 LLVector3 east_north = region->getPosRegionFromGlobal(self->mEastNorth);
02291
02292 LLMessageSystem* msg = gMessageSystem;
02293 msg->newMessage("ParcelDivide");
02294 msg->nextBlock("AgentData");
02295 msg->addUUID("AgentID", gAgent.getID());
02296 msg->addUUID("SessionID", gAgent.getSessionID());
02297 msg->nextBlock("ParcelData");
02298 msg->addF32("West", west_south.mV[VX]);
02299 msg->addF32("South", west_south.mV[VY]);
02300 msg->addF32("East", east_north.mV[VX]);
02301 msg->addF32("North", east_north.mV[VY]);
02302 msg->sendReliable(region->getHost());
02303 }
02304 }
02305
02306
02307 void LLViewerParcelMgr::startJoinLand()
02308 {
02309 if (!mSelected)
02310 {
02311 gViewerWindow->alertXml("CannotJoinLandNothingSelected");
02312 return;
02313 }
02314
02315 if (mCurrentParcelSelection->mWholeParcelSelected)
02316 {
02317 gViewerWindow->alertXml("CannotJoinLandEntireParcelSelected");
02318 return;
02319 }
02320
02321 if (!mCurrentParcelSelection->mSelectedMultipleOwners)
02322 {
02323 gViewerWindow->alertXml("CannotJoinLandSelection");
02324 return;
02325 }
02326
02327 gViewerWindow->alertXml("JoinLandWarning",
02328 callbackJoinLand,
02329 this);
02330 }
02331
02332
02333 void LLViewerParcelMgr::callbackJoinLand(S32 option, void* data)
02334 {
02335 LLViewerParcelMgr* self = (LLViewerParcelMgr*)data;
02336
02337 LLVector3d parcel_center = (self->mWestSouth + self->mEastNorth) / 2.0;
02338 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02339 if (!region)
02340 {
02341 gViewerWindow->alertXml("CannotJoinLandNoRegion");
02342 return;
02343 }
02344
02345 if (0 == option)
02346 {
02347 LLVector3 west_south = region->getPosRegionFromGlobal(self->mWestSouth);
02348 LLVector3 east_north = region->getPosRegionFromGlobal(self->mEastNorth);
02349
02350 LLMessageSystem* msg = gMessageSystem;
02351 msg->newMessage("ParcelJoin");
02352 msg->nextBlock("AgentData");
02353 msg->addUUID("AgentID", gAgent.getID());
02354 msg->addUUID("SessionID", gAgent.getSessionID());
02355 msg->nextBlock("ParcelData");
02356 msg->addF32("West", west_south.mV[VX]);
02357 msg->addF32("South", west_south.mV[VY]);
02358 msg->addF32("East", east_north.mV[VX]);
02359 msg->addF32("North", east_north.mV[VY]);
02360 msg->sendReliable(region->getHost());
02361 }
02362 }
02363
02364
02365 void LLViewerParcelMgr::startDeedLandToGroup()
02366 {
02367 if (!mSelected || !mCurrentParcel)
02368 {
02369 gViewerWindow->alertXml("CannotDeedLandNothingSelected");
02370 return;
02371 }
02372
02373 if (mRequestResult == PARCEL_RESULT_NO_DATA)
02374 {
02375 gViewerWindow->alertXml("CannotDeedLandWaitingForServer");
02376 return;
02377 }
02378
02379 if (mRequestResult == PARCEL_RESULT_MULTIPLE)
02380 {
02381 gViewerWindow->alertXml("CannotDeedLandMultipleSelected");
02382 return;
02383 }
02384
02385 LLVector3d parcel_center = (mWestSouth + mEastNorth) / 2.0;
02386 LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02387 if (!region)
02388 {
02389 gViewerWindow->alertXml("CannotDeedLandNoRegion");
02390 return;
02391 }
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407 deedLandToGroup();
02408 }
02409 void LLViewerParcelMgr::reclaimParcel()
02410 {
02411 LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel();
02412 LLViewerRegion* regionp = gParcelMgr->getSelectionRegion();
02413 if(parcel && parcel->getOwnerID().notNull()
02414 && (parcel->getOwnerID() != gAgent.getID())
02415 && regionp && (regionp->getOwner() == gAgent.getID()))
02416 {
02417 LLMessageSystem* msg = gMessageSystem;
02418 msg->newMessage("ParcelReclaim");
02419 msg->nextBlock("AgentData");
02420 msg->addUUID("AgentID", gAgent.getID());
02421 msg->addUUID("SessionID", gAgent.getSessionID());
02422 msg->nextBlock("Data");
02423 msg->addS32("LocalID", parcel->getLocalID());
02424 msg->sendReliable(regionp->getHost());
02425 }
02426 }
02427
02428
02429 void LLViewerParcelMgr::releaseAlertCB(S32 option, void *)
02430 {
02431 if (option == 0)
02432 {
02433
02434 gParcelMgr->sendParcelRelease();
02435 }
02436 }
02437
02438 void LLViewerParcelMgr::buyPass()
02439 {
02440 LLParcel* parcel = getParcelSelection()->getParcel();
02441 if (!parcel) return;
02442
02443 LLViewerRegion* region = getSelectionRegion();
02444 if (!region) return;
02445
02446 LLMessageSystem* msg = gMessageSystem;
02447 msg->newMessageFast(_PREHASH_ParcelBuyPass);
02448 msg->nextBlock("AgentData");
02449 msg->addUUID("AgentID", gAgent.getID());
02450 msg->addUUID("SessionID", gAgent.getSessionID());
02451 msg->nextBlockFast(_PREHASH_ParcelData);
02452 msg->addS32Fast(_PREHASH_LocalID, parcel->getLocalID() );
02453 msg->sendReliable( region->getHost() );
02454 }
02455
02456
02457 BOOL LLViewerParcelMgr::isCollisionBanned()
02458 {
02459 if ((mCollisionBanned == BA_ALLOWED) || (mCollisionBanned == BA_NOT_ON_LIST) || (mCollisionBanned == BA_NOT_IN_GROUP))
02460 return FALSE;
02461 else
02462 return TRUE;
02463 }
02464
02465
02466
02467 BOOL LLViewerParcelMgr::isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power)
02468 {
02469 if (!parcelp)
02470 {
02471 return FALSE;
02472 }
02473
02474
02475 if (gAgent.isGodlike())
02476 {
02477 return TRUE;
02478 }
02479
02480
02481 if (parcelp->getOwnerID() == gAgent.getID())
02482 {
02483 return TRUE;
02484 }
02485
02486
02487 if (parcelp->isPublic())
02488 {
02489 return FALSE;
02490 }
02491
02492
02493
02494 return gAgent.hasPowerInGroup(parcelp->getOwnerID(), group_proxy_power);
02495 }
02496
02497
02498
02499 BOOL LLViewerParcelMgr::isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power)
02500 {
02501
02502 BOOL rv = FALSE;
02503 if (parcelp)
02504 {
02505
02506
02507 rv = isParcelOwnedByAgent(parcelp, group_proxy_power);
02508
02509
02510 if( (gAgent.getID() == parcelp->getOwnerID())
02511 && !gAgent.isGodlike()
02512 && (parcelp->getOwnershipStatus() != LLParcel::OS_LEASED) )
02513 {
02514 rv = FALSE;
02515 }
02516 }
02517 return rv;
02518 }
02519
02520 void sanitize_corners(const LLVector3d &corner1,
02521 const LLVector3d &corner2,
02522 LLVector3d &west_south_bottom,
02523 LLVector3d &east_north_top)
02524 {
02525 west_south_bottom.mdV[VX] = llmin( corner1.mdV[VX], corner2.mdV[VX] );
02526 west_south_bottom.mdV[VY] = llmin( corner1.mdV[VY], corner2.mdV[VY] );
02527 west_south_bottom.mdV[VZ] = llmin( corner1.mdV[VZ], corner2.mdV[VZ] );
02528
02529 east_north_top.mdV[VX] = llmax( corner1.mdV[VX], corner2.mdV[VX] );
02530 east_north_top.mdV[VY] = llmax( corner1.mdV[VY], corner2.mdV[VY] );
02531 east_north_top.mdV[VZ] = llmax( corner1.mdV[VZ], corner2.mdV[VZ] );
02532 }
02533
02534
02535
02536
02537 LLParcelSelection::LLParcelSelection() :
02538 mParcel(NULL),
02539 mSelectedMultipleOwners(FALSE),
02540 mWholeParcelSelected(FALSE),
02541 mSelectedSelfCount(0),
02542 mSelectedOtherCount(0),
02543 mSelectedPublicCount(0)
02544 {
02545 }
02546
02547 LLParcelSelection::LLParcelSelection(LLParcel* parcel) :
02548 mParcel(parcel),
02549 mSelectedMultipleOwners(FALSE),
02550 mWholeParcelSelected(FALSE),
02551 mSelectedSelfCount(0),
02552 mSelectedOtherCount(0),
02553 mSelectedPublicCount(0)
02554 {
02555 }
02556
02557 LLParcelSelection::~LLParcelSelection()
02558 {
02559 }
02560
02561 BOOL LLParcelSelection::getMultipleOwners() const
02562 {
02563 return mSelectedMultipleOwners;
02564 }
02565
02566
02567 BOOL LLParcelSelection::getWholeParcelSelected() const
02568 {
02569 return mWholeParcelSelected;
02570 }
02571
02572
02573 S32 LLParcelSelection::getClaimableArea() const
02574 {
02575 const S32 UNIT_AREA = S32( PARCEL_GRID_STEP_METERS * PARCEL_GRID_STEP_METERS );
02576 return mSelectedPublicCount * UNIT_AREA;
02577 }
02578
02579 bool LLParcelSelection::hasOthersSelected() const
02580 {
02581 return mSelectedOtherCount != 0;
02582 }
02583
02584 static LLPointer<LLParcelSelection> sNullSelection;
02585
02586 LLParcelSelection* get_null_parcel_selection()
02587 {
02588 if (sNullSelection.isNull())
02589 {
02590 sNullSelection = new LLParcelSelection;
02591 }
02592
02593 return sNullSelection;
02594 }
02595
02596 void LLViewerParcelMgr::cleanupGlobals()
02597 {
02598 delete gParcelMgr;
02599 gParcelMgr = NULL;
02600 sNullSelection = NULL;
02601 }