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