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