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