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