29 using System.Collections.Generic;
30 using System.Reflection;
33 using OpenSim.Framework;
34 using OpenSim.Region.Framework.Interfaces;
35 using OpenSim.Region.Framework.Scenes;
45 #region Member Variables
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static readonly
string LogHeader =
"[LAND OBJECT]";
50 private readonly
int landUnit = 4;
52 private int m_lastSeqId = 0;
53 private int m_expiryCounter = 0;
56 protected List<SceneObjectGroup> primsOverMe =
new List<SceneObjectGroup>();
57 protected Dictionary<uint, UUID> m_listTransactions =
new Dictionary<uint, UUID>();
59 protected ExpiringCache<UUID, bool> m_groupMemberCache =
new ExpiringCache<UUID, bool>();
60 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30);
62 private bool[,] m_landBitmap;
63 public bool[,] LandBitmap
65 get {
return m_landBitmap; }
66 set { m_landBitmap = value; }
73 m_scene.EventManager.TriggerParcelPrimCountUpdate();
74 int free = GetSimulatorMaxPrimCount() - LandData.SimwidePrims;
81 get {
return m_landData; }
83 set { m_landData = value; }
88 public UUID RegionUUID
90 get {
return m_scene.RegionInfo.RegionID; }
93 private Vector2 m_startPoint = Vector2.Zero;
94 private Vector2 m_endPoint = Vector2.Zero;
95 private Vector2 m_centerPoint = Vector2.Zero;
96 private Vector2 m_AABBmin = Vector2.Zero;
97 private Vector2 m_AABBmax = Vector2.Zero;
99 public Vector2 StartPoint
107 public Vector2 EndPoint
116 public Vector2 CenterPoint
120 return m_centerPoint;
126 Vector3 direction =
new Vector3(m_centerPoint.X - pos.X, m_centerPoint.Y - pos.Y, 0f );
127 return GetNearestPointAlongDirection(pos, direction);
135 testpos.X = pos.X / landUnit;
136 testpos.Y = pos.Y / landUnit;
138 if(LandBitmap[(
int)testpos.X, (
int)testpos.Y])
139 return new Vector2(pos.X, pos.Y);
141 direction.X = pdirection.X;
142 direction.Y = pdirection.Y;
144 if(direction.X == 0f && direction.Y == 0f)
147 direction.Normalize();
149 int minx = (int)(m_AABBmin.X / landUnit);
150 int maxx = (int)(m_AABBmax.X / landUnit);
155 if(testpos.X >= maxx)
160 else if(direction.X < 0f)
164 if(testpos.X >= maxx)
165 testpos.X = maxx - 1;
171 else if(testpos.X >= maxx)
175 int miny = (int)(m_AABBmin.Y / landUnit);
176 int maxy = (int)(m_AABBmax.Y / landUnit);
180 if(testpos.Y >= maxy)
185 else if(direction.Y < 0f)
189 if(testpos.Y >= maxy)
190 testpos.Y = maxy - 1;
196 else if(testpos.Y >= maxy)
200 while(!LandBitmap[(
int)testpos.X, (int)testpos.Y])
202 testpos += direction;
206 if (testpos.X >= maxx)
210 if (testpos.Y >= maxy)
217 if(Math.Abs(direction.X) > Math.Abs(direction.Y))
220 testpos.X += landUnit - 0.5f;
223 ftmp = testpos.X - pos.X;
225 ftmp = Math.Abs(ftmp);
229 if(ftmp < testpos.Y + .5f)
230 ftmp = testpos.Y + .5f;
233 testpos.Y += landUnit - 0.5f;
242 testpos.Y += landUnit - 0.5f;
245 ftmp = testpos.Y - pos.Y;
247 ftmp = Math.Abs(ftmp);
251 if(ftmp < testpos.X + .5f)
252 ftmp = testpos.X + .5f;
255 testpos.X += landUnit - 0.5f;
277 LandBitmap =
new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
279 LandBitmap =
new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
282 LandData.OwnerID = owner_id;
284 LandData.GroupID = owner_id;
286 LandData.GroupID = UUID.Zero;
287 LandData.IsGroupOwned = is_group_owned;
289 m_scene.EventManager.OnFrame += OnFrame;
294 #region Member Functions
296 #region General Functions
306 if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
308 return LandBitmap[x / landUnit, y / landUnit];
319 newLand.LandBitmap = (
bool[,]) (LandBitmap.Clone());
328 overrideParcelMaxPrimCount = overrideDel;
332 overrideSimulatorMaxPrimCount = overrideDel;
337 if (overrideParcelMaxPrimCount != null)
339 return overrideParcelMaxPrimCount(
this);
344 int parcelMax = (int)( (
long)LandData.Area
345 * (long)m_scene.RegionInfo.ObjectCapacity
346 * (
long)m_scene.RegionInfo.RegionSettings.ObjectBonus
347 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
353 private int GetParcelBasePrimCount()
355 if (overrideParcelMaxPrimCount != null)
357 return overrideParcelMaxPrimCount(
this);
362 int parcelMax = (int)((
long)LandData.Area
363 * (long)m_scene.RegionInfo.ObjectCapacity
371 if (overrideSimulatorMaxPrimCount != null)
373 return overrideSimulatorMaxPrimCount(
this);
378 int simMax = (int)( (
long)LandData.SimwideArea
379 * (long)m_scene.RegionInfo.ObjectCapacity
380 / (
long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
388 #region Packet Request Handling
397 uint regionFlags = (uint)(
RegionFlags.PublicAllowed
402 if (estateModule != null)
403 regionFlags = estateModule.GetRegionFlags();
406 if (snap_selection && (sequence_id == 0))
408 seq_id = m_lastSeqId;
412 seq_id = sequence_id;
413 m_lastSeqId = seq_id;
416 remote_client.SendLandProperties(seq_id,
417 snap_selection, request_result,
this,
418 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
419 GetParcelBasePrimCount(),
420 GetSimulatorMaxPrimCount(), regionFlags);
426 snap_selection =
false;
430 uint allowedDelta = 0;
436 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandOptions,
false))
438 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
439 ParcelFlags.AllowTerraform |
440 ParcelFlags.AllowDamage |
441 ParcelFlags.CreateObjects |
442 ParcelFlags.RestrictPushObject |
443 ParcelFlags.AllowOtherScripts |
444 ParcelFlags.AllowGroupScripts |
445 ParcelFlags.CreateGroupObjects |
446 ParcelFlags.AllowAPrimitiveEntry |
447 ParcelFlags.AllowGroupObjectEntry |
448 ParcelFlags.AllowFly);
449 newData.SeeAVs = args.SeeAVs;
450 newData.AnyAVSounds = args.AnyAVSounds;
451 newData.GroupAVSounds = args.GroupAVSounds;
454 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandSetSale,
true))
459 snap_selection =
true;
462 newData.AuthBuyerID = args.AuthBuyerID;
463 newData.SalePrice = args.SalePrice;
467 newData.GroupID = args.GroupID;
469 allowedDelta |= (uint)(ParcelFlags.AllowDeedToGroup |
470 ParcelFlags.ContributeWithDeed |
471 ParcelFlags.SellParcelObjects);
474 allowedDelta |= (uint)ParcelFlags.ForSale;
477 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.FindPlaces,
false))
479 newData.Category = args.Category;
481 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
482 ParcelFlags.AllowPublish |
483 ParcelFlags.MaturePublish) | (uint)(1 << 23);
486 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandChangeIdentity,
false))
488 newData.Description = args.Desc;
489 newData.Name = args.Name;
490 newData.SnapshotID = args.SnapshotID;
493 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.SetLandingPoint,
false))
495 newData.LandingType = args.LandingType;
496 newData.UserLocation = args.UserLocation;
497 newData.UserLookAt = args.UserLookAt;
500 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.ChangeMedia,
false))
502 newData.MediaAutoScale = args.MediaAutoScale;
503 newData.MediaID = args.MediaID;
504 newData.MediaURL = args.MediaURL;
505 newData.MusicURL = args.MusicURL;
506 newData.MediaType = args.MediaType;
507 newData.MediaDescription = args.MediaDescription;
508 newData.MediaWidth = args.MediaWidth;
509 newData.MediaHeight = args.MediaHeight;
510 newData.MediaLoop = args.MediaLoop;
511 newData.ObscureMusic = args.ObscureMusic;
512 newData.ObscureMedia = args.ObscureMedia;
514 allowedDelta |= (uint)(ParcelFlags.SoundLocal |
515 ParcelFlags.UrlWebPage |
516 ParcelFlags.UrlRawHtml |
517 ParcelFlags.AllowVoiceChat |
518 ParcelFlags.UseEstateVoiceChan);
521 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandManagePasses,
false))
523 newData.PassHours = args.PassHours;
524 newData.PassPrice = args.PassPrice;
526 allowedDelta |= (uint)ParcelFlags.UsePassList;
529 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandManageAllowed,
false))
531 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
532 ParcelFlags.UseAccessList);
535 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandManageBanned,
false))
537 allowedDelta |= (uint)(ParcelFlags.UseBanList |
538 ParcelFlags.DenyAnonymous |
539 ParcelFlags.DenyAgeUnverified);
542 if (allowedDelta != (uint)ParcelFlags.None)
544 uint preserve = LandData.Flags & ~allowedDelta;
545 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
547 uint curdelta = LandData.Flags ^ newData.Flags;
548 curdelta &= (uint)(ParcelFlags.SoundLocal);
553 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
559 public void UpdateLandSold(UUID avatarID, UUID groupID,
bool groupOwned, uint AuctionID,
int claimprice,
int area)
562 newData.OwnerID = avatarID;
563 newData.GroupID = groupID;
564 newData.IsGroupOwned = groupOwned;
566 newData.ClaimDate = Util.UnixTimeSinceEpoch();
567 newData.ClaimPrice = claimprice;
568 newData.SalePrice = 0;
569 newData.AuthBuyerID = UUID.Zero;
570 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
572 bool sellObjects = (LandData.Flags & (uint)(ParcelFlags.SellParcelObjects)) != 0
578 SendLandUpdateToAvatarsOverMe(
true);
580 if (sellObjects) SellLandObjects(previousOwner);
586 newData.OwnerID = groupID;
587 newData.GroupID = groupID;
588 newData.IsGroupOwned =
true;
591 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
593 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
594 m_scene.EventManager.TriggerParcelPrimCountUpdate();
595 SendLandUpdateToAvatarsOverMe(
true);
600 if (IsBannedFromLand(avatar))
604 else if (IsRestrictedFromLand(avatar))
617 else if (IsRestrictedFromLand(avatar))
629 if (!m_scene.TryGetScenePresence(avatar, out sp))
632 if (m_groupMemberCache.TryGetValue(avatar, out isMember))
634 m_groupMemberCache.Update(avatar, isMember, m_groupMemberCacheTimeout);
639 if (groupsModule == null)
643 if (membership == null || membership.Length == 0)
645 m_groupMemberCache.Add(avatar,
false, m_groupMemberCacheTimeout);
653 m_groupMemberCache.Add(avatar,
true, m_groupMemberCacheTimeout);
657 m_groupMemberCache.Add(avatar,
false, m_groupMemberCacheTimeout);
661 return sp.ControllingClient.IsGroupMember(LandData.GroupID);
670 if (m_scene.Permissions.IsAdministrator(avatar))
673 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
697 if ((
LandData.
Flags & (uint) ParcelFlags.UseAccessList) == 0)
700 if (m_scene.Permissions.IsAdministrator(avatar))
703 if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
709 if (HasGroupAccess(avatar))
712 return !IsInLandAccessList(avatar);
722 if (e.
AgentID == avatar && e.
Flags == AccessList.Access)
734 SendLandProperties(0,
false, 0, remote_client);
739 m_scene.EventManager.TriggerParcelPrimCountUpdate();
740 SendLandProperties(0, snap_selection, 0, remote_client);
745 SendLandUpdateToAvatarsOverMe(
false);
750 m_scene.EventManager.TriggerParcelPrimCountUpdate();
751 m_scene.ForEachRootScenePresence(delegate(
ScenePresence avatar)
757 m_scene.LandChannel.GetLandObject(Util.Clamp<
int>((int)Math.Round(avatar.
AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
758 Util.Clamp<
int>((
int)Math.Round(avatar.AbsolutePosition.Y), 0, ((
int)m_scene.RegionInfo.RegionSizeY - 1)));
762 m_log.Warn(
"[LAND]: " +
"unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) +
" y: " +
770 if (((over.
LandData.
Flags & (uint)ParcelFlags.AllowDamage) != 0) &&
771 m_scene.RegionInfo.RegionSettings.AllowDamage)
777 avatar.currentParcelUUID = LandData.GlobalID;
785 #region AccessList Functions
791 List<LandAccessEntry> list =
new List<LandAccessEntry>();
794 if (entry.
Flags == flag)
800 e.AgentID = UUID.Zero;
810 public void SendAccessList(UUID agentID, UUID sessionID, uint flags,
int sequenceID,
814 if ((flags & (uint) AccessList.Access) != 0)
816 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access);
817 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,
LandData.
LocalID);
820 if ((flags & (uint) AccessList.Ban) != 0)
822 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban);
823 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban,
LandData.
LocalID);
828 int sequenceID,
int sections,
829 List<LandAccessEntry> entries,
834 if ((!m_listTransactions.ContainsKey(flags)) ||
835 m_listTransactions[flags] != transactionID)
837 m_listTransactions[flags] = transactionID;
839 List<LandAccessEntry> toRemove =
840 new List<LandAccessEntry>();
844 if (entry.
Flags == (AccessList)flags)
850 newData.ParcelAccessList.Remove(entry);
855 if (entries.Count == 1 && entries[0].AgentID ==
UUID.Zero)
857 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
868 temp.AgentID = entry.AgentID;
869 temp.Expires = entry.Expires;
870 temp.Flags = (AccessList)flags;
872 newData.ParcelAccessList.Add(temp);
877 uint parcelflags = newData.Flags;
879 if((flags & (uint)AccessList.Access) != 0)
880 parcelflags |= (uint)ParcelFlags.UseAccessList;
881 if((flags & (uint)AccessList.Ban) != 0)
882 parcelflags |= (uint)ParcelFlags.UseBanList;
884 newData.Flags = parcelflags;
891 #region Update Functions
895 LandData.Bitmap = ConvertLandBitmapToBytes();
903 UpdateGeometryValues();
904 UpdateLandBitmapByteArray();
909 LandBitmap = ConvertBytesToLandBitmap();
915 private void UpdateGeometryValues()
917 int min_x = Int32.MaxValue;
918 int min_y = Int32.MaxValue;
919 int max_x = Int32.MinValue;
920 int max_y = Int32.MinValue;
929 bool needFirst =
true;
931 for (x = 0; x < LandBitmap.GetLength(0); x++)
933 for (y = 0; y < LandBitmap.GetLength(1); y++)
935 if (LandBitmap[x, y])
950 m_startPoint.X = x * landUnit;
951 m_startPoint.Y = y * landUnit;
957 avgx = (avgx * tempArea + x) / (tempArea + 1);
958 avgy = (avgy * tempArea + y) / (tempArea + 1);
969 int halfunit = landUnit/2;
971 m_centerPoint.X = avgx * landUnit + halfunit;
972 m_centerPoint.Y = avgy * landUnit + halfunit;
974 m_endPoint.X = lastX * landUnit + landUnit;
975 m_endPoint.Y = lastY * landUnit + landUnit;
981 int regionSizeY = (
int)Constants.RegionSize;
985 regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
986 regionSizeY = (
int)m_scene.RegionInfo.RegionSizeX;
989 int tx = min_x * landUnit;
990 if (tx >= regionSizeX)
991 tx = regionSizeX - 1;
993 int ty = min_y * landUnit;
994 if (ty >= regionSizeY)
995 ty = regionSizeY - 1;
1000 if(m_scene == null || m_scene.Heightmap == null)
1001 LandData.AABBMin =
new Vector3(tx, ty, 0f);
1003 LandData.AABBMin =
new Vector3(tx, ty, (
float)m_scene.Heightmap[tx, ty]);
1006 tx = max_x * landUnit;
1007 if (tx > regionSizeX)
1011 ty = max_y * landUnit;
1012 if (ty > regionSizeY)
1018 if(m_scene == null || m_scene.Heightmap == null)
1019 LandData.AABBMax =
new Vector3(tx, ty, 0f);
1021 LandData.AABBMax =
new Vector3(tx, ty, (
float)m_scene.Heightmap[tx - 1, ty - 1]);
1023 LandData.Area = tempArea * landUnit * landUnit;
1028 #region Land Bitmap Functions
1036 LandBitmap = bitmap;
1037 ForceUpdateLandInfo();
1051 return GetSquareLandBitmap(0, 0, (
int)m_scene.RegionInfo.RegionSizeX, (
int) m_scene.RegionInfo.RegionSizeY,
true);
1057 bool[,] tempBitmap =
new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
1058 tempBitmap.Initialize();
1061 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, set_value);
1081 for (y = 0; y < land_bitmap.GetLength(1); y++)
1083 for (x = 0; x < land_bitmap.GetLength(0); x++)
1085 if (x >= start_x / landUnit && x < end_x / landUnit
1086 && y >= start_y / landUnit && y < end_y / landUnit)
1088 land_bitmap[x, y] = set_value;
1105 if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
1106 || bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
1107 || bitmap_add.Rank != 2
1108 || bitmap_base.Rank != 2)
1110 throw new Exception(
1111 String.Format(
"{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
1112 LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
1117 for (y = 0; y < bitmap_base.GetLength(1); y++)
1119 for (x = 0; x < bitmap_add.GetLength(0); x++)
1121 if (bitmap_add[x, y])
1123 bitmap_base[x, y] =
true;
1144 public bool[,]
RemapLandBitmap(
bool[,] bitmap_base, Vector2 displacement,
float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Vector2 regionSize, out
bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1147 int baseX = bitmap_base.GetLength(0);
1148 int baseY = bitmap_base.GetLength(1);
1151 int offsetX = baseX / 4;
1152 int offsetY = baseY / 4;
1153 int tmpX = baseX + baseX / 2;
1154 int tmpY = baseY + baseY / 2;
1155 int centreX = tmpX / 2;
1156 int centreY = tmpY / 2;
1157 bool[,] bitmap_tmp =
new bool[tmpX, tmpY];
1159 double radianRotation = Math.PI * rotationDegrees / 180f;
1160 double cosR = Math.Cos(radianRotation);
1161 double sinR = Math.Sin(radianRotation);
1162 if (rotationDegrees < 0f) rotationDegrees += 360f;
1168 for (y = 0; y <= tmpY; y++)
1170 for (x = 0; x <= tmpX; x++)
1172 if (rotationDegrees == 0f)
1177 else if (rotationDegrees == 90f)
1180 sy = tmpY - 1 - x - offsetY;
1182 else if (rotationDegrees == 180f)
1184 sx = tmpX - 1 - x - offsetX;
1185 sy = tmpY - 1 - y - offsetY;
1187 else if (rotationDegrees == 270f)
1189 sx = tmpX - 1 - y - offsetX;
1195 sx = centreX + (int)Math.Round((((
double)x - centreX) * cosR) + (((
double)y - centreY) * sinR)) - offsetX;
1196 sy = centreY + (int)Math.Round((((
double)y - centreY) * cosR) - (((
double)x - centreX) * sinR)) - offsetY;
1198 if (sx >= 0 && sx < baseX && sy >= 0 && sy < baseY)
1202 if (bitmap_base[sx, sy]) bitmap_tmp[x, y] =
true;
1206 m_log.DebugFormat(
"{0} RemapLandBitmap Rotate: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, sx, sy, x, y);
1217 int newX = (int)(regionSize.X / landUnit);
1218 int newY = (int)(regionSize.Y / landUnit);
1219 bool[,] bitmap_new =
new bool[newX, newY];
1221 int dispX = (int)Math.Floor(displacement.X / landUnit);
1222 int dispY = (int)Math.Floor(displacement.Y / landUnit);
1225 int startX = (int)Math.Floor(boundingOrigin.X / landUnit) + offsetX;
1226 if (startX > tmpX) startX = tmpX;
1227 if (startX < 0) startX = 0;
1228 int startY = (int)Math.Floor(boundingOrigin.Y / landUnit) + offsetY;
1229 if (startY > tmpY) startY = tmpY;
1230 if (startY < 0) startY = 0;
1232 int endX = (int)Math.Floor((boundingOrigin.X + boundingSize.X) / landUnit) + offsetX;
1233 if (endX > tmpX) endX = tmpX;
1234 if (endX < 0) endX = 0;
1235 int endY = (int)Math.Floor((boundingOrigin.Y + boundingSize.Y) / landUnit) + offsetY;
1236 if (endY > tmpY) endY = tmpY;
1237 if (endY < 0) endY = 0;
1249 for (y = startY; y < endY; y++)
1251 for (x = startX; x < endX; x++)
1253 dx = x - startX + dispX;
1254 dy = y - startY + dispY;
1255 if (dx >= 0 && dx < newX && dy >= 0 && dy < newY)
1259 if (bitmap_tmp[x, y])
1261 bitmap_new[dx, dy] =
true;
1263 if (dx < minX) minX = dx;
1264 if (dy < minY) minY = dy;
1265 if (dx > maxX) maxX = dx;
1266 if (dy > maxY) maxY = dy;
1271 m_log.DebugFormat(
"{0} RemapLandBitmap - Bound & Displace: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, x, y, dx, dy);
1283 AABBMin =
new Vector3(minX * landUnit, minY * landUnit, 0);
1284 AABBMax =
new Vector3(maxX * landUnit, maxY * landUnit, 0);
1298 public bool[,]
RemoveFromLandBitmap(
bool[,] bitmap_base,
bool[,] bitmap_new, out
bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1301 int baseX = bitmap_base.GetLength(0);
1302 int baseY = bitmap_base.GetLength(1);
1303 int newX = bitmap_new.GetLength(0);
1304 int newY = bitmap_new.GetLength(1);
1306 if (baseX != newX || baseY != newY)
1308 throw new Exception(
1309 String.Format(
"{0} RemoveFromLandBitmap: Land bitmaps are not the same size! baseX={1} baseY={2} newX={3} newY={4}", LogHeader, baseX, baseY, newX, newY));
1318 for (
int y = 0; y < baseY; y++)
1320 for (
int x = 0; x < baseX; x++)
1322 if (bitmap_new[x, y]) bitmap_base[x, y] =
false;
1323 if (bitmap_base[x, y])
1326 if (x < minX) minX = x;
1327 if (y < minY) minY = y;
1328 if (x > maxX) maxX = x;
1329 if (y > maxY) maxY = y;
1339 AABBMin =
new Vector3(minX * landUnit, minY * landUnit, 0);
1340 AABBMax =
new Vector3(maxX * landUnit, maxY * landUnit, 0);
1350 byte[] tempConvertArr =
new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
1356 for (
int y = 0; y < LandBitmap.GetLength(1); y++)
1358 for (
int x = 0; x < LandBitmap.GetLength(0); x++)
1360 if (LandBitmap[x, y])
1366 tempConvertArr[byteNum++] = (byte)tempByte;
1372 if(tempByte != 0 && byteNum < 512)
1373 tempConvertArr[byteNum] = (byte)tempByte;
1375 return tempConvertArr;
1382 bool[,] tempConvertMap;
1384 if (overrideRegionSize)
1391 bitmapLen = LandData.Bitmap.Length;
1392 xLen = (int)Math.Abs(Math.Sqrt(bitmapLen * 8));
1393 tempConvertMap =
new bool[xLen, xLen];
1394 tempConvertMap.Initialize();
1398 tempConvertMap =
new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
1399 tempConvertMap.Initialize();
1401 bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
1402 xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
1403 if (bitmapLen == 512)
1414 for (
int i = 0; i < bitmapLen; i++)
1416 tempByte = LandData.Bitmap[i];
1417 for (
int bitNum = 0; bitNum < 8; bitNum++)
1419 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
1422 tempConvertMap[x, y] = bit;
1426 m_log.DebugFormat(
"{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
1437 return tempConvertMap;
1442 for (
int y = 0; y < landBitmap.GetLength(1); y++)
1444 for (
int x = 0; x < landBitmap.GetLength(0); x++)
1446 if (landBitmap[x, y])
return false;
1454 m_log.InfoFormat(
"{0}: Map Key: #=claimed land .=unclaimed land.", LogHeader);
1455 for (
int y = landBitmap.GetLength(1) - 1; y >= 0; y--)
1458 for (
int x = 0; x < landBitmap.GetLength(0); x++)
1460 row += landBitmap[x, y] ?
"#" :
".";
1462 m_log.InfoFormat(
"{0}: {1}", LogHeader, row);
1468 #region Object Select and Object Owner Listing
1472 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandOptions,
true))
1474 List<uint> resultLocalIDs =
new List<uint>();
1485 resultLocalIDs.Add(obj.LocalId);
1489 resultLocalIDs.Add(obj.LocalId);
1494 resultLocalIDs.Add(obj.LocalId);
1496 else if (request_type == (
int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
1498 resultLocalIDs.Add(obj.LocalId);
1503 }
catch (InvalidOperationException)
1505 m_log.Error(
"[LAND]: Unable to force select the parcel objects. Arr.");
1508 remote_client.SendForceClientSelectObjects(resultLocalIDs);
1522 if (m_scene.Permissions.CanEditParcelProperties(remote_client.
AgentId,
this, GroupPowers.LandOptions,
true))
1524 Dictionary<UUID, int> primCount =
new Dictionary<UUID, int>();
1525 List<UUID> groups =
new List<UUID>();
1539 if (!primCount.ContainsKey(obj.
OwnerID))
1541 primCount.Add(obj.OwnerID, 0);
1544 catch (NullReferenceException)
1546 m_log.Error(
"[LAND]: " +
"Got Null Reference when searching land owners from the parcel panel");
1550 primCount[obj.OwnerID] += obj.PrimCount;
1552 catch (KeyNotFoundException)
1554 m_log.Error(
"[LAND]: Unable to match a prim with it's owner.");
1557 groups.Add(obj.OwnerID);
1560 catch (InvalidOperationException)
1562 m_log.Error(
"[LAND]: Unable to Enumerate Land object arr.");
1566 remote_client.SendLandObjectOwners(
LandData, groups, primCount);
1572 Dictionary<UUID, int> ownersAndCount =
new Dictionary<UUID, int>();
1581 if (!ownersAndCount.ContainsKey(obj.
OwnerID))
1583 ownersAndCount.Add(obj.OwnerID, 0);
1585 ownersAndCount[obj.OwnerID] += obj.PrimCount;
1588 catch (InvalidOperationException)
1590 m_log.Error(
"[LAND]: Unable to enumerate land owners. arr.");
1594 return ownersAndCount;
1599 #region Object Sales
1610 if (m_BuySellModule == null)
1612 m_log.Error(
"[LAND OBJECT]: BuySellModule not found");
1619 m_log.Error(
"[LAND OBJECT]: New owner is not present in scene");
1629 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0);
1636 #region Object Returning
1642 m_scene.returnObjects(objs, obj.OwnerID);
1650 Dictionary<UUID,List<SceneObjectGroup>> returns =
new Dictionary<UUID,List<SceneObjectGroup>>();
1654 if (type == (uint)ObjectReturnType.Owner)
1660 if (!returns.ContainsKey(obj.
OwnerID))
1662 new List<SceneObjectGroup>();
1663 returns[obj.OwnerID].Add(obj);
1667 else if (type == (uint)ObjectReturnType.Group && LandData.GroupID != UUID.Zero)
1673 if (!returns.ContainsKey(obj.
OwnerID))
1675 new List<SceneObjectGroup>();
1676 returns[obj.OwnerID].Add(obj);
1680 else if (type == (uint)ObjectReturnType.Other)
1688 if (!returns.ContainsKey(obj.
OwnerID))
1690 new List<SceneObjectGroup>();
1691 returns[obj.OwnerID].Add(obj);
1695 else if (type == (uint)ObjectReturnType.List)
1697 List<UUID> ownerlist =
new List<UUID>(owners);
1701 if (ownerlist.Contains(obj.
OwnerID))
1703 if (!returns.ContainsKey(obj.
OwnerID))
1705 new List<SceneObjectGroup>();
1706 returns[obj.OwnerID].Add(obj);
1712 foreach (List<SceneObjectGroup> ol
in returns.Values)
1714 if (m_scene.Permissions.CanReturnObjects(
this, remote_client.AgentId, ol))
1715 m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
1721 #region Object Adding/Removing from Parcel
1726 primsOverMe.Clear();
1734 primsOverMe.Add(obj);
1742 primsOverMe.Remove(obj);
1753 LandData.MediaURL = url;
1754 m_scene.LandChannel.UpdateLandObject(LandData.LocalID,
LandData);
1755 SendLandUpdateToAvatarsOverMe();
1764 LandData.MusicURL = url;
1765 m_scene.LandChannel.UpdateLandObject(LandData.LocalID,
LandData);
1766 SendLandUpdateToAvatarsOverMe();
1775 return LandData.MusicURL;
1780 private void OnFrame()
1784 if (m_expiryCounter >= 50)
1787 m_expiryCounter = 0;
1791 private void ExpireAccessList()
1793 List<LandAccessEntry>
delete =
new List<LandAccessEntry>();
1797 if (entry.
Expires != 0 && entry.
Expires < Util.UnixTimeSinceEpoch())
1802 LandData.ParcelAccessList.Remove(entry);
1805 if (m_scene.TryGetScenePresence(entry.
AgentID, out presence) && (!presence.IsChildAgent))
1807 ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
1810 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1811 presence.TeleportWithMomentum(pos, null);
1812 presence.ControllingClient.SendAlertMessage(
"You have been ejected from this land");
1815 m_log.DebugFormat(
"[LAND]: Removing entry {0} because it has expired", entry.AgentID);
1818 if (
delete.Count > 0)
1819 m_scene.EventManager.TriggerLandObjectUpdated((uint)
LandData.
LocalID,
this);
const int LAND_SELECT_OBJECTS_OWNER
uint GetEffectivePermissions()
int GetParcelMaxPrimCount()
List< LandAccessEntry > CreateAccessListArrayByFlag(AccessList flag)
void SendLandUpdateToClient(IClientAPI remote_client)
bool[,] GetLandBitmap()
Gets the land's bitmap manually
IClientAPI ControllingClient
void UpdateLandBitmapByteArray()
void ForceUpdateLandInfo()
Update all settings in land such as area, bitmap byte array, etc
LandObject(LandData landData, Scene scene)
bool[,] ConvertBytesToLandBitmap(bool overrideRegionSize=false)
void SendLandUpdateToAvatarsOverMe(bool snap_selection)
bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, bool set_value)
Change a land bitmap at within a square and set those points to a specific value
bool IsBannedFromLand(UUID avatar)
void RemovePrimFromOverMe(SceneObjectGroup obj)
void DebugLandBitmap(bool[,] landBitmap)
List< LandAccessEntry > ParcelAccessList
List of access data for the parcel. User data, some bitflags, and a time
LandObject(UUID owner_id, bool is_group_owned, Scene scene)
OpenMetaverse.RegionFlags RegionFlags
const int LAND_SELECT_OBJECTS_OTHER
void SendLandUpdateToAvatarsOverMe()
bool CanBeOnThisLand(UUID avatar, float posHeight)
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
bool[,] RemoveFromLandBitmap(bool[,] bitmap_base, bool[,] bitmap_new, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
Clears any parcel data in bitmap_base where there exists parcel data in bitmap_new. In other words the parcel data in bitmap_new takes over the space of the parcel data in bitmap_base.
void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
void DeedToGroup(UUID groupID)
PresenceType
Indicate the type of ScenePresence.
ISceneAgent SceneAgent
The scene agent for this client. This will only be set if the client has an agent in a scene (i...
void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client)
byte[] ConvertLandBitmapToBytes()
Converts the land bitmap to a packet friendly byte array
bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
Vector2 GetNearestPoint(Vector3 pos)
void UpdateAccessList(uint flags, UUID transactionID, int sequenceID, int sections, List< LandAccessEntry > entries, IClientAPI remote_client)
Keeps track of a specific piece of land's information
bool[,] BasicFullRegionLandBitmap()
Get a land bitmap that would cover an entire region.
bool HasGroupAccess(UUID avatar)
UUID GroupID
Unique ID of the Group that owns
void AddPrimOverMe(SceneObjectGroup obj)
RegionFlags
Region flags used internally by OpenSimulator to store installation specific information about region...
override Vector3 AbsolutePosition
Position of this avatar relative to the region the avatar is in
int GetSimulatorMaxPrimCount()
bool ContainsPoint(int x, int y)
Checks to see if this land object contains a point
void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
void SetMusicUrl(string url)
Set the music url for this land parcel
bool[,] RemapLandBitmap(bool[,] bitmap_base, Vector2 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Vector2 regionSize, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
Remap a land bitmap. Takes the supplied land bitmap and rotates it, crops it and finally offsets it i...
Details of a Parcel of land
void SendForceObjectSelect(int local_id, int request_type, List< UUID > returnIDs, IClientAPI remote_client)
void SetLandBitmap(bool[,] bitmap)
Sets the land's bitmap manually
delegate int overrideParcelMaxPrimCountDelegate(ILandObject obj)
const float BAN_LINE_SAFETY_HEIGHT
void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, IClientAPI remote_client)
void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
void SetLandBitmapFromByteArray()
void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
void SellLandObjects(UUID previousOwner)
void ReturnObject(SceneObjectGroup obj)
Interactive OpenSim region server
delegate int overrideSimulatorMaxPrimCountDelegate(ILandObject obj)
void SendLandObjectOwners(IClientAPI remote_client)
Notify the parcel owner each avatar that owns prims situated on their land. This notification include...
void SetMediaUrl(string url)
Set the media url for this land parcel
Dictionary< UUID, int > GetLandObjectOwners()
bool IsInLandAccessList(UUID avatar)
bool IsRestrictedFromLand(UUID avatar)
bool IsGroupOwned
Returns true if the Land Parcel is owned by a group
uint Flags
Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags ...
int SalePrice
When the parcel is being sold, this is the price to purchase the parcel
bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
Join the true values of 2 bitmaps together
string GetMusicUrl()
Get the music url for this land parcel
bool IsLandBitmapEmpty(bool[,] landBitmap)
int LocalID
Internal ID of the parcel. Sometimes the client will try to use this value
bool IsEitherBannedOrRestricted(UUID avatar)
const int LAND_SELECT_OBJECTS_GROUP
UUID AuthBuyerID
UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it.
Vector2 GetNearestPointAlongDirection(Vector3 pos, Vector3 pdirection)
bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y, bool set_value=true)
Create a square land bitmap.
PresenceType PresenceType
What type of presence is this? User, NPC, etc.
UUID OwnerID
Owner Avatar or Group of the parcel. Naturally, all land masses must be owned by someone ...