clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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 OpenSimulator 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  
28 using System;
29 using System.Collections.Generic;
30 using System.Reflection;
31 using log4net;
32 using OpenMetaverse;
33 using OpenSim.Framework;
34 using OpenSim.Region.Framework.Interfaces;
35 using OpenSim.Region.Framework.Scenes;
36 using RegionFlags = OpenMetaverse.RegionFlags;
37  
38 namespace OpenSim.Region.CoreModules.World.Land
39 {
40 /// <summary>
41 /// Keeps track of a specific piece of land's information
42 /// </summary>
43 public class LandObject : ILandObject
44 {
45 #region Member Variables
46  
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 #pragma warning disable 0429
49 private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
50 #pragma warning restore 0429
51 private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
52  
53 private int m_lastSeqId = 0;
54  
55 protected LandData m_landData = new LandData();
56 protected Scene m_scene;
57 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
58 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
59  
60 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
61 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
62  
63 public bool[,] LandBitmap
64 {
65 get { return m_landBitmap; }
66 set { m_landBitmap = value; }
67 }
68  
69 #endregion
70  
71 public int GetPrimsFree()
72 {
73 m_scene.EventManager.TriggerParcelPrimCountUpdate();
74 int free = GetSimulatorMaxPrimCount() - m_landData.SimwidePrims;
75 return free;
76 }
77  
78 public LandData LandData
79 {
80 get { return m_landData; }
81  
82 set { m_landData = value; }
83 }
84  
85 public IPrimCounts PrimCounts { get; set; }
86  
87 public UUID RegionUUID
88 {
89 get { return m_scene.RegionInfo.RegionID; }
90 }
91  
92 public Vector3 StartPoint
93 {
94 get
95 {
96 for (int y = 0; y < landArrayMax; y++)
97 {
98 for (int x = 0; x < landArrayMax; x++)
99 {
100 if (LandBitmap[x, y])
101 return new Vector3(x * 4, y * 4, 0);
102 }
103 }
104  
105 return new Vector3(-1, -1, -1);
106 }
107 }
108  
109 public Vector3 EndPoint
110 {
111 get
112 {
113 for (int y = landArrayMax - 1; y >= 0; y--)
114 {
115 for (int x = landArrayMax - 1; x >= 0; x--)
116 {
117 if (LandBitmap[x, y])
118 {
119 return new Vector3(x * 4 + 4, y * 4 + 4, 0);
120 }
121 }
122 }
123  
124 return new Vector3(-1, -1, -1);
125 }
126 }
127  
128 #region Constructors
129  
130 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
131 {
132 m_scene = scene;
133 LandData.OwnerID = owner_id;
134 if (is_group_owned)
135 LandData.GroupID = owner_id;
136 else
137 LandData.GroupID = UUID.Zero;
138 LandData.IsGroupOwned = is_group_owned;
139 }
140  
141 #endregion
142  
143 #region Member Functions
144  
145 #region General Functions
146  
147 /// <summary>
148 /// Checks to see if this land object contains a point
149 /// </summary>
150 /// <param name="x"></param>
151 /// <param name="y"></param>
152 /// <returns>Returns true if the piece of land contains the specified point</returns>
153 public bool ContainsPoint(int x, int y)
154 {
155 if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize)
156 {
157 return (LandBitmap[x / 4, y / 4] == true);
158 }
159 else
160 {
161 return false;
162 }
163 }
164  
165 public ILandObject Copy()
166 {
167 ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene);
168  
169 //Place all new variables here!
170 newLand.LandBitmap = (bool[,]) (LandBitmap.Clone());
171 newLand.LandData = LandData.Copy();
172  
173 return newLand;
174 }
175  
176 static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
177 static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
178  
179 public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
180 {
181 overrideParcelMaxPrimCount = overrideDel;
182 }
183 public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
184 {
185 overrideSimulatorMaxPrimCount = overrideDel;
186 }
187  
188 public int GetParcelMaxPrimCount()
189 {
190 if (overrideParcelMaxPrimCount != null)
191 {
192 return overrideParcelMaxPrimCount(this);
193 }
194 else
195 {
196 // Normal Calculations
197 int parcelMax = (int)(((float)LandData.Area / 65536.0f)
198 * (float)m_scene.RegionInfo.ObjectCapacity
199 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
200 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL!
201 return parcelMax;
202 }
203 }
204  
205 public int GetSimulatorMaxPrimCount()
206 {
207 if (overrideSimulatorMaxPrimCount != null)
208 {
209 return overrideSimulatorMaxPrimCount(this);
210 }
211 else
212 {
213 //Normal Calculations
214 int simMax = (int)(((float)LandData.SimwideArea / 65536.0f)
215 * (float)m_scene.RegionInfo.ObjectCapacity);
216 return simMax;
217 }
218 }
219  
220 #endregion
221  
222 #region Packet Request Handling
223  
224 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
225 {
226 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
227 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
228 if (estateModule != null)
229 regionFlags = estateModule.GetRegionFlags();
230  
231 int seq_id;
232 if (snap_selection && (sequence_id == 0))
233 {
234 seq_id = m_lastSeqId;
235 }
236 else
237 {
238 seq_id = sequence_id;
239 m_lastSeqId = seq_id;
240 }
241  
242 remote_client.SendLandProperties(seq_id,
243 snap_selection, request_result, this,
244 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
245 GetParcelMaxPrimCount(),
246 GetSimulatorMaxPrimCount(), regionFlags);
247 }
248  
249 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
250 {
251 //Needs later group support
252 bool snap_selection = false;
253 LandData newData = LandData.Copy();
254  
255 uint allowedDelta = 0;
256  
257 // These two are always blocked as no client can set them anyway
258 // ParcelFlags.ForSaleObjects
259 // ParcelFlags.LindenHome
260  
261 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
262 {
263 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
264 ParcelFlags.AllowTerraform |
265 ParcelFlags.AllowDamage |
266 ParcelFlags.CreateObjects |
267 ParcelFlags.RestrictPushObject |
268 ParcelFlags.AllowOtherScripts |
269 ParcelFlags.AllowGroupScripts |
270 ParcelFlags.CreateGroupObjects |
271 ParcelFlags.AllowAPrimitiveEntry |
272 ParcelFlags.AllowGroupObjectEntry |
273 ParcelFlags.AllowFly);
274 }
275  
276 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale))
277 {
278 if (args.AuthBuyerID != newData.AuthBuyerID ||
279 args.SalePrice != newData.SalePrice)
280 {
281 snap_selection = true;
282 }
283  
284 newData.AuthBuyerID = args.AuthBuyerID;
285 newData.SalePrice = args.SalePrice;
286  
287 if (!LandData.IsGroupOwned)
288 {
289 newData.GroupID = args.GroupID;
290  
291 allowedDelta |= (uint)(ParcelFlags.AllowDeedToGroup |
292 ParcelFlags.ContributeWithDeed |
293 ParcelFlags.SellParcelObjects);
294 }
295  
296 allowedDelta |= (uint)ParcelFlags.ForSale;
297 }
298  
299 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces))
300 {
301 newData.Category = args.Category;
302  
303 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
304 ParcelFlags.AllowPublish |
305 ParcelFlags.MaturePublish);
306 }
307  
308 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity))
309 {
310 newData.Description = args.Desc;
311 newData.Name = args.Name;
312 newData.SnapshotID = args.SnapshotID;
313 }
314  
315 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint))
316 {
317 newData.LandingType = args.LandingType;
318 newData.UserLocation = args.UserLocation;
319 newData.UserLookAt = args.UserLookAt;
320 }
321  
322 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia))
323 {
324 newData.MediaAutoScale = args.MediaAutoScale;
325 newData.MediaID = args.MediaID;
326 newData.MediaURL = args.MediaURL;
327 newData.MusicURL = args.MusicURL;
328 newData.MediaType = args.MediaType;
329 newData.MediaDescription = args.MediaDescription;
330 newData.MediaWidth = args.MediaWidth;
331 newData.MediaHeight = args.MediaHeight;
332 newData.MediaLoop = args.MediaLoop;
333 newData.ObscureMusic = args.ObscureMusic;
334 newData.ObscureMedia = args.ObscureMedia;
335  
336 allowedDelta |= (uint)(ParcelFlags.SoundLocal |
337 ParcelFlags.UrlWebPage |
338 ParcelFlags.UrlRawHtml |
339 ParcelFlags.AllowVoiceChat |
340 ParcelFlags.UseEstateVoiceChan);
341 }
342  
343 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses))
344 {
345 newData.PassHours = args.PassHours;
346 newData.PassPrice = args.PassPrice;
347  
348 allowedDelta |= (uint)ParcelFlags.UsePassList;
349 }
350  
351 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed))
352 {
353 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
354 ParcelFlags.UseAccessList);
355 }
356  
357 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned))
358 {
359 allowedDelta |= (uint)(ParcelFlags.UseBanList |
360 ParcelFlags.DenyAnonymous |
361 ParcelFlags.DenyAgeUnverified);
362 }
363  
364 uint preserve = LandData.Flags & ~allowedDelta;
365 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
366  
367 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
368  
369 SendLandUpdateToAvatarsOverMe(snap_selection);
370 }
371  
372 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
373 {
374 LandData newData = LandData.Copy();
375 newData.OwnerID = avatarID;
376 newData.GroupID = groupID;
377 newData.IsGroupOwned = groupOwned;
378 //newData.auctionID = AuctionID;
379 newData.ClaimDate = Util.UnixTimeSinceEpoch();
380 newData.ClaimPrice = claimprice;
381 newData.SalePrice = 0;
382 newData.AuthBuyerID = UUID.Zero;
383 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
384 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
385 m_scene.EventManager.TriggerParcelPrimCountUpdate();
386 SendLandUpdateToAvatarsOverMe(true);
387 }
388  
389 public void DeedToGroup(UUID groupID)
390 {
391 LandData newData = LandData.Copy();
392 newData.OwnerID = groupID;
393 newData.GroupID = groupID;
394 newData.IsGroupOwned = true;
395  
396 // Reset show in directory flag on deed
397 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
398  
399 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
400 m_scene.EventManager.TriggerParcelPrimCountUpdate();
401 SendLandUpdateToAvatarsOverMe(true);
402 }
403  
404 public bool IsEitherBannedOrRestricted(UUID avatar)
405 {
406 if (IsBannedFromLand(avatar))
407 {
408 return true;
409 }
410 else if (IsRestrictedFromLand(avatar))
411 {
412 return true;
413 }
414 return false;
415 }
416  
417 public bool HasGroupAccess(UUID avatar)
418 {
419 if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
420 {
421 ScenePresence sp;
422 if (!m_scene.TryGetScenePresence(avatar, out sp))
423 {
424 bool isMember;
425 if (m_groupMemberCache.TryGetValue(avatar, out isMember))
426 {
427 m_groupMemberCache.Update(avatar, isMember, m_groupMemberCacheTimeout);
428 return isMember;
429 }
430  
431 IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
432 if (groupsModule == null)
433 return false;
434  
435 GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar);
436 if (membership == null || membership.Length == 0)
437 {
438 m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout);
439 return false;
440 }
441  
442 foreach (GroupMembershipData d in membership)
443 {
444 if (d.GroupID == LandData.GroupID)
445 {
446 m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout);
447 return true;
448 }
449 }
450 m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout);
451 return false;
452 }
453  
454 return sp.ControllingClient.IsGroupMember(LandData.GroupID);
455 }
456 return false;
457 }
458  
459 public bool IsBannedFromLand(UUID avatar)
460 {
461 ExpireAccessList();
462  
463 if (m_scene.Permissions.IsAdministrator(avatar))
464 return false;
465  
466 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
467 return false;
468  
469 if (avatar == LandData.OwnerID)
470 return false;
471  
472 if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
473 {
474 if (LandData.ParcelAccessList.FindIndex(
475 delegate(LandAccessEntry e)
476 {
477 if (e.AgentID == avatar && e.Flags == AccessList.Ban)
478 return true;
479 return false;
480 }) != -1)
481 {
482 return true;
483 }
484 }
485 return false;
486 }
487  
488 public bool IsRestrictedFromLand(UUID avatar)
489 {
490 if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0)
491 return false;
492  
493 if (m_scene.Permissions.IsAdministrator(avatar))
494 return false;
495  
496 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
497 return false;
498  
499 if (avatar == LandData.OwnerID)
500 return false;
501  
502 if (HasGroupAccess(avatar))
503 return false;
504  
505 return !IsInLandAccessList(avatar);
506 }
507  
508 public bool IsInLandAccessList(UUID avatar)
509 {
510 ExpireAccessList();
511  
512 if (LandData.ParcelAccessList.FindIndex(
513 delegate(LandAccessEntry e)
514 {
515 if (e.AgentID == avatar && e.Flags == AccessList.Access)
516 return true;
517 return false;
518 }) == -1)
519 {
520 return false;
521 }
522 return true;
523 }
524  
525 public void SendLandUpdateToClient(IClientAPI remote_client)
526 {
527 SendLandProperties(0, false, 0, remote_client);
528 }
529  
530 public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client)
531 {
532 m_scene.EventManager.TriggerParcelPrimCountUpdate();
533 SendLandProperties(0, snap_selection, 0, remote_client);
534 }
535  
536 public void SendLandUpdateToAvatarsOverMe()
537 {
538 SendLandUpdateToAvatarsOverMe(false);
539 }
540  
541 public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
542 {
543 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
544 {
545 ILandObject over = null;
546 try
547 {
548 over =
549 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)),
550 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1)));
551 }
552 catch (Exception)
553 {
554 m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " +
555 Math.Round(avatar.AbsolutePosition.Y));
556 }
557  
558 if (over != null)
559 {
560 if (over.LandData.LocalID == LandData.LocalID)
561 {
562 if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) &&
563 m_scene.RegionInfo.RegionSettings.AllowDamage)
564 avatar.Invulnerable = false;
565 else
566 avatar.Invulnerable = true;
567  
568 SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
569 }
570 }
571 });
572 }
573  
574 #endregion
575  
576 #region AccessList Functions
577  
578 public List<LandAccessEntry> CreateAccessListArrayByFlag(AccessList flag)
579 {
580 ExpireAccessList();
581  
582 List<LandAccessEntry> list = new List<LandAccessEntry>();
583 foreach (LandAccessEntry entry in LandData.ParcelAccessList)
584 {
585 if (entry.Flags == flag)
586 list.Add(entry);
587 }
588 if (list.Count == 0)
589 {
590 LandAccessEntry e = new LandAccessEntry();
591 e.AgentID = UUID.Zero;
592 e.Flags = 0;
593 e.Expires = 0;
594  
595 list.Add(e);
596 }
597  
598 return list;
599 }
600  
601 public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
602 IClientAPI remote_client)
603 {
604  
605 if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both)
606 {
607 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access);
608 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID);
609 }
610  
611 if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both)
612 {
613 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban);
614 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID);
615 }
616 }
617  
618 public void UpdateAccessList(uint flags, UUID transactionID,
619 int sequenceID, int sections,
620 List<LandAccessEntry> entries,
621 IClientAPI remote_client)
622 {
623 LandData newData = LandData.Copy();
624  
625 if ((!m_listTransactions.ContainsKey(flags)) ||
626 m_listTransactions[flags] != transactionID)
627 {
628 m_listTransactions[flags] = transactionID;
629  
630 List<LandAccessEntry> toRemove =
631 new List<LandAccessEntry>();
632  
633 foreach (LandAccessEntry entry in newData.ParcelAccessList)
634 {
635 if (entry.Flags == (AccessList)flags)
636 toRemove.Add(entry);
637 }
638  
639 foreach (LandAccessEntry entry in toRemove)
640 {
641 newData.ParcelAccessList.Remove(entry);
642 }
643  
644 // Checked here because this will always be the first
645 // and only packet in a transaction
646 if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
647 {
648 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
649  
650 return;
651 }
652 }
653  
654 foreach (LandAccessEntry entry in entries)
655 {
656 LandAccessEntry temp =
657 new LandAccessEntry();
658  
659 temp.AgentID = entry.AgentID;
660 temp.Expires = entry.Expires;
661 temp.Flags = (AccessList)flags;
662  
663 newData.ParcelAccessList.Add(temp);
664 }
665  
666 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
667 }
668  
669 #endregion
670  
671 #region Update Functions
672  
673 public void UpdateLandBitmapByteArray()
674 {
675 LandData.Bitmap = ConvertLandBitmapToBytes();
676 }
677  
678 /// <summary>
679 /// Update all settings in land such as area, bitmap byte array, etc
680 /// </summary>
681 public void ForceUpdateLandInfo()
682 {
683 UpdateAABBAndAreaValues();
684 UpdateLandBitmapByteArray();
685 }
686  
687 public void SetLandBitmapFromByteArray()
688 {
689 LandBitmap = ConvertBytesToLandBitmap();
690 }
691  
692 /// <summary>
693 /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
694 /// </summary>
695 private void UpdateAABBAndAreaValues()
696 {
697 int min_x = 64;
698 int min_y = 64;
699 int max_x = 0;
700 int max_y = 0;
701 int tempArea = 0;
702 int x, y;
703 for (x = 0; x < 64; x++)
704 {
705 for (y = 0; y < 64; y++)
706 {
707 if (LandBitmap[x, y] == true)
708 {
709 if (min_x > x) min_x = x;
710 if (min_y > y) min_y = y;
711 if (max_x < x) max_x = x;
712 if (max_y < y) max_y = y;
713 tempArea += 16; //16sqm peice of land
714 }
715 }
716 }
717 int tx = min_x * 4;
718 if (tx > ((int)Constants.RegionSize - 1))
719 tx = ((int)Constants.RegionSize - 1);
720 int ty = min_y * 4;
721 if (ty > ((int)Constants.RegionSize - 1))
722 ty = ((int)Constants.RegionSize - 1);
723  
724 LandData.AABBMin =
725 new Vector3(
726 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
727  
728 tx = max_x * 4;
729 if (tx > ((int)Constants.RegionSize - 1))
730 tx = ((int)Constants.RegionSize - 1);
731 ty = max_y * 4;
732 if (ty > ((int)Constants.RegionSize - 1))
733 ty = ((int)Constants.RegionSize - 1);
734  
735 LandData.AABBMax
736 = new Vector3(
737 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
738  
739 LandData.Area = tempArea;
740 }
741  
742 #endregion
743  
744 #region Land Bitmap Functions
745  
746 /// <summary>
747 /// Sets the land's bitmap manually
748 /// </summary>
749 /// <param name="bitmap">64x64 block representing where this land is on a map</param>
750 public void SetLandBitmap(bool[,] bitmap)
751 {
752 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
753 {
754 //Throw an exception - The bitmap is not 64x64
755 //throw new Exception("Error: Invalid Parcel Bitmap");
756 }
757 else
758 {
759 //Valid: Lets set it
760 LandBitmap = bitmap;
761 ForceUpdateLandInfo();
762 }
763 }
764  
765 /// <summary>
766 /// Gets the land's bitmap manually
767 /// </summary>
768 /// <returns></returns>
769 public bool[,] GetLandBitmap()
770 {
771 return LandBitmap;
772 }
773  
774 public bool[,] BasicFullRegionLandBitmap()
775 {
776 return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
777 }
778  
779 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
780 {
781 bool[,] tempBitmap = new bool[64,64];
782 tempBitmap.Initialize();
783  
784 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
785 return tempBitmap;
786 }
787  
788 /// <summary>
789 /// Change a land bitmap at within a square and set those points to a specific value
790 /// </summary>
791 /// <param name="land_bitmap"></param>
792 /// <param name="start_x"></param>
793 /// <param name="start_y"></param>
794 /// <param name="end_x"></param>
795 /// <param name="end_y"></param>
796 /// <param name="set_value"></param>
797 /// <returns></returns>
798 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
799 bool set_value)
800 {
801 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
802 {
803 //Throw an exception - The bitmap is not 64x64
804 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
805 }
806  
807 int x, y;
808 for (y = 0; y < 64; y++)
809 {
810 for (x = 0; x < 64; x++)
811 {
812 if (x >= start_x / 4 && x < end_x / 4
813 && y >= start_y / 4 && y < end_y / 4)
814 {
815 land_bitmap[x, y] = set_value;
816 }
817 }
818 }
819 return land_bitmap;
820 }
821  
822 /// <summary>
823 /// Join the true values of 2 bitmaps together
824 /// </summary>
825 /// <param name="bitmap_base"></param>
826 /// <param name="bitmap_add"></param>
827 /// <returns></returns>
828 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
829 {
830 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
831 {
832 //Throw an exception - The bitmap is not 64x64
833 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
834 }
835 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
836 {
837 //Throw an exception - The bitmap is not 64x64
838 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
839 }
840  
841 int x, y;
842 for (y = 0; y < 64; y++)
843 {
844 for (x = 0; x < 64; x++)
845 {
846 if (bitmap_add[x, y])
847 {
848 bitmap_base[x, y] = true;
849 }
850 }
851 }
852 return bitmap_base;
853 }
854  
855 /// <summary>
856 /// Converts the land bitmap to a packet friendly byte array
857 /// </summary>
858 /// <returns></returns>
859 private byte[] ConvertLandBitmapToBytes()
860 {
861 byte[] tempConvertArr = new byte[512];
862 byte tempByte = 0;
863 int x, y, i, byteNum = 0;
864 i = 0;
865 for (y = 0; y < 64; y++)
866 {
867 for (x = 0; x < 64; x++)
868 {
869 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
870 if (i % 8 == 0)
871 {
872 tempConvertArr[byteNum] = tempByte;
873 tempByte = (byte) 0;
874 i = 0;
875 byteNum++;
876 }
877 }
878 }
879 return tempConvertArr;
880 }
881  
882 private bool[,] ConvertBytesToLandBitmap()
883 {
884 bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax];
885 tempConvertMap.Initialize();
886 byte tempByte = 0;
887 int x = 0, y = 0, i = 0, bitNum = 0;
888 for (i = 0; i < 512; i++)
889 {
890 tempByte = LandData.Bitmap[i];
891 for (bitNum = 0; bitNum < 8; bitNum++)
892 {
893 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
894 tempConvertMap[x, y] = bit;
895 x++;
896 if (x > 63)
897 {
898 x = 0;
899 y++;
900 }
901 }
902 }
903 return tempConvertMap;
904 }
905  
906 #endregion
907  
908 #region Object Select and Object Owner Listing
909  
910 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
911 {
912 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
913 {
914 List<uint> resultLocalIDs = new List<uint>();
915 try
916 {
917 lock (primsOverMe)
918 {
919 foreach (SceneObjectGroup obj in primsOverMe)
920 {
921 if (obj.LocalId > 0)
922 {
923 if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID)
924 {
925 resultLocalIDs.Add(obj.LocalId);
926 }
927 else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero)
928 {
929 resultLocalIDs.Add(obj.LocalId);
930 }
931 else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
932 obj.OwnerID != remote_client.AgentId)
933 {
934 resultLocalIDs.Add(obj.LocalId);
935 }
936 else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
937 {
938 resultLocalIDs.Add(obj.LocalId);
939 }
940 }
941 }
942 }
943 } catch (InvalidOperationException)
944 {
945 m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
946 }
947  
948 remote_client.SendForceClientSelectObjects(resultLocalIDs);
949 }
950 }
951  
952 /// <summary>
953 /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
954 /// aggreagete details such as the number of prims.
955 ///
956 /// </summary>
957 /// <param name="remote_client">
958 /// A <see cref="IClientAPI"/>
959 /// </param>
960 public void SendLandObjectOwners(IClientAPI remote_client)
961 {
962 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
963 {
964 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
965 List<UUID> groups = new List<UUID>();
966  
967 lock (primsOverMe)
968 {
969 // m_log.DebugFormat(
970 // "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region",
971 // remote_client.Name, primsOverMe.Count);
972  
973 try
974 {
975 foreach (SceneObjectGroup obj in primsOverMe)
976 {
977 try
978 {
979 if (!primCount.ContainsKey(obj.OwnerID))
980 {
981 primCount.Add(obj.OwnerID, 0);
982 }
983 }
984 catch (NullReferenceException)
985 {
986 m_log.Error("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
987 }
988 try
989 {
990 primCount[obj.OwnerID] += obj.PrimCount;
991 }
992 catch (KeyNotFoundException)
993 {
994 m_log.Error("[LAND]: Unable to match a prim with it's owner.");
995 }
996 if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID)))
997 groups.Add(obj.OwnerID);
998 }
999 }
1000 catch (InvalidOperationException)
1001 {
1002 m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
1003 }
1004 }
1005  
1006 remote_client.SendLandObjectOwners(LandData, groups, primCount);
1007 }
1008 }
1009  
1010 public Dictionary<UUID, int> GetLandObjectOwners()
1011 {
1012 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
1013  
1014 lock (primsOverMe)
1015 {
1016 try
1017 {
1018  
1019 foreach (SceneObjectGroup obj in primsOverMe)
1020 {
1021 if (!ownersAndCount.ContainsKey(obj.OwnerID))
1022 {
1023 ownersAndCount.Add(obj.OwnerID, 0);
1024 }
1025 ownersAndCount[obj.OwnerID] += obj.PrimCount;
1026 }
1027 }
1028 catch (InvalidOperationException)
1029 {
1030 m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
1031 }
1032  
1033 }
1034 return ownersAndCount;
1035 }
1036  
1037 #endregion
1038  
1039 #region Object Returning
1040  
1041 public void ReturnObject(SceneObjectGroup obj)
1042 {
1043 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1044 objs[0] = obj;
1045 m_scene.returnObjects(objs, obj.OwnerID);
1046 }
1047  
1048 public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
1049 {
1050 // m_log.DebugFormat(
1051 // "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name);
1052  
1053 Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>();
1054  
1055 lock (primsOverMe)
1056 {
1057 if (type == (uint)ObjectReturnType.Owner)
1058 {
1059 foreach (SceneObjectGroup obj in primsOverMe)
1060 {
1061 if (obj.OwnerID == m_landData.OwnerID)
1062 {
1063 if (!returns.ContainsKey(obj.OwnerID))
1064 returns[obj.OwnerID] =
1065 new List<SceneObjectGroup>();
1066 returns[obj.OwnerID].Add(obj);
1067 }
1068 }
1069 }
1070 else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero)
1071 {
1072 foreach (SceneObjectGroup obj in primsOverMe)
1073 {
1074 if (obj.GroupID == m_landData.GroupID)
1075 {
1076 if (!returns.ContainsKey(obj.OwnerID))
1077 returns[obj.OwnerID] =
1078 new List<SceneObjectGroup>();
1079 returns[obj.OwnerID].Add(obj);
1080 }
1081 }
1082 }
1083 else if (type == (uint)ObjectReturnType.Other)
1084 {
1085 foreach (SceneObjectGroup obj in primsOverMe)
1086 {
1087 if (obj.OwnerID != m_landData.OwnerID &&
1088 (obj.GroupID != m_landData.GroupID ||
1089 m_landData.GroupID == UUID.Zero))
1090 {
1091 if (!returns.ContainsKey(obj.OwnerID))
1092 returns[obj.OwnerID] =
1093 new List<SceneObjectGroup>();
1094 returns[obj.OwnerID].Add(obj);
1095 }
1096 }
1097 }
1098 else if (type == (uint)ObjectReturnType.List)
1099 {
1100 List<UUID> ownerlist = new List<UUID>(owners);
1101  
1102 foreach (SceneObjectGroup obj in primsOverMe)
1103 {
1104 if (ownerlist.Contains(obj.OwnerID))
1105 {
1106 if (!returns.ContainsKey(obj.OwnerID))
1107 returns[obj.OwnerID] =
1108 new List<SceneObjectGroup>();
1109 returns[obj.OwnerID].Add(obj);
1110 }
1111 }
1112 }
1113 }
1114  
1115 foreach (List<SceneObjectGroup> ol in returns.Values)
1116 {
1117 if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol))
1118 m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
1119 }
1120 }
1121  
1122 #endregion
1123  
1124 #region Object Adding/Removing from Parcel
1125  
1126 public void ResetOverMeRecord()
1127 {
1128 lock (primsOverMe)
1129 primsOverMe.Clear();
1130 }
1131  
1132 public void AddPrimOverMe(SceneObjectGroup obj)
1133 {
1134 // m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name);
1135  
1136 lock (primsOverMe)
1137 primsOverMe.Add(obj);
1138 }
1139  
1140 public void RemovePrimFromOverMe(SceneObjectGroup obj)
1141 {
1142 // m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name);
1143  
1144 lock (primsOverMe)
1145 primsOverMe.Remove(obj);
1146 }
1147  
1148 #endregion
1149  
1150 /// <summary>
1151 /// Set the media url for this land parcel
1152 /// </summary>
1153 /// <param name="url"></param>
1154 public void SetMediaUrl(string url)
1155 {
1156 LandData.MediaURL = url;
1157 SendLandUpdateToAvatarsOverMe();
1158 }
1159  
1160 /// <summary>
1161 /// Set the music url for this land parcel
1162 /// </summary>
1163 /// <param name="url"></param>
1164 public void SetMusicUrl(string url)
1165 {
1166 LandData.MusicURL = url;
1167 SendLandUpdateToAvatarsOverMe();
1168 }
1169  
1170 /// <summary>
1171 /// Get the music url for this land parcel
1172 /// </summary>
1173 /// <returns>The music url.</returns>
1174 public string GetMusicUrl()
1175 {
1176 return LandData.MusicURL;
1177 }
1178  
1179 #endregion
1180  
1181 private void ExpireAccessList()
1182 {
1183 List<LandAccessEntry> delete = new List<LandAccessEntry>();
1184  
1185 foreach (LandAccessEntry entry in LandData.ParcelAccessList)
1186 {
1187 if (entry.Expires != 0 && entry.Expires < Util.UnixTimeSinceEpoch())
1188 delete.Add(entry);
1189 }
1190 foreach (LandAccessEntry entry in delete)
1191 LandData.ParcelAccessList.Remove(entry);
1192  
1193 if (delete.Count > 0)
1194 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this);
1195 }
1196 }
1197 }