llviewerparcelmgr.cpp

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

Generated on Fri May 16 08:34:16 2008 for SecondLife by  doxygen 1.5.5