aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Land
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/World/Land')
-rw-r--r--OpenSim/Region/CoreModules/World/Land/DwellModule.cs22
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs5
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs938
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs324
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs266
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs1
7 files changed, 1205 insertions, 362 deletions
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
index bd22155..70c6028 100644
--- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
@@ -45,17 +45,19 @@ using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 45using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
46using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes; 47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager; 48using OpenSim.Region.PhysicsModules.SharedBase;
49using OpenSim.Services.Interfaces; 49using OpenSim.Services.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps; 50using Caps = OpenSim.Framework.Capabilities.Caps;
51using GridRegion = OpenSim.Services.Interfaces.GridRegion; 51using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52 52
53namespace OpenSim.Region.CoreModules.World.Land 53namespace OpenSim.Region.CoreModules.World.Land
54{ 54{
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DwellModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultDwellModule")]
56 public class DwellModule : IDwellModule, INonSharedRegionModule 56 public class DefaultDwellModule : IDwellModule, INonSharedRegionModule
57 { 57 {
58 private Scene m_scene; 58 private Scene m_scene;
59 private IConfigSource m_Config;
60 private bool m_Enabled = false;
59 61
60 public Type ReplaceableInterface 62 public Type ReplaceableInterface
61 { 63 {
@@ -64,15 +66,27 @@ namespace OpenSim.Region.CoreModules.World.Land
64 66
65 public string Name 67 public string Name
66 { 68 {
67 get { return "DwellModule"; } 69 get { return "DefaultDwellModule"; }
68 } 70 }
69 71
70 public void Initialise(IConfigSource source) 72 public void Initialise(IConfigSource source)
71 { 73 {
74 m_Config = source;
75
76 IConfig DwellConfig = m_Config.Configs ["Dwell"];
77
78 if (DwellConfig == null) {
79 m_Enabled = false;
80 return;
81 }
82 m_Enabled = (DwellConfig.GetString ("DwellModule", "DefaultDwellModule") == "DefaultDwellModule");
72 } 83 }
73 84
74 public void AddRegion(Scene scene) 85 public void AddRegion(Scene scene)
75 { 86 {
87 if (!m_Enabled)
88 return;
89
76 m_scene = scene; 90 m_scene = scene;
77 91
78 m_scene.EventManager.OnNewClient += OnNewClient; 92 m_scene.EventManager.OnNewClient += OnNewClient;
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 7fc358d..73c592d 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -95,6 +95,11 @@ namespace OpenSim.Region.CoreModules.World.Land
95 return null; 95 return null;
96 } 96 }
97 97
98 public ILandObject GetLandObject(Vector3 position)
99 {
100 return GetLandObject(position.X, position.Y);
101 }
102
98 public ILandObject GetLandObject(int x, int y) 103 public ILandObject GetLandObject(int x, int y)
99 { 104 {
100 if (m_landManagementModule != null) 105 if (m_landManagementModule != null)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index bad7205..92f6c1b 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -42,10 +42,9 @@ using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers; 43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer; 44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
46using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.PhysicsModules.SharedBase;
49using OpenSim.Services.Interfaces; 48using OpenSim.Services.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps; 49using Caps = OpenSim.Framework.Capabilities.Caps;
51using GridRegion = OpenSim.Services.Interfaces.GridRegion; 50using GridRegion = OpenSim.Services.Interfaces.GridRegion;
@@ -65,25 +64,27 @@ namespace OpenSim.Region.CoreModules.World.Land
65 public class LandManagementModule : INonSharedRegionModule 64 public class LandManagementModule : INonSharedRegionModule
66 { 65 {
67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
68
69 /// <summary>
70 /// Minimum land unit size in region co-ordinates.
71 /// </summary>
72 public const int LandUnit = 4;
68 73
69 private static readonly string remoteParcelRequestPath = "0009/"; 74 private static readonly string remoteParcelRequestPath = "0009/";
70 75
71 private LandChannel landChannel; 76 private LandChannel landChannel;
72 private Scene m_scene; 77 private Scene m_scene;
73 protected Commander m_commander = new Commander("land"); 78
74 79 protected IGroupsModule m_groupManager;
75 protected IUserManagement m_userManager; 80 protected IUserManagement m_userManager;
76 protected IPrimCountModule m_primCountModule; 81 protected IPrimCountModule m_primCountModule;
77 82 protected IDialogModule m_Dialog;
78 // Minimum for parcels to work is 64m even if we don't actually use them.
79 #pragma warning disable 0429
80 private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
81 #pragma warning restore 0429
82 83
83 /// <value> 84 /// <value>
84 /// Local land ids at specified region co-ordinates (region size / 4) 85 /// Local land ids at specified region co-ordinates (region size / 4)
85 /// </value> 86 /// </value>
86 private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax]; 87 private int[,] m_landIDList;
87 88
88 /// <value> 89 /// <value>
89 /// Land objects keyed by local id 90 /// Land objects keyed by local id
@@ -97,11 +98,17 @@ namespace OpenSim.Region.CoreModules.World.Land
97 // caches ExtendedLandData 98 // caches ExtendedLandData
98 private Cache parcelInfoCache; 99 private Cache parcelInfoCache;
99 100
101
100 /// <summary> 102 /// <summary>
101 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. 103 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
102 /// </summary> 104 /// </summary>
103 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>(); 105 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>();
104 106
107 // Enables limiting parcel layer info transmission when doing simple updates
108 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; }
109 // "View distance" for sending parcel layer info if asked for from a view point in the region
110 private int parcelLayerViewDistance { get; set; }
111
105 #region INonSharedRegionModule Members 112 #region INonSharedRegionModule Members
106 113
107 public Type ReplaceableInterface 114 public Type ReplaceableInterface
@@ -111,12 +118,20 @@ namespace OpenSim.Region.CoreModules.World.Land
111 118
112 public void Initialise(IConfigSource source) 119 public void Initialise(IConfigSource source)
113 { 120 {
121 shouldLimitParcelLayerInfoToViewDistance = true;
122 parcelLayerViewDistance = 128;
123 IConfig landManagementConfig = source.Configs["LandManagement"];
124 if (landManagementConfig != null)
125 {
126 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance);
127 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance);
128 }
114 } 129 }
115 130
116 public void AddRegion(Scene scene) 131 public void AddRegion(Scene scene)
117 { 132 {
118 m_scene = scene; 133 m_scene = scene;
119 m_landIDList.Initialize(); 134 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit];
120 landChannel = new LandChannel(scene, this); 135 landChannel = new LandChannel(scene, this);
121 136
122 parcelInfoCache = new Cache(); 137 parcelInfoCache = new Cache();
@@ -139,28 +154,26 @@ namespace OpenSim.Region.CoreModules.World.Land
139 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 154 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
140 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; 155 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
141 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; 156 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
142 m_scene.EventManager.OnPluginConsole += EventManagerOnPluginConsole;
143 157
144 lock (m_scene) 158 lock (m_scene)
145 { 159 {
146 m_scene.LandChannel = (ILandChannel)landChannel; 160 m_scene.LandChannel = (ILandChannel)landChannel;
147 } 161 }
148 162
149 InstallInterfaces(); 163 RegisterCommands();
150 } 164 }
151 165
152 public void RegionLoaded(Scene scene) 166 public void RegionLoaded(Scene scene)
153 { 167 {
154 m_userManager = m_scene.RequestModuleInterface<IUserManagement>(); 168 m_userManager = m_scene.RequestModuleInterface<IUserManagement>();
155 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>(); 169 m_groupManager = m_scene.RequestModuleInterface<IGroupsModule>();
170 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>();
171 m_Dialog = m_scene.RequestModuleInterface<IDialogModule>();
156 } 172 }
157 173
158 public void RemoveRegion(Scene scene) 174 public void RemoveRegion(Scene scene)
159 { 175 {
160 // TODO: Also release other event manager listeners here 176 // TODO: Release event manager listeners here
161
162 m_scene.EventManager.OnPluginConsole -= EventManagerOnPluginConsole;
163 m_scene.UnregisterModuleCommander(m_commander.Name);
164 } 177 }
165 178
166// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason) 179// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
@@ -168,30 +181,7 @@ namespace OpenSim.Region.CoreModules.World.Land
168// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y); 181// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
169// reason = "You are not allowed to enter this sim."; 182// reason = "You are not allowed to enter this sim.";
170// return nearestParcel != null; 183// return nearestParcel != null;
171// } 184// }
172
173 /// <summary>
174 /// Processes commandline input. Do not call directly.
175 /// </summary>
176 /// <param name="args">Commandline arguments</param>
177 protected void EventManagerOnPluginConsole(string[] args)
178 {
179 if (args[0] == "land")
180 {
181 if (args.Length == 1)
182 {
183 m_commander.ProcessConsoleCommand("help", new string[0]);
184 return;
185 }
186
187 string[] tmpArgs = new string[args.Length - 2];
188 int i;
189 for (i = 2; i < args.Length; i++)
190 tmpArgs[i - 2] = args[i];
191
192 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
193 }
194 }
195 185
196 void EventManagerOnNewClient(IClientAPI client) 186 void EventManagerOnNewClient(IClientAPI client)
197 { 187 {
@@ -210,6 +200,10 @@ namespace OpenSim.Region.CoreModules.World.Land
210 client.OnParcelInfoRequest += ClientOnParcelInfoRequest; 200 client.OnParcelInfoRequest += ClientOnParcelInfoRequest;
211 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; 201 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
212 client.OnPreAgentUpdate += ClientOnPreAgentUpdate; 202 client.OnPreAgentUpdate += ClientOnPreAgentUpdate;
203 client.OnParcelEjectUser += ClientOnParcelEjectUser;
204 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
205 client.OnSetStartLocationRequest += ClientOnSetHome;
206
213 207
214 EntityBase presenceEntity; 208 EntityBase presenceEntity;
215 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 209 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
@@ -293,14 +287,15 @@ namespace OpenSim.Region.CoreModules.World.Land
293 LandData newData = data.Copy(); 287 LandData newData = data.Copy();
294 newData.LocalID = local_id; 288 newData.LocalID = local_id;
295 289
290 ILandObject land;
296 lock (m_landList) 291 lock (m_landList)
297 { 292 {
298 if (m_landList.ContainsKey(local_id)) 293 if (m_landList.TryGetValue(local_id, out land))
299 { 294 land.LandData = newData;
300 m_landList[local_id].LandData = newData;
301 m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]);
302 }
303 } 295 }
296
297 if (land != null)
298 m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land);
304 } 299 }
305 300
306 public bool AllowedForcefulBans 301 public bool AllowedForcefulBans
@@ -319,7 +314,7 @@ namespace OpenSim.Region.CoreModules.World.Land
319 { 314 {
320 m_landList.Clear(); 315 m_landList.Clear();
321 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 316 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
322 m_landIDList.Initialize(); 317 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit];
323 } 318 }
324 } 319 }
325 320
@@ -333,7 +328,8 @@ namespace OpenSim.Region.CoreModules.World.Land
333 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); 328 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
334 329
335 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 330 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
336 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 331 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
332 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
337 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 333 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
338 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 334 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
339 335
@@ -460,8 +456,8 @@ namespace OpenSim.Region.CoreModules.World.Land
460 456
461 public void SendLandUpdate(ScenePresence avatar, bool force) 457 public void SendLandUpdate(ScenePresence avatar, bool force)
462 { 458 {
463 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 459 ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
464 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); 460 (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
465 461
466 if (over != null) 462 if (over != null)
467 { 463 {
@@ -543,16 +539,13 @@ namespace OpenSim.Region.CoreModules.World.Land
543 /// </summary> 539 /// </summary>
544 /// <param name="avatar"></param> 540 /// <param name="avatar"></param>
545 public void EventManagerOnClientMovement(ScenePresence avatar) 541 public void EventManagerOnClientMovement(ScenePresence avatar)
546 //
547 { 542 {
548 ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 543 Vector3 pos = avatar.AbsolutePosition;
544 ILandObject over = GetLandObject(pos.X, pos.Y);
549 if (over != null) 545 if (over != null)
550 { 546 {
551 if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)) 547 if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || pos.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT))
552 { 548 avatar.lastKnownAllowedPosition = pos;
553 avatar.lastKnownAllowedPosition =
554 new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
555 }
556 } 549 }
557 } 550 }
558 551
@@ -611,7 +604,10 @@ namespace OpenSim.Region.CoreModules.World.Land
611 /// <summary> 604 /// <summary>
612 /// Adds a land object to the stored list and adds them to the landIDList to what they own 605 /// Adds a land object to the stored list and adds them to the landIDList to what they own
613 /// </summary> 606 /// </summary>
614 /// <param name="new_land">The land object being added</param> 607 /// <param name="new_land">
608 /// The land object being added.
609 /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted.
610 /// </param>
615 public ILandObject AddLandObject(ILandObject land) 611 public ILandObject AddLandObject(ILandObject land)
616 { 612 {
617 ILandObject new_land = land.Copy(); 613 ILandObject new_land = land.Copy();
@@ -619,34 +615,76 @@ namespace OpenSim.Region.CoreModules.World.Land
619 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated 615 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated
620 // as a random UUID inside LandData initialization 616 // as a random UUID inside LandData initialization
621 if (m_primCountModule != null) 617 if (m_primCountModule != null)
622 new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID); 618 new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID);
623 619
624 lock (m_landList) 620 lock (m_landList)
625 { 621 {
626 int newLandLocalID = ++m_lastLandLocalID; 622 int newLandLocalID = m_lastLandLocalID + 1;
627 new_land.LandData.LocalID = newLandLocalID; 623 new_land.LandData.LocalID = newLandLocalID;
628 624
629 bool[,] landBitmap = new_land.GetLandBitmap(); 625 bool[,] landBitmap = new_land.GetLandBitmap();
630 for (int x = 0; x < landArrayMax; x++) 626 // m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). newLocalID={3}",
627 // LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), newLandLocalID);
628
629 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
630 {
631 // Going to variable sized regions can cause mismatches
632 m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
633 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1) );
634 }
635 else
631 { 636 {
632 for (int y = 0; y < landArrayMax; y++) 637 // If other land objects still believe that they occupy any parts of the same space,
638 // then do not allow the add to proceed.
639 for (int x = 0; x < landBitmap.GetLength(0); x++)
633 { 640 {
634 if (landBitmap[x, y]) 641 for (int y = 0; y < landBitmap.GetLength(1); y++)
635 { 642 {
636// m_log.DebugFormat( 643 if (landBitmap[x, y])
637// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", 644 {
638// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); 645 int lastRecordedLandId = m_landIDList[x, y];
639 646
640 m_landIDList[x, y] = newLandLocalID; 647 if (lastRecordedLandId > 0)
648 {
649 ILandObject lastRecordedLo = m_landList[lastRecordedLandId];
650
651 if (lastRecordedLo.LandBitmap[x, y])
652 {
653 m_log.ErrorFormat(
654 "{0}: Cannot add parcel \"{1}\", local ID {2} at tile {3},{4} because this is still occupied by parcel \"{5}\", local ID {6} in {7}",
655 LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y,
656 lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name);
657
658 return null;
659 }
660 }
661 }
662 }
663 }
664
665 for (int x = 0; x < landBitmap.GetLength(0); x++)
666 {
667 for (int y = 0; y < landBitmap.GetLength(1); y++)
668 {
669 if (landBitmap[x, y])
670 {
671 // m_log.DebugFormat(
672 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
673 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
674
675 m_landIDList[x, y] = newLandLocalID;
676 }
641 } 677 }
642 } 678 }
643 } 679 }
644 680
645 m_landList.Add(newLandLocalID, new_land); 681 m_landList.Add(newLandLocalID, new_land);
682 m_lastLandLocalID++;
646 } 683 }
647 684
648 new_land.ForceUpdateLandInfo(); 685 new_land.ForceUpdateLandInfo();
649 m_scene.EventManager.TriggerLandObjectAdded(new_land); 686 m_scene.EventManager.TriggerLandObjectAdded(new_land);
687
650 return new_land; 688 return new_land;
651 } 689 }
652 690
@@ -656,11 +694,12 @@ namespace OpenSim.Region.CoreModules.World.Land
656 /// <param name="local_id">Land.localID of the peice of land to remove.</param> 694 /// <param name="local_id">Land.localID of the peice of land to remove.</param>
657 public void removeLandObject(int local_id) 695 public void removeLandObject(int local_id)
658 { 696 {
697 ILandObject land;
659 lock (m_landList) 698 lock (m_landList)
660 { 699 {
661 for (int x = 0; x < 64; x++) 700 for (int x = 0; x < m_landIDList.GetLength(0); x++)
662 { 701 {
663 for (int y = 0; y < 64; y++) 702 for (int y = 0; y < m_landIDList.GetLength(1); y++)
664 { 703 {
665 if (m_landIDList[x, y] == local_id) 704 if (m_landIDList[x, y] == local_id)
666 { 705 {
@@ -672,9 +711,11 @@ namespace OpenSim.Region.CoreModules.World.Land
672 } 711 }
673 } 712 }
674 713
675 m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID); 714 land = m_landList[local_id];
676 m_landList.Remove(local_id); 715 m_landList.Remove(local_id);
677 } 716 }
717
718 m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID);
678 } 719 }
679 720
680 /// <summary> 721 /// <summary>
@@ -682,21 +723,27 @@ namespace OpenSim.Region.CoreModules.World.Land
682 /// </summary> 723 /// </summary>
683 public void Clear(bool setupDefaultParcel) 724 public void Clear(bool setupDefaultParcel)
684 { 725 {
726 List<ILandObject> parcels;
685 lock (m_landList) 727 lock (m_landList)
686 { 728 {
687 foreach (ILandObject lo in m_landList.Values) 729 parcels = new List<ILandObject>(m_landList.Values);
688 { 730 }
689 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); 731
690 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); 732 foreach (ILandObject lo in parcels)
691 } 733 {
734 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID);
735 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID);
736 }
692 737
738 lock (m_landList)
739 {
693 m_landList.Clear(); 740 m_landList.Clear();
694 741
695 ResetSimLandObjects(); 742 ResetSimLandObjects();
696
697 if (setupDefaultParcel)
698 CreateDefaultParcel();
699 } 743 }
744
745 if (setupDefaultParcel)
746 CreateDefaultParcel();
700 } 747 }
701 748
702 private void performFinalLandJoin(ILandObject master, ILandObject slave) 749 private void performFinalLandJoin(ILandObject master, ILandObject slave)
@@ -704,9 +751,9 @@ namespace OpenSim.Region.CoreModules.World.Land
704 bool[,] landBitmapSlave = slave.GetLandBitmap(); 751 bool[,] landBitmapSlave = slave.GetLandBitmap();
705 lock (m_landList) 752 lock (m_landList)
706 { 753 {
707 for (int x = 0; x < 64; x++) 754 for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
708 { 755 {
709 for (int y = 0; y < 64; y++) 756 for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
710 { 757 {
711 if (landBitmapSlave[x, y]) 758 if (landBitmapSlave[x, y])
712 { 759 {
@@ -740,23 +787,28 @@ namespace OpenSim.Region.CoreModules.World.Land
740 /// <returns>Land object at the point supplied</returns> 787 /// <returns>Land object at the point supplied</returns>
741 public ILandObject GetLandObject(float x_float, float y_float) 788 public ILandObject GetLandObject(float x_float, float y_float)
742 { 789 {
790 return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */);
791 /*
743 int x; 792 int x;
744 int y; 793 int y;
745 794
746 if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) 795 if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
747 return null; 796 return null;
748 797
749 try 798 try
750 { 799 {
751 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0)); 800 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
752 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0)); 801 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
753 } 802 }
754 catch (OverflowException) 803 catch (OverflowException)
755 { 804 {
756 return null; 805 return null;
757 } 806 }
758 807
759 if (x >= 64 || y >= 64 || x < 0 || y < 0) 808 if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
809 || y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
810 || x < 0
811 || y < 0)
760 { 812 {
761 return null; 813 return null;
762 } 814 }
@@ -772,38 +824,70 @@ namespace OpenSim.Region.CoreModules.World.Land
772// m_log.DebugFormat( 824// m_log.DebugFormat(
773// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}", 825// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}",
774// x, y, m_scene.RegionInfo.RegionName); 826// x, y, m_scene.RegionInfo.RegionName);
775 827
776 if (m_landList.ContainsKey(m_landIDList[x, y])) 828 try
777 return m_landList[m_landIDList[x, y]]; 829 {
830 if (m_landList.ContainsKey(m_landIDList[x, y]))
831 return m_landList[m_landIDList[x, y]];
832 }
833 catch (Exception e)
834 {
835 m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})",
836 LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
837 }
778 838
779 return null; 839 return null;
780 } 840 }
841 */
781 } 842 }
782 843
844 // Public entry.
845 // Throws exception if land object is not found
783 public ILandObject GetLandObject(int x, int y) 846 public ILandObject GetLandObject(int x, int y)
784 { 847 {
785 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) 848 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
849 }
850
851 /// <summary>
852 /// Given a region position, return the parcel land object for that location
853 /// </summary>
854 /// <returns>
855 /// The land object.
856 /// </returns>
857 /// <param name='x'></param>
858 /// <param name='y'></param>
859 /// <param name='returnNullIfLandObjectNotFound'>
860 /// Return null if the land object requested is not within the region's bounds.
861 /// </param>
862 private ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds)
863 {
864 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
786 { 865 {
787 // These exceptions here will cause a lot of complaints from the users specifically because 866 // These exceptions here will cause a lot of complaints from the users specifically because
788 // they happen every time at border crossings 867 // they happen every time at border crossings
789 throw new Exception("Error: Parcel not found at point " + x + ", " + y); 868 if (returnNullIfLandObjectOutsideBounds)
790 }
791
792 lock (m_landIDList)
793 {
794 try
795 {
796 return m_landList[m_landIDList[x / 4, y / 4]];
797 }
798 catch (IndexOutOfRangeException)
799 {
800// m_log.WarnFormat(
801// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}",
802// x, y, m_scene.RegionInfo.RegionName);
803
804 return null; 869 return null;
805 } 870 else
871 throw new Exception(
872 String.Format("{0} GetLandObject for non-existent position. Region={1}, pos=<{2},{3}",
873 LogHeader, m_scene.RegionInfo.RegionName, x, y)
874 );
806 } 875 }
876
877 return m_landList[m_landIDList[x / 4, y / 4]];
878 }
879
880 // Create a 'parcel is here' bitmap for the parcel identified by the passed landID
881 private bool[,] CreateBitmapForID(int landID)
882 {
883 bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)];
884
885 for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
886 for (int yy = 0; yy < m_landIDList.GetLength(0); yy++)
887 if (m_landIDList[xx, yy] == landID)
888 ret[xx, yy] = true;
889
890 return ret;
807 } 891 }
808 892
809 #endregion 893 #endregion
@@ -973,8 +1057,12 @@ namespace OpenSim.Region.CoreModules.World.Land
973 1057
974 //Now add the new land object 1058 //Now add the new land object
975 ILandObject result = AddLandObject(newLand); 1059 ILandObject result = AddLandObject(newLand);
976 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); 1060
977 result.SendLandUpdateToAvatarsOverMe(); 1061 if (result != null)
1062 {
1063 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData);
1064 result.SendLandUpdateToAvatarsOverMe();
1065 }
978 } 1066 }
979 1067
980 /// <summary> 1068 /// <summary>
@@ -1055,96 +1143,164 @@ namespace OpenSim.Region.CoreModules.World.Land
1055 1143
1056 #region Parcel Updating 1144 #region Parcel Updating
1057 1145
1146 // Send parcel layer info for the whole region
1147 public void SendParcelOverlay(IClientAPI remote_client)
1148 {
1149 SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize);
1150 }
1151
1058 /// <summary> 1152 /// <summary>
1059 /// Where we send the ParcelOverlay packet to the client 1153 /// Send the parcel overlay blocks to the client. We send the overlay packets
1154 /// around a location and limited by the 'parcelLayerViewDistance'. This number
1155 /// is usually 128 and the code is arranged so it sends all the parcel overlay
1156 /// information for a whole region if the region is legacy sized (256x256). If
1157 /// the region is larger, only the parcel layer information is sent around
1158 /// the point specified. This reduces the problem of parcel layer information
1159 /// blocks increasing exponentially as region size increases.
1060 /// </summary> 1160 /// </summary>
1061 /// <param name="remote_client">The object representing the client</param> 1161 /// <param name="remote_client">The object representing the client</param>
1062 public void SendParcelOverlay(IClientAPI remote_client) 1162 /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param>
1163 /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param>
1164 /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param>
1165 private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance)
1063 { 1166 {
1064 const int LAND_BLOCKS_PER_PACKET = 1024; 1167 const int LAND_BLOCKS_PER_PACKET = 1024;
1065 1168
1066 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1169 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1067 int byteArrayCount = 0; 1170 int byteArrayCount = 0;
1068 int sequenceID = 0; 1171 int sequenceID = 0;
1069 int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize;
1070 1172
1173 int xLow = 0;
1174 int xHigh = (int)m_scene.RegionInfo.RegionSizeX;
1175 int yLow = 0;
1176 int yHigh = (int)m_scene.RegionInfo.RegionSizeY;
1071 1177
1072 for (int y = 0; y < blockmeters; y++) 1178 if (shouldLimitParcelLayerInfoToViewDistance)
1073 { 1179 {
1074 for (int x = 0; x < blockmeters; x++) 1180 // Compute view distance around the given point
1181 int txLow = xPlace - layerViewDistance;
1182 int txHigh = xPlace + layerViewDistance;
1183 // If the distance is outside the region area, move the view distance to ba all in the region
1184 if (txLow < xLow)
1185 {
1186 txLow = xLow;
1187 txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh);
1188 }
1189 if (txHigh > xHigh)
1075 { 1190 {
1076 byte tempByte = 0; //This represents the byte for the current 4x4 1191 txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2));
1192 txHigh = xHigh;
1193 }
1194 xLow = txLow;
1195 xHigh = txHigh;
1077 1196
1078 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); 1197 int tyLow = yPlace - layerViewDistance;
1198 int tyHigh = yPlace + layerViewDistance;
1199 if (tyLow < yLow)
1200 {
1201 tyLow = yLow;
1202 tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh);
1203 }
1204 if (tyHigh > yHigh)
1205 {
1206 tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2));
1207 tyHigh = yHigh;
1208 }
1209 yLow = tyLow;
1210 yHigh = tyHigh;
1211 }
1212 // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>",
1213 // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh);
1079 1214
1080 if (currentParcelBlock != null) 1215 // Layer data is in landUnit (4m) chunks
1216 for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1217 {
1218 for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
1219 {
1220 byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client);
1221 byteArrayCount++;
1222 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1081 { 1223 {
1082 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) 1224 // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length);
1083 { 1225 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1084 //Owner Flag 1226 byteArrayCount = 0;
1085 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1227 sequenceID++;
1086 } 1228 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1087 else if (currentParcelBlock.LandData.SalePrice > 0 && 1229 }
1088 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1089 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1090 {
1091 //Sale Flag
1092 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1093 }
1094 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1095 {
1096 //Public Flag
1097 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1098 }
1099 else
1100 {
1101 //Other Flag
1102 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1103 }
1104 1230
1105 //Now for border control 1231 }
1232 }
1106 1233
1107 ILandObject westParcel = null; 1234 if (byteArrayCount != 0)
1108 ILandObject southParcel = null; 1235 {
1109 if (x > 0) 1236 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1110 { 1237 // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length);
1111 westParcel = GetLandObject((x - 1) * 4, y * 4); 1238 }
1112 } 1239 }
1113 if (y > 0)
1114 {
1115 southParcel = GetLandObject(x * 4, (y - 1) * 4);
1116 }
1117 1240
1118 if (x == 0) 1241 private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client)
1119 { 1242 {
1120 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); 1243 byte tempByte = 0; //This represents the byte for the current 4x4
1121 }
1122 else if (westParcel != null && westParcel != currentParcelBlock)
1123 {
1124 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1125 }
1126 1244
1127 if (y == 0) 1245 if (currentParcelBlock != null)
1128 { 1246 {
1129 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1247 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
1130 } 1248 {
1131 else if (southParcel != null && southParcel != currentParcelBlock) 1249 //Owner Flag
1132 { 1250 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1133 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1251 }
1134 } 1252 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1253 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1254 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1255 {
1256 //Sale Flag
1257 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1258 }
1259 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1260 {
1261 //Public Flag
1262 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1263 }
1264 else
1265 {
1266 //Other Flag
1267 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1268 }
1135 1269
1136 byteArray[byteArrayCount] = tempByte; 1270 //Now for border control
1137 byteArrayCount++; 1271
1138 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) 1272 ILandObject westParcel = null;
1139 { 1273 ILandObject southParcel = null;
1140 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1274 if (x > 0)
1141 byteArrayCount = 0; 1275 {
1142 sequenceID++; 1276 westParcel = GetLandObject((x - 1) * LandUnit, y * LandUnit);
1143 byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1277 }
1144 } 1278 if (y > 0)
1145 } 1279 {
1280 southParcel = GetLandObject(x * LandUnit, (y - 1) * LandUnit);
1281 }
1282
1283 if (x == 0)
1284 {
1285 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1286 }
1287 else if (westParcel != null && westParcel != currentParcelBlock)
1288 {
1289 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1146 } 1290 }
1291
1292 if (y == 0)
1293 {
1294 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
1295 }
1296 else if (southParcel != null && southParcel != currentParcelBlock)
1297 {
1298 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
1299 }
1300
1147 } 1301 }
1302
1303 return tempByte;
1148 } 1304 }
1149 1305
1150 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, 1306 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
@@ -1182,7 +1338,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1182 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); 1338 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
1183 } 1339 }
1184 1340
1185 SendParcelOverlay(remote_client); 1341 // Also send the layer data around the point of interest
1342 SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance);
1186 } 1343 }
1187 1344
1188 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) 1345 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
@@ -1254,6 +1411,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1254 1411
1255 m_scene.ForEachClient(SendParcelOverlay); 1412 m_scene.ForEachClient(SendParcelOverlay);
1256 land.SendLandUpdateToClient(true, remote_client); 1413 land.SendLandUpdateToClient(true, remote_client);
1414 UpdateLandObject(land.LandData.LocalID, land.LandData);
1257 } 1415 }
1258 } 1416 }
1259 } 1417 }
@@ -1274,8 +1432,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1274 land.LandData.GroupID = UUID.Zero; 1432 land.LandData.GroupID = UUID.Zero;
1275 land.LandData.IsGroupOwned = false; 1433 land.LandData.IsGroupOwned = false;
1276 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1434 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1435
1277 m_scene.ForEachClient(SendParcelOverlay); 1436 m_scene.ForEachClient(SendParcelOverlay);
1278 land.SendLandUpdateToClient(true, remote_client); 1437 land.SendLandUpdateToClient(true, remote_client);
1438 UpdateLandObject(land.LandData.LocalID, land.LandData);
1279 } 1439 }
1280 } 1440 }
1281 } 1441 }
@@ -1302,6 +1462,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1302 1462
1303 m_scene.ForEachClient(SendParcelOverlay); 1463 m_scene.ForEachClient(SendParcelOverlay);
1304 land.SendLandUpdateToClient(true, remote_client); 1464 land.SendLandUpdateToClient(true, remote_client);
1465 UpdateLandObject(land.LandData.LocalID, land.LandData);
1305 } 1466 }
1306 } 1467 }
1307 } 1468 }
@@ -1382,19 +1543,78 @@ namespace OpenSim.Region.CoreModules.World.Land
1382 1543
1383 #region Land Object From Storage Functions 1544 #region Land Object From Storage Functions
1384 1545
1385 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1546 private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1386 { 1547 {
1387// m_log.DebugFormat( 1548// m_log.DebugFormat(
1388// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name); 1549// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name);
1389 1550
1390 for (int i = 0; i < data.Count; i++) 1551 // Prevent race conditions from any auto-creation of new parcels for varregions whilst we are still loading
1391 IncomingLandObjectFromStorage(data[i]); 1552 // the existing parcels.
1553 lock (m_landList)
1554 {
1555 for (int i = 0; i < data.Count; i++)
1556 IncomingLandObjectFromStorage(data[i]);
1557
1558 // Layer data is in landUnit (4m) chunks
1559 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1560 {
1561 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
1562 {
1563 if (m_landIDList[x, y] == 0)
1564 {
1565 if (m_landList.Count == 1)
1566 {
1567 m_log.DebugFormat(
1568 "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}",
1569 LogHeader, x, y, m_scene.Name);
1570
1571 int onlyParcelID = 0;
1572 ILandObject onlyLandObject = null;
1573 foreach (KeyValuePair<int, ILandObject> kvp in m_landList)
1574 {
1575 onlyParcelID = kvp.Key;
1576 onlyLandObject = kvp.Value;
1577 break;
1578 }
1579
1580 // There is only one parcel. Grow it to fill all the unallocated spaces.
1581 for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
1582 for (int yy = 0; yy < m_landIDList.GetLength(1); yy++)
1583 if (m_landIDList[xx, yy] == 0)
1584 m_landIDList[xx, yy] = onlyParcelID;
1585
1586 onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID);
1587 }
1588 else if (m_landList.Count > 1)
1589 {
1590 m_log.DebugFormat(
1591 "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}",
1592 LogHeader, x, y, m_scene.Name);
1593
1594 // There are several other parcels so we must create a new one for the unassigned space
1595 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
1596 // Claim all the unclaimed "0" ids
1597 newLand.SetLandBitmap(CreateBitmapForID(0));
1598 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
1599 newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
1600 newLand = AddLandObject(newLand);
1601 }
1602 else
1603 {
1604 // We should never reach this point as the separate code path when no land data exists should have fired instead.
1605 m_log.WarnFormat(
1606 "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present",
1607 LogHeader, m_scene.Name);
1608 }
1609 }
1610 }
1611 }
1612 }
1392 } 1613 }
1393 1614
1394 public void IncomingLandObjectFromStorage(LandData data) 1615 private void IncomingLandObjectFromStorage(LandData data)
1395 { 1616 {
1396 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); 1617 ILandObject new_land = new LandObject(data, m_scene);
1397 new_land.LandData = data.Copy();
1398 new_land.SetLandBitmapFromByteArray(); 1618 new_land.SetLandBitmapFromByteArray();
1399 AddLandObject(new_land); 1619 AddLandObject(new_land);
1400 } 1620 }
@@ -1409,7 +1629,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1409 m_landList.TryGetValue(localID, out selectedParcel); 1629 m_landList.TryGetValue(localID, out selectedParcel);
1410 } 1630 }
1411 1631
1412 if (selectedParcel == null) return; 1632 if (selectedParcel == null)
1633 return;
1413 1634
1414 selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); 1635 selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
1415 } 1636 }
@@ -1417,7 +1638,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1417 { 1638 {
1418 if (returnType != 1) 1639 if (returnType != 1)
1419 { 1640 {
1420 m_log.WarnFormat("[LAND MANAGEMENT MODULE] ReturnObjectsInParcel: unknown return type {0}", returnType); 1641 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown return type {0}", returnType);
1421 return; 1642 return;
1422 } 1643 }
1423 1644
@@ -1437,14 +1658,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1437 } 1658 }
1438 else 1659 else
1439 { 1660 {
1440 m_log.WarnFormat("[LAND MANAGEMENT MODULE] ReturnObjectsInParcel: unknown object {0}", groupID); 1661 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown object {0}", groupID);
1441 } 1662 }
1442 } 1663 }
1443 1664
1444 int num = 0; 1665 int num = 0;
1445 foreach (HashSet<SceneObjectGroup> objs in returns.Values) 1666 foreach (HashSet<SceneObjectGroup> objs in returns.Values)
1446 num += objs.Count; 1667 num += objs.Count;
1447 m_log.DebugFormat("[LAND MANAGEMENT MODULE] Returning {0} specific object(s)", num); 1668 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Returning {0} specific object(s)", num);
1448 1669
1449 foreach (HashSet<SceneObjectGroup> objs in returns.Values) 1670 foreach (HashSet<SceneObjectGroup> objs in returns.Values)
1450 { 1671 {
@@ -1455,7 +1676,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1455 } 1676 }
1456 else 1677 else
1457 { 1678 {
1458 m_log.WarnFormat("[LAND MANAGEMENT MODULE] ReturnObjectsInParcel: not permitted to return {0} object(s) belonging to user {1}", 1679 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: not permitted to return {0} object(s) belonging to user {1}",
1459 objs2.Count, objs2[0].OwnerID); 1680 objs2.Count, objs2[0].OwnerID);
1460 } 1681 }
1461 } 1682 }
@@ -1464,11 +1685,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1464 1685
1465 public void EventManagerOnNoLandDataFromStorage() 1686 public void EventManagerOnNoLandDataFromStorage()
1466 { 1687 {
1467 lock (m_landList) 1688 ResetSimLandObjects();
1468 { 1689 CreateDefaultParcel();
1469 ResetSimLandObjects();
1470 CreateDefaultParcel();
1471 }
1472 } 1690 }
1473 1691
1474 #endregion 1692 #endregion
@@ -1694,7 +1912,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1694 { 1912 {
1695 // most likely still cached from building the extLandData entry 1913 // most likely still cached from building the extLandData entry
1696 uint x = 0, y = 0; 1914 uint x = 0, y = 0;
1697 Utils.LongToUInts(data.RegionHandle, out x, out y); 1915 Util.RegionHandleToWorldLoc(data.RegionHandle, out x, out y);
1698 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 1916 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
1699 } 1917 }
1700 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. 1918 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
@@ -1730,66 +1948,332 @@ namespace OpenSim.Region.CoreModules.World.Land
1730 UpdateLandObject(localID, land.LandData); 1948 UpdateLandObject(localID, land.LandData);
1731 } 1949 }
1732 1950
1733 protected void InstallInterfaces() 1951 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1952
1953 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1954 {
1955 ScenePresence targetAvatar = null;
1956 ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
1957 ScenePresence parcelManager = null;
1958 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1959 System.Threading.Timer Timer;
1960
1961 if (targetAvatar.UserLevel == 0)
1962 {
1963 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1964 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1965 return;
1966 if (flags == 0)
1967 {
1968 targetAvatar.AllowMovement = false;
1969 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world.");
1970 parcelManager.ControllingClient.SendAlertMessage("Avatar Frozen.");
1971 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
1972 Timer = new System.Threading.Timer(timeCB, targetAvatar, 30000, 0);
1973 Timers.Add(targetAvatar.UUID, Timer);
1974 }
1975 else
1976 {
1977 targetAvatar.AllowMovement = true;
1978 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has unfrozen you.");
1979 parcelManager.ControllingClient.SendAlertMessage("Avatar Unfrozen.");
1980 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1981 Timers.Remove(targetAvatar.UUID);
1982 Timer.Dispose();
1983 }
1984 }
1985 }
1986
1987 private void OnEndParcelFrozen(object avatar)
1734 { 1988 {
1735 Command clearCommand 1989 ScenePresence targetAvatar = (ScenePresence)avatar;
1736 = new Command("clear", CommandIntentions.COMMAND_HAZARDOUS, ClearCommand, "Clears all the parcels from the region."); 1990 targetAvatar.AllowMovement = true;
1737 Command showCommand 1991 System.Threading.Timer Timer;
1738 = new Command("show", CommandIntentions.COMMAND_STATISTICAL, ShowParcelsCommand, "Shows all parcels on the region."); 1992 Timers.TryGetValue(targetAvatar.UUID, out Timer);
1993 Timers.Remove(targetAvatar.UUID);
1994 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1995 }
1996
1997 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1998 {
1999 ScenePresence targetAvatar = null;
2000 ScenePresence parcelManager = null;
2001
2002 // Must have presences
2003 if (!m_scene.TryGetScenePresence(target, out targetAvatar) ||
2004 !m_scene.TryGetScenePresence(client.AgentId, out parcelManager))
2005 return;
2006
2007 // Cannot eject estate managers or gods
2008 if (m_scene.Permissions.IsAdministrator(target))
2009 return;
2010
2011 // Check if you even have permission to do this
2012 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
2013 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) &&
2014 !m_scene.Permissions.IsAdministrator(client.AgentId))
2015 return;
2016 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
2017
2018 targetAvatar.TeleportWithMomentum(pos, null);
2019 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
2020 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1739 2021
1740 m_commander.RegisterCommand("clear", clearCommand); 2022 if ((flags & 1) != 0) // Ban TODO: Remove magic number
1741 m_commander.RegisterCommand("show", showCommand); 2023 {
2024 LandAccessEntry entry = new LandAccessEntry();
2025 entry.AgentID = targetAvatar.UUID;
2026 entry.Flags = AccessList.Ban;
2027 entry.Expires = 0; // Perm
1742 2028
1743 // Add this to our scene so scripts can call these functions 2029 land.LandData.ParcelAccessList.Add(entry);
1744 m_scene.RegisterModuleCommander(m_commander); 2030 }
2031 }
2032
2033 /// <summary>
2034 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
2035 /// </summary>
2036 /// <param name="remoteClient"></param>
2037 /// <param name="regionHandle"></param>
2038 /// <param name="position"></param>
2039 /// <param name="lookAt"></param>
2040 /// <param name="flags"></param>
2041 public virtual void ClientOnSetHome(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
2042 {
2043 // Let's find the parcel in question
2044 ILandObject land = landChannel.GetLandObject(position);
2045 if (land == null || m_scene.GridUserService == null)
2046 {
2047 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
2048 return;
2049 }
2050
2051 // Gather some data
2052 ulong gpowers = remoteClient.GetGroupPowers(land.LandData.GroupID);
2053 SceneObjectGroup telehub = null;
2054 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
2055 // Does the telehub exist in the scene?
2056 telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
2057
2058 // Can the user set home here?
2059 if (// Required: local user; foreign users cannot set home
2060 m_scene.UserManagementModule.IsLocalGridUser(remoteClient.AgentId) &&
2061 (// (a) gods and land managers can set home
2062 m_scene.Permissions.IsAdministrator(remoteClient.AgentId) ||
2063 m_scene.Permissions.IsGod(remoteClient.AgentId) ||
2064 // (b) land owners can set home
2065 remoteClient.AgentId == land.LandData.OwnerID ||
2066 // (c) members of the land-associated group in roles that can set home
2067 ((gpowers & (ulong)GroupPowers.AllowSetHome) == (ulong)GroupPowers.AllowSetHome) ||
2068 // (d) parcels with telehubs can be the home of anyone
2069 (telehub != null && land.ContainsPoint((int)telehub.AbsolutePosition.X, (int)telehub.AbsolutePosition.Y))))
2070 {
2071 string userId;
2072 UUID test;
2073 if (!m_scene.UserManagementModule.GetUserUUI(remoteClient.AgentId, out userId))
2074 {
2075 /* Do not set a home position in this grid for a HG visitor */
2076 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed. (User Lookup)");
2077 }
2078 else if (!UUID.TryParse(userId, out test))
2079 {
2080 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed. (HG visitor)");
2081 }
2082 else if (m_scene.GridUserService.SetHome(userId, land.RegionUUID, position, lookAt))
2083 {
2084 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2085 m_Dialog.SendAlertToUser(remoteClient, "Home position set.");
2086 }
2087 else
2088 {
2089 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
2090 }
2091 }
2092 else
2093 m_Dialog.SendAlertToUser(remoteClient, "You are not allowed to set your home location in this parcel.");
2094 }
2095
2096 protected void RegisterCommands()
2097 {
2098 ICommands commands = MainConsole.Instance.Commands;
2099
2100 commands.AddCommand(
2101 "Land", false, "land clear",
2102 "land clear",
2103 "Clear all the parcels from the region.",
2104 "Command will ask for confirmation before proceeding.",
2105 HandleClearCommand);
2106
2107 commands.AddCommand(
2108 "Land", false, "land show",
2109 "land show [<local-land-id>]",
2110 "Show information about the parcels on the region.",
2111 "If no local land ID is given, then summary information about all the parcels is shown.\n"
2112 + "If a local land ID is given then full information about that parcel is shown.",
2113 HandleShowCommand);
1745 } 2114 }
1746 2115
1747 protected void ClearCommand(Object[] args) 2116 protected void HandleClearCommand(string module, string[] args)
1748 { 2117 {
2118 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
2119 return;
2120
1749 string response = MainConsole.Instance.CmdPrompt( 2121 string response = MainConsole.Instance.CmdPrompt(
1750 string.Format( 2122 string.Format(
1751 "Are you sure that you want to clear all land parcels from {0} (y or n)", 2123 "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name),
1752 m_scene.RegionInfo.RegionName),
1753 "n"); 2124 "n");
1754 2125
1755 if (response.ToLower() == "y") 2126 if (response.ToLower() == "y")
1756 { 2127 {
1757 Clear(true); 2128 Clear(true);
1758 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.RegionInfo.RegionName); 2129 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.Name);
1759 } 2130 }
1760 else 2131 else
1761 { 2132 {
1762 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.RegionInfo.RegionName); 2133 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name);
1763 } 2134 }
1764 } 2135 }
1765 2136
1766 protected void ShowParcelsCommand(Object[] args) 2137 protected void HandleShowCommand(string module, string[] args)
1767 { 2138 {
1768 StringBuilder report = new StringBuilder(); 2139 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
1769 2140 return;
1770 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName); 2141
1771 report.AppendFormat( 2142 StringBuilder report = new StringBuilder();
1772 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", 2143
1773 "Parcel Name", 2144 if (args.Length <= 2)
1774 "Local ID", 2145 {
1775 "Area", 2146 AppendParcelsSummaryReport(report);
1776 "Starts", 2147 }
1777 "Ends", 2148 else
1778 "Owner"); 2149 {
2150 int landLocalId;
2151
2152 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId))
2153 return;
2154
2155 ILandObject lo;
2156
2157 lock (m_landList)
2158 {
2159 if (!m_landList.TryGetValue(landLocalId, out lo))
2160 {
2161 MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId);
2162 return;
2163 }
2164 }
2165
2166 AppendParcelReport(report, lo);
2167 }
2168
2169 MainConsole.Instance.Output(report.ToString());
2170 }
2171
2172 private void AppendParcelsSummaryReport(StringBuilder report)
2173 {
2174 report.AppendFormat("Land information for {0}\n", m_scene.Name);
2175
2176 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
2177 cdt.AddColumn("Parcel Name", ConsoleDisplayUtil.ParcelNameSize);
2178 cdt.AddColumn("ID", 3);
2179 cdt.AddColumn("Area", 6);
2180 cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize);
2181 cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize);
2182 cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize);
1779 2183
1780 lock (m_landList) 2184 lock (m_landList)
1781 { 2185 {
1782 foreach (ILandObject lo in m_landList.Values) 2186 foreach (ILandObject lo in m_landList.Values)
1783 { 2187 {
1784 LandData ld = lo.LandData; 2188 LandData ld = lo.LandData;
1785 2189 string ownerName;
1786 report.AppendFormat( 2190 if (ld.IsGroupOwned)
1787 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", 2191 {
1788 ld.Name, ld.LocalID, ld.Area, lo.StartPoint, lo.EndPoint, m_userManager.GetUserName(ld.OwnerID)); 2192 GroupRecord rec = m_groupManager.GetGroupRecord(ld.GroupID);
2193 ownerName = (rec != null) ? rec.GroupName : "Unknown Group";
2194 }
2195 else
2196 {
2197 ownerName = m_userManager.GetUserName(ld.OwnerID);
2198 }
2199 cdt.AddRow(
2200 ld.Name, ld.LocalID, ld.Area, lo.StartPoint, lo.EndPoint, ownerName);
1789 } 2201 }
1790 } 2202 }
1791 2203
1792 MainConsole.Instance.Output(report.ToString()); 2204 report.Append(cdt.ToString());
1793 } 2205 }
2206
2207 private void AppendParcelReport(StringBuilder report, ILandObject lo)
2208 {
2209 LandData ld = lo.LandData;
2210
2211 ConsoleDisplayList cdl = new ConsoleDisplayList();
2212 cdl.AddRow("Parcel name", ld.Name);
2213 cdl.AddRow("Local ID", ld.LocalID);
2214 cdl.AddRow("Description", ld.Description);
2215 cdl.AddRow("Snapshot ID", ld.SnapshotID);
2216 cdl.AddRow("Area", ld.Area);
2217 cdl.AddRow("Starts", lo.StartPoint);
2218 cdl.AddRow("Ends", lo.EndPoint);
2219 cdl.AddRow("AABB Min", ld.AABBMin);
2220 cdl.AddRow("AABB Max", ld.AABBMax);
2221 string ownerName;
2222 if (ld.IsGroupOwned)
2223 {
2224 GroupRecord rec = m_groupManager.GetGroupRecord(ld.GroupID);
2225 ownerName = (rec != null) ? rec.GroupName : "Unknown Group";
2226 }
2227 else
2228 {
2229 ownerName = m_userManager.GetUserName(ld.OwnerID);
2230 }
2231 cdl.AddRow("Owner", ownerName);
2232 cdl.AddRow("Is group owned?", ld.IsGroupOwned);
2233 cdl.AddRow("GroupID", ld.GroupID);
2234
2235 cdl.AddRow("Status", ld.Status);
2236 cdl.AddRow("Flags", (ParcelFlags)ld.Flags);
2237
2238 cdl.AddRow("Landing Type", (LandingType)ld.LandingType);
2239 cdl.AddRow("User Location", ld.UserLocation);
2240 cdl.AddRow("User look at", ld.UserLookAt);
2241
2242 cdl.AddRow("Other clean time", ld.OtherCleanTime);
2243
2244 cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount());
2245 IPrimCounts pc = lo.PrimCounts;
2246 cdl.AddRow("Owner Prims", pc.Owner);
2247 cdl.AddRow("Group Prims", pc.Group);
2248 cdl.AddRow("Other Prims", pc.Others);
2249 cdl.AddRow("Selected Prims", pc.Selected);
2250 cdl.AddRow("Total Prims", pc.Total);
2251
2252 cdl.AddRow("Music URL", ld.MusicURL);
2253 cdl.AddRow("Obscure Music", ld.ObscureMusic);
2254
2255 cdl.AddRow("Media ID", ld.MediaID);
2256 cdl.AddRow("Media Autoscale", Convert.ToBoolean(ld.MediaAutoScale));
2257 cdl.AddRow("Media URL", ld.MediaURL);
2258 cdl.AddRow("Media Type", ld.MediaType);
2259 cdl.AddRow("Media Description", ld.MediaDescription);
2260 cdl.AddRow("Media Width", ld.MediaWidth);
2261 cdl.AddRow("Media Height", ld.MediaHeight);
2262 cdl.AddRow("Media Loop", ld.MediaLoop);
2263 cdl.AddRow("Obscure Media", ld.ObscureMedia);
2264
2265 cdl.AddRow("Parcel Category", ld.Category);
2266
2267 cdl.AddRow("Claim Date", ld.ClaimDate);
2268 cdl.AddRow("Claim Price", ld.ClaimPrice);
2269 cdl.AddRow("Pass Hours", ld.PassHours);
2270 cdl.AddRow("Pass Price", ld.PassPrice);
2271
2272 cdl.AddRow("Auction ID", ld.AuctionID);
2273 cdl.AddRow("Authorized Buyer ID", ld.AuthBuyerID);
2274 cdl.AddRow("Sale Price", ld.SalePrice);
2275
2276 cdl.AddToStringBuilder(report);
2277 }
1794 } 2278 }
1795} 2279}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 5969d45..a0c1b9d 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -45,14 +45,12 @@ namespace OpenSim.Region.CoreModules.World.Land
45 #region Member Variables 45 #region Member Variables
46 46
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 #pragma warning disable 0429 48 private static readonly string LogHeader = "[LAND OBJECT]";
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 49
53 private int m_lastSeqId = 0; 50 private readonly int landUnit = 4;
54 51
55 protected LandData m_landData = new LandData(); 52 private int m_lastSeqId = 0;
53
56 protected Scene m_scene; 54 protected Scene m_scene;
57 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 55 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
58 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>(); 56 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
@@ -60,76 +58,83 @@ namespace OpenSim.Region.CoreModules.World.Land
60 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>(); 58 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
61 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds 59 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
62 60
63 public bool[,] LandBitmap 61 public bool[,] LandBitmap { get; set; }
64 {
65 get { return m_landBitmap; }
66 set { m_landBitmap = value; }
67 }
68 62
69 #endregion 63 #endregion
70 64
71 public int GetPrimsFree() 65 public int GetPrimsFree()
72 { 66 {
73 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 67 m_scene.EventManager.TriggerParcelPrimCountUpdate();
74 int free = GetSimulatorMaxPrimCount() - m_landData.SimwidePrims; 68 int free = GetSimulatorMaxPrimCount() - LandData.SimwidePrims;
75 return free; 69 return free;
76 } 70 }
77 71
78 public LandData LandData 72 public LandData LandData { get; set; }
79 {
80 get { return m_landData; }
81 73
82 set { m_landData = value; }
83 }
84
85 public IPrimCounts PrimCounts { get; set; } 74 public IPrimCounts PrimCounts { get; set; }
86 75
87 public UUID RegionUUID 76 public UUID RegionUUID
88 { 77 {
89 get { return m_scene.RegionInfo.RegionID; } 78 get { return m_scene.RegionInfo.RegionID; }
90 } 79 }
91 80
92 public Vector3 StartPoint 81 public Vector3 StartPoint
93 { 82 {
94 get 83 get
95 { 84 {
96 for (int y = 0; y < landArrayMax; y++) 85 for (int y = 0; y < LandBitmap.GetLength(1); y++)
97 { 86 {
98 for (int x = 0; x < landArrayMax; x++) 87 for (int x = 0; x < LandBitmap.GetLength(0); x++)
99 { 88 {
100 if (LandBitmap[x, y]) 89 if (LandBitmap[x, y])
101 return new Vector3(x * 4, y * 4, 0); 90 return new Vector3(x * landUnit, y * landUnit, 0);
102 } 91 }
103 } 92 }
104 93
94 m_log.ErrorFormat("{0} StartPoint. No start point found. bitmapSize=<{1},{2}>",
95 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
105 return new Vector3(-1, -1, -1); 96 return new Vector3(-1, -1, -1);
106 } 97 }
107 } 98 }
108 99
109 public Vector3 EndPoint 100 public Vector3 EndPoint
110 { 101 {
111 get 102 get
112 { 103 {
113 for (int y = landArrayMax - 1; y >= 0; y--) 104 for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
114 { 105 {
115 for (int x = landArrayMax - 1; x >= 0; x--) 106 for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
116 { 107 {
117 if (LandBitmap[x, y]) 108 if (LandBitmap[x, y])
118 { 109 {
119 return new Vector3(x * 4, y * 4, 0); 110 return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
120 } 111 }
121 } 112 }
122 } 113 }
123 114
115 m_log.ErrorFormat("{0} EndPoint. No end point found. bitmapSize=<{1},{2}>",
116 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
124 return new Vector3(-1, -1, -1); 117 return new Vector3(-1, -1, -1);
125 } 118 }
126 } 119 }
127 120
128 #region Constructors 121 #region Constructors
129 122
123 public LandObject(LandData landData, Scene scene)
124 {
125 LandData = landData.Copy();
126 m_scene = scene;
127 }
128
130 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 129 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
131 { 130 {
132 m_scene = scene; 131 m_scene = scene;
132 if (m_scene == null)
133 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
134 else
135 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
136
137 LandData = new LandData();
133 LandData.OwnerID = owner_id; 138 LandData.OwnerID = owner_id;
134 if (is_group_owned) 139 if (is_group_owned)
135 LandData.GroupID = owner_id; 140 LandData.GroupID = owner_id;
@@ -152,9 +157,9 @@ namespace OpenSim.Region.CoreModules.World.Land
152 /// <returns>Returns true if the piece of land contains the specified point</returns> 157 /// <returns>Returns true if the piece of land contains the specified point</returns>
153 public bool ContainsPoint(int x, int y) 158 public bool ContainsPoint(int x, int y)
154 { 159 {
155 if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize) 160 if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
156 { 161 {
157 return (LandBitmap[x / 4, y / 4] == true); 162 return LandBitmap[x / landUnit, y / landUnit];
158 } 163 }
159 else 164 else
160 { 165 {
@@ -164,12 +169,8 @@ namespace OpenSim.Region.CoreModules.World.Land
164 169
165 public ILandObject Copy() 170 public ILandObject Copy()
166 { 171 {
167 ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene); 172 ILandObject newLand = new LandObject(LandData, m_scene);
168
169 //Place all new variables here!
170 newLand.LandBitmap = (bool[,]) (LandBitmap.Clone()); 173 newLand.LandBitmap = (bool[,]) (LandBitmap.Clone());
171 newLand.LandData = LandData.Copy();
172
173 return newLand; 174 return newLand;
174 } 175 }
175 176
@@ -194,7 +195,7 @@ namespace OpenSim.Region.CoreModules.World.Land
194 else 195 else
195 { 196 {
196 // Normal Calculations 197 // Normal Calculations
197 int parcelMax = (int)(((float)LandData.Area / 65536.0f) 198 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
198 * (float)m_scene.RegionInfo.ObjectCapacity 199 * (float)m_scene.RegionInfo.ObjectCapacity
199 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 200 * (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 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL!
@@ -211,7 +212,7 @@ namespace OpenSim.Region.CoreModules.World.Land
211 else 212 else
212 { 213 {
213 //Normal Calculations 214 //Normal Calculations
214 int simMax = (int)(((float)LandData.SimwideArea / 65536.0f) 215 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
215 * (float)m_scene.RegionInfo.ObjectCapacity); 216 * (float)m_scene.RegionInfo.ObjectCapacity);
216 return simMax; 217 return simMax;
217 } 218 }
@@ -224,17 +225,15 @@ namespace OpenSim.Region.CoreModules.World.Land
224 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 225 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
225 { 226 {
226 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 227 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
227 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 228 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
229 uint regionFlags = (uint)(RegionFlags.PublicAllowed
230 | RegionFlags.AllowDirectTeleport
231 | RegionFlags.AllowParcelChanges
232 | RegionFlags.AllowVoice );
233
228 if (estateModule != null) 234 if (estateModule != null)
229 regionFlags = estateModule.GetRegionFlags(); 235 regionFlags = estateModule.GetRegionFlags();
230 236
231 // In a perfect world, this would have worked.
232 //
233// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0)
234// regionFlags |= (uint)RegionFlags.AllowLandmark;
235// if (landData.OwnerID == remote_client.AgentId)
236// regionFlags |= (uint)RegionFlags.AllowSetHome;
237
238 int seq_id; 237 int seq_id;
239 if (snap_selection && (sequence_id == 0)) 238 if (snap_selection && (sequence_id == 0))
240 { 239 {
@@ -368,12 +367,14 @@ namespace OpenSim.Region.CoreModules.World.Land
368 ParcelFlags.DenyAgeUnverified); 367 ParcelFlags.DenyAgeUnverified);
369 } 368 }
370 369
371 uint preserve = LandData.Flags & ~allowedDelta; 370 if (allowedDelta != (uint)ParcelFlags.None)
372 newData.Flags = preserve | (args.ParcelFlags & allowedDelta); 371 {
373 372 uint preserve = LandData.Flags & ~allowedDelta;
374 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 373 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
375 374
376 SendLandUpdateToAvatarsOverMe(snap_selection); 375 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
376 SendLandUpdateToAvatarsOverMe(snap_selection);
377 }
377 } 378 }
378 379
379 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 380 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -388,9 +389,16 @@ namespace OpenSim.Region.CoreModules.World.Land
388 newData.SalePrice = 0; 389 newData.SalePrice = 0;
389 newData.AuthBuyerID = UUID.Zero; 390 newData.AuthBuyerID = UUID.Zero;
390 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 391 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
392
393 bool sellObjects = (LandData.Flags & (uint)(ParcelFlags.SellParcelObjects)) != 0
394 && !LandData.IsGroupOwned && !groupOwned;
395 UUID previousOwner = LandData.OwnerID;
396
391 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 397 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
392 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 398 m_scene.EventManager.TriggerParcelPrimCountUpdate();
393 SendLandUpdateToAvatarsOverMe(true); 399 SendLandUpdateToAvatarsOverMe(true);
400
401 if (sellObjects) SellLandObjects(previousOwner);
394 } 402 }
395 403
396 public void DeedToGroup(UUID groupID) 404 public void DeedToGroup(UUID groupID)
@@ -421,6 +429,19 @@ namespace OpenSim.Region.CoreModules.World.Land
421 return false; 429 return false;
422 } 430 }
423 431
432 public bool CanBeOnThisLand(UUID avatar, float posHeight)
433 {
434 if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar))
435 {
436 return false;
437 }
438 else if (IsRestrictedFromLand(avatar))
439 {
440 return false;
441 }
442 return true;
443 }
444
424 public bool HasGroupAccess(UUID avatar) 445 public bool HasGroupAccess(UUID avatar)
425 { 446 {
426 if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) 447 if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
@@ -553,8 +574,8 @@ namespace OpenSim.Region.CoreModules.World.Land
553 try 574 try
554 { 575 {
555 over = 576 over =
556 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), 577 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
557 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); 578 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
558 } 579 }
559 catch (Exception) 580 catch (Exception)
560 { 581 {
@@ -701,15 +722,15 @@ namespace OpenSim.Region.CoreModules.World.Land
701 /// </summary> 722 /// </summary>
702 private void UpdateAABBAndAreaValues() 723 private void UpdateAABBAndAreaValues()
703 { 724 {
704 int min_x = 64; 725 int min_x = 10000;
705 int min_y = 64; 726 int min_y = 10000;
706 int max_x = 0; 727 int max_x = 0;
707 int max_y = 0; 728 int max_y = 0;
708 int tempArea = 0; 729 int tempArea = 0;
709 int x, y; 730 int x, y;
710 for (x = 0; x < 64; x++) 731 for (x = 0; x < LandBitmap.GetLength(0); x++)
711 { 732 {
712 for (y = 0; y < 64; y++) 733 for (y = 0; y < LandBitmap.GetLength(1); y++)
713 { 734 {
714 if (LandBitmap[x, y] == true) 735 if (LandBitmap[x, y] == true)
715 { 736 {
@@ -717,31 +738,31 @@ namespace OpenSim.Region.CoreModules.World.Land
717 if (min_y > y) min_y = y; 738 if (min_y > y) min_y = y;
718 if (max_x < x) max_x = x; 739 if (max_x < x) max_x = x;
719 if (max_y < y) max_y = y; 740 if (max_y < y) max_y = y;
720 tempArea += 16; //16sqm peice of land 741 tempArea += landUnit * landUnit; //16sqm peice of land
721 } 742 }
722 } 743 }
723 } 744 }
724 int tx = min_x * 4; 745 int tx = min_x * landUnit;
725 if (tx > ((int)Constants.RegionSize - 1)) 746 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
726 tx = ((int)Constants.RegionSize - 1); 747 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
727 int ty = min_y * 4; 748 int ty = min_y * landUnit;
728 if (ty > ((int)Constants.RegionSize - 1)) 749 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
729 ty = ((int)Constants.RegionSize - 1); 750 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
730 751
731 LandData.AABBMin = 752 LandData.AABBMin =
732 new Vector3( 753 new Vector3(
733 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 754 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
734 755
735 tx = max_x * 4; 756 tx = max_x * landUnit;
736 if (tx > ((int)Constants.RegionSize - 1)) 757 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
737 tx = ((int)Constants.RegionSize - 1); 758 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
738 ty = max_y * 4; 759 ty = max_y * landUnit;
739 if (ty > ((int)Constants.RegionSize - 1)) 760 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
740 ty = ((int)Constants.RegionSize - 1); 761 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
741 762
742 LandData.AABBMax 763 LandData.AABBMax
743 = new Vector3( 764 = new Vector3(
744 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 765 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
745 766
746 LandData.Area = tempArea; 767 LandData.Area = tempArea;
747 } 768 }
@@ -753,20 +774,12 @@ namespace OpenSim.Region.CoreModules.World.Land
753 /// <summary> 774 /// <summary>
754 /// Sets the land's bitmap manually 775 /// Sets the land's bitmap manually
755 /// </summary> 776 /// </summary>
756 /// <param name="bitmap">64x64 block representing where this land is on a map</param> 777 /// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
757 public void SetLandBitmap(bool[,] bitmap) 778 public void SetLandBitmap(bool[,] bitmap)
758 { 779 {
759 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) 780 LandBitmap = bitmap;
760 { 781 // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
761 //Throw an exception - The bitmap is not 64x64 782 ForceUpdateLandInfo();
762 //throw new Exception("Error: Invalid Parcel Bitmap");
763 }
764 else
765 {
766 //Valid: Lets set it
767 LandBitmap = bitmap;
768 ForceUpdateLandInfo();
769 }
770 } 783 }
771 784
772 /// <summary> 785 /// <summary>
@@ -780,15 +793,19 @@ namespace OpenSim.Region.CoreModules.World.Land
780 793
781 public bool[,] BasicFullRegionLandBitmap() 794 public bool[,] BasicFullRegionLandBitmap()
782 { 795 {
783 return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); 796 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
784 } 797 }
785 798
786 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) 799 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
787 { 800 {
788 bool[,] tempBitmap = new bool[64,64]; 801 // Empty bitmap for the whole region
802 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
789 tempBitmap.Initialize(); 803 tempBitmap.Initialize();
790 804
805 // Fill the bitmap square area specified by state and end
791 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); 806 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
807 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>",
808 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1));
792 return tempBitmap; 809 return tempBitmap;
793 } 810 }
794 811
@@ -805,24 +822,20 @@ namespace OpenSim.Region.CoreModules.World.Land
805 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, 822 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
806 bool set_value) 823 bool set_value)
807 { 824 {
808 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
809 {
810 //Throw an exception - The bitmap is not 64x64
811 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
812 }
813
814 int x, y; 825 int x, y;
815 for (y = 0; y < 64; y++) 826 for (y = 0; y < land_bitmap.GetLength(1); y++)
816 { 827 {
817 for (x = 0; x < 64; x++) 828 for (x = 0; x < land_bitmap.GetLength(0); x++)
818 { 829 {
819 if (x >= start_x / 4 && x < end_x / 4 830 if (x >= start_x / landUnit && x < end_x / landUnit
820 && y >= start_y / 4 && y < end_y / 4) 831 && y >= start_y / landUnit && y < end_y / landUnit)
821 { 832 {
822 land_bitmap[x, y] = set_value; 833 land_bitmap[x, y] = set_value;
823 } 834 }
824 } 835 }
825 } 836 }
837 // m_log.DebugFormat("{0} ModifyLandBitmapSquare. startXY=<{1},{2}>, endXY=<{3},{4}>, val={5}, landBitmapSize=<{6},{7}>",
838 // LogHeader, start_x, start_y, end_x, end_y, set_value, land_bitmap.GetLength(0), land_bitmap.GetLength(1));
826 return land_bitmap; 839 return land_bitmap;
827 } 840 }
828 841
@@ -834,21 +847,21 @@ namespace OpenSim.Region.CoreModules.World.Land
834 /// <returns></returns> 847 /// <returns></returns>
835 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) 848 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
836 { 849 {
837 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) 850 if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
851 || bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
852 || bitmap_add.Rank != 2
853 || bitmap_base.Rank != 2)
838 { 854 {
839 //Throw an exception - The bitmap is not 64x64 855 throw new Exception(
840 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); 856 String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
841 } 857 LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
842 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) 858 );
843 {
844 //Throw an exception - The bitmap is not 64x64
845 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
846 } 859 }
847 860
848 int x, y; 861 int x, y;
849 for (y = 0; y < 64; y++) 862 for (y = 0; y < bitmap_base.GetLength(1); y++)
850 { 863 {
851 for (x = 0; x < 64; x++) 864 for (x = 0; x < bitmap_add.GetLength(0); x++)
852 { 865 {
853 if (bitmap_add[x, y]) 866 if (bitmap_add[x, y])
854 { 867 {
@@ -865,13 +878,13 @@ namespace OpenSim.Region.CoreModules.World.Land
865 /// <returns></returns> 878 /// <returns></returns>
866 private byte[] ConvertLandBitmapToBytes() 879 private byte[] ConvertLandBitmapToBytes()
867 { 880 {
868 byte[] tempConvertArr = new byte[512]; 881 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
869 byte tempByte = 0; 882 byte tempByte = 0;
870 int x, y, i, byteNum = 0; 883 int byteNum = 0;
871 i = 0; 884 int i = 0;
872 for (y = 0; y < 64; y++) 885 for (int y = 0; y < LandBitmap.GetLength(1); y++)
873 { 886 {
874 for (x = 0; x < 64; x++) 887 for (int x = 0; x < LandBitmap.GetLength(0); x++)
875 { 888 {
876 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 889 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
877 if (i % 8 == 0) 890 if (i % 8 == 0)
@@ -883,30 +896,52 @@ namespace OpenSim.Region.CoreModules.World.Land
883 } 896 }
884 } 897 }
885 } 898 }
899 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>",
900 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
886 return tempConvertArr; 901 return tempConvertArr;
887 } 902 }
888 903
889 private bool[,] ConvertBytesToLandBitmap() 904 private bool[,] ConvertBytesToLandBitmap()
890 { 905 {
891 bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; 906 bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
892 tempConvertMap.Initialize(); 907 tempConvertMap.Initialize();
893 byte tempByte = 0; 908 byte tempByte = 0;
894 int x = 0, y = 0, i = 0, bitNum = 0; 909 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
895 for (i = 0; i < 512; i++) 910 int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
911 int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
912
913 if (bitmapLen == 512)
914 {
915 // Legacy bitmap being passed in. Use the legacy region size
916 // and only set the lower area of the larger region.
917 xLen = (int)(Constants.RegionSize / landUnit);
918 }
919 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
920
921 int x = 0, y = 0;
922 for (int i = 0; i < bitmapLen; i++)
896 { 923 {
897 tempByte = LandData.Bitmap[i]; 924 tempByte = LandData.Bitmap[i];
898 for (bitNum = 0; bitNum < 8; bitNum++) 925 for (int bitNum = 0; bitNum < 8; bitNum++)
899 { 926 {
900 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); 927 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
901 tempConvertMap[x, y] = bit; 928 try
929 {
930 tempConvertMap[x, y] = bit;
931 }
932 catch (Exception)
933 {
934 m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
935 }
902 x++; 936 x++;
903 if (x > 63) 937 if (x >= xLen)
904 { 938 {
905 x = 0; 939 x = 0;
906 y++; 940 y++;
907 } 941 }
908 } 942 }
909 } 943 }
944
910 return tempConvertMap; 945 return tempConvertMap;
911 } 946 }
912 947
@@ -1043,6 +1078,43 @@ namespace OpenSim.Region.CoreModules.World.Land
1043 1078
1044 #endregion 1079 #endregion
1045 1080
1081 #region Object Sales
1082
1083 public void SellLandObjects(UUID previousOwner)
1084 {
1085 // m_log.DebugFormat(
1086 // "[LAND OBJECT]: Request to sell objects in {0} from {1}", LandData.Name, previousOwner);
1087
1088 if (LandData.IsGroupOwned)
1089 return;
1090
1091 IBuySellModule m_BuySellModule = m_scene.RequestModuleInterface<IBuySellModule>();
1092 if (m_BuySellModule == null)
1093 {
1094 m_log.Error("[LAND OBJECT]: BuySellModule not found");
1095 return;
1096 }
1097
1098 ScenePresence sp;
1099 if (!m_scene.TryGetScenePresence(LandData.OwnerID, out sp))
1100 {
1101 m_log.Error("[LAND OBJECT]: New owner is not present in scene");
1102 return;
1103 }
1104
1105 lock (primsOverMe)
1106 {
1107 foreach (SceneObjectGroup obj in primsOverMe)
1108 {
1109 if (obj.OwnerID == previousOwner && obj.GroupID == UUID.Zero &&
1110 (obj.GetEffectivePermissions() & (uint)(OpenSim.Framework.PermissionMask.Transfer)) != 0)
1111 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0);
1112 }
1113 }
1114 }
1115
1116 #endregion
1117
1046 #region Object Returning 1118 #region Object Returning
1047 1119
1048 public void ReturnObject(SceneObjectGroup obj) 1120 public void ReturnObject(SceneObjectGroup obj)
@@ -1065,7 +1137,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1065 { 1137 {
1066 foreach (SceneObjectGroup obj in primsOverMe) 1138 foreach (SceneObjectGroup obj in primsOverMe)
1067 { 1139 {
1068 if (obj.OwnerID == m_landData.OwnerID) 1140 if (obj.OwnerID == LandData.OwnerID)
1069 { 1141 {
1070 if (!returns.ContainsKey(obj.OwnerID)) 1142 if (!returns.ContainsKey(obj.OwnerID))
1071 returns[obj.OwnerID] = 1143 returns[obj.OwnerID] =
@@ -1074,11 +1146,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1074 } 1146 }
1075 } 1147 }
1076 } 1148 }
1077 else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero) 1149 else if (type == (uint)ObjectReturnType.Group && LandData.GroupID != UUID.Zero)
1078 { 1150 {
1079 foreach (SceneObjectGroup obj in primsOverMe) 1151 foreach (SceneObjectGroup obj in primsOverMe)
1080 { 1152 {
1081 if (obj.GroupID == m_landData.GroupID) 1153 if (obj.GroupID == LandData.GroupID)
1082 { 1154 {
1083 if (!returns.ContainsKey(obj.OwnerID)) 1155 if (!returns.ContainsKey(obj.OwnerID))
1084 returns[obj.OwnerID] = 1156 returns[obj.OwnerID] =
@@ -1091,9 +1163,9 @@ namespace OpenSim.Region.CoreModules.World.Land
1091 { 1163 {
1092 foreach (SceneObjectGroup obj in primsOverMe) 1164 foreach (SceneObjectGroup obj in primsOverMe)
1093 { 1165 {
1094 if (obj.OwnerID != m_landData.OwnerID && 1166 if (obj.OwnerID != LandData.OwnerID &&
1095 (obj.GroupID != m_landData.GroupID || 1167 (obj.GroupID != LandData.GroupID ||
1096 m_landData.GroupID == UUID.Zero)) 1168 LandData.GroupID == UUID.Zero))
1097 { 1169 {
1098 if (!returns.ContainsKey(obj.OwnerID)) 1170 if (!returns.ContainsKey(obj.OwnerID))
1099 returns[obj.OwnerID] = 1171 returns[obj.OwnerID] =
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index f9cc0cf..9b51cc8 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -490,11 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Land
490 490
491 m_Scene.ForEachSOG(AddObject); 491 m_Scene.ForEachSOG(AddObject);
492 492
493 List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys); 493 lock (m_PrimCounts)
494 foreach (UUID k in primcountKeys)
495 { 494 {
496 if (!m_OwnerMap.ContainsKey(k)) 495 List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys);
497 m_PrimCounts.Remove(k); 496 foreach (UUID k in primcountKeys)
497 {
498 if (!m_OwnerMap.ContainsKey(k))
499 m_PrimCounts.Remove(k);
500 }
498 } 501 }
499 502
500 m_Tainted = false; 503 m_Tainted = false;
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
new file mode 100644
index 0000000..4ed67f3
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
@@ -0,0 +1,266 @@
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
28using System;
29using NUnit.Framework;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Tests.Common;
34
35namespace OpenSim.Region.CoreModules.World.Land.Tests
36{
37 public class LandManagementModuleTests : OpenSimTestCase
38 {
39 [Test]
40 public void TestAddLandObject()
41 {
42 TestHelpers.InMethod();
43// TestHelpers.EnableLogging();
44
45 UUID userId = TestHelpers.ParseTail(0x1);
46
47 LandManagementModule lmm = new LandManagementModule();
48 Scene scene = new SceneHelpers().SetupScene();
49 SceneHelpers.SetupSceneModules(scene, lmm);
50
51 ILandObject lo = new LandObject(userId, false, scene);
52 lo.LandData.Name = "lo1";
53 lo.SetLandBitmap(
54 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
55 lo = lmm.AddLandObject(lo);
56
57 // TODO: Should add asserts to check that land object was added properly.
58
59 // At the moment, this test just makes sure that we can't add a land object that overlaps the areas that
60 // the first still holds.
61 ILandObject lo2 = new LandObject(userId, false, scene);
62 lo2.SetLandBitmap(
63 lo2.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
64 lo2.LandData.Name = "lo2";
65 lo2 = lmm.AddLandObject(lo2);
66
67 {
68 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
69 Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID));
70 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID));
71 }
72
73 {
74 ILandObject loAtCoord = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1));
75 Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID));
76 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID));
77 }
78 }
79
80 /// <summary>
81 /// Test parcels on region when no land data exists to be loaded.
82 /// </summary>
83 [Test]
84 public void TestLoadWithNoParcels()
85 {
86 TestHelpers.InMethod();
87// TestHelpers.EnableLogging();
88
89 SceneHelpers sh = new SceneHelpers();
90 LandManagementModule lmm = new LandManagementModule();
91 Scene scene = sh.SetupScene();
92 SceneHelpers.SetupSceneModules(scene, lmm);
93
94 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID);
95
96 ILandObject loAtCoord1 = lmm.GetLandObject(0, 0);
97 Assert.That(loAtCoord1.LandData.LocalID, Is.Not.EqualTo(0));
98 Assert.That(loAtCoord1.LandData.GlobalID, Is.Not.EqualTo(UUID.Zero));
99
100 ILandObject loAtCoord2 = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1));
101 Assert.That(loAtCoord2.LandData.LocalID, Is.EqualTo(loAtCoord1.LandData.LocalID));
102 Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(loAtCoord1.LandData.GlobalID));
103 }
104
105 /// <summary>
106 /// Test parcels on region when a single parcel already exists but it does not cover the whole region.
107 /// </summary>
108 [Test]
109 public void TestLoadWithSinglePartialCoveringParcel()
110 {
111 TestHelpers.InMethod();
112// TestHelpers.EnableLogging();
113
114 UUID userId = TestHelpers.ParseTail(0x1);
115
116 SceneHelpers sh = new SceneHelpers();
117 LandManagementModule lmm = new LandManagementModule();
118 Scene scene = sh.SetupScene();
119 SceneHelpers.SetupSceneModules(scene, lmm);
120
121 ILandObject originalLo1 = new LandObject(userId, false, scene);
122 originalLo1.LandData.Name = "lo1";
123 originalLo1.SetLandBitmap(
124 originalLo1.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize / 2));
125
126 sh.SimDataService.StoreLandObject(originalLo1);
127
128 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID);
129
130 ILandObject loAtCoord1 = lmm.GetLandObject(0, 0);
131 Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name));
132 Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID));
133
134 ILandObject loAtCoord2 = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1));
135 Assert.That(loAtCoord2.LandData.LocalID, Is.EqualTo(loAtCoord1.LandData.LocalID));
136 Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(loAtCoord1.LandData.GlobalID));
137 }
138
139 /// <summary>
140 /// Test parcels on region when a single parcel already exists but it does not cover the whole region.
141 /// </summary>
142 [Test]
143 public void TestLoadWithMultiplePartialCoveringParcels()
144 {
145 TestHelpers.InMethod();
146// TestHelpers.EnableLogging();
147
148 UUID userId = TestHelpers.ParseTail(0x1);
149
150 SceneHelpers sh = new SceneHelpers();
151 LandManagementModule lmm = new LandManagementModule();
152 Scene scene = sh.SetupScene();
153 SceneHelpers.SetupSceneModules(scene, lmm);
154
155 ILandObject originalLo1 = new LandObject(userId, false, scene);
156 originalLo1.LandData.Name = "lo1";
157 originalLo1.SetLandBitmap(
158 originalLo1.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize / 2));
159
160 sh.SimDataService.StoreLandObject(originalLo1);
161
162 ILandObject originalLo2 = new LandObject(userId, false, scene);
163 originalLo2.LandData.Name = "lo2";
164 originalLo2.SetLandBitmap(
165 originalLo2.GetSquareLandBitmap(
166 0, (int)Constants.RegionSize / 2, (int)Constants.RegionSize, ((int)Constants.RegionSize / 4) * 3));
167
168 sh.SimDataService.StoreLandObject(originalLo2);
169
170 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID);
171
172 ILandObject loAtCoord1 = lmm.GetLandObject(0, 0);
173 Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name));
174 Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID));
175
176 ILandObject loAtCoord2
177 = lmm.GetLandObject((int)Constants.RegionSize - 1, (((int)Constants.RegionSize / 4) * 3) - 1);
178 Assert.That(loAtCoord2.LandData.Name, Is.EqualTo(originalLo2.LandData.Name));
179 Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID));
180
181 ILandObject loAtCoord3 = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1));
182 Assert.That(loAtCoord3.LandData.LocalID, Is.Not.EqualTo(loAtCoord1.LandData.LocalID));
183 Assert.That(loAtCoord3.LandData.LocalID, Is.Not.EqualTo(loAtCoord2.LandData.LocalID));
184 Assert.That(loAtCoord3.LandData.GlobalID, Is.Not.EqualTo(loAtCoord1.LandData.GlobalID));
185 Assert.That(loAtCoord3.LandData.GlobalID, Is.Not.EqualTo(loAtCoord2.LandData.GlobalID));
186 }
187
188 /// <summary>
189 /// Test parcels on region when whole region is parcelled (which should normally always be the case).
190 /// </summary>
191 [Test]
192 public void TestLoad()
193 {
194 TestHelpers.InMethod();
195// TestHelpers.EnableLogging();
196
197 UUID userId = TestHelpers.ParseTail(0x1);
198
199 SceneHelpers sh = new SceneHelpers();
200 LandManagementModule lmm = new LandManagementModule();
201 Scene scene = sh.SetupScene();
202 SceneHelpers.SetupSceneModules(scene, lmm);
203
204 ILandObject originalLo1 = new LandObject(userId, false, scene);
205 originalLo1.LandData.Name = "lo1";
206 originalLo1.SetLandBitmap(
207 originalLo1.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize / 2));
208
209 sh.SimDataService.StoreLandObject(originalLo1);
210
211 ILandObject originalLo2 = new LandObject(userId, false, scene);
212 originalLo2.LandData.Name = "lo2";
213 originalLo2.SetLandBitmap(
214 originalLo2.GetSquareLandBitmap(0, (int)Constants.RegionSize / 2, (int)Constants.RegionSize, (int)Constants.RegionSize));
215
216 sh.SimDataService.StoreLandObject(originalLo2);
217
218 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID);
219
220 {
221 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
222 Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo1.LandData.Name));
223 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID));
224 }
225
226 {
227 ILandObject loAtCoord = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1));
228 Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo2.LandData.Name));
229 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID));
230 }
231 }
232
233 [Test]
234 public void TestSubdivide()
235 {
236 TestHelpers.InMethod();
237// TestHelpers.EnableLogging();
238
239 UUID userId = TestHelpers.ParseTail(0x1);
240
241 LandManagementModule lmm = new LandManagementModule();
242 Scene scene = new SceneHelpers().SetupScene();
243 SceneHelpers.SetupSceneModules(scene, lmm);
244
245 ILandObject lo = new LandObject(userId, false, scene);
246 lo.LandData.Name = "lo1";
247 lo.SetLandBitmap(
248 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
249 lo = lmm.AddLandObject(lo);
250
251 lmm.Subdivide(0, 0, LandManagementModule.LandUnit, LandManagementModule.LandUnit, userId);
252
253 {
254 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
255 Assert.That(loAtCoord.LandData.LocalID, Is.Not.EqualTo(lo.LandData.LocalID));
256 Assert.That(loAtCoord.LandData.GlobalID, Is.Not.EqualTo(lo.LandData.GlobalID));
257 }
258
259 {
260 ILandObject loAtCoord = lmm.GetLandObject(LandManagementModule.LandUnit, LandManagementModule.LandUnit);
261 Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID));
262 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID));
263 }
264 }
265 }
266} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index 0945b43..949acb6 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -36,7 +36,6 @@ using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Tests.Common; 38using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock;
40 39
41namespace OpenSim.Region.CoreModules.World.Land.Tests 40namespace OpenSim.Region.CoreModules.World.Land.Tests
42{ 41{