aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs878
1 files changed, 28 insertions, 850 deletions
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs b/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
index 82341a9..77c70a8 100644
--- a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs
@@ -27,12 +27,10 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using Axiom.Math;
31using libsecondlife; 30using libsecondlife;
32using OpenSim.Framework; 31using OpenSim.Framework;
33using OpenSim.Region.Environment.Interfaces; 32using OpenSim.Region.Environment.Interfaces;
34using OpenSim.Region.Environment.Scenes; 33using OpenSim.Region.Environment.Scenes;
35using OpenSim.Region.Physics.Manager;
36 34
37namespace OpenSim.Region.Environment.Modules.World.Land 35namespace OpenSim.Region.Environment.Modules.World.Land
38{ 36{
@@ -66,68 +64,17 @@ namespace OpenSim.Region.Environment.Modules.World.Land
66 64
67 #endregion 65 #endregion
68 66
69 private readonly int[,] landIDList = new int[64,64];
70 private readonly Dictionary<int, ILandObject> landList = new Dictionary<int, ILandObject>();
71
72 private bool landPrimCountTainted;
73 private int lastLandLocalID = START_LAND_LOCAL_ID - 1;
74
75 private bool m_allowedForcefulBans = true;
76 private readonly Scene m_scene; 67 private readonly Scene m_scene;
68 private readonly LandManagementModule m_landManagementModule;
77 69
78 public LandChannel(Scene scene) 70 public LandChannel(Scene scene, LandManagementModule landManagementMod)
79 { 71 {
80 m_scene = scene; 72 m_scene = scene;
81 landIDList.Initialize(); 73 m_landManagementModule = landManagementMod;
82 } 74 }
83 75
84 #region Land Object From Storage Functions 76 #region ILandChannel Members
85
86 public void IncomingLandObjectsFromStorage(List<LandData> data)
87 {
88 for (int i = 0; i < data.Count; i++)
89 {
90 //try
91 //{
92 IncomingLandObjectFromStorage(data[i]);
93 //}
94 //catch (Exception ex)
95 //{
96 //m_log.Error("[LandManager]: IncomingLandObjectsFromStorage: Exception: " + ex.ToString());
97 //throw ex;
98 //}
99 }
100 //foreach (LandData parcel in data)
101 //{
102 // IncomingLandObjectFromStorage(parcel);
103 //}
104 }
105
106 public void IncomingLandObjectFromStorage(LandData data)
107 {
108 ILandObject new_land = new LandObject(data.ownerID, data.isGroupOwned, m_scene);
109 new_land.landData = data.Copy();
110 new_land.setLandBitmapFromByteArray();
111 AddLandObject(new_land);
112 }
113
114 public void NoLandDataFromStorage()
115 {
116 ResetSimLandObjects();
117 }
118
119 #endregion
120
121 #region Parcel Add/Remove/Get/Create
122 77
123 public void UpdateLandObject(int local_id, LandData newData)
124 {
125 if (landList.ContainsKey(local_id))
126 {
127 landList[local_id].landData = newData.Copy();
128 m_scene.EventManager.TriggerLandObjectUpdated((uint) local_id, landList[local_id]);
129 }
130 }
131 78
132 /// <summary> 79 /// <summary>
133 /// Get the land object at the specified point 80 /// Get the land object at the specified point
@@ -137,834 +84,65 @@ namespace OpenSim.Region.Environment.Modules.World.Land
137 /// <returns>Land object at the point supplied</returns> 84 /// <returns>Land object at the point supplied</returns>
138 public ILandObject GetLandObject(float x_float, float y_float) 85 public ILandObject GetLandObject(float x_float, float y_float)
139 { 86 {
140 int x; 87 if (m_landManagementModule != null)
141 int y;
142
143 try
144 { 88 {
145 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / Convert.ToDouble(4.0))); 89 return m_landManagementModule.GetLandObject(x_float, y_float);
146 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / Convert.ToDouble(4.0)));
147 } 90 }
148 catch (OverflowException) 91 ILandObject obj = new LandObject(LLUUID.Zero, false, m_scene);
149 { 92 obj.landData.landName = "NO LAND";
150 return null; 93 return obj;
151 }
152
153 if (x >= 64 || y >= 64 || x < 0 || y < 0)
154 {
155 return null;
156 }
157 return landList[landIDList[x, y]];
158 } 94 }
159 95
160 public ILandObject GetLandObject(int x, int y) 96 public ILandObject GetLandObject(int x, int y)
161 { 97 {
162 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
163 {
164 // These exceptions here will cause a lot of complaints from the users specifically because
165 // they happen every time at border crossings
166 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
167 }
168 return landList[landIDList[x / 4, y / 4]];
169 }
170
171 /// <summary>
172 /// Creates a basic Parcel object without an owner (a zeroed key)
173 /// </summary>
174 /// <returns></returns>
175 public ILandObject CreateBaseLand()
176 {
177 return new LandObject(LLUUID.Zero, false, m_scene);
178 }
179
180 /// <summary>
181 /// Adds a land object to the stored list and adds them to the landIDList to what they own
182 /// </summary>
183 /// <param name="new_land">The land object being added</param>
184 public ILandObject AddLandObject(ILandObject new_land)
185 {
186 lastLandLocalID++;
187 new_land.landData.localID = lastLandLocalID;
188 landList.Add(lastLandLocalID, new_land.Copy());
189
190
191 bool[,] landBitmap = new_land.getLandBitmap();
192 int x;
193 for (x = 0; x < 64; x++)
194 {
195 int y;
196 for (y = 0; y < 64; y++)
197 {
198 if (landBitmap[x, y])
199 {
200 landIDList[x, y] = lastLandLocalID;
201 }
202 }
203 }
204 landList[lastLandLocalID].forceUpdateLandInfo();
205 m_scene.EventManager.TriggerLandObjectAdded(new_land);
206 return new_land;
207 }
208
209 /// <summary>
210 /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
211 /// </summary>
212 /// <param name="local_id">Land.localID of the peice of land to remove.</param>
213 public void removeLandObject(int local_id)
214 {
215 int x;
216 for (x = 0; x < 64; x++)
217 {
218 int y;
219 for (y = 0; y < 64; y++)
220 {
221 if (landIDList[x, y] == local_id)
222 {
223 return;
224 //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
225 }
226 }
227 }
228
229 m_scene.EventManager.TriggerLandObjectRemoved(landList[local_id].landData.globalID);
230 landList.Remove(local_id);
231 }
232 98
233 private void performFinalLandJoin(ILandObject master, ILandObject slave) 99 if (m_landManagementModule != null)
234 {
235 int x;
236 bool[,] landBitmapSlave = slave.getLandBitmap();
237 for (x = 0; x < 64; x++)
238 { 100 {
239 int y; 101 return m_landManagementModule.GetLandObject(x, y);
240 for (y = 0; y < 64; y++)
241 {
242 if (landBitmapSlave[x, y])
243 {
244 landIDList[x, y] = master.landData.localID;
245 }
246 }
247 } 102 }
248 103 ILandObject obj = new LandObject(LLUUID.Zero, false, m_scene);
249 removeLandObject(slave.landData.localID); 104 obj.landData.landName = "NO LAND";
250 UpdateLandObject(master.landData.localID, master.landData); 105 return obj;
251 }
252
253 public ILandObject GetLandObject(int parcelLocalID)
254 {
255 lock (landList)
256 {
257 if (landList.ContainsKey(parcelLocalID))
258 {
259 return landList[parcelLocalID];
260 }
261 }
262 return null;
263 }
264
265 #endregion
266
267 #region Parcel Modification
268
269 public void ResetAllLandPrimCounts()
270 {
271 foreach (LandObject p in landList.Values)
272 {
273 p.resetLandPrimCounts();
274 }
275 }
276
277 public void SetPrimsTainted()
278 {
279 landPrimCountTainted = true;
280 }
281
282 public bool IsLandPrimCountTainted()
283 {
284 return landPrimCountTainted;
285 }
286
287 public void AddPrimToLandPrimCounts(SceneObjectGroup obj)
288 {
289 LLVector3 position = obj.AbsolutePosition;
290 ILandObject landUnderPrim = GetLandObject(position.X, position.Y);
291 if (landUnderPrim != null)
292 {
293 landUnderPrim.addPrimToCount(obj);
294 }
295 }
296
297 public void RemovePrimFromLandPrimCounts(SceneObjectGroup obj)
298 {
299 foreach (LandObject p in landList.Values)
300 {
301 p.removePrimFromCount(obj);
302 }
303 }
304
305 public void FinalizeLandPrimCountUpdate()
306 {
307 //Get Simwide prim count for owner
308 Dictionary<LLUUID, List<LandObject>> landOwnersAndParcels = new Dictionary<LLUUID, List<LandObject>>();
309 foreach (LandObject p in landList.Values)
310 {
311 if (!landOwnersAndParcels.ContainsKey(p.landData.ownerID))
312 {
313 List<LandObject> tempList = new List<LandObject>();
314 tempList.Add(p);
315 landOwnersAndParcels.Add(p.landData.ownerID, tempList);
316 }
317 else
318 {
319 landOwnersAndParcels[p.landData.ownerID].Add(p);
320 }
321 }
322
323 foreach (LLUUID owner in landOwnersAndParcels.Keys)
324 {
325 int simArea = 0;
326 int simPrims = 0;
327 foreach (LandObject p in landOwnersAndParcels[owner])
328 {
329 simArea += p.landData.area;
330 simPrims += p.landData.ownerPrims + p.landData.otherPrims + p.landData.groupPrims +
331 p.landData.selectedPrims;
332 }
333
334 foreach (LandObject p in landOwnersAndParcels[owner])
335 {
336 p.landData.simwideArea = simArea;
337 p.landData.simwidePrims = simPrims;
338 }
339 }
340 }
341
342 public void UpdateLandPrimCounts()
343 {
344 foreach (EntityBase obj in m_scene.Entities.Values)
345 {
346 if (obj is SceneObjectGroup)
347 {
348 m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup) obj);
349 }
350 }
351 }
352
353 public void PerformParcelPrimCountUpdate()
354 {
355 ResetAllLandPrimCounts();
356 m_scene.EventManager.TriggerParcelPrimCountUpdate();
357 FinalizeLandPrimCountUpdate();
358 landPrimCountTainted = false;
359 }
360
361 /// <summary>
362 /// Subdivides a piece of land
363 /// </summary>
364 /// <param name="start_x">West Point</param>
365 /// <param name="start_y">South Point</param>
366 /// <param name="end_x">East Point</param>
367 /// <param name="end_y">North Point</param>
368 /// <param name="attempting_user_id">LLUUID of user who is trying to subdivide</param>
369 /// <returns>Returns true if successful</returns>
370 private void subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
371 {
372 //First, lets loop through the points and make sure they are all in the same peice of land
373 //Get the land object at start
374
375 ILandObject startLandObject = GetLandObject(start_x, start_y);
376
377 if (startLandObject == null) return;
378
379 //Loop through the points
380 try
381 {
382 int totalX = end_x - start_x;
383 int totalY = end_y - start_y;
384 int y;
385 for (y = 0; y < totalY; y++)
386 {
387 int x;
388 for (x = 0; x < totalX; x++)
389 {
390 ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y);
391 if (tempLandObject == null) return;
392 if (tempLandObject != startLandObject) return;
393 }
394 }
395 }
396 catch (Exception)
397 {
398 return;
399 }
400
401 //If we are still here, then they are subdividing within one piece of land
402 //Check owner
403 if (!m_scene.ExternalChecks.ExternalChecksCanEditParcel(attempting_user_id,startLandObject))
404 {
405 return;
406 }
407
408 //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
409 ILandObject newLand = startLandObject.Copy();
410 newLand.landData.landName = "Subdivision of " + newLand.landData.landName;
411 newLand.landData.globalID = LLUUID.Random();
412
413 newLand.setLandBitmap(newLand.getSquareLandBitmap(start_x, start_y, end_x, end_y));
414
415 //Now, lets set the subdivision area of the original to false
416 int startLandObjectIndex = startLandObject.landData.localID;
417 landList[startLandObjectIndex].setLandBitmap(
418 newLand.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false));
419 landList[startLandObjectIndex].forceUpdateLandInfo();
420
421 SetPrimsTainted();
422
423 //Now add the new land object
424 ILandObject result = AddLandObject(newLand);
425 UpdateLandObject(startLandObject.landData.localID, startLandObject.landData);
426 result.sendLandUpdateToAvatarsOverMe();
427
428
429 return;
430 }
431
432 /// <summary>
433 /// Join 2 land objects together
434 /// </summary>
435 /// <param name="start_x">x value in first piece of land</param>
436 /// <param name="start_y">y value in first piece of land</param>
437 /// <param name="end_x">x value in second peice of land</param>
438 /// <param name="end_y">y value in second peice of land</param>
439 /// <param name="attempting_user_id">LLUUID of the avatar trying to join the land objects</param>
440 /// <returns>Returns true if successful</returns>
441 private void join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
442 {
443 end_x -= 4;
444 end_y -= 4;
445
446 List<ILandObject> selectedLandObjects = new List<ILandObject>();
447 int stepYSelected;
448 for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
449 {
450 int stepXSelected;
451 for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
452 {
453 ILandObject p = GetLandObject(stepXSelected, stepYSelected);
454
455 if (p != null)
456 {
457 if (!selectedLandObjects.Contains(p))
458 {
459 selectedLandObjects.Add(p);
460 }
461 }
462 }
463 }
464 ILandObject masterLandObject = selectedLandObjects[0];
465 selectedLandObjects.RemoveAt(0);
466
467
468 if (selectedLandObjects.Count < 1)
469 {
470 return;
471 }
472 if (!m_scene.ExternalChecks.ExternalChecksCanEditParcel(attempting_user_id, masterLandObject))
473 {
474 return;
475 }
476 foreach (ILandObject p in selectedLandObjects)
477 {
478 if (p.landData.ownerID != masterLandObject.landData.ownerID)
479 {
480 return;
481 }
482 }
483 foreach (ILandObject slaveLandObject in selectedLandObjects)
484 {
485 landList[masterLandObject.landData.localID].setLandBitmap(
486 slaveLandObject.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap()));
487 performFinalLandJoin(masterLandObject, slaveLandObject);
488 }
489
490
491 SetPrimsTainted();
492
493 masterLandObject.sendLandUpdateToAvatarsOverMe();
494
495 return;
496 }
497
498 #endregion
499
500 #region Parcel Updating
501
502 /// <summary>
503 /// Where we send the ParcelOverlay packet to the client
504 /// </summary>
505 /// <param name="remote_client">The object representing the client</param>
506 public void SendParcelOverlay(IClientAPI remote_client)
507 {
508 const int LAND_BLOCKS_PER_PACKET = 1024;
509
510 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
511 int byteArrayCount = 0;
512 int sequenceID = 0;
513
514 int y;
515 for (y = 0; y < 64; y++)
516 {
517 int x;
518 for (x = 0; x < 64; x++)
519 {
520 byte tempByte = 0; //This represents the byte for the current 4x4
521
522 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4);
523
524
525 if (currentParcelBlock != null)
526 {
527 if (currentParcelBlock.landData.ownerID == remote_client.AgentId)
528 {
529 //Owner Flag
530 tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_REQUESTER);
531 }
532 else if (currentParcelBlock.landData.salePrice > 0 &&
533 (currentParcelBlock.landData.authBuyerID == LLUUID.Zero ||
534 currentParcelBlock.landData.authBuyerID == remote_client.AgentId))
535 {
536 //Sale Flag
537 tempByte = Convert.ToByte(tempByte | LAND_TYPE_IS_FOR_SALE);
538 }
539 else if (currentParcelBlock.landData.ownerID == LLUUID.Zero)
540 {
541 //Public Flag
542 tempByte = Convert.ToByte(tempByte | LAND_TYPE_PUBLIC);
543 }
544 else
545 {
546 //Other Flag
547 tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_OTHER);
548 }
549
550
551 //Now for border control
552
553 ILandObject westParcel = null;
554 ILandObject southParcel = null;
555 if (x > 0)
556 {
557 westParcel = GetLandObject((x - 1) * 4, y * 4);
558 }
559 if (y > 0)
560 {
561 southParcel = GetLandObject(x * 4, (y - 1) * 4);
562 }
563
564 if (x == 0)
565 {
566 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST);
567 }
568 else if (westParcel != null && westParcel != currentParcelBlock)
569 {
570 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST);
571 }
572
573 if (y == 0)
574 {
575 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH);
576 }
577 else if (southParcel != null && southParcel != currentParcelBlock)
578 {
579 tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH);
580 }
581
582 byteArray[byteArrayCount] = tempByte;
583 byteArrayCount++;
584 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
585 {
586 remote_client.sendLandParcelOverlay(byteArray, sequenceID);
587 byteArrayCount = 0;
588 sequenceID++;
589 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
590 }
591 }
592 }
593 }
594 }
595
596 public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
597 bool snap_selection, IClientAPI remote_client)
598 {
599 //Get the land objects within the bounds
600 List<ILandObject> temp = new List<ILandObject>();
601 int x;
602 int i;
603 int inc_x = end_x - start_x;
604 int inc_y = end_y - start_y;
605 for (x = 0; x < inc_x; x++)
606 {
607 int y;
608 for (y = 0; y < inc_y; y++)
609 {
610 ILandObject currentParcel = GetLandObject(start_x + x, start_y + y);
611
612 if (currentParcel != null)
613 {
614 if (!temp.Contains(currentParcel))
615 {
616 currentParcel.forceUpdateLandInfo();
617 temp.Add(currentParcel);
618 }
619 }
620 }
621 }
622
623 int requestResult = LAND_RESULT_SINGLE;
624 if (temp.Count > 1)
625 {
626 requestResult = LAND_RESULT_MULTIPLE;
627 }
628
629 for (i = 0; i < temp.Count; i++)
630 {
631 temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
632 }
633
634
635 SendParcelOverlay(remote_client);
636 }
637
638 public void handleParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
639 {
640 if (landList.ContainsKey(localID))
641 {
642 landList[localID].updateLandProperties(args, remote_client);
643 }
644 }
645
646 public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
647 {
648 subdivide(west, south, east, north, remote_client.AgentId);
649 }
650
651 public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
652 {
653 join(west, south, east, north, remote_client.AgentId);
654 }
655
656 public void handleParcelSelectObjectsRequest(int local_id, int request_type, IClientAPI remote_client)
657 {
658
659 landList[local_id].sendForceObjectSelect(local_id, request_type, remote_client);
660 }
661
662 public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client)
663 {
664 landList[local_id].sendLandObjectOwners(remote_client);
665 }
666
667 public void handleParcelAbandonRequest(int local_id, IClientAPI remote_client)
668 {
669 if (landList.ContainsKey(local_id))
670 {
671 if (m_scene.ExternalChecks.ExternalChecksCanAbandonParcel(remote_client.AgentId, landList[local_id]))
672 {
673 landList[local_id].landData.ownerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
674 m_scene.Broadcast(SendParcelOverlay);
675 }
676 }
677
678 }
679 #endregion
680
681 #region ILandChannel Members
682
683 public bool AllowedForcefulBans
684 {
685 get { return m_allowedForcefulBans; }
686 set { m_allowedForcefulBans = value; }
687 }
688
689 /// <summary>
690 /// Resets the sim to the default land object (full sim piece of land owned by the default user)
691 /// </summary>
692 public void ResetSimLandObjects()
693 {
694 //Remove all the land objects in the sim and add a blank, full sim land object set to public
695 landList.Clear();
696 lastLandLocalID = START_LAND_LOCAL_ID - 1;
697 landIDList.Initialize();
698
699 ILandObject fullSimParcel = new LandObject(LLUUID.Zero, false, m_scene);
700
701 fullSimParcel.setLandBitmap(fullSimParcel.getSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize));
702 fullSimParcel.landData.ownerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
703
704 AddLandObject(fullSimParcel);
705 } 106 }
706 107
707 public List<ILandObject> ParcelsNearPoint(LLVector3 position) 108 public List<ILandObject> ParcelsNearPoint(LLVector3 position)
708 { 109 {
709 List<ILandObject> parcelsNear = new List<ILandObject>(); 110 if (m_landManagementModule != null)
710 int x;
711 for (x = -4; x <= 4; x += 4)
712 { 111 {
713 int y; 112 return m_landManagementModule.ParcelsNearPoint(position);
714 for (y = -4; y <= 4; y += 4)
715 {
716 ILandObject check = GetLandObject(position.X + x, position.Y + y);
717 if (check != null)
718 {
719 if (!parcelsNear.Contains(check))
720 {
721 parcelsNear.Add(check);
722 }
723 }
724 }
725 } 113 }
726 114
727 return parcelsNear; 115 return new List<ILandObject>();
728 } 116 }
729 117
730 public void SendYouAreBannedNotice(ScenePresence avatar) 118 public bool IsLandPrimCountTainted()
731 {
732 if (AllowedForcefulBans)
733 {
734 avatar.ControllingClient.SendAlertMessage(
735 "You are not allowed on this parcel because you are banned. Please go away. <3 OpenSim Developers");
736
737 avatar.PhysicsActor.Position =
738 new PhysicsVector(avatar.lastKnownAllowedPosition.x, avatar.lastKnownAllowedPosition.y,
739 avatar.lastKnownAllowedPosition.z);
740 avatar.PhysicsActor.Velocity = new PhysicsVector(0, 0, 0);
741 }
742 else
743 {
744 avatar.ControllingClient.SendAlertMessage(
745 "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim! <3 OpenSim Developers");
746 }
747 }
748
749 public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
750 {
751 if (m_scene.RegionInfo.RegionID == regionID)
752 {
753 if (landList[localLandID] != null)
754 {
755 ILandObject parcelAvatarIsEntering = landList[localLandID];
756 if (avatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT)
757 {
758 if (parcelAvatarIsEntering.isBannedFromLand(avatar.UUID))
759 {
760 SendYouAreBannedNotice(avatar);
761 }
762 else if (parcelAvatarIsEntering.isRestrictedFromLand(avatar.UUID))
763 {
764 avatar.ControllingClient.SendAlertMessage(
765 "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!). <3 OpenSim Developers");
766 }
767 else
768 {
769 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
770 }
771 }
772 else
773 {
774 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
775 }
776 }
777 }
778 }
779
780 public void SendOutNearestBanLine(IClientAPI avatar)
781 {
782 List<ScenePresence> avatars = m_scene.GetAvatars();
783 foreach (ScenePresence presence in avatars)
784 {
785 if (presence.UUID == avatar.AgentId)
786 {
787 List<ILandObject> checkLandParcels = ParcelsNearPoint(presence.AbsolutePosition);
788 foreach (ILandObject checkBan in checkLandParcels)
789 {
790 if (checkBan.isBannedFromLand(avatar.AgentId))
791 {
792 checkBan.sendLandProperties(-30000, false, (int) ParcelManager.ParcelResult.Single, avatar);
793 return; //Only send one
794 }
795 if (checkBan.isRestrictedFromLand(avatar.AgentId))
796 {
797 checkBan.sendLandProperties(-40000, false, (int) ParcelManager.ParcelResult.Single, avatar);
798 return; //Only send one
799 }
800 }
801 return;
802 }
803 }
804 }
805
806 public void SendLandUpdate(ScenePresence avatar, bool force)
807 { 119 {
808 ILandObject over = GetLandObject((int) Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 120 if (m_landManagementModule != null)
809 (int) Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
810
811
812 if (over != null)
813 { 121 {
814 if (force) 122 return m_landManagementModule.IsLandPrimCountTainted();
815 {
816 if (!avatar.IsChildAgent)
817 {
818 over.sendLandUpdateToClient(avatar.ControllingClient);
819 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.localID,
820 m_scene.RegionInfo.RegionID);
821 }
822 }
823
824 if (avatar.currentParcelUUID != over.landData.globalID)
825 {
826 if (!avatar.IsChildAgent)
827 {
828 over.sendLandUpdateToClient(avatar.ControllingClient);
829 avatar.currentParcelUUID = over.landData.globalID;
830 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.localID,
831 m_scene.RegionInfo.RegionID);
832 }
833 }
834 } 123 }
835 }
836 124
837 public void SendLandUpdate(ScenePresence avatar) 125 return false;
838 {
839 SendLandUpdate(avatar, false);
840 } 126 }
841 127
842 public void handleSignificantClientMovement(IClientAPI remote_client) 128 public bool IsForcefulBansAllowed()
843 { 129 {
844 ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId); 130 if (m_landManagementModule != null)
845
846 if (clientAvatar != null)
847 { 131 {
848 SendLandUpdate(clientAvatar); 132 return m_landManagementModule.AllowedForcefulBans;
849 SendOutNearestBanLine(remote_client);
850 ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y);
851 if (parcel != null)
852 {
853 if (clientAvatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT &&
854 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown)
855 {
856 handleAvatarChangingParcel(clientAvatar, parcel.landData.localID, m_scene.RegionInfo.RegionID);
857 //They are going below the safety line!
858 if (!parcel.isBannedFromLand(clientAvatar.UUID))
859 {
860 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false;
861 }
862 }
863 else if (clientAvatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT &&
864 parcel.isBannedFromLand(clientAvatar.UUID))
865 {
866 SendYouAreBannedNotice(clientAvatar);
867 }
868 }
869 } 133 }
870 }
871 134
872 public void handleAnyClientMovement(ScenePresence avatar) 135 return false;
873 //Like handleSignificantClientMovement, but called with an AgentUpdate regardless of distance.
874 {
875 ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
876 if (over != null)
877 {
878 if (!over.isBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= BAN_LINE_SAFETY_HIEGHT)
879 {
880 avatar.lastKnownAllowedPosition =
881 new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
882 }
883 }
884 } 136 }
885 137
886 138 public void UpdateLandObject(int localID, LandData data)
887 public void handleParcelAccessRequest(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID,
888 int landLocalID, IClientAPI remote_client)
889 { 139 {
890 if (landList.ContainsKey(landLocalID)) 140 if (m_landManagementModule != null)
891 { 141 {
892 landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client); 142 m_landManagementModule.UpdateLandObject(localID, data);
893 } 143 }
894 } 144 }
895
896 public void handleParcelAccessUpdateRequest(LLUUID agentID, LLUUID sessionID, uint flags, int landLocalID,
897 List<ParcelManager.ParcelAccessEntry> entries,
898 IClientAPI remote_client)
899 {
900 if (landList.ContainsKey(landLocalID))
901 {
902 if (agentID == landList[landLocalID].landData.ownerID)
903 {
904 landList[landLocalID].updateAccessList(flags, entries, remote_client);
905 }
906 }
907 else
908 {
909 Console.WriteLine("INVALID LOCAL LAND ID");
910 }
911 }
912
913 #endregion 145 #endregion
914 146
915 // If the economy has been validated by the economy module,
916 // and land has been validated as well, this method transfers
917 // the land ownership
918
919 public void handleLandBuyRequest(Object o, EventManager.LandBuyArgs e)
920 {
921 if (e.economyValidated && e.landValidated)
922 {
923 lock (landList)
924 {
925 if (landList.ContainsKey(e.parcelLocalID))
926 {
927 landList[e.parcelLocalID].updateLandSold(e.agentId, e.groupId, e.groupOwned, (uint) e.transactionID, e.parcelPrice, e.parcelArea);
928 return;
929 }
930 }
931 }
932 }
933
934 // After receiving a land buy packet, first the data needs to
935 // be validated. This method validates the right to buy the
936 // parcel
937
938 public void handleLandValidationRequest(Object o, EventManager.LandBuyArgs e)
939 {
940 if (e.landValidated == false)
941 {
942 ILandObject lob = null;
943 lock (landList)
944 {
945 if (landList.ContainsKey(e.parcelLocalID))
946 {
947 lob = landList[e.parcelLocalID];
948 }
949 }
950 if (lob != null)
951 {
952 LLUUID AuthorizedID = lob.landData.authBuyerID;
953 int saleprice = lob.landData.salePrice;
954 LLUUID pOwnerID = lob.landData.ownerID;
955
956 bool landforsale = ((lob.landData.landFlags &
957 (uint) (Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects)) != 0);
958 if ((AuthorizedID == LLUUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale)
959 {
960 lock (e)
961 {
962 e.parcelOwnerID = pOwnerID;
963 e.landValidated = true;
964 }
965 }
966 }
967 }
968 }
969 } 147 }
970} \ No newline at end of file 148} \ No newline at end of file