diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 1333 |
1 files changed, 793 insertions, 540 deletions
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 92f6c1b..b1f5122 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | |||
@@ -41,6 +41,7 @@ using OpenSim.Framework; | |||
41 | using OpenSim.Framework.Capabilities; | 41 | using OpenSim.Framework.Capabilities; |
42 | using OpenSim.Framework.Console; | 42 | using OpenSim.Framework.Console; |
43 | using OpenSim.Framework.Servers; | 43 | using OpenSim.Framework.Servers; |
44 | using OpenSim.Framework.Monitoring; | ||
44 | using OpenSim.Framework.Servers.HttpServer; | 45 | using OpenSim.Framework.Servers.HttpServer; |
45 | using OpenSim.Region.Framework.Interfaces; | 46 | using OpenSim.Region.Framework.Interfaces; |
46 | using OpenSim.Region.Framework.Scenes; | 47 | using OpenSim.Region.Framework.Scenes; |
@@ -52,7 +53,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; | |||
52 | namespace OpenSim.Region.CoreModules.World.Land | 53 | namespace OpenSim.Region.CoreModules.World.Land |
53 | { | 54 | { |
54 | // used for caching | 55 | // used for caching |
55 | internal class ExtendedLandData | 56 | internal class ExtendedLandData |
56 | { | 57 | { |
57 | public LandData LandData; | 58 | public LandData LandData; |
58 | public ulong RegionHandle; | 59 | public ulong RegionHandle; |
@@ -69,9 +70,8 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
69 | /// <summary> | 70 | /// <summary> |
70 | /// Minimum land unit size in region co-ordinates. | 71 | /// Minimum land unit size in region co-ordinates. |
71 | /// </summary> | 72 | /// </summary> |
72 | public const int LandUnit = 4; | ||
73 | 73 | ||
74 | private static readonly string remoteParcelRequestPath = "0009/"; | 74 | public const int LandUnit = 4; |
75 | 75 | ||
76 | private LandChannel landChannel; | 76 | private LandChannel landChannel; |
77 | private Scene m_scene; | 77 | private Scene m_scene; |
@@ -89,20 +89,27 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
89 | /// <value> | 89 | /// <value> |
90 | /// Land objects keyed by local id | 90 | /// Land objects keyed by local id |
91 | /// </value> | 91 | /// </value> |
92 | private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>(); | 92 | // private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>(); |
93 | |||
94 | //ubit: removed the readonly so i can move it around | ||
95 | private Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>(); | ||
96 | private Dictionary<UUID, int> m_landUUIDList = new Dictionary<UUID, int>(); | ||
93 | 97 | ||
94 | private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; | 98 | private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; |
95 | 99 | ||
96 | private bool m_allowedForcefulBans = true; | 100 | private bool m_allowedForcefulBans = true; |
101 | private bool m_showBansLines = true; | ||
102 | private UUID DefaultGodParcelGroup; | ||
103 | private string DefaultGodParcelName; | ||
97 | 104 | ||
98 | // caches ExtendedLandData | 105 | // caches ExtendedLandData |
99 | private Cache parcelInfoCache; | 106 | private Cache parcelInfoCache; |
100 | 107 | ||
101 | |||
102 | /// <summary> | 108 | /// <summary> |
103 | /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. | 109 | /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. |
104 | /// </summary> | 110 | /// </summary> |
105 | private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>(); | 111 | private HashSet<UUID> forcedPosition = new HashSet<UUID>(); |
112 | |||
106 | 113 | ||
107 | // Enables limiting parcel layer info transmission when doing simple updates | 114 | // Enables limiting parcel layer info transmission when doing simple updates |
108 | private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } | 115 | private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } |
@@ -125,6 +132,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
125 | { | 132 | { |
126 | shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); | 133 | shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); |
127 | parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); | 134 | parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); |
135 | DefaultGodParcelGroup = new UUID(landManagementConfig.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString())); | ||
136 | DefaultGodParcelName = landManagementConfig.GetString("DefaultAdministratorParcelName", "Default Parcel"); | ||
137 | bool disablebans = landManagementConfig.GetBoolean("DisableParcelBans", !m_allowedForcefulBans); | ||
138 | m_allowedForcefulBans = !disablebans; | ||
139 | m_showBansLines = landManagementConfig.GetBoolean("ShowParcelBansLines", m_showBansLines); | ||
128 | } | 140 | } |
129 | } | 141 | } |
130 | 142 | ||
@@ -132,17 +144,20 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
132 | { | 144 | { |
133 | m_scene = scene; | 145 | m_scene = scene; |
134 | m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; | 146 | m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; |
147 | |||
135 | landChannel = new LandChannel(scene, this); | 148 | landChannel = new LandChannel(scene, this); |
136 | 149 | ||
137 | parcelInfoCache = new Cache(); | 150 | parcelInfoCache = new Cache(); |
138 | parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache | 151 | parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache |
139 | parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0); | 152 | parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0); |
140 | 153 | ||
154 | m_scene.EventManager.OnObjectAddedToScene += EventManagerOnParcelPrimCountAdd; | ||
141 | m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd; | 155 | m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd; |
156 | |||
157 | m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene; | ||
142 | m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate; | 158 | m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate; |
143 | m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene; | ||
144 | m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate; | 159 | m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate; |
145 | 160 | ||
146 | m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel; | 161 | m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel; |
147 | m_scene.EventManager.OnClientMovement += EventManagerOnClientMovement; | 162 | m_scene.EventManager.OnClientMovement += EventManagerOnClientMovement; |
148 | m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy; | 163 | m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy; |
@@ -152,14 +167,14 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
152 | m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement; | 167 | m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement; |
153 | m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage; | 168 | m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage; |
154 | m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; | 169 | m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; |
155 | m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; | 170 | m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; |
156 | m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; | 171 | m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; |
157 | 172 | ||
158 | lock (m_scene) | 173 | lock (m_scene) |
159 | { | 174 | { |
160 | m_scene.LandChannel = (ILandChannel)landChannel; | 175 | m_scene.LandChannel = (ILandChannel)landChannel; |
161 | } | 176 | } |
162 | 177 | ||
163 | RegisterCommands(); | 178 | RegisterCommands(); |
164 | } | 179 | } |
165 | 180 | ||
@@ -172,8 +187,8 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
172 | } | 187 | } |
173 | 188 | ||
174 | public void RemoveRegion(Scene scene) | 189 | public void RemoveRegion(Scene scene) |
175 | { | 190 | { |
176 | // TODO: Release event manager listeners here | 191 | // TODO: Release event manager listeners here |
177 | } | 192 | } |
178 | 193 | ||
179 | // private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason) | 194 | // private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason) |
@@ -181,7 +196,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
181 | // ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y); | 196 | // ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y); |
182 | // reason = "You are not allowed to enter this sim."; | 197 | // reason = "You are not allowed to enter this sim."; |
183 | // return nearestParcel != null; | 198 | // return nearestParcel != null; |
184 | // } | 199 | // } |
185 | 200 | ||
186 | void EventManagerOnNewClient(IClientAPI client) | 201 | void EventManagerOnNewClient(IClientAPI client) |
187 | { | 202 | { |
@@ -199,18 +214,10 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
199 | client.OnParcelReclaim += ClientOnParcelReclaim; | 214 | client.OnParcelReclaim += ClientOnParcelReclaim; |
200 | client.OnParcelInfoRequest += ClientOnParcelInfoRequest; | 215 | client.OnParcelInfoRequest += ClientOnParcelInfoRequest; |
201 | client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; | 216 | client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; |
202 | client.OnPreAgentUpdate += ClientOnPreAgentUpdate; | ||
203 | client.OnParcelEjectUser += ClientOnParcelEjectUser; | 217 | client.OnParcelEjectUser += ClientOnParcelEjectUser; |
204 | client.OnParcelFreezeUser += ClientOnParcelFreezeUser; | 218 | client.OnParcelFreezeUser += ClientOnParcelFreezeUser; |
205 | client.OnSetStartLocationRequest += ClientOnSetHome; | 219 | client.OnSetStartLocationRequest += ClientOnSetHome; |
206 | 220 | client.OnParcelBuyPass += ClientParcelBuyPass; | |
207 | |||
208 | EntityBase presenceEntity; | ||
209 | if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) | ||
210 | { | ||
211 | SendLandUpdate((ScenePresence)presenceEntity, true); | ||
212 | SendParcelOverlay(client); | ||
213 | } | ||
214 | } | 221 | } |
215 | 222 | ||
216 | public void EventMakeChildAgent(ScenePresence avatar) | 223 | public void EventMakeChildAgent(ScenePresence avatar) |
@@ -218,52 +225,6 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
218 | avatar.currentParcelUUID = UUID.Zero; | 225 | avatar.currentParcelUUID = UUID.Zero; |
219 | } | 226 | } |
220 | 227 | ||
221 | void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | ||
222 | { | ||
223 | //If we are forcing a position for them to go | ||
224 | if (forcedPosition.ContainsKey(remoteClient.AgentId)) | ||
225 | { | ||
226 | ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId); | ||
227 | |||
228 | //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND | ||
229 | //When the avatar walks into a ban line on the ground, it prevents getting stuck | ||
230 | agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; | ||
231 | |||
232 | //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines | ||
233 | if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2) | ||
234 | { | ||
235 | // m_log.DebugFormat( | ||
236 | // "[LAND MANAGEMENT MODULE]: Stopping force position of {0} because {1} is close enough to {2}", | ||
237 | // clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]); | ||
238 | |||
239 | forcedPosition.Remove(remoteClient.AgentId); | ||
240 | } | ||
241 | //if we are far away, teleport | ||
242 | else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3) | ||
243 | { | ||
244 | Vector3 forcePosition = forcedPosition[remoteClient.AgentId]; | ||
245 | // m_log.DebugFormat( | ||
246 | // "[LAND MANAGEMENT MODULE]: Teleporting out {0} because {1} is too far from avatar position {2}", | ||
247 | // clientAvatar.Name, clientAvatar.AbsolutePosition, forcePosition); | ||
248 | |||
249 | m_scene.RequestTeleportLocation(remoteClient, m_scene.RegionInfo.RegionHandle, | ||
250 | forcePosition, clientAvatar.Lookat, (uint)Constants.TeleportFlags.ForceRedirect); | ||
251 | |||
252 | forcedPosition.Remove(remoteClient.AgentId); | ||
253 | } | ||
254 | else | ||
255 | { | ||
256 | // m_log.DebugFormat( | ||
257 | // "[LAND MANAGEMENT MODULE]: Forcing {0} from {1} to {2}", | ||
258 | // clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]); | ||
259 | |||
260 | //Forces them toward the forced position we want if they aren't there yet | ||
261 | agentData.UseClientAgentPosition = true; | ||
262 | agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId]; | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | public void Close() | 228 | public void Close() |
268 | { | 229 | { |
269 | } | 230 | } |
@@ -291,7 +252,10 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
291 | lock (m_landList) | 252 | lock (m_landList) |
292 | { | 253 | { |
293 | if (m_landList.TryGetValue(local_id, out land)) | 254 | if (m_landList.TryGetValue(local_id, out land)) |
255 | { | ||
294 | land.LandData = newData; | 256 | land.LandData = newData; |
257 | m_landUUIDList[newData.GlobalID] = local_id; | ||
258 | } | ||
295 | } | 259 | } |
296 | 260 | ||
297 | if (land != null) | 261 | if (land != null) |
@@ -312,28 +276,35 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
312 | //Remove all the land objects in the sim and add a blank, full sim land object set to public | 276 | //Remove all the land objects in the sim and add a blank, full sim land object set to public |
313 | lock (m_landList) | 277 | lock (m_landList) |
314 | { | 278 | { |
279 | foreach(ILandObject parcel in m_landList.Values) | ||
280 | parcel.Clear(); | ||
281 | |||
315 | m_landList.Clear(); | 282 | m_landList.Clear(); |
283 | m_landUUIDList.Clear(); | ||
316 | m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; | 284 | m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; |
285 | |||
317 | m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; | 286 | m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; |
318 | } | 287 | } |
319 | } | 288 | } |
320 | 289 | ||
321 | /// <summary> | 290 | /// <summary> |
322 | /// Create a default parcel that spans the entire region and is owned by the estate owner. | 291 | /// Create a default parcel that spans the entire region and is owned by the estate owner. |
323 | /// </summary> | 292 | /// </summary> |
324 | /// <returns>The parcel created.</returns> | 293 | /// <returns>The parcel created.</returns> |
325 | protected ILandObject CreateDefaultParcel() | 294 | protected ILandObject CreateDefaultParcel() |
326 | { | 295 | { |
327 | m_log.DebugFormat( | 296 | m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName); |
328 | "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); | 297 | |
329 | 298 | ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); | |
330 | ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); | 299 | |
331 | fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, | 300 | fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, |
332 | (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY)); | 301 | (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY)); |
333 | fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; | 302 | LandData ldata = fullSimParcel.LandData; |
334 | fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); | 303 | ldata.SimwideArea = ldata.Area; |
335 | 304 | ldata.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; | |
336 | return AddLandObject(fullSimParcel); | 305 | ldata.ClaimDate = Util.UnixTimeSinceEpoch(); |
306 | |||
307 | return AddLandObject(fullSimParcel); | ||
337 | } | 308 | } |
338 | 309 | ||
339 | public List<ILandObject> AllParcels() | 310 | public List<ILandObject> AllParcels() |
@@ -347,9 +318,9 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
347 | public List<ILandObject> ParcelsNearPoint(Vector3 position) | 318 | public List<ILandObject> ParcelsNearPoint(Vector3 position) |
348 | { | 319 | { |
349 | List<ILandObject> parcelsNear = new List<ILandObject>(); | 320 | List<ILandObject> parcelsNear = new List<ILandObject>(); |
350 | for (int x = -4; x <= 4; x += 4) | 321 | for (int x = -8; x <= 8; x += 4) |
351 | { | 322 | { |
352 | for (int y = -4; y <= 4; y += 4) | 323 | for (int y = -8; y <= 8; y += 4) |
353 | { | 324 | { |
354 | ILandObject check = GetLandObject(position.X + x, position.Y + y); | 325 | ILandObject check = GetLandObject(position.X + x, position.Y + y); |
355 | if (check != null) | 326 | if (check != null) |
@@ -365,33 +336,99 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
365 | return parcelsNear; | 336 | return parcelsNear; |
366 | } | 337 | } |
367 | 338 | ||
368 | public void SendYouAreBannedNotice(ScenePresence avatar) | 339 | // checks and enforces bans or restrictions |
340 | // returns true if enforced | ||
341 | public bool EnforceBans(ILandObject land, ScenePresence avatar) | ||
369 | { | 342 | { |
370 | if (AllowedForcefulBans) | 343 | Vector3 agentpos = avatar.AbsolutePosition; |
344 | float h = m_scene.GetGroundHeight(agentpos.X, agentpos.Y) + LandChannel.BAN_LINE_SAFETY_HEIGHT; | ||
345 | float zdif = avatar.AbsolutePosition.Z - h; | ||
346 | if (zdif > 0 ) | ||
347 | { | ||
348 | forcedPosition.Remove(avatar.UUID); | ||
349 | avatar.lastKnownAllowedPosition = agentpos; | ||
350 | return false; | ||
351 | } | ||
352 | |||
353 | bool ban = false; | ||
354 | string reason = ""; | ||
355 | if (land.IsRestrictedFromLand(avatar.UUID)) | ||
371 | { | 356 | { |
372 | avatar.ControllingClient.SendAlertMessage( | 357 | reason = "You do not have access to the parcel"; |
373 | "You are not allowed on this parcel because you are banned. Please go away."); | 358 | ban = true; |
359 | } | ||
360 | |||
361 | if (land.IsBannedFromLand(avatar.UUID)) | ||
362 | { | ||
363 | if ( m_allowedForcefulBans) | ||
364 | { | ||
365 | reason ="You are banned from parcel"; | ||
366 | ban = true; | ||
367 | } | ||
368 | else if(!ban) | ||
369 | { | ||
370 | if (forcedPosition.Contains(avatar.UUID)) | ||
371 | avatar.ControllingClient.SendAlertMessage("You are banned from parcel, please leave by your own will"); | ||
372 | forcedPosition.Remove(avatar.UUID); | ||
373 | avatar.lastKnownAllowedPosition = agentpos; | ||
374 | return false; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | if(ban) | ||
379 | { | ||
380 | if (!forcedPosition.Contains(avatar.UUID)) | ||
381 | avatar.ControllingClient.SendAlertMessage(reason); | ||
382 | |||
383 | if(zdif > -4f) | ||
384 | { | ||
385 | |||
386 | agentpos.Z = h + 4.0f; | ||
387 | ForceAvatarToPosition(avatar, agentpos); | ||
388 | return true; | ||
389 | } | ||
390 | |||
391 | if (land.ContainsPoint((int)avatar.lastKnownAllowedPosition.X, | ||
392 | (int) avatar.lastKnownAllowedPosition.Y)) | ||
393 | { | ||
394 | Vector3? pos = m_scene.GetNearestAllowedPosition(avatar); | ||
395 | if (pos == null) | ||
396 | { | ||
397 | forcedPosition.Remove(avatar.UUID); | ||
398 | m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient); | ||
399 | } | ||
400 | else | ||
401 | ForceAvatarToPosition(avatar, (Vector3)pos); | ||
402 | } | ||
403 | else | ||
404 | { | ||
405 | ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition); | ||
406 | } | ||
407 | return true; | ||
374 | } | 408 | } |
375 | else | 409 | else |
376 | { | 410 | { |
377 | avatar.ControllingClient.SendAlertMessage( | 411 | forcedPosition.Remove(avatar.UUID); |
378 | "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim!"); | 412 | avatar.lastKnownAllowedPosition = agentpos; |
413 | return false; | ||
379 | } | 414 | } |
380 | } | 415 | } |
381 | 416 | ||
382 | private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) | 417 | private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) |
383 | { | 418 | { |
384 | if (m_scene.Permissions.IsGod(avatar.UUID)) return; | 419 | if (m_scene.Permissions.IsGod(avatar.UUID)) return; |
385 | if (position.HasValue) | ||
386 | { | ||
387 | forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; | ||
388 | } | ||
389 | } | ||
390 | 420 | ||
391 | public void SendYouAreRestrictedNotice(ScenePresence avatar) | 421 | if (!position.HasValue) |
392 | { | 422 | return; |
393 | avatar.ControllingClient.SendAlertMessage( | 423 | |
394 | "You are not allowed on this parcel because the land owner has restricted access."); | 424 | if(avatar.MovingToTarget) |
425 | avatar.ResetMoveToTarget(); | ||
426 | avatar.AbsolutePosition = position.Value; | ||
427 | avatar.lastKnownAllowedPosition = position.Value; | ||
428 | avatar.Velocity = Vector3.Zero; | ||
429 | if(avatar.IsSatOnObject) | ||
430 | avatar.StandUp(); | ||
431 | forcedPosition.Add(avatar.UUID); | ||
395 | } | 432 | } |
396 | 433 | ||
397 | public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID) | 434 | public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID) |
@@ -404,29 +441,12 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
404 | parcelAvatarIsEntering = m_landList[localLandID]; | 441 | parcelAvatarIsEntering = m_landList[localLandID]; |
405 | } | 442 | } |
406 | 443 | ||
407 | if (parcelAvatarIsEntering != null) | 444 | if (parcelAvatarIsEntering != null && |
445 | avatar.currentParcelUUID != parcelAvatarIsEntering.LandData.GlobalID) | ||
408 | { | 446 | { |
409 | if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) | 447 | SendLandUpdate(avatar, parcelAvatarIsEntering); |
410 | { | 448 | avatar.currentParcelUUID = parcelAvatarIsEntering.LandData.GlobalID; |
411 | if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) | 449 | EnforceBans(parcelAvatarIsEntering, avatar); |
412 | { | ||
413 | SendYouAreBannedNotice(avatar); | ||
414 | ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar)); | ||
415 | } | ||
416 | else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID)) | ||
417 | { | ||
418 | SendYouAreRestrictedNotice(avatar); | ||
419 | ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar)); | ||
420 | } | ||
421 | else | ||
422 | { | ||
423 | avatar.sentMessageAboutRestrictedParcelFlyingDown = true; | ||
424 | } | ||
425 | } | ||
426 | else | ||
427 | { | ||
428 | avatar.sentMessageAboutRestrictedParcelFlyingDown = true; | ||
429 | } | ||
430 | } | 450 | } |
431 | } | 451 | } |
432 | } | 452 | } |
@@ -434,7 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
434 | public void SendOutNearestBanLine(IClientAPI client) | 454 | public void SendOutNearestBanLine(IClientAPI client) |
435 | { | 455 | { |
436 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 456 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
437 | if (sp == null || sp.IsChildAgent) | 457 | if (sp == null || sp.IsDeleted) |
438 | return; | 458 | return; |
439 | 459 | ||
440 | List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition); | 460 | List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition); |
@@ -454,98 +474,180 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
454 | return; | 474 | return; |
455 | } | 475 | } |
456 | 476 | ||
457 | public void SendLandUpdate(ScenePresence avatar, bool force) | 477 | public void sendClientInitialLandInfo(IClientAPI remoteClient) |
458 | { | 478 | { |
459 | ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), | 479 | ScenePresence avatar; |
460 | (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); | ||
461 | 480 | ||
462 | if (over != null) | 481 | if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out avatar)) |
482 | return; | ||
483 | |||
484 | if (!avatar.IsChildAgent) | ||
463 | { | 485 | { |
464 | if (force) | 486 | ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); |
465 | { | 487 | if (over == null) |
466 | if (!avatar.IsChildAgent) | 488 | return; |
467 | { | ||
468 | over.SendLandUpdateToClient(avatar.ControllingClient); | ||
469 | m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, | ||
470 | m_scene.RegionInfo.RegionID); | ||
471 | } | ||
472 | } | ||
473 | 489 | ||
474 | if (avatar.currentParcelUUID != over.LandData.GlobalID) | 490 | avatar.currentParcelUUID = over.LandData.GlobalID; |
475 | { | 491 | over.SendLandUpdateToClient(avatar.ControllingClient); |
476 | if (!avatar.IsChildAgent) | ||
477 | { | ||
478 | over.SendLandUpdateToClient(avatar.ControllingClient); | ||
479 | avatar.currentParcelUUID = over.LandData.GlobalID; | ||
480 | m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, | ||
481 | m_scene.RegionInfo.RegionID); | ||
482 | } | ||
483 | } | ||
484 | } | 492 | } |
493 | SendParcelOverlay(remoteClient); | ||
485 | } | 494 | } |
486 | 495 | ||
487 | public void SendLandUpdate(ScenePresence avatar) | 496 | public void SendLandUpdate(ScenePresence avatar, ILandObject over) |
488 | { | 497 | { |
489 | SendLandUpdate(avatar, false); | 498 | if (avatar.IsChildAgent) |
490 | } | 499 | return; |
491 | 500 | ||
492 | public void EventManagerOnSignificantClientMovement(ScenePresence clientAvatar) | 501 | if (over != null) |
493 | { | ||
494 | SendLandUpdate(clientAvatar); | ||
495 | SendOutNearestBanLine(clientAvatar.ControllingClient); | ||
496 | ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); | ||
497 | if (parcel != null) | ||
498 | { | 502 | { |
499 | if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && | 503 | over.SendLandUpdateToClient(avatar.ControllingClient); |
500 | clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) | 504 | // sl doesnt seem to send this now, as it used 2 |
501 | { | 505 | // SendParcelOverlay(avatar.ControllingClient); |
502 | EventManagerOnAvatarEnteringNewParcel(clientAvatar, parcel.LandData.LocalID, | ||
503 | m_scene.RegionInfo.RegionID); | ||
504 | //They are going under the safety line! | ||
505 | if (!parcel.IsBannedFromLand(clientAvatar.UUID)) | ||
506 | { | ||
507 | clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false; | ||
508 | } | ||
509 | } | ||
510 | else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && | ||
511 | parcel.IsBannedFromLand(clientAvatar.UUID)) | ||
512 | { | ||
513 | //once we've sent the message once, keep going toward the target until we are done | ||
514 | if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId)) | ||
515 | { | ||
516 | SendYouAreBannedNotice(clientAvatar); | ||
517 | ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar)); | ||
518 | } | ||
519 | } | ||
520 | else if (parcel.IsRestrictedFromLand(clientAvatar.UUID)) | ||
521 | { | ||
522 | //once we've sent the message once, keep going toward the target until we are done | ||
523 | if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId)) | ||
524 | { | ||
525 | SendYouAreRestrictedNotice(clientAvatar); | ||
526 | ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar)); | ||
527 | } | ||
528 | } | ||
529 | else | ||
530 | { | ||
531 | //when we are finally in a safe place, lets release the forced position lock | ||
532 | forcedPosition.Remove(clientAvatar.ControllingClient.AgentId); | ||
533 | } | ||
534 | } | 506 | } |
535 | } | 507 | } |
536 | 508 | ||
509 | public void EventManagerOnSignificantClientMovement(ScenePresence avatar) | ||
510 | { | ||
511 | if (avatar.IsChildAgent) | ||
512 | return; | ||
513 | |||
514 | if ( m_allowedForcefulBans && m_showBansLines) | ||
515 | SendOutNearestBanLine(avatar.ControllingClient); | ||
516 | } | ||
517 | |||
537 | /// <summary> | 518 | /// <summary> |
538 | /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. | 519 | /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. |
539 | /// </summary> | 520 | /// </summary> |
540 | /// <param name="avatar"></param> | 521 | /// <param name="avatar"></param> |
541 | public void EventManagerOnClientMovement(ScenePresence avatar) | 522 | public void EventManagerOnClientMovement(ScenePresence avatar) |
542 | { | 523 | { |
524 | if (avatar.IsChildAgent) | ||
525 | return; | ||
526 | |||
543 | Vector3 pos = avatar.AbsolutePosition; | 527 | Vector3 pos = avatar.AbsolutePosition; |
544 | ILandObject over = GetLandObject(pos.X, pos.Y); | 528 | ILandObject over = GetLandObject(pos.X, pos.Y); |
545 | if (over != null) | 529 | if (over != null) |
546 | { | 530 | { |
547 | if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || pos.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)) | 531 | EnforceBans(over, avatar); |
548 | avatar.lastKnownAllowedPosition = pos; | 532 | pos = avatar.AbsolutePosition; |
533 | ILandObject newover = GetLandObject(pos.X, pos.Y); | ||
534 | if(over != newover || avatar.currentParcelUUID != newover.LandData.GlobalID) | ||
535 | { | ||
536 | m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, | ||
537 | newover.LandData.LocalID, m_scene.RegionInfo.RegionID); | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
542 | public void ClientParcelBuyPass(IClientAPI remote_client, UUID targetID, int landLocalID) | ||
543 | { | ||
544 | ILandObject land; | ||
545 | lock (m_landList) | ||
546 | { | ||
547 | m_landList.TryGetValue(landLocalID, out land); | ||
548 | } | ||
549 | // trivial checks | ||
550 | if(land == null) | ||
551 | return; | ||
552 | |||
553 | LandData ldata = land.LandData; | ||
554 | |||
555 | if(ldata == null) | ||
556 | return; | ||
557 | |||
558 | if(ldata.OwnerID == targetID) | ||
559 | return; | ||
560 | |||
561 | if(ldata.PassHours == 0) | ||
562 | return; | ||
563 | |||
564 | // don't allow passes on group owned until we can give money to groups | ||
565 | if(ldata.IsGroupOwned) | ||
566 | { | ||
567 | remote_client.SendAgentAlertMessage("pass to group owned parcel not suported", false); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | if((ldata.Flags & (uint)ParcelFlags.UsePassList) == 0) | ||
572 | return; | ||
573 | |||
574 | int cost = ldata.PassPrice; | ||
575 | |||
576 | int idx = land.LandData.ParcelAccessList.FindIndex( | ||
577 | delegate(LandAccessEntry e) | ||
578 | { | ||
579 | if (e.AgentID == targetID && e.Flags == AccessList.Access) | ||
580 | return true; | ||
581 | return false; | ||
582 | }); | ||
583 | int now = Util.UnixTimeSinceEpoch(); | ||
584 | int expires = (int)(3600.0 * ldata.PassHours + 0.5f); | ||
585 | int currenttime = -1; | ||
586 | if (idx != -1) | ||
587 | { | ||
588 | if(ldata.ParcelAccessList[idx].Expires == 0) | ||
589 | { | ||
590 | remote_client.SendAgentAlertMessage("You already have access to parcel", false); | ||
591 | return; | ||
592 | } | ||
593 | |||
594 | currenttime = ldata.ParcelAccessList[idx].Expires - now; | ||
595 | if(currenttime > (int)(0.25f * expires + 0.5f)) | ||
596 | { | ||
597 | if(currenttime > 3600) | ||
598 | remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.###} hours", | ||
599 | currenttime/3600f), false); | ||
600 | else if(currenttime > 60) | ||
601 | remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.##} minutes", | ||
602 | currenttime/60f), false); | ||
603 | else | ||
604 | remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.#} seconds", | ||
605 | currenttime), false); | ||
606 | return; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | LandAccessEntry entry = new LandAccessEntry(); | ||
611 | entry.AgentID = targetID; | ||
612 | entry.Flags = AccessList.Access; | ||
613 | entry.Expires = now + expires; | ||
614 | if(currenttime > 0) | ||
615 | entry.Expires += currenttime; | ||
616 | IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>(); | ||
617 | if(cost != 0 && mm != null) | ||
618 | { | ||
619 | WorkManager.RunInThreadPool( | ||
620 | delegate | ||
621 | { | ||
622 | string regionName = m_scene.RegionInfo.RegionName; | ||
623 | |||
624 | if (!mm.AmountCovered(remote_client.AgentId, cost)) | ||
625 | { | ||
626 | remote_client.SendAgentAlertMessage(String.Format("Insufficient funds in region '{0}' money system", regionName), true); | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | string payDescription = String.Format("Parcel '{0}' at region '{1} {2:0.###} hours access pass", ldata.Name, regionName, ldata.PassHours); | ||
631 | |||
632 | if(!mm.MoveMoney(remote_client.AgentId, ldata.OwnerID, cost,MoneyTransactionType.LandPassSale, payDescription)) | ||
633 | { | ||
634 | remote_client.SendAgentAlertMessage("Sorry pass payment processing failed, please try again later", true); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | if (idx != -1) | ||
639 | ldata.ParcelAccessList.RemoveAt(idx); | ||
640 | ldata.ParcelAccessList.Add(entry); | ||
641 | m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | ||
642 | return; | ||
643 | }, null, "ParcelBuyPass"); | ||
644 | } | ||
645 | else | ||
646 | { | ||
647 | if (idx != -1) | ||
648 | ldata.ParcelAccessList.RemoveAt(idx); | ||
649 | ldata.ParcelAccessList.Add(entry); | ||
650 | m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | ||
549 | } | 651 | } |
550 | } | 652 | } |
551 | 653 | ||
@@ -589,7 +691,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
589 | requiredPowers = GroupPowers.LandManageBanned; | 691 | requiredPowers = GroupPowers.LandManageBanned; |
590 | 692 | ||
591 | if (m_scene.Permissions.CanEditParcelProperties(agentID, | 693 | if (m_scene.Permissions.CanEditParcelProperties(agentID, |
592 | land, requiredPowers)) | 694 | land, requiredPowers, false)) |
593 | { | 695 | { |
594 | land.UpdateAccessList(flags, transactionID, sequenceID, | 696 | land.UpdateAccessList(flags, transactionID, sequenceID, |
595 | sections, entries, remote_client); | 697 | sections, entries, remote_client); |
@@ -605,13 +707,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
605 | /// Adds a land object to the stored list and adds them to the landIDList to what they own | 707 | /// Adds a land object to the stored list and adds them to the landIDList to what they own |
606 | /// </summary> | 708 | /// </summary> |
607 | /// <param name="new_land"> | 709 | /// <param name="new_land"> |
608 | /// The land object being added. | 710 | /// The land object being added. |
609 | /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted. | 711 | /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted. |
610 | /// </param> | 712 | /// </param> |
611 | public ILandObject AddLandObject(ILandObject land) | 713 | public ILandObject AddLandObject(ILandObject new_land) |
612 | { | 714 | { |
613 | ILandObject new_land = land.Copy(); | ||
614 | |||
615 | // Only now can we add the prim counts to the land object - we rely on the global ID which is generated | 715 | // Only now can we add the prim counts to the land object - we rely on the global ID which is generated |
616 | // as a random UUID inside LandData initialization | 716 | // as a random UUID inside LandData initialization |
617 | if (m_primCountModule != null) | 717 | if (m_primCountModule != null) |
@@ -623,18 +723,15 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
623 | new_land.LandData.LocalID = newLandLocalID; | 723 | new_land.LandData.LocalID = newLandLocalID; |
624 | 724 | ||
625 | bool[,] landBitmap = new_land.GetLandBitmap(); | 725 | bool[,] landBitmap = new_land.GetLandBitmap(); |
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)) | 726 | if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1)) |
630 | { | 727 | { |
631 | // Going to variable sized regions can cause mismatches | 728 | // 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})", | 729 | 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) ); | 730 | LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1)); |
634 | } | 731 | } |
635 | else | 732 | else |
636 | { | 733 | { |
637 | // If other land objects still believe that they occupy any parts of the same space, | 734 | // If other land objects still believe that they occupy any parts of the same space, |
638 | // then do not allow the add to proceed. | 735 | // then do not allow the add to proceed. |
639 | for (int x = 0; x < landBitmap.GetLength(0); x++) | 736 | for (int x = 0; x < landBitmap.GetLength(0); x++) |
640 | { | 737 | { |
@@ -652,7 +749,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
652 | { | 749 | { |
653 | m_log.ErrorFormat( | 750 | 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}", | 751 | "{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, | 752 | LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y, |
656 | lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name); | 753 | lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name); |
657 | 754 | ||
658 | return null; | 755 | return null; |
@@ -668,10 +765,10 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
668 | { | 765 | { |
669 | if (landBitmap[x, y]) | 766 | if (landBitmap[x, y]) |
670 | { | 767 | { |
671 | // m_log.DebugFormat( | 768 | // m_log.DebugFormat( |
672 | // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", | 769 | // "[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); | 770 | // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); |
674 | 771 | ||
675 | m_landIDList[x, y] = newLandLocalID; | 772 | m_landIDList[x, y] = newLandLocalID; |
676 | } | 773 | } |
677 | } | 774 | } |
@@ -679,6 +776,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
679 | } | 776 | } |
680 | 777 | ||
681 | m_landList.Add(newLandLocalID, new_land); | 778 | m_landList.Add(newLandLocalID, new_land); |
779 | m_landUUIDList[new_land.LandData.GlobalID] = newLandLocalID; | ||
682 | m_lastLandLocalID++; | 780 | m_lastLandLocalID++; |
683 | } | 781 | } |
684 | 782 | ||
@@ -695,6 +793,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
695 | public void removeLandObject(int local_id) | 793 | public void removeLandObject(int local_id) |
696 | { | 794 | { |
697 | ILandObject land; | 795 | ILandObject land; |
796 | UUID landGlobalID = UUID.Zero; | ||
698 | lock (m_landList) | 797 | lock (m_landList) |
699 | { | 798 | { |
700 | for (int x = 0; x < m_landIDList.GetLength(0); x++) | 799 | for (int x = 0; x < m_landIDList.GetLength(0); x++) |
@@ -713,37 +812,47 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
713 | 812 | ||
714 | land = m_landList[local_id]; | 813 | land = m_landList[local_id]; |
715 | m_landList.Remove(local_id); | 814 | m_landList.Remove(local_id); |
815 | if(land != null && land.LandData != null) | ||
816 | { | ||
817 | landGlobalID = land.LandData.GlobalID; | ||
818 | m_landUUIDList.Remove(landGlobalID); | ||
819 | } | ||
716 | } | 820 | } |
717 | 821 | ||
718 | m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID); | 822 | if(landGlobalID != UUID.Zero) |
823 | { | ||
824 | m_scene.EventManager.TriggerLandObjectRemoved(landGlobalID); | ||
825 | land.Clear(); | ||
826 | } | ||
719 | } | 827 | } |
720 | 828 | ||
721 | /// <summary> | 829 | /// <summary> |
722 | /// Clear the scene of all parcels | 830 | /// Clear the scene of all parcels |
723 | /// </summary> | 831 | /// </summary> |
724 | public void Clear(bool setupDefaultParcel) | 832 | public void Clear(bool setupDefaultParcel) |
725 | { | 833 | { |
726 | List<ILandObject> parcels; | 834 | Dictionary<int, ILandObject> landworkList; |
835 | // move to work pointer since we are deleting it all | ||
727 | lock (m_landList) | 836 | lock (m_landList) |
728 | { | 837 | { |
729 | parcels = new List<ILandObject>(m_landList.Values); | 838 | landworkList = m_landList; |
839 | m_landList = new Dictionary<int, ILandObject>(); | ||
730 | } | 840 | } |
731 | 841 | ||
732 | foreach (ILandObject lo in parcels) | 842 | // this 2 methods have locks (now) |
843 | ResetSimLandObjects(); | ||
844 | |||
845 | if (setupDefaultParcel) | ||
846 | CreateDefaultParcel(); | ||
847 | |||
848 | // fire outside events unlocked | ||
849 | foreach (ILandObject lo in landworkList.Values) | ||
733 | { | 850 | { |
734 | //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); | 851 | //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); |
735 | m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); | 852 | m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); |
736 | } | 853 | } |
854 | landworkList.Clear(); | ||
737 | 855 | ||
738 | lock (m_landList) | ||
739 | { | ||
740 | m_landList.Clear(); | ||
741 | |||
742 | ResetSimLandObjects(); | ||
743 | } | ||
744 | |||
745 | if (setupDefaultParcel) | ||
746 | CreateDefaultParcel(); | ||
747 | } | 856 | } |
748 | 857 | ||
749 | private void performFinalLandJoin(ILandObject master, ILandObject slave) | 858 | private void performFinalLandJoin(ILandObject master, ILandObject slave) |
@@ -762,11 +871,29 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
762 | } | 871 | } |
763 | } | 872 | } |
764 | } | 873 | } |
765 | 874 | master.LandData.Dwell += slave.LandData.Dwell; | |
766 | removeLandObject(slave.LandData.LocalID); | 875 | removeLandObject(slave.LandData.LocalID); |
767 | UpdateLandObject(master.LandData.LocalID, master.LandData); | 876 | UpdateLandObject(master.LandData.LocalID, master.LandData); |
768 | } | 877 | } |
769 | 878 | ||
879 | public ILandObject GetLandObject(UUID globalID) | ||
880 | { | ||
881 | lock (m_landList) | ||
882 | { | ||
883 | int lid = -1; | ||
884 | if(m_landUUIDList.TryGetValue(globalID, out lid) && lid >= 0) | ||
885 | { | ||
886 | if (m_landList.ContainsKey(lid)) | ||
887 | { | ||
888 | return m_landList[lid]; | ||
889 | } | ||
890 | else | ||
891 | m_landUUIDList.Remove(globalID); // auto heal | ||
892 | } | ||
893 | } | ||
894 | return null; | ||
895 | } | ||
896 | |||
770 | public ILandObject GetLandObject(int parcelLocalID) | 897 | public ILandObject GetLandObject(int parcelLocalID) |
771 | { | 898 | { |
772 | lock (m_landList) | 899 | lock (m_landList) |
@@ -787,58 +914,37 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
787 | /// <returns>Land object at the point supplied</returns> | 914 | /// <returns>Land object at the point supplied</returns> |
788 | public ILandObject GetLandObject(float x_float, float y_float) | 915 | public ILandObject GetLandObject(float x_float, float y_float) |
789 | { | 916 | { |
790 | return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */); | 917 | return GetLandObject((int)x_float, (int)y_float, true); |
791 | /* | 918 | } |
792 | int x; | ||
793 | int y; | ||
794 | |||
795 | if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0) | ||
796 | return null; | ||
797 | 919 | ||
798 | try | 920 | // if x,y is off region this will return the parcel at cliped x,y |
799 | { | 921 | // as did code it replaces |
800 | x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit)); | 922 | public ILandObject GetLandObjectClipedXY(float x, float y) |
801 | y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit)); | 923 | { |
802 | } | 924 | //do clip inline |
803 | catch (OverflowException) | 925 | int avx = (int)x; |
804 | { | 926 | if (avx < 0) |
805 | return null; | 927 | avx = 0; |
806 | } | 928 | else if (avx >= m_scene.RegionInfo.RegionSizeX) |
929 | avx = (int)Constants.RegionSize - 1; | ||
807 | 930 | ||
808 | if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit) | 931 | int avy = (int)y; |
809 | || y >= (m_scene.RegionInfo.RegionSizeY / landUnit) | 932 | if (avy < 0) |
810 | || x < 0 | 933 | avy = 0; |
811 | || y < 0) | 934 | else if (avy >= m_scene.RegionInfo.RegionSizeY) |
812 | { | 935 | avy = (int)Constants.RegionSize - 1; |
813 | return null; | ||
814 | } | ||
815 | 936 | ||
816 | lock (m_landList) | 937 | lock (m_landIDList) |
817 | { | 938 | { |
818 | // Corner case. If an autoreturn happens during sim startup | ||
819 | // we will come here with the list uninitialized | ||
820 | // | ||
821 | // int landId = m_landIDList[x, y]; | ||
822 | |||
823 | // if (landId == 0) | ||
824 | // m_log.DebugFormat( | ||
825 | // "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}", | ||
826 | // x, y, m_scene.RegionInfo.RegionName); | ||
827 | |||
828 | try | 939 | try |
829 | { | 940 | { |
830 | if (m_landList.ContainsKey(m_landIDList[x, y])) | 941 | return m_landList[m_landIDList[avx / LandUnit, avy / LandUnit]]; |
831 | return m_landList[m_landIDList[x, y]]; | ||
832 | } | 942 | } |
833 | catch (Exception e) | 943 | catch (IndexOutOfRangeException) |
834 | { | 944 | { |
835 | m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})", | 945 | return null; |
836 | LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1)); | ||
837 | } | 946 | } |
838 | |||
839 | return null; | ||
840 | } | 947 | } |
841 | */ | ||
842 | } | 948 | } |
843 | 949 | ||
844 | // Public entry. | 950 | // Public entry. |
@@ -848,33 +954,32 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
848 | return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */); | 954 | return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */); |
849 | } | 955 | } |
850 | 956 | ||
851 | /// <summary> | 957 | public ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds) |
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 | { | 958 | { |
864 | if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) | 959 | if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) |
865 | { | 960 | { |
866 | // These exceptions here will cause a lot of complaints from the users specifically because | 961 | // These exceptions here will cause a lot of complaints from the users specifically because |
867 | // they happen every time at border crossings | 962 | // they happen every time at border crossings |
868 | if (returnNullIfLandObjectOutsideBounds) | 963 | if (returnNullIfLandObjectOutsideBounds) |
869 | return null; | 964 | return null; |
870 | else | 965 | else |
871 | throw new Exception( | 966 | throw new Exception("Error: Parcel not found at point " + x + ", " + y); |
872 | String.Format("{0} GetLandObject for non-existent position. Region={1}, pos=<{2},{3}", | ||
873 | LogHeader, m_scene.RegionInfo.RegionName, x, y) | ||
874 | ); | ||
875 | } | 967 | } |
876 | 968 | ||
877 | return m_landList[m_landIDList[x / 4, y / 4]]; | 969 | if(m_landList.Count == 0 || m_landIDList == null) |
970 | return null; | ||
971 | |||
972 | lock (m_landIDList) | ||
973 | { | ||
974 | try | ||
975 | { | ||
976 | return m_landList[m_landIDList[x / 4, y / 4]]; | ||
977 | } | ||
978 | catch (IndexOutOfRangeException) | ||
979 | { | ||
980 | return null; | ||
981 | } | ||
982 | } | ||
878 | } | 983 | } |
879 | 984 | ||
880 | // Create a 'parcel is here' bitmap for the parcel identified by the passed landID | 985 | // Create a 'parcel is here' bitmap for the parcel identified by the passed landID |
@@ -926,7 +1031,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
926 | } | 1031 | } |
927 | } | 1032 | } |
928 | 1033 | ||
929 | public void FinalizeLandPrimCountUpdate() | 1034 | private void FinalizeLandPrimCountUpdate() |
930 | { | 1035 | { |
931 | //Get Simwide prim count for owner | 1036 | //Get Simwide prim count for owner |
932 | Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>(); | 1037 | Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>(); |
@@ -967,10 +1072,10 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
967 | 1072 | ||
968 | public void EventManagerOnParcelPrimCountUpdate() | 1073 | public void EventManagerOnParcelPrimCountUpdate() |
969 | { | 1074 | { |
970 | // m_log.DebugFormat( | 1075 | //m_log.DebugFormat( |
971 | // "[LAND MANAGEMENT MODULE]: Triggered EventManagerOnParcelPrimCountUpdate() for {0}", | 1076 | // "[land management module]: triggered eventmanageronparcelprimcountupdate() for {0}", |
972 | // m_scene.RegionInfo.RegionName); | 1077 | // m_scene.RegionInfo.RegionName); |
973 | 1078 | ||
974 | ResetOverMeRecords(); | 1079 | ResetOverMeRecords(); |
975 | EntityBase[] entities = m_scene.Entities.GetEntities(); | 1080 | EntityBase[] entities = m_scene.Entities.GetEntities(); |
976 | foreach (EntityBase obj in entities) | 1081 | foreach (EntityBase obj in entities) |
@@ -1002,27 +1107,33 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1002 | /// <param name="end_y">North Point</param> | 1107 | /// <param name="end_y">North Point</param> |
1003 | /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param> | 1108 | /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param> |
1004 | /// <returns>Returns true if successful</returns> | 1109 | /// <returns>Returns true if successful</returns> |
1005 | private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) | 1110 | public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) |
1006 | { | 1111 | { |
1007 | //First, lets loop through the points and make sure they are all in the same peice of land | 1112 | //First, lets loop through the points and make sure they are all in the same peice of land |
1008 | //Get the land object at start | 1113 | //Get the land object at start |
1009 | 1114 | ||
1010 | ILandObject startLandObject = GetLandObject(start_x, start_y); | 1115 | ILandObject startLandObject = GetLandObject(start_x, start_y); |
1011 | 1116 | ||
1012 | if (startLandObject == null) return; | 1117 | if (startLandObject == null) |
1118 | return; | ||
1119 | |||
1120 | if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin, true)) | ||
1121 | { | ||
1122 | return; | ||
1123 | } | ||
1013 | 1124 | ||
1014 | //Loop through the points | 1125 | //Loop through the points |
1015 | try | 1126 | try |
1016 | { | 1127 | { |
1017 | int totalX = end_x - start_x; | 1128 | for (int y = start_y; y < end_y; y++) |
1018 | int totalY = end_y - start_y; | ||
1019 | for (int y = 0; y < totalY; y++) | ||
1020 | { | 1129 | { |
1021 | for (int x = 0; x < totalX; x++) | 1130 | for (int x = start_x; x < end_x; x++) |
1022 | { | 1131 | { |
1023 | ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y); | 1132 | ILandObject tempLandObject = GetLandObject(x, y); |
1024 | if (tempLandObject == null) return; | 1133 | if (tempLandObject == null) |
1025 | if (tempLandObject != startLandObject) return; | 1134 | return; |
1135 | if (tempLandObject != startLandObject) | ||
1136 | return; | ||
1026 | } | 1137 | } |
1027 | } | 1138 | } |
1028 | } | 1139 | } |
@@ -1031,22 +1142,22 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1031 | return; | 1142 | return; |
1032 | } | 1143 | } |
1033 | 1144 | ||
1034 | //If we are still here, then they are subdividing within one piece of land | 1145 | //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) |
1035 | //Check owner | ||
1036 | if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin)) | ||
1037 | { | ||
1038 | return; | ||
1039 | } | ||
1040 | |||
1041 | //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) | ||
1042 | ILandObject newLand = startLandObject.Copy(); | 1146 | ILandObject newLand = startLandObject.Copy(); |
1147 | |||
1043 | newLand.LandData.Name = newLand.LandData.Name; | 1148 | newLand.LandData.Name = newLand.LandData.Name; |
1044 | newLand.LandData.GlobalID = UUID.Random(); | 1149 | newLand.LandData.GlobalID = UUID.Random(); |
1045 | newLand.LandData.Dwell = 0; | 1150 | newLand.LandData.Dwell = 0; |
1151 | // Clear "Show in search" on the cut out parcel to prevent double-charging | ||
1152 | newLand.LandData.Flags &= ~(uint)ParcelFlags.ShowDirectory; | ||
1153 | // invalidate landing point | ||
1154 | newLand.LandData.LandingType = (byte)LandingType.Direct; | ||
1155 | newLand.LandData.UserLocation = Vector3.Zero; | ||
1156 | newLand.LandData.UserLookAt = Vector3.Zero; | ||
1046 | 1157 | ||
1047 | newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); | 1158 | newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); |
1048 | 1159 | ||
1049 | //Now, lets set the subdivision area of the original to false | 1160 | //lets set the subdivision area of the original to false |
1050 | int startLandObjectIndex = startLandObject.LandData.LocalID; | 1161 | int startLandObjectIndex = startLandObject.LandData.LocalID; |
1051 | lock (m_landList) | 1162 | lock (m_landList) |
1052 | { | 1163 | { |
@@ -1055,65 +1166,85 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1055 | m_landList[startLandObjectIndex].ForceUpdateLandInfo(); | 1166 | m_landList[startLandObjectIndex].ForceUpdateLandInfo(); |
1056 | } | 1167 | } |
1057 | 1168 | ||
1058 | //Now add the new land object | 1169 | //add the new land object |
1059 | ILandObject result = AddLandObject(newLand); | 1170 | ILandObject result = AddLandObject(newLand); |
1060 | 1171 | ||
1061 | if (result != null) | 1172 | UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); |
1173 | |||
1174 | if(startLandObject.LandData.LandingType == (byte)LandingType.LandingPoint) | ||
1062 | { | 1175 | { |
1063 | UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); | 1176 | int x = (int)startLandObject.LandData.UserLocation.X; |
1064 | result.SendLandUpdateToAvatarsOverMe(); | 1177 | int y = (int)startLandObject.LandData.UserLocation.Y; |
1065 | } | 1178 | if(!startLandObject.ContainsPoint(x, y)) |
1179 | { | ||
1180 | startLandObject.LandData.LandingType = (byte)LandingType.Direct; | ||
1181 | startLandObject.LandData.UserLocation = Vector3.Zero; | ||
1182 | startLandObject.LandData.UserLookAt = Vector3.Zero; | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1186 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | ||
1187 | |||
1188 | result.SendLandUpdateToAvatarsOverMe(); | ||
1189 | startLandObject.SendLandUpdateToAvatarsOverMe(); | ||
1190 | m_scene.ForEachClient(SendParcelOverlay); | ||
1191 | |||
1066 | } | 1192 | } |
1067 | 1193 | ||
1068 | /// <summary> | 1194 | /// <summary> |
1069 | /// Join 2 land objects together | 1195 | /// Join 2 land objects together |
1070 | /// </summary> | 1196 | /// </summary> |
1071 | /// <param name="start_x">x value in first piece of land</param> | 1197 | /// <param name="start_x">start x of selection area</param> |
1072 | /// <param name="start_y">y value in first piece of land</param> | 1198 | /// <param name="start_y">start y of selection area</param> |
1073 | /// <param name="end_x">x value in second peice of land</param> | 1199 | /// <param name="end_x">end x of selection area</param> |
1074 | /// <param name="end_y">y value in second peice of land</param> | 1200 | /// <param name="end_y">end y of selection area</param> |
1075 | /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param> | 1201 | /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param> |
1076 | /// <returns>Returns true if successful</returns> | 1202 | /// <returns>Returns true if successful</returns> |
1077 | private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) | 1203 | public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) |
1078 | { | 1204 | { |
1079 | end_x -= 4; | 1205 | int index = 0; |
1080 | end_y -= 4; | 1206 | int maxindex = -1; |
1207 | int maxArea = 0; | ||
1081 | 1208 | ||
1082 | List<ILandObject> selectedLandObjects = new List<ILandObject>(); | 1209 | List<ILandObject> selectedLandObjects = new List<ILandObject>(); |
1083 | int stepYSelected; | 1210 | for (int x = start_x; x < end_x; x += 4) |
1084 | for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4) | ||
1085 | { | 1211 | { |
1086 | int stepXSelected; | 1212 | for (int y = start_y; y < end_y; y += 4) |
1087 | for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4) | ||
1088 | { | 1213 | { |
1089 | ILandObject p = GetLandObject(stepXSelected, stepYSelected); | 1214 | ILandObject p = GetLandObject(x, y); |
1090 | 1215 | ||
1091 | if (p != null) | 1216 | if (p != null) |
1092 | { | 1217 | { |
1093 | if (!selectedLandObjects.Contains(p)) | 1218 | if (!selectedLandObjects.Contains(p)) |
1094 | { | 1219 | { |
1095 | selectedLandObjects.Add(p); | 1220 | selectedLandObjects.Add(p); |
1221 | if(p.LandData.Area > maxArea) | ||
1222 | { | ||
1223 | maxArea = p.LandData.Area; | ||
1224 | maxindex = index; | ||
1225 | } | ||
1226 | index++; | ||
1096 | } | 1227 | } |
1097 | } | 1228 | } |
1098 | } | 1229 | } |
1099 | } | 1230 | } |
1100 | ILandObject masterLandObject = selectedLandObjects[0]; | ||
1101 | selectedLandObjects.RemoveAt(0); | ||
1102 | 1231 | ||
1103 | if (selectedLandObjects.Count < 1) | 1232 | if(maxindex < 0 || selectedLandObjects.Count < 2) |
1104 | { | ||
1105 | return; | 1233 | return; |
1106 | } | 1234 | |
1107 | if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin)) | 1235 | ILandObject masterLandObject = selectedLandObjects[maxindex]; |
1236 | selectedLandObjects.RemoveAt(maxindex); | ||
1237 | |||
1238 | if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin, true)) | ||
1108 | { | 1239 | { |
1109 | return; | 1240 | return; |
1110 | } | 1241 | } |
1242 | |||
1243 | UUID masterOwner = masterLandObject.LandData.OwnerID; | ||
1111 | foreach (ILandObject p in selectedLandObjects) | 1244 | foreach (ILandObject p in selectedLandObjects) |
1112 | { | 1245 | { |
1113 | if (p.LandData.OwnerID != masterLandObject.LandData.OwnerID) | 1246 | if (p.LandData.OwnerID != masterOwner) |
1114 | { | ||
1115 | return; | 1247 | return; |
1116 | } | ||
1117 | } | 1248 | } |
1118 | 1249 | ||
1119 | lock (m_landList) | 1250 | lock (m_landList) |
@@ -1126,29 +1257,14 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1126 | } | 1257 | } |
1127 | } | 1258 | } |
1128 | 1259 | ||
1260 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | ||
1129 | masterLandObject.SendLandUpdateToAvatarsOverMe(); | 1261 | masterLandObject.SendLandUpdateToAvatarsOverMe(); |
1262 | m_scene.ForEachClient(SendParcelOverlay); | ||
1130 | } | 1263 | } |
1131 | |||
1132 | public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) | ||
1133 | { | ||
1134 | join(start_x, start_y, end_x, end_y, attempting_user_id); | ||
1135 | } | ||
1136 | |||
1137 | public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) | ||
1138 | { | ||
1139 | subdivide(start_x, start_y, end_x, end_y, attempting_user_id); | ||
1140 | } | ||
1141 | |||
1142 | #endregion | 1264 | #endregion |
1143 | 1265 | ||
1144 | #region Parcel Updating | 1266 | #region Parcel Updating |
1145 | 1267 | ||
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 | |||
1152 | /// <summary> | 1268 | /// <summary> |
1153 | /// Send the parcel overlay blocks to the client. We send the overlay packets | 1269 | /// Send the parcel overlay blocks to the client. We send the overlay packets |
1154 | /// around a location and limited by the 'parcelLayerViewDistance'. This number | 1270 | /// around a location and limited by the 'parcelLayerViewDistance'. This number |
@@ -1162,145 +1278,115 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1162 | /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param> | 1278 | /// <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> | 1279 | /// <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> | 1280 | /// <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) | 1281 | public void SendParcelOverlay(IClientAPI remote_client) |
1166 | { | 1282 | { |
1283 | if (remote_client.SceneAgent.PresenceType == PresenceType.Npc) | ||
1284 | return; | ||
1285 | |||
1167 | const int LAND_BLOCKS_PER_PACKET = 1024; | 1286 | const int LAND_BLOCKS_PER_PACKET = 1024; |
1168 | 1287 | ||
1169 | byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; | 1288 | byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; |
1170 | int byteArrayCount = 0; | 1289 | int byteArrayCount = 0; |
1171 | int sequenceID = 0; | 1290 | int sequenceID = 0; |
1172 | 1291 | ||
1173 | int xLow = 0; | 1292 | // Layer data is in LandUnit (4m) chunks |
1174 | int xHigh = (int)m_scene.RegionInfo.RegionSizeX; | 1293 | for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += LandUnit) |
1175 | int yLow = 0; | ||
1176 | int yHigh = (int)m_scene.RegionInfo.RegionSizeY; | ||
1177 | |||
1178 | if (shouldLimitParcelLayerInfoToViewDistance) | ||
1179 | { | 1294 | { |
1180 | // Compute view distance around the given point | 1295 | for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += LandUnit) |
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 | { | 1296 | { |
1186 | txLow = xLow; | 1297 | byte tempByte = 0; //This represents the byte for the current 4x4 |
1187 | txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh); | ||
1188 | } | ||
1189 | if (txHigh > xHigh) | ||
1190 | { | ||
1191 | txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2)); | ||
1192 | txHigh = xHigh; | ||
1193 | } | ||
1194 | xLow = txLow; | ||
1195 | xHigh = txHigh; | ||
1196 | 1298 | ||
1197 | int tyLow = yPlace - layerViewDistance; | 1299 | ILandObject currentParcelBlock = GetLandObject(x, y); |
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); | ||
1214 | 1300 | ||
1215 | // Layer data is in landUnit (4m) chunks | 1301 | if (currentParcelBlock != null) |
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) | ||
1223 | { | 1302 | { |
1224 | // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); | 1303 | // types |
1225 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); | 1304 | if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) |
1226 | byteArrayCount = 0; | 1305 | { |
1227 | sequenceID++; | 1306 | //Owner Flag |
1228 | byteArray = new byte[LAND_BLOCKS_PER_PACKET]; | 1307 | tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER; |
1229 | } | 1308 | } |
1309 | else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID)) | ||
1310 | { | ||
1311 | tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP; | ||
1312 | } | ||
1313 | else if (currentParcelBlock.LandData.SalePrice > 0 && | ||
1314 | (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || | ||
1315 | currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) | ||
1316 | { | ||
1317 | //Sale type | ||
1318 | tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE; | ||
1319 | } | ||
1320 | else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) | ||
1321 | { | ||
1322 | //Public type | ||
1323 | tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero | ||
1324 | } | ||
1325 | // LAND_TYPE_IS_BEING_AUCTIONED still unsuported | ||
1326 | else | ||
1327 | { | ||
1328 | //Other Flag | ||
1329 | tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER; | ||
1330 | } | ||
1230 | 1331 | ||
1231 | } | 1332 | // now flags |
1232 | } | 1333 | // border control |
1233 | 1334 | ||
1234 | if (byteArrayCount != 0) | 1335 | ILandObject westParcel = null; |
1235 | { | 1336 | ILandObject southParcel = null; |
1236 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); | 1337 | if (x > 0) |
1237 | // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); | 1338 | { |
1238 | } | 1339 | westParcel = GetLandObject((x - 1), y); |
1239 | } | 1340 | } |
1341 | if (y > 0) | ||
1342 | { | ||
1343 | southParcel = GetLandObject(x, (y - 1)); | ||
1344 | } | ||
1240 | 1345 | ||
1241 | private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client) | 1346 | if (x == 0) |
1242 | { | 1347 | { |
1243 | byte tempByte = 0; //This represents the byte for the current 4x4 | 1348 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; |
1349 | } | ||
1350 | else if (westParcel != null && westParcel != currentParcelBlock) | ||
1351 | { | ||
1352 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; | ||
1353 | } | ||
1244 | 1354 | ||
1245 | if (currentParcelBlock != null) | 1355 | if (y == 0) |
1246 | { | 1356 | { |
1247 | if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) | 1357 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; |
1248 | { | 1358 | } |
1249 | //Owner Flag | 1359 | else if (southParcel != null && southParcel != currentParcelBlock) |
1250 | tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); | 1360 | { |
1251 | } | 1361 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; |
1252 | else if (currentParcelBlock.LandData.SalePrice > 0 && | 1362 | } |
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 | } | ||
1269 | 1363 | ||
1270 | //Now for border control | 1364 | // local sound |
1365 | if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0) | ||
1366 | tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND; | ||
1271 | 1367 | ||
1272 | ILandObject westParcel = null; | 1368 | // hide avatars |
1273 | ILandObject southParcel = null; | 1369 | if (!currentParcelBlock.LandData.SeeAVs) |
1274 | if (x > 0) | 1370 | tempByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS; |
1275 | { | ||
1276 | westParcel = GetLandObject((x - 1) * LandUnit, y * LandUnit); | ||
1277 | } | ||
1278 | if (y > 0) | ||
1279 | { | ||
1280 | southParcel = GetLandObject(x * LandUnit, (y - 1) * LandUnit); | ||
1281 | } | ||
1282 | 1371 | ||
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); | ||
1290 | } | ||
1291 | 1372 | ||
1292 | if (y == 0) | 1373 | byteArray[byteArrayCount] = tempByte; |
1293 | { | 1374 | byteArrayCount++; |
1294 | tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); | 1375 | if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) |
1295 | } | 1376 | { |
1296 | else if (southParcel != null && southParcel != currentParcelBlock) | 1377 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); |
1297 | { | 1378 | byteArrayCount = 0; |
1298 | tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); | 1379 | sequenceID++; |
1380 | byteArray = new byte[LAND_BLOCKS_PER_PACKET]; | ||
1381 | } | ||
1382 | } | ||
1299 | } | 1383 | } |
1300 | |||
1301 | } | 1384 | } |
1302 | 1385 | ||
1303 | return tempByte; | 1386 | if (byteArrayCount > 0) |
1387 | { | ||
1388 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); | ||
1389 | } | ||
1304 | } | 1390 | } |
1305 | 1391 | ||
1306 | public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, | 1392 | public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, |
@@ -1320,8 +1406,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1320 | { | 1406 | { |
1321 | if (!temp.Contains(currentParcel)) | 1407 | if (!temp.Contains(currentParcel)) |
1322 | { | 1408 | { |
1323 | currentParcel.ForceUpdateLandInfo(); | 1409 | if (!currentParcel.IsBannedFromLand(remote_client.AgentId)) |
1324 | temp.Add(currentParcel); | 1410 | { |
1411 | currentParcel.ForceUpdateLandInfo(); | ||
1412 | temp.Add(currentParcel); | ||
1413 | } | ||
1325 | } | 1414 | } |
1326 | } | 1415 | } |
1327 | } | 1416 | } |
@@ -1338,8 +1427,44 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1338 | temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); | 1427 | temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); |
1339 | } | 1428 | } |
1340 | 1429 | ||
1341 | // Also send the layer data around the point of interest | 1430 | // SendParcelOverlay(remote_client); |
1342 | SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance); | 1431 | } |
1432 | |||
1433 | public void UpdateLandProperties(ILandObject land, LandUpdateArgs args, IClientAPI remote_client) | ||
1434 | { | ||
1435 | bool snap_selection = false; | ||
1436 | bool needOverlay = false; | ||
1437 | if (land.UpdateLandProperties(args, remote_client, out snap_selection, out needOverlay)) | ||
1438 | { | ||
1439 | UUID parcelID = land.LandData.GlobalID; | ||
1440 | m_scene.ForEachScenePresence(delegate(ScenePresence avatar) | ||
1441 | { | ||
1442 | if (avatar.IsDeleted || avatar.IsNPC) | ||
1443 | return; | ||
1444 | |||
1445 | IClientAPI client = avatar.ControllingClient; | ||
1446 | if (needOverlay) | ||
1447 | SendParcelOverlay(client); | ||
1448 | |||
1449 | if (avatar.IsChildAgent) | ||
1450 | { | ||
1451 | if(client == remote_client) | ||
1452 | land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client); | ||
1453 | return; | ||
1454 | } | ||
1455 | |||
1456 | ILandObject aland = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); | ||
1457 | if (aland != null) | ||
1458 | { | ||
1459 | if(client == remote_client && land != aland) | ||
1460 | land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client); | ||
1461 | else if (land == aland) | ||
1462 | aland.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, client); | ||
1463 | } | ||
1464 | if (avatar.currentParcelUUID == parcelID) | ||
1465 | avatar.currentParcelUUID = parcelID; // force parcel flags review | ||
1466 | }); | ||
1467 | } | ||
1343 | } | 1468 | } |
1344 | 1469 | ||
1345 | public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) | 1470 | public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) |
@@ -1352,19 +1477,19 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1352 | 1477 | ||
1353 | if (land != null) | 1478 | if (land != null) |
1354 | { | 1479 | { |
1355 | land.UpdateLandProperties(args, remote_client); | 1480 | UpdateLandProperties(land, args, remote_client); |
1356 | m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); | 1481 | m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); |
1357 | } | 1482 | } |
1358 | } | 1483 | } |
1359 | 1484 | ||
1360 | public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) | 1485 | public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) |
1361 | { | 1486 | { |
1362 | subdivide(west, south, east, north, remote_client.AgentId); | 1487 | Subdivide(west, south, east, north, remote_client.AgentId); |
1363 | } | 1488 | } |
1364 | 1489 | ||
1365 | public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) | 1490 | public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) |
1366 | { | 1491 | { |
1367 | join(west, south, east, north, remote_client.AgentId); | 1492 | Join(west, south, east, north, remote_client.AgentId); |
1368 | } | 1493 | } |
1369 | 1494 | ||
1370 | public void ClientOnParcelSelectObjects(int local_id, int request_type, | 1495 | public void ClientOnParcelSelectObjects(int local_id, int request_type, |
@@ -1375,7 +1500,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1375 | 1500 | ||
1376 | public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client) | 1501 | public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client) |
1377 | { | 1502 | { |
1378 | ILandObject land; | 1503 | ILandObject land = null; |
1379 | lock (m_landList) | 1504 | lock (m_landList) |
1380 | { | 1505 | { |
1381 | m_landList.TryGetValue(local_id, out land); | 1506 | m_landList.TryGetValue(local_id, out land); |
@@ -1384,7 +1509,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1384 | if (land != null) | 1509 | if (land != null) |
1385 | { | 1510 | { |
1386 | m_scene.EventManager.TriggerParcelPrimCountUpdate(); | 1511 | m_scene.EventManager.TriggerParcelPrimCountUpdate(); |
1387 | m_landList[local_id].SendLandObjectOwners(remote_client); | 1512 | land.SendLandObjectOwners(remote_client); |
1388 | } | 1513 | } |
1389 | else | 1514 | else |
1390 | { | 1515 | { |
@@ -1394,7 +1519,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1394 | 1519 | ||
1395 | public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client) | 1520 | public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client) |
1396 | { | 1521 | { |
1397 | ILandObject land; | 1522 | ILandObject land = null; |
1398 | lock (m_landList) | 1523 | lock (m_landList) |
1399 | { | 1524 | { |
1400 | m_landList.TryGetValue(local_id, out land); | 1525 | m_landList.TryGetValue(local_id, out land); |
@@ -1408,7 +1533,6 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1408 | land.LandData.GroupID = UUID.Zero; | 1533 | land.LandData.GroupID = UUID.Zero; |
1409 | land.LandData.IsGroupOwned = false; | 1534 | land.LandData.IsGroupOwned = false; |
1410 | land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); | 1535 | land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); |
1411 | |||
1412 | m_scene.ForEachClient(SendParcelOverlay); | 1536 | m_scene.ForEachClient(SendParcelOverlay); |
1413 | land.SendLandUpdateToClient(true, remote_client); | 1537 | land.SendLandUpdateToClient(true, remote_client); |
1414 | UpdateLandObject(land.LandData.LocalID, land.LandData); | 1538 | UpdateLandObject(land.LandData.LocalID, land.LandData); |
@@ -1418,7 +1542,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1418 | 1542 | ||
1419 | public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client) | 1543 | public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client) |
1420 | { | 1544 | { |
1421 | ILandObject land; | 1545 | ILandObject land = null; |
1422 | lock (m_landList) | 1546 | lock (m_landList) |
1423 | { | 1547 | { |
1424 | m_landList.TryGetValue(local_id, out land); | 1548 | m_landList.TryGetValue(local_id, out land); |
@@ -1432,7 +1556,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1432 | land.LandData.GroupID = UUID.Zero; | 1556 | land.LandData.GroupID = UUID.Zero; |
1433 | land.LandData.IsGroupOwned = false; | 1557 | land.LandData.IsGroupOwned = false; |
1434 | land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); | 1558 | land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); |
1435 | 1559 | ||
1436 | m_scene.ForEachClient(SendParcelOverlay); | 1560 | m_scene.ForEachClient(SendParcelOverlay); |
1437 | land.SendLandUpdateToClient(true, remote_client); | 1561 | land.SendLandUpdateToClient(true, remote_client); |
1438 | UpdateLandObject(land.LandData.LocalID, land.LandData); | 1562 | UpdateLandObject(land.LandData.LocalID, land.LandData); |
@@ -1442,7 +1566,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1442 | 1566 | ||
1443 | public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client) | 1567 | public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client) |
1444 | { | 1568 | { |
1445 | ILandObject land; | 1569 | ILandObject land = null; |
1446 | lock (m_landList) | 1570 | lock (m_landList) |
1447 | { | 1571 | { |
1448 | m_landList.TryGetValue(local_id, out land); | 1572 | m_landList.TryGetValue(local_id, out land); |
@@ -1458,8 +1582,10 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1458 | land.LandData.IsGroupOwned = false; | 1582 | land.LandData.IsGroupOwned = false; |
1459 | land.LandData.SalePrice = 0; | 1583 | land.LandData.SalePrice = 0; |
1460 | land.LandData.AuthBuyerID = UUID.Zero; | 1584 | land.LandData.AuthBuyerID = UUID.Zero; |
1585 | land.LandData.SeeAVs = true; | ||
1586 | land.LandData.AnyAVSounds = true; | ||
1587 | land.LandData.GroupAVSounds = true; | ||
1461 | land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); | 1588 | land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); |
1462 | |||
1463 | m_scene.ForEachClient(SendParcelOverlay); | 1589 | m_scene.ForEachClient(SendParcelOverlay); |
1464 | land.SendLandUpdateToClient(true, remote_client); | 1590 | land.SendLandUpdateToClient(true, remote_client); |
1465 | UpdateLandObject(land.LandData.LocalID, land.LandData); | 1591 | UpdateLandObject(land.LandData.LocalID, land.LandData); |
@@ -1526,17 +1652,16 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1526 | 1652 | ||
1527 | void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client) | 1653 | void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client) |
1528 | { | 1654 | { |
1529 | ILandObject land; | 1655 | ILandObject land = null; |
1530 | lock (m_landList) | 1656 | lock (m_landList) |
1531 | { | 1657 | { |
1532 | m_landList.TryGetValue(parcelLocalID, out land); | 1658 | m_landList.TryGetValue(parcelLocalID, out land); |
1533 | } | 1659 | } |
1534 | 1660 | ||
1535 | if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land)) | ||
1536 | return; | ||
1537 | |||
1538 | if (land != null) | 1661 | if (land != null) |
1539 | { | 1662 | { |
1663 | if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land)) | ||
1664 | return; | ||
1540 | land.DeedToGroup(groupID); | 1665 | land.DeedToGroup(groupID); |
1541 | } | 1666 | } |
1542 | } | 1667 | } |
@@ -1545,17 +1670,12 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1545 | 1670 | ||
1546 | private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) | 1671 | private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) |
1547 | { | 1672 | { |
1548 | // m_log.DebugFormat( | ||
1549 | // "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name); | ||
1550 | |||
1551 | // Prevent race conditions from any auto-creation of new parcels for varregions whilst we are still loading | ||
1552 | // the existing parcels. | ||
1553 | lock (m_landList) | 1673 | lock (m_landList) |
1554 | { | 1674 | { |
1555 | for (int i = 0; i < data.Count; i++) | 1675 | for (int i = 0; i < data.Count; i++) |
1556 | IncomingLandObjectFromStorage(data[i]); | 1676 | IncomingLandObjectFromStorage(data[i]); |
1557 | 1677 | ||
1558 | // Layer data is in landUnit (4m) chunks | 1678 | // Layer data is in LandUnit (4m) chunks |
1559 | for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) | 1679 | for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) |
1560 | { | 1680 | { |
1561 | for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) | 1681 | for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) |
@@ -1565,7 +1685,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1565 | if (m_landList.Count == 1) | 1685 | if (m_landList.Count == 1) |
1566 | { | 1686 | { |
1567 | m_log.DebugFormat( | 1687 | 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}", | 1688 | "[{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); | 1689 | LogHeader, x, y, m_scene.Name); |
1570 | 1690 | ||
1571 | int onlyParcelID = 0; | 1691 | int onlyParcelID = 0; |
@@ -1588,11 +1708,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1588 | else if (m_landList.Count > 1) | 1708 | else if (m_landList.Count > 1) |
1589 | { | 1709 | { |
1590 | m_log.DebugFormat( | 1710 | 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}", | 1711 | "{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); | 1712 | LogHeader, x, y, m_scene.Name); |
1593 | 1713 | ||
1594 | // There are several other parcels so we must create a new one for the unassigned space | 1714 | // 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); | 1715 | ILandObject newLand = new LandObject(UUID.Zero, false, m_scene); |
1596 | // Claim all the unclaimed "0" ids | 1716 | // Claim all the unclaimed "0" ids |
1597 | newLand.SetLandBitmap(CreateBitmapForID(0)); | 1717 | newLand.SetLandBitmap(CreateBitmapForID(0)); |
1598 | newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; | 1718 | newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
@@ -1603,20 +1723,23 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1603 | { | 1723 | { |
1604 | // We should never reach this point as the separate code path when no land data exists should have fired instead. | 1724 | // We should never reach this point as the separate code path when no land data exists should have fired instead. |
1605 | m_log.WarnFormat( | 1725 | m_log.WarnFormat( |
1606 | "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", | 1726 | "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", |
1607 | LogHeader, m_scene.Name); | 1727 | LogHeader, m_scene.Name); |
1608 | } | 1728 | } |
1609 | } | 1729 | } |
1610 | } | 1730 | } |
1611 | } | 1731 | } |
1732 | FinalizeLandPrimCountUpdate(); // update simarea information | ||
1612 | } | 1733 | } |
1613 | } | 1734 | } |
1614 | 1735 | ||
1615 | private void IncomingLandObjectFromStorage(LandData data) | 1736 | private void IncomingLandObjectFromStorage(LandData data) |
1616 | { | 1737 | { |
1617 | ILandObject new_land = new LandObject(data, m_scene); | 1738 | ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene, data); |
1618 | new_land.SetLandBitmapFromByteArray(); | 1739 | |
1740 | new_land.SetLandBitmapFromByteArray(); | ||
1619 | AddLandObject(new_land); | 1741 | AddLandObject(new_land); |
1742 | // new_land.SendLandUpdateToAvatarsOverMe(); | ||
1620 | } | 1743 | } |
1621 | 1744 | ||
1622 | public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) | 1745 | public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) |
@@ -1629,7 +1752,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1629 | m_landList.TryGetValue(localID, out selectedParcel); | 1752 | m_landList.TryGetValue(localID, out selectedParcel); |
1630 | } | 1753 | } |
1631 | 1754 | ||
1632 | if (selectedParcel == null) | 1755 | if (selectedParcel == null) |
1633 | return; | 1756 | return; |
1634 | 1757 | ||
1635 | selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); | 1758 | selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); |
@@ -1670,9 +1793,9 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1670 | foreach (HashSet<SceneObjectGroup> objs in returns.Values) | 1793 | foreach (HashSet<SceneObjectGroup> objs in returns.Values) |
1671 | { | 1794 | { |
1672 | List<SceneObjectGroup> objs2 = new List<SceneObjectGroup>(objs); | 1795 | List<SceneObjectGroup> objs2 = new List<SceneObjectGroup>(objs); |
1673 | if (m_scene.Permissions.CanReturnObjects(null, remoteClient.AgentId, objs2)) | 1796 | if (m_scene.Permissions.CanReturnObjects(null, remoteClient, objs2)) |
1674 | { | 1797 | { |
1675 | m_scene.returnObjects(objs2.ToArray(), remoteClient.AgentId); | 1798 | m_scene.returnObjects(objs2.ToArray(), remoteClient); |
1676 | } | 1799 | } |
1677 | else | 1800 | else |
1678 | { | 1801 | { |
@@ -1710,12 +1833,13 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1710 | 1833 | ||
1711 | private void EventManagerOnRegisterCaps(UUID agentID, Caps caps) | 1834 | private void EventManagerOnRegisterCaps(UUID agentID, Caps caps) |
1712 | { | 1835 | { |
1836 | //string capsBase = "/CAPS/" + UUID.Random(); | ||
1713 | string capsBase = "/CAPS/" + caps.CapsObjectPath; | 1837 | string capsBase = "/CAPS/" + caps.CapsObjectPath; |
1714 | caps.RegisterHandler( | 1838 | caps.RegisterHandler( |
1715 | "RemoteParcelRequest", | 1839 | "RemoteParcelRequest", |
1716 | new RestStreamHandler( | 1840 | new RestStreamHandler( |
1717 | "POST", | 1841 | "POST", |
1718 | capsBase + remoteParcelRequestPath, | 1842 | capsBase, |
1719 | (request, path, param, httpRequest, httpResponse) | 1843 | (request, path, param, httpRequest, httpResponse) |
1720 | => RemoteParcelRequest(request, path, param, agentID, caps), | 1844 | => RemoteParcelRequest(request, path, param, agentID, caps), |
1721 | "RemoteParcelRequest", | 1845 | "RemoteParcelRequest", |
@@ -1735,7 +1859,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1735 | private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps) | 1859 | private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps) |
1736 | { | 1860 | { |
1737 | IClientAPI client; | 1861 | IClientAPI client; |
1738 | if (!m_scene.TryGetClient(agentID, out client)) | 1862 | if (!m_scene.TryGetClient(agentID, out client)) |
1739 | { | 1863 | { |
1740 | m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID); | 1864 | m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID); |
1741 | return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); | 1865 | return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); |
@@ -1759,7 +1883,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1759 | land_update.MusicURL = properties.MusicURL; | 1883 | land_update.MusicURL = properties.MusicURL; |
1760 | land_update.Name = properties.Name; | 1884 | land_update.Name = properties.Name; |
1761 | land_update.ParcelFlags = (uint) properties.ParcelFlags; | 1885 | land_update.ParcelFlags = (uint) properties.ParcelFlags; |
1762 | land_update.PassHours = (int) properties.PassHours; | 1886 | land_update.PassHours = properties.PassHours; |
1763 | land_update.PassPrice = (int) properties.PassPrice; | 1887 | land_update.PassPrice = (int) properties.PassPrice; |
1764 | land_update.SalePrice = (int) properties.SalePrice; | 1888 | land_update.SalePrice = (int) properties.SalePrice; |
1765 | land_update.SnapshotID = properties.SnapshotID; | 1889 | land_update.SnapshotID = properties.SnapshotID; |
@@ -1773,7 +1897,20 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1773 | land_update.ObscureMusic = properties.ObscureMusic; | 1897 | land_update.ObscureMusic = properties.ObscureMusic; |
1774 | land_update.ObscureMedia = properties.ObscureMedia; | 1898 | land_update.ObscureMedia = properties.ObscureMedia; |
1775 | 1899 | ||
1776 | ILandObject land; | 1900 | if (args.ContainsKey("see_avs")) |
1901 | { | ||
1902 | land_update.SeeAVs = args["see_avs"].AsBoolean(); | ||
1903 | land_update.AnyAVSounds = args["any_av_sounds"].AsBoolean(); | ||
1904 | land_update.GroupAVSounds = args["group_av_sounds"].AsBoolean(); | ||
1905 | } | ||
1906 | else | ||
1907 | { | ||
1908 | land_update.SeeAVs = true; | ||
1909 | land_update.AnyAVSounds = true; | ||
1910 | land_update.GroupAVSounds = true; | ||
1911 | } | ||
1912 | |||
1913 | ILandObject land = null; | ||
1777 | lock (m_landList) | 1914 | lock (m_landList) |
1778 | { | 1915 | { |
1779 | m_landList.TryGetValue(parcelID, out land); | 1916 | m_landList.TryGetValue(parcelID, out land); |
@@ -1781,13 +1918,14 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1781 | 1918 | ||
1782 | if (land != null) | 1919 | if (land != null) |
1783 | { | 1920 | { |
1784 | land.UpdateLandProperties(land_update, client); | 1921 | UpdateLandProperties(land,land_update, client); |
1785 | m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); | 1922 | m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); |
1786 | } | 1923 | } |
1787 | else | 1924 | else |
1788 | { | 1925 | { |
1789 | m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); | 1926 | m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); |
1790 | } | 1927 | } |
1928 | |||
1791 | return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); | 1929 | return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); |
1792 | } | 1930 | } |
1793 | // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the | 1931 | // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the |
@@ -1815,9 +1953,9 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1815 | { | 1953 | { |
1816 | Hashtable hash = new Hashtable(); | 1954 | Hashtable hash = new Hashtable(); |
1817 | hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); | 1955 | hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); |
1818 | if (hash.ContainsKey("region_id") && hash.ContainsKey("location")) | 1956 | if (hash.ContainsKey("location")) |
1819 | { | 1957 | { |
1820 | UUID regionID = (UUID)hash["region_id"]; | 1958 | UUID scope = m_scene.RegionInfo.ScopeID; |
1821 | ArrayList list = (ArrayList)hash["location"]; | 1959 | ArrayList list = (ArrayList)hash["location"]; |
1822 | uint x = (uint)(double)list[0]; | 1960 | uint x = (uint)(double)list[0]; |
1823 | uint y = (uint)(double)list[1]; | 1961 | uint y = (uint)(double)list[1]; |
@@ -1826,19 +1964,46 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1826 | // if you do a "About Landmark" on a landmark a second time, the viewer sends the | 1964 | // if you do a "About Landmark" on a landmark a second time, the viewer sends the |
1827 | // region_handle it got earlier via RegionHandleRequest | 1965 | // region_handle it got earlier via RegionHandleRequest |
1828 | ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]); | 1966 | ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]); |
1829 | parcelID = Util.BuildFakeParcelID(regionHandle, x, y); | 1967 | if(regionHandle == m_scene.RegionInfo.RegionHandle) |
1968 | parcelID = Util.BuildFakeParcelID(regionHandle, x, y); | ||
1969 | else | ||
1970 | { | ||
1971 | uint wx; | ||
1972 | uint wy; | ||
1973 | Util.RegionHandleToWorldLoc(regionHandle, out wx, out wy); | ||
1974 | GridRegion info = m_scene.GridService.GetRegionByPosition(scope, (int)wx, (int)wy); | ||
1975 | if(info != null) | ||
1976 | { | ||
1977 | wx -= (uint)info.RegionLocX; | ||
1978 | wy -= (uint)info.RegionLocY; | ||
1979 | wx += x; | ||
1980 | wy += y; | ||
1981 | // Firestorm devs have no ideia how to do handlers math | ||
1982 | // on all cases | ||
1983 | if(wx > info.RegionSizeX || wy > info.RegionSizeY) | ||
1984 | { | ||
1985 | wx = x; | ||
1986 | wy = y; | ||
1987 | } | ||
1988 | parcelID = Util.BuildFakeParcelID(info.RegionHandle, wx, wy); | ||
1989 | } | ||
1990 | } | ||
1830 | } | 1991 | } |
1831 | else if (regionID == m_scene.RegionInfo.RegionID) | 1992 | else if(hash.ContainsKey("region_id")) |
1832 | { | 1993 | { |
1994 | UUID regionID = (UUID)hash["region_id"]; | ||
1995 | if (regionID == m_scene.RegionInfo.RegionID) | ||
1996 | { | ||
1833 | // a parcel request for a local parcel => no need to query the grid | 1997 | // a parcel request for a local parcel => no need to query the grid |
1834 | parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y); | 1998 | parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y); |
1835 | } | 1999 | } |
1836 | else | 2000 | else |
1837 | { | 2001 | { |
1838 | // a parcel request for a parcel in another region. Ask the grid about the region | 2002 | // a parcel request for a parcel in another region. Ask the grid about the region |
1839 | GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, regionID); | 2003 | GridRegion info = m_scene.GridService.GetRegionByUUID(scope, regionID); |
1840 | if (info != null) | 2004 | if (info != null) |
1841 | parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y); | 2005 | parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y); |
2006 | } | ||
1842 | } | 2007 | } |
1843 | } | 2008 | } |
1844 | } | 2009 | } |
@@ -1854,7 +2019,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1854 | 2019 | ||
1855 | LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); | 2020 | LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); |
1856 | response.parcel_id = parcelID; | 2021 | response.parcel_id = parcelID; |
1857 | m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID); | 2022 | //m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID); |
1858 | 2023 | ||
1859 | return LLSDHelpers.SerialiseLLSDReply(response); | 2024 | return LLSDHelpers.SerialiseLLSDReply(response); |
1860 | } | 2025 | } |
@@ -1871,17 +2036,25 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1871 | { | 2036 | { |
1872 | UUID parcel = UUID.Zero; | 2037 | UUID parcel = UUID.Zero; |
1873 | UUID.TryParse(id, out parcel); | 2038 | UUID.TryParse(id, out parcel); |
2039 | |||
1874 | // assume we've got the parcelID we just computed in RemoteParcelRequest | 2040 | // assume we've got the parcelID we just computed in RemoteParcelRequest |
1875 | ExtendedLandData extLandData = new ExtendedLandData(); | 2041 | ExtendedLandData extLandData = new ExtendedLandData(); |
1876 | Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, | 2042 | if(!Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, |
1877 | out extLandData.X, out extLandData.Y); | 2043 | out extLandData.X, out extLandData.Y)) |
1878 | m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", | 2044 | return null; |
2045 | m_log.DebugFormat("[LAND MANAGEMENT MODULE] : Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", | ||
1879 | extLandData.RegionHandle, extLandData.X, extLandData.Y); | 2046 | extLandData.RegionHandle, extLandData.X, extLandData.Y); |
1880 | 2047 | ||
1881 | // for this region or for somewhere else? | 2048 | // for this region or for somewhere else? |
1882 | if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle) | 2049 | if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle) |
1883 | { | 2050 | { |
1884 | extLandData.LandData = this.GetLandObject(extLandData.X, extLandData.Y).LandData; | 2051 | ILandObject extLandObject = this.GetLandObject(extLandData.X, extLandData.Y); |
2052 | if(extLandObject == null) | ||
2053 | { | ||
2054 | m_log.DebugFormat("[LAND MANAGEMENT MODULE]: ParcelInfoRequest: a FakeParcelID points to outside the region"); | ||
2055 | return null; | ||
2056 | } | ||
2057 | extLandData.LandData = extLandObject.LandData; | ||
1885 | extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel; | 2058 | extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel; |
1886 | } | 2059 | } |
1887 | else | 2060 | else |
@@ -1907,6 +2080,9 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1907 | if (data.RegionHandle == m_scene.RegionInfo.RegionHandle) | 2080 | if (data.RegionHandle == m_scene.RegionInfo.RegionHandle) |
1908 | { | 2081 | { |
1909 | info = new GridRegion(m_scene.RegionInfo); | 2082 | info = new GridRegion(m_scene.RegionInfo); |
2083 | IDwellModule dwellModule = m_scene.RequestModuleInterface<IDwellModule>(); | ||
2084 | if (dwellModule != null) | ||
2085 | data.LandData.Dwell = dwellModule.GetDwell(data.LandData); | ||
1910 | } | 2086 | } |
1911 | else | 2087 | else |
1912 | { | 2088 | { |
@@ -1932,7 +2108,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1932 | 2108 | ||
1933 | public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) | 2109 | public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) |
1934 | { | 2110 | { |
1935 | ILandObject land; | 2111 | ILandObject land = null; |
1936 | lock (m_landList) | 2112 | lock (m_landList) |
1937 | { | 2113 | { |
1938 | m_landList.TryGetValue(localID, out land); | 2114 | m_landList.TryGetValue(localID, out land); |
@@ -1940,14 +2116,91 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1940 | 2116 | ||
1941 | if (land == null) return; | 2117 | if (land == null) return; |
1942 | 2118 | ||
1943 | if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions)) | 2119 | if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions, false)) |
1944 | return; | 2120 | return; |
1945 | 2121 | ||
1946 | land.LandData.OtherCleanTime = otherCleanTime; | 2122 | land.LandData.OtherCleanTime = otherCleanTime; |
1947 | 2123 | ||
1948 | UpdateLandObject(localID, land.LandData); | 2124 | UpdateLandObject(localID, land.LandData); |
1949 | } | 2125 | } |
1950 | 2126 | ||
2127 | public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID) | ||
2128 | { | ||
2129 | ILandObject land = null; | ||
2130 | List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels(); | ||
2131 | foreach (ILandObject landObject in Land) | ||
2132 | { | ||
2133 | if (landObject.LandData.LocalID == landID) | ||
2134 | { | ||
2135 | land = landObject; | ||
2136 | } | ||
2137 | } | ||
2138 | land.DeedToGroup(DefaultGodParcelGroup); | ||
2139 | land.LandData.Name = DefaultGodParcelName; | ||
2140 | land.SendLandUpdateToAvatarsOverMe(); | ||
2141 | } | ||
2142 | |||
2143 | private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID) | ||
2144 | { | ||
2145 | ScenePresence SP; | ||
2146 | ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP); | ||
2147 | List<SceneObjectGroup> returns = new List<SceneObjectGroup>(); | ||
2148 | if (SP.GodController.UserLevel != 0) | ||
2149 | { | ||
2150 | if (flags == 0) //All parcels, scripted or not | ||
2151 | { | ||
2152 | ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) | ||
2153 | { | ||
2154 | if (e.OwnerID == targetID) | ||
2155 | { | ||
2156 | returns.Add(e); | ||
2157 | } | ||
2158 | } | ||
2159 | ); | ||
2160 | } | ||
2161 | if (flags == 4) //All parcels, scripted object | ||
2162 | { | ||
2163 | ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) | ||
2164 | { | ||
2165 | if (e.OwnerID == targetID) | ||
2166 | { | ||
2167 | if (e.ContainsScripts()) | ||
2168 | { | ||
2169 | returns.Add(e); | ||
2170 | } | ||
2171 | } | ||
2172 | }); | ||
2173 | } | ||
2174 | if (flags == 4) //not target parcel, scripted object | ||
2175 | { | ||
2176 | ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) | ||
2177 | { | ||
2178 | if (e.OwnerID == targetID) | ||
2179 | { | ||
2180 | ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y); | ||
2181 | if (landobject.LandData.OwnerID != e.OwnerID) | ||
2182 | { | ||
2183 | if (e.ContainsScripts()) | ||
2184 | { | ||
2185 | returns.Add(e); | ||
2186 | } | ||
2187 | } | ||
2188 | } | ||
2189 | }); | ||
2190 | } | ||
2191 | foreach (SceneObjectGroup ol in returns) | ||
2192 | { | ||
2193 | ReturnObject(ol, client); | ||
2194 | } | ||
2195 | } | ||
2196 | } | ||
2197 | public void ReturnObject(SceneObjectGroup obj, IClientAPI client) | ||
2198 | { | ||
2199 | SceneObjectGroup[] objs = new SceneObjectGroup[1]; | ||
2200 | objs[0] = obj; | ||
2201 | ((Scene)client.Scene).returnObjects(objs, client); | ||
2202 | } | ||
2203 | |||
1951 | Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); | 2204 | Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); |
1952 | 2205 | ||
1953 | public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) | 2206 | public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) |
@@ -1958,12 +2211,12 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1958 | ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager); | 2211 | ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager); |
1959 | System.Threading.Timer Timer; | 2212 | System.Threading.Timer Timer; |
1960 | 2213 | ||
1961 | if (targetAvatar.UserLevel == 0) | 2214 | if (targetAvatar.GodController.UserLevel < 200) |
1962 | { | 2215 | { |
1963 | ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); | 2216 | 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)) | 2217 | if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true)) |
1965 | return; | 2218 | return; |
1966 | if (flags == 0) | 2219 | if ((flags & 1) == 0) // only lowest bit has meaning for now |
1967 | { | 2220 | { |
1968 | targetAvatar.AllowMovement = false; | 2221 | 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."); | 2222 | targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world."); |
@@ -1983,7 +2236,6 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1983 | } | 2236 | } |
1984 | } | 2237 | } |
1985 | } | 2238 | } |
1986 | |||
1987 | private void OnEndParcelFrozen(object avatar) | 2239 | private void OnEndParcelFrozen(object avatar) |
1988 | { | 2240 | { |
1989 | ScenePresence targetAvatar = (ScenePresence)avatar; | 2241 | ScenePresence targetAvatar = (ScenePresence)avatar; |
@@ -2010,12 +2262,13 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2010 | 2262 | ||
2011 | // Check if you even have permission to do this | 2263 | // Check if you even have permission to do this |
2012 | ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); | 2264 | ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); |
2013 | if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) && | 2265 | if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true) && |
2014 | !m_scene.Permissions.IsAdministrator(client.AgentId)) | 2266 | !m_scene.Permissions.IsAdministrator(client.AgentId)) |
2015 | return; | 2267 | return; |
2268 | |||
2016 | Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); | 2269 | Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); |
2017 | 2270 | ||
2018 | targetAvatar.TeleportWithMomentum(pos, null); | 2271 | targetAvatar.TeleportOnEject(pos); |
2019 | targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); | 2272 | targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); |
2020 | parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); | 2273 | parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); |
2021 | 2274 | ||
@@ -2059,7 +2312,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2059 | if (// Required: local user; foreign users cannot set home | 2312 | if (// Required: local user; foreign users cannot set home |
2060 | m_scene.UserManagementModule.IsLocalGridUser(remoteClient.AgentId) && | 2313 | m_scene.UserManagementModule.IsLocalGridUser(remoteClient.AgentId) && |
2061 | (// (a) gods and land managers can set home | 2314 | (// (a) gods and land managers can set home |
2062 | m_scene.Permissions.IsAdministrator(remoteClient.AgentId) || | 2315 | m_scene.Permissions.IsAdministrator(remoteClient.AgentId) || |
2063 | m_scene.Permissions.IsGod(remoteClient.AgentId) || | 2316 | m_scene.Permissions.IsGod(remoteClient.AgentId) || |
2064 | // (b) land owners can set home | 2317 | // (b) land owners can set home |
2065 | remoteClient.AgentId == land.LandData.OwnerID || | 2318 | remoteClient.AgentId == land.LandData.OwnerID || |
@@ -2111,8 +2364,8 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2111 | "If no local land ID is given, then summary information about all the parcels is shown.\n" | 2364 | "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.", | 2365 | + "If a local land ID is given then full information about that parcel is shown.", |
2113 | HandleShowCommand); | 2366 | HandleShowCommand); |
2114 | } | 2367 | } |
2115 | 2368 | ||
2116 | protected void HandleClearCommand(string module, string[] args) | 2369 | protected void HandleClearCommand(string module, string[] args) |
2117 | { | 2370 | { |
2118 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) | 2371 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) |
@@ -2120,9 +2373,9 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2120 | 2373 | ||
2121 | string response = MainConsole.Instance.CmdPrompt( | 2374 | string response = MainConsole.Instance.CmdPrompt( |
2122 | string.Format( | 2375 | string.Format( |
2123 | "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name), | 2376 | "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name), |
2124 | "n"); | 2377 | "n"); |
2125 | 2378 | ||
2126 | if (response.ToLower() == "y") | 2379 | if (response.ToLower() == "y") |
2127 | { | 2380 | { |
2128 | Clear(true); | 2381 | Clear(true); |
@@ -2132,14 +2385,14 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2132 | { | 2385 | { |
2133 | MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name); | 2386 | MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name); |
2134 | } | 2387 | } |
2135 | } | 2388 | } |
2136 | 2389 | ||
2137 | protected void HandleShowCommand(string module, string[] args) | 2390 | protected void HandleShowCommand(string module, string[] args) |
2138 | { | 2391 | { |
2139 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) | 2392 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) |
2140 | return; | 2393 | return; |
2141 | 2394 | ||
2142 | StringBuilder report = new StringBuilder(); | 2395 | StringBuilder report = new StringBuilder(); |
2143 | 2396 | ||
2144 | if (args.Length <= 2) | 2397 | if (args.Length <= 2) |
2145 | { | 2398 | { |
@@ -2152,10 +2405,10 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2152 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId)) | 2405 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId)) |
2153 | return; | 2406 | return; |
2154 | 2407 | ||
2155 | ILandObject lo; | 2408 | ILandObject lo = null; |
2156 | 2409 | ||
2157 | lock (m_landList) | 2410 | lock (m_landList) |
2158 | { | 2411 | { |
2159 | if (!m_landList.TryGetValue(landLocalId, out lo)) | 2412 | if (!m_landList.TryGetValue(landLocalId, out lo)) |
2160 | { | 2413 | { |
2161 | MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId); | 2414 | MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId); |
@@ -2170,7 +2423,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2170 | } | 2423 | } |
2171 | 2424 | ||
2172 | private void AppendParcelsSummaryReport(StringBuilder report) | 2425 | private void AppendParcelsSummaryReport(StringBuilder report) |
2173 | { | 2426 | { |
2174 | report.AppendFormat("Land information for {0}\n", m_scene.Name); | 2427 | report.AppendFormat("Land information for {0}\n", m_scene.Name); |
2175 | 2428 | ||
2176 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); | 2429 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
@@ -2180,7 +2433,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2180 | cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize); | 2433 | cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize); |
2181 | cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize); | 2434 | cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize); |
2182 | cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize); | 2435 | cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize); |
2183 | 2436 | ||
2184 | lock (m_landList) | 2437 | lock (m_landList) |
2185 | { | 2438 | { |
2186 | foreach (ILandObject lo in m_landList.Values) | 2439 | foreach (ILandObject lo in m_landList.Values) |
@@ -2202,7 +2455,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2202 | } | 2455 | } |
2203 | 2456 | ||
2204 | report.Append(cdt.ToString()); | 2457 | report.Append(cdt.ToString()); |
2205 | } | 2458 | } |
2206 | 2459 | ||
2207 | private void AppendParcelReport(StringBuilder report, ILandObject lo) | 2460 | private void AppendParcelReport(StringBuilder report, ILandObject lo) |
2208 | { | 2461 | { |
@@ -2214,8 +2467,6 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2214 | cdl.AddRow("Description", ld.Description); | 2467 | cdl.AddRow("Description", ld.Description); |
2215 | cdl.AddRow("Snapshot ID", ld.SnapshotID); | 2468 | cdl.AddRow("Snapshot ID", ld.SnapshotID); |
2216 | cdl.AddRow("Area", ld.Area); | 2469 | cdl.AddRow("Area", ld.Area); |
2217 | cdl.AddRow("Starts", lo.StartPoint); | ||
2218 | cdl.AddRow("Ends", lo.EndPoint); | ||
2219 | cdl.AddRow("AABB Min", ld.AABBMin); | 2470 | cdl.AddRow("AABB Min", ld.AABBMin); |
2220 | cdl.AddRow("AABB Max", ld.AABBMax); | 2471 | cdl.AddRow("AABB Max", ld.AABBMax); |
2221 | string ownerName; | 2472 | string ownerName; |
@@ -2233,7 +2484,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2233 | cdl.AddRow("GroupID", ld.GroupID); | 2484 | cdl.AddRow("GroupID", ld.GroupID); |
2234 | 2485 | ||
2235 | cdl.AddRow("Status", ld.Status); | 2486 | cdl.AddRow("Status", ld.Status); |
2236 | cdl.AddRow("Flags", (ParcelFlags)ld.Flags); | 2487 | cdl.AddRow("Flags", (ParcelFlags)ld.Flags); |
2237 | 2488 | ||
2238 | cdl.AddRow("Landing Type", (LandingType)ld.LandingType); | 2489 | cdl.AddRow("Landing Type", (LandingType)ld.LandingType); |
2239 | cdl.AddRow("User Location", ld.UserLocation); | 2490 | cdl.AddRow("User Location", ld.UserLocation); |
@@ -2242,12 +2493,14 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
2242 | cdl.AddRow("Other clean time", ld.OtherCleanTime); | 2493 | cdl.AddRow("Other clean time", ld.OtherCleanTime); |
2243 | 2494 | ||
2244 | cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount()); | 2495 | cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount()); |
2496 | cdl.AddRow("Simwide Max Prims (owner)", lo.GetSimulatorMaxPrimCount()); | ||
2245 | IPrimCounts pc = lo.PrimCounts; | 2497 | IPrimCounts pc = lo.PrimCounts; |
2246 | cdl.AddRow("Owner Prims", pc.Owner); | 2498 | cdl.AddRow("Owner Prims", pc.Owner); |
2247 | cdl.AddRow("Group Prims", pc.Group); | 2499 | cdl.AddRow("Group Prims", pc.Group); |
2248 | cdl.AddRow("Other Prims", pc.Others); | 2500 | cdl.AddRow("Other Prims", pc.Others); |
2249 | cdl.AddRow("Selected Prims", pc.Selected); | 2501 | cdl.AddRow("Selected Prims", pc.Selected); |
2250 | cdl.AddRow("Total Prims", pc.Total); | 2502 | cdl.AddRow("Total Prims", pc.Total); |
2503 | cdl.AddRow("SimWide Prims (owner)", pc.Simulator); | ||
2251 | 2504 | ||
2252 | cdl.AddRow("Music URL", ld.MusicURL); | 2505 | cdl.AddRow("Music URL", ld.MusicURL); |
2253 | cdl.AddRow("Obscure Music", ld.ObscureMusic); | 2506 | cdl.AddRow("Obscure Music", ld.ObscureMusic); |