aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/World')
-rw-r--r--OpenSim/Region/CoreModules/World/Access/AccessModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs363
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs122
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs232
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs39
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs209
-rw-r--r--OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs86
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateConnector.cs (renamed from OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs)62
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs38
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs663
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateModule.cs (renamed from OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs)64
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs (renamed from OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs)24
-rw-r--r--OpenSim/Region/CoreModules/World/Land/DwellModule.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs62
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs1333
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs883
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs177
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs40
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs224
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs53
-rw-r--r--OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs255
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs36
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs120
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2054
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs91
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs186
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs174
-rw-r--r--OpenSim/Region/CoreModules/World/Sun/SunModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs81
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs14
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs29
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs32
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs14
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs20
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs704
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs381
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs19
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs21
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs167
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs1601
79 files changed, 7001 insertions, 4346 deletions
diff --git a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
index f567cab..081439a 100644
--- a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
+++ b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.CoreModules.World
44 public class AccessModule : ISharedRegionModule 44 public class AccessModule : ISharedRegionModule
45 { 45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private List<Scene> m_SceneList = new List<Scene>(); 48 private List<Scene> m_SceneList = new List<Scene>();
49 49
50 public void Initialise(IConfigSource config) 50 public void Initialise(IConfigSource config)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 9c6706f..41515c0 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -40,6 +40,7 @@ using OpenSim.Framework.Monitoring;
40using OpenSim.Framework.Serialization; 40using OpenSim.Framework.Serialization;
41using OpenSim.Framework.Serialization.External; 41using OpenSim.Framework.Serialization.External;
42using OpenSim.Region.CoreModules.World.Terrain; 42using OpenSim.Region.CoreModules.World.Terrain;
43using OpenSim.Region.CoreModules.World.Land;
43using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.Framework.Scenes.Serialization; 46using OpenSim.Region.Framework.Scenes.Serialization;
@@ -76,14 +77,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
76 SceneObjects = new List<SceneObjectGroup>(); 77 SceneObjects = new List<SceneObjectGroup>();
77 } 78 }
78 } 79 }
79 80
80 81
81 /// <summary> 82 /// <summary>
82 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version 83 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
83 /// bumps here should be compatible. 84 /// bumps here should be compatible.
84 /// </summary> 85 /// </summary>
85 public static int MAX_MAJOR_VERSION = 1; 86 public static int MAX_MAJOR_VERSION = 1;
86 87
87 /// <summary> 88 /// <summary>
88 /// Has the control file been loaded for this archive? 89 /// Has the control file been loaded for this archive?
89 /// </summary> 90 /// </summary>
@@ -126,12 +127,29 @@ namespace OpenSim.Region.CoreModules.World.Archiver
126 /// </value> 127 /// </value>
127 protected float m_rotation = 0f; 128 protected float m_rotation = 0f;
128 129
130 /// <value>
131 /// original oar region size. not using Constants.RegionSize
132 /// </value>
133 protected Vector3 m_incomingRegionSize = new Vector3(256f, 256f, float.MaxValue);
134
135 /// <value>
136 /// Center around which to apply the rotation relative to the original oar position
137 /// </value>
138 protected Vector3 m_rotationCenter = new Vector3(128f, 128f, 0f);
139
140 /// <value>
141 /// Corner 1 of a bounding cuboid which specifies which objects we load from the oar
142 /// </value>
143 protected Vector3 m_boundingOrigin = Vector3.Zero;
144
129 /// <value> 145 /// <value>
130 /// Center around which to apply the rotation relative to the origional oar position 146 /// Size of a bounding cuboid which specifies which objects we load from the oar
131 /// </value> 147 /// </value>
132 protected Vector3 m_rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f); 148 protected Vector3 m_boundingSize = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, float.MaxValue);
133 149
134 protected bool m_noObjects = false; 150 protected bool m_noObjects = false;
151 protected bool m_boundingBox = false;
152 protected bool m_debug = false;
135 153
136 /// <summary> 154 /// <summary>
137 /// Used to cache lookups for valid uuids. 155 /// Used to cache lookups for valid uuids.
@@ -160,10 +178,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
160 178
161 private IAssetService m_assetService = null; 179 private IAssetService m_assetService = null;
162 180
163
164 private UUID m_defaultUser; 181 private UUID m_defaultUser;
165 182
166 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string,object>options) 183 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options)
167 { 184 {
168 m_rootScene = scene; 185 m_rootScene = scene;
169 186
@@ -172,7 +189,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
172 m_defaultUser = (UUID)options["default-user"]; 189 m_defaultUser = (UUID)options["default-user"];
173 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString()); 190 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString());
174 } 191 }
175 else 192 else
176 { 193 {
177 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 194 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
178 } 195 }
@@ -189,8 +206,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
189 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 206 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
190 m_log.Error(e); 207 m_log.Error(e);
191 } 208 }
192 209
193 m_errorMessage = String.Empty; 210 m_errorMessage = String.Empty;
211
194 m_merge = options.ContainsKey("merge"); 212 m_merge = options.ContainsKey("merge");
195 m_forceTerrain = options.ContainsKey("force-terrain"); 213 m_forceTerrain = options.ContainsKey("force-terrain");
196 m_forceParcels = options.ContainsKey("force-parcels"); 214 m_forceParcels = options.ContainsKey("force-parcels");
@@ -199,10 +217,45 @@ namespace OpenSim.Region.CoreModules.World.Archiver
199 m_requestId = requestId; 217 m_requestId = requestId;
200 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero; 218 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
201 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f; 219 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
202 m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
203 : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
204 220
205 // Zero can never be a valid user or group id 221 m_boundingOrigin = Vector3.Zero;
222 m_boundingSize = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, float.MaxValue);
223
224 if (options.ContainsKey("bounding-origin"))
225 {
226 Vector3 boOption = (Vector3)options["bounding-origin"];
227 if (boOption != m_boundingOrigin)
228 {
229 m_boundingOrigin = boOption;
230 }
231 m_boundingBox = true;
232 }
233
234 if (options.ContainsKey("bounding-size"))
235 {
236 Vector3 bsOption = (Vector3)options["bounding-size"];
237 bool clip = false;
238 if (bsOption.X <= 0 || bsOption.X > m_boundingSize.X)
239 {
240 bsOption.X = m_boundingSize.X;
241 clip = true;
242 }
243 if (bsOption.Y <= 0 || bsOption.Y > m_boundingSize.Y)
244 {
245 bsOption.Y = m_boundingSize.Y;
246 clip = true;
247 }
248 if (bsOption != m_boundingSize)
249 {
250 m_boundingSize = bsOption;
251 m_boundingBox = true;
252 }
253 if (clip) m_log.InfoFormat("[ARCHIVER]: The bounding cube specified is larger than the destination region! Clipping to {0}.", m_boundingSize.ToString());
254 }
255
256 m_debug = options.ContainsKey("debug");
257
258 // Zero can never be a valid user id (or group)
206 m_validUserUuids[UUID.Zero] = false; 259 m_validUserUuids[UUID.Zero] = false;
207 m_validGroupUuids[UUID.Zero] = false; 260 m_validGroupUuids[UUID.Zero] = false;
208 261
@@ -210,7 +263,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
210 m_assetService = m_rootScene.AssetService; 263 m_assetService = m_rootScene.AssetService;
211 } 264 }
212 265
213 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object>options) 266 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object> options)
214 { 267 {
215 m_rootScene = scene; 268 m_rootScene = scene;
216 m_loadPath = null; 269 m_loadPath = null;
@@ -220,7 +273,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
220 m_requestId = requestId; 273 m_requestId = requestId;
221 274
222 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 275 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
223 276
224 // Zero can never be a valid user id 277 // Zero can never be a valid user id
225 m_validUserUuids[UUID.Zero] = false; 278 m_validUserUuids[UUID.Zero] = false;
226 279
@@ -233,6 +286,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
233 /// </summary> 286 /// </summary>
234 public void DearchiveRegion() 287 public void DearchiveRegion()
235 { 288 {
289 DearchiveRegion(true);
290 }
291
292 public void DearchiveRegion(bool shouldStartScripts)
293 {
236 int successfulAssetRestores = 0; 294 int successfulAssetRestores = 0;
237 int failedAssetRestores = 0; 295 int failedAssetRestores = 0;
238 296
@@ -255,7 +313,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
255 { 313 {
256 //m_log.DebugFormat( 314 //m_log.DebugFormat(
257 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); 315 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
258 316
259 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 317 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
260 continue; 318 continue;
261 319
@@ -301,11 +359,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
301 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) 359 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
302 { 360 {
303 LoadRegionSettings(scene, filePath, data, dearchivedScenes); 361 LoadRegionSettings(scene, filePath, data, dearchivedScenes);
304 } 362 }
305 else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH) && (!m_merge || m_forceParcels)) 363 else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH) && (!m_merge || m_forceParcels))
306 { 364 {
307 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); 365 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
308 } 366 }
309 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 367 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
310 { 368 {
311 // Ignore, because we already read the control file 369 // Ignore, because we already read the control file
@@ -353,7 +411,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
353 { 411 {
354 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels); 412 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
355 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects); 413 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
356 414
357 // Inform any interested parties that the region has changed. We waited until now so that all 415 // Inform any interested parties that the region has changed. We waited until now so that all
358 // of the region's objects will be loaded when we send this notification. 416 // of the region's objects will be loaded when we send this notification.
359 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>(); 417 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
@@ -372,22 +430,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
372 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so 430 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
373 // that users can enter the scene. If we allow the scripts to start in the loop above 431 // that users can enter the scene. If we allow the scripts to start in the loop above
374 // then they significantly increase the time until the OAR finishes loading. 432 // then they significantly increase the time until the OAR finishes loading.
375 WorkManager.RunInThread(o => 433 if (shouldStartScripts)
376 { 434 {
377 Thread.Sleep(15000); 435 WorkManager.RunInThread(o =>
378 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
379
380 foreach (DearchiveContext sceneContext in sceneContexts.Values)
381 { 436 {
382 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) 437 Thread.Sleep(15000);
438 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
439
440 foreach (DearchiveContext sceneContext in sceneContexts.Values)
383 { 441 {
384 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart 442 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
385 sceneObject.ResumeScripts(); 443 {
386 } 444 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
445 sceneObject.ResumeScripts();
446 }
387 447
388 sceneContext.SceneObjects.Clear(); 448 sceneContext.SceneObjects.Clear();
389 } 449 }
390 }, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId)); 450 }, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId));
451 }
391 452
392 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); 453 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
393 454
@@ -418,7 +479,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
418 { 479 {
419 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 480 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
420 continue; 481 continue;
421 482
422 if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 483 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
423 { 484 {
424 LoadControlFile(filePath, data, dearchivedScenes); 485 LoadControlFile(filePath, data, dearchivedScenes);
@@ -435,7 +496,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
435 // If the control file wasn't the first file then reset the read pointer 496 // If the control file wasn't the first file then reset the read pointer
436 if (!firstFile) 497 if (!firstFile)
437 { 498 {
438 m_log.Warn("Control file wasn't the first file in the archive"); 499 m_log.Warn("[ARCHIVER]: Control file wasn't the first file in the archive");
439 if (m_loadStream.CanSeek) 500 if (m_loadStream.CanSeek)
440 { 501 {
441 m_loadStream.Seek(0, SeekOrigin.Begin); 502 m_loadStream.Seek(0, SeekOrigin.Begin);
@@ -452,7 +513,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
452 else 513 else
453 { 514 {
454 // There isn't currently a scenario where this happens, but it's best to add a check just in case 515 // There isn't currently a scenario where this happens, but it's best to add a check just in case
455 throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking"); 516 throw new Exception("[ARCHIVER]: Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
456 } 517 }
457 } 518 }
458 519
@@ -462,9 +523,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
462 firstFile = false; 523 firstFile = false;
463 } 524 }
464 525
465 throw new Exception("Control file not found"); 526 throw new Exception("[ARCHIVER]: Control file not found");
466 } 527 }
467 528
468 /// <summary> 529 /// <summary>
469 /// Load serialized scene objects. 530 /// Load serialized scene objects.
470 /// </summary> 531 /// </summary>
@@ -473,12 +534,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
473 // Reload serialized prims 534 // Reload serialized prims
474 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); 535 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
475 536
476 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation); 537 // Convert rotation to radians
538 double rotation = Math.PI * m_rotation / 180f;
539
540 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, (float)rotation);
477 541
478 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; 542 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
479 543
480 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); 544 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
481 int sceneObjectsLoadedCount = 0; 545 int sceneObjectsLoadedCount = 0;
546 Vector3 boundingExtent = new Vector3(m_boundingOrigin.X + m_boundingSize.X, m_boundingOrigin.Y + m_boundingSize.Y, m_boundingOrigin.Z + m_boundingSize.Z);
482 547
483 foreach (string serialisedSceneObject in serialisedSceneObjects) 548 foreach (string serialisedSceneObject in serialisedSceneObjects)
484 { 549 {
@@ -488,7 +553,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
488 // Really large xml files (multi megabyte) appear to cause 553 // Really large xml files (multi megabyte) appear to cause
489 // memory problems 554 // memory problems
490 // when loading the xml. But don't enable this check yet 555 // when loading the xml. But don't enable this check yet
491 556
492 if (serialisedSceneObject.Length > 5000000) 557 if (serialisedSceneObject.Length > 5000000)
493 { 558 {
494 m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);"); 559 m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);");
@@ -498,31 +563,52 @@ namespace OpenSim.Region.CoreModules.World.Archiver
498 563
499 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); 564 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
500 565
566 Vector3 pos = sceneObject.AbsolutePosition;
567 if (m_debug)
568 m_log.DebugFormat("[ARCHIVER]: Loading object from OAR with original scene position {0}.", pos.ToString());
569
501 // Happily this does not do much to the object since it hasn't been added to the scene yet 570 // Happily this does not do much to the object since it hasn't been added to the scene yet
502 if (!sceneObject.IsAttachment) 571 if (!sceneObject.IsAttachment)
503 { 572 {
504 if (m_displacement != Vector3.Zero || m_rotation != 0f) 573 if (m_rotation != 0f)
505 { 574 {
506 Vector3 pos = sceneObject.AbsolutePosition; 575 //fix the rotation center to the middle of the incoming region now as it's otherwise hopelessly confusing on varRegions
507 if (m_rotation != 0f) 576 //as it only works with objects and terrain (using old Merge method) and not parcels
508 { 577 m_rotationCenter.X = m_incomingRegionSize.X / 2;
509 // Rotate the object 578 m_rotationCenter.Y = m_incomingRegionSize.Y / 2;
510 sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation; 579
511 // Get object position relative to rotation axis 580 // Rotate the object
512 Vector3 offset = pos - m_rotationCenter; 581 sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
513 // Rotate the object position 582 // Get object position relative to rotation axis
514 offset *= rot; 583 Vector3 offset = pos - m_rotationCenter;
515 // Restore the object position back to relative to the region 584 // Rotate the object position
516 pos = m_rotationCenter + offset; 585 offset *= rot;
517 } 586 // Restore the object position back to relative to the region
518 if (m_displacement != Vector3.Zero) 587 pos = m_rotationCenter + offset;
588 if (m_debug) m_log.DebugFormat("[ARCHIVER]: After rotation, object from OAR is at scene position {0}.", pos.ToString());
589 }
590 if (m_boundingBox)
591 {
592 if (pos.X < m_boundingOrigin.X || pos.X >= boundingExtent.X
593 || pos.Y < m_boundingOrigin.Y || pos.Y >= boundingExtent.Y
594 || pos.Z < m_boundingOrigin.Z || pos.Z >= boundingExtent.Z)
519 { 595 {
520 pos += m_displacement; 596 if (m_debug) m_log.DebugFormat("[ARCHIVER]: Skipping object from OAR in scene because it's position {0} is outside of bounding cube.", pos.ToString());
597 continue;
521 } 598 }
522 sceneObject.AbsolutePosition = pos; 599 //adjust object position to be relative to <0,0> so we can apply the displacement
600 pos.X -= m_boundingOrigin.X;
601 pos.Y -= m_boundingOrigin.Y;
602 }
603 if (m_displacement != Vector3.Zero)
604 {
605 pos += m_displacement;
606 if (m_debug) m_log.DebugFormat("[ARCHIVER]: After displacement, object from OAR is at scene position {0}.", pos.ToString());
523 } 607 }
608 sceneObject.AbsolutePosition = pos;
524 } 609 }
525 610 if (m_debug)
611 m_log.DebugFormat("[ARCHIVER]: Placing object from OAR in scene at position {0}. ", pos.ToString());
526 612
527 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); 613 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
528 614
@@ -554,11 +640,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
554 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount; 640 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;
555 641
556 if (ignoredObjects > 0) 642 if (ignoredObjects > 0)
557 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); 643 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene or were out of bounds", ignoredObjects);
558 644
559 if (oldTelehubUUID != UUID.Zero) 645 if (oldTelehubUUID != UUID.Zero)
560 { 646 {
561 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); 647 m_log.WarnFormat("[ARCHIVER]: Telehub object not found: {0}", oldTelehubUUID);
562 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; 648 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
563 scene.RegionInfo.RegionSettings.ClearSpawnPoints(); 649 scene.RegionInfo.RegionSettings.ClearSpawnPoints();
564 } 650 }
@@ -600,6 +686,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
600 // being no copy/no mod for everyone 686 // being no copy/no mod for everyone
601 lock (part.TaskInventory) 687 lock (part.TaskInventory)
602 { 688 {
689/* avination code disabled for opensim
690 // And zap any troublesome sit target information
691 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
692 part.SitTargetPosition = new Vector3(0, 0, 0);
693*/
694 // Fix ownership/creator of inventory items
695 // Not doing so results in inventory items
696 // being no copy/no mod for everyone
697 part.TaskInventory.LockItemsForRead(true);
698
603 TaskInventoryDictionary inv = part.TaskInventory; 699 TaskInventoryDictionary inv = part.TaskInventory;
604 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 700 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
605 { 701 {
@@ -620,11 +716,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
620 if (!ResolveGroupUuid(kvp.Value.GroupID)) 716 if (!ResolveGroupUuid(kvp.Value.GroupID))
621 kvp.Value.GroupID = UUID.Zero; 717 kvp.Value.GroupID = UUID.Zero;
622 } 718 }
719 part.TaskInventory.LockItemsForRead(false);
720
623 } 721 }
624 } 722 }
625 } 723 }
626 724
627
628 /// <summary> 725 /// <summary>
629 /// Load serialized parcels. 726 /// Load serialized parcels.
630 /// </summary> 727 /// </summary>
@@ -635,17 +732,88 @@ namespace OpenSim.Region.CoreModules.World.Archiver
635 // Reload serialized parcels 732 // Reload serialized parcels
636 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); 733 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
637 List<LandData> landData = new List<LandData>(); 734 List<LandData> landData = new List<LandData>();
735 ILandObject landObject = scene.RequestModuleInterface<ILandObject>();
736 List<ILandObject> parcels;
737 Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
738 Vector2 displacement = new Vector2(m_displacement.X, m_displacement.Y);
739 Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
740 Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
741 Vector2 regionSize = new Vector2(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY);
742
743 // Gather any existing parcels before we add any more. Later as we add parcels we can check if the new parcel
744 // data overlays any of the old data, and we can modify and remove (if empty) the old parcel so that there's no conflict
745 parcels = scene.LandChannel.AllParcels();
746
638 foreach (string serialisedParcel in serialisedParcels) 747 foreach (string serialisedParcel in serialisedParcels)
639 { 748 {
640 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); 749 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
750 bool overrideRegionSize = true; //use the src land parcel data size not the dst region size
751 bool isEmptyNow;
752 Vector3 AABBMin;
753 Vector3 AABBMax;
754
755 // create a new LandObject that we can use to manipulate the incoming source parcel data
756 // this is ok, but just beware that some of the LandObject functions (that we haven't used here) still
757 // assume we're always using the destination region size
758 LandData ld = new LandData();
759 landObject = new LandObject(ld, scene);
760 landObject.LandData = parcel;
761
762 bool[,] srcLandBitmap = landObject.ConvertBytesToLandBitmap(overrideRegionSize);
763 if (landObject.IsLandBitmapEmpty(srcLandBitmap))
764 {
765 m_log.InfoFormat("[ARCHIVER]: Skipping source parcel {0} with GlobalID: {1} LocalID: {2} that has no claimed land.",
766 parcel.Name, parcel.GlobalID, parcel.LocalID);
767 continue;
768 }
769 //m_log.DebugFormat("[ARCHIVER]: Showing claimed land for source parcel: {0} with GlobalID: {1} LocalID: {2}.",
770 // parcel.Name, parcel.GlobalID, parcel.LocalID);
771 //landObject.DebugLandBitmap(srcLandBitmap);
772
773 bool[,] dstLandBitmap = landObject.RemapLandBitmap(srcLandBitmap, displacement, m_rotation, boundingOrigin, boundingSize, regionSize, out isEmptyNow, out AABBMin, out AABBMax);
774 if (isEmptyNow)
775 {
776 m_log.WarnFormat("[ARCHIVER]: Not adding destination parcel {0} with GlobalID: {1} LocalID: {2} because, after applying rotation, bounding and displacement, it has no claimed land.",
777 parcel.Name, parcel.GlobalID, parcel.LocalID);
778 continue;
779 }
780 //m_log.DebugFormat("[ARCHIVER]: Showing claimed land for destination parcel: {0} with GlobalID: {1} LocalID: {2} after applying rotation, bounding and displacement.",
781 // parcel.Name, parcel.GlobalID, parcel.LocalID);
782 //landObject.DebugLandBitmap(dstLandBitmap);
783
784 landObject.LandBitmap = dstLandBitmap;
785 parcel.Bitmap = landObject.ConvertLandBitmapToBytes();
786 parcel.AABBMin = AABBMin;
787 parcel.AABBMax = AABBMax;
641 788
642 if (m_displacement != Vector3.Zero) 789 if (m_merge)
643 { 790 {
644 Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f); 791 // give the remapped parcel a new GlobalID, in case we're using the same OAR twice and a bounding cube, displacement and --merge
645 parcel.AABBMin += parcelDisp; 792 parcel.GlobalID = UUID.Random();
646 parcel.AABBMax += parcelDisp; 793
794 //now check if the area of this new incoming parcel overlays an area in any existing parcels
795 //and if so modify or lose the existing parcels
796 for (int i = 0; i < parcels.Count; i++)
797 {
798 if (parcels[i] != null)
799 {
800 bool[,] modLandBitmap = parcels[i].ConvertBytesToLandBitmap(overrideRegionSize);
801 modLandBitmap = parcels[i].RemoveFromLandBitmap(modLandBitmap, dstLandBitmap, out isEmptyNow, out AABBMin, out AABBMax);
802 if (isEmptyNow)
803 {
804 parcels[i] = null;
805 }
806 else
807 {
808 parcels[i].LandBitmap = modLandBitmap;
809 parcels[i].LandData.Bitmap = parcels[i].ConvertLandBitmapToBytes();
810 parcels[i].LandData.AABBMin = AABBMin;
811 parcels[i].LandData.AABBMax = AABBMax;
812 }
813 }
814 }
647 } 815 }
648 816
649 // Validate User and Group UUID's 817 // Validate User and Group UUID's
650 818
651 if (!ResolveGroupUuid(parcel.GroupID)) 819 if (!ResolveGroupUuid(parcel.GroupID))
@@ -679,19 +847,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
679 } 847 }
680 parcel.ParcelAccessList = accessList; 848 parcel.ParcelAccessList = accessList;
681 849
682// m_log.DebugFormat( 850 if (m_debug) m_log.DebugFormat("[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
683// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}", 851 parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
684// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area); 852
685
686 landData.Add(parcel); 853 landData.Add(parcel);
687 } 854 }
688 855
689 if (!m_merge) 856 if (m_merge)
690 { 857 {
691 bool setupDefaultParcel = (landData.Count == 0); 858 for (int i = 0; i < parcels.Count; i++) //if merging then we need to also add back in any existing parcels
692 scene.LandChannel.Clear(setupDefaultParcel); 859 {
860 if (parcels[i] != null) landData.Add(parcels[i].LandData);
861 }
693 } 862 }
694 863
864 m_log.InfoFormat("[ARCHIVER]: Clearing {0} parcels.", parcels.Count);
865 bool setupDefaultParcel = (landData.Count == 0);
866 scene.LandChannel.Clear(setupDefaultParcel);
695 scene.EventManager.TriggerIncomingLandDataFromStorage(landData); 867 scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
696 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); 868 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
697 } 869 }
@@ -772,6 +944,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
772 944
773 if (m_assetService.GetMetadata(uuid) != null) 945 if (m_assetService.GetMetadata(uuid) != null)
774 { 946 {
947 sbyte asype = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
948 if(asype == -2)
949 {
950
951 }
952
775 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); 953 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
776 return true; 954 return true;
777 } 955 }
@@ -780,6 +958,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
780 { 958 {
781 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; 959 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
782 960
961 if(assetType == -2)
962 {
963
964 }
783 if (assetType == (sbyte)AssetType.Unknown) 965 if (assetType == (sbyte)AssetType.Unknown)
784 { 966 {
785 m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid); 967 m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
@@ -792,7 +974,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
792 ModifySceneObject(m_rootScene, sog); 974 ModifySceneObject(m_rootScene, sog);
793 return true; 975 return true;
794 }); 976 });
795 977
796 if (data == null) 978 if (data == null)
797 return false; 979 return false;
798 } 980 }
@@ -898,7 +1080,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
898 currentRegionSettings.Save(); 1080 currentRegionSettings.Save();
899 1081
900 scene.TriggerEstateSunUpdate(); 1082 scene.TriggerEstateSunUpdate();
901 1083
902 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>(); 1084 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
903 if (estateModule != null) 1085 if (estateModule != null)
904 estateModule.sendRegionHandshakeToAll(); 1086 estateModule.sendRegionHandshakeToAll();
@@ -918,13 +1100,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
918 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) 1100 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
919 { 1101 {
920 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); 1102 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
921
922 using (MemoryStream ms = new MemoryStream(data)) 1103 using (MemoryStream ms = new MemoryStream(data))
923 { 1104 {
924 if (m_displacement != Vector3.Zero || m_rotation != 0f) 1105 if (m_displacement != Vector3.Zero || m_rotation != 0f || m_boundingBox)
925 { 1106 {
926 Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y); 1107 Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
927 terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms); 1108 Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
1109 terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, boundingOrigin, boundingSize, ms); ;
928 } 1110 }
929 else 1111 else
930 { 1112 {
@@ -948,6 +1130,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
948 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 1130 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
949 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 1131 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
950 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); 1132 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
1133 xtr.ProhibitDtd = true;
951 1134
952 // Loaded metadata will be empty if no information exists in the archive 1135 // Loaded metadata will be empty if no information exists in the archive
953 dearchivedScenes.LoadedCreationDateTime = 0; 1136 dearchivedScenes.LoadedCreationDateTime = 0;
@@ -955,16 +1138,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
955 1138
956 bool multiRegion = false; 1139 bool multiRegion = false;
957 1140
958 while (xtr.Read()) 1141 while (xtr.Read())
959 { 1142 {
960 if (xtr.NodeType == XmlNodeType.Element) 1143 if (xtr.NodeType == XmlNodeType.Element)
961 { 1144 {
962 if (xtr.Name.ToString() == "archive") 1145 if (xtr.Name.ToString() == "archive")
963 { 1146 {
964 int majorVersion = int.Parse(xtr["major_version"]); 1147 int majorVersion = int.Parse(xtr["major_version"]);
965 int minorVersion = int.Parse(xtr["minor_version"]); 1148 int minorVersion = int.Parse(xtr["minor_version"]);
966 string version = string.Format("{0}.{1}", majorVersion, minorVersion); 1149 string version = string.Format("{0}.{1}", majorVersion, minorVersion);
967 1150
968 if (majorVersion > MAX_MAJOR_VERSION) 1151 if (majorVersion > MAX_MAJOR_VERSION)
969 { 1152 {
970 throw new Exception( 1153 throw new Exception(
@@ -972,15 +1155,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
972 "The OAR you are trying to load has major version number of {0} but this version of OpenSim can only load OARs with major version number {1} and below", 1155 "The OAR you are trying to load has major version number of {0} but this version of OpenSim can only load OARs with major version number {1} and below",
973 majorVersion, MAX_MAJOR_VERSION)); 1156 majorVersion, MAX_MAJOR_VERSION));
974 } 1157 }
975 1158
976 m_log.InfoFormat("[ARCHIVER]: Loading OAR with version {0}", version); 1159 m_log.InfoFormat("[ARCHIVER]: Loading OAR with version {0}", version);
977 } 1160 }
978 if (xtr.Name.ToString() == "datetime") 1161 else if (xtr.Name.ToString() == "datetime")
979 { 1162 {
980 int value; 1163 int value;
981 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) 1164 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
982 dearchivedScenes.LoadedCreationDateTime = value; 1165 dearchivedScenes.LoadedCreationDateTime = value;
983 } 1166 }
984 else if (xtr.Name.ToString() == "row") 1167 else if (xtr.Name.ToString() == "row")
985 { 1168 {
986 multiRegion = true; 1169 multiRegion = true;
@@ -994,13 +1177,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver
994 { 1177 {
995 string id = xtr.ReadElementContentAsString(); 1178 string id = xtr.ReadElementContentAsString();
996 dearchivedScenes.DefaultOriginalID = id; 1179 dearchivedScenes.DefaultOriginalID = id;
997 if (multiRegion) 1180 if(multiRegion)
998 dearchivedScenes.SetRegionOriginalID(id); 1181 dearchivedScenes.SetRegionOriginalID(id);
999 } 1182 }
1000 else if (xtr.Name.ToString() == "dir") 1183 else if (xtr.Name.ToString() == "dir")
1001 { 1184 {
1002 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); 1185 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
1003 } 1186 }
1187 else if (xtr.Name.ToString() == "size_in_meters")
1188 {
1189 Vector3 value;
1190 string size = "<" + xtr.ReadElementContentAsString() + ",0>";
1191 if (Vector3.TryParse(size, out value))
1192 {
1193 m_incomingRegionSize = value;
1194 if(multiRegion)
1195 dearchivedScenes.SetRegionSize(m_incomingRegionSize);
1196 m_log.DebugFormat("[ARCHIVER]: Found region_size info {0}",
1197 m_incomingRegionSize.ToString());
1198 }
1199 }
1004 } 1200 }
1005 } 1201 }
1006 1202
@@ -1012,9 +1208,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
1012 dearchivedScenes.StartRegion(); 1208 dearchivedScenes.StartRegion();
1013 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID); 1209 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
1014 dearchivedScenes.SetRegionDirectory(""); 1210 dearchivedScenes.SetRegionDirectory("");
1211 dearchivedScenes.SetRegionSize(m_incomingRegionSize);
1015 } 1212 }
1016 1213
1017 ControlFileLoaded = true; 1214 ControlFileLoaded = true;
1215 if(xtr != null)
1216 xtr.Close();
1018 1217
1019 return dearchivedScenes; 1218 return dearchivedScenes;
1020 } 1219 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
index d8dace2..2fb4426 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
50 /// The inner dictionaries contain each row's regions (key: X coordinate). 50 /// The inner dictionaries contain each row's regions (key: X coordinate).
51 /// </summary> 51 /// </summary>
52 public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; } 52 public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; }
53 53
54 /// <summary> 54 /// <summary>
55 /// The subdirectory where each region is stored in the archive. 55 /// The subdirectory where each region is stored in the archive.
56 /// </summary> 56 /// </summary>
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
152 } 152 }
153 } 153 }
154 } 154 }
155 155
156 /// <summary> 156 /// <summary>
157 /// Returns the scene at position 'location'. 157 /// Returns the scene at position 'location'.
158 /// </summary> 158 /// </summary>
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index cb2c7f1..ec273d6 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -60,8 +60,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
60 /// <summary> 60 /// <summary>
61 /// The minimum major version of OAR that we can write. 61 /// The minimum major version of OAR that we can write.
62 /// </summary> 62 /// </summary>
63 public static int MIN_MAJOR_VERSION = 0; 63 public static int MIN_MAJOR_VERSION = 0;
64 64
65 /// <summary> 65 /// <summary>
66 /// The maximum major version of OAR that we can write. 66 /// The maximum major version of OAR that we can write.
67 /// </summary> 67 /// </summary>
@@ -112,7 +112,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
112 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); 112 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
113 } 113 }
114 } 114 }
115 115
116 /// <summary> 116 /// <summary>
117 /// Constructor. 117 /// Constructor.
118 /// </summary> 118 /// </summary>
@@ -181,11 +181,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
181 // Archive the regions 181 // Archive the regions
182 182
183 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>(); 183 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
184 HashSet<UUID> failedIDs = new HashSet<UUID>();
185 HashSet<UUID> uncertainAssetsUUIDs = new HashSet<UUID>();
184 186
185 scenesGroup.ForEachScene(delegate(Scene scene) 187 scenesGroup.ForEachScene(delegate(Scene scene)
186 { 188 {
187 string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; 189 string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
188 ArchiveOneRegion(scene, regionDir, assetUuids); 190 ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs);
189 }); 191 });
190 192
191 // Archive the assets 193 // Archive the assets
@@ -193,23 +195,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver
193 if (SaveAssets) 195 if (SaveAssets)
194 { 196 {
195 m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); 197 m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
196 198
197 // Asynchronously request all the assets required to perform this archive operation 199 AssetsRequest ar = new AssetsRequest(
198 AssetsRequest ar
199 = new AssetsRequest(
200 new AssetsArchiver(m_archiveWriter), assetUuids, 200 new AssetsArchiver(m_archiveWriter), assetUuids,
201 failedIDs.Count,
201 m_rootScene.AssetService, m_rootScene.UserAccountService, 202 m_rootScene.AssetService, m_rootScene.UserAccountService,
202 m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); 203 m_rootScene.RegionInfo.ScopeID, options, null);
203 204 ar.Execute();
204 WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request"); 205 assetUuids = null;
205
206 // CloseArchive() will be called from ReceivedAllAssets()
207 } 206 }
208 else 207 else
209 { 208 {
210 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); 209 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
211 CloseArchive(string.Empty); 210// CloseArchive(string.Empty);
212 } 211 }
212 CloseArchive(string.Empty);
213 } 213 }
214 catch (Exception e) 214 catch (Exception e)
215 { 215 {
@@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
218 } 218 }
219 } 219 }
220 220
221 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids) 221 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids,
222 HashSet<UUID> failedIDs, HashSet<UUID> uncertainAssetsUUIDs)
222 { 223 {
223 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name); 224 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name);
224 225
@@ -226,7 +227,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
226 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 227 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
227 228
228 int numObjectsSkippedPermissions = 0; 229 int numObjectsSkippedPermissions = 0;
229 230
230 // Filter entities so that we only have scene objects. 231 // Filter entities so that we only have scene objects.
231 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods 232 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
232 // end up having to do this 233 // end up having to do this
@@ -237,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
237 { 238 {
238 SceneObjectGroup sceneObject = (SceneObjectGroup)entity; 239 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
239 240
240 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) 241 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment && !sceneObject.IsTemporary && !sceneObject.inTransit)
241 { 242 {
242 if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule)) 243 if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule))
243 { 244 {
@@ -254,17 +255,39 @@ namespace OpenSim.Region.CoreModules.World.Archiver
254 255
255 if (SaveAssets) 256 if (SaveAssets)
256 { 257 {
257 UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids); 258 UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids, failedIDs, uncertainAssetsUUIDs);
258 int prevAssets = assetUuids.Count; 259 int prevAssets = assetUuids.Count;
259 260
260 foreach (SceneObjectGroup sceneObject in sceneObjects) 261 foreach (SceneObjectGroup sceneObject in sceneObjects)
262 {
263 int curErrorCntr = assetGatherer.ErrorCount;
264 int possible = assetGatherer.possibleNotAssetCount;
261 assetGatherer.AddForInspection(sceneObject); 265 assetGatherer.AddForInspection(sceneObject);
266 assetGatherer.GatherAll();
267 curErrorCntr = assetGatherer.ErrorCount - curErrorCntr;
268 possible = assetGatherer.possibleNotAssetCount - possible;
269 if(curErrorCntr > 0)
270 {
271 m_log.ErrorFormat("[ARCHIVER]: object {0} '{1}', at {2}, contains {3} references to missing or damaged assets, or not a problem.",
272 sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), curErrorCntr);
273//// if(possible > 0)
274//// m_log.WarnFormat("[ARCHIVER Warning]: object also contains {0} references that may be to missing or damaged assets or not a problem", possible);
275 }
276//// else if(possible > 0)
277//// {
278//// m_log.WarnFormat("[ARCHIVER Warning]: object {0} '{1}', at {2}, contains {3} references that may be to missing or damaged assets or not a problem",
279//// sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), possible);
280//// }
281 }
262 282
263 assetGatherer.GatherAll(); 283 assetGatherer.GatherAll();
264 284
285 int errors = assetGatherer.FailedUUIDs.Count;
265 m_log.DebugFormat( 286 m_log.DebugFormat(
266 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", 287 "[ARCHIVER]: {0} region scene objects to save reference {1} possible assets",
267 sceneObjects.Count, assetUuids.Count - prevAssets); 288 sceneObjects.Count, assetUuids.Count - prevAssets + errors);
289 if(errors > 0)
290 m_log.DebugFormat("[ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
268 } 291 }
269 292
270 if (numObjectsSkippedPermissions > 0) 293 if (numObjectsSkippedPermissions > 0)
@@ -276,16 +299,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
276 299
277 // Make sure that we also request terrain texture assets 300 // Make sure that we also request terrain texture assets
278 RegionSettings regionSettings = scene.RegionInfo.RegionSettings; 301 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
279 302
280 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) 303 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
281 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture; 304 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
282 305
283 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) 306 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
284 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture; 307 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
285 308
286 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) 309 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
287 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture; 310 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
288 311
289 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) 312 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
290 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture; 313 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
291 314
@@ -398,18 +421,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
398// string[] parts = m_options["version"].ToString().Split('.'); 421// string[] parts = m_options["version"].ToString().Split('.');
399// if (parts.Length >= 1) 422// if (parts.Length >= 1)
400// { 423// {
401// majorVersion = Int32.Parse(parts[0]); 424// majorVersion = Int32.Parse(parts[0]);
402// 425//
403// if (parts.Length >= 2) 426// if (parts.Length >= 2)
404// minorVersion = Int32.Parse(parts[1]); 427// minorVersion = Int32.Parse(parts[1]);
405// } 428// }
406// } 429// }
407// 430//
408// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) 431// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
409// { 432// {
410// throw new Exception( 433// throw new Exception(
411// string.Format( 434// string.Format(
412// "OAR version number for save must be between {0} and {1}", 435// "OAR version number for save must be between {0} and {1}",
413// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); 436// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
414// } 437// }
415// else if (majorVersion == MAX_MAJOR_VERSION) 438// else if (majorVersion == MAX_MAJOR_VERSION)
@@ -420,9 +443,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
420// else if (majorVersion == MIN_MAJOR_VERSION) 443// else if (majorVersion == MIN_MAJOR_VERSION)
421// { 444// {
422// // Force 0.4 445// // Force 0.4
423// minorVersion = 4; 446// minorVersion = 4;
424// } 447// }
425 448
426 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); 449 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
427 if (majorVersion == 1) 450 if (majorVersion == 1)
428 { 451 {
@@ -430,7 +453,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
430 } 453 }
431 454
432 String s; 455 String s;
433 456
434 using (StringWriter sw = new StringWriter()) 457 using (StringWriter sw = new StringWriter())
435 { 458 {
436 using (XmlTextWriter xtw = new XmlTextWriter(sw)) 459 using (XmlTextWriter xtw = new XmlTextWriter(sw))
@@ -440,7 +463,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
440 xtw.WriteStartElement("archive"); 463 xtw.WriteStartElement("archive");
441 xtw.WriteAttributeString("major_version", majorVersion.ToString()); 464 xtw.WriteAttributeString("major_version", majorVersion.ToString());
442 xtw.WriteAttributeString("minor_version", minorVersion.ToString()); 465 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
443 466
444 xtw.WriteStartElement("creation_info"); 467 xtw.WriteStartElement("creation_info");
445 DateTime now = DateTime.UtcNow; 468 DateTime now = DateTime.UtcNow;
446 TimeSpan t = now - new DateTime(1970, 1, 1); 469 TimeSpan t = now - new DateTime(1970, 1, 1);
@@ -448,7 +471,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
448 if (!MultiRegionFormat) 471 if (!MultiRegionFormat)
449 xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); 472 xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString());
450 xtw.WriteEndElement(); 473 xtw.WriteEndElement();
451 474
452 xtw.WriteElementString("assets_included", SaveAssets.ToString()); 475 xtw.WriteElementString("assets_included", SaveAssets.ToString());
453 476
454 if (MultiRegionFormat) 477 if (MultiRegionFormat)
@@ -463,7 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
463 } 486 }
464 487
465 xtw.WriteEndElement(); 488 xtw.WriteEndElement();
466 489
467 xtw.Flush(); 490 xtw.Flush();
468 } 491 }
469 492
@@ -522,22 +545,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
522 545
523 protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) 546 protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw)
524 { 547 {
525 bool isMegaregion;
526 Vector2 size; 548 Vector2 size;
527 549
528 IRegionCombinerModule rcMod = scene.RequestModuleInterface<IRegionCombinerModule>(); 550 size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
529 551
530 if (rcMod != null)
531 isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID);
532 else
533 isMegaregion = false;
534
535 if (isMegaregion)
536 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
537 else
538 size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
539
540 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
541 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); 552 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
542 } 553 }
543 554
@@ -560,7 +571,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
560 foreach (ILandObject lo in landObjects) 571 foreach (ILandObject lo in landObjects)
561 { 572 {
562 LandData landData = lo.LandData; 573 LandData landData = lo.LandData;
563 string landDataPath 574 string landDataPath
564 = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData)); 575 = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData));
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); 576 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 } 577 }
@@ -584,17 +595,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
584 foreach (SceneObjectGroup sceneObject in sceneObjects) 595 foreach (SceneObjectGroup sceneObject in sceneObjects)
585 { 596 {
586 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); 597 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
587 598 if(sceneObject.IsDeleted || sceneObject.inTransit)
599 continue;
588 string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); 600 string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
589 string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); 601 string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
590 m_archiveWriter.WriteFile(objectPath, serializedObject); 602 m_archiveWriter.WriteFile(objectPath, serializedObject);
591 } 603 }
592 } 604 }
593 605
594 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut) 606 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut)
595 { 607 {
596 string errorMessage; 608 string errorMessage;
597 609
598 if (timedOut) 610 if (timedOut)
599 { 611 {
600 errorMessage = "Loading assets timed out"; 612 errorMessage = "Loading assets timed out";
@@ -612,10 +624,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
612 624
613 errorMessage = String.Empty; 625 errorMessage = String.Empty;
614 } 626 }
615 627
616 CloseArchive(errorMessage); 628 CloseArchive(errorMessage);
617 } 629 }
618 630
619 /// <summary> 631 /// <summary>
620 /// Closes the archive and notifies that we're done. 632 /// Closes the archive and notifies that we're done.
621 /// </summary> 633 /// </summary>
@@ -634,7 +646,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
634 if (errorMessage == string.Empty) 646 if (errorMessage == string.Empty)
635 errorMessage = e.Message; 647 errorMessage = e.Message;
636 } 648 }
637 649
638 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); 650 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName);
639 651
640 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); 652 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index 6a09caf..1305545 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -49,24 +49,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ArchiverModule")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ArchiverModule")]
50 public class ArchiverModule : INonSharedRegionModule, IRegionArchiverModule 50 public class ArchiverModule : INonSharedRegionModule, IRegionArchiverModule
51 { 51 {
52 private static readonly ILog m_log = 52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 54
55 public Scene Scene { get; private set; } 55 public Scene Scene { get; private set; }
56 public IRegionCombinerModule RegionCombinerModule { get; private set; }
57 56
58 /// <value> 57 /// <value>
59 /// The file used to load and save an opensimulator archive if no filename has been specified 58 /// The file used to load and save an opensimulator archive if no filename has been specified
60 /// </value> 59 /// </value>
61 protected const string DEFAULT_OAR_BACKUP_FILENAME = "region.oar"; 60 protected const string DEFAULT_OAR_BACKUP_FILENAME = "region.oar";
62 61
63 public string Name 62 public string Name
64 { 63 {
65 get { return "RegionArchiverModule"; } 64 get { return "RegionArchiverModule"; }
66 } 65 }
67 66
68 public Type ReplaceableInterface 67 public Type ReplaceableInterface
69 { 68 {
70 get { return null; } 69 get { return null; }
71 } 70 }
72 71
@@ -85,7 +84,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
85 84
86 public void RegionLoaded(Scene scene) 85 public void RegionLoaded(Scene scene)
87 { 86 {
88 RegionCombinerModule = scene.RequestModuleInterface<IRegionCombinerModule>();
89 } 87 }
90 88
91 public void RemoveRegion(Scene scene) 89 public void RemoveRegion(Scene scene)
@@ -110,18 +108,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
110 Vector3 displacement = new Vector3(0f, 0f, 0f); 108 Vector3 displacement = new Vector3(0f, 0f, 0f);
111 String defaultUser = ""; 109 String defaultUser = "";
112 float rotation = 0f; 110 float rotation = 0f;
113 Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0); 111 Vector3 rotationCenter = new Vector3(Scene.RegionInfo.RegionSizeX / 2f, Scene.RegionInfo.RegionSizeY / 2f, 0);
114 112 Vector3 boundingOrigin = new Vector3(0f, 0f, 0f);
113 Vector3 boundingSize = new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, float.MaxValue);
114 bool debug = false;
115
115 OptionSet options = new OptionSet(); 116 OptionSet options = new OptionSet();
116 options.Add("m|merge", delegate (string v) { mergeOar = (v != null); }); 117 options.Add("m|merge", delegate(string v) { mergeOar = (v != null); });
117 options.Add("s|skip-assets", delegate (string v) { skipAssets = (v != null); }); 118 options.Add("s|skip-assets", delegate(string v) { skipAssets = (v != null); });
118 options.Add("force-terrain", delegate (string v) { forceTerrain = (v != null); }); 119 options.Add("force-terrain", delegate(string v) { forceTerrain = (v != null); });
119 options.Add("forceterrain", delegate (string v) { forceTerrain = (v != null); }); // downward compatibility 120 options.Add("forceterrain", delegate(string v) { forceTerrain = (v != null); }); // downward compatibility
120 options.Add("force-parcels", delegate (string v) { forceParcels = (v != null); }); 121 options.Add("force-parcels", delegate(string v) { forceParcels = (v != null); });
121 options.Add("forceparcels", delegate (string v) { forceParcels = (v != null); }); // downward compatibility 122 options.Add("forceparcels", delegate(string v) { forceParcels = (v != null); }); // downward compatibility
122 options.Add("no-objects", delegate (string v) { noObjects = (v != null); }); 123 options.Add("no-objects", delegate(string v) { noObjects = (v != null); });
123 options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; }); 124 options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; });
124 options.Add("displacement=", delegate (string v) { 125 options.Add("displacement=", delegate(string v)
126 {
125 try 127 try
126 { 128 {
127 displacement = v == null ? Vector3.Zero : Vector3.Parse(v); 129 displacement = v == null ? Vector3.Zero : Vector3.Parse(v);
@@ -145,12 +147,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
145 m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45"); 147 m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45");
146 return; 148 return;
147 } 149 }
148 // Convert to radians for internals 150 //pass this in as degrees now, convert to radians later during actual work phase
149 rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI; 151 rotation = Util.Clamp<float>(rotation, -359f, 359f);
150 }); 152 });
151 options.Add("rotation-center=", delegate (string v) { 153 options.Add("rotation-center=", delegate(string v)
154 {
152 try 155 try
153 { 156 {
157 m_log.Info("[ARCHIVER MODULE] Warning: --rotation-center no longer does anything and will be removed soon!");
154 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v); 158 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
155 } 159 }
156 catch 160 catch
@@ -160,6 +164,33 @@ namespace OpenSim.Region.CoreModules.World.Archiver
160 return; 164 return;
161 } 165 }
162 }); 166 });
167 options.Add("bounding-origin=", delegate(string v)
168 {
169 try
170 {
171 boundingOrigin = v == null ? Vector3.Zero : Vector3.Parse(v);
172 }
173 catch
174 {
175 m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube origin");
176 m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --bounding-origin \"<128,128,0>\"");
177 return;
178 }
179 });
180 options.Add("bounding-size=", delegate(string v)
181 {
182 try
183 {
184 boundingSize = v == null ? new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, float.MaxValue) : Vector3.Parse(v);
185 }
186 catch
187 {
188 m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube size");
189 m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as a positive vector3: --bounding-size \"<256,256,4096>\"");
190 return;
191 }
192 });
193 options.Add("d|debug", delegate(string v) { debug = (v != null); });
163 194
164 // Send a message to the region ready module 195 // Send a message to the region ready module
165 /* bluewall* Disable this for the time being 196 /* bluewall* Disable this for the time being
@@ -170,9 +201,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
170 rready.OarLoadingAlert("load"); 201 rready.OarLoadingAlert("load");
171 } 202 }
172 */ 203 */
173 204
174 List<string> mainParams = options.Parse(cmdparams); 205 List<string> mainParams = options.Parse(cmdparams);
175 206
176// m_log.DebugFormat("MERGE OAR IS [{0}]", mergeOar); 207// m_log.DebugFormat("MERGE OAR IS [{0}]", mergeOar);
177// 208//
178// foreach (string param in mainParams) 209// foreach (string param in mainParams)
@@ -208,6 +239,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
208 archiveOptions.Add("displacement", displacement); 239 archiveOptions.Add("displacement", displacement);
209 archiveOptions.Add("rotation", rotation); 240 archiveOptions.Add("rotation", rotation);
210 archiveOptions.Add("rotation-center", rotationCenter); 241 archiveOptions.Add("rotation-center", rotationCenter);
242 archiveOptions.Add("bounding-origin", boundingOrigin);
243 archiveOptions.Add("bounding-size", boundingSize);
244 if (debug) archiveOptions.Add("debug", null);
211 245
212 if (mainParams.Count > 2) 246 if (mainParams.Count > 2)
213 { 247 {
@@ -254,7 +288,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
254 288
255 ArchiveRegion(path, options); 289 ArchiveRegion(path, options);
256 } 290 }
257 291
258 public void ArchiveRegion(string savePath, Dictionary<string, object> options) 292 public void ArchiveRegion(string savePath, Dictionary<string, object> options)
259 { 293 {
260 ArchiveRegion(savePath, Guid.Empty, options); 294 ArchiveRegion(savePath, Guid.Empty, options);
@@ -264,7 +298,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
264 { 298 {
265 m_log.InfoFormat( 299 m_log.InfoFormat(
266 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); 300 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
267 301
268 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); 302 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options);
269 } 303 }
270 304
@@ -288,21 +322,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
288 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 322 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
289 DearchiveRegion(loadPath, Guid.Empty, archiveOptions); 323 DearchiveRegion(loadPath, Guid.Empty, archiveOptions);
290 } 324 }
291 325
292 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options) 326 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string, object> options)
293 { 327 {
294 m_log.InfoFormat( 328 m_log.InfoFormat(
295 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath); 329 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
296 330
297 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion(); 331 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion();
298 } 332 }
299 333
300 public void DearchiveRegion(Stream loadStream) 334 public void DearchiveRegion(Stream loadStream)
301 { 335 {
302 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 336 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
303 DearchiveRegion(loadStream, Guid.Empty, archiveOptions); 337 DearchiveRegion(loadStream, Guid.Empty, archiveOptions);
304 } 338 }
305
306 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options) 339 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options)
307 { 340 {
308 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion(); 341 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion();
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
index bc6a97d..0a955c5 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
@@ -46,13 +46,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
46 /// <value> 46 /// <value>
47 /// Post a message to the log every x assets as a progress bar 47 /// Post a message to the log every x assets as a progress bar
48 /// </value> 48 /// </value>
49 protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 50; 49 protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 100;
50 50
51 /// <value> 51 /// <value>
52 /// Keep a count of the number of assets written so that we can provide status updates 52 /// Keep a count of the number of assets written so that we can provide status updates
53 /// </value> 53 /// </value>
54 protected int m_assetsWritten; 54 protected int m_assetsWritten;
55 55
56 protected TarArchiveWriter m_archiveWriter; 56 protected TarArchiveWriter m_archiveWriter;
57 57
58 public AssetsArchiver(TarArchiveWriter archiveWriter) 58 public AssetsArchiver(TarArchiveWriter archiveWriter)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
index 8c0ef88..5d3be62 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
93 93
94 StringReader sr = new StringReader(xml); 94 StringReader sr = new StringReader(xml);
95 XmlTextReader reader = new XmlTextReader(sr); 95 XmlTextReader reader = new XmlTextReader(sr);
96 reader.ProhibitDtd = true;
96 97
97 reader.ReadStartElement("assets"); 98 reader.ReadStartElement("assets");
98 reader.Read(); 99 reader.Read();
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index db66c83..91f4dc3 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -60,29 +60,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
60 Completed, 60 Completed,
61 Aborted 61 Aborted
62 }; 62 };
63
64 /// <value>
65 /// Timeout threshold if we still need assets or missing asset notifications but have stopped receiving them
66 /// from the asset service
67 /// </value>
68 protected const int TIMEOUT = 60 * 1000;
69
70 /// <value>
71 /// If a timeout does occur, limit the amount of UUID information put to the console.
72 /// </value>
73 protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3;
74
75 protected System.Timers.Timer m_requestCallbackTimer;
76 63
77 /// <value> 64 /// <value>
78 /// State of this request
79 /// </value>
80 private RequestState m_requestState = RequestState.Initial;
81
82 /// <value>
83 /// uuids to request 65 /// uuids to request
84 /// </value> 66 /// </value>
85 protected IDictionary<UUID, sbyte> m_uuids; 67 protected IDictionary<UUID, sbyte> m_uuids;
68 private int m_previousErrorsCount;
86 69
87 /// <value> 70 /// <value>
88 /// Callback used when all the assets requested have been received. 71 /// Callback used when all the assets requested have been received.
@@ -93,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
93 /// List of assets that were found. This will be passed back to the requester. 76 /// List of assets that were found. This will be passed back to the requester.
94 /// </value> 77 /// </value>
95 protected List<UUID> m_foundAssetUuids = new List<UUID>(); 78 protected List<UUID> m_foundAssetUuids = new List<UUID>();
96 79
97 /// <value> 80 /// <value>
98 /// Maintain a list of assets that could not be found. This will be passed back to the requester. 81 /// Maintain a list of assets that could not be found. This will be passed back to the requester.
99 /// </value> 82 /// </value>
@@ -104,217 +87,114 @@ namespace OpenSim.Region.CoreModules.World.Archiver
104 /// </value> 87 /// </value>
105 private int m_repliesRequired; 88 private int m_repliesRequired;
106 89
90 private System.Timers.Timer m_timeOutTimer;
91 private bool m_timeout;
92
107 /// <value> 93 /// <value>
108 /// Asset service used to request the assets 94 /// Asset service used to request the assets
109 /// </value> 95 /// </value>
110 protected IAssetService m_assetService; 96 protected IAssetService m_assetService;
111 protected IUserAccountService m_userAccountService; 97 protected IUserAccountService m_userAccountService;
112 protected UUID m_scopeID; // the grid ID 98 protected UUID m_scopeID; // the grid ID
113 99
114 protected AssetsArchiver m_assetsArchiver; 100 protected AssetsArchiver m_assetsArchiver;
115 101
116 protected Dictionary<string, object> m_options; 102 protected Dictionary<string, object> m_options;
117 103
118 protected internal AssetsRequest( 104 protected internal AssetsRequest(
119 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids, 105 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
120 IAssetService assetService, IUserAccountService userService, 106 int previousErrorsCount,
121 UUID scope, Dictionary<string, object> options, 107 IAssetService assetService, IUserAccountService userService,
108 UUID scope, Dictionary<string, object> options,
122 AssetsRequestCallback assetsRequestCallback) 109 AssetsRequestCallback assetsRequestCallback)
123 { 110 {
124 m_assetsArchiver = assetsArchiver; 111 m_assetsArchiver = assetsArchiver;
125 m_uuids = uuids; 112 m_uuids = uuids;
113 m_previousErrorsCount = previousErrorsCount;
126 m_assetsRequestCallback = assetsRequestCallback; 114 m_assetsRequestCallback = assetsRequestCallback;
127 m_assetService = assetService; 115 m_assetService = assetService;
128 m_userAccountService = userService; 116 m_userAccountService = userService;
129 m_scopeID = scope; 117 m_scopeID = scope;
130 m_options = options; 118 m_options = options;
131 m_repliesRequired = uuids.Count; 119 m_repliesRequired = uuids.Count;
132
133 // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
134 // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
135 // so we can properly abort that thread. Or request all assets synchronously, though that would be a more
136 // radical change
137 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
138 m_requestCallbackTimer.AutoReset = false;
139 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
140 } 120 }
141 121
142 protected internal void Execute() 122 protected internal void Execute()
143 { 123 {
144 m_requestState = RequestState.Running; 124 Culture.SetCurrentCulture();
145
146 m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
147
148 // We can stop here if there are no assets to fetch 125 // We can stop here if there are no assets to fetch
149 if (m_repliesRequired == 0) 126 if (m_repliesRequired == 0)
150 { 127 {
151 m_requestState = RequestState.Completed;
152 PerformAssetsRequestCallback(false); 128 PerformAssetsRequestCallback(false);
153 return; 129 return;
154 } 130 }
155 131
156 m_requestCallbackTimer.Enabled = true; 132 m_timeOutTimer = new System.Timers.Timer(60000);
133 m_timeOutTimer .AutoReset = false;
134 m_timeOutTimer.Elapsed += OnTimeout;
135 m_timeout = false;
157 136
158 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids) 137 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
159 { 138 {
160// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); 139 string thiskey = kvp.Key.ToString();
161 140 try
162// m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); 141 {
163 AssetBase asset = m_assetService.Get(kvp.Key.ToString()); 142 m_timeOutTimer.Enabled = true;
164 PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); 143 AssetBase asset = m_assetService.Get(thiskey);
165 } 144 if(m_timeout)
166 } 145 break;
146
147 m_timeOutTimer.Enabled = false;
167 148
168 protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) 149 if(asset == null)
169 { 150 {
170 bool timedOut = true; 151 m_notFoundAssetUuids.Add(new UUID(thiskey));
152 continue;
153 }
171 154
172 try 155 sbyte assetType = kvp.Value;
173 { 156 if (asset != null && assetType == (sbyte)AssetType.Unknown)
174 lock (this)
175 {
176 // Take care of the possibilty that this thread started but was paused just outside the lock before
177 // the final request came in (assuming that such a thing is possible)
178 if (m_requestState == RequestState.Completed)
179 { 157 {
180 timedOut = false; 158 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType));
181 return; 159 asset.Type = assetType;
182 } 160 }
183
184 m_requestState = RequestState.Aborted;
185 }
186 161
187 // Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure 162 m_foundAssetUuids.Add(asset.FullID);
188 // case anyway. 163 m_assetsArchiver.WriteAsset(PostProcess(asset));
189 List<UUID> uuids = new List<UUID>();
190 foreach (UUID uuid in m_uuids.Keys)
191 {
192 uuids.Add(uuid);
193 } 164 }
194 165
195 foreach (UUID uuid in m_foundAssetUuids) 166 catch (Exception e)
196 {
197 uuids.Remove(uuid);
198 }
199
200 foreach (UUID uuid in m_notFoundAssetUuids)
201 { 167 {
202 uuids.Remove(uuid); 168 m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e);
203 }
204
205 m_log.ErrorFormat(
206 "[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count);
207
208 int i = 0;
209 foreach (UUID uuid in uuids)
210 {
211 m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid);
212
213 if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT)
214 break;
215 } 169 }
216
217 if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT)
218 m_log.ErrorFormat(
219 "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT);
220
221 m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE.");
222 }
223 catch (Exception e)
224 {
225 m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace);
226 } 170 }
227 finally
228 {
229 if (timedOut)
230 WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback");
231 }
232 }
233 171
234 protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset) 172 m_timeOutTimer.Dispose();
235 { 173 int totalerrors = m_notFoundAssetUuids.Count + m_previousErrorsCount;
236 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
237 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
238 {
239 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
240 fetchedAsset.Type = (sbyte)assetType;
241 }
242 174
243 AssetRequestCallback(fetchedAssetID, this, fetchedAsset); 175 if(m_timeout)
244 } 176 m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count);
177 else if(totalerrors == 0)
178 m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count);
179 else
180 m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} of total possible assets requested were not found, were damaged or were not assets)",
181 m_foundAssetUuids.Count, totalerrors);
245 182
246 /// <summary> 183 PerformAssetsRequestCallback(m_timeout);
247 /// Called back by the asset cache when it has the asset 184 }
248 /// </summary> 185
249 /// <param name="assetID"></param> 186 private void OnTimeout(object source, ElapsedEventArgs args)
250 /// <param name="asset"></param>
251 public void AssetRequestCallback(string id, object sender, AssetBase asset)
252 { 187 {
253 Culture.SetCurrentCulture(); 188 m_timeout = true;
254
255 try
256 {
257 lock (this)
258 {
259 //m_log.DebugFormat("[ARCHIVER]: Received callback for asset {0}", id);
260
261 m_requestCallbackTimer.Stop();
262
263 if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed))
264 {
265 m_log.WarnFormat(
266 "[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.",
267 id, m_requestState);
268
269 return;
270 }
271
272 if (asset != null)
273 {
274 if (m_options.ContainsKey("verbose"))
275 m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id);
276
277 m_foundAssetUuids.Add(asset.FullID);
278
279 m_assetsArchiver.WriteAsset(PostProcess(asset));
280 }
281 else
282 {
283 if (m_options.ContainsKey("verbose"))
284 m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id);
285
286 m_notFoundAssetUuids.Add(new UUID(id));
287 }
288
289 if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired)
290 {
291 m_requestState = RequestState.Completed;
292
293 m_log.DebugFormat(
294 "[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)",
295 m_foundAssetUuids.Count, m_notFoundAssetUuids.Count);
296
297 // We want to stop using the asset cache thread asap
298 // as we now need to do the work of producing the rest of the archive
299 WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback");
300 }
301 else
302 {
303 m_requestCallbackTimer.Start();
304 }
305 }
306 }
307 catch (Exception e)
308 {
309 m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e);
310 }
311 } 189 }
312 190
313 /// <summary> 191 /// <summary>
314 /// Perform the callback on the original requester of the assets 192 /// Perform the callback on the original requester of the assets
315 /// </summary> 193 /// </summary>
316 protected void PerformAssetsRequestCallback(object o) 194 private void PerformAssetsRequestCallback(object o)
317 { 195 {
196 if(m_assetsRequestCallback == null)
197 return;
318 Culture.SetCurrentCulture(); 198 Culture.SetCurrentCulture();
319 199
320 Boolean timedOut = (Boolean)o; 200 Boolean timedOut = (Boolean)o;
@@ -330,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
330 } 210 }
331 } 211 }
332 212
333 protected AssetBase PostProcess(AssetBase asset) 213 private AssetBase PostProcess(AssetBase asset)
334 { 214 {
335 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) 215 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
336 { 216 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
index 3dcc020..809d863 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
@@ -70,6 +70,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
70 /// If null then the region doesn't have a corresponding scene, and it won't be loaded. 70 /// If null then the region doesn't have a corresponding scene, and it won't be loaded.
71 /// </summary> 71 /// </summary>
72 public Scene Scene { get; set; } 72 public Scene Scene { get; set; }
73
74 /// <summary>
75 /// The size of the region being loaded.
76 /// </summary>
77 public Vector3 RegionSize { get; set; }
78
79 public RegionInfo()
80 {
81 RegionSize = new Vector3(256f,256f,float.MaxValue);
82 }
73 } 83 }
74 84
75 /// <summary> 85 /// <summary>
@@ -113,23 +123,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver
113 public void StartRegion() 123 public void StartRegion()
114 { 124 {
115 m_curX = (m_curX == null) ? 0 : m_curX + 1; 125 m_curX = (m_curX == null) ? 0 : m_curX + 1;
116 // Note: this doesn't mean we have a real region in this location; this could just be a "hole" 126 // Note: this doesn't mean we have a real region in this location; this could just be a "hole"
117 } 127 }
118 128
119 public void SetRegionOriginalID(string id) 129 public void SetRegionOriginalID(string id)
120 { 130 {
121 m_curRegion = new RegionInfo(); 131 m_curRegion = new RegionInfo();
122 m_curRegion.Location = new Point((int)m_curX, (int)m_curY); 132 int x = (int)((m_curX == null) ? 0 : m_curX);
133 int y = (int)((m_curY == null) ? 0 : m_curY);
134
135 m_curRegion.Location = new Point(x, y);
123 m_curRegion.OriginalID = id; 136 m_curRegion.OriginalID = id;
124 // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called 137 // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
125 } 138 }
126 139
127 public void SetRegionDirectory(string directory) 140 public void SetRegionDirectory(string directory)
128 { 141 {
129 m_curRegion.Directory = directory; 142 if(m_curRegion != null)
130 m_directory2region[directory] = m_curRegion; 143 {
144 m_curRegion.Directory = directory;
145 m_directory2region[directory] = m_curRegion;
146 }
131 } 147 }
132 148
149 public void SetRegionSize(Vector3 size)
150 {
151 if(m_curRegion != null)
152 m_curRegion.RegionSize = size;
153 }
133 154
134 /// <summary> 155 /// <summary>
135 /// Sets all the scenes present in the simulator. 156 /// Sets all the scenes present in the simulator.
@@ -145,7 +166,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
145 { 166 {
146 foreach (RegionInfo archivedRegion in m_directory2region.Values) 167 foreach (RegionInfo archivedRegion in m_directory2region.Values)
147 { 168 {
148 Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY); 169 Point location = new Point((int)rootScene.RegionInfo.RegionLocX,
170 (int)rootScene.RegionInfo.RegionLocY);
171
149 location.Offset(archivedRegion.Location); 172 location.Offset(archivedRegion.Location);
150 173
151 Scene scene; 174 Scene scene;
@@ -191,7 +214,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
191 return false; 214 return false;
192 string regionDirectory = parts[1]; 215 string regionDirectory = parts[1];
193 relativePath = parts[2]; 216 relativePath = parts[2];
194 217
195 RegionInfo region; 218 RegionInfo region;
196 if (m_directory2region.TryGetValue(regionDirectory, out region)) 219 if (m_directory2region.TryGetValue(regionDirectory, out region))
197 { 220 {
@@ -228,5 +251,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
228 return m_newId2region.Keys.ToList(); 251 return m_newId2region.Keys.ToList();
229 } 252 }
230 253
254 public int GetScenesCount()
255 {
256 return m_directory2region.Count;
257 }
231 } 258 }
232} 259}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 9f197f5..6885299 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -65,7 +65,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
65 protected SerialiserModule m_serialiserModule; 65 protected SerialiserModule m_serialiserModule;
66 66
67 protected TaskInventoryItem m_soundItem; 67 protected TaskInventoryItem m_soundItem;
68 68
69 private AutoResetEvent m_oarEvent = new AutoResetEvent(false);
70
69 [SetUp] 71 [SetUp]
70 public override void SetUp() 72 public override void SetUp()
71 { 73 {
@@ -87,11 +89,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
87 m_lastRequestId = requestId; 89 m_lastRequestId = requestId;
88 m_lastErrorMessage = errorMessage; 90 m_lastErrorMessage = errorMessage;
89 Console.WriteLine("About to pulse ArchiverTests on LoadCompleted"); 91 Console.WriteLine("About to pulse ArchiverTests on LoadCompleted");
90 92 m_oarEvent.Set();
91 Monitor.PulseAll(this);
92 } 93 }
93 } 94 }
94 95
95 private void SaveCompleted(Guid requestId, string errorMessage) 96 private void SaveCompleted(Guid requestId, string errorMessage)
96 { 97 {
97 lock (this) 98 lock (this)
@@ -99,7 +100,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
99 m_lastRequestId = requestId; 100 m_lastRequestId = requestId;
100 m_lastErrorMessage = errorMessage; 101 m_lastErrorMessage = errorMessage;
101 Console.WriteLine("About to pulse ArchiverTests on SaveCompleted"); 102 Console.WriteLine("About to pulse ArchiverTests on SaveCompleted");
102 Monitor.PulseAll(this); 103 m_oarEvent.Set();
103 } 104 }
104 } 105 }
105 106
@@ -110,6 +111,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
110 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); 111 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
111 Vector3 groupPosition = new Vector3(10, 20, 30); 112 Vector3 groupPosition = new Vector3(10, 20, 30);
112 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); 113 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
114 rotationOffset.Normalize();
113// Vector3 offsetPosition = new Vector3(5, 10, 15); 115// Vector3 offsetPosition = new Vector3(5, 10, 15);
114 116
115 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, Vector3.Zero) { Name = partName }; 117 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, Vector3.Zero) { Name = partName };
@@ -122,11 +124,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
122 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); 124 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder();
123 Vector3 groupPosition = new Vector3(90, 80, 70); 125 Vector3 groupPosition = new Vector3(90, 80, 70);
124 Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); 126 Quaternion rotationOffset = new Quaternion(60, 70, 80, 90);
127 rotationOffset.Normalize();
125 Vector3 offsetPosition = new Vector3(20, 25, 30); 128 Vector3 offsetPosition = new Vector3(20, 25, 30);
126 129
127 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; 130 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
128 } 131 }
129 132
130 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) 133 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
131 { 134 {
132 SceneObjectPart part1 = CreateSceneObjectPart1(); 135 SceneObjectPart part1 = CreateSceneObjectPart1();
@@ -192,17 +195,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
192 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 195 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
193 196
194 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); 197 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
195 198
196 lock (this) 199 m_oarEvent.Reset();
197 { 200 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId);
198 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId); 201 //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer;
199 //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; 202 //while (assetServer.HasWaitingRequests())
200 //while (assetServer.HasWaitingRequests()) 203 // assetServer.ProcessNextRequest();
201 // assetServer.ProcessNextRequest(); 204
202 205 m_oarEvent.WaitOne(60000);
203 Monitor.Wait(this, 60000); 206
204 }
205
206 Assert.That(m_lastRequestId, Is.EqualTo(requestId)); 207 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
207 208
208 byte[] archive = archiveWriteStream.ToArray(); 209 byte[] archive = archiveWriteStream.ToArray();
@@ -210,7 +211,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
210 TarArchiveReader tar = new TarArchiveReader(archiveReadStream); 211 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
211 212
212 bool gotNcAssetFile = false; 213 bool gotNcAssetFile = false;
213 214
214 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt"); 215 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt");
215 216
216 List<string> foundPaths = new List<string>(); 217 List<string> foundPaths = new List<string>();
@@ -219,7 +220,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
219 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); 220 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
220 221
221 string filePath; 222 string filePath;
222 TarArchiveReader.TarEntryType tarEntryType; 223 TarArchiveReader.TarEntryType tarEntryType;
223 224
224 byte[] data = tar.ReadEntry(out filePath, out tarEntryType); 225 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
225 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 226 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
@@ -227,9 +228,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
227 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 228 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
228 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); 229 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
229 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 230 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
230 231
231 Assert.That(arr.ControlFileLoaded, Is.True); 232 Assert.That(arr.ControlFileLoaded, Is.True);
232 233
233 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 234 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
234 { 235 {
235 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) 236 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
@@ -265,7 +266,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
265 m_scene.AddNewSceneObject(sog1, false); 266 m_scene.AddNewSceneObject(sog1, false);
266 267
267 SceneObjectPart part2 = CreateSceneObjectPart2(); 268 SceneObjectPart part2 = CreateSceneObjectPart2();
268 269
269 AssetNotecard nc = new AssetNotecard(); 270 AssetNotecard nc = new AssetNotecard();
270 nc.BodyText = "Hello World!"; 271 nc.BodyText = "Hello World!";
271 nc.Encode(); 272 nc.Encode();
@@ -275,10 +276,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
275 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); 276 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
276 m_scene.AssetService.Store(ncAsset); 277 m_scene.AssetService.Store(ncAsset);
277 SceneObjectGroup sog2 = new SceneObjectGroup(part2); 278 SceneObjectGroup sog2 = new SceneObjectGroup(part2);
278 TaskInventoryItem ncItem 279 TaskInventoryItem ncItem
279 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; 280 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
280 part2.Inventory.AddInventoryItem(ncItem, true); 281 part2.Inventory.AddInventoryItem(ncItem, true);
281 282
282 m_scene.AddNewSceneObject(sog2, false); 283 m_scene.AddNewSceneObject(sog2, false);
283 284
284 MemoryStream archiveWriteStream = new MemoryStream(); 285 MemoryStream archiveWriteStream = new MemoryStream();
@@ -287,6 +288,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
287 288
288 Dictionary<string, Object> options = new Dictionary<string, Object>(); 289 Dictionary<string, Object> options = new Dictionary<string, Object>();
289 options.Add("noassets", true); 290 options.Add("noassets", true);
291
290 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); 292 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
291 293
292 // Don't wait for completion - with --noassets save oar happens synchronously 294 // Don't wait for completion - with --noassets save oar happens synchronously
@@ -304,7 +306,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
304 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); 306 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
305 307
306 string filePath; 308 string filePath;
307 TarArchiveReader.TarEntryType tarEntryType; 309 TarArchiveReader.TarEntryType tarEntryType;
308 310
309 byte[] data = tar.ReadEntry(out filePath, out tarEntryType); 311 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
310 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 312 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
@@ -312,9 +314,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
312 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 314 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
313 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); 315 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
314 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 316 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
315 317
316 Assert.That(arr.ControlFileLoaded, Is.True); 318 Assert.That(arr.ControlFileLoaded, Is.True);
317 319
318 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 320 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
319 { 321 {
320 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) 322 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
@@ -343,11 +345,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
343 345
344 MemoryStream archiveWriteStream = new MemoryStream(); 346 MemoryStream archiveWriteStream = new MemoryStream();
345 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); 347 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
346 348
347 // Put in a random blank directory to check that this doesn't upset the load process 349 // Put in a random blank directory to check that this doesn't upset the load process
348 tar.WriteDir("ignoreme"); 350 tar.WriteDir("ignoreme");
349 351
350 // Also check that direct entries which will also have a file entry containing that directory doesn't 352 // Also check that direct entries which will also have a file entry containing that directory doesn't
351 // upset load 353 // upset load
352 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 354 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
353 355
@@ -390,17 +392,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
390 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), 392 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
391 part1.UUID); 393 part1.UUID);
392 tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1)); 394 tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1));
393 395
394 tar.Close(); 396 tar.Close();
395 397
396 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 398 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
397 399
398 lock (this) 400 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
399 { 401 m_oarEvent.Reset();
400 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 402 m_archiverModule.DearchiveRegion(archiveReadStream);
401 m_archiverModule.DearchiveRegion(archiveReadStream); 403
402 } 404 m_oarEvent.WaitOne(60000);
403 405
404 Assert.That(m_lastErrorMessage, Is.Null); 406 Assert.That(m_lastErrorMessage, Is.Null);
405 407
406 TestLoadedRegion(part1, soundItemName, soundData); 408 TestLoadedRegion(part1, soundItemName, soundData);
@@ -444,11 +446,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
444 446
445 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 447 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
446 448
447 lock (this) 449 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
448 { 450 m_oarEvent.Reset();
449 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 451 m_archiverModule.DearchiveRegion(archiveReadStream);
450 m_archiverModule.DearchiveRegion(archiveReadStream); 452
451 } 453 m_oarEvent.WaitOne(60000);
452 454
453 Assert.That(m_lastErrorMessage, Is.Null); 455 Assert.That(m_lastErrorMessage, Is.Null);
454 456
@@ -473,35 +475,33 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
473 m_scene.AddNewSceneObject(sog1, false); 475 m_scene.AddNewSceneObject(sog1, false);
474 476
475 SceneObjectPart part2 = CreateSceneObjectPart2(); 477 SceneObjectPart part2 = CreateSceneObjectPart2();
476 478
477 AssetNotecard nc = new AssetNotecard(); 479 AssetNotecard nc = new AssetNotecard();
478 nc.BodyText = "Hello World!"; 480 nc.BodyText = "Hello World!";
479 nc.Encode(); 481 nc.Encode();
480 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); 482 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
481 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); 483 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
482 AssetBase ncAsset 484 AssetBase ncAsset
483 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); 485 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
484 m_scene.AssetService.Store(ncAsset); 486 m_scene.AssetService.Store(ncAsset);
485 SceneObjectGroup sog2 = new SceneObjectGroup(part2); 487 SceneObjectGroup sog2 = new SceneObjectGroup(part2);
486 TaskInventoryItem ncItem 488 TaskInventoryItem ncItem
487 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; 489 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
488 part2.Inventory.AddInventoryItem(ncItem, true); 490 part2.Inventory.AddInventoryItem(ncItem, true);
489 491
490 m_scene.AddNewSceneObject(sog2, false); 492 m_scene.AddNewSceneObject(sog2, false);
491 493
492 MemoryStream archiveWriteStream = new MemoryStream(); 494 MemoryStream archiveWriteStream = new MemoryStream();
493 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 495 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
494 496
495 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); 497 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
496 498
497 lock (this) 499 m_oarEvent.Reset();
498 { 500 m_archiverModule.ArchiveRegion(
499 m_archiverModule.ArchiveRegion(
500 archiveWriteStream, requestId, new Dictionary<string, Object>() { { "wipe-owners", Boolean.TrueString } }); 501 archiveWriteStream, requestId, new Dictionary<string, Object>() { { "wipe-owners", Boolean.TrueString } });
501 502
502 Monitor.Wait(this, 60000); 503 m_oarEvent.WaitOne(60000);
503 } 504
504
505 Assert.That(m_lastRequestId, Is.EqualTo(requestId)); 505 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
506 506
507 byte[] archive = archiveWriteStream.ToArray(); 507 byte[] archive = archiveWriteStream.ToArray();
@@ -526,11 +526,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
526 526
527 scene2.RegionInfo.EstateSettings.EstateOwner = estateOwner; 527 scene2.RegionInfo.EstateSettings.EstateOwner = estateOwner;
528 528
529 lock (this) 529 scene2.EventManager.OnOarFileLoaded += LoadCompleted;
530 { 530 m_oarEvent.Reset();
531 scene2.EventManager.OnOarFileLoaded += LoadCompleted; 531 archiverModule.DearchiveRegion(archiveReadStream);
532 archiverModule.DearchiveRegion(archiveReadStream); 532
533 } 533 m_oarEvent.WaitOne(60000);
534 534
535 Assert.That(m_lastErrorMessage, Is.Null); 535 Assert.That(m_lastErrorMessage, Is.Null);
536 536
@@ -557,16 +557,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
557 MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector(); 557 MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector();
558 558
559 IConfigSource configSource = new IniConfigSource(); 559 IConfigSource configSource = new IniConfigSource();
560 IConfig config = configSource.AddConfig("Groups"); 560 IConfig config = configSource.AddConfig("Groups");
561 config.Set("Enabled", true); 561 config.Set("Enabled", true);
562 config.Set("Module", "GroupsModule"); 562 config.Set("Module", "GroupsModule");
563 config.Set("DebugEnabled", true); 563 config.Set("DebugEnabled", true);
564 SceneHelpers.SetupSceneModules( 564 SceneHelpers.SetupSceneModules(
565 m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() }); 565 m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() });
566 566
567 // Create group in scene for loading 567 // Create group in scene for loading
568 // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests. 568 // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests.
569 UUID groupID 569 UUID groupID
570 = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero); 570 = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero);
571 571
572 // Construct OAR 572 // Construct OAR
@@ -591,11 +591,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
591 oarStream = new MemoryStream(oarStream.ToArray()); 591 oarStream = new MemoryStream(oarStream.ToArray());
592 592
593 // Load OAR 593 // Load OAR
594 lock (this) 594 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
595 { 595 m_oarEvent.Reset();
596 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 596 m_archiverModule.DearchiveRegion(oarStream);
597 m_archiverModule.DearchiveRegion(oarStream); 597
598 } 598 m_oarEvent.WaitOne(60000);
599 599
600 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16); 600 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16);
601 LandData rLd = rLo.LandData; 601 LandData rLd = rLo.LandData;
@@ -617,7 +617,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
617 617
618 MemoryStream archiveWriteStream = new MemoryStream(); 618 MemoryStream archiveWriteStream = new MemoryStream();
619 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); 619 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
620 620
621 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 621 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
622 tar.WriteFile( 622 tar.WriteFile(
623 ArchiveConstants.CONTROL_FILE_PATH, 623 ArchiveConstants.CONTROL_FILE_PATH,
@@ -658,17 +658,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
658 rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33")); 658 rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33"));
659 659
660 tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs)); 660 tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs));
661 661
662 tar.Close(); 662 tar.Close();
663 663
664 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 664 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
665 665
666 lock (this) 666 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
667 { 667 m_oarEvent.Reset();
668 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 668 m_archiverModule.DearchiveRegion(archiveReadStream);
669 m_archiverModule.DearchiveRegion(archiveReadStream); 669
670 } 670 m_oarEvent.WaitOne(60000);
671 671
672 Assert.That(m_lastErrorMessage, Is.Null); 672 Assert.That(m_lastErrorMessage, Is.Null);
673 RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings; 673 RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings;
674 674
@@ -705,7 +705,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
705 Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID 705 Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID
706 Assert.AreEqual(0, loadedRs.SpawnPoints().Count); 706 Assert.AreEqual(0, loadedRs.SpawnPoints().Count);
707 } 707 }
708 708
709 /// <summary> 709 /// <summary>
710 /// Test merging an OpenSim Region Archive into an existing scene 710 /// Test merging an OpenSim Region Archive into an existing scene
711 /// </summary> 711 /// </summary>
@@ -737,13 +737,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
737 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); 737 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
738 738
739 // Write out this scene 739 // Write out this scene
740
740 scene.EventManager.OnOarFileSaved += SaveCompleted; 741 scene.EventManager.OnOarFileSaved += SaveCompleted;
742 m_oarEvent.Reset();
743 m_archiverModule.ArchiveRegion(archiveWriteStream);
741 744
742 lock (this) 745 m_oarEvent.WaitOne(60000);
743 {
744 m_archiverModule.ArchiveRegion(archiveWriteStream);
745 Monitor.Wait(this, 60000);
746 }
747 } 746 }
748 747
749 { 748 {
@@ -754,10 +753,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
754 byte[] archive = archiveWriteStream.ToArray(); 753 byte[] archive = archiveWriteStream.ToArray();
755 MemoryStream archiveReadStream = new MemoryStream(archive); 754 MemoryStream archiveReadStream = new MemoryStream(archive);
756 755
756 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
757 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 757 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
758 archiveOptions.Add("merge", null); 758 archiveOptions.Add("merge", null);
759 m_oarEvent.Reset();
759 m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions); 760 m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions);
760 761
762 m_oarEvent.WaitOne(60000);
763
761 SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name); 764 SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
762 Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); 765 Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
763 Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge"); 766 Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge");
@@ -816,7 +819,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
816 SceneObjectGroup sog1; 819 SceneObjectGroup sog1;
817 SceneObjectGroup sog2; 820 SceneObjectGroup sog2;
818 UUID ncAssetUuid; 821 UUID ncAssetUuid;
819 822
820 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid); 823 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
821 824
822 expectedPaths[scene.RegionInfo.RegionID] = new List<string>(); 825 expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
@@ -829,18 +832,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
829 832
830 // Save OAR 833 // Save OAR
831 MemoryStream archiveWriteStream = new MemoryStream(); 834 MemoryStream archiveWriteStream = new MemoryStream();
832 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
833 835
834 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); 836 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
835 837
836 Dictionary<string, Object> options = new Dictionary<string, Object>(); 838 Dictionary<string, Object> options = new Dictionary<string, Object>();
837 options.Add("all", true); 839 options.Add("all", true);
838 840
839 lock (this) 841 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
840 { 842 m_oarEvent.Reset();
841 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); 843 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
842 Monitor.Wait(this, 60000); 844
843 } 845 m_oarEvent.WaitOne(60000);
844 846
845 847
846 // Check that the OAR contains the expected data 848 // Check that the OAR contains the expected data
@@ -991,7 +993,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
991 993
992 tar.Close(); 994 tar.Close();
993 995
994 996
995 // Delete the current objects, to test that they're loaded from the OAR and didn't 997 // Delete the current objects, to test that they're loaded from the OAR and didn't
996 // just remain in the scene. 998 // just remain in the scene.
997 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene) 999 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
@@ -1007,11 +1009,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
1007 1009
1008 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 1010 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
1009 1011
1010 lock (this) 1012 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
1011 { 1013 m_oarEvent.Reset();
1012 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 1014 m_archiverModule.DearchiveRegion(archiveReadStream);
1013 m_archiverModule.DearchiveRegion(archiveReadStream); 1015
1014 } 1016 m_oarEvent.WaitOne(60000);
1015 1017
1016 Assert.That(m_lastErrorMessage, Is.Null); 1018 Assert.That(m_lastErrorMessage, Is.Null);
1017 1019
@@ -1027,8 +1029,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
1027 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 1029 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
1028 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); 1030 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
1029 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); 1031 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
1030 Assert.That( 1032
1031 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); 1033 Quaternion qtmp1 = new Quaternion (
1034 (float)Math.Round(object1PartLoaded.RotationOffset.X,5),
1035 (float)Math.Round(object1PartLoaded.RotationOffset.Y,5),
1036 (float)Math.Round(object1PartLoaded.RotationOffset.Z,5),
1037 (float)Math.Round(object1PartLoaded.RotationOffset.W,5));
1038 Quaternion qtmp2 = new Quaternion (
1039 (float)Math.Round(part1.RotationOffset.X,5),
1040 (float)Math.Round(part1.RotationOffset.Y,5),
1041 (float)Math.Round(part1.RotationOffset.Z,5),
1042 (float)Math.Round(part1.RotationOffset.W,5));
1043
1044 Assert.That(qtmp1, Is.EqualTo(qtmp2), "object1 rotation offset not equal");
1032 Assert.That( 1045 Assert.That(
1033 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); 1046 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
1034 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); 1047 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
diff --git a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
index d217f36..a450dd6 100644
--- a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
+++ b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading;
30using Mono.Addins; 31using Mono.Addins;
31using Nini.Config; 32using Nini.Config;
32using OpenMetaverse; 33using OpenMetaverse;
@@ -39,16 +40,20 @@ namespace OpenSim.Region.CoreModules.World
39 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CloudModule")] 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CloudModule")]
40 public class CloudModule : ICloudModule, INonSharedRegionModule 41 public class CloudModule : ICloudModule, INonSharedRegionModule
41 { 42 {
42// private static readonly log4net.ILog m_log 43// private static readonly log4net.ILog m_log
43// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 44// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
44 private uint m_frame = 0; 45 private uint m_frame = 0;
45 private int m_frameUpdateRate = 1000; 46 private int m_frameUpdateRate = 1000;
46 private Random m_rndnums = new Random(Environment.TickCount); 47 private Random m_rndnums;
47 private Scene m_scene = null; 48 private Scene m_scene = null;
48 private bool m_ready = false; 49 private bool m_ready = false;
49 private bool m_enabled = false; 50 private bool m_enabled = false;
50 private float m_cloudDensity = 1.0F; 51 private float m_cloudDensity = 1.0F;
51 private float[] cloudCover = new float[16 * 16]; 52 private float[] cloudCover = new float[16 * 16];
53 private int m_dataVersion;
54 private bool m_busy;
55 private object cloudlock = new object();
56
52 57
53 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
54 { 59 {
@@ -70,11 +75,17 @@ namespace OpenSim.Region.CoreModules.World
70 75
71 m_scene = scene; 76 m_scene = scene;
72 77
73 scene.EventManager.OnNewClient += CloudsToClient;
74 scene.RegisterModuleInterface<ICloudModule>(this); 78 scene.RegisterModuleInterface<ICloudModule>(this);
75 scene.EventManager.OnFrame += CloudUpdate; 79 int seed = Environment.TickCount;
80 seed += (int)(scene.RegionInfo.RegionLocX << 16);
81 seed += (int)(scene.RegionInfo.RegionLocY);
82 m_rndnums = new Random(seed);
76 83
77 GenerateCloudCover(); 84 GenerateCloudCover();
85 m_dataVersion = (int)m_scene.AllocateLocalId();
86
87 scene.EventManager.OnNewClient += CloudsToClient;
88 scene.EventManager.OnFrame += CloudUpdate;
78 89
79 m_ready = true; 90 m_ready = true;
80 } 91 }
@@ -89,7 +100,6 @@ namespace OpenSim.Region.CoreModules.World
89 m_scene.EventManager.OnNewClient -= CloudsToClient; 100 m_scene.EventManager.OnNewClient -= CloudsToClient;
90 m_scene.EventManager.OnFrame -= CloudUpdate; 101 m_scene.EventManager.OnFrame -= CloudUpdate;
91 m_scene.UnregisterModuleInterface<ICloudModule>(this); 102 m_scene.UnregisterModuleInterface<ICloudModule>(this);
92
93 m_scene = null; 103 m_scene = null;
94 } 104 }
95 105
@@ -127,7 +137,8 @@ namespace OpenSim.Region.CoreModules.World
127 137
128 if (cloudCover != null) 138 if (cloudCover != null)
129 { 139 {
130 cover = cloudCover[y * 16 + x]; 140 lock(cloudlock)
141 cover = cloudCover[y * 16 + x];
131 } 142 }
132 143
133 return cover; 144 return cover;
@@ -152,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World
152 columnRight = 0; 163 columnRight = 0;
153 columnLeft = x - 1; 164 columnLeft = x - 1;
154 } 165 }
155 else 166 else
156 { 167 {
157 columnRight = x + 1; 168 columnRight = x + 1;
158 columnLeft = x - 1; 169 columnLeft = x - 1;
@@ -174,40 +185,65 @@ namespace OpenSim.Region.CoreModules.World
174 rowAbove = y + 1; 185 rowAbove = y + 1;
175 rowBelow = y - 1; 186 rowBelow = y - 1;
176 } 187 }
177 float neighborAverage = (cloudCover[rowBelow * 16 + columnLeft] + 188 float neighborAverage = (cloudCover[rowBelow * 16 + columnLeft] +
178 cloudCover[y * 16 + columnLeft] + 189 cloudCover[y * 16 + columnLeft] +
179 cloudCover[rowAbove * 16 + columnLeft] + 190 cloudCover[rowAbove * 16 + columnLeft] +
180 cloudCover[rowBelow * 16 + x] + 191 cloudCover[rowBelow * 16 + x] +
181 cloudCover[rowAbove * 16 + x] + 192 cloudCover[rowAbove * 16 + x] +
182 cloudCover[rowBelow * 16 + columnRight] + 193 cloudCover[rowBelow * 16 + columnRight] +
183 cloudCover[y * 16 + columnRight] + 194 cloudCover[y * 16 + columnRight] +
184 cloudCover[rowAbove * 16 + columnRight] + 195 cloudCover[rowAbove * 16 + columnRight] +
185 cloudCover[y * 16 + x]) / 9; 196 cloudCover[y * 16 + x]) / 9;
186 newCover[y * 16 + x] = ((neighborAverage / m_cloudDensity) + 0.175f) % 1.0f; 197 newCover[y * 16 + x] = ((neighborAverage / m_cloudDensity) + 0.175f) % 1.0f;
187 newCover[y * 16 + x] *= m_cloudDensity; 198 newCover[y * 16 + x] *= m_cloudDensity;
188 } 199 }
189 } 200 }
190 Array.Copy(newCover, cloudCover, 16 * 16); 201 Array.Copy(newCover, cloudCover, 16 * 16);
202 m_dataVersion++;
191 } 203 }
192 204
193 private void CloudUpdate() 205 private void CloudUpdate()
194 { 206 {
195 if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready || (m_cloudDensity == 0)) 207 if ((!m_ready || m_busy || m_cloudDensity == 0 ||
196 { 208 (m_frame++ % m_frameUpdateRate) != 0))
197 return; 209 return;
198 } 210
199 UpdateCloudCover(); 211 if(Monitor.TryEnter(cloudlock))
212 {
213 m_busy = true;
214 Util.FireAndForget(delegate
215 {
216 try
217 {
218 lock(cloudlock)
219 {
220 UpdateCloudCover();
221 m_scene.ForEachClient(delegate(IClientAPI client)
222 {
223 client.SendCloudData(m_dataVersion, cloudCover);
224 });
225 }
226 }
227 finally
228 {
229 m_busy = false;
230 }
231 },
232 null, "CloudModuleUpdate");
233 Monitor.Exit(cloudlock);
234 }
200 } 235 }
201 236
202 public void CloudsToClient(IClientAPI client) 237 public void CloudsToClient(IClientAPI client)
203 { 238 {
204 if (m_ready) 239 if (m_ready)
205 { 240 {
206 client.SendCloudData(cloudCover); 241 lock(cloudlock)
242 client.SendCloudData(m_dataVersion, cloudCover);
207 } 243 }
208 } 244 }
209 245
210 246
211 /// <summary> 247 /// <summary>
212 /// Calculate the cloud cover over the region. 248 /// Calculate the cloud cover over the region.
213 /// </summary> 249 /// </summary>
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs b/OpenSim/Region/CoreModules/World/Estate/EstateConnector.cs
index 73e706c..8001c3c 100644
--- a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateConnector.cs
@@ -45,17 +45,22 @@ namespace OpenSim.Region.CoreModules.World.Estate
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 protected XEstateModule m_EstateModule; 48 protected EstateModule m_EstateModule;
49 private string token;
50 uint port = 0;
49 51
50 public EstateConnector(XEstateModule module) 52 public EstateConnector(EstateModule module, string _token, uint _port)
51 { 53 {
52 m_EstateModule = module; 54 m_EstateModule = module;
55 token = _token;
56 port = _port;
53 } 57 }
54 58
55 public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID) 59 public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID)
56 { 60 {
57 Dictionary<string, object> sendData = new Dictionary<string, object>(); 61 Dictionary<string, object> sendData = new Dictionary<string, object>();
58 sendData["METHOD"] = "teleport_home_one_user"; 62 sendData["METHOD"] = "teleport_home_one_user";
63 sendData["TOKEN"] = token;
59 64
60 sendData["EstateID"] = EstateID.ToString(); 65 sendData["EstateID"] = EstateID.ToString();
61 sendData["PreyID"] = PreyID.ToString(); 66 sendData["PreyID"] = PreyID.ToString();
@@ -67,6 +72,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
67 { 72 {
68 Dictionary<string, object> sendData = new Dictionary<string, object>(); 73 Dictionary<string, object> sendData = new Dictionary<string, object>();
69 sendData["METHOD"] = "teleport_home_all_users"; 74 sendData["METHOD"] = "teleport_home_all_users";
75 sendData["TOKEN"] = token;
70 76
71 sendData["EstateID"] = EstateID.ToString(); 77 sendData["EstateID"] = EstateID.ToString();
72 78
@@ -77,6 +83,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
77 { 83 {
78 Dictionary<string, object> sendData = new Dictionary<string, object>(); 84 Dictionary<string, object> sendData = new Dictionary<string, object>();
79 sendData["METHOD"] = "update_covenant"; 85 sendData["METHOD"] = "update_covenant";
86 sendData["TOKEN"] = token;
80 87
81 sendData["CovenantID"] = CovenantID.ToString(); 88 sendData["CovenantID"] = CovenantID.ToString();
82 sendData["EstateID"] = EstateID.ToString(); 89 sendData["EstateID"] = EstateID.ToString();
@@ -99,6 +106,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
99 { 106 {
100 Dictionary<string, object> sendData = new Dictionary<string, object>(); 107 Dictionary<string, object> sendData = new Dictionary<string, object>();
101 sendData["METHOD"] = "update_estate"; 108 sendData["METHOD"] = "update_estate";
109 sendData["TOKEN"] = token;
102 110
103 sendData["EstateID"] = EstateID.ToString(); 111 sendData["EstateID"] = EstateID.ToString();
104 112
@@ -119,6 +127,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
119 { 127 {
120 Dictionary<string, object> sendData = new Dictionary<string, object>(); 128 Dictionary<string, object> sendData = new Dictionary<string, object>();
121 sendData["METHOD"] = "estate_message"; 129 sendData["METHOD"] = "estate_message";
130 sendData["TOKEN"] = token;
122 131
123 sendData["EstateID"] = EstateID.ToString(); 132 sendData["EstateID"] = EstateID.ToString();
124 sendData["FromID"] = FromID.ToString(); 133 sendData["FromID"] = FromID.ToString();
@@ -132,47 +141,43 @@ namespace OpenSim.Region.CoreModules.World.Estate
132 { 141 {
133 List<UUID> regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID); 142 List<UUID> regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID);
134 143
135 UUID ScopeID = UUID.Zero; 144 // Don't send to the same instance twice
145 List<string> done = new List<string>();
136 146
137 // Handle local regions locally 147 // Handle local regions locally
138 //
139 lock (m_EstateModule.Scenes) 148 lock (m_EstateModule.Scenes)
140 { 149 {
141 foreach (Scene s in m_EstateModule.Scenes) 150 foreach (Scene s in m_EstateModule.Scenes)
142 { 151 {
143 if (regions.Contains(s.RegionInfo.RegionID)) 152 RegionInfo sreg = s.RegionInfo;
153 if (regions.Contains(sreg.RegionID))
144 { 154 {
145 // All regions in one estate are in the same scope. 155 string url = sreg.ExternalHostName + ":" + sreg.HttpPort;
146 // Use that scope. 156 regions.Remove(sreg.RegionID);
147 // 157 if(!done.Contains(url)) // we may have older regs with same url lost in dbs
148 ScopeID = s.RegionInfo.ScopeID; 158 done.Add(url);
149 regions.Remove(s.RegionInfo.RegionID);
150 } 159 }
151 } 160 }
152 } 161 }
153 162
154 // Our own region should always be in the above list. 163 if(regions.Count == 0)
155 // In a standalone this would not be true. But then, 164 return;
156 // Scope ID is not relevat there. Use first scope.
157 //
158 if (ScopeID == UUID.Zero)
159 ScopeID = m_EstateModule.Scenes[0].RegionInfo.ScopeID;
160 165
161 // Don't send to the same instance twice 166 Scene baseScene = m_EstateModule.Scenes[0];
162 // 167 UUID ScopeID = baseScene.RegionInfo.ScopeID;
163 List<string> done = new List<string>(); 168 IGridService gridService = baseScene.GridService;
169 if(gridService == null)
170 return;
164 171
165 // Send to remote regions 172 // Send to remote regions
166 //
167 foreach (UUID regionID in regions) 173 foreach (UUID regionID in regions)
168 { 174 {
169 GridRegion region = m_EstateModule.Scenes[0].GridService.GetRegionByUUID(ScopeID, regionID); 175 GridRegion region = gridService.GetRegionByUUID(ScopeID, regionID);
170 if (region != null) 176 if (region != null)
171 { 177 {
172 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; 178 string url = region.ExternalHostName + ":" + region.HttpPort;
173 if (done.Contains(url)) 179 if(done.Contains(url))
174 continue; 180 continue;
175
176 Call(region, sendData); 181 Call(region, sendData);
177 done.Add(url); 182 done.Add(url);
178 } 183 }
@@ -185,9 +190,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
185 // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString); 190 // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString);
186 try 191 try
187 { 192 {
188 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; 193 string url = "";
194 if(port != 0)
195 url = "http://" + region.ExternalHostName + ":" + port + "/";
196 else
197 url = region.ServerURI;
198
189 string reply = SynchronousRestFormsRequester.MakeRequest("POST", 199 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
190 url + "/estate", 200 url + "estate",
191 reqString); 201 reqString);
192 if (reply != string.Empty) 202 if (reply != string.Empty)
193 { 203 {
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index 702b503..7879f83 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -49,18 +49,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
49 public class EstateManagementCommands 49 public class EstateManagementCommands
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 protected EstateManagementModule m_module; 53 protected EstateManagementModule m_module;
54 54
55 public EstateManagementCommands(EstateManagementModule module) 55 public EstateManagementCommands(EstateManagementModule module)
56 { 56 {
57 m_module = module; 57 m_module = module;
58 } 58 }
59 59
60 public void Initialise() 60 public void Initialise()
61 { 61 {
62// m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName); 62// m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName);
63 63
64 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture", 64 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture",
65 "set terrain texture <number> <uuid> [<x>] [<y>]", 65 "set terrain texture <number> <uuid> [<x>] [<y>]",
66 "Sets the terrain <number> to <uuid>, if <x> or <y> are specified, it will only " + 66 "Sets the terrain <number> to <uuid>, if <x> or <y> are specified, it will only " +
@@ -77,14 +77,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
77 77
78 m_module.Scene.AddCommand("Regions", m_module, "set water height", 78 m_module.Scene.AddCommand("Regions", m_module, "set water height",
79 "set water height <height> [<x>] [<y>]", 79 "set water height <height> [<x>] [<y>]",
80 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " + 80 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " +
81 "Specify -1 in <x> or <y> to wildcard that coordinate.", 81 "Specify -1 in <x> or <y> to wildcard that coordinate.",
82 consoleSetWaterHeight); 82 consoleSetWaterHeight);
83 83
84 m_module.Scene.AddCommand( 84 m_module.Scene.AddCommand(
85 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand); 85 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
86 } 86 }
87 87
88 public void Close() {} 88 public void Close() {}
89 89
90 #region CommandHandlers 90 #region CommandHandlers
@@ -120,7 +120,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
120 m_module.Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; 120 m_module.Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture;
121 break; 121 break;
122 } 122 }
123 123
124 m_module.Scene.RegionInfo.RegionSettings.Save(); 124 m_module.Scene.RegionInfo.RegionSettings.Save();
125 m_module.TriggerRegionInfoChange(); 125 m_module.TriggerRegionInfoChange();
126 m_module.sendRegionHandshakeToAll(); 126 m_module.sendRegionHandshakeToAll();
@@ -130,7 +130,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
130 protected void consoleSetWaterHeight(string module, string[] args) 130 protected void consoleSetWaterHeight(string module, string[] args)
131 { 131 {
132 string heightstring = args[3]; 132 string heightstring = args[3];
133 133
134 int x = (args.Length > 4 ? int.Parse(args[4]) : -1); 134 int x = (args.Length > 4 ? int.Parse(args[4]) : -1);
135 int y = (args.Length > 5 ? int.Parse(args[5]) : -1); 135 int y = (args.Length > 5 ? int.Parse(args[5]) : -1);
136 136
@@ -143,13 +143,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
143 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " + 143 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " +
144 string.Format(" {0}", selectedheight)); 144 string.Format(" {0}", selectedheight));
145 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight; 145 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight;
146 146
147 m_module.Scene.RegionInfo.RegionSettings.Save(); 147 m_module.Scene.RegionInfo.RegionSettings.Save();
148 m_module.TriggerRegionInfoChange(); 148 m_module.TriggerRegionInfoChange();
149 m_module.sendRegionHandshakeToAll(); 149 m_module.sendRegionHandshakeToAll();
150 } 150 }
151 } 151 }
152 } 152 }
153 protected void consoleSetTerrainHeights(string module, string[] args) 153 protected void consoleSetTerrainHeights(string module, string[] args)
154 { 154 {
155 string num = args[3]; 155 string num = args[3];
@@ -198,31 +198,31 @@ namespace OpenSim.Region.CoreModules.World.Estate
198 m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; 198 m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
199 break; 199 break;
200 } 200 }
201 201
202 m_module.Scene.RegionInfo.RegionSettings.Save(); 202 m_module.Scene.RegionInfo.RegionSettings.Save();
203 m_module.TriggerRegionInfoChange(); 203 m_module.TriggerRegionInfoChange();
204 m_module.sendRegionHandshakeToAll(); 204 m_module.sendRegionHandshakeToAll();
205 } 205 }
206 } 206 }
207 } 207 }
208 208
209 protected void ShowEstatesCommand(string module, string[] cmd) 209 protected void ShowEstatesCommand(string module, string[] cmd)
210 { 210 {
211 StringBuilder report = new StringBuilder(); 211 StringBuilder report = new StringBuilder();
212 RegionInfo ri = m_module.Scene.RegionInfo; 212 RegionInfo ri = m_module.Scene.RegionInfo;
213 EstateSettings es = ri.EstateSettings; 213 EstateSettings es = ri.EstateSettings;
214 214
215 report.AppendFormat("Estate information for region {0}\n", ri.RegionName); 215 report.AppendFormat("Estate information for region {0}\n", ri.RegionName);
216 report.AppendFormat( 216 report.AppendFormat(
217 "{0,-20} {1,-7} {2,-20}\n", 217 "{0,-20} {1,-7} {2,-20}\n",
218 "Estate Name", 218 "Estate Name",
219 "ID", 219 "ID",
220 "Owner"); 220 "Owner");
221 221
222 report.AppendFormat( 222 report.AppendFormat(
223 "{0,-20} {1,-7} {2,-20}\n", 223 "{0,-20} {1,-7} {2,-20}\n",
224 es.EstateName, es.EstateID, m_module.UserManager.GetUserName(es.EstateOwner)); 224 es.EstateName, es.EstateID, m_module.UserManager.GetUserName(es.EstateOwner));
225 225
226 MainConsole.Instance.Output(report.ToString()); 226 MainConsole.Instance.Output(report.ToString());
227 } 227 }
228 #endregion 228 #endregion
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 80fa08a..924f448 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -33,15 +33,19 @@ using System.Linq;
33using System.Reflection; 33using System.Reflection;
34using System.Security; 34using System.Security;
35using System.Timers; 35using System.Timers;
36using System.Threading;
36using log4net; 37using log4net;
37using Mono.Addins; 38using Mono.Addins;
38using Nini.Config; 39using Nini.Config;
39using OpenMetaverse; 40using OpenMetaverse;
40using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
44using RegionFlags = OpenMetaverse.RegionFlags; 46using RegionFlags = OpenMetaverse.RegionFlags;
47using Timer = System.Timers.Timer;
48
45 49
46namespace OpenSim.Region.CoreModules.World.Estate 50namespace OpenSim.Region.CoreModules.World.Estate
47{ 51{
@@ -53,8 +57,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
53 private Timer m_regionChangeTimer = new Timer(); 57 private Timer m_regionChangeTimer = new Timer();
54 public Scene Scene { get; private set; } 58 public Scene Scene { get; private set; }
55 public IUserManagement UserManager { get; private set; } 59 public IUserManagement UserManager { get; private set; }
56 60
57 protected EstateManagementCommands m_commands; 61 protected EstateManagementCommands m_commands;
58 62
59 /// <summary> 63 /// <summary>
60 /// If false, region restart requests from the client are blocked even if they are otherwise legitimate. 64 /// If false, region restart requests from the client are blocked even if they are otherwise legitimate.
@@ -67,14 +71,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
67 public event ChangeDelegate OnRegionInfoChange; 71 public event ChangeDelegate OnRegionInfoChange;
68 public event ChangeDelegate OnEstateInfoChange; 72 public event ChangeDelegate OnEstateInfoChange;
69 public event MessageDelegate OnEstateMessage; 73 public event MessageDelegate OnEstateMessage;
74 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
75 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
76
77 private int m_delayCount = 0;
70 78
71 #region Region Module interface 79 #region Region Module interface
72 80
73 public string Name { get { return "EstateManagementModule"; } } 81 public string Name { get { return "EstateManagementModule"; } }
74
75 public Type ReplaceableInterface { get { return null; } }
76 82
77 public void Initialise(IConfigSource source) 83 public Type ReplaceableInterface { get { return null; } }
84
85 public void Initialise(IConfigSource source)
78 { 86 {
79 AllowRegionRestartFromClient = true; 87 AllowRegionRestartFromClient = true;
80 88
@@ -83,7 +91,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
83 if (config != null) 91 if (config != null)
84 AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true); 92 AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true);
85 } 93 }
86 94
87 public void AddRegion(Scene scene) 95 public void AddRegion(Scene scene)
88 { 96 {
89 Scene = scene; 97 Scene = scene;
@@ -95,20 +103,24 @@ namespace OpenSim.Region.CoreModules.World.Estate
95 103
96 m_commands = new EstateManagementCommands(this); 104 m_commands = new EstateManagementCommands(this);
97 m_commands.Initialise(); 105 m_commands.Initialise();
106
107 m_regionChangeTimer.Interval = 10000;
108 m_regionChangeTimer.Elapsed += RaiseRegionInfoChange;
109 m_regionChangeTimer.AutoReset = false;
98 } 110 }
99 111
100 public void RemoveRegion(Scene scene) {} 112 public void RemoveRegion(Scene scene) {}
101 113
102 public void RegionLoaded(Scene scene) 114 public void RegionLoaded(Scene scene)
103 { 115 {
104 // Sets up the sun module based no the saved Estate and Region Settings 116 // Sets up the sun module based no the saved Estate and Region Settings
105 // DO NOT REMOVE or the sun will stop working 117 // DO NOT REMOVE or the sun will stop working
106 scene.TriggerEstateSunUpdate(); 118 scene.TriggerEstateSunUpdate();
107 119
108 UserManager = scene.RequestModuleInterface<IUserManagement>(); 120 UserManager = scene.RequestModuleInterface<IUserManagement>();
109 } 121 }
110 122
111 public void Close() 123 public void Close()
112 { 124 {
113 m_commands.Close(); 125 m_commands.Close();
114 } 126 }
@@ -142,6 +154,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
142 flags |= RegionFlags.AllowParcelChanges; 154 flags |= RegionFlags.AllowParcelChanges;
143 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) 155 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch)
144 flags |= RegionFlags.BlockParcelSearch; 156 flags |= RegionFlags.BlockParcelSearch;
157 if (Scene.RegionInfo.RegionSettings.GodBlockSearch)
158 flags |= (RegionFlags)(1 << 11);
159 if (Scene.RegionInfo.RegionSettings.Casino)
160 flags |= (RegionFlags)(1 << 10);
145 161
146 if (Scene.RegionInfo.RegionSettings.FixedSun) 162 if (Scene.RegionInfo.RegionSettings.FixedSun)
147 flags |= RegionFlags.SunFixed; 163 flags |= RegionFlags.SunFixed;
@@ -194,6 +210,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
194 change(Scene.RegionInfo.RegionID); 210 change(Scene.RegionInfo.RegionID);
195 } 211 }
196 212
213 protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e)
214 {
215 ChangeDelegate change = OnRegionInfoChange;
216
217 if (change != null)
218 change(Scene.RegionInfo.RegionID);
219 }
220
197 public void TriggerRegionInfoChange() 221 public void TriggerRegionInfoChange()
198 { 222 {
199 m_regionChangeTimer.Stop(); 223 m_regionChangeTimer.Stop();
@@ -423,7 +447,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
423 Scene.RegionInfo.EstateSettings.EstateID); 447 Scene.RegionInfo.EstateSettings.EstateID);
424 448
425 remote_client.SendEstateList(invoice, 449 remote_client.SendEstateList(invoice,
426 (int)Constants.EstateAccessCodex.AccessOptions, 450 (int)Constants.EstateAccessCodex.AllowedAccess,
427 Scene.RegionInfo.EstateSettings.EstateAccess, 451 Scene.RegionInfo.EstateSettings.EstateAccess,
428 Scene.RegionInfo.EstateSettings.EstateID); 452 Scene.RegionInfo.EstateSettings.EstateID);
429 453
@@ -462,7 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
462 486
463 if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity) 487 if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity)
464 Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; 488 Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents;
465 else 489 else
466 Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity; 490 Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity;
467 491
468 Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; 492 Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor;
@@ -554,6 +578,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
554 bool UseEstateSun, bool UseFixedSun, float SunHour, 578 bool UseEstateSun, bool UseFixedSun, float SunHour,
555 bool UseGlobal, bool EstateFixedSun, float EstateSunHour) 579 bool UseGlobal, bool EstateFixedSun, float EstateSunHour)
556 { 580 {
581 double lastwaterlevel = Scene.RegionInfo.RegionSettings.WaterHeight;
557 // Water Height 582 // Water Height
558 Scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight; 583 Scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight;
559 584
@@ -566,6 +591,9 @@ namespace OpenSim.Region.CoreModules.World.Estate
566 Scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun; 591 Scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun;
567 Scene.RegionInfo.RegionSettings.SunPosition = SunHour; 592 Scene.RegionInfo.RegionSettings.SunPosition = SunHour;
568 593
594 if(Scene.PhysicsEnabled && Scene.PhysicsScene != null && lastwaterlevel != WaterHeight)
595 Scene.PhysicsScene.SetWaterLevel(WaterHeight);
596
569 Scene.TriggerEstateSunUpdate(); 597 Scene.TriggerEstateSunUpdate();
570 598
571 //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString()); 599 //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString());
@@ -587,6 +615,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
587 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 615 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
588 if (restartModule != null) 616 if (restartModule != null)
589 { 617 {
618 if (timeInSeconds == -1)
619 {
620 m_delayCount++;
621 if (m_delayCount > 3)
622 return;
623
624 restartModule.DelayRestart(3600, "Restart delayed by region manager");
625 return;
626 }
627
590 List<int> times = new List<int>(); 628 List<int> times = new List<int>();
591 while (timeInSeconds > 0) 629 while (timeInSeconds > 0)
592 { 630 {
@@ -602,7 +640,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
602 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false); 640 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false);
603 641
604 m_log.InfoFormat( 642 m_log.InfoFormat(
605 "User {0} requested restart of region {1} in {2} seconds", 643 "User {0} requested restart of region {1} in {2} seconds",
606 remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0); 644 remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0);
607 } 645 }
608 } 646 }
@@ -610,236 +648,363 @@ namespace OpenSim.Region.CoreModules.World.Estate
610 private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID) 648 private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID)
611 { 649 {
612// m_log.DebugFormat( 650// m_log.DebugFormat(
613// "[ESTATE MANAGEMENT MODULE]: Handling request from {0} to change estate covenant to {1}", 651// "[ESTATE MANAGEMENT MODULE]: Handling request from {0} to change estate covenant to {1}",
614// remoteClient.Name, estateCovenantID); 652// remoteClient.Name, estateCovenantID);
615 653
616 Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; 654 Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID;
617 Scene.RegionInfo.RegionSettings.CovenantChangedDateTime = Util.UnixTimeSinceEpoch(); 655 Scene.RegionInfo.RegionSettings.CovenantChangedDateTime = Util.UnixTimeSinceEpoch();
618 Scene.RegionInfo.RegionSettings.Save(); 656 Scene.RegionInfo.RegionSettings.Save();
619 TriggerRegionInfoChange(); 657 TriggerRegionInfoChange();
620 } 658 }
621 659
622 private void handleEstateAccessDeltaRequest(IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user) 660 private object deltareqLock = new object();
661 private bool runnigDeltaExec = false;
662
663 private class EstateAccessDeltaRequest
664 {
665 public IClientAPI remote_client;
666 public UUID invoice;
667 public int estateAccessType;
668 public UUID user;
669 }
670
671 private OpenSim.Framework.BlockingQueue<EstateAccessDeltaRequest> deltaRequests = new OpenSim.Framework.BlockingQueue<EstateAccessDeltaRequest>();
672
673 private void handleEstateAccessDeltaRequest(IClientAPI _remote_client, UUID _invoice, int _estateAccessType, UUID _user)
623 { 674 {
624 // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc. 675 // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc.
625 676
626 if (user == Scene.RegionInfo.EstateSettings.EstateOwner) 677 if (_user == Scene.RegionInfo.EstateSettings.EstateOwner)
627 return; // never process EO 678 return; // never process EO
628 679
629 if ((estateAccessType & 4) != 0) // User add 680 EstateAccessDeltaRequest newreq = new EstateAccessDeltaRequest();
681 newreq.remote_client = _remote_client;
682 newreq.invoice = _invoice;
683 newreq.estateAccessType = _estateAccessType;
684 newreq.user = _user;
685
686 deltaRequests.Enqueue(newreq);
687
688 lock(deltareqLock)
630 { 689 {
631 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) 690 if(!runnigDeltaExec)
632 { 691 {
633 if ((estateAccessType & 1) != 0) // All estates 692 runnigDeltaExec = true;
693 WorkManager.RunInThreadPool(execDeltaRequests,null,"execDeltaRequests");
694 }
695 }
696 }
697
698 private void execDeltaRequests(object o)
699 {
700 IClientAPI remote_client;
701 UUID invoice;
702 int estateAccessType;
703 UUID user;
704 Dictionary<int,EstateSettings> changed = new Dictionary<int,EstateSettings>();
705 Dictionary<IClientAPI,UUID> sendAllowedOrBanList = new Dictionary<IClientAPI,UUID>();
706 Dictionary<IClientAPI,UUID> sendManagers = new Dictionary<IClientAPI,UUID>();
707 Dictionary<IClientAPI,UUID> sendGroups = new Dictionary<IClientAPI,UUID>();
708
709 List<EstateSettings> otherEstates = new List<EstateSettings>();
710
711 bool sentAllowedFull = false;
712 bool sentBansFull = false;
713 bool sentGroupsFull = false;
714 bool sentManagersFull = false;
715
716 while(Scene.IsRunning)
717 {
718 EstateAccessDeltaRequest req = deltaRequests.Dequeue(500);
719
720 if(!Scene.IsRunning)
721 break;
722
723 if(req == null)
724 {
725 if(changed.Count > 0)
634 { 726 {
635 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 727 foreach(EstateSettings est in changed.Values)
636 EstateSettings estateSettings; 728 Scene.EstateDataService.StoreEstateSettings(est);
637 729
638 foreach (int estateID in estateIDs) 730 TriggerEstateInfoChange();
639 {
640 if (estateID != Scene.RegionInfo.EstateSettings.EstateID)
641 {
642 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID);
643 estateSettings.AddEstateUser(user);
644 Scene.EstateDataService.StoreEstateSettings(estateSettings);
645 }
646 }
647 } 731 }
648 732
649 Scene.RegionInfo.EstateSettings.AddEstateUser(user); 733 EstateSettings es = Scene.RegionInfo.EstateSettings;
650 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 734 foreach(KeyValuePair<IClientAPI,UUID> kvp in sendAllowedOrBanList)
735 {
736 IClientAPI cli = kvp.Key;
737 UUID invoive = kvp.Value;
738 cli.SendEstateList(invoive, (int)Constants.EstateAccessCodex.AllowedAccess, es.EstateAccess, es.EstateID);
739 cli.SendBannedUserList(invoive, es.EstateBans, es.EstateID);
740 }
741 sendAllowedOrBanList.Clear();
651 742
652 TriggerEstateInfoChange(); 743 foreach(KeyValuePair<IClientAPI,UUID> kvp in sendManagers)
653 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, Scene.RegionInfo.EstateSettings.EstateAccess, Scene.RegionInfo.EstateSettings.EstateID); 744 {
745 IClientAPI cli = kvp.Key;
746 cli.SendEstateList(kvp.Value, (int)Constants.EstateAccessCodex.EstateManagers, es.EstateManagers, es.EstateID);
747 }
748 foreach(KeyValuePair<IClientAPI,UUID> kvp in sendGroups)
749 {
750 IClientAPI cli = kvp.Key;
751 cli.SendEstateList(kvp.Value, (int)Constants.EstateAccessCodex.AllowedGroups, es.EstateGroups, es.EstateID);
752 }
753 otherEstates.Clear();
754 sendAllowedOrBanList.Clear();
755 sendManagers.Clear();
756 sendGroups.Clear();
757 changed.Clear();
758 lock(deltareqLock)
759 {
760 if(deltaRequests.Count() != 0)
761 continue;
762 runnigDeltaExec = false;
763 return;
764 }
654 } 765 }
655 else 766
767 remote_client = req.remote_client;
768 if(!remote_client.IsActive)
769 continue;
770
771 invoice = req.invoice;
772 user = req.user;
773
774 estateAccessType = req.estateAccessType;
775
776 bool needReply = ((estateAccessType & 1024) == 0);
777 bool doOtherEstates = ((estateAccessType & 3) != 0);
778
779 EstateSettings thisSettings = Scene.RegionInfo.EstateSettings;
780 int thisEstateID =(int)thisSettings.EstateID;
781
782 UUID agentID = remote_client.AgentId;
783
784 bool isadmin = Scene.Permissions.IsAdministrator(agentID);
785 // just i case recheck rights
786 if (!isadmin && !Scene.Permissions.IsEstateManager(agentID))
656 { 787 {
657 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 788 remote_client.SendAlertMessage("Method EstateAccess Failed, you don't have permissions");
789 continue;
658 } 790 }
659 791
660 } 792 otherEstates.Clear();
661 793 if(doOtherEstates)
662 if ((estateAccessType & 8) != 0) // User remove
663 {
664 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
665 { 794 {
666 if ((estateAccessType & 1) != 0) // All estates 795 UUID thisOwner = Scene.RegionInfo.EstateSettings.EstateOwner;
796 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(thisOwner);
797 foreach (int estateID in estateIDs)
667 { 798 {
668 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 799 if (estateID == thisEstateID)
800 continue;
801
669 EstateSettings estateSettings; 802 EstateSettings estateSettings;
803 if(changed.ContainsKey(estateID))
804 estateSettings = changed[estateID];
805 else
806 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID);
807
808 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
809 continue;
810 otherEstates.Add(estateSettings);
811 }
812 estateIDs.Clear();
813 }
670 814
671 foreach (int estateID in estateIDs) 815 // the commands
816 // first the ones allowed for estate managers on this region
817 if ((estateAccessType & 4) != 0) // User add
818 {
819 if(thisSettings.EstateUsersCount() >= (int)Constants.EstateAccessLimits.AllowedAccess)
820 {
821 if(!sentAllowedFull)
672 { 822 {
673 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 823 sentAllowedFull = true;
824 remote_client.SendAlertMessage("Estate Allowed users list is full");
825 }
826 }
827 else
828 {
829 if (doOtherEstates)
830 {
831 foreach (EstateSettings estateSettings in otherEstates)
674 { 832 {
675 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 833 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
676 estateSettings.RemoveEstateUser(user); 834 continue;
677 Scene.EstateDataService.StoreEstateSettings(estateSettings); 835 if(estateSettings.EstateUsersCount() >= (int)Constants.EstateAccessLimits.AllowedAccess)
836 continue;
837 estateSettings.AddEstateUser(user);
838 estateSettings.RemoveBan(user);
839 changed[(int)estateSettings.EstateID] = estateSettings;
678 } 840 }
679 } 841 }
680 }
681 842
682 Scene.RegionInfo.EstateSettings.RemoveEstateUser(user); 843 thisSettings.AddEstateUser(user);
683 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 844 thisSettings.RemoveBan(user);
845 changed[thisEstateID] = thisSettings;;
684 846
685 TriggerEstateInfoChange(); 847 if(needReply)
686 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, Scene.RegionInfo.EstateSettings.EstateAccess, Scene.RegionInfo.EstateSettings.EstateID); 848 sendAllowedOrBanList[remote_client] = invoice;
849 }
687 } 850 }
688 else 851
852 if ((estateAccessType & 8) != 0) // User remove
689 { 853 {
690 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 854 if (doOtherEstates) // All estates
855 {
856 foreach (EstateSettings estateSettings in otherEstates)
857 {
858 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
859 continue;
860 estateSettings.RemoveEstateUser(user);
861 changed[(int)estateSettings.EstateID] = estateSettings;
862 }
863 }
864
865 thisSettings.RemoveEstateUser(user);
866 changed[thisEstateID] = thisSettings;;
867
868 if(needReply)
869 sendAllowedOrBanList[remote_client] = invoice;
691 } 870 }
692 }
693 871
694 if ((estateAccessType & 16) != 0) // Group add 872 if ((estateAccessType & 16) != 0) // Group add
695 {
696 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
697 { 873 {
698 if ((estateAccessType & 1) != 0) // All estates 874 if(thisSettings.EstateGroupsCount() >= (int)Constants.EstateAccessLimits.AllowedGroups)
699 { 875 {
700 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 876 if(!sentGroupsFull)
701 EstateSettings estateSettings; 877 {
702 878 sentGroupsFull = true;
703 foreach (int estateID in estateIDs) 879 remote_client.SendAlertMessage("Estate Allowed groups list is full");
880 }
881 }
882 else
883 {
884 if (doOtherEstates) // All estates
704 { 885 {
705 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 886 foreach (EstateSettings estateSettings in otherEstates)
706 { 887 {
707 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 888 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
889 continue;
890 if(estateSettings.EstateGroupsCount() >= (int)Constants.EstateAccessLimits.AllowedGroups)
891 continue;
708 estateSettings.AddEstateGroup(user); 892 estateSettings.AddEstateGroup(user);
709 Scene.EstateDataService.StoreEstateSettings(estateSettings); 893 changed[(int)estateSettings.EstateID] = estateSettings;
710 } 894 }
711 } 895 }
712 }
713 896
714 Scene.RegionInfo.EstateSettings.AddEstateGroup(user); 897 thisSettings.AddEstateGroup(user);
715 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 898 changed[thisEstateID] = thisSettings;
716 899
717 TriggerEstateInfoChange(); 900 sendGroups[remote_client] = invoice;
718 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, Scene.RegionInfo.EstateSettings.EstateGroups, Scene.RegionInfo.EstateSettings.EstateID); 901 }
719 }
720 else
721 {
722 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
723 } 902 }
724 }
725 903
726 if ((estateAccessType & 32) != 0) // Group remove 904 if ((estateAccessType & 32) != 0) // Group remove
727 {
728 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
729 { 905 {
730 if ((estateAccessType & 1) != 0) // All estates 906 if (doOtherEstates) // All estates
731 { 907 {
732 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 908 foreach (EstateSettings estateSettings in otherEstates)
733 EstateSettings estateSettings;
734
735 foreach (int estateID in estateIDs)
736 { 909 {
737 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 910 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
738 { 911 continue;
739 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 912 estateSettings.RemoveEstateGroup(user);
740 estateSettings.RemoveEstateGroup(user); 913 changed[(int)estateSettings.EstateID] = estateSettings;
741 Scene.EstateDataService.StoreEstateSettings(estateSettings);
742 }
743 } 914 }
744 } 915 }
745 916
746 Scene.RegionInfo.EstateSettings.RemoveEstateGroup(user); 917 thisSettings.RemoveEstateGroup(user);
747 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 918 changed[thisEstateID] = thisSettings;
748 919
749 TriggerEstateInfoChange(); 920 sendGroups[remote_client] = invoice;
750 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, Scene.RegionInfo.EstateSettings.EstateGroups, Scene.RegionInfo.EstateSettings.EstateID);
751 } 921 }
752 else
753 {
754 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
755 }
756 }
757 922
758 if ((estateAccessType & 64) != 0) // Ban add 923 if ((estateAccessType & 64) != 0) // Ban add
759 {
760 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
761 { 924 {
762 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
763 925
764 bool alreadyInList = false; 926 if(thisSettings.EstateBansCount() >= (int)Constants.EstateAccessLimits.EstateBans)
765
766 for (int i = 0; i < banlistcheck.Length; i++)
767 { 927 {
768 if (user == banlistcheck[i].BannedUserID) 928 if(!sentBansFull)
769 { 929 {
770 alreadyInList = true; 930 sentBansFull = true;
771 break; 931 remote_client.SendAlertMessage("Estate Ban list is full");
772 } 932 }
773
774 } 933 }
775 if (!alreadyInList) 934 else
776 { 935 {
936 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
777 937
778 if ((estateAccessType & 1) != 0) // All estates 938 bool alreadyInList = false;
779 {
780 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner);
781 EstateSettings estateSettings;
782 939
783 foreach (int estateID in estateIDs) 940 for (int i = 0; i < banlistcheck.Length; i++)
941 {
942 if (user == banlistcheck[i].BannedUserID)
943 {
944 alreadyInList = true;
945 break;
946 }
947 }
948 if (!alreadyInList)
949 {
950 if (doOtherEstates) // All estates
784 { 951 {
785 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 952 foreach (EstateSettings estateSettings in otherEstates)
786 { 953 {
954 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
955 continue;
956
957 if(estateSettings.EstateBansCount() >= (int)Constants.EstateAccessLimits.EstateBans)
958 continue;
959
787 EstateBan bitem = new EstateBan(); 960 EstateBan bitem = new EstateBan();
788 961
789 bitem.BannedUserID = user; 962 bitem.BannedUserID = user;
790 bitem.EstateID = (uint)estateID; 963 bitem.EstateID = estateSettings.EstateID;
791 bitem.BannedHostAddress = "0.0.0.0"; 964 bitem.BannedHostAddress = "0.0.0.0";
792 bitem.BannedHostIPMask = "0.0.0.0"; 965 bitem.BannedHostIPMask = "0.0.0.0";
793 966
794 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID);
795 estateSettings.AddBan(bitem); 967 estateSettings.AddBan(bitem);
796 Scene.EstateDataService.StoreEstateSettings(estateSettings); 968 estateSettings.RemoveEstateUser(user);
969 changed[(int)estateSettings.EstateID] = estateSettings;
797 } 970 }
798 } 971 }
799 }
800 972
801 EstateBan item = new EstateBan(); 973 EstateBan item = new EstateBan();
802 974
803 item.BannedUserID = user; 975 item.BannedUserID = user;
804 item.EstateID = Scene.RegionInfo.EstateSettings.EstateID; 976 item.EstateID = Scene.RegionInfo.EstateSettings.EstateID;
805 item.BannedHostAddress = "0.0.0.0"; 977 item.BannedHostAddress = "0.0.0.0";
806 item.BannedHostIPMask = "0.0.0.0"; 978 item.BannedHostIPMask = "0.0.0.0";
807 979
808 Scene.RegionInfo.EstateSettings.AddBan(item); 980 thisSettings.AddBan(item);
809 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 981 thisSettings.RemoveEstateUser(user);
982 changed[thisEstateID] = thisSettings;
810 983
811 TriggerEstateInfoChange(); 984 ScenePresence s = Scene.GetScenePresence(user);
812 985 if (s != null)
813 ScenePresence s = Scene.GetScenePresence(user);
814 if (s != null)
815 {
816 if (!s.IsChildAgent)
817 { 986 {
818 if (!Scene.TeleportClientHome(user, s.ControllingClient)) 987 if (!s.IsChildAgent)
819 { 988 {
820 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); 989 if (!Scene.TeleportClientHome(user, s.ControllingClient))
821 Scene.CloseAgent(s.UUID, false); 990 {
991 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
992 Scene.CloseAgent(s.UUID, false);
993 }
822 } 994 }
823 } 995 }
824 } 996 }
825 997 else
826 } 998 {
827 else 999 remote_client.SendAlertMessage("User is already on the region ban list");
828 { 1000 }
829 remote_client.SendAlertMessage("User is already on the region ban list"); 1001 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
1002 if(needReply)
1003 sendAllowedOrBanList[remote_client] = invoice;
830 } 1004 }
831 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
832 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID);
833 }
834 else
835 {
836 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
837 } 1005 }
838 }
839 1006
840 if ((estateAccessType & 128) != 0) // Ban remove 1007 if ((estateAccessType & 128) != 0) // Ban remove
841 {
842 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
843 { 1008 {
844 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 1009 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
845 1010
@@ -855,107 +1020,93 @@ namespace OpenSim.Region.CoreModules.World.Estate
855 break; 1020 break;
856 } 1021 }
857 } 1022 }
858 1023
859 if (alreadyInList && listitem != null) 1024 if (alreadyInList && listitem != null)
860 { 1025 {
861 if ((estateAccessType & 1) != 0) // All estates 1026 if (doOtherEstates) // All estates
862 { 1027 {
863 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 1028 foreach (EstateSettings estateSettings in otherEstates)
864 EstateSettings estateSettings;
865
866 foreach (int estateID in estateIDs)
867 { 1029 {
868 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 1030 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
869 { 1031 continue;
870 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 1032 estateSettings.RemoveBan(user);
871 estateSettings.RemoveBan(user); 1033 changed[(int)estateSettings.EstateID] = estateSettings;
872 Scene.EstateDataService.StoreEstateSettings(estateSettings);
873 }
874 } 1034 }
875 } 1035 }
876 1036
877 Scene.RegionInfo.EstateSettings.RemoveBan(listitem.BannedUserID); 1037 thisSettings.RemoveBan(listitem.BannedUserID);
878 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 1038 changed[thisEstateID] = thisSettings;
879
880 TriggerEstateInfoChange();
881 } 1039 }
882 else 1040 else
883 { 1041 {
884 remote_client.SendAlertMessage("User is not on the region ban list"); 1042 remote_client.SendAlertMessage("User is not on the region ban list");
885 } 1043 }
886 1044
887 //Scene.RegionInfo.regionBanlist.Add(Manager(user); 1045 if(needReply)
888 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); 1046 sendAllowedOrBanList[remote_client] = invoice;
889 } 1047 }
890 else 1048
1049 // last the ones only for owners of this region
1050 if (!Scene.Permissions.CanIssueEstateCommand(agentID, true))
891 { 1051 {
892 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 1052 remote_client.SendAlertMessage("Method EstateAccess Failed, you don't have permissions");
1053 continue;
893 } 1054 }
894 }
895 1055
896 if ((estateAccessType & 256) != 0) // Manager add 1056 if ((estateAccessType & 256) != 0) // Manager add
897 {
898 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
899 { 1057 {
900 if ((estateAccessType & 1) != 0) // All estates 1058 if(thisSettings.EstateManagersCount() >= (int)Constants.EstateAccessLimits.EstateManagers)
901 { 1059 {
902 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 1060 if(!sentManagersFull)
903 EstateSettings estateSettings; 1061 {
904 1062 sentManagersFull = true;
905 foreach (int estateID in estateIDs) 1063 remote_client.SendAlertMessage("Estate Managers list is full");
1064 }
1065 }
1066 else
1067 {
1068 if (doOtherEstates) // All estates
906 { 1069 {
907 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 1070 foreach (EstateSettings estateSettings in otherEstates)
908 { 1071 {
909 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 1072 if(!isadmin && !estateSettings.IsEstateOwner(agentID)) // redundante check?
1073 continue;
1074 if(estateSettings.EstateManagersCount() >= (int)Constants.EstateAccessLimits.EstateManagers)
1075 continue;
910 estateSettings.AddEstateManager(user); 1076 estateSettings.AddEstateManager(user);
911 Scene.EstateDataService.StoreEstateSettings(estateSettings); 1077 changed[(int)estateSettings.EstateID] = estateSettings;
912 } 1078 }
913 } 1079 }
914 }
915 1080
916 Scene.RegionInfo.EstateSettings.AddEstateManager(user); 1081 thisSettings.AddEstateManager(user);
917 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 1082 changed[thisEstateID] = thisSettings;
918 1083
919 TriggerEstateInfoChange(); 1084 sendManagers[remote_client] = invoice;
920 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, Scene.RegionInfo.EstateSettings.EstateID); 1085 }
921 }
922 else
923 {
924 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
925 } 1086 }
926 }
927 1087
928 if ((estateAccessType & 512) != 0) // Manager remove 1088 if ((estateAccessType & 512) != 0) // Manager remove
929 {
930 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
931 { 1089 {
932 if ((estateAccessType & 1) != 0) // All estates 1090 if (doOtherEstates) // All estates
933 { 1091 {
934 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 1092 foreach (EstateSettings estateSettings in otherEstates)
935 EstateSettings estateSettings;
936
937 foreach (int estateID in estateIDs)
938 { 1093 {
939 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 1094 if(!isadmin && !estateSettings.IsEstateOwner(agentID))
940 { 1095 continue;
941 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 1096
942 estateSettings.RemoveEstateManager(user); 1097 estateSettings.RemoveEstateManager(user);
943 Scene.EstateDataService.StoreEstateSettings(estateSettings); 1098 changed[(int)estateSettings.EstateID] = estateSettings;
944 }
945 } 1099 }
946 } 1100 }
947 1101
948 Scene.RegionInfo.EstateSettings.RemoveEstateManager(user); 1102 thisSettings.RemoveEstateManager(user);
949 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 1103 changed[thisEstateID] = thisSettings;
950 1104
951 TriggerEstateInfoChange(); 1105 sendManagers[remote_client] = invoice;
952 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, Scene.RegionInfo.EstateSettings.EstateID);
953 }
954 else
955 {
956 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
957 } 1106 }
958 } 1107 }
1108 lock(deltareqLock)
1109 runnigDeltaExec = false;
959 } 1110 }
960 1111
961 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 1112 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
@@ -1007,7 +1158,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1007 IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) 1158 IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message)
1008 { 1159 {
1009 IDialogModule dm = Scene.RequestModuleInterface<IDialogModule>(); 1160 IDialogModule dm = Scene.RequestModuleInterface<IDialogModule>();
1010 1161
1011 if (dm != null) 1162 if (dm != null)
1012 dm.SendNotificationToUsersInRegion(senderID, senderName, message); 1163 dm.SendNotificationToUsersInRegion(senderID, senderName, message);
1013 } 1164 }
@@ -1044,13 +1195,20 @@ namespace OpenSim.Region.CoreModules.World.Estate
1044 1195
1045 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) 1196 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey)
1046 { 1197 {
1198 EstateTeleportOneUserHomeRequest evOverride = OnEstateTeleportOneUserHomeRequest;
1199 if(evOverride != null)
1200 {
1201 evOverride(remover_client, invoice, senderID, prey);
1202 return;
1203 }
1204
1047 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) 1205 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false))
1048 return; 1206 return;
1049 1207
1050 if (prey != UUID.Zero) 1208 if (prey != UUID.Zero)
1051 { 1209 {
1052 ScenePresence s = Scene.GetScenePresence(prey); 1210 ScenePresence s = Scene.GetScenePresence(prey);
1053 if (s != null) 1211 if (s != null && !s.IsDeleted && !s.IsInTransit)
1054 { 1212 {
1055 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 1213 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
1056 { 1214 {
@@ -1063,6 +1221,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
1063 1221
1064 private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID) 1222 private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID)
1065 { 1223 {
1224 EstateTeleportAllUsersHomeRequest evOverride = OnEstateTeleportAllUsersHomeRequest;
1225 if(evOverride != null)
1226 {
1227 evOverride(remover_client, invoice, senderID);
1228 return;
1229 }
1230
1066 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) 1231 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false))
1067 return; 1232 return;
1068 1233
@@ -1084,7 +1249,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1084 } 1249 }
1085 }); 1250 });
1086 } 1251 }
1087 1252
1088 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) 1253 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
1089 { 1254 {
1090 lock (this) 1255 lock (this)
@@ -1167,7 +1332,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1167 if (TerrainUploader == null) 1332 if (TerrainUploader == null)
1168 { 1333 {
1169 m_log.DebugFormat( 1334 m_log.DebugFormat(
1170 "[TERRAIN]: Started receiving terrain upload for region {0} from {1}", 1335 "[TERRAIN]: Started receiving terrain upload for region {0} from {1}",
1171 Scene.Name, remote_client.Name); 1336 Scene.Name, remote_client.Name);
1172 1337
1173 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName); 1338 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
@@ -1187,25 +1352,43 @@ namespace OpenSim.Region.CoreModules.World.Estate
1187 { 1352 {
1188 // Save terrain here 1353 // Save terrain here
1189 ITerrainModule terr = Scene.RequestModuleInterface<ITerrainModule>(); 1354 ITerrainModule terr = Scene.RequestModuleInterface<ITerrainModule>();
1190 1355
1191 if (terr != null) 1356 if (terr != null)
1192 { 1357 {
1358 string file = Util.cacheDir() + "/terrain_";
1359 try
1360 {
1361 file = file + Uri.EscapeDataString(Scene.Name) + ".raw";
1362 }
1363 catch (Exception)
1364 {
1365 file = file + ".raw";
1366 }
1193// m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + Scene.RegionInfo.RegionName); 1367// m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + Scene.RegionInfo.RegionName);
1194 if (File.Exists(Util.dataDir() + "/terrain.raw")) 1368 if (File.Exists(file))
1369 {
1370 File.Delete(file);
1371 }
1372 terr.SaveToFile(file);
1373
1374 byte[] bdata;
1375 using(FileStream input = new FileStream(file, FileMode.Open))
1376 {
1377 bdata = new byte[input.Length];
1378 input.Read(bdata, 0, (int)input.Length);
1379 }
1380 if(bdata == null || bdata.Length == 0)
1195 { 1381 {
1196 File.Delete(Util.dataDir() + "/terrain.raw"); 1382 remote_client.SendAlertMessage("Terrain error");
1383 return;
1197 } 1384 }
1198 terr.SaveToFile(Util.dataDir() + "/terrain.raw");
1199 1385
1200 FileStream input = new FileStream(Util.dataDir() + "/terrain.raw", FileMode.Open);
1201 byte[] bdata = new byte[input.Length];
1202 input.Read(bdata, 0, (int)input.Length);
1203 remote_client.SendAlertMessage("Terrain file written, starting download..."); 1386 remote_client.SendAlertMessage("Terrain file written, starting download...");
1204 Scene.XferManager.AddNewFile("terrain.raw", bdata); 1387 string xfername = (UUID.Random()).ToString();
1388 Scene.XferManager.AddNewFile(xfername, bdata);
1205 1389
1206 m_log.DebugFormat("[CLIENT]: Sending terrain for region {0} to {1}", Scene.Name, remote_client.Name); 1390 m_log.DebugFormat("[CLIENT]: Sending terrain for region {0} to {1}", Scene.Name, remote_client.Name);
1207 1391 remote_client.SendInitiateDownload(xfername, clientFileName);
1208 remote_client.SendInitiateDownload("terrain.raw", clientFileName);
1209 } 1392 }
1210 } 1393 }
1211 1394
@@ -1319,7 +1502,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
1319 1502
1320 public void sendRegionInfoPacketToAll() 1503 public void sendRegionInfoPacketToAll()
1321 { 1504 {
1322 Scene.ForEachRootClient(delegate(IClientAPI client) 1505// Scene.ForEachRootClient(delegate(IClientAPI client)
1506 Scene.ForEachClient(delegate(IClientAPI client)
1323 { 1507 {
1324 HandleRegionInfoRequest(client); 1508 HandleRegionInfoRequest(client);
1325 }); 1509 });
@@ -1443,7 +1627,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1443 Scene.RegionInfo.EstateSettings.FixedSun, 1627 Scene.RegionInfo.EstateSettings.FixedSun,
1444 (float)Scene.RegionInfo.EstateSettings.SunPosition); 1628 (float)Scene.RegionInfo.EstateSettings.SunPosition);
1445 1629
1446 sendRegionInfoPacketToAll(); 1630// sendRegionInfoPacketToAll(); already done by setRegionTerrainSettings
1447 } 1631 }
1448 1632
1449 1633
@@ -1477,7 +1661,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
1477 sendRegionHandshake(client); 1661 sendRegionHandshake(client);
1478 } 1662 }
1479 1663
1480 private uint GetEstateFlags() 1664
1665 public uint GetEstateFlags()
1481 { 1666 {
1482 RegionFlags flags = RegionFlags.None; 1667 RegionFlags flags = RegionFlags.None;
1483 1668
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
index 4bb3799..f3c8aa8 100644
--- a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
@@ -45,12 +45,14 @@ using Mono.Addins;
45namespace OpenSim.Region.CoreModules.World.Estate 45namespace OpenSim.Region.CoreModules.World.Estate
46{ 46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")]
48 public class XEstateModule : ISharedRegionModule 48 public class EstateModule : ISharedRegionModule
49 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 protected List<Scene> m_Scenes = new List<Scene>(); 52 protected List<Scene> m_Scenes = new List<Scene>();
53 protected bool m_InInfoUpdate = false; 53 protected bool m_InInfoUpdate = false;
54 private string token = "7db8eh2gvgg45jj";
55 protected bool m_enabled = false;
54 56
55 public bool InInfoUpdate 57 public bool InInfoUpdate
56 { 58 {
@@ -67,19 +69,33 @@ namespace OpenSim.Region.CoreModules.World.Estate
67 69
68 public void Initialise(IConfigSource config) 70 public void Initialise(IConfigSource config)
69 { 71 {
70 int port = 0; 72 uint port = MainServer.Instance.Port;
71 73
72 IConfig estateConfig = config.Configs["Estate"]; 74 IConfig estateConfig = config.Configs["Estates"];
73 if (estateConfig != null) 75 if (estateConfig != null)
74 { 76 {
75 port = estateConfig.GetInt("Port", 0); 77 if (estateConfig.GetString("EstateCommunicationsHandler", Name) == Name)
78 m_enabled = true;
79 else
80 return;
81
82 port = (uint)estateConfig.GetInt("Port", 0);
83 // this will need to came from somewhere else
84 token = estateConfig.GetString("Token", token);
85 }
86 else
87 {
88 m_enabled = true;
76 } 89 }
77 90
78 m_EstateConnector = new EstateConnector(this); 91 m_EstateConnector = new EstateConnector(this, token, port);
92
93 if(port == 0)
94 port = MainServer.Instance.Port;
79 95
80 // Instantiate the request handler 96 // Instantiate the request handler
81 IHttpServer server = MainServer.GetHttpServer((uint)port); 97 IHttpServer server = MainServer.GetHttpServer(port);
82 server.AddStreamHandler(new EstateRequestHandler(this)); 98 server.AddStreamHandler(new EstateRequestHandler(this, token));
83 } 99 }
84 100
85 public void PostInitialise() 101 public void PostInitialise()
@@ -92,24 +108,31 @@ namespace OpenSim.Region.CoreModules.World.Estate
92 108
93 public void AddRegion(Scene scene) 109 public void AddRegion(Scene scene)
94 { 110 {
111 if (!m_enabled)
112 return;
113
95 lock (m_Scenes) 114 lock (m_Scenes)
96 m_Scenes.Add(scene); 115 m_Scenes.Add(scene);
97
98 scene.EventManager.OnNewClient += OnNewClient;
99 } 116 }
100 117
101 public void RegionLoaded(Scene scene) 118 public void RegionLoaded(Scene scene)
102 { 119 {
120 if (!m_enabled)
121 return;
122
103 IEstateModule em = scene.RequestModuleInterface<IEstateModule>(); 123 IEstateModule em = scene.RequestModuleInterface<IEstateModule>();
104 124
105 em.OnRegionInfoChange += OnRegionInfoChange; 125 em.OnRegionInfoChange += OnRegionInfoChange;
106 em.OnEstateInfoChange += OnEstateInfoChange; 126 em.OnEstateInfoChange += OnEstateInfoChange;
107 em.OnEstateMessage += OnEstateMessage; 127 em.OnEstateMessage += OnEstateMessage;
128 em.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest;
129 em.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest;
108 } 130 }
109 131
110 public void RemoveRegion(Scene scene) 132 public void RemoveRegion(Scene scene)
111 { 133 {
112 scene.EventManager.OnNewClient -= OnNewClient; 134 if (!m_enabled)
135 return;
113 136
114 lock (m_Scenes) 137 lock (m_Scenes)
115 m_Scenes.Remove(scene); 138 m_Scenes.Remove(scene);
@@ -181,13 +204,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
181 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message); 204 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message);
182 } 205 }
183 206
184 private void OnNewClient(IClientAPI client)
185 {
186 client.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest;
187 client.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest;
188
189 }
190
191 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey) 207 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey)
192 { 208 {
193 if (prey == UUID.Zero) 209 if (prey == UUID.Zero)
@@ -205,16 +221,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
205 221
206 foreach (Scene s in Scenes) 222 foreach (Scene s in Scenes)
207 { 223 {
208 if (s == scene)
209 continue; // Already handles by estate module
210 if (s.RegionInfo.EstateSettings.EstateID != estateID) 224 if (s.RegionInfo.EstateSettings.EstateID != estateID)
211 continue; 225 continue;
212 226
213 ScenePresence p = scene.GetScenePresence(prey); 227 ScenePresence p = scene.GetScenePresence(prey);
214 if (p != null && !p.IsChildAgent) 228 if (p != null && !p.IsChildAgent )
215 { 229 {
216 p.ControllingClient.SendTeleportStart(16); 230 if(!p.IsDeleted && !p.IsInTransit)
217 scene.TeleportClientHome(prey, p.ControllingClient); 231 {
232 p.ControllingClient.SendTeleportStart(16);
233 scene.TeleportClientHome(prey, p.ControllingClient);
234 }
235 return;
218 } 236 }
219 } 237 }
220 238
@@ -235,8 +253,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
235 253
236 foreach (Scene s in Scenes) 254 foreach (Scene s in Scenes)
237 { 255 {
238 if (s == scene)
239 continue; // Already handles by estate module
240 if (s.RegionInfo.EstateSettings.EstateID != estateID) 256 if (s.RegionInfo.EstateSettings.EstateID != estateID)
241 continue; 257 continue;
242 258
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs
index ec5af2b..5eda8ab 100644
--- a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs
@@ -46,24 +46,27 @@ namespace OpenSim.Region.CoreModules.World.Estate
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 protected XEstateModule m_EstateModule; 49 protected EstateModule m_EstateModule;
50 protected Object m_RequestLock = new Object(); 50 protected Object m_RequestLock = new Object();
51 private string token;
51 52
52 public EstateRequestHandler(XEstateModule fmodule) 53 public EstateRequestHandler(EstateModule fmodule, string _token)
53 : base("POST", "/estate") 54 : base("POST", "/estate")
54 { 55 {
55 m_EstateModule = fmodule; 56 m_EstateModule = fmodule;
57 token = _token;
56 } 58 }
57 59
58 protected override byte[] ProcessRequest(string path, Stream requestData, 60 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 61 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 { 62 {
61 StreamReader sr = new StreamReader(requestData); 63 string body;
62 string body = sr.ReadToEnd(); 64 using(StreamReader sr = new StreamReader(requestData))
63 sr.Close(); 65 body = sr.ReadToEnd();
66
64 body = body.Trim(); 67 body = body.Trim();
65 68
66 m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body); 69 // m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body);
67 70
68 try 71 try
69 { 72 {
@@ -75,6 +78,15 @@ namespace OpenSim.Region.CoreModules.World.Estate
75 if (!request.ContainsKey("METHOD")) 78 if (!request.ContainsKey("METHOD"))
76 return FailureResult(); 79 return FailureResult();
77 80
81 if (!request.ContainsKey("TOKEN"))
82 return FailureResult();
83
84 string reqToken = request["TOKEN"].ToString();
85 request.Remove("TOKEN");
86
87 if(token != reqToken)
88 return FailureResult();
89
78 string method = request["METHOD"].ToString(); 90 string method = request["METHOD"].ToString();
79 request.Remove("METHOD"); 91 request.Remove("METHOD");
80 92
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
index 70c6028..22480e6 100644
--- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
@@ -53,7 +53,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
53namespace OpenSim.Region.CoreModules.World.Land 53namespace OpenSim.Region.CoreModules.World.Land
54{ 54{
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultDwellModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultDwellModule")]
56 public class DefaultDwellModule : IDwellModule, INonSharedRegionModule 56 public class DefaultDwellModule : INonSharedRegionModule, IDwellModule
57 { 57 {
58 private Scene m_scene; 58 private Scene m_scene;
59 private IConfigSource m_Config; 59 private IConfigSource m_Config;
@@ -88,16 +88,21 @@ namespace OpenSim.Region.CoreModules.World.Land
88 return; 88 return;
89 89
90 m_scene = scene; 90 m_scene = scene;
91 91 m_scene.RegisterModuleInterface<IDwellModule>(this);
92 m_scene.EventManager.OnNewClient += OnNewClient;
93 } 92 }
94 93
95 public void RegionLoaded(Scene scene) 94 public void RegionLoaded(Scene scene)
96 { 95 {
96 if (!m_Enabled)
97 return;
98 m_scene.EventManager.OnNewClient += OnNewClient;
97 } 99 }
98 100
99 public void RemoveRegion(Scene scene) 101 public void RemoveRegion(Scene scene)
100 { 102 {
103 if (!m_Enabled)
104 return;
105 m_scene.EventManager.OnNewClient -= OnNewClient;
101 } 106 }
102 107
103 public void Close() 108 public void Close()
@@ -115,12 +120,26 @@ namespace OpenSim.Region.CoreModules.World.Land
115 if (parcel == null) 120 if (parcel == null)
116 return; 121 return;
117 122
118 client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); 123 LandData land = parcel.LandData;
124 if(land!= null)
125 client.SendParcelDwellReply(localID, land.GlobalID, land.Dwell);
119 } 126 }
120 127
128
121 public int GetDwell(UUID parcelID) 129 public int GetDwell(UUID parcelID)
122 { 130 {
131 ILandObject parcel = m_scene.LandChannel.GetLandObject(parcelID);
132 if (parcel != null && parcel.LandData != null)
133 return (int)(parcel.LandData.Dwell);
134 return 0;
135 }
136
137 public int GetDwell(LandData land)
138 {
139 if (land != null)
140 return (int)(land.Dwell);
123 return 0; 141 return 0;
124 } 142 }
143
125 } 144 }
126} 145}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 73c592d..5ff063b 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -37,26 +37,37 @@ namespace OpenSim.Region.CoreModules.World.Land
37 { 37 {
38 #region Constants 38 #region Constants
39 39
40 public const float BAN_LINE_SAFETY_HEIGHT = 100;
40 //Land types set with flags in ParcelOverlay. 41 //Land types set with flags in ParcelOverlay.
41 //Only one of these can be used. 42 //Only one of these can be used.
42 public const float BAN_LINE_SAFETY_HIEGHT = 100; 43
43 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000
44 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000
45 44
46 //RequestResults (I think these are right, they seem to work): 45 //RequestResults (I think these are right, they seem to work):
47 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land 46 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
48 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land 47 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
49 48
50 //ParcelSelectObjects 49 //ParcelSelectObjects
50 public const int LAND_SELECT_OBJECTS_OWNER = 2;
51 public const int LAND_SELECT_OBJECTS_GROUP = 4; 51 public const int LAND_SELECT_OBJECTS_GROUP = 4;
52 public const int LAND_SELECT_OBJECTS_OTHER = 8; 52 public const int LAND_SELECT_OBJECTS_OTHER = 8;
53 public const int LAND_SELECT_OBJECTS_OWNER = 2; 53
54 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101 54
55 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100 55 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
56 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010 56 // types 1 to 7 are exclusive
57 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001 57 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
58 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011 59 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
59 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000 60 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
61 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
62 public const byte LAND_TYPE_unused6 = 6;
63 public const byte LAND_TYPE_unused7 = 7;
64 // next are flags
65 public const byte LAND_FLAG_unused8 = 0x08; // this may become excluside in future
66 public const byte LAND_FLAG_HIDEAVATARS = 0x10;
67 public const byte LAND_FLAG_LOCALSOUND = 0x20;
68 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 0x40; //Equals 01000000
69 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 0x80; //Equals 10000000
70
60 71
61 //These are other constants. Yay! 72 //These are other constants. Yay!
62 public const int START_LAND_LOCAL_ID = 1; 73 public const int START_LAND_LOCAL_ID = 1;
@@ -64,7 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Land
64 #endregion 75 #endregion
65 76
66 private readonly Scene m_scene; 77 private readonly Scene m_scene;
67 private readonly LandManagementModule m_landManagementModule; 78 private readonly LandManagementModule m_landManagementModule;
68 79
69 public LandChannel(Scene scene, LandManagementModule landManagementMod) 80 public LandChannel(Scene scene, LandManagementModule landManagementMod)
70 { 81 {
@@ -80,7 +91,7 @@ namespace OpenSim.Region.CoreModules.World.Land
80 { 91 {
81 return m_landManagementModule.GetLandObject(x_float, y_float); 92 return m_landManagementModule.GetLandObject(x_float, y_float);
82 } 93 }
83 94
84 ILandObject obj = new LandObject(UUID.Zero, false, m_scene); 95 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
85 obj.LandData.Name = "NO LAND"; 96 obj.LandData.Name = "NO LAND";
86 return obj; 97 return obj;
@@ -95,6 +106,15 @@ namespace OpenSim.Region.CoreModules.World.Land
95 return null; 106 return null;
96 } 107 }
97 108
109 public ILandObject GetLandObject(UUID GlobalID)
110 {
111 if (m_landManagementModule != null)
112 {
113 return m_landManagementModule.GetLandObject(GlobalID);
114 }
115 return null;
116 }
117
98 public ILandObject GetLandObject(Vector3 position) 118 public ILandObject GetLandObject(Vector3 position)
99 { 119 {
100 return GetLandObject(position.X, position.Y); 120 return GetLandObject(position.X, position.Y);
@@ -106,7 +126,7 @@ namespace OpenSim.Region.CoreModules.World.Land
106 { 126 {
107 return m_landManagementModule.GetLandObject(x, y); 127 return m_landManagementModule.GetLandObject(x, y);
108 } 128 }
109 129
110 ILandObject obj = new LandObject(UUID.Zero, false, m_scene); 130 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
111 obj.LandData.Name = "NO LAND"; 131 obj.LandData.Name = "NO LAND";
112 return obj; 132 return obj;
@@ -121,7 +141,7 @@ namespace OpenSim.Region.CoreModules.World.Land
121 141
122 return new List<ILandObject>(); 142 return new List<ILandObject>();
123 } 143 }
124 144
125 public void Clear(bool setupDefaultParcel) 145 public void Clear(bool setupDefaultParcel)
126 { 146 {
127 if (m_landManagementModule != null) 147 if (m_landManagementModule != null)
@@ -156,6 +176,14 @@ namespace OpenSim.Region.CoreModules.World.Land
156 } 176 }
157 } 177 }
158 178
179 public void SendParcelsOverlay(IClientAPI client)
180 {
181 if (m_landManagementModule != null)
182 {
183 m_landManagementModule.SendParcelOverlay(client);
184 }
185 }
186
159 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) 187 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
160 { 188 {
161 if (m_landManagementModule != null) 189 if (m_landManagementModule != null)
@@ -171,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.Land
171 m_landManagementModule.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id); 199 m_landManagementModule.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
172 } 200 }
173 } 201 }
174 202
175 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 203 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
176 { 204 {
177 if (m_landManagementModule != null) 205 if (m_landManagementModule != null)
@@ -203,7 +231,13 @@ namespace OpenSim.Region.CoreModules.World.Land
203 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); 231 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
204 } 232 }
205 } 233 }
206 234 public void sendClientInitialLandInfo(IClientAPI remoteClient)
235 {
236 if (m_landManagementModule != null)
237 {
238 m_landManagementModule.sendClientInitialLandInfo(remoteClient);
239 }
240 }
207 #endregion 241 #endregion
208 } 242 }
209} 243}
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;
41using OpenSim.Framework.Capabilities; 41using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers; 43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Monitoring;
44using OpenSim.Framework.Servers.HttpServer; 45using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 47using OpenSim.Region.Framework.Scenes;
@@ -52,7 +53,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52namespace OpenSim.Region.CoreModules.World.Land 53namespace 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);
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index a0c1b9d..ce67fcc 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -50,15 +50,22 @@ namespace OpenSim.Region.CoreModules.World.Land
50 private readonly int landUnit = 4; 50 private readonly int landUnit = 4;
51 51
52 private int m_lastSeqId = 0; 52 private int m_lastSeqId = 0;
53 53 private int m_expiryCounter = 0;
54
54 protected Scene m_scene; 55 protected Scene m_scene;
55 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
56 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>(); 57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
57 58
58 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>(); 59 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
59 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds 60 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
61 IDwellModule m_dwellModule;
60 62
61 public bool[,] LandBitmap { get; set; } 63 private bool[,] m_landBitmap;
64 public bool[,] LandBitmap
65 {
66 get { return m_landBitmap; }
67 set { m_landBitmap = value; }
68 }
62 69
63 #endregion 70 #endregion
64 71
@@ -69,7 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Land
69 return free; 76 return free;
70 } 77 }
71 78
72 public LandData LandData { get; set; } 79 protected LandData m_landData;
80 public LandData LandData
81 {
82 get { return m_landData; }
83
84 set { m_landData = value; }
85 }
73 86
74 public IPrimCounts PrimCounts { get; set; } 87 public IPrimCounts PrimCounts { get; set; }
75 88
@@ -78,77 +91,230 @@ namespace OpenSim.Region.CoreModules.World.Land
78 get { return m_scene.RegionInfo.RegionID; } 91 get { return m_scene.RegionInfo.RegionID; }
79 } 92 }
80 93
81 public Vector3 StartPoint 94 private Vector2 m_startPoint = Vector2.Zero;
95 private Vector2 m_endPoint = Vector2.Zero;
96 private Vector2 m_centerPoint = Vector2.Zero;
97 private Vector2 m_AABBmin = Vector2.Zero;
98 private Vector2 m_AABBmax = Vector2.Zero;
99
100 public Vector2 StartPoint
82 { 101 {
83 get 102 get
84 { 103 {
85 for (int y = 0; y < LandBitmap.GetLength(1); y++) 104 return m_startPoint;
86 { 105 }
87 for (int x = 0; x < LandBitmap.GetLength(0); x++) 106 }
88 {
89 if (LandBitmap[x, y])
90 return new Vector3(x * landUnit, y * landUnit, 0);
91 }
92 }
93 107
94 m_log.ErrorFormat("{0} StartPoint. No start point found. bitmapSize=<{1},{2}>", 108 public Vector2 EndPoint
95 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 109 {
96 return new Vector3(-1, -1, -1); 110 get
111 {
112 return m_endPoint;
97 } 113 }
98 } 114 }
99 115
100 public Vector3 EndPoint 116 //estimate a center point of a parcel
117 public Vector2 CenterPoint
101 { 118 {
102 get 119 get
103 { 120 {
104 for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--) 121 return m_centerPoint;
122 }
123 }
124
125 public Vector2? GetNearestPoint(Vector3 pos)
126 {
127 Vector3 direction = new Vector3(m_centerPoint.X - pos.X, m_centerPoint.Y - pos.Y, 0f );
128 return GetNearestPointAlongDirection(pos, direction);
129 }
130
131 public Vector2? GetNearestPointAlongDirection(Vector3 pos, Vector3 pdirection)
132 {
133 Vector2 testpos;
134 Vector2 direction;
135
136 testpos.X = pos.X / landUnit;
137 testpos.Y = pos.Y / landUnit;
138
139 if(LandBitmap[(int)testpos.X, (int)testpos.Y])
140 return new Vector2(pos.X, pos.Y); // we are already here
141
142 direction.X = pdirection.X;
143 direction.Y = pdirection.Y;
144
145 if(direction.X == 0f && direction.Y == 0f)
146 return null; // we can't look anywhere
147
148 direction.Normalize();
149
150 int minx = (int)(m_AABBmin.X / landUnit);
151 int maxx = (int)(m_AABBmax.X / landUnit);
152
153 // check against AABB
154 if(direction.X > 0f)
155 {
156 if(testpos.X >= maxx)
157 return null; // will never get there
158 if(testpos.X < minx)
159 testpos.X = minx;
160 }
161 else if(direction.X < 0f)
162 {
163 if(testpos.X < minx)
164 return null; // will never get there
165 if(testpos.X >= maxx)
166 testpos.X = maxx - 1;
167 }
168 else
169 {
170 if(testpos.X < minx)
171 return null; // will never get there
172 else if(testpos.X >= maxx)
173 return null; // will never get there
174 }
175
176 int miny = (int)(m_AABBmin.Y / landUnit);
177 int maxy = (int)(m_AABBmax.Y / landUnit);
178
179 if(direction.Y > 0f)
180 {
181 if(testpos.Y >= maxy)
182 return null; // will never get there
183 if(testpos.Y < miny)
184 testpos.Y = miny;
185 }
186 else if(direction.Y < 0f)
187 {
188 if(testpos.Y < miny)
189 return null; // will never get there
190 if(testpos.Y >= maxy)
191 testpos.Y = maxy - 1;
192 }
193 else
194 {
195 if(testpos.Y < miny)
196 return null; // will never get there
197 else if(testpos.Y >= maxy)
198 return null; // will never get there
199 }
200
201 while(!LandBitmap[(int)testpos.X, (int)testpos.Y])
202 {
203 testpos += direction;
204
205 if(testpos.X < minx)
206 return null;
207 if (testpos.X >= maxx)
208 return null;
209 if(testpos.Y < miny)
210 return null;
211 if (testpos.Y >= maxy)
212 return null;
213 }
214
215 testpos *= landUnit;
216 float ftmp;
217
218 if(Math.Abs(direction.X) > Math.Abs(direction.Y))
219 {
220 if(direction.X < 0)
221 testpos.X += landUnit - 0.5f;
222 else
223 testpos.X += 0.5f;
224 ftmp = testpos.X - pos.X;
225 ftmp /= direction.X;
226 ftmp = Math.Abs(ftmp);
227 ftmp *= direction.Y;
228 ftmp += pos.Y;
229
230 if(ftmp < testpos.Y + .5f)
231 ftmp = testpos.Y + .5f;
232 else
105 { 233 {
106 for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--) 234 testpos.Y += landUnit - 0.5f;
107 { 235 if(ftmp > testpos.Y)
108 if (LandBitmap[x, y]) 236 ftmp = testpos.Y;
109 {
110 return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
111 }
112 }
113 } 237 }
114 238 testpos.Y = ftmp;
115 m_log.ErrorFormat("{0} EndPoint. No end point found. bitmapSize=<{1},{2}>", 239 }
116 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 240 else
117 return new Vector3(-1, -1, -1); 241 {
242 if(direction.Y < 0)
243 testpos.Y += landUnit - 0.5f;
244 else
245 testpos.Y += 0.5f;
246 ftmp = testpos.Y - pos.Y;
247 ftmp /= direction.Y;
248 ftmp = Math.Abs(ftmp);
249 ftmp *= direction.X;
250 ftmp += pos.X;
251
252 if(ftmp < testpos.X + .5f)
253 ftmp = testpos.X + .5f;
254 else
255 {
256 testpos.X += landUnit - 0.5f;
257 if(ftmp > testpos.X)
258 ftmp = testpos.X;
259 }
260 testpos.X = ftmp;
118 } 261 }
262 return testpos;
119 } 263 }
120 264
265
121 #region Constructors 266 #region Constructors
122 267
123 public LandObject(LandData landData, Scene scene) 268 public LandObject(LandData landData, Scene scene)
124 { 269 {
125 LandData = landData.Copy(); 270 LandData = landData.Copy();
126 m_scene = scene; 271 m_scene = scene;
272 m_scene.EventManager.OnFrame += OnFrame;
273 m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
127 } 274 }
128 275
129 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 276 public LandObject(UUID owner_id, bool is_group_owned, Scene scene, LandData data = null)
130 { 277 {
131 m_scene = scene; 278 m_scene = scene;
132 if (m_scene == null) 279 if (m_scene == null)
133 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit]; 280 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
134 else 281 else
282 {
135 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 283 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
284 m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
285 }
286
287 if(data == null)
288 LandData = new LandData();
289 else
290 LandData = data;
136 291
137 LandData = new LandData();
138 LandData.OwnerID = owner_id; 292 LandData.OwnerID = owner_id;
139 if (is_group_owned) 293 if (is_group_owned)
140 LandData.GroupID = owner_id; 294 LandData.GroupID = owner_id;
141 else 295
142 LandData.GroupID = UUID.Zero;
143 LandData.IsGroupOwned = is_group_owned; 296 LandData.IsGroupOwned = is_group_owned;
297
298 if(m_dwellModule == null)
299 LandData.Dwell = 0;
300
301 m_scene.EventManager.OnFrame += OnFrame;
302 }
303
304 public void Clear()
305 {
306 if(m_scene != null)
307 m_scene.EventManager.OnFrame -= OnFrame;
308 LandData = null;
144 } 309 }
145 310
311
146 #endregion 312 #endregion
147 313
148 #region Member Functions 314 #region Member Functions
149 315
150 #region General Functions 316 #region General Functions
151 317
152 /// <summary> 318 /// <summary>
153 /// Checks to see if this land object contains a point 319 /// Checks to see if this land object contains a point
154 /// </summary> 320 /// </summary>
@@ -195,14 +361,22 @@ namespace OpenSim.Region.CoreModules.World.Land
195 else 361 else
196 { 362 {
197 // Normal Calculations 363 // Normal Calculations
198 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 364 int parcelMax = (int)(
199 * (float)m_scene.RegionInfo.ObjectCapacity 365 (double)LandData.Area
200 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 366 * (double)m_scene.RegionInfo.ObjectCapacity
201 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 367 * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
368 / (double)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
369 + 0.5 );
370
371 if(parcelMax > m_scene.RegionInfo.ObjectCapacity)
372 parcelMax = m_scene.RegionInfo.ObjectCapacity;
373
374 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
202 return parcelMax; 375 return parcelMax;
203 } 376 }
204 } 377 }
205 378
379 // the total prims a parcel owner can have on a region
206 public int GetSimulatorMaxPrimCount() 380 public int GetSimulatorMaxPrimCount()
207 { 381 {
208 if (overrideSimulatorMaxPrimCount != null) 382 if (overrideSimulatorMaxPrimCount != null)
@@ -212,18 +386,34 @@ namespace OpenSim.Region.CoreModules.World.Land
212 else 386 else
213 { 387 {
214 //Normal Calculations 388 //Normal Calculations
215 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 389 int simMax = (int)( (double)LandData.SimwideArea
216 * (float)m_scene.RegionInfo.ObjectCapacity); 390 * (double)m_scene.RegionInfo.ObjectCapacity
391 * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
392 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
393 +0.5 );
394 // sanity check
395 if(simMax > m_scene.RegionInfo.ObjectCapacity)
396 simMax = m_scene.RegionInfo.ObjectCapacity;
397 //m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}, SimWidePrims {3}",
398 // LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax, LandData.SimwidePrims);
217 return simMax; 399 return simMax;
218 } 400 }
219 } 401 }
220 402
221 #endregion 403 #endregion
222 404
223 #region Packet Request Handling 405 #region Packet Request Handling
224 406
225 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 407 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
226 { 408 {
409 if(m_scene.RegionInfo.RegionSettings.AllowDamage)
410 remote_client.SceneAgent.Invulnerable = false;
411 else
412 remote_client.SceneAgent.Invulnerable = (m_landData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
413
414 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
415 return;
416
227 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 417 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
228 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 418 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
229 uint regionFlags = (uint)(RegionFlags.PublicAllowed 419 uint regionFlags = (uint)(RegionFlags.PublicAllowed
@@ -252,10 +442,11 @@ namespace OpenSim.Region.CoreModules.World.Land
252 GetSimulatorMaxPrimCount(), regionFlags); 442 GetSimulatorMaxPrimCount(), regionFlags);
253 } 443 }
254 444
255 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) 445 public bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
256 { 446 {
257 //Needs later group support 447 //Needs later group support
258 bool snap_selection = false; 448 snap_selection = false;
449 needOverlay = false;
259 LandData newData = LandData.Copy(); 450 LandData newData = LandData.Copy();
260 451
261 uint allowedDelta = 0; 452 uint allowedDelta = 0;
@@ -264,7 +455,7 @@ namespace OpenSim.Region.CoreModules.World.Land
264 // ParcelFlags.ForSaleObjects 455 // ParcelFlags.ForSaleObjects
265 // ParcelFlags.LindenHome 456 // ParcelFlags.LindenHome
266 457
267 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 458 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, false))
268 { 459 {
269 allowedDelta |= (uint)(ParcelFlags.AllowLandmark | 460 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
270 ParcelFlags.AllowTerraform | 461 ParcelFlags.AllowTerraform |
@@ -277,9 +468,12 @@ namespace OpenSim.Region.CoreModules.World.Land
277 ParcelFlags.AllowAPrimitiveEntry | 468 ParcelFlags.AllowAPrimitiveEntry |
278 ParcelFlags.AllowGroupObjectEntry | 469 ParcelFlags.AllowGroupObjectEntry |
279 ParcelFlags.AllowFly); 470 ParcelFlags.AllowFly);
471 newData.SeeAVs = args.SeeAVs;
472 newData.AnyAVSounds = args.AnyAVSounds;
473 newData.GroupAVSounds = args.GroupAVSounds;
280 } 474 }
281 475
282 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale)) 476 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true))
283 { 477 {
284 if (args.AuthBuyerID != newData.AuthBuyerID || 478 if (args.AuthBuyerID != newData.AuthBuyerID ||
285 args.SalePrice != newData.SalePrice) 479 args.SalePrice != newData.SalePrice)
@@ -302,30 +496,30 @@ namespace OpenSim.Region.CoreModules.World.Land
302 allowedDelta |= (uint)ParcelFlags.ForSale; 496 allowedDelta |= (uint)ParcelFlags.ForSale;
303 } 497 }
304 498
305 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces)) 499 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces, false))
306 { 500 {
307 newData.Category = args.Category; 501 newData.Category = args.Category;
308 502
309 allowedDelta |= (uint)(ParcelFlags.ShowDirectory | 503 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
310 ParcelFlags.AllowPublish | 504 ParcelFlags.AllowPublish |
311 ParcelFlags.MaturePublish); 505 ParcelFlags.MaturePublish) | (uint)(1 << 23);
312 } 506 }
313 507
314 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity)) 508 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity, false))
315 { 509 {
316 newData.Description = args.Desc; 510 newData.Description = args.Desc;
317 newData.Name = args.Name; 511 newData.Name = args.Name;
318 newData.SnapshotID = args.SnapshotID; 512 newData.SnapshotID = args.SnapshotID;
319 } 513 }
320 514
321 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint)) 515 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint, false))
322 { 516 {
323 newData.LandingType = args.LandingType; 517 newData.LandingType = args.LandingType;
324 newData.UserLocation = args.UserLocation; 518 newData.UserLocation = args.UserLocation;
325 newData.UserLookAt = args.UserLookAt; 519 newData.UserLookAt = args.UserLookAt;
326 } 520 }
327 521
328 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia)) 522 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia, false))
329 { 523 {
330 newData.MediaAutoScale = args.MediaAutoScale; 524 newData.MediaAutoScale = args.MediaAutoScale;
331 newData.MediaID = args.MediaID; 525 newData.MediaID = args.MediaID;
@@ -346,7 +540,8 @@ namespace OpenSim.Region.CoreModules.World.Land
346 ParcelFlags.UseEstateVoiceChan); 540 ParcelFlags.UseEstateVoiceChan);
347 } 541 }
348 542
349 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses)) 543 // don't allow passes on group owned until we can give money to groups
544 if (!newData.IsGroupOwned && m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
350 { 545 {
351 newData.PassHours = args.PassHours; 546 newData.PassHours = args.PassHours;
352 newData.PassPrice = args.PassPrice; 547 newData.PassPrice = args.PassPrice;
@@ -354,13 +549,13 @@ namespace OpenSim.Region.CoreModules.World.Land
354 allowedDelta |= (uint)ParcelFlags.UsePassList; 549 allowedDelta |= (uint)ParcelFlags.UsePassList;
355 } 550 }
356 551
357 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed)) 552 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed, false))
358 { 553 {
359 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup | 554 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
360 ParcelFlags.UseAccessList); 555 ParcelFlags.UseAccessList);
361 } 556 }
362 557
363 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned)) 558 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned, false))
364 { 559 {
365 allowedDelta |= (uint)(ParcelFlags.UseBanList | 560 allowedDelta |= (uint)(ParcelFlags.UseBanList |
366 ParcelFlags.DenyAnonymous | 561 ParcelFlags.DenyAnonymous |
@@ -372,9 +567,16 @@ namespace OpenSim.Region.CoreModules.World.Land
372 uint preserve = LandData.Flags & ~allowedDelta; 567 uint preserve = LandData.Flags & ~allowedDelta;
373 newData.Flags = preserve | (args.ParcelFlags & allowedDelta); 568 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
374 569
570 uint curdelta = LandData.Flags ^ newData.Flags;
571 curdelta &= (uint)(ParcelFlags.SoundLocal);
572
573 if(curdelta != 0 || newData.SeeAVs != LandData.SeeAVs)
574 needOverlay = true;
575
375 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 576 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
376 SendLandUpdateToAvatarsOverMe(snap_selection); 577 return true;
377 } 578 }
579 return false;
378 } 580 }
379 581
380 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 582 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -395,7 +597,7 @@ namespace OpenSim.Region.CoreModules.World.Land
395 UUID previousOwner = LandData.OwnerID; 597 UUID previousOwner = LandData.OwnerID;
396 598
397 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 599 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
398 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 600// m_scene.EventManager.TriggerParcelPrimCountUpdate();
399 SendLandUpdateToAvatarsOverMe(true); 601 SendLandUpdateToAvatarsOverMe(true);
400 602
401 if (sellObjects) SellLandObjects(previousOwner); 603 if (sellObjects) SellLandObjects(previousOwner);
@@ -431,7 +633,7 @@ namespace OpenSim.Region.CoreModules.World.Land
431 633
432 public bool CanBeOnThisLand(UUID avatar, float posHeight) 634 public bool CanBeOnThisLand(UUID avatar, float posHeight)
433 { 635 {
434 if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar)) 636 if (posHeight < LandChannel.BAN_LINE_SAFETY_HEIGHT && IsBannedFromLand(avatar))
435 { 637 {
436 return false; 638 return false;
437 } 639 }
@@ -530,7 +732,30 @@ namespace OpenSim.Region.CoreModules.World.Land
530 if (HasGroupAccess(avatar)) 732 if (HasGroupAccess(avatar))
531 return false; 733 return false;
532 734
533 return !IsInLandAccessList(avatar); 735 if(IsInLandAccessList(avatar))
736 return false;
737
738 // check for a NPC
739 ScenePresence sp;
740 if (!m_scene.TryGetScenePresence(avatar, out sp))
741 return true;
742
743 if(sp==null || !sp.IsNPC)
744 return true;
745
746 INPC npccli = (INPC)sp.ControllingClient;
747 if(npccli== null)
748 return true;
749
750 UUID owner = npccli.Owner;
751
752 if(owner == UUID.Zero)
753 return true;
754
755 if (owner == LandData.OwnerID)
756 return false;
757
758 return !IsInLandAccessList(owner);
534 } 759 }
535 760
536 public bool IsInLandAccessList(UUID avatar) 761 public bool IsInLandAccessList(UUID avatar)
@@ -568,6 +793,7 @@ namespace OpenSim.Region.CoreModules.World.Land
568 793
569 public void SendLandUpdateToAvatarsOverMe(bool snap_selection) 794 public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
570 { 795 {
796 m_scene.EventManager.TriggerParcelPrimCountUpdate();
571 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar) 797 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
572 { 798 {
573 ILandObject over = null; 799 ILandObject over = null;
@@ -587,13 +813,13 @@ namespace OpenSim.Region.CoreModules.World.Land
587 { 813 {
588 if (over.LandData.LocalID == LandData.LocalID) 814 if (over.LandData.LocalID == LandData.LocalID)
589 { 815 {
590 if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && 816 if(m_scene.RegionInfo.RegionSettings.AllowDamage)
591 m_scene.RegionInfo.RegionSettings.AllowDamage)
592 avatar.Invulnerable = false; 817 avatar.Invulnerable = false;
593 else 818 else
594 avatar.Invulnerable = true; 819 avatar.Invulnerable = (over.LandData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
595 820
596 SendLandUpdateToClient(snap_selection, avatar.ControllingClient); 821 SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
822 avatar.currentParcelUUID = LandData.GlobalID;
597 } 823 }
598 } 824 }
599 }); 825 });
@@ -630,13 +856,13 @@ namespace OpenSim.Region.CoreModules.World.Land
630 IClientAPI remote_client) 856 IClientAPI remote_client)
631 { 857 {
632 858
633 if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) 859 if ((flags & (uint) AccessList.Access) != 0)
634 { 860 {
635 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access); 861 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access);
636 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID); 862 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID);
637 } 863 }
638 864
639 if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) 865 if ((flags & (uint) AccessList.Ban) != 0)
640 { 866 {
641 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban); 867 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban);
642 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID); 868 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID);
@@ -691,6 +917,17 @@ namespace OpenSim.Region.CoreModules.World.Land
691 newData.ParcelAccessList.Add(temp); 917 newData.ParcelAccessList.Add(temp);
692 } 918 }
693 919
920 // update use lists flags
921 // rights already checked or we wont be here
922 uint parcelflags = newData.Flags;
923
924 if((flags & (uint)AccessList.Access) != 0)
925 parcelflags |= (uint)ParcelFlags.UseAccessList;
926 if((flags & (uint)AccessList.Ban) != 0)
927 parcelflags |= (uint)ParcelFlags.UseBanList;
928
929 newData.Flags = parcelflags;
930
694 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 931 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
695 } 932 }
696 933
@@ -708,7 +945,7 @@ namespace OpenSim.Region.CoreModules.World.Land
708 /// </summary> 945 /// </summary>
709 public void ForceUpdateLandInfo() 946 public void ForceUpdateLandInfo()
710 { 947 {
711 UpdateAABBAndAreaValues(); 948 UpdateGeometryValues();
712 UpdateLandBitmapByteArray(); 949 UpdateLandBitmapByteArray();
713 } 950 }
714 951
@@ -718,52 +955,117 @@ namespace OpenSim.Region.CoreModules.World.Land
718 } 955 }
719 956
720 /// <summary> 957 /// <summary>
721 /// Updates the AABBMin and AABBMax values after area/shape modification of the land object 958 /// Updates geomtric values after area/shape modification of the land object
722 /// </summary> 959 /// </summary>
723 private void UpdateAABBAndAreaValues() 960 private void UpdateGeometryValues()
724 { 961 {
725 int min_x = 10000; 962 int min_x = Int32.MaxValue;
726 int min_y = 10000; 963 int min_y = Int32.MaxValue;
727 int max_x = 0; 964 int max_x = Int32.MinValue;
728 int max_y = 0; 965 int max_y = Int32.MinValue;
729 int tempArea = 0; 966 int tempArea = 0;
730 int x, y; 967 int x, y;
968
969 int lastX = 0;
970 int lastY = 0;
971 float avgx = 0f;
972 float avgy = 0f;
973
974 bool needFirst = true;
975
731 for (x = 0; x < LandBitmap.GetLength(0); x++) 976 for (x = 0; x < LandBitmap.GetLength(0); x++)
732 { 977 {
733 for (y = 0; y < LandBitmap.GetLength(1); y++) 978 for (y = 0; y < LandBitmap.GetLength(1); y++)
734 { 979 {
735 if (LandBitmap[x, y] == true) 980 if (LandBitmap[x, y])
736 { 981 {
737 if (min_x > x) min_x = x; 982 if (min_x > x)
738 if (min_y > y) min_y = y; 983 min_x = x;
739 if (max_x < x) max_x = x; 984 if (min_y > y)
740 if (max_y < y) max_y = y; 985 min_y = y;
741 tempArea += landUnit * landUnit; //16sqm peice of land 986 if (max_x < x)
987 max_x = x;
988 if (max_y < y)
989 max_y = y;
990
991 if(needFirst)
992 {
993 avgx = x;
994 avgy = y;
995 m_startPoint.X = x * landUnit;
996 m_startPoint.Y = y * landUnit;
997 needFirst = false;
998 }
999 else
1000 {
1001 // keeping previus odd average
1002 avgx = (avgx * tempArea + x) / (tempArea + 1);
1003 avgy = (avgy * tempArea + y) / (tempArea + 1);
1004 }
1005
1006 tempArea++;
1007
1008 lastX = x;
1009 lastY = y;
742 } 1010 }
743 } 1011 }
744 } 1012 }
1013
1014 int halfunit = landUnit/2;
1015
1016 m_centerPoint.X = avgx * landUnit + halfunit;
1017 m_centerPoint.Y = avgy * landUnit + halfunit;
1018
1019 m_endPoint.X = lastX * landUnit + landUnit;
1020 m_endPoint.Y = lastY * landUnit + landUnit;
1021
1022 // next tests should not be needed
1023 // if they fail, something is wrong
1024
1025 int regionSizeX = (int)Constants.RegionSize;
1026 int regionSizeY = (int)Constants.RegionSize;
1027
1028 if(m_scene != null)
1029 {
1030 regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
1031 regionSizeY = (int)m_scene.RegionInfo.RegionSizeX;
1032 }
1033
745 int tx = min_x * landUnit; 1034 int tx = min_x * landUnit;
746 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 1035 if (tx >= regionSizeX)
747 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 1036 tx = regionSizeX - 1;
1037
748 int ty = min_y * landUnit; 1038 int ty = min_y * landUnit;
749 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 1039 if (ty >= regionSizeY)
750 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 1040 ty = regionSizeY - 1;
751 1041
752 LandData.AABBMin = 1042 m_AABBmin.X = tx;
753 new Vector3( 1043 m_AABBmin.Y = ty;
754 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 1044
1045 if(m_scene == null || m_scene.Heightmap == null)
1046 LandData.AABBMin = new Vector3(tx, ty, 0f);
1047 else
1048 LandData.AABBMin = new Vector3(tx, ty, (float)m_scene.Heightmap[tx, ty]);
755 1049
1050 max_x++;
756 tx = max_x * landUnit; 1051 tx = max_x * landUnit;
757 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 1052 if (tx > regionSizeX)
758 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 1053 tx = regionSizeX;
1054
1055 max_y++;
759 ty = max_y * landUnit; 1056 ty = max_y * landUnit;
760 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 1057 if (ty > regionSizeY)
761 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 1058 ty = regionSizeY;
1059
1060 m_AABBmax.X = tx;
1061 m_AABBmax.Y = ty;
762 1062
763 LandData.AABBMax 1063 if(m_scene == null || m_scene.Heightmap == null)
764 = new Vector3( 1064 LandData.AABBMax = new Vector3(tx, ty, 0f);
765 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 1065 else
1066 LandData.AABBMax = new Vector3(tx, ty, (float)m_scene.Heightmap[tx - 1, ty - 1]);
766 1067
1068 tempArea *= landUnit * landUnit;
767 LandData.Area = tempArea; 1069 LandData.Area = tempArea;
768 } 1070 }
769 1071
@@ -778,7 +1080,6 @@ namespace OpenSim.Region.CoreModules.World.Land
778 public void SetLandBitmap(bool[,] bitmap) 1080 public void SetLandBitmap(bool[,] bitmap)
779 { 1081 {
780 LandBitmap = bitmap; 1082 LandBitmap = bitmap;
781 // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
782 ForceUpdateLandInfo(); 1083 ForceUpdateLandInfo();
783 } 1084 }
784 1085
@@ -793,17 +1094,17 @@ namespace OpenSim.Region.CoreModules.World.Land
793 1094
794 public bool[,] BasicFullRegionLandBitmap() 1095 public bool[,] BasicFullRegionLandBitmap()
795 { 1096 {
796 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY); 1097 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY, true);
797 } 1098 }
798 1099
799 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) 1100 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y, bool set_value = true)
800 { 1101 {
801 // Empty bitmap for the whole region 1102 // Empty bitmap for the whole region
802 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 1103 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
803 tempBitmap.Initialize(); 1104 tempBitmap.Initialize();
804 1105
805 // Fill the bitmap square area specified by state and end 1106 // Fill the bitmap square area specified by state and end
806 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); 1107 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, set_value);
807 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>", 1108 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>",
808 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1)); 1109 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1));
809 return tempBitmap; 1110 return tempBitmap;
@@ -873,51 +1174,287 @@ namespace OpenSim.Region.CoreModules.World.Land
873 } 1174 }
874 1175
875 /// <summary> 1176 /// <summary>
1177 /// Remap a land bitmap. Takes the supplied land bitmap and rotates it, crops it and finally offsets it into
1178 /// a final land bitmap of the target region size.
1179 /// </summary>
1180 /// <param name="bitmap_base">The original parcel bitmap</param>
1181 /// <param name="rotationDegrees"></param>
1182 /// <param name="displacement">&lt;x,y,?&gt;</param>
1183 /// <param name="boundingOrigin">&lt;x,y,?&gt;</param>
1184 /// <param name="boundingSize">&lt;x,y,?&gt;</param>
1185 /// <param name="regionSize">&lt;x,y,?&gt;</param>
1186 /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
1187 /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
1188 /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
1189 /// <returns>New parcel bitmap</returns>
1190 public bool[,] RemapLandBitmap(bool[,] bitmap_base, Vector2 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Vector2 regionSize, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1191 {
1192 // get the size of the incoming bitmap
1193 int baseX = bitmap_base.GetLength(0);
1194 int baseY = bitmap_base.GetLength(1);
1195
1196 // create an intermediate bitmap that is 25% bigger on each side that we can work with to handle rotations
1197 int offsetX = baseX / 4; // the original origin will now be at these coordinates so now we can have imaginary negative coordinates ;)
1198 int offsetY = baseY / 4;
1199 int tmpX = baseX + baseX / 2;
1200 int tmpY = baseY + baseY / 2;
1201 int centreX = tmpX / 2;
1202 int centreY = tmpY / 2;
1203 bool[,] bitmap_tmp = new bool[tmpX, tmpY];
1204
1205 double radianRotation = Math.PI * rotationDegrees / 180f;
1206 double cosR = Math.Cos(radianRotation);
1207 double sinR = Math.Sin(radianRotation);
1208 if (rotationDegrees < 0f) rotationDegrees += 360f; //-90=270 -180=180 -270=90
1209
1210 // So first we apply the rotation to the incoming bitmap, storing the result in bitmap_tmp
1211 // We special case orthogonal rotations for accuracy because even using double precision math, Math.Cos(90 degrees) is never fully 0
1212 // and we can never rotate around a centre pixel because the bitmap size is always even
1213 int x, y, sx, sy;
1214 for (y = 0; y <= tmpY; y++)
1215 {
1216 for (x = 0; x <= tmpX; x++)
1217 {
1218 if (rotationDegrees == 0f)
1219 {
1220 sx = x - offsetX;
1221 sy = y - offsetY;
1222 }
1223 else if (rotationDegrees == 90f)
1224 {
1225 sx = y - offsetX;
1226 sy = tmpY - 1 - x - offsetY;
1227 }
1228 else if (rotationDegrees == 180f)
1229 {
1230 sx = tmpX - 1 - x - offsetX;
1231 sy = tmpY - 1 - y - offsetY;
1232 }
1233 else if (rotationDegrees == 270f)
1234 {
1235 sx = tmpX - 1 - y - offsetX;
1236 sy = x - offsetY;
1237 }
1238 else
1239 {
1240 // arbitary rotation: hmmm should I be using (centreX - 0.5) and (centreY - 0.5) and round cosR and sinR to say only 5 decimal places?
1241 sx = centreX + (int)Math.Round((((double)x - centreX) * cosR) + (((double)y - centreY) * sinR)) - offsetX;
1242 sy = centreY + (int)Math.Round((((double)y - centreY) * cosR) - (((double)x - centreX) * sinR)) - offsetY;
1243 }
1244 if (sx >= 0 && sx < baseX && sy >= 0 && sy < baseY)
1245 {
1246 try
1247 {
1248 if (bitmap_base[sx, sy]) bitmap_tmp[x, y] = true;
1249 }
1250 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
1251 {
1252 m_log.DebugFormat("{0} RemapLandBitmap Rotate: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, sx, sy, x, y);
1253 }
1254 }
1255 }
1256 }
1257
1258 // We could also incorporate the next steps, bounding-rectangle and displacement in the loop above, but it's simpler to visualise if done separately
1259 // and will also make it much easier when later I want the option for maybe a circular or oval bounding shape too ;).
1260 // So... our output land bitmap must be the size of the current region but rememeber, parcel landbitmaps are landUnit metres (4x4 metres) per point,
1261 // and region sizes, boundaries and displacements are in metres so we need to scale down
1262
1263 int newX = (int)(regionSize.X / landUnit);
1264 int newY = (int)(regionSize.Y / landUnit);
1265 bool[,] bitmap_new = new bool[newX, newY];
1266 // displacement is relative to <0,0> in the destination region and defines where the origin of the data selected by the bounding-rectangle is placed
1267 int dispX = (int)Math.Floor(displacement.X / landUnit);
1268 int dispY = (int)Math.Floor(displacement.Y / landUnit);
1269
1270 // startX/Y and endX/Y are coordinates in bitmap_tmp
1271 int startX = (int)Math.Floor(boundingOrigin.X / landUnit) + offsetX;
1272 if (startX > tmpX) startX = tmpX;
1273 if (startX < 0) startX = 0;
1274 int startY = (int)Math.Floor(boundingOrigin.Y / landUnit) + offsetY;
1275 if (startY > tmpY) startY = tmpY;
1276 if (startY < 0) startY = 0;
1277
1278 int endX = (int)Math.Floor((boundingOrigin.X + boundingSize.X) / landUnit) + offsetX;
1279 if (endX > tmpX) endX = tmpX;
1280 if (endX < 0) endX = 0;
1281 int endY = (int)Math.Floor((boundingOrigin.Y + boundingSize.Y) / landUnit) + offsetY;
1282 if (endY > tmpY) endY = tmpY;
1283 if (endY < 0) endY = 0;
1284
1285 //m_log.DebugFormat("{0} RemapLandBitmap: inSize=<{1},{2}>, disp=<{3},{4}> rot={5}, offset=<{6},{7}>, boundingStart=<{8},{9}>, boundingEnd=<{10},{11}>, cosR={12}, sinR={13}, outSize=<{14},{15}>", LogHeader,
1286 // baseX, baseY, dispX, dispY, radianRotation, offsetX, offsetY, startX, startY, endX, endY, cosR, sinR, newX, newY);
1287
1288 isEmptyNow = true;
1289 int minX = newX;
1290 int minY = newY;
1291 int maxX = 0;
1292 int maxY = 0;
1293
1294 int dx, dy;
1295 for (y = startY; y < endY; y++)
1296 {
1297 for (x = startX; x < endX; x++)
1298 {
1299 dx = x - startX + dispX;
1300 dy = y - startY + dispY;
1301 if (dx >= 0 && dx < newX && dy >= 0 && dy < newY)
1302 {
1303 try
1304 {
1305 if (bitmap_tmp[x, y])
1306 {
1307 bitmap_new[dx, dy] = true;
1308 isEmptyNow = false;
1309 if (dx < minX) minX = dx;
1310 if (dy < minY) minY = dy;
1311 if (dx > maxX) maxX = dx;
1312 if (dy > maxY) maxY = dy;
1313 }
1314 }
1315 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
1316 {
1317 m_log.DebugFormat("{0} RemapLandBitmap - Bound & Displace: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, x, y, dx, dy);
1318 }
1319 }
1320 }
1321 }
1322 if (isEmptyNow)
1323 {
1324 //m_log.DebugFormat("{0} RemapLandBitmap: Land bitmap is marked as Empty", LogHeader);
1325 minX = 0;
1326 minY = 0;
1327 }
1328
1329 AABBMin = new Vector3(minX * landUnit, minY * landUnit, 0);
1330 AABBMax = new Vector3(maxX * landUnit, maxY * landUnit, 0);
1331 return bitmap_new;
1332 }
1333
1334 /// <summary>
1335 /// Clears any parcel data in bitmap_base where there exists parcel data in bitmap_new. In other words the parcel data
1336 /// in bitmap_new takes over the space of the parcel data in bitmap_base.
1337 /// </summary>
1338 /// <param name="bitmap_base"></param>
1339 /// <param name="bitmap_new"></param>
1340 /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
1341 /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
1342 /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
1343 /// <returns>New parcel bitmap</returns>
1344 public bool[,] RemoveFromLandBitmap(bool[,] bitmap_base, bool[,] bitmap_new, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1345 {
1346 // get the size of the incoming bitmaps
1347 int baseX = bitmap_base.GetLength(0);
1348 int baseY = bitmap_base.GetLength(1);
1349 int newX = bitmap_new.GetLength(0);
1350 int newY = bitmap_new.GetLength(1);
1351
1352 if (baseX != newX || baseY != newY)
1353 {
1354 throw new Exception(
1355 String.Format("{0} RemoveFromLandBitmap: Land bitmaps are not the same size! baseX={1} baseY={2} newX={3} newY={4}", LogHeader, baseX, baseY, newX, newY));
1356 }
1357
1358 isEmptyNow = true;
1359 int minX = baseX;
1360 int minY = baseY;
1361 int maxX = 0;
1362 int maxY = 0;
1363
1364 for (int y = 0; y < baseY; y++)
1365 {
1366 for (int x = 0; x < baseX; x++)
1367 {
1368 if (bitmap_new[x, y]) bitmap_base[x, y] = false;
1369 if (bitmap_base[x, y])
1370 {
1371 isEmptyNow = false;
1372 if (x < minX) minX = x;
1373 if (y < minY) minY = y;
1374 if (x > maxX) maxX = x;
1375 if (y > maxY) maxY = y;
1376 }
1377 }
1378 }
1379 if (isEmptyNow)
1380 {
1381 //m_log.DebugFormat("{0} RemoveFromLandBitmap: Land bitmap is marked as Empty", LogHeader);
1382 minX = 0;
1383 minY = 0;
1384 }
1385 AABBMin = new Vector3(minX * landUnit, minY * landUnit, 0);
1386 AABBMax = new Vector3(maxX * landUnit, maxY * landUnit, 0);
1387 return bitmap_base;
1388 }
1389
1390 /// <summary>
876 /// Converts the land bitmap to a packet friendly byte array 1391 /// Converts the land bitmap to a packet friendly byte array
877 /// </summary> 1392 /// </summary>
878 /// <returns></returns> 1393 /// <returns></returns>
879 private byte[] ConvertLandBitmapToBytes() 1394 public byte[] ConvertLandBitmapToBytes()
880 { 1395 {
881 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8]; 1396 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
882 byte tempByte = 0; 1397
1398 int tempByte = 0;
883 int byteNum = 0; 1399 int byteNum = 0;
884 int i = 0; 1400 int mask = 1;
885 for (int y = 0; y < LandBitmap.GetLength(1); y++) 1401 for (int y = 0; y < LandBitmap.GetLength(1); y++)
886 { 1402 {
887 for (int x = 0; x < LandBitmap.GetLength(0); x++) 1403 for (int x = 0; x < LandBitmap.GetLength(0); x++)
888 { 1404 {
889 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 1405 if (LandBitmap[x, y])
890 if (i % 8 == 0) 1406 tempByte |= mask;
1407 mask = mask << 1;
1408 if (mask == 0x100)
891 { 1409 {
892 tempConvertArr[byteNum] = tempByte; 1410 mask = 1;
893 tempByte = (byte) 0; 1411 tempConvertArr[byteNum++] = (byte)tempByte;
894 i = 0; 1412 tempByte = 0;
895 byteNum++;
896 } 1413 }
897 } 1414 }
898 } 1415 }
899 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>", 1416
900 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 1417 if(tempByte != 0 && byteNum < 512)
1418 tempConvertArr[byteNum] = (byte)tempByte;
1419
901 return tempConvertArr; 1420 return tempConvertArr;
902 } 1421 }
903 1422
904 private bool[,] ConvertBytesToLandBitmap() 1423 public bool[,] ConvertBytesToLandBitmap(bool overrideRegionSize = false)
905 { 1424 {
906 bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 1425 int bitmapLen;
907 tempConvertMap.Initialize(); 1426 int xLen;
908 byte tempByte = 0; 1427 bool[,] tempConvertMap;
909 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
910 int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
911 int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
912 1428
913 if (bitmapLen == 512) 1429 if (overrideRegionSize)
1430 {
1431 // Importing land parcel data from an OAR where the source region is a different size to the dest region requires us
1432 // to make a LandBitmap that's not derived from the current region's size. We use the LandData.Bitmap size in bytes
1433 // to figure out what the OAR's region dimensions are. (Is there a better way to get the src region x and y from the OAR?)
1434 // This method assumes we always will have square regions
1435
1436 bitmapLen = LandData.Bitmap.Length;
1437 xLen = (int)Math.Abs(Math.Sqrt(bitmapLen * 8));
1438 tempConvertMap = new bool[xLen, xLen];
1439 tempConvertMap.Initialize();
1440 }
1441 else
914 { 1442 {
915 // Legacy bitmap being passed in. Use the legacy region size 1443 tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
916 // and only set the lower area of the larger region. 1444 tempConvertMap.Initialize();
917 xLen = (int)(Constants.RegionSize / landUnit); 1445 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
1446 bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
1447 xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
1448 if (bitmapLen == 512)
1449 {
1450 // Legacy bitmap being passed in. Use the legacy region size
1451 // and only set the lower area of the larger region.
1452 xLen = (int)(Constants.RegionSize / landUnit);
1453 }
918 } 1454 }
919 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen); 1455 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
920 1456
1457 byte tempByte;
921 int x = 0, y = 0; 1458 int x = 0, y = 0;
922 for (int i = 0; i < bitmapLen; i++) 1459 for (int i = 0; i < bitmapLen; i++)
923 { 1460 {
@@ -945,13 +1482,39 @@ namespace OpenSim.Region.CoreModules.World.Land
945 return tempConvertMap; 1482 return tempConvertMap;
946 } 1483 }
947 1484
1485 public bool IsLandBitmapEmpty(bool[,] landBitmap)
1486 {
1487 for (int y = 0; y < landBitmap.GetLength(1); y++)
1488 {
1489 for (int x = 0; x < landBitmap.GetLength(0); x++)
1490 {
1491 if (landBitmap[x, y]) return false;
1492 }
1493 }
1494 return true;
1495 }
1496
1497 public void DebugLandBitmap(bool[,] landBitmap)
1498 {
1499 m_log.InfoFormat("{0}: Map Key: #=claimed land .=unclaimed land.", LogHeader);
1500 for (int y = landBitmap.GetLength(1) - 1; y >= 0; y--)
1501 {
1502 string row = "";
1503 for (int x = 0; x < landBitmap.GetLength(0); x++)
1504 {
1505 row += landBitmap[x, y] ? "#" : ".";
1506 }
1507 m_log.InfoFormat("{0}: {1}", LogHeader, row);
1508 }
1509 }
1510
948 #endregion 1511 #endregion
949 1512
950 #region Object Select and Object Owner Listing 1513 #region Object Select and Object Owner Listing
951 1514
952 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client) 1515 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
953 { 1516 {
954 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1517 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
955 { 1518 {
956 List<uint> resultLocalIDs = new List<uint>(); 1519 List<uint> resultLocalIDs = new List<uint>();
957 try 1520 try
@@ -1001,7 +1564,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1001 /// </param> 1564 /// </param>
1002 public void SendLandObjectOwners(IClientAPI remote_client) 1565 public void SendLandObjectOwners(IClientAPI remote_client)
1003 { 1566 {
1004 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1567 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
1005 { 1568 {
1006 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>(); 1569 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
1007 List<UUID> groups = new List<UUID>(); 1570 List<UUID> groups = new List<UUID>();
@@ -1009,9 +1572,9 @@ namespace OpenSim.Region.CoreModules.World.Land
1009 lock (primsOverMe) 1572 lock (primsOverMe)
1010 { 1573 {
1011// m_log.DebugFormat( 1574// m_log.DebugFormat(
1012// "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region", 1575// "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region",
1013// remote_client.Name, primsOverMe.Count); 1576// remote_client.Name, primsOverMe.Count);
1014 1577
1015 try 1578 try
1016 { 1579 {
1017 foreach (SceneObjectGroup obj in primsOverMe) 1580 foreach (SceneObjectGroup obj in primsOverMe)
@@ -1052,7 +1615,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1052 public Dictionary<UUID, int> GetLandObjectOwners() 1615 public Dictionary<UUID, int> GetLandObjectOwners()
1053 { 1616 {
1054 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>(); 1617 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
1055 1618
1056 lock (primsOverMe) 1619 lock (primsOverMe)
1057 { 1620 {
1058 try 1621 try
@@ -1106,8 +1669,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1106 { 1669 {
1107 foreach (SceneObjectGroup obj in primsOverMe) 1670 foreach (SceneObjectGroup obj in primsOverMe)
1108 { 1671 {
1109 if (obj.OwnerID == previousOwner && obj.GroupID == UUID.Zero && 1672 if(m_scene.Permissions.CanSellObject(previousOwner,obj, (byte)SaleType.Original))
1110 (obj.GetEffectivePermissions() & (uint)(OpenSim.Framework.PermissionMask.Transfer)) != 0)
1111 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0); 1673 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0);
1112 } 1674 }
1113 } 1675 }
@@ -1121,14 +1683,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1121 { 1683 {
1122 SceneObjectGroup[] objs = new SceneObjectGroup[1]; 1684 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1123 objs[0] = obj; 1685 objs[0] = obj;
1124 m_scene.returnObjects(objs, obj.OwnerID); 1686 m_scene.returnObjects(objs, null);
1125 } 1687 }
1126 1688
1127 public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) 1689 public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
1128 { 1690 {
1129// m_log.DebugFormat( 1691// m_log.DebugFormat(
1130// "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name); 1692// "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name);
1131 1693
1132 Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>(); 1694 Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>();
1133 1695
1134 lock (primsOverMe) 1696 lock (primsOverMe)
@@ -1152,6 +1714,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1152 { 1714 {
1153 if (obj.GroupID == LandData.GroupID) 1715 if (obj.GroupID == LandData.GroupID)
1154 { 1716 {
1717 if (obj.OwnerID == LandData.OwnerID)
1718 continue;
1155 if (!returns.ContainsKey(obj.OwnerID)) 1719 if (!returns.ContainsKey(obj.OwnerID))
1156 returns[obj.OwnerID] = 1720 returns[obj.OwnerID] =
1157 new List<SceneObjectGroup>(); 1721 new List<SceneObjectGroup>();
@@ -1193,8 +1757,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1193 1757
1194 foreach (List<SceneObjectGroup> ol in returns.Values) 1758 foreach (List<SceneObjectGroup> ol in returns.Values)
1195 { 1759 {
1196 if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) 1760 if (m_scene.Permissions.CanReturnObjects(this, remote_client, ol))
1197 m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); 1761 m_scene.returnObjects(ol.ToArray(), remote_client);
1198 } 1762 }
1199 } 1763 }
1200 1764
@@ -1211,7 +1775,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1211 public void AddPrimOverMe(SceneObjectGroup obj) 1775 public void AddPrimOverMe(SceneObjectGroup obj)
1212 { 1776 {
1213// m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name); 1777// m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name);
1214 1778
1215 lock (primsOverMe) 1779 lock (primsOverMe)
1216 primsOverMe.Add(obj); 1780 primsOverMe.Add(obj);
1217 } 1781 }
@@ -1219,13 +1783,13 @@ namespace OpenSim.Region.CoreModules.World.Land
1219 public void RemovePrimFromOverMe(SceneObjectGroup obj) 1783 public void RemovePrimFromOverMe(SceneObjectGroup obj)
1220 { 1784 {
1221// m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name); 1785// m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name);
1222 1786
1223 lock (primsOverMe) 1787 lock (primsOverMe)
1224 primsOverMe.Remove(obj); 1788 primsOverMe.Remove(obj);
1225 } 1789 }
1226 1790
1227 #endregion 1791 #endregion
1228 1792
1229 /// <summary> 1793 /// <summary>
1230 /// Set the media url for this land parcel 1794 /// Set the media url for this land parcel
1231 /// </summary> 1795 /// </summary>
@@ -1233,9 +1797,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1233 public void SetMediaUrl(string url) 1797 public void SetMediaUrl(string url)
1234 { 1798 {
1235 LandData.MediaURL = url; 1799 LandData.MediaURL = url;
1800 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1236 SendLandUpdateToAvatarsOverMe(); 1801 SendLandUpdateToAvatarsOverMe();
1237 } 1802 }
1238 1803
1239 /// <summary> 1804 /// <summary>
1240 /// Set the music url for this land parcel 1805 /// Set the music url for this land parcel
1241 /// </summary> 1806 /// </summary>
@@ -1243,6 +1808,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1243 public void SetMusicUrl(string url) 1808 public void SetMusicUrl(string url)
1244 { 1809 {
1245 LandData.MusicURL = url; 1810 LandData.MusicURL = url;
1811 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1246 SendLandUpdateToAvatarsOverMe(); 1812 SendLandUpdateToAvatarsOverMe();
1247 } 1813 }
1248 1814
@@ -1257,6 +1823,48 @@ namespace OpenSim.Region.CoreModules.World.Land
1257 1823
1258 #endregion 1824 #endregion
1259 1825
1826 private void OnFrame()
1827 {
1828 m_expiryCounter++;
1829
1830 if (m_expiryCounter >= 50)
1831 {
1832 ExpireAccessList();
1833 m_expiryCounter = 0;
1834 }
1835
1836 // need to update dwell here bc landdata has no parent info
1837 if(LandData != null && m_dwellModule != null)
1838 {
1839 double now = Util.GetTimeStampMS();
1840 double elapsed = now - LandData.LastDwellTimeMS;
1841 if(elapsed > 150000) //2.5 minutes resolution / throttle
1842 {
1843 float dwell = LandData.Dwell;
1844 double cur = dwell * 60000.0;
1845 double decay = 1.5e-8 * cur * elapsed;
1846 cur -= decay;
1847 if(cur < 0)
1848 cur = 0;
1849
1850 UUID lgid = LandData.GlobalID;
1851 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
1852 {
1853 if(sp.IsNPC || sp.IsLoggingIn || sp.IsDeleted || sp.currentParcelUUID != lgid)
1854 return;
1855 cur += (now - sp.ParcelDwellTickMS);
1856 sp.ParcelDwellTickMS = now;
1857 });
1858
1859 float newdwell = (float)(cur * 1.666666666667e-5);
1860 LandData.Dwell = newdwell;
1861
1862 if(Math.Abs(newdwell - dwell) >= 0.9)
1863 m_scene.EventManager.TriggerLandObjectAdded(this);
1864 }
1865 }
1866 }
1867
1260 private void ExpireAccessList() 1868 private void ExpireAccessList()
1261 { 1869 {
1262 List<LandAccessEntry> delete = new List<LandAccessEntry>(); 1870 List<LandAccessEntry> delete = new List<LandAccessEntry>();
@@ -1267,7 +1875,22 @@ namespace OpenSim.Region.CoreModules.World.Land
1267 delete.Add(entry); 1875 delete.Add(entry);
1268 } 1876 }
1269 foreach (LandAccessEntry entry in delete) 1877 foreach (LandAccessEntry entry in delete)
1878 {
1270 LandData.ParcelAccessList.Remove(entry); 1879 LandData.ParcelAccessList.Remove(entry);
1880 ScenePresence presence;
1881
1882 if (m_scene.TryGetScenePresence(entry.AgentID, out presence) && (!presence.IsChildAgent))
1883 {
1884 ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
1885 if (land.LandData.LocalID == LandData.LocalID)
1886 {
1887 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1888 presence.TeleportOnEject(pos);
1889 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
1890 }
1891 }
1892 m_log.DebugFormat("[LAND]: Removing entry {0} because it has expired", entry.AgentID);
1893 }
1271 1894
1272 if (delete.Count > 0) 1895 if (delete.Count > 0)
1273 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this); 1896 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this);
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 9b51cc8..2a720db 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -69,11 +69,11 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// For now, a simple simwide taint to get this up. Later parcel based 69 /// For now, a simple simwide taint to get this up. Later parcel based
70 /// taint to allow recounting a parcel if only ownership has changed 70 /// taint to allow recounting a parcel if only ownership has changed
71 /// without recounting the whole sim. 71 /// without recounting the whole sim.
72 /// 72 ///
73 /// We start out tainted so that the first get call resets the various prim counts. 73 /// We start out tainted so that the first get call resets the various prim counts.
74 /// </value> 74 /// </value>
75 private bool m_Tainted = true; 75 private bool m_Tainted = true;
76 76
77 private Object m_TaintLock = new Object(); 77 private Object m_TaintLock = new Object();
78 78
79 public Type ReplaceableInterface 79 public Type ReplaceableInterface
@@ -88,14 +88,12 @@ namespace OpenSim.Region.CoreModules.World.Land
88 public void AddRegion(Scene scene) 88 public void AddRegion(Scene scene)
89 { 89 {
90 m_Scene = scene; 90 m_Scene = scene;
91 91
92 m_Scene.RegisterModuleInterface<IPrimCountModule>(this); 92 m_Scene.RegisterModuleInterface<IPrimCountModule>(this);
93 93
94 m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd; 94 m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd;
95 m_Scene.EventManager.OnObjectBeingRemovedFromScene += 95 m_Scene.EventManager.OnObjectBeingRemovedFromScene += OnObjectBeingRemovedFromScene;
96 OnObjectBeingRemovedFromScene; 96 m_Scene.EventManager.OnParcelPrimCountTainted += OnParcelPrimCountTainted;
97 m_Scene.EventManager.OnParcelPrimCountTainted +=
98 OnParcelPrimCountTainted;
99 m_Scene.EventManager.OnLandObjectAdded += delegate(ILandObject lo) { OnParcelPrimCountTainted(); }; 97 m_Scene.EventManager.OnLandObjectAdded += delegate(ILandObject lo) { OnParcelPrimCountTainted(); };
100 } 98 }
101 99
@@ -104,7 +102,7 @@ namespace OpenSim.Region.CoreModules.World.Land
104 } 102 }
105 103
106 public void RemoveRegion(Scene scene) 104 public void RemoveRegion(Scene scene)
107 { 105 {
108 } 106 }
109 107
110 public void Close() 108 public void Close()
@@ -126,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Land
126 AddObject(obj); 124 AddObject(obj);
127// else 125// else
128// m_log.DebugFormat( 126// m_log.DebugFormat(
129// "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted", 127// "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted",
130// obj.Name, m_Scene.RegionInfo.RegionName); 128// obj.Name, m_Scene.RegionInfo.RegionName);
131 } 129 }
132 } 130 }
@@ -140,16 +138,16 @@ namespace OpenSim.Region.CoreModules.World.Land
140 RemoveObject(obj); 138 RemoveObject(obj);
141// else 139// else
142// m_log.DebugFormat( 140// m_log.DebugFormat(
143// "[PRIM COUNT MODULE]: Ignoring OnObjectBeingRemovedFromScene() for {0} on {1} since count is tainted", 141// "[PRIM COUNT MODULE]: Ignoring OnObjectBeingRemovedFromScene() for {0} on {1} since count is tainted",
144// obj.Name, m_Scene.RegionInfo.RegionName); 142// obj.Name, m_Scene.RegionInfo.RegionName);
145 } 143 }
146 } 144 }
147 145
148 private void OnParcelPrimCountTainted() 146 private void OnParcelPrimCountTainted()
149 { 147 {
150// m_log.DebugFormat( 148// m_log.DebugFormat(
151// "[PRIM COUNT MODULE]: OnParcelPrimCountTainted() called on {0}", m_Scene.RegionInfo.RegionName); 149// "[PRIM COUNT MODULE]: OnParcelPrimCountTainted() called on {0}", m_Scene.RegionInfo.RegionName);
152 150
153 lock (m_TaintLock) 151 lock (m_TaintLock)
154 m_Tainted = true; 152 m_Tainted = true;
155 } 153 }
@@ -174,40 +172,40 @@ namespace OpenSim.Region.CoreModules.World.Land
174 172
175 // NOTE: Call under Taint Lock 173 // NOTE: Call under Taint Lock
176 private void AddObject(SceneObjectGroup obj) 174 private void AddObject(SceneObjectGroup obj)
177 { 175 {
178 if (obj.IsAttachment) 176 if (obj.IsAttachment)
179 return; 177 return;
180 if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) 178 if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0))
181 return; 179 return;
182 180
183 Vector3 pos = obj.AbsolutePosition; 181 Vector3 pos = obj.AbsolutePosition;
184 ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); 182 ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
185 183
186 // If for some reason there is no land object (perhaps the object is out of bounds) then we can't count it 184 // If for some reason there is no land object (perhaps the object is out of bounds) then we can't count it
187 if (landObject == null) 185 if (landObject == null)
188 { 186 {
189// m_log.WarnFormat( 187// m_log.WarnFormat(
190// "[PRIM COUNT MODULE]: Found no land object for {0} at position ({1}, {2}) on {3}", 188// "[PRIM COUNT MODULE]: Found no land object for {0} at position ({1}, {2}) on {3}",
191// obj.Name, pos.X, pos.Y, m_Scene.RegionInfo.RegionName); 189// obj.Name, pos.X, pos.Y, m_Scene.RegionInfo.RegionName);
192 190
193 return; 191 return;
194 } 192 }
195 193
196 LandData landData = landObject.LandData; 194 LandData landData = landObject.LandData;
197 195
198// m_log.DebugFormat( 196// m_log.DebugFormat(
199// "[PRIM COUNT MODULE]: Adding object {0} with {1} parts to prim count for parcel {2} on {3}", 197// "[PRIM COUNT MODULE]: Adding object {0} with {1} parts to prim count for parcel {2} on {3}",
200// obj.Name, obj.Parts.Length, landData.Name, m_Scene.RegionInfo.RegionName); 198// obj.Name, obj.Parts.Length, landData.Name, m_Scene.RegionInfo.RegionName);
201 199
202// m_log.DebugFormat( 200// m_log.DebugFormat(
203// "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}", 201// "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}",
204// obj.Name, obj.OwnerID, landData.OwnerID); 202// obj.Name, obj.OwnerID, landData.OwnerID);
205 203
206 ParcelCounts parcelCounts; 204 ParcelCounts parcelCounts;
207 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) 205 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
208 { 206 {
209 UUID landOwner = landData.OwnerID; 207 UUID landOwner = landData.OwnerID;
210 int partCount = obj.Parts.Length; 208 int partCount = obj.GetPartCount();
211 209
212 m_SimwideCounts[landOwner] += partCount; 210 m_SimwideCounts[landOwner] += partCount;
213 if (parcelCounts.Users.ContainsKey(obj.OwnerID)) 211 if (parcelCounts.Users.ContainsKey(obj.OwnerID))
@@ -215,37 +213,23 @@ namespace OpenSim.Region.CoreModules.World.Land
215 else 213 else
216 parcelCounts.Users[obj.OwnerID] = partCount; 214 parcelCounts.Users[obj.OwnerID] = partCount;
217 215
218 if (obj.IsSelected) 216 if (obj.IsSelected || obj.GetSittingAvatarsCount() > 0)
219 { 217 parcelCounts.Selected += partCount;
220 parcelCounts.Selected += partCount; 218
221 } 219 if (obj.OwnerID == landData.OwnerID)
220 parcelCounts.Owner += partCount;
221 else if (landData.GroupID != UUID.Zero && obj.GroupID == landData.GroupID)
222 parcelCounts.Group += partCount;
222 else 223 else
223 { 224 parcelCounts.Others += partCount;
224 if (landData.IsGroupOwned)
225 {
226 if (obj.OwnerID == landData.GroupID)
227 parcelCounts.Owner += partCount;
228 else if (landData.GroupID != UUID.Zero && obj.GroupID == landData.GroupID)
229 parcelCounts.Group += partCount;
230 else
231 parcelCounts.Others += partCount;
232 }
233 else
234 {
235 if (obj.OwnerID == landData.OwnerID)
236 parcelCounts.Owner += partCount;
237 else
238 parcelCounts.Others += partCount;
239 }
240 }
241 } 225 }
242 } 226 }
243 227
244 // NOTE: Call under Taint Lock 228 // NOTE: Call under Taint Lock
245 private void RemoveObject(SceneObjectGroup obj) 229 private void RemoveObject(SceneObjectGroup obj)
246 { 230 {
247// m_log.DebugFormat("[PRIM COUNT MODULE]: Removing object {0} {1} from prim count", obj.Name, obj.UUID); 231// m_log.DebugFormat("[PRIM COUNT MODULE]: Removing object {0} {1} from prim count", obj.Name, obj.UUID);
248 232
249 // Currently this is being done by tainting the count instead. 233 // Currently this is being done by tainting the count instead.
250 } 234 }
251 235
@@ -253,7 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Land
253 { 237 {
254// m_log.DebugFormat( 238// m_log.DebugFormat(
255// "[PRIM COUNT MODULE]: GetPrimCounts for parcel {0} in {1}", parcelID, m_Scene.RegionInfo.RegionName); 239// "[PRIM COUNT MODULE]: GetPrimCounts for parcel {0} in {1}", parcelID, m_Scene.RegionInfo.RegionName);
256 240
257 PrimCounts primCounts; 241 PrimCounts primCounts;
258 242
259 lock (m_PrimCounts) 243 lock (m_PrimCounts)
@@ -267,7 +251,7 @@ namespace OpenSim.Region.CoreModules.World.Land
267 return primCounts; 251 return primCounts;
268 } 252 }
269 253
270 254
271 /// <summary> 255 /// <summary>
272 /// Get the number of prims on the parcel that are owned by the parcel owner. 256 /// Get the number of prims on the parcel that are owned by the parcel owner.
273 /// </summary> 257 /// </summary>
@@ -276,7 +260,7 @@ namespace OpenSim.Region.CoreModules.World.Land
276 public int GetOwnerCount(UUID parcelID) 260 public int GetOwnerCount(UUID parcelID)
277 { 261 {
278 int count = 0; 262 int count = 0;
279 263
280 lock (m_TaintLock) 264 lock (m_TaintLock)
281 { 265 {
282 if (m_Tainted) 266 if (m_Tainted)
@@ -286,11 +270,11 @@ namespace OpenSim.Region.CoreModules.World.Land
286 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 270 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
287 count = counts.Owner; 271 count = counts.Owner;
288 } 272 }
289 273
290// m_log.DebugFormat( 274// m_log.DebugFormat(
291// "[PRIM COUNT MODULE]: GetOwnerCount for parcel {0} in {1} returning {2}", 275// "[PRIM COUNT MODULE]: GetOwnerCount for parcel {0} in {1} returning {2}",
292// parcelID, m_Scene.RegionInfo.RegionName, count); 276// parcelID, m_Scene.RegionInfo.RegionName, count);
293 277
294 return count; 278 return count;
295 } 279 }
296 280
@@ -298,11 +282,11 @@ namespace OpenSim.Region.CoreModules.World.Land
298 /// Get the number of prims on the parcel that have been set to the group that owns the parcel. 282 /// Get the number of prims on the parcel that have been set to the group that owns the parcel.
299 /// </summary> 283 /// </summary>
300 /// <param name="parcelID"></param> 284 /// <param name="parcelID"></param>
301 /// <returns></returns> 285 /// <returns></returns>
302 public int GetGroupCount(UUID parcelID) 286 public int GetGroupCount(UUID parcelID)
303 { 287 {
304 int count = 0; 288 int count = 0;
305 289
306 lock (m_TaintLock) 290 lock (m_TaintLock)
307 { 291 {
308 if (m_Tainted) 292 if (m_Tainted)
@@ -312,11 +296,11 @@ namespace OpenSim.Region.CoreModules.World.Land
312 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 296 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
313 count = counts.Group; 297 count = counts.Group;
314 } 298 }
315 299
316// m_log.DebugFormat( 300// m_log.DebugFormat(
317// "[PRIM COUNT MODULE]: GetGroupCount for parcel {0} in {1} returning {2}", 301// "[PRIM COUNT MODULE]: GetGroupCount for parcel {0} in {1} returning {2}",
318// parcelID, m_Scene.RegionInfo.RegionName, count); 302// parcelID, m_Scene.RegionInfo.RegionName, count);
319 303
320 return count; 304 return count;
321 } 305 }
322 306
@@ -324,11 +308,11 @@ namespace OpenSim.Region.CoreModules.World.Land
324 /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group. 308 /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group.
325 /// </summary> 309 /// </summary>
326 /// <param name="parcelID"></param> 310 /// <param name="parcelID"></param>
327 /// <returns></returns> 311 /// <returns></returns>
328 public int GetOthersCount(UUID parcelID) 312 public int GetOthersCount(UUID parcelID)
329 { 313 {
330 int count = 0; 314 int count = 0;
331 315
332 lock (m_TaintLock) 316 lock (m_TaintLock)
333 { 317 {
334 if (m_Tainted) 318 if (m_Tainted)
@@ -338,23 +322,23 @@ namespace OpenSim.Region.CoreModules.World.Land
338 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 322 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
339 count = counts.Others; 323 count = counts.Others;
340 } 324 }
341 325
342// m_log.DebugFormat( 326// m_log.DebugFormat(
343// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}", 327// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
344// parcelID, m_Scene.RegionInfo.RegionName, count); 328// parcelID, m_Scene.RegionInfo.RegionName, count);
345 329
346 return count; 330 return count;
347 } 331 }
348 332
349 /// <summary> 333 /// <summary>
350 /// Get the number of selected prims. 334 /// Get the number of selected prims.
351 /// </summary> 335 /// </summary>
352 /// <param name="parcelID"></param> 336 /// <param name="parcelID"></param>
353 /// <returns></returns> 337 /// <returns></returns>
354 public int GetSelectedCount(UUID parcelID) 338 public int GetSelectedCount(UUID parcelID)
355 { 339 {
356 int count = 0; 340 int count = 0;
357 341
358 lock (m_TaintLock) 342 lock (m_TaintLock)
359 { 343 {
360 if (m_Tainted) 344 if (m_Tainted)
@@ -364,24 +348,24 @@ namespace OpenSim.Region.CoreModules.World.Land
364 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 348 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
365 count = counts.Selected; 349 count = counts.Selected;
366 } 350 }
367 351
368// m_log.DebugFormat( 352// m_log.DebugFormat(
369// "[PRIM COUNT MODULE]: GetSelectedCount for parcel {0} in {1} returning {2}", 353// "[PRIM COUNT MODULE]: GetSelectedCount for parcel {0} in {1} returning {2}",
370// parcelID, m_Scene.RegionInfo.RegionName, count); 354// parcelID, m_Scene.RegionInfo.RegionName, count);
371 355
372 return count; 356 return count;
373 } 357 }
374 358
375 /// <summary> 359 /// <summary>
376 /// Get the total count of owner, group and others prims on the parcel. 360 /// Get the total count of owner, group and others prims on the parcel.
377 /// FIXME: Need to do selected prims once this is reimplemented. 361 /// FIXME: Need to do selected prims once this is reimplemented.
378 /// </summary> 362 /// </summary>
379 /// <param name="parcelID"></param> 363 /// <param name="parcelID"></param>
380 /// <returns></returns> 364 /// <returns></returns>
381 public int GetTotalCount(UUID parcelID) 365 public int GetTotalCount(UUID parcelID)
382 { 366 {
383 int count = 0; 367 int count = 0;
384 368
385 lock (m_TaintLock) 369 lock (m_TaintLock)
386 { 370 {
387 if (m_Tainted) 371 if (m_Tainted)
@@ -393,31 +377,30 @@ namespace OpenSim.Region.CoreModules.World.Land
393 count = counts.Owner; 377 count = counts.Owner;
394 count += counts.Group; 378 count += counts.Group;
395 count += counts.Others; 379 count += counts.Others;
396 count += counts.Selected;
397 } 380 }
398 } 381 }
399 382
400// m_log.DebugFormat( 383// m_log.DebugFormat(
401// "[PRIM COUNT MODULE]: GetTotalCount for parcel {0} in {1} returning {2}", 384// "[PRIM COUNT MODULE]: GetTotalCount for parcel {0} in {1} returning {2}",
402// parcelID, m_Scene.RegionInfo.RegionName, count); 385// parcelID, m_Scene.RegionInfo.RegionName, count);
403 386
404 return count; 387 return count;
405 } 388 }
406 389
407 /// <summary> 390 /// <summary>
408 /// Get the number of prims that are in the entire simulator for the owner of this parcel. 391 /// Get the number of prims that are in the entire simulator for the owner of this parcel.
409 /// </summary> 392 /// </summary>
410 /// <param name="parcelID"></param> 393 /// <param name="parcelID"></param>
411 /// <returns></returns> 394 /// <returns></returns>
412 public int GetSimulatorCount(UUID parcelID) 395 public int GetSimulatorCount(UUID parcelID)
413 { 396 {
414 int count = 0; 397 int count = 0;
415 398
416 lock (m_TaintLock) 399 lock (m_TaintLock)
417 { 400 {
418 if (m_Tainted) 401 if (m_Tainted)
419 Recount(); 402 Recount();
420 403
421 UUID owner; 404 UUID owner;
422 if (m_OwnerMap.TryGetValue(parcelID, out owner)) 405 if (m_OwnerMap.TryGetValue(parcelID, out owner))
423 { 406 {
@@ -426,11 +409,11 @@ namespace OpenSim.Region.CoreModules.World.Land
426 count = val; 409 count = val;
427 } 410 }
428 } 411 }
429 412
430// m_log.DebugFormat( 413// m_log.DebugFormat(
431// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}", 414// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
432// parcelID, m_Scene.RegionInfo.RegionName, count); 415// parcelID, m_Scene.RegionInfo.RegionName, count);
433 416
434 return count; 417 return count;
435 } 418 }
436 419
@@ -439,11 +422,11 @@ namespace OpenSim.Region.CoreModules.World.Land
439 /// </summary> 422 /// </summary>
440 /// <param name="parcelID"></param> 423 /// <param name="parcelID"></param>
441 /// <param name="userID"></param> 424 /// <param name="userID"></param>
442 /// <returns></returns> 425 /// <returns></returns>
443 public int GetUserCount(UUID parcelID, UUID userID) 426 public int GetUserCount(UUID parcelID, UUID userID)
444 { 427 {
445 int count = 0; 428 int count = 0;
446 429
447 lock (m_TaintLock) 430 lock (m_TaintLock)
448 { 431 {
449 if (m_Tainted) 432 if (m_Tainted)
@@ -459,9 +442,9 @@ namespace OpenSim.Region.CoreModules.World.Land
459 } 442 }
460 443
461// m_log.DebugFormat( 444// m_log.DebugFormat(
462// "[PRIM COUNT MODULE]: GetUserCount for user {0} in parcel {1} in region {2} returning {3}", 445// "[PRIM COUNT MODULE]: GetUserCount for user {0} in parcel {1} in region {2} returning {3}",
463// userID, parcelID, m_Scene.RegionInfo.RegionName, count); 446// userID, parcelID, m_Scene.RegionInfo.RegionName, count);
464 447
465 return count; 448 return count;
466 } 449 }
467 450
@@ -469,13 +452,13 @@ namespace OpenSim.Region.CoreModules.World.Land
469 private void Recount() 452 private void Recount()
470 { 453 {
471// m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName); 454// m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName);
472 455
473 m_OwnerMap.Clear(); 456 m_OwnerMap.Clear();
474 m_SimwideCounts.Clear(); 457 m_SimwideCounts.Clear();
475 m_ParcelCounts.Clear(); 458 m_ParcelCounts.Clear();
476 459
477 List<ILandObject> land = m_Scene.LandChannel.AllParcels(); 460 List<ILandObject> land = m_Scene.LandChannel.AllParcels();
478 461
479 foreach (ILandObject l in land) 462 foreach (ILandObject l in land)
480 { 463 {
481 LandData landData = l.LandData; 464 LandData landData = l.LandData;
@@ -483,7 +466,7 @@ namespace OpenSim.Region.CoreModules.World.Land
483 m_OwnerMap[landData.GlobalID] = landData.OwnerID; 466 m_OwnerMap[landData.GlobalID] = landData.OwnerID;
484 m_SimwideCounts[landData.OwnerID] = 0; 467 m_SimwideCounts[landData.OwnerID] = 0;
485// m_log.DebugFormat( 468// m_log.DebugFormat(
486// "[PRIM COUNT MODULE]: Initializing parcel count for {0} on {1}", 469// "[PRIM COUNT MODULE]: Initializing parcel count for {0} on {1}",
487// landData.Name, m_Scene.RegionInfo.RegionName); 470// landData.Name, m_Scene.RegionInfo.RegionName);
488 m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); 471 m_ParcelCounts[landData.GlobalID] = new ParcelCounts();
489 } 472 }
@@ -499,7 +482,7 @@ namespace OpenSim.Region.CoreModules.World.Land
499 m_PrimCounts.Remove(k); 482 m_PrimCounts.Remove(k);
500 } 483 }
501 } 484 }
502 485
503 m_Tainted = false; 486 m_Tainted = false;
504 } 487 }
505 } 488 }
@@ -541,7 +524,7 @@ namespace OpenSim.Region.CoreModules.World.Land
541 return m_Parent.GetOthersCount(m_ParcelID); 524 return m_Parent.GetOthersCount(m_ParcelID);
542 } 525 }
543 } 526 }
544 527
545 public int Selected 528 public int Selected
546 { 529 {
547 get 530 get
@@ -549,7 +532,7 @@ namespace OpenSim.Region.CoreModules.World.Land
549 return m_Parent.GetSelectedCount(m_ParcelID); 532 return m_Parent.GetSelectedCount(m_ParcelID);
550 } 533 }
551 } 534 }
552 535
553 public int Total 536 public int Total
554 { 537 {
555 get 538 get
@@ -597,4 +580,4 @@ namespace OpenSim.Region.CoreModules.World.Land
597 } 580 }
598 } 581 }
599 } 582 }
600} \ No newline at end of file 583}
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
index 4ed67f3..d6a3ded 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
@@ -45,14 +45,14 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
45 UUID userId = TestHelpers.ParseTail(0x1); 45 UUID userId = TestHelpers.ParseTail(0x1);
46 46
47 LandManagementModule lmm = new LandManagementModule(); 47 LandManagementModule lmm = new LandManagementModule();
48 Scene scene = new SceneHelpers().SetupScene(); 48 Scene scene = new SceneHelpers().SetupScene();
49 SceneHelpers.SetupSceneModules(scene, lmm); 49 SceneHelpers.SetupSceneModules(scene, lmm);
50 50
51 ILandObject lo = new LandObject(userId, false, scene); 51 ILandObject lo = new LandObject(userId, false, scene);
52 lo.LandData.Name = "lo1"; 52 lo.LandData.Name = "lo1";
53 lo.SetLandBitmap( 53 lo.SetLandBitmap(
54 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 54 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
55 lo = lmm.AddLandObject(lo); 55 lo = lmm.AddLandObject(lo);
56 56
57 // TODO: Should add asserts to check that land object was added properly. 57 // TODO: Should add asserts to check that land object was added properly.
58 58
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
67 { 67 {
68 ILandObject loAtCoord = lmm.GetLandObject(0, 0); 68 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
69 Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID)); 69 Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID));
70 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID)); 70 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID));
71 } 71 }
72 72
73 { 73 {
@@ -88,8 +88,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
88 88
89 SceneHelpers sh = new SceneHelpers(); 89 SceneHelpers sh = new SceneHelpers();
90 LandManagementModule lmm = new LandManagementModule(); 90 LandManagementModule lmm = new LandManagementModule();
91 Scene scene = sh.SetupScene(); 91 Scene scene = sh.SetupScene();
92 SceneHelpers.SetupSceneModules(scene, lmm); 92 SceneHelpers.SetupSceneModules(scene, lmm);
93 93
94 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID); 94 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID);
95 95
@@ -115,8 +115,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
115 115
116 SceneHelpers sh = new SceneHelpers(); 116 SceneHelpers sh = new SceneHelpers();
117 LandManagementModule lmm = new LandManagementModule(); 117 LandManagementModule lmm = new LandManagementModule();
118 Scene scene = sh.SetupScene(); 118 Scene scene = sh.SetupScene();
119 SceneHelpers.SetupSceneModules(scene, lmm); 119 SceneHelpers.SetupSceneModules(scene, lmm);
120 120
121 ILandObject originalLo1 = new LandObject(userId, false, scene); 121 ILandObject originalLo1 = new LandObject(userId, false, scene);
122 originalLo1.LandData.Name = "lo1"; 122 originalLo1.LandData.Name = "lo1";
@@ -149,8 +149,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
149 149
150 SceneHelpers sh = new SceneHelpers(); 150 SceneHelpers sh = new SceneHelpers();
151 LandManagementModule lmm = new LandManagementModule(); 151 LandManagementModule lmm = new LandManagementModule();
152 Scene scene = sh.SetupScene(); 152 Scene scene = sh.SetupScene();
153 SceneHelpers.SetupSceneModules(scene, lmm); 153 SceneHelpers.SetupSceneModules(scene, lmm);
154 154
155 ILandObject originalLo1 = new LandObject(userId, false, scene); 155 ILandObject originalLo1 = new LandObject(userId, false, scene);
156 originalLo1.LandData.Name = "lo1"; 156 originalLo1.LandData.Name = "lo1";
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
173 Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name)); 173 Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name));
174 Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID)); 174 Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID));
175 175
176 ILandObject loAtCoord2 176 ILandObject loAtCoord2
177 = lmm.GetLandObject((int)Constants.RegionSize - 1, (((int)Constants.RegionSize / 4) * 3) - 1); 177 = lmm.GetLandObject((int)Constants.RegionSize - 1, (((int)Constants.RegionSize / 4) * 3) - 1);
178 Assert.That(loAtCoord2.LandData.Name, Is.EqualTo(originalLo2.LandData.Name)); 178 Assert.That(loAtCoord2.LandData.Name, Is.EqualTo(originalLo2.LandData.Name));
179 Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID)); 179 Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID));
@@ -198,8 +198,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
198 198
199 SceneHelpers sh = new SceneHelpers(); 199 SceneHelpers sh = new SceneHelpers();
200 LandManagementModule lmm = new LandManagementModule(); 200 LandManagementModule lmm = new LandManagementModule();
201 Scene scene = sh.SetupScene(); 201 Scene scene = sh.SetupScene();
202 SceneHelpers.SetupSceneModules(scene, lmm); 202 SceneHelpers.SetupSceneModules(scene, lmm);
203 203
204 ILandObject originalLo1 = new LandObject(userId, false, scene); 204 ILandObject originalLo1 = new LandObject(userId, false, scene);
205 originalLo1.LandData.Name = "lo1"; 205 originalLo1.LandData.Name = "lo1";
@@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
220 { 220 {
221 ILandObject loAtCoord = lmm.GetLandObject(0, 0); 221 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
222 Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo1.LandData.Name)); 222 Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo1.LandData.Name));
223 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID)); 223 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID));
224 } 224 }
225 225
226 { 226 {
@@ -239,21 +239,21 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
239 UUID userId = TestHelpers.ParseTail(0x1); 239 UUID userId = TestHelpers.ParseTail(0x1);
240 240
241 LandManagementModule lmm = new LandManagementModule(); 241 LandManagementModule lmm = new LandManagementModule();
242 Scene scene = new SceneHelpers().SetupScene(); 242 Scene scene = new SceneHelpers().SetupScene();
243 SceneHelpers.SetupSceneModules(scene, lmm); 243 SceneHelpers.SetupSceneModules(scene, lmm);
244 244
245 ILandObject lo = new LandObject(userId, false, scene); 245 ILandObject lo = new LandObject(userId, false, scene);
246 lo.LandData.Name = "lo1"; 246 lo.LandData.Name = "lo1";
247 lo.SetLandBitmap( 247 lo.SetLandBitmap(
248 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 248 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
249 lo = lmm.AddLandObject(lo); 249 lo = lmm.AddLandObject(lo);
250 250
251 lmm.Subdivide(0, 0, LandManagementModule.LandUnit, LandManagementModule.LandUnit, userId); 251 lmm.Subdivide(0, 0, LandManagementModule.LandUnit, LandManagementModule.LandUnit, userId);
252 252
253 { 253 {
254 ILandObject loAtCoord = lmm.GetLandObject(0, 0); 254 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
255 Assert.That(loAtCoord.LandData.LocalID, Is.Not.EqualTo(lo.LandData.LocalID)); 255 Assert.That(loAtCoord.LandData.LocalID, Is.Not.EqualTo(lo.LandData.LocalID));
256 Assert.That(loAtCoord.LandData.GlobalID, Is.Not.EqualTo(lo.LandData.GlobalID)); 256 Assert.That(loAtCoord.LandData.GlobalID, Is.Not.EqualTo(lo.LandData.GlobalID));
257 } 257 }
258 258
259 { 259 {
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index 949acb6..a349aa1 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -43,21 +43,21 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
43 public class PrimCountModuleTests : OpenSimTestCase 43 public class PrimCountModuleTests : OpenSimTestCase
44 { 44 {
45 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); 45 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000");
46 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); 46 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000");
47 protected UUID m_otherUserId = new UUID("99999999-9999-9999-9999-999999999999"); 47 protected UUID m_otherUserId = new UUID("99999999-9999-9999-9999-999999999999");
48 protected TestScene m_scene; 48 protected TestScene m_scene;
49 protected PrimCountModule m_pcm; 49 protected PrimCountModule m_pcm;
50 50
51 /// <summary> 51 /// <summary>
52 /// A parcel that covers the entire sim except for a 1 unit wide strip on the eastern side. 52 /// A parcel that covers the entire sim except for a 1 unit wide strip on the eastern side.
53 /// </summary> 53 /// </summary>
54 protected ILandObject m_lo; 54 protected ILandObject m_lo;
55 55
56 /// <summary> 56 /// <summary>
57 /// A parcel that covers just the eastern strip of the sim. 57 /// A parcel that covers just the eastern strip of the sim.
58 /// </summary> 58 /// </summary>
59 protected ILandObject m_lo2; 59 protected ILandObject m_lo2;
60 60
61 [SetUp] 61 [SetUp]
62 public override void SetUp() 62 public override void SetUp()
63 { 63 {
@@ -65,24 +65,24 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
65 65
66 m_pcm = new PrimCountModule(); 66 m_pcm = new PrimCountModule();
67 LandManagementModule lmm = new LandManagementModule(); 67 LandManagementModule lmm = new LandManagementModule();
68 m_scene = new SceneHelpers().SetupScene(); 68 m_scene = new SceneHelpers().SetupScene();
69 SceneHelpers.SetupSceneModules(m_scene, lmm, m_pcm); 69 SceneHelpers.SetupSceneModules(m_scene, lmm, m_pcm);
70 70
71 int xParcelDivider = (int)Constants.RegionSize - 1; 71 int xParcelDivider = (int)Constants.RegionSize - 1;
72 72
73 ILandObject lo = new LandObject(m_userId, false, m_scene); 73 ILandObject lo = new LandObject(m_userId, false, m_scene);
74 lo.LandData.Name = "m_lo"; 74 lo.LandData.Name = "m_lo";
75 lo.SetLandBitmap( 75 lo.SetLandBitmap(
76 lo.GetSquareLandBitmap(0, 0, xParcelDivider, (int)Constants.RegionSize)); 76 lo.GetSquareLandBitmap(0, 0, xParcelDivider, (int)Constants.RegionSize));
77 m_lo = lmm.AddLandObject(lo); 77 m_lo = lmm.AddLandObject(lo);
78 78
79 ILandObject lo2 = new LandObject(m_userId, false, m_scene); 79 ILandObject lo2 = new LandObject(m_userId, false, m_scene);
80 lo2.SetLandBitmap( 80 lo2.SetLandBitmap(
81 lo2.GetSquareLandBitmap(xParcelDivider, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 81 lo2.GetSquareLandBitmap(xParcelDivider, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
82 lo2.LandData.Name = "m_lo2"; 82 lo2.LandData.Name = "m_lo2";
83 m_lo2 = lmm.AddLandObject(lo2); 83 m_lo2 = lmm.AddLandObject(lo2);
84 } 84 }
85 85
86 /// <summary> 86 /// <summary>
87 /// Test that counts before we do anything are correct. 87 /// Test that counts before we do anything are correct.
88 /// </summary> 88 /// </summary>
@@ -90,7 +90,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
90 public void TestInitialCounts() 90 public void TestInitialCounts()
91 { 91 {
92 IPrimCounts pc = m_lo.PrimCounts; 92 IPrimCounts pc = m_lo.PrimCounts;
93 93
94 Assert.That(pc.Owner, Is.EqualTo(0)); 94 Assert.That(pc.Owner, Is.EqualTo(0));
95 Assert.That(pc.Group, Is.EqualTo(0)); 95 Assert.That(pc.Group, Is.EqualTo(0));
96 Assert.That(pc.Others, Is.EqualTo(0)); 96 Assert.That(pc.Others, Is.EqualTo(0));
@@ -98,9 +98,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
98 Assert.That(pc.Selected, Is.EqualTo(0)); 98 Assert.That(pc.Selected, Is.EqualTo(0));
99 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 99 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
100 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 100 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
101 Assert.That(pc.Simulator, Is.EqualTo(0)); 101 Assert.That(pc.Simulator, Is.EqualTo(0));
102 } 102 }
103 103
104 /// <summary> 104 /// <summary>
105 /// Test count after a parcel owner owned object is added. 105 /// Test count after a parcel owner owned object is added.
106 /// </summary> 106 /// </summary>
@@ -108,13 +108,13 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
108 public void TestAddOwnerObject() 108 public void TestAddOwnerObject()
109 { 109 {
110 TestHelpers.InMethod(); 110 TestHelpers.InMethod();
111// log4net.Config.XmlConfigurator.Configure(); 111// log4net.Config.XmlConfigurator.Configure();
112 112
113 IPrimCounts pc = m_lo.PrimCounts; 113 IPrimCounts pc = m_lo.PrimCounts;
114 114
115 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 115 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
116 m_scene.AddNewSceneObject(sog, false); 116 m_scene.AddNewSceneObject(sog, false);
117 117
118 Assert.That(pc.Owner, Is.EqualTo(3)); 118 Assert.That(pc.Owner, Is.EqualTo(3));
119 Assert.That(pc.Group, Is.EqualTo(0)); 119 Assert.That(pc.Group, Is.EqualTo(0));
120 Assert.That(pc.Others, Is.EqualTo(0)); 120 Assert.That(pc.Others, Is.EqualTo(0));
@@ -122,12 +122,12 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
122 Assert.That(pc.Selected, Is.EqualTo(0)); 122 Assert.That(pc.Selected, Is.EqualTo(0));
123 Assert.That(pc.Users[m_userId], Is.EqualTo(3)); 123 Assert.That(pc.Users[m_userId], Is.EqualTo(3));
124 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 124 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
125 Assert.That(pc.Simulator, Is.EqualTo(3)); 125 Assert.That(pc.Simulator, Is.EqualTo(3));
126 126
127 // Add a second object and retest 127 // Add a second object and retest
128 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10); 128 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10);
129 m_scene.AddNewSceneObject(sog2, false); 129 m_scene.AddNewSceneObject(sog2, false);
130 130
131 Assert.That(pc.Owner, Is.EqualTo(5)); 131 Assert.That(pc.Owner, Is.EqualTo(5));
132 Assert.That(pc.Group, Is.EqualTo(0)); 132 Assert.That(pc.Group, Is.EqualTo(0));
133 Assert.That(pc.Others, Is.EqualTo(0)); 133 Assert.That(pc.Others, Is.EqualTo(0));
@@ -135,9 +135,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
135 Assert.That(pc.Selected, Is.EqualTo(0)); 135 Assert.That(pc.Selected, Is.EqualTo(0));
136 Assert.That(pc.Users[m_userId], Is.EqualTo(5)); 136 Assert.That(pc.Users[m_userId], Is.EqualTo(5));
137 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 137 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
138 Assert.That(pc.Simulator, Is.EqualTo(5)); 138 Assert.That(pc.Simulator, Is.EqualTo(5));
139 } 139 }
140 140
141 /// <summary> 141 /// <summary>
142 /// Test count after a parcel owner owned copied object is added. 142 /// Test count after a parcel owner owned copied object is added.
143 /// </summary> 143 /// </summary>
@@ -145,14 +145,14 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
145 public void TestCopyOwnerObject() 145 public void TestCopyOwnerObject()
146 { 146 {
147 TestHelpers.InMethod(); 147 TestHelpers.InMethod();
148// log4net.Config.XmlConfigurator.Configure(); 148// log4net.Config.XmlConfigurator.Configure();
149 149
150 IPrimCounts pc = m_lo.PrimCounts; 150 IPrimCounts pc = m_lo.PrimCounts;
151 151
152 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 152 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
153 m_scene.AddNewSceneObject(sog, false); 153 m_scene.AddNewSceneObject(sog, false);
154 m_scene.SceneGraph.DuplicateObject(sog.LocalId, Vector3.Zero, 0, m_userId, UUID.Zero, Quaternion.Identity); 154 m_scene.SceneGraph.DuplicateObject(sog.LocalId, Vector3.Zero, m_userId, UUID.Zero, Quaternion.Identity, false);
155 155
156 Assert.That(pc.Owner, Is.EqualTo(6)); 156 Assert.That(pc.Owner, Is.EqualTo(6));
157 Assert.That(pc.Group, Is.EqualTo(0)); 157 Assert.That(pc.Group, Is.EqualTo(0));
158 Assert.That(pc.Others, Is.EqualTo(0)); 158 Assert.That(pc.Others, Is.EqualTo(0));
@@ -160,9 +160,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
160 Assert.That(pc.Selected, Is.EqualTo(0)); 160 Assert.That(pc.Selected, Is.EqualTo(0));
161 Assert.That(pc.Users[m_userId], Is.EqualTo(6)); 161 Assert.That(pc.Users[m_userId], Is.EqualTo(6));
162 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 162 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
163 Assert.That(pc.Simulator, Is.EqualTo(6)); 163 Assert.That(pc.Simulator, Is.EqualTo(6));
164 } 164 }
165 165
166 /// <summary> 166 /// <summary>
167 /// Test that parcel counts update correctly when an object is moved between parcels, where that movement 167 /// Test that parcel counts update correctly when an object is moved between parcels, where that movement
168 /// is not done directly by the user/ 168 /// is not done directly by the user/
@@ -171,18 +171,18 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
171 public void TestMoveOwnerObject() 171 public void TestMoveOwnerObject()
172 { 172 {
173 TestHelpers.InMethod(); 173 TestHelpers.InMethod();
174// log4net.Config.XmlConfigurator.Configure(); 174// log4net.Config.XmlConfigurator.Configure();
175 175
176 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 176 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
177 m_scene.AddNewSceneObject(sog, false); 177 m_scene.AddNewSceneObject(sog, false);
178 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10); 178 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10);
179 m_scene.AddNewSceneObject(sog2, false); 179 m_scene.AddNewSceneObject(sog2, false);
180 180
181 // Move the first scene object to the eastern strip parcel 181 // Move the first scene object to the eastern strip parcel
182 sog.AbsolutePosition = new Vector3(254, 2, 2); 182 sog.AbsolutePosition = new Vector3(254, 2, 2);
183 183
184 IPrimCounts pclo1 = m_lo.PrimCounts; 184 IPrimCounts pclo1 = m_lo.PrimCounts;
185 185
186 Assert.That(pclo1.Owner, Is.EqualTo(2)); 186 Assert.That(pclo1.Owner, Is.EqualTo(2));
187 Assert.That(pclo1.Group, Is.EqualTo(0)); 187 Assert.That(pclo1.Group, Is.EqualTo(0));
188 Assert.That(pclo1.Others, Is.EqualTo(0)); 188 Assert.That(pclo1.Others, Is.EqualTo(0));
@@ -190,10 +190,10 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
190 Assert.That(pclo1.Selected, Is.EqualTo(0)); 190 Assert.That(pclo1.Selected, Is.EqualTo(0));
191 Assert.That(pclo1.Users[m_userId], Is.EqualTo(2)); 191 Assert.That(pclo1.Users[m_userId], Is.EqualTo(2));
192 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0)); 192 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0));
193 Assert.That(pclo1.Simulator, Is.EqualTo(5)); 193 Assert.That(pclo1.Simulator, Is.EqualTo(5));
194 194
195 IPrimCounts pclo2 = m_lo2.PrimCounts; 195 IPrimCounts pclo2 = m_lo2.PrimCounts;
196 196
197 Assert.That(pclo2.Owner, Is.EqualTo(3)); 197 Assert.That(pclo2.Owner, Is.EqualTo(3));
198 Assert.That(pclo2.Group, Is.EqualTo(0)); 198 Assert.That(pclo2.Group, Is.EqualTo(0));
199 Assert.That(pclo2.Others, Is.EqualTo(0)); 199 Assert.That(pclo2.Others, Is.EqualTo(0));
@@ -201,11 +201,11 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
201 Assert.That(pclo2.Selected, Is.EqualTo(0)); 201 Assert.That(pclo2.Selected, Is.EqualTo(0));
202 Assert.That(pclo2.Users[m_userId], Is.EqualTo(3)); 202 Assert.That(pclo2.Users[m_userId], Is.EqualTo(3));
203 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0)); 203 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0));
204 Assert.That(pclo2.Simulator, Is.EqualTo(5)); 204 Assert.That(pclo2.Simulator, Is.EqualTo(5));
205 205
206 // Now move it back again 206 // Now move it back again
207 sog.AbsolutePosition = new Vector3(2, 2, 2); 207 sog.AbsolutePosition = new Vector3(2, 2, 2);
208 208
209 Assert.That(pclo1.Owner, Is.EqualTo(5)); 209 Assert.That(pclo1.Owner, Is.EqualTo(5));
210 Assert.That(pclo1.Group, Is.EqualTo(0)); 210 Assert.That(pclo1.Group, Is.EqualTo(0));
211 Assert.That(pclo1.Others, Is.EqualTo(0)); 211 Assert.That(pclo1.Others, Is.EqualTo(0));
@@ -213,8 +213,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
213 Assert.That(pclo1.Selected, Is.EqualTo(0)); 213 Assert.That(pclo1.Selected, Is.EqualTo(0));
214 Assert.That(pclo1.Users[m_userId], Is.EqualTo(5)); 214 Assert.That(pclo1.Users[m_userId], Is.EqualTo(5));
215 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0)); 215 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0));
216 Assert.That(pclo1.Simulator, Is.EqualTo(5)); 216 Assert.That(pclo1.Simulator, Is.EqualTo(5));
217 217
218 Assert.That(pclo2.Owner, Is.EqualTo(0)); 218 Assert.That(pclo2.Owner, Is.EqualTo(0));
219 Assert.That(pclo2.Group, Is.EqualTo(0)); 219 Assert.That(pclo2.Group, Is.EqualTo(0));
220 Assert.That(pclo2.Others, Is.EqualTo(0)); 220 Assert.That(pclo2.Others, Is.EqualTo(0));
@@ -222,9 +222,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
222 Assert.That(pclo2.Selected, Is.EqualTo(0)); 222 Assert.That(pclo2.Selected, Is.EqualTo(0));
223 Assert.That(pclo2.Users[m_userId], Is.EqualTo(0)); 223 Assert.That(pclo2.Users[m_userId], Is.EqualTo(0));
224 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0)); 224 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0));
225 Assert.That(pclo2.Simulator, Is.EqualTo(5)); 225 Assert.That(pclo2.Simulator, Is.EqualTo(5));
226 } 226 }
227 227
228 /// <summary> 228 /// <summary>
229 /// Test count after a parcel owner owned object is removed. 229 /// Test count after a parcel owner owned object is removed.
230 /// </summary> 230 /// </summary>
@@ -233,14 +233,14 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
233 { 233 {
234 TestHelpers.InMethod(); 234 TestHelpers.InMethod();
235// log4net.Config.XmlConfigurator.Configure(); 235// log4net.Config.XmlConfigurator.Configure();
236 236
237 IPrimCounts pc = m_lo.PrimCounts; 237 IPrimCounts pc = m_lo.PrimCounts;
238 238
239 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1), false); 239 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1), false);
240 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10); 240 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10);
241 m_scene.AddNewSceneObject(sogToDelete, false); 241 m_scene.AddNewSceneObject(sogToDelete, false);
242 m_scene.DeleteSceneObject(sogToDelete, false); 242 m_scene.DeleteSceneObject(sogToDelete, false);
243 243
244 Assert.That(pc.Owner, Is.EqualTo(1)); 244 Assert.That(pc.Owner, Is.EqualTo(1));
245 Assert.That(pc.Group, Is.EqualTo(0)); 245 Assert.That(pc.Group, Is.EqualTo(0));
246 Assert.That(pc.Others, Is.EqualTo(0)); 246 Assert.That(pc.Others, Is.EqualTo(0));
@@ -248,37 +248,37 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
248 Assert.That(pc.Selected, Is.EqualTo(0)); 248 Assert.That(pc.Selected, Is.EqualTo(0));
249 Assert.That(pc.Users[m_userId], Is.EqualTo(1)); 249 Assert.That(pc.Users[m_userId], Is.EqualTo(1));
250 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 250 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
251 Assert.That(pc.Simulator, Is.EqualTo(1)); 251 Assert.That(pc.Simulator, Is.EqualTo(1));
252 } 252 }
253 253
254 [Test] 254 [Test]
255 public void TestAddGroupObject() 255 public void TestAddGroupObject()
256 { 256 {
257 TestHelpers.InMethod(); 257 TestHelpers.InMethod();
258// log4net.Config.XmlConfigurator.Configure(); 258// log4net.Config.XmlConfigurator.Configure();
259 259
260 m_lo.DeedToGroup(m_groupId); 260 m_lo.DeedToGroup(m_groupId);
261 261
262 IPrimCounts pc = m_lo.PrimCounts; 262 IPrimCounts pc = m_lo.PrimCounts;
263 263
264 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01); 264 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01);
265 sog.GroupID = m_groupId; 265 sog.GroupID = m_groupId;
266 m_scene.AddNewSceneObject(sog, false); 266 m_scene.AddNewSceneObject(sog, false);
267 267
268 Assert.That(pc.Owner, Is.EqualTo(0)); 268 Assert.That(pc.Owner, Is.EqualTo(0));
269 Assert.That(pc.Group, Is.EqualTo(3)); 269 Assert.That(pc.Group, Is.EqualTo(3));
270 Assert.That(pc.Others, Is.EqualTo(0)); 270 Assert.That(pc.Others, Is.EqualTo(0));
271 Assert.That(pc.Total, Is.EqualTo(3)); 271 Assert.That(pc.Total, Is.EqualTo(3));
272 Assert.That(pc.Selected, Is.EqualTo(0)); 272 Assert.That(pc.Selected, Is.EqualTo(0));
273 273
274 // Is this desired behaviour? Not totally sure. 274 // Is this desired behaviour? Not totally sure.
275 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 275 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
276 Assert.That(pc.Users[m_groupId], Is.EqualTo(0)); 276 Assert.That(pc.Users[m_groupId], Is.EqualTo(0));
277 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3)); 277 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3));
278 278
279 Assert.That(pc.Simulator, Is.EqualTo(3)); 279 Assert.That(pc.Simulator, Is.EqualTo(3));
280 } 280 }
281 281
282 /// <summary> 282 /// <summary>
283 /// Test count after a parcel owner owned object is removed. 283 /// Test count after a parcel owner owned object is removed.
284 /// </summary> 284 /// </summary>
@@ -287,19 +287,19 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
287 { 287 {
288 TestHelpers.InMethod(); 288 TestHelpers.InMethod();
289// log4net.Config.XmlConfigurator.Configure(); 289// log4net.Config.XmlConfigurator.Configure();
290 290
291 m_lo.DeedToGroup(m_groupId); 291 m_lo.DeedToGroup(m_groupId);
292 292
293 IPrimCounts pc = m_lo.PrimCounts; 293 IPrimCounts pc = m_lo.PrimCounts;
294 294
295 SceneObjectGroup sogToKeep = SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1); 295 SceneObjectGroup sogToKeep = SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1);
296 sogToKeep.GroupID = m_groupId; 296 sogToKeep.GroupID = m_groupId;
297 m_scene.AddNewSceneObject(sogToKeep, false); 297 m_scene.AddNewSceneObject(sogToKeep, false);
298 298
299 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10); 299 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10);
300 m_scene.AddNewSceneObject(sogToDelete, false); 300 m_scene.AddNewSceneObject(sogToDelete, false);
301 m_scene.DeleteSceneObject(sogToDelete, false); 301 m_scene.DeleteSceneObject(sogToDelete, false);
302 302
303 Assert.That(pc.Owner, Is.EqualTo(0)); 303 Assert.That(pc.Owner, Is.EqualTo(0));
304 Assert.That(pc.Group, Is.EqualTo(1)); 304 Assert.That(pc.Group, Is.EqualTo(1));
305 Assert.That(pc.Others, Is.EqualTo(0)); 305 Assert.That(pc.Others, Is.EqualTo(0));
@@ -308,20 +308,20 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
308 Assert.That(pc.Users[m_userId], Is.EqualTo(1)); 308 Assert.That(pc.Users[m_userId], Is.EqualTo(1));
309 Assert.That(pc.Users[m_groupId], Is.EqualTo(0)); 309 Assert.That(pc.Users[m_groupId], Is.EqualTo(0));
310 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 310 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
311 Assert.That(pc.Simulator, Is.EqualTo(1)); 311 Assert.That(pc.Simulator, Is.EqualTo(1));
312 } 312 }
313 313
314 [Test] 314 [Test]
315 public void TestAddOthersObject() 315 public void TestAddOthersObject()
316 { 316 {
317 TestHelpers.InMethod(); 317 TestHelpers.InMethod();
318// log4net.Config.XmlConfigurator.Configure(); 318// log4net.Config.XmlConfigurator.Configure();
319 319
320 IPrimCounts pc = m_lo.PrimCounts; 320 IPrimCounts pc = m_lo.PrimCounts;
321 321
322 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01); 322 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01);
323 m_scene.AddNewSceneObject(sog, false); 323 m_scene.AddNewSceneObject(sog, false);
324 324
325 Assert.That(pc.Owner, Is.EqualTo(0)); 325 Assert.That(pc.Owner, Is.EqualTo(0));
326 Assert.That(pc.Group, Is.EqualTo(0)); 326 Assert.That(pc.Group, Is.EqualTo(0));
327 Assert.That(pc.Others, Is.EqualTo(3)); 327 Assert.That(pc.Others, Is.EqualTo(3));
@@ -329,22 +329,22 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
329 Assert.That(pc.Selected, Is.EqualTo(0)); 329 Assert.That(pc.Selected, Is.EqualTo(0));
330 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 330 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
331 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3)); 331 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3));
332 Assert.That(pc.Simulator, Is.EqualTo(3)); 332 Assert.That(pc.Simulator, Is.EqualTo(3));
333 } 333 }
334 334
335 [Test] 335 [Test]
336 public void TestRemoveOthersObject() 336 public void TestRemoveOthersObject()
337 { 337 {
338 TestHelpers.InMethod(); 338 TestHelpers.InMethod();
339// log4net.Config.XmlConfigurator.Configure(); 339// log4net.Config.XmlConfigurator.Configure();
340 340
341 IPrimCounts pc = m_lo.PrimCounts; 341 IPrimCounts pc = m_lo.PrimCounts;
342 342
343 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_otherUserId, "a", 0x1), false); 343 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_otherUserId, "a", 0x1), false);
344 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_otherUserId, "b", 0x10); 344 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_otherUserId, "b", 0x10);
345 m_scene.AddNewSceneObject(sogToDelete, false); 345 m_scene.AddNewSceneObject(sogToDelete, false);
346 m_scene.DeleteSceneObject(sogToDelete, false); 346 m_scene.DeleteSceneObject(sogToDelete, false);
347 347
348 Assert.That(pc.Owner, Is.EqualTo(0)); 348 Assert.That(pc.Owner, Is.EqualTo(0));
349 Assert.That(pc.Group, Is.EqualTo(0)); 349 Assert.That(pc.Group, Is.EqualTo(0));
350 Assert.That(pc.Others, Is.EqualTo(1)); 350 Assert.That(pc.Others, Is.EqualTo(1));
@@ -352,9 +352,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
352 Assert.That(pc.Selected, Is.EqualTo(0)); 352 Assert.That(pc.Selected, Is.EqualTo(0));
353 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 353 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
354 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(1)); 354 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(1));
355 Assert.That(pc.Simulator, Is.EqualTo(1)); 355 Assert.That(pc.Simulator, Is.EqualTo(1));
356 } 356 }
357 357
358 /// <summary> 358 /// <summary>
359 /// Test the count is correct after is has been tainted. 359 /// Test the count is correct after is has been tainted.
360 /// </summary> 360 /// </summary>
@@ -363,12 +363,12 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
363 { 363 {
364 TestHelpers.InMethod(); 364 TestHelpers.InMethod();
365 IPrimCounts pc = m_lo.PrimCounts; 365 IPrimCounts pc = m_lo.PrimCounts;
366 366
367 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 367 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
368 m_scene.AddNewSceneObject(sog, false); 368 m_scene.AddNewSceneObject(sog, false);
369 369
370 m_pcm.TaintPrimCount(); 370 m_pcm.TaintPrimCount();
371 371
372 Assert.That(pc.Owner, Is.EqualTo(3)); 372 Assert.That(pc.Owner, Is.EqualTo(3));
373 Assert.That(pc.Group, Is.EqualTo(0)); 373 Assert.That(pc.Group, Is.EqualTo(0));
374 Assert.That(pc.Others, Is.EqualTo(0)); 374 Assert.That(pc.Others, Is.EqualTo(0));
@@ -376,7 +376,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
376 Assert.That(pc.Selected, Is.EqualTo(0)); 376 Assert.That(pc.Selected, Is.EqualTo(0));
377 Assert.That(pc.Users[m_userId], Is.EqualTo(3)); 377 Assert.That(pc.Users[m_userId], Is.EqualTo(3));
378 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 378 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
379 Assert.That(pc.Simulator, Is.EqualTo(3)); 379 Assert.That(pc.Simulator, Is.EqualTo(3));
380 } 380 }
381 } 381 }
382} \ No newline at end of file 382} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 796a15f..1e63662 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -73,6 +73,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
73 73
74 #region IMapImageGenerator Members 74 #region IMapImageGenerator Members
75 75
76 public Bitmap CreateMapTileForce()
77 {
78 return CreateMapTile();
79 }
76 public Bitmap CreateMapTile() 80 public Bitmap CreateMapTile()
77 { 81 {
78 bool drawPrimVolume = true; 82 bool drawPrimVolume = true;
@@ -82,11 +86,11 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
82 86
83 string[] configSections = new string[] { "Map", "Startup" }; 87 string[] configSections = new string[] { "Map", "Startup" };
84 88
85 drawPrimVolume 89 drawPrimVolume
86 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume); 90 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
87 textureTerrain 91 textureTerrain
88 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain); 92 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
89 generateMaptiles 93 generateMaptiles
90 = Util.GetConfigVarFromSections<bool>(m_config, "GenerateMaptiles", configSections, generateMaptiles); 94 = Util.GetConfigVarFromSections<bool>(m_config, "GenerateMaptiles", configSections, generateMaptiles);
91 95
92 if (generateMaptiles) 96 if (generateMaptiles)
@@ -112,7 +116,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
112 //} 116 //}
113 //t = System.Environment.TickCount - t; 117 //t = System.Environment.TickCount - t;
114 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); 118 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
115
116 if (drawPrimVolume) 119 if (drawPrimVolume)
117 { 120 {
118 DrawObjectVolume(m_scene, mapbmp); 121 DrawObjectVolume(m_scene, mapbmp);
@@ -127,15 +130,15 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
127 catch (Exception) 130 catch (Exception)
128 { 131 {
129 m_log.ErrorFormat( 132 m_log.ErrorFormat(
130 "[MAPTILE]: Failed to load Static map image texture file: {0} for {1}", 133 "[MAPTILE]: Failed to load Static map image texture file: {0} for {1}",
131 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name); 134 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name);
132 //mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 135 //mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
133 mapbmp = null; 136 mapbmp = null;
134 } 137 }
135 138
136 if (mapbmp != null) 139 if (mapbmp != null)
137 m_log.DebugFormat( 140 m_log.DebugFormat(
138 "[MAPTILE]: Static map image texture file {0} found for {1}", 141 "[MAPTILE]: Static map image texture file {0} found for {1}",
139 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name); 142 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name);
140 } 143 }
141 } 144 }
@@ -309,7 +312,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
309 List<uint> z_localIDs = new List<uint>(); 312 List<uint> z_localIDs = new List<uint>();
310 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>(); 313 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
311 314
312 try 315 try
313 { 316 {
314 lock (objs) 317 lock (objs)
315 { 318 {
@@ -383,7 +386,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
383 386
384 Vector3 pos = part.GetWorldPosition(); 387 Vector3 pos = part.GetWorldPosition();
385 388
386 // skip prim outside of retion 389 // skip prim outside of region
387 if (!m_scene.PositionIsInCurrentRegion(pos)) 390 if (!m_scene.PositionIsInCurrentRegion(pos))
388 continue; 391 continue;
389 392
@@ -407,12 +410,13 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
407 { 410 {
408 // Translate scale by rotation so scale is represented properly when object is rotated 411 // Translate scale by rotation so scale is represented properly when object is rotated
409 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z); 412 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
413 lscale *= 0.5f;
414
410 Vector3 scale = new Vector3(); 415 Vector3 scale = new Vector3();
411 Vector3 tScale = new Vector3(); 416 Vector3 tScale = new Vector3();
412 Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z); 417 Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z);
413 418
414 Quaternion llrot = part.GetWorldRotation(); 419 Quaternion rot = part.GetWorldRotation();
415 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
416 scale = lscale * rot; 420 scale = lscale * rot;
417 421
418 // negative scales don't work in this situation 422 // negative scales don't work in this situation
@@ -471,7 +475,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
471 475
472 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z); 476 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
473 scale = ((tScale * rot)); 477 scale = ((tScale * rot));
474
475 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); 478 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
476 479
477 //vertexes[2].x = pos.X + vertexes[2].x; 480 //vertexes[2].x = pos.X + vertexes[2].x;
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index 708286c..0b37179 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -38,18 +38,20 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
38{ 38{
39 public class ShadedMapTileRenderer : IMapTileTerrainRenderer 39 public class ShadedMapTileRenderer : IMapTileTerrainRenderer
40 { 40 {
41 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
42
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]"; 42 private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]";
45 43
46 private Scene m_scene; 44 private Scene m_scene;
47 //private IConfigSource m_config; // not used currently 45 private IConfigSource m_config;
46 private Color m_color_water;
48 47
49 public void Initialise(Scene scene, IConfigSource config) 48 public void Initialise(Scene scene, IConfigSource config)
50 { 49 {
51 m_scene = scene; 50 m_scene = scene;
52 // m_config = config; // not used currently 51 m_config = config;
52
53 string[] configSections = new string[] { "Map", "Startup" };
54 m_color_water = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColorWater", configSections, "#1D475F"));
53 } 55 }
54 56
55 public void TerrainToBitmap(Bitmap mapbmp) 57 public void TerrainToBitmap(Bitmap mapbmp)
@@ -231,7 +233,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
231 233
232 try 234 try
233 { 235 {
234 mapbmp.SetPixel(x, yr, WATER_COLOR); 236 mapbmp.SetPixel(x, yr, m_color_water);
235 } 237 }
236 catch (ArgumentException) 238 catch (ArgumentException)
237 { 239 {
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index 9f23141..c71f5c0 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -130,21 +130,19 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
130 // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank"). 130 // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank").
131 // The color-values were choosen because they "look right" (at least to me) ;-) 131 // The color-values were choosen because they "look right" (at least to me) ;-)
132 private static readonly UUID defaultTerrainTexture1 = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5"); 132 private static readonly UUID defaultTerrainTexture1 = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5");
133 private static readonly Color defaultColor1 = Color.FromArgb(165, 137, 118);
134 private static readonly UUID defaultTerrainTexture2 = new UUID("63338ede-0037-c4fd-855b-015d77112fc8"); 133 private static readonly UUID defaultTerrainTexture2 = new UUID("63338ede-0037-c4fd-855b-015d77112fc8");
135 private static readonly Color defaultColor2 = Color.FromArgb(69, 89, 49);
136 private static readonly UUID defaultTerrainTexture3 = new UUID("303cd381-8560-7579-23f1-f0a880799740"); 134 private static readonly UUID defaultTerrainTexture3 = new UUID("303cd381-8560-7579-23f1-f0a880799740");
137 private static readonly Color defaultColor3 = Color.FromArgb(162, 154, 141);
138 private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c"); 135 private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c");
139 private static readonly Color defaultColor4 = Color.FromArgb(200, 200, 200);
140
141 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
142 136
143 #endregion 137 #endregion
144 138
145
146 private Scene m_scene; 139 private Scene m_scene;
147 // private IConfigSource m_config; // not used currently 140 private IConfigSource m_config;
141 private Color m_color_water;
142 private Color m_color_1;
143 private Color m_color_2;
144 private Color m_color_3;
145 private Color m_color_4;
148 146
149 // mapping from texture UUIDs to averaged color. This will contain 5-9 values, in general; new values are only 147 // mapping from texture UUIDs to averaged color. This will contain 5-9 values, in general; new values are only
150 // added when the terrain textures are changed in the estate dialog and a new map is generated (and will stay in 148 // added when the terrain textures are changed in the estate dialog and a new map is generated (and will stay in
@@ -156,12 +154,21 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
156 public void Initialise(Scene scene, IConfigSource source) 154 public void Initialise(Scene scene, IConfigSource source)
157 { 155 {
158 m_scene = scene; 156 m_scene = scene;
159 // m_config = source; // not used currently 157 m_config = source;
158
159 string[] configSections = new string[] { "Map", "Startup" };
160
161 m_color_water = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColorWater", configSections, "#1D475F"));
162 m_color_1 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor1", configSections, "#A58976"));
163 m_color_2 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor2", configSections, "#455931"));
164 m_color_3 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor3", configSections, "#A29A8D"));
165 m_color_4 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor4", configSections, "#C8C8C8"));
166
160 m_mapping = new Dictionary<UUID,Color>(); 167 m_mapping = new Dictionary<UUID,Color>();
161 m_mapping.Add(defaultTerrainTexture1, defaultColor1); 168 m_mapping.Add(defaultTerrainTexture1, m_color_1);
162 m_mapping.Add(defaultTerrainTexture2, defaultColor2); 169 m_mapping.Add(defaultTerrainTexture2, m_color_2);
163 m_mapping.Add(defaultTerrainTexture3, defaultColor3); 170 m_mapping.Add(defaultTerrainTexture3, m_color_3);
164 m_mapping.Add(defaultTerrainTexture4, defaultColor4); 171 m_mapping.Add(defaultTerrainTexture4, m_color_4);
165 m_mapping.Add(Util.BLANK_TEXTURE_UUID, Color.White); 172 m_mapping.Add(Util.BLANK_TEXTURE_UUID, Color.White);
166 } 173 }
167 174
@@ -180,7 +187,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
180 187
181 ManagedImage managedImage; 188 ManagedImage managedImage;
182 Image image; 189 Image image;
183 190
184 try 191 try
185 { 192 {
186 if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image)) 193 if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image))
@@ -201,7 +208,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
201 m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id); 208 m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id);
202 } 209 }
203 return null; 210 return null;
204 211
205 } 212 }
206 213
207 // Compute the average color of a texture. 214 // Compute the average color of a texture.
@@ -288,7 +295,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
288 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height) 295 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
289 { 296 {
290 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>", 297 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
291 LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height); 298 "[TEXTURED MAP TILE RENDERER]", mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
292 } 299 }
293 300
294 // These textures should be in the AssetCache anyway, as every client conneting to this 301 // These textures should be in the AssetCache anyway, as every client conneting to this
@@ -298,10 +305,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
298 RegionSettings settings = m_scene.RegionInfo.RegionSettings; 305 RegionSettings settings = m_scene.RegionInfo.RegionSettings;
299 306
300 // the four terrain colors as HSVs for interpolation 307 // the four terrain colors as HSVs for interpolation
301 HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, defaultColor1)); 308 HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, m_color_1));
302 HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, defaultColor2)); 309 HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, m_color_2));
303 HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, defaultColor3)); 310 HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, m_color_3));
304 HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, defaultColor4)); 311 HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, m_color_4));
305 312
306 float levelNElow = (float)settings.Elevation1NE; 313 float levelNElow = (float)settings.Elevation1NE;
307 float levelNEhigh = (float)settings.Elevation2NE; 314 float levelNEhigh = (float)settings.Elevation2NE;
@@ -371,8 +378,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
371 // first, rescale h to 0.0 - 1.0 378 // first, rescale h to 0.0 - 1.0
372 hmod = (hmod - low) / (high - low); 379 hmod = (hmod - low) / (high - low);
373 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 380 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4
374 if (hmod < 1f/3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f); 381 if (hmod < 1f / 3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f);
375 else if (hmod < 2f/3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f); 382 else if (hmod < 2f / 3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f);
376 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f); 383 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f);
377 } 384 }
378 385
@@ -417,7 +424,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
417 424
418 heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0 425 heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0
419 426
420 mapbmp.SetPixel(x, yr, WATER_COLOR); 427 mapbmp.SetPixel(x, yr, m_color_water);
421 } 428 }
422 } 429 }
423 } 430 }
diff --git a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
index 0a4e83e..f13d648 100644
--- a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
+++ b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
@@ -190,6 +190,9 @@ namespace OpenSim.Region.CoreModules.World.LightShare
190 190
191 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl) 191 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl)
192 { 192 {
193 if (client == null)
194 return;
195
193 if (m_enableWindlight) 196 if (m_enableWindlight)
194 { 197 {
195 if (m_scene.RegionInfo.WindlightSettings.valid) 198 if (m_scene.RegionInfo.WindlightSettings.valid)
@@ -207,8 +210,8 @@ namespace OpenSim.Region.CoreModules.World.LightShare
207 210
208 private void EventManager_OnMakeRootAgent(ScenePresence presence) 211 private void EventManager_OnMakeRootAgent(ScenePresence presence)
209 { 212 {
210// m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client {0}", presence.Name); 213 if (m_enableWindlight && m_scene.RegionInfo.WindlightSettings.valid)
211 214 m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client");
212 SendProfileToClient(presence.ControllingClient); 215 SendProfileToClient(presence.ControllingClient);
213 } 216 }
214 217
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
index 46b0470..f5aa40a 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
56 public class MoapModule : INonSharedRegionModule, IMoapModule 56 public class MoapModule : INonSharedRegionModule, IMoapModule
57 { 57 {
58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 59
60 public string Name { get { return "MoapModule"; } } 60 public string Name { get { return "MoapModule"; } }
61 public Type ReplaceableInterface { get { return null; } } 61 public Type ReplaceableInterface { get { return null; } }
62 62
@@ -64,33 +64,33 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
64 /// Is this module enabled? 64 /// Is this module enabled?
65 /// </summary> 65 /// </summary>
66 protected bool m_isEnabled = true; 66 protected bool m_isEnabled = true;
67 67
68 /// <summary> 68 /// <summary>
69 /// The scene to which this module is attached 69 /// The scene to which this module is attached
70 /// </summary> 70 /// </summary>
71 protected Scene m_scene; 71 protected Scene m_scene;
72 72
73 /// <summary> 73 /// <summary>
74 /// Track the ObjectMedia capabilities given to users keyed by path 74 /// Track the ObjectMedia capabilities given to users keyed by path
75 /// </summary> 75 /// </summary>
76 protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>(); 76 protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>();
77 77
78 /// <summary> 78 /// <summary>
79 /// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate. 79 /// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate.
80 /// </summary> 80 /// </summary>
81 protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>(); 81 protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>();
82 82
83 /// <summary> 83 /// <summary>
84 /// Track the ObjectMediaUpdate capabilities given to users keyed by path 84 /// Track the ObjectMediaUpdate capabilities given to users keyed by path
85 /// </summary> 85 /// </summary>
86 protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>(); 86 protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>();
87 87
88 /// <summary> 88 /// <summary>
89 /// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate 89 /// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate
90 /// </summary> 90 /// </summary>
91 protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>(); 91 protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>();
92 92
93 public void Initialise(IConfigSource configSource) 93 public void Initialise(IConfigSource configSource)
94 { 94 {
95 IConfig config = configSource.Configs["MediaOnAPrim"]; 95 IConfig config = configSource.Configs["MediaOnAPrim"];
96 96
@@ -100,63 +100,63 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
100// m_log.Debug("[MOAP]: Initialised module.")l 100// m_log.Debug("[MOAP]: Initialised module.")l
101 } 101 }
102 102
103 public void AddRegion(Scene scene) 103 public void AddRegion(Scene scene)
104 { 104 {
105 if (!m_isEnabled) 105 if (!m_isEnabled)
106 return; 106 return;
107 107
108 m_scene = scene; 108 m_scene = scene;
109 m_scene.RegisterModuleInterface<IMoapModule>(this); 109 m_scene.RegisterModuleInterface<IMoapModule>(this);
110 } 110 }
111 111
112 public void RemoveRegion(Scene scene) {} 112 public void RemoveRegion(Scene scene) {}
113 113
114 public void RegionLoaded(Scene scene) 114 public void RegionLoaded(Scene scene)
115 { 115 {
116 if (!m_isEnabled) 116 if (!m_isEnabled)
117 return; 117 return;
118 118
119 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 119 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
120 m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps; 120 m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps;
121 m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy; 121 m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy;
122 } 122 }
123 123
124 public void Close() 124 public void Close()
125 { 125 {
126 if (!m_isEnabled) 126 if (!m_isEnabled)
127 return; 127 return;
128 128
129 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 129 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
130 m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps; 130 m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps;
131 m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy; 131 m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy;
132 } 132 }
133 133
134 public void OnRegisterCaps(UUID agentID, Caps caps) 134 public void OnRegisterCaps(UUID agentID, Caps caps)
135 { 135 {
136// m_log.DebugFormat( 136// m_log.DebugFormat(
137// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID); 137// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID);
138 138
139 string omCapUrl = "/CAPS/" + UUID.Random(); 139 string omCapUrl = "/CAPS/" + UUID.Random();
140 140
141 lock (m_omCapUsers) 141 lock (m_omCapUsers)
142 { 142 {
143 m_omCapUsers[omCapUrl] = agentID; 143 m_omCapUsers[omCapUrl] = agentID;
144 m_omCapUrls[agentID] = omCapUrl; 144 m_omCapUrls[agentID] = omCapUrl;
145 145
146 // Even though we're registering for POST we're going to get GETS and UPDATES too 146 // Even though we're registering for POST we're going to get GETS and UPDATES too
147 caps.RegisterHandler( 147 caps.RegisterHandler(
148 "ObjectMedia", 148 "ObjectMedia",
149 new RestStreamHandler( 149 new RestStreamHandler(
150 "POST", omCapUrl, HandleObjectMediaMessage, "ObjectMedia", agentID.ToString())); 150 "POST", omCapUrl, HandleObjectMediaMessage, "ObjectMedia", agentID.ToString()));
151 } 151 }
152 152
153 string omuCapUrl = "/CAPS/" + UUID.Random(); 153 string omuCapUrl = "/CAPS/" + UUID.Random();
154 154
155 lock (m_omuCapUsers) 155 lock (m_omuCapUsers)
156 { 156 {
157 m_omuCapUsers[omuCapUrl] = agentID; 157 m_omuCapUsers[omuCapUrl] = agentID;
158 m_omuCapUrls[agentID] = omuCapUrl; 158 m_omuCapUrls[agentID] = omuCapUrl;
159 159
160 // Even though we're registering for POST we're going to get GETS and UPDATES too 160 // Even though we're registering for POST we're going to get GETS and UPDATES too
161 caps.RegisterHandler( 161 caps.RegisterHandler(
162 "ObjectMediaNavigate", 162 "ObjectMediaNavigate",
@@ -164,7 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
164 "POST", omuCapUrl, HandleObjectMediaNavigateMessage, "ObjectMediaNavigate", agentID.ToString())); 164 "POST", omuCapUrl, HandleObjectMediaNavigateMessage, "ObjectMediaNavigate", agentID.ToString()));
165 } 165 }
166 } 166 }
167 167
168 public void OnDeregisterCaps(UUID agentID, Caps caps) 168 public void OnDeregisterCaps(UUID agentID, Caps caps)
169 { 169 {
170 lock (m_omCapUsers) 170 lock (m_omCapUsers)
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
173 m_omCapUrls.Remove(agentID); 173 m_omCapUrls.Remove(agentID);
174 m_omCapUsers.Remove(path); 174 m_omCapUsers.Remove(path);
175 } 175 }
176 176
177 lock (m_omuCapUsers) 177 lock (m_omuCapUsers)
178 { 178 {
179 string path = m_omuCapUrls[agentID]; 179 string path = m_omuCapUrls[agentID];
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
181 m_omuCapUsers.Remove(path); 181 m_omuCapUsers.Remove(path);
182 } 182 }
183 } 183 }
184 184
185 protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed) 185 protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
186 { 186 {
187 if (original.Shape.Media != null) 187 if (original.Shape.Media != null)
@@ -197,19 +197,19 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
197 dupeMedia.Add(null); 197 dupeMedia.Add(null);
198 } 198 }
199 } 199 }
200 200
201 copy.Shape.Media = dupeMedia; 201 copy.Shape.Media = dupeMedia;
202 } 202 }
203 } 203 }
204 204
205 public MediaEntry GetMediaEntry(SceneObjectPart part, int face) 205 public MediaEntry GetMediaEntry(SceneObjectPart part, int face)
206 { 206 {
207 MediaEntry me = null; 207 MediaEntry me = null;
208 208
209 CheckFaceParam(part, face); 209 CheckFaceParam(part, face);
210 210
211 List<MediaEntry> media = part.Shape.Media; 211 List<MediaEntry> media = part.Shape.Media;
212 212
213 if (null == media) 213 if (null == media)
214 { 214 {
215 me = null; 215 me = null;
@@ -218,17 +218,17 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
218 { 218 {
219 lock (media) 219 lock (media)
220 me = media[face]; 220 me = media[face];
221 221
222 // TODO: Really need a proper copy constructor down in libopenmetaverse 222 // TODO: Really need a proper copy constructor down in libopenmetaverse
223 if (me != null) 223 if (me != null)
224 me = MediaEntry.FromOSD(me.GetOSD()); 224 me = MediaEntry.FromOSD(me.GetOSD());
225 } 225 }
226 226
227// m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me); 227// m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me);
228 228
229 return me; 229 return me;
230 } 230 }
231 231
232 /// <summary> 232 /// <summary>
233 /// Set the media entry on the face of the given part. 233 /// Set the media entry on the face of the given part.
234 /// </summary> 234 /// </summary>
@@ -238,28 +238,29 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
238 public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) 238 public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me)
239 { 239 {
240// m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face); 240// m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face);
241 241
242 CheckFaceParam(part, face); 242 CheckFaceParam(part, face);
243 243
244 if (null == part.Shape.Media) 244 if (null == part.Shape.Media)
245 { 245 {
246 if (me == null) 246 if (me == null)
247 return; 247 return;
248 else 248 else
249 part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]); 249 part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
250 } 250 }
251 251
252 lock (part.Shape.Media) 252 lock (part.Shape.Media)
253 part.Shape.Media[face] = me; 253 part.Shape.Media[face] = me;
254 254
255 UpdateMediaUrl(part, UUID.Zero); 255 UpdateMediaUrl(part, UUID.Zero);
256 256
257 SetPartMediaFlags(part, face, me != null); 257 SetPartMediaFlags(part, face, me != null);
258 258
259 part.ParentGroup.HasGroupChanged = true;
259 part.ScheduleFullUpdate(); 260 part.ScheduleFullUpdate();
260 part.TriggerScriptChangedEvent(Changed.MEDIA); 261 part.TriggerScriptChangedEvent(Changed.MEDIA);
261 } 262 }
262 263
263 /// <summary> 264 /// <summary>
264 /// Clear the media entry from the face of the given part. 265 /// Clear the media entry from the face of the given part.
265 /// </summary> 266 /// </summary>
@@ -267,9 +268,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
267 /// <param name="face"></param> 268 /// <param name="face"></param>
268 public void ClearMediaEntry(SceneObjectPart part, int face) 269 public void ClearMediaEntry(SceneObjectPart part, int face)
269 { 270 {
270 SetMediaEntry(part, face, null); 271 SetMediaEntry(part, face, null);
271 } 272 }
272 273
273 /// <summary> 274 /// <summary>
274 /// Set the media flags on the texture face of the given part. 275 /// Set the media flags on the texture face of the given part.
275 /// </summary> 276 /// </summary>
@@ -284,9 +285,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
284 Primitive.TextureEntry te = part.Shape.Textures; 285 Primitive.TextureEntry te = part.Shape.Textures;
285 Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); 286 Primitive.TextureEntryFace teFace = te.CreateFace((uint)face);
286 teFace.MediaFlags = flag; 287 teFace.MediaFlags = flag;
287 part.Shape.Textures = te; 288 part.Shape.Textures = te;
288 } 289 }
289 290
290 /// <summary> 291 /// <summary>
291 /// Sets or gets per face media textures. 292 /// Sets or gets per face media textures.
292 /// </summary> 293 /// </summary>
@@ -300,11 +301,11 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
300 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 301 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
301 { 302 {
302// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request); 303// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request);
303 304
304 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request); 305 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
305 ObjectMediaMessage omm = new ObjectMediaMessage(); 306 ObjectMediaMessage omm = new ObjectMediaMessage();
306 omm.Deserialize(osd); 307 omm.Deserialize(osd);
307 308
308 if (omm.Request is ObjectMediaRequest) 309 if (omm.Request is ObjectMediaRequest)
309 return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest); 310 return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest);
310 else if (omm.Request is ObjectMediaUpdate) 311 else if (omm.Request is ObjectMediaUpdate)
@@ -312,10 +313,10 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
312 313
313 throw new Exception( 314 throw new Exception(
314 string.Format( 315 string.Format(
315 "[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}", 316 "[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}",
316 omm.Request.GetType())); 317 omm.Request.GetType()));
317 } 318 }
318 319
319 /// <summary> 320 /// <summary>
320 /// Handle a fetch request for media textures 321 /// Handle a fetch request for media textures
321 /// </summary> 322 /// </summary>
@@ -324,36 +325,36 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
324 protected string HandleObjectMediaRequest(ObjectMediaRequest omr) 325 protected string HandleObjectMediaRequest(ObjectMediaRequest omr)
325 { 326 {
326 UUID primId = omr.PrimID; 327 UUID primId = omr.PrimID;
327 328
328 SceneObjectPart part = m_scene.GetSceneObjectPart(primId); 329 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
329 330
330 if (null == part) 331 if (null == part)
331 { 332 {
332 m_log.WarnFormat( 333 m_log.WarnFormat(
333 "[MOAP]: Received a GET ObjectMediaRequest for prim {0} but this doesn't exist in region {1}", 334 "[MOAP]: Received a GET ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
334 primId, m_scene.RegionInfo.RegionName); 335 primId, m_scene.RegionInfo.RegionName);
335 return string.Empty; 336 return string.Empty;
336 } 337 }
337 338
338 if (null == part.Shape.Media) 339 if (null == part.Shape.Media)
339 return string.Empty; 340 return string.Empty;
340 341
341 ObjectMediaResponse resp = new ObjectMediaResponse(); 342 ObjectMediaResponse resp = new ObjectMediaResponse();
342 343
343 resp.PrimID = primId; 344 resp.PrimID = primId;
344 345
345 lock (part.Shape.Media) 346 lock (part.Shape.Media)
346 resp.FaceMedia = part.Shape.Media.ToArray(); 347 resp.FaceMedia = part.Shape.Media.ToArray();
347 348
348 resp.Version = part.MediaUrl; 349 resp.Version = part.MediaUrl;
349 350
350 string rawResp = OSDParser.SerializeLLSDXmlString(resp.Serialize()); 351 string rawResp = OSDParser.SerializeLLSDXmlString(resp.Serialize());
351 352
352// m_log.DebugFormat("[MOAP]: Got HandleObjectMediaRequestGet raw response is [{0}]", rawResp); 353// m_log.DebugFormat("[MOAP]: Got HandleObjectMediaRequestGet raw response is [{0}]", rawResp);
353 354
354 return rawResp; 355 return rawResp;
355 } 356 }
356 357
357 /// <summary> 358 /// <summary>
358 /// Handle an update of media textures. 359 /// Handle an update of media textures.
359 /// </summary> 360 /// </summary>
@@ -363,46 +364,46 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
363 protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu) 364 protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu)
364 { 365 {
365 UUID primId = omu.PrimID; 366 UUID primId = omu.PrimID;
366 367
367 SceneObjectPart part = m_scene.GetSceneObjectPart(primId); 368 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
368 369
369 if (null == part) 370 if (null == part)
370 { 371 {
371 m_log.WarnFormat( 372 m_log.WarnFormat(
372 "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}", 373 "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
373 primId, m_scene.RegionInfo.RegionName); 374 primId, m_scene.RegionInfo.RegionName);
374 return string.Empty; 375 return string.Empty;
375 } 376 }
376 377
377// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId); 378// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);
378// 379//
379// for (int i = 0; i < omu.FaceMedia.Length; i++) 380// for (int i = 0; i < omu.FaceMedia.Length; i++)
380// { 381// {
381// MediaEntry me = omu.FaceMedia[i]; 382// MediaEntry me = omu.FaceMedia[i];
382// string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD())); 383// string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD()));
383// m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v); 384// m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v);
384// } 385// }
385 386
386 if (omu.FaceMedia.Length > part.GetNumberOfSides()) 387 if (omu.FaceMedia.Length > part.GetNumberOfSides())
387 { 388 {
388 m_log.WarnFormat( 389 m_log.WarnFormat(
389 "[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.", 390 "[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.",
390 omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides()); 391 omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
391 return string.Empty; 392 return string.Empty;
392 } 393 }
393 394
394 UUID agentId = default(UUID); 395 UUID agentId = default(UUID);
395 396
396 lock (m_omCapUsers) 397 lock (m_omCapUsers)
397 agentId = m_omCapUsers[path]; 398 agentId = m_omCapUsers[path];
398 399
399 List<MediaEntry> media = part.Shape.Media; 400 List<MediaEntry> media = part.Shape.Media;
400 401
401 if (null == media) 402 if (null == media)
402 { 403 {
403// m_log.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name); 404// m_log.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name);
404 part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia); 405 part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia);
405 406
406 for (int i = 0; i < omu.FaceMedia.Length; i++) 407 for (int i = 0; i < omu.FaceMedia.Length; i++)
407 { 408 {
408 if (omu.FaceMedia[i] != null) 409 if (omu.FaceMedia[i] != null)
@@ -412,7 +413,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
412 // directly. 413 // directly.
413 SetPartMediaFlags(part, i, true); 414 SetPartMediaFlags(part, i, true);
414// m_log.DebugFormat( 415// m_log.DebugFormat(
415// "[MOAP]: Media flags for face {0} is {1}", 416// "[MOAP]: Media flags for face {0} is {1}",
416// i, part.Shape.Textures.FaceTextures[i].MediaFlags); 417// i, part.Shape.Textures.FaceTextures[i].MediaFlags);
417 } 418 }
418 } 419 }
@@ -420,15 +421,15 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
420 else 421 else
421 { 422 {
422// m_log.DebugFormat("[MOAP]: Setting existing media list for {0}", part.Name); 423// m_log.DebugFormat("[MOAP]: Setting existing media list for {0}", part.Name);
423 424
424 // We need to go through the media textures one at a time to make sure that we have permission 425 // We need to go through the media textures one at a time to make sure that we have permission
425 // to change them 426 // to change them
426 427
427 // FIXME: Race condition here since some other texture entry manipulator may overwrite/get 428 // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
428 // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry 429 // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
429 // directly. 430 // directly.
430 Primitive.TextureEntry te = part.Shape.Textures; 431 Primitive.TextureEntry te = part.Shape.Textures;
431 432
432 lock (media) 433 lock (media)
433 { 434 {
434 for (int i = 0; i < media.Count; i++) 435 for (int i = 0; i < media.Count; i++)
@@ -436,38 +437,39 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
436 if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i)) 437 if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i))
437 { 438 {
438 media[i] = omu.FaceMedia[i]; 439 media[i] = omu.FaceMedia[i];
439 440
440 // When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal 441 // When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal
441 // texture update, so we don't need to worry about clearing MediaFlags here. 442 // texture update, so we don't need to worry about clearing MediaFlags here.
442 if (null == media[i]) 443 if (null == media[i])
443 continue; 444 continue;
444 445
445 SetPartMediaFlags(part, i, true); 446 SetPartMediaFlags(part, i, true);
446 447
447 // m_log.DebugFormat( 448 // m_log.DebugFormat(
448 // "[MOAP]: Media flags for face {0} is {1}", 449 // "[MOAP]: Media flags for face {0} is {1}",
449 // i, face.MediaFlags); 450 // i, face.MediaFlags);
450 // m_log.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name); 451 // m_log.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name);
451 } 452 }
452 } 453 }
453 } 454 }
454 455
455 part.Shape.Textures = te; 456 part.Shape.Textures = te;
456 457
457// for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++) 458// for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++)
458// m_log.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]); 459// m_log.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]);
459 } 460 }
460 461
461 UpdateMediaUrl(part, agentId); 462 UpdateMediaUrl(part, agentId);
462 463
463 // Arguably, we could avoid sending a full update to the avatar that just changed the texture. 464 // Arguably, we could avoid sending a full update to the avatar that just changed the texture.
465 part.ParentGroup.HasGroupChanged = true;
464 part.ScheduleFullUpdate(); 466 part.ScheduleFullUpdate();
465 467
466 part.TriggerScriptChangedEvent(Changed.MEDIA); 468 part.TriggerScriptChangedEvent(Changed.MEDIA);
467 469
468 return string.Empty; 470 return string.Empty;
469 } 471 }
470 472
471 /// <summary> 473 /// <summary>
472 /// Received from the viewer if a user has changed the url of a media texture. 474 /// Received from the viewer if a user has changed the url of a media texture.
473 /// </summary> 475 /// </summary>
@@ -481,71 +483,72 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
481 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 483 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
482 { 484 {
483// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request); 485// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);
484 486
485 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request); 487 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
486 ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage(); 488 ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();
487 omn.Deserialize(osd); 489 omn.Deserialize(osd);
488 490
489 UUID primId = omn.PrimID; 491 UUID primId = omn.PrimID;
490 492
491 SceneObjectPart part = m_scene.GetSceneObjectPart(primId); 493 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
492 494
493 if (null == part) 495 if (null == part)
494 { 496 {
495 m_log.WarnFormat( 497 m_log.WarnFormat(
496 "[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}", 498 "[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
497 primId, m_scene.RegionInfo.RegionName); 499 primId, m_scene.RegionInfo.RegionName);
498 return string.Empty; 500 return string.Empty;
499 } 501 }
500 502
501 UUID agentId = default(UUID); 503 UUID agentId = default(UUID);
502 504
503 lock (m_omuCapUsers) 505 lock (m_omuCapUsers)
504 agentId = m_omuCapUsers[path]; 506 agentId = m_omuCapUsers[path];
505 507
506 if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face)) 508 if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
507 return string.Empty; 509 return string.Empty;
508 510
509// m_log.DebugFormat( 511// m_log.DebugFormat(
510// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}", 512// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
511// omn.Face, part.Name, part.UUID, omn.URL); 513// omn.Face, part.Name, part.UUID, omn.URL);
512 514
513 // If media has never been set for this prim, then just return. 515 // If media has never been set for this prim, then just return.
514 if (null == part.Shape.Media) 516 if (null == part.Shape.Media)
515 return string.Empty; 517 return string.Empty;
516 518
517 MediaEntry me = null; 519 MediaEntry me = null;
518 520
519 lock (part.Shape.Media) 521 lock (part.Shape.Media)
520 me = part.Shape.Media[omn.Face]; 522 me = part.Shape.Media[omn.Face];
521 523
522 // Do the same if media has not been set up for a specific face 524 // Do the same if media has not been set up for a specific face
523 if (null == me) 525 if (null == me)
524 return string.Empty; 526 return string.Empty;
525 527
526 if (me.EnableWhiteList) 528 if (me.EnableWhiteList)
527 { 529 {
528 if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList)) 530 if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
529 { 531 {
530// m_log.DebugFormat( 532// m_log.DebugFormat(
531// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist", 533// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
532// omn.Face, part.Name, part.UUID, omn.URL); 534// omn.Face, part.Name, part.UUID, omn.URL);
533 535
534 return string.Empty; 536 return string.Empty;
535 } 537 }
536 } 538 }
537 539
538 me.CurrentURL = omn.URL; 540 me.CurrentURL = omn.URL;
539 541
540 UpdateMediaUrl(part, agentId); 542 UpdateMediaUrl(part, agentId);
541 543
544 part.ParentGroup.HasGroupChanged = true;
542 part.ScheduleFullUpdate(); 545 part.ScheduleFullUpdate();
543 546
544 part.TriggerScriptChangedEvent(Changed.MEDIA); 547 part.TriggerScriptChangedEvent(Changed.MEDIA);
545 548
546 return OSDParser.SerializeLLSDXmlString(new OSD()); 549 return OSDParser.SerializeLLSDXmlString(new OSD());
547 } 550 }
548 551
549 /// <summary> 552 /// <summary>
550 /// Check that the face number is valid for the given prim. 553 /// Check that the face number is valid for the given prim.
551 /// </summary> 554 /// </summary>
@@ -555,13 +558,13 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
555 { 558 {
556 if (face < 0) 559 if (face < 0)
557 throw new ArgumentException("Face cannot be less than zero"); 560 throw new ArgumentException("Face cannot be less than zero");
558 561
559 int maxFaces = part.GetNumberOfSides() - 1; 562 int maxFaces = part.GetNumberOfSides() - 1;
560 if (face > maxFaces) 563 if (face > maxFaces)
561 throw new ArgumentException( 564 throw new ArgumentException(
562 string.Format("Face argument was {0} but max is {1}", face, maxFaces)); 565 string.Format("Face argument was {0} but max is {1}", face, maxFaces));
563 } 566 }
564 567
565 /// <summary> 568 /// <summary>
566 /// Update the media url of the given part 569 /// Update the media url of the given part
567 /// </summary> 570 /// </summary>
@@ -583,10 +586,10 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
583 int version = int.Parse(rawVersion); 586 int version = int.Parse(rawVersion);
584 part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId); 587 part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId);
585 } 588 }
586 589
587// m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID); 590// m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
588 } 591 }
589 592
590 /// <summary> 593 /// <summary>
591 /// Check the given url against the given whitelist. 594 /// Check the given url against the given whitelist.
592 /// </summary> 595 /// </summary>
@@ -599,22 +602,22 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
599 return false; 602 return false;
600 603
601 Uri url = new Uri(rawUrl); 604 Uri url = new Uri(rawUrl);
602 605
603 foreach (string origWlUrl in whitelist) 606 foreach (string origWlUrl in whitelist)
604 { 607 {
605 string wlUrl = origWlUrl; 608 string wlUrl = origWlUrl;
606 609
607 // Deal with a line-ending wildcard 610 // Deal with a line-ending wildcard
608 if (wlUrl.EndsWith("*")) 611 if (wlUrl.EndsWith("*"))
609 wlUrl = wlUrl.Remove(wlUrl.Length - 1); 612 wlUrl = wlUrl.Remove(wlUrl.Length - 1);
610 613
611// m_log.DebugFormat("[MOAP]: Checking whitelist URL pattern {0}", origWlUrl); 614// m_log.DebugFormat("[MOAP]: Checking whitelist URL pattern {0}", origWlUrl);
612 615
613 // Handle a line starting wildcard slightly differently since this can only match the domain, not the path 616 // Handle a line starting wildcard slightly differently since this can only match the domain, not the path
614 if (wlUrl.StartsWith("*")) 617 if (wlUrl.StartsWith("*"))
615 { 618 {
616 wlUrl = wlUrl.Substring(1); 619 wlUrl = wlUrl.Substring(1);
617 620
618 if (url.Host.Contains(wlUrl)) 621 if (url.Host.Contains(wlUrl))
619 { 622 {
620// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl); 623// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
@@ -624,7 +627,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
624 else 627 else
625 { 628 {
626 string urlToMatch = url.Authority + url.AbsolutePath; 629 string urlToMatch = url.Authority + url.AbsolutePath;
627 630
628 if (urlToMatch.StartsWith(wlUrl)) 631 if (urlToMatch.StartsWith(wlUrl))
629 { 632 {
630// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl); 633// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
@@ -632,7 +635,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
632 } 635 }
633 } 636 }
634 } 637 }
635 638
636 return false; 639 return false;
637 } 640 }
638 } 641 }
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
index ee57aed..7080705 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
47 { 47 {
48 protected TestScene m_scene; 48 protected TestScene m_scene;
49 protected MoapModule m_module; 49 protected MoapModule m_module;
50 50
51 [SetUp] 51 [SetUp]
52 public override void SetUp() 52 public override void SetUp()
53 { 53 {
@@ -55,45 +55,45 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
55 55
56 m_module = new MoapModule(); 56 m_module = new MoapModule();
57 m_scene = new SceneHelpers().SetupScene(); 57 m_scene = new SceneHelpers().SetupScene();
58 SceneHelpers.SetupSceneModules(m_scene, m_module); 58 SceneHelpers.SetupSceneModules(m_scene, m_module);
59 } 59 }
60 60
61 [Test] 61 [Test]
62 public void TestClearMediaUrl() 62 public void TestClearMediaUrl()
63 { 63 {
64 TestHelpers.InMethod(); 64 TestHelpers.InMethod();
65// log4net.Config.XmlConfigurator.Configure(); 65// log4net.Config.XmlConfigurator.Configure();
66 66
67 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 67 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
68 MediaEntry me = new MediaEntry(); 68 MediaEntry me = new MediaEntry();
69 69
70 m_module.SetMediaEntry(part, 1, me); 70 m_module.SetMediaEntry(part, 1, me);
71 m_module.ClearMediaEntry(part, 1); 71 m_module.ClearMediaEntry(part, 1);
72 72
73 Assert.That(part.Shape.Media[1], Is.EqualTo(null)); 73 Assert.That(part.Shape.Media[1], Is.EqualTo(null));
74 74
75 // Although we've cleared one face, other faces may still be present. So we need to check for an 75 // Although we've cleared one face, other faces may still be present. So we need to check for an
76 // update media url version 76 // update media url version
77 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000001/" + UUID.Zero)); 77 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000001/" + UUID.Zero));
78 78
79 // By changing media flag to false, the face texture once again becomes identical to the DefaultTexture. 79 // By changing media flag to false, the face texture once again becomes identical to the DefaultTexture.
80 // Therefore, when libOMV reserializes it, it disappears and we are left with no face texture in this slot. 80 // Therefore, when libOMV reserializes it, it disappears and we are left with no face texture in this slot.
81 // Not at all confusing, eh? 81 // Not at all confusing, eh?
82 Assert.That(part.Shape.Textures.FaceTextures[1], Is.Null); 82 Assert.That(part.Shape.Textures.FaceTextures[1], Is.Null);
83 } 83 }
84 84
85 [Test] 85 [Test]
86 public void TestSetMediaUrl() 86 public void TestSetMediaUrl()
87 { 87 {
88 TestHelpers.InMethod(); 88 TestHelpers.InMethod();
89 89
90 string homeUrl = "opensimulator.org"; 90 string homeUrl = "opensimulator.org";
91 91
92 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 92 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
93 MediaEntry me = new MediaEntry() { HomeURL = homeUrl }; 93 MediaEntry me = new MediaEntry() { HomeURL = homeUrl };
94 94
95 m_module.SetMediaEntry(part, 1, me); 95 m_module.SetMediaEntry(part, 1, me);
96 96
97 Assert.That(part.Shape.Media[1].HomeURL, Is.EqualTo(homeUrl)); 97 Assert.That(part.Shape.Media[1].HomeURL, Is.EqualTo(homeUrl));
98 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000000/" + UUID.Zero)); 98 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000000/" + UUID.Zero));
99 Assert.That(part.Shape.Textures.FaceTextures[1].MediaFlags, Is.True); 99 Assert.That(part.Shape.Textures.FaceTextures[1].MediaFlags, Is.True);
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 2abc910..6a8f4c0 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -45,38 +45,38 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BuySellModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BuySellModule")]
46 public class BuySellModule : IBuySellModule, INonSharedRegionModule 46 public class BuySellModule : IBuySellModule, INonSharedRegionModule
47 { 47 {
48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 protected Scene m_scene = null; 50 protected Scene m_scene = null;
51 protected IDialogModule m_dialogModule; 51 protected IDialogModule m_dialogModule;
52 52
53 public string Name { get { return "Object BuySell Module"; } } 53 public string Name { get { return "Object BuySell Module"; } }
54 public Type ReplaceableInterface { get { return null; } } 54 public Type ReplaceableInterface { get { return null; } }
55 55
56 public void Initialise(IConfigSource source) {} 56 public void Initialise(IConfigSource source) {}
57 57
58 public void AddRegion(Scene scene) 58 public void AddRegion(Scene scene)
59 { 59 {
60 m_scene = scene; 60 m_scene = scene;
61 m_scene.RegisterModuleInterface<IBuySellModule>(this); 61 m_scene.RegisterModuleInterface<IBuySellModule>(this);
62 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 62 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
63 } 63 }
64 64
65 public void RemoveRegion(Scene scene) 65 public void RemoveRegion(Scene scene)
66 { 66 {
67 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 67 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
68 } 68 }
69 69
70 public void RegionLoaded(Scene scene) 70 public void RegionLoaded(Scene scene)
71 { 71 {
72 m_dialogModule = scene.RequestModuleInterface<IDialogModule>(); 72 m_dialogModule = scene.RequestModuleInterface<IDialogModule>();
73 } 73 }
74 74
75 public void Close() 75 public void Close()
76 { 76 {
77 RemoveRegion(m_scene); 77 RemoveRegion(m_scene);
78 } 78 }
79 79
80 public void SubscribeToClientEvents(IClientAPI client) 80 public void SubscribeToClientEvents(IClientAPI client)
81 { 81 {
82 client.OnObjectSaleInfo += ObjectSaleInfo; 82 client.OnObjectSaleInfo += ObjectSaleInfo;
@@ -89,18 +89,23 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
89 if (part == null) 89 if (part == null)
90 return; 90 return;
91 91
92 if (part.ParentGroup.IsDeleted) 92 SceneObjectGroup sog = part.ParentGroup;
93 if (sog == null || sog.IsDeleted)
93 return; 94 return;
94 95
95 if (part.OwnerID != client.AgentId && (!m_scene.Permissions.IsGod(client.AgentId))) 96 // Does the user have the power to put the object on sale?
97 if (!m_scene.Permissions.CanSellObject(client, sog, saleType))
98 {
99 client.SendAgentAlertMessage("You don't have permission to set object on sale", false);
96 return; 100 return;
101 }
97 102
98 part = part.ParentGroup.RootPart; 103 part = sog.RootPart;
99 104
100 part.ObjectSaleType = saleType; 105 part.ObjectSaleType = saleType;
101 part.SalePrice = salePrice; 106 part.SalePrice = salePrice;
102 107
103 part.ParentGroup.HasGroupChanged = true; 108 sog.HasGroupChanged = true;
104 109
105 part.SendPropertiesToClient(client); 110 part.SendPropertiesToClient(client);
106 } 111 }
@@ -113,11 +118,16 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
113 return false; 118 return false;
114 119
115 SceneObjectGroup group = part.ParentGroup; 120 SceneObjectGroup group = part.ParentGroup;
121 if(group == null || group.IsDeleted || group.inTransit)
122 return false;
123
124 // make sure we are not buying a child part
125 part = group.RootPart;
116 126
117 switch (saleType) 127 switch (saleType)
118 { 128 {
119 case 1: // Sell as original (in-place sale) 129 case 1: // Sell as original (in-place sale)
120 uint effectivePerms = group.GetEffectivePermissions(); 130 uint effectivePerms = group.EffectiveOwnerPerms;
121 131
122 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) 132 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
123 { 133 {
@@ -126,8 +136,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
126 return false; 136 return false;
127 } 137 }
128 138
129 group.SetOwnerId(remoteClient.AgentId); 139 group.SetOwner(remoteClient.AgentId, remoteClient.ActiveGroupId);
130 group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId);
131 140
132 if (m_scene.Permissions.PropagatePermissions()) 141 if (m_scene.Permissions.PropagatePermissions())
133 { 142 {
@@ -137,6 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
137 child.TriggerScriptChangedEvent(Changed.OWNER); 146 child.TriggerScriptChangedEvent(Changed.OWNER);
138 child.ApplyNextOwnerPermissions(); 147 child.ApplyNextOwnerPermissions();
139 } 148 }
149 group.InvalidateDeepEffectivePerms();
140 } 150 }
141 151
142 part.ObjectSaleType = 0; 152 part.ObjectSaleType = 0;
@@ -152,19 +162,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
152 break; 162 break;
153 163
154 case 2: // Sell a copy 164 case 2: // Sell a copy
155 Vector3 inventoryStoredPosition = new Vector3( 165 uint perms = group.EffectiveOwnerPerms;
156 Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6),
157 Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6),
158 group.AbsolutePosition.Z);
159
160 Vector3 originalPosition = group.AbsolutePosition;
161
162 group.AbsolutePosition = inventoryStoredPosition;
163
164 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(group);
165 group.AbsolutePosition = originalPosition;
166
167 uint perms = group.GetEffectivePermissions();
168 166
169 if ((perms & (uint)PermissionMask.Transfer) == 0) 167 if ((perms & (uint)PermissionMask.Transfer) == 0)
170 { 168 {
@@ -173,6 +171,15 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
173 return false; 171 return false;
174 } 172 }
175 173
174 if ((perms & (uint)PermissionMask.Copy) == 0)
175 {
176 if (m_dialogModule != null)
177 m_dialogModule.SendAlertToUser(remoteClient, "This sale has been blocked by the permissions system");
178 return false;
179 }
180
181 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(group);
182
176 AssetBase asset = m_scene.CreateAsset( 183 AssetBase asset = m_scene.CreateAsset(
177 group.GetPartName(localID), 184 group.GetPartName(localID),
178 group.GetPartDescription(localID), 185 group.GetPartDescription(localID),
@@ -193,16 +200,21 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
193 item.AssetType = asset.Type; 200 item.AssetType = asset.Type;
194 item.InvType = (int)InventoryType.Object; 201 item.InvType = (int)InventoryType.Object;
195 item.Folder = categoryID; 202 item.Folder = categoryID;
203
204 perms = group.CurrentAndFoldedNextPermissions();
205 // apply parts inventory next perms
206 PermissionsUtil.ApplyNoModFoldedPermissions(perms, ref perms);
207 // change to next owner perms
208 perms &= part.NextOwnerMask;
209 // update folded
210 perms = PermissionsUtil.FixAndFoldPermissions(perms);
211
212 item.BasePermissions = perms;
213 item.CurrentPermissions = perms;
214 item.NextPermissions = part.NextOwnerMask & perms;
215 item.EveryOnePermissions = part.EveryoneMask & perms;
216 item.GroupPermissions = part.GroupMask & perms;
196 217
197 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
198
199 item.BasePermissions = perms & part.NextOwnerMask;
200 item.CurrentPermissions = perms & part.NextOwnerMask;
201 item.NextPermissions = part.NextOwnerMask;
202 item.EveryOnePermissions = part.EveryoneMask &
203 part.NextOwnerMask;
204 item.GroupPermissions = part.GroupMask &
205 part.NextOwnerMask;
206 item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 218 item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
207 item.CreationDate = Util.UnixTimeSinceEpoch(); 219 item.CreationDate = Util.UnixTimeSinceEpoch();
208 220
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index e77f0aa..3d786dd 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -53,30 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectCommandsModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectCommandsModule")]
54 public class ObjectCommandsModule : INonSharedRegionModule 54 public class ObjectCommandsModule : INonSharedRegionModule
55 { 55 {
56// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 57
58 private Scene m_scene; 58 private Scene m_scene;
59 private ICommandConsole m_console; 59 private ICommandConsole m_console;
60 60
61 public string Name { get { return "Object Commands Module"; } } 61 public string Name { get { return "Object Commands Module"; } }
62 62
63 public Type ReplaceableInterface { get { return null; } } 63 public Type ReplaceableInterface { get { return null; } }
64 64
65 public void Initialise(IConfigSource source) 65 public void Initialise(IConfigSource source)
66 { 66 {
67// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE"); 67// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE");
68 } 68 }
69 69
70 public void PostInitialise() 70 public void PostInitialise()
71 { 71 {
72// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE"); 72// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE");
73 } 73 }
74 74
75 public void Close() 75 public void Close()
76 { 76 {
77// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE"); 77// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE");
78 } 78 }
79 79
80 public void AddRegion(Scene scene) 80 public void AddRegion(Scene scene)
81 { 81 {
82// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); 82// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
@@ -123,8 +123,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
123 "Objects", 123 "Objects",
124 false, 124 false,
125 "delete object pos", 125 "delete object pos",
126 "delete object pos <start-coord> to <end-coord>", 126 "delete object pos <start x, start y , start z> <end x, end y, end z>",
127 "Delete scene objects within the given area.", 127 "Delete scene objects within the given volume.",
128 ConsoleUtil.CoordHelp, 128 ConsoleUtil.CoordHelp,
129 HandleDeleteObject); 129 HandleDeleteObject);
130 130
@@ -152,9 +152,18 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
152 m_console.Commands.AddCommand( 152 m_console.Commands.AddCommand(
153 "Objects", 153 "Objects",
154 false, 154 false,
155 "show object owner",
156 "show object owner [--full] <OwnerID>",
157 "Show details of scene objects with given owner.",
158 "The --full option will print out information on all the parts of the object.\n",
159 HandleShowObjectByOwnerID);
160
161 m_console.Commands.AddCommand(
162 "Objects",
163 false,
155 "show object pos", 164 "show object pos",
156 "show object pos [--full] <start-coord> to <end-coord>", 165 "show object pos [--full] <start x, start y , start z> <end x, end y, end z>",
157 "Show details of scene objects within the given area.", 166 "Show details of scene objects within give volume",
158 "The --full option will print out information on all the parts of the object.\n" 167 "The --full option will print out information on all the parts of the object.\n"
159 + "For yet more detailed part information, use the \"show part\" commands.\n" 168 + "For yet more detailed part information, use the \"show part\" commands.\n"
160 + ConsoleUtil.CoordHelp, 169 + ConsoleUtil.CoordHelp,
@@ -180,8 +189,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
180 "Objects", 189 "Objects",
181 false, 190 false,
182 "show part pos", 191 "show part pos",
183 "show part pos <start-coord> to <end-coord>", 192 "show part pos <start x, start y , start z> <end x, end y, end z>",
184 "Show details of scene object parts within the given area.", 193 "Show details of scene object parts within the given volume.",
185 ConsoleUtil.CoordHelp, 194 ConsoleUtil.CoordHelp,
186 HandleShowPartByPos); 195 HandleShowPartByPos);
187 196
@@ -325,6 +334,32 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
325 OutputSogsToConsole(searchPredicate, showFull); 334 OutputSogsToConsole(searchPredicate, showFull);
326 } 335 }
327 336
337 private void HandleShowObjectByOwnerID(string module, string[] cmdparams)
338 {
339 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
340 return;
341
342 bool showFull = false;
343 OptionSet options = new OptionSet().Add("full", v => showFull = v != null);
344
345 List<string> mainParams = options.Parse(cmdparams);
346
347 if (mainParams.Count < 4)
348 {
349 m_console.OutputFormat("Usage: show object owner <OwnerID>");
350 return;
351 }
352
353 UUID ownerID;
354 if (!ConsoleUtil.TryParseConsoleUuid(m_console, mainParams[3], out ownerID))
355 return;
356
357 Predicate<SceneObjectGroup> searchPredicate
358 = so => so.OwnerID == ownerID && !so.IsAttachment;
359
360 OutputSogsToConsole(searchPredicate, showFull);
361 }
362
328 private void HandleShowObjectByPos(string module, string[] cmdparams) 363 private void HandleShowObjectByPos(string module, string[] cmdparams)
329 { 364 {
330 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 365 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
@@ -504,13 +539,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
504 539
505 if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) 540 if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName))
506 return; 541 return;
507 542
508 using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) 543 using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8))
509 { 544 {
510 xtw.Formatting = Formatting.Indented; 545 xtw.Formatting = Formatting.Indented;
511 SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); 546 SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true);
512 } 547 }
513 548
514 m_console.OutputFormat("Object dumped to file {0}", fileName); 549 m_console.OutputFormat("Object dumped to file {0}", fileName);
515 } 550 }
516 551
@@ -590,7 +625,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
590 cdl.AddRow("FlexiSoftness", s.FlexiSoftness); 625 cdl.AddRow("FlexiSoftness", s.FlexiSoftness);
591 cdl.AddRow("HollowShape", s.HollowShape); 626 cdl.AddRow("HollowShape", s.HollowShape);
592 cdl.AddRow( 627 cdl.AddRow(
593 "LightColor", 628 "LightColor",
594 string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA)); 629 string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA));
595 cdl.AddRow("LightCutoff", s.LightCutoff); 630 cdl.AddRow("LightCutoff", s.LightCutoff);
596 cdl.AddRow("LightEntry", s.LightEntry); 631 cdl.AddRow("LightEntry", s.LightEntry);
@@ -624,7 +659,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
624 cdl.AddRow("Rotation (World)", sop.GetWorldRotation()); 659 cdl.AddRow("Rotation (World)", sop.GetWorldRotation());
625 cdl.AddRow("Scale", s.Scale); 660 cdl.AddRow("Scale", s.Scale);
626 cdl.AddRow( 661 cdl.AddRow(
627 "SculptData", 662 "SculptData",
628 string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a")); 663 string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a"));
629 cdl.AddRow("SculptEntry", s.SculptEntry); 664 cdl.AddRow("SculptEntry", s.SculptEntry);
630 cdl.AddRow("SculptTexture", s.SculptTexture); 665 cdl.AddRow("SculptTexture", s.SculptTexture);
@@ -633,7 +668,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
633 668
634 // TODO, need to display more information about textures but in a compact format 669 // TODO, need to display more information about textures but in a compact format
635 // to stop output becoming huge. 670 // to stop output becoming huge.
636 for (int i = 0; i < sop.GetNumberOfSides(); i++) 671 for (int i = 0; i < sop.GetNumberOfSides(); i++)
637 { 672 {
638 Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i]; 673 Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i];
639 674
@@ -730,12 +765,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
730 if (g.OwnerID == match && !g.IsAttachment) 765 if (g.OwnerID == match && !g.IsAttachment)
731 deletes.Add(g); 766 deletes.Add(g);
732 }); 767 });
733 768
734 // if (deletes.Count == 0) 769 // if (deletes.Count == 0)
735 // m_console.OutputFormat("No objects were found with owner {0}", match); 770 // m_console.OutputFormat("No objects were found with owner {0}", match);
736 771
737 break; 772 break;
738 773
739 case "creator": 774 case "creator":
740 if (!UUID.TryParse(o, out match)) 775 if (!UUID.TryParse(o, out match))
741 return; 776 return;
@@ -747,12 +782,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
747 if (g.RootPart.CreatorID == match && !g.IsAttachment) 782 if (g.RootPart.CreatorID == match && !g.IsAttachment)
748 deletes.Add(g); 783 deletes.Add(g);
749 }); 784 });
750 785
751 // if (deletes.Count == 0) 786 // if (deletes.Count == 0)
752 // m_console.OutputFormat("No objects were found with creator {0}", match); 787 // m_console.OutputFormat("No objects were found with creator {0}", match);
753 788
754 break; 789 break;
755 790
756 case "id": 791 case "id":
757 UUID uuid; 792 UUID uuid;
758 uint localId; 793 uint localId;
@@ -768,18 +803,21 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
768 else 803 else
769 so = m_scene.GetSceneObjectGroup(localId); 804 so = m_scene.GetSceneObjectGroup(localId);
770 805
771 if (!so.IsAttachment) 806 if (so!= null)
772 deletes.Add(so); 807 {
773 808 deletes.Add(so);
774 // if (deletes.Count == 0) 809 if(so.IsAttachment)
775 // m_console.OutputFormat("No objects were found with uuid {0}", match); 810 {
776 811 requireConfirmation = true;
812 m_console.OutputFormat("Warning: object with uuid {0} is a attachment", uuid);
813 }
814 }
777 break; 815 break;
778 816
779 case "name": 817 case "name":
780 deletes = GetDeleteCandidatesByName(module, cmd); 818 deletes = GetDeleteCandidatesByName(module, cmd);
781 break; 819 break;
782 820
783 case "outside": 821 case "outside":
784 deletes = new List<SceneObjectGroup>(); 822 deletes = new List<SceneObjectGroup>();
785 823
@@ -787,7 +825,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
787 { 825 {
788 SceneObjectPart rootPart = g.RootPart; 826 SceneObjectPart rootPart = g.RootPart;
789 bool delete = false; 827 bool delete = false;
790 828
791 if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) 829 if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0)
792 { 830 {
793 delete = true; 831 delete = true;
@@ -796,18 +834,18 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
796 { 834 {
797 ILandObject parcel 835 ILandObject parcel
798 = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y); 836 = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y);
799 837
800 if (parcel == null || parcel.LandData.Name == "NO LAND") 838 if (parcel == null || parcel.LandData.Name == "NO LAND")
801 delete = true; 839 delete = true;
802 } 840 }
803 841
804 if (delete && !g.IsAttachment && !deletes.Contains(g)) 842 if (delete && !g.IsAttachment && !deletes.Contains(g))
805 deletes.Add(g); 843 deletes.Add(g);
806 }); 844 });
807 845
808 if (deletes.Count == 0) 846 if (deletes.Count == 0)
809 m_console.OutputFormat("No objects were found outside region bounds"); 847 m_console.OutputFormat("No objects were found outside region bounds");
810 848
811 break; 849 break;
812 850
813 case "pos": 851 case "pos":
@@ -829,7 +867,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
829 "Are you sure that you want to delete {0} objects from {1}", 867 "Are you sure that you want to delete {0} objects from {1}",
830 deletes.Count, m_scene.RegionInfo.RegionName), 868 deletes.Count, m_scene.RegionInfo.RegionName),
831 "y/N"); 869 "y/N");
832 870
833 if (response.ToLower() != "y") 871 if (response.ToLower() != "y")
834 { 872 {
835 MainConsole.Instance.OutputFormat( 873 MainConsole.Instance.OutputFormat(
@@ -869,11 +907,11 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
869 if (useRegex) 907 if (useRegex)
870 { 908 {
871 Regex nameRegex = new Regex(name); 909 Regex nameRegex = new Regex(name);
872 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; 910 searchAction = so => { if (nameRegex.IsMatch(so.Name)) {if(!so.IsAttachment) sceneObjects.Add(so);}};
873 } 911 }
874 else 912 else
875 { 913 {
876 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; 914 searchAction = so => { if (so.Name == name) {if(!so.IsAttachment) sceneObjects.Add(so);}};
877 } 915 }
878 916
879 m_scene.ForEachSOG(searchAction); 917 m_scene.ForEachSOG(searchAction);
@@ -916,11 +954,11 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
916 { 954 {
917 m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector); 955 m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector);
918 endVector = Vector3.Zero; 956 endVector = Vector3.Zero;
919 957
920 return false; 958 return false;
921 } 959 }
922 960
923 string rawConsoleEndVector = rawComponents.Skip(2).Take(1).Single(); 961 string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
924 962
925 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) 963 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
926 { 964 {
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 780ec69..45c1c56 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -43,12 +43,13 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
43 43
44namespace OpenSim.Region.CoreModules.World.Permissions 44namespace OpenSim.Region.CoreModules.World.Permissions
45{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PermissionsModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultPermissionsModule")]
47 public class PermissionsModule : INonSharedRegionModule, IPermissionsModule 47 public class DefaultPermissionsModule : INonSharedRegionModule, IPermissionsModule
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 protected Scene m_scene; 51 protected Scene m_scene;
52 protected ScenePermissions scenePermissions;
52 protected bool m_Enabled; 53 protected bool m_Enabled;
53 54
54 private InventoryFolderImpl m_libraryRootFolder; 55 private InventoryFolderImpl m_libraryRootFolder;
@@ -69,15 +70,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
69 } 70 }
70 71
71 #region Constants 72 #region Constants
72 // These are here for testing. They will be taken out
73
74 //private uint PERM_ALL = (uint)2147483647;
75 private uint PERM_COPY = (uint)32768;
76 //private uint PERM_MODIFY = (uint)16384;
77 private uint PERM_MOVE = (uint)524288;
78 private uint PERM_TRANS = (uint)8192;
79 private uint PERM_LOCKED = (uint)540672;
80
81 /// <value> 73 /// <value>
82 /// Different user set names that come in from the configuration file. 74 /// Different user set names that come in from the configuration file.
83 /// </value> 75 /// </value>
@@ -96,12 +88,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
96 private bool m_bypassPermissionsValue = true; 88 private bool m_bypassPermissionsValue = true;
97 private bool m_propagatePermissions = false; 89 private bool m_propagatePermissions = false;
98 private bool m_debugPermissions = false; 90 private bool m_debugPermissions = false;
99 private bool m_allowGridGods = false; 91 private bool m_allowGridAdmins = false;
100 private bool m_RegionOwnerIsGod = false; 92 private bool m_RegionOwnerIsAdmin = false;
101 private bool m_RegionManagerIsGod = false; 93 private bool m_RegionManagerIsAdmin = false;
102 private bool m_ParcelOwnerIsGod = false; 94 private bool m_forceGridAdminsOnly;
103 95 private bool m_forceAdminModeAlwaysOn;
104 private bool m_SimpleBuildPermissions = false; 96 private bool m_allowAdminActionsWithoutGodMode;
105 97
106 /// <value> 98 /// <value>
107 /// The set of users that are allowed to create scripts. This is only active if permissions are not being 99 /// The set of users that are allowed to create scripts. This is only active if permissions are not being
@@ -110,17 +102,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions
110 private UserSet m_allowedScriptCreators = UserSet.All; 102 private UserSet m_allowedScriptCreators = UserSet.All;
111 103
112 /// <value> 104 /// <value>
113 /// The set of users that are allowed to edit (save) scripts. This is only active if 105 /// The set of users that are allowed to edit (save) scripts. This is only active if
114 /// permissions are not being bypassed. This overrides normal permissions.- 106 /// permissions are not being bypassed. This overrides normal permissions.-
115 /// </value> 107 /// </value>
116 private UserSet m_allowedScriptEditors = UserSet.All; 108 private UserSet m_allowedScriptEditors = UserSet.All;
117 109
118 private Dictionary<string, bool> GrantLSL = new Dictionary<string, bool>(); 110 private Dictionary<string, bool> GrantLSL = new Dictionary<string, bool>();
119 private Dictionary<string, bool> GrantCS = new Dictionary<string, bool>(); 111 private Dictionary<string, bool> GrantCS = new Dictionary<string, bool>();
120 private Dictionary<string, bool> GrantVB = new Dictionary<string, bool>(); 112 private Dictionary<string, bool> GrantVB = new Dictionary<string, bool>();
121 private Dictionary<string, bool> GrantJS = new Dictionary<string, bool>(); 113 private Dictionary<string, bool> GrantJS = new Dictionary<string, bool>();
122 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>(); 114 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>();
123 115
124 private IFriendsModule m_friendsModule; 116 private IFriendsModule m_friendsModule;
125 private IFriendsModule FriendsModule 117 private IFriendsModule FriendsModule
126 { 118 {
@@ -168,21 +160,25 @@ namespace OpenSim.Region.CoreModules.World.Permissions
168 160
169 m_Enabled = true; 161 m_Enabled = true;
170 162
171 m_allowGridGods = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", 163 string[] sections = new string[] { "Startup", "Permissions" };
172 new string[] { "Startup", "Permissions" }, false); 164
173 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions", 165 m_allowGridAdmins = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", sections, false);
174 new string[] { "Startup", "Permissions" }, true); 166 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions", sections, true);
175 m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions", 167 m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions", sections, true);
176 new string[] { "Startup", "Permissions" }, true); 168
177 m_RegionOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god", 169 m_forceGridAdminsOnly = Util.GetConfigVarFromSections<bool>(config, "force_grid_gods_only", sections, false);
178 new string[] { "Startup", "Permissions" }, true); 170 if(!m_forceGridAdminsOnly)
179 m_RegionManagerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god", 171 {
180 new string[] { "Startup", "Permissions" }, false); 172 m_RegionOwnerIsAdmin = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god",sections, true);
181 m_ParcelOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "parcel_owner_is_god", 173 m_RegionManagerIsAdmin = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god",sections, false);
182 new string[] { "Startup", "Permissions" }, true); 174 }
183 175 else
184 m_SimpleBuildPermissions = Util.GetConfigVarFromSections<bool>(config, "simple_build_permissions", 176 m_allowGridAdmins = true;
185 new string[] { "Startup", "Permissions" }, false); 177
178 m_forceAdminModeAlwaysOn = Util.GetConfigVarFromSections<bool>(config, "automatic_gods", sections, false);
179 m_allowAdminActionsWithoutGodMode = Util.GetConfigVarFromSections<bool>(config, "implicit_gods", sections, false);
180 if(m_allowAdminActionsWithoutGodMode)
181 m_forceAdminModeAlwaysOn = false;
186 182
187 m_allowedScriptCreators 183 m_allowedScriptCreators
188 = ParseUserSetConfigSetting(config, "allowed_script_creators", m_allowedScriptCreators); 184 = ParseUserSetConfigSetting(config, "allowed_script_creators", m_allowedScriptCreators);
@@ -206,7 +202,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
206 } 202 }
207 203
208 grant = Util.GetConfigVarFromSections<string>(config, "GrantCS", 204 grant = Util.GetConfigVarFromSections<string>(config, "GrantCS",
209 new string[] { "Startup", "Permissions" }, string.Empty); 205 new string[] { "Startup", "Permissions" }, string.Empty);
210 if (grant.Length > 0) 206 if (grant.Length > 0)
211 { 207 {
212 foreach (string uuidl in grant.Split(',')) 208 foreach (string uuidl in grant.Split(','))
@@ -258,61 +254,79 @@ namespace OpenSim.Region.CoreModules.World.Permissions
258 m_scene = scene; 254 m_scene = scene;
259 255
260 scene.RegisterModuleInterface<IPermissionsModule>(this); 256 scene.RegisterModuleInterface<IPermissionsModule>(this);
257 scenePermissions = m_scene.Permissions;
261 258
262 //Register functions with Scene External Checks! 259 //Register functions with Scene External Checks!
263 m_scene.Permissions.OnBypassPermissions += BypassPermissions; 260 scenePermissions.OnBypassPermissions += BypassPermissions;
264 m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; 261 scenePermissions.OnSetBypassPermissions += SetBypassPermissions;
265 m_scene.Permissions.OnPropagatePermissions += PropagatePermissions; 262 scenePermissions.OnPropagatePermissions += PropagatePermissions;
266 m_scene.Permissions.OnGenerateClientFlags += GenerateClientFlags; 263
267 m_scene.Permissions.OnAbandonParcel += CanAbandonParcel; 264 scenePermissions.OnIsGridGod += IsGridAdministrator;
268 m_scene.Permissions.OnReclaimParcel += CanReclaimParcel; 265 scenePermissions.OnIsAdministrator += IsAdministrator;
269 m_scene.Permissions.OnDeedParcel += CanDeedParcel; 266 scenePermissions.OnIsEstateManager += IsEstateManager;
270 m_scene.Permissions.OnDeedObject += CanDeedObject; 267
271 m_scene.Permissions.OnIsGod += IsGod; 268 scenePermissions.OnGenerateClientFlags += GenerateClientFlags;
272 m_scene.Permissions.OnIsGridGod += IsGridGod; 269
273 m_scene.Permissions.OnIsAdministrator += IsAdministrator; 270 scenePermissions.OnIssueEstateCommand += CanIssueEstateCommand;
274 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; 271 scenePermissions.OnRunConsoleCommand += CanRunConsoleCommand;
275 m_scene.Permissions.OnDeleteObject += CanDeleteObject; 272
276 m_scene.Permissions.OnEditObject += CanEditObject; 273 scenePermissions.OnTeleport += CanTeleport;
277 m_scene.Permissions.OnEditParcelProperties += CanEditParcelProperties; 274
278 m_scene.Permissions.OnInstantMessage += CanInstantMessage; 275 scenePermissions.OnInstantMessage += CanInstantMessage;
279 m_scene.Permissions.OnInventoryTransfer += CanInventoryTransfer; 276
280 m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; 277 scenePermissions.OnAbandonParcel += CanAbandonParcel;
281 m_scene.Permissions.OnMoveObject += CanMoveObject; 278 scenePermissions.OnReclaimParcel += CanReclaimParcel;
282 m_scene.Permissions.OnObjectEntry += CanObjectEntry; 279 scenePermissions.OnDeedParcel += CanDeedParcel;
283 m_scene.Permissions.OnReturnObjects += CanReturnObjects; 280 scenePermissions.OnSellParcel += CanSellParcel;
284 m_scene.Permissions.OnRezObject += CanRezObject; 281 scenePermissions.OnEditParcelProperties += CanEditParcelProperties;
285 m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand; 282 scenePermissions.OnTerraformLand += CanTerraformLand;
286 m_scene.Permissions.OnRunScript += CanRunScript; 283 scenePermissions.OnBuyLand += CanBuyLand;
287 m_scene.Permissions.OnCompileScript += CanCompileScript; 284
288 m_scene.Permissions.OnSellParcel += CanSellParcel; 285 scenePermissions.OnReturnObjects += CanReturnObjects;
289 m_scene.Permissions.OnTakeObject += CanTakeObject; 286
290 m_scene.Permissions.OnTakeCopyObject += CanTakeCopyObject; 287 scenePermissions.OnRezObject += CanRezObject;
291 m_scene.Permissions.OnTerraformLand += CanTerraformLand; 288 scenePermissions.OnObjectEntry += CanObjectEntry;
292 m_scene.Permissions.OnLinkObject += CanLinkObject; 289 scenePermissions.OnObjectEnterWithScripts += OnObjectEnterWithScripts;
293 m_scene.Permissions.OnDelinkObject += CanDelinkObject; 290
294 m_scene.Permissions.OnBuyLand += CanBuyLand; 291 scenePermissions.OnDuplicateObject += CanDuplicateObject;
295 292 scenePermissions.OnDeleteObjectByIDs += CanDeleteObjectByIDs;
296 m_scene.Permissions.OnViewNotecard += CanViewNotecard; 293 scenePermissions.OnDeleteObject += CanDeleteObject;
297 m_scene.Permissions.OnViewScript += CanViewScript; 294 scenePermissions.OnEditObjectByIDs += CanEditObjectByIDs;
298 m_scene.Permissions.OnEditNotecard += CanEditNotecard; 295 scenePermissions.OnEditObject += CanEditObject;
299 m_scene.Permissions.OnEditScript += CanEditScript; 296 scenePermissions.OnEditObjectPerms += CanEditObjectPerms;
300 297 scenePermissions.OnInventoryTransfer += CanInventoryTransfer;
301 m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory; 298 scenePermissions.OnMoveObject += CanMoveObject;
302 m_scene.Permissions.OnEditObjectInventory += CanEditObjectInventory; 299 scenePermissions.OnTakeObject += CanTakeObject;
303 m_scene.Permissions.OnCopyObjectInventory += CanCopyObjectInventory; 300 scenePermissions.OnTakeCopyObject += CanTakeCopyObject;
304 m_scene.Permissions.OnDeleteObjectInventory += CanDeleteObjectInventory; 301 scenePermissions.OnLinkObject += CanLinkObject;
305 m_scene.Permissions.OnResetScript += CanResetScript; 302 scenePermissions.OnDelinkObject += CanDelinkObject;
303 scenePermissions.OnDeedObject += CanDeedObject;
304 scenePermissions.OnSellGroupObject += CanSellGroupObject;
305 scenePermissions.OnSellObjectByUserID += CanSellObjectByUserID;
306 scenePermissions.OnSellObject += CanSellObject;
306 307
307 m_scene.Permissions.OnCreateUserInventory += CanCreateUserInventory; 308 scenePermissions.OnCreateObjectInventory += CanCreateObjectInventory;
308 m_scene.Permissions.OnCopyUserInventory += CanCopyUserInventory; 309 scenePermissions.OnEditObjectInventory += CanEditObjectInventory;
309 m_scene.Permissions.OnEditUserInventory += CanEditUserInventory; 310 scenePermissions.OnCopyObjectInventory += CanCopyObjectInventory;
310 m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; 311 scenePermissions.OnDeleteObjectInventory += CanDeleteObjectInventory;
312 scenePermissions.OnDoObjectInvToObjectInv += CanDoObjectInvToObjectInv;
313 scenePermissions.OnDropInObjectInv += CanDropInObjectInv;
314
315 scenePermissions.OnViewNotecard += CanViewNotecard;
316 scenePermissions.OnViewScript += CanViewScript;
317 scenePermissions.OnEditNotecard += CanEditNotecard;
318 scenePermissions.OnEditScript += CanEditScript;
319 scenePermissions.OnResetScript += CanResetScript;
320 scenePermissions.OnRunScript += CanRunScript;
321 scenePermissions.OnCompileScript += CanCompileScript;
311 322
312 m_scene.Permissions.OnTeleport += CanTeleport; 323 scenePermissions.OnCreateUserInventory += CanCreateUserInventory;
313 324 scenePermissions.OnCopyUserInventory += CanCopyUserInventory;
314 m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia; 325 scenePermissions.OnEditUserInventory += CanEditUserInventory;
315 m_scene.Permissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia; 326 scenePermissions.OnDeleteUserInventory += CanDeleteUserInventory;
327
328 scenePermissions.OnControlPrimMedia += CanControlPrimMedia;
329 scenePermissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia;
316 330
317 m_scene.AddCommand("Users", this, "bypass permissions", 331 m_scene.AddCommand("Users", this, "bypass permissions",
318 "bypass permissions <true / false>", 332 "bypass permissions <true / false>",
@@ -327,8 +341,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
327 m_scene.AddCommand("Debug", this, "debug permissions", 341 m_scene.AddCommand("Debug", this, "debug permissions",
328 "debug permissions <true / false>", 342 "debug permissions <true / false>",
329 "Turn on permissions debugging", 343 "Turn on permissions debugging",
330 HandleDebugPermissions); 344 HandleDebugPermissions);
331 345
332 } 346 }
333 347
334 public void RegionLoaded(Scene scene) 348 public void RegionLoaded(Scene scene)
@@ -341,6 +355,79 @@ namespace OpenSim.Region.CoreModules.World.Permissions
341 return; 355 return;
342 356
343 m_scene.UnregisterModuleInterface<IPermissionsModule>(this); 357 m_scene.UnregisterModuleInterface<IPermissionsModule>(this);
358
359 scenePermissions.OnBypassPermissions -= BypassPermissions;
360 scenePermissions.OnSetBypassPermissions -= SetBypassPermissions;
361 scenePermissions.OnPropagatePermissions -= PropagatePermissions;
362
363 scenePermissions.OnIsGridGod -= IsGridAdministrator;
364 scenePermissions.OnIsAdministrator -= IsAdministrator;
365 scenePermissions.OnIsEstateManager -= IsEstateManager;
366
367 scenePermissions.OnGenerateClientFlags -= GenerateClientFlags;
368
369 scenePermissions.OnIssueEstateCommand -= CanIssueEstateCommand;
370 scenePermissions.OnRunConsoleCommand -= CanRunConsoleCommand;
371
372 scenePermissions.OnTeleport -= CanTeleport;
373
374 scenePermissions.OnInstantMessage -= CanInstantMessage;
375
376 scenePermissions.OnAbandonParcel -= CanAbandonParcel;
377 scenePermissions.OnReclaimParcel -= CanReclaimParcel;
378 scenePermissions.OnDeedParcel -= CanDeedParcel;
379 scenePermissions.OnSellParcel -= CanSellParcel;
380 scenePermissions.OnEditParcelProperties -= CanEditParcelProperties;
381 scenePermissions.OnTerraformLand -= CanTerraformLand;
382 scenePermissions.OnBuyLand -= CanBuyLand;
383
384 scenePermissions.OnRezObject -= CanRezObject;
385 scenePermissions.OnObjectEntry -= CanObjectEntry;
386 scenePermissions.OnObjectEnterWithScripts -= OnObjectEnterWithScripts;
387
388 scenePermissions.OnReturnObjects -= CanReturnObjects;
389
390 scenePermissions.OnDuplicateObject -= CanDuplicateObject;
391 scenePermissions.OnDeleteObjectByIDs -= CanDeleteObjectByIDs;
392 scenePermissions.OnDeleteObject -= CanDeleteObject;
393 scenePermissions.OnEditObjectByIDs -= CanEditObjectByIDs;
394 scenePermissions.OnEditObject -= CanEditObject;
395 scenePermissions.OnEditObjectPerms -= CanEditObjectPerms;
396 scenePermissions.OnInventoryTransfer -= CanInventoryTransfer;
397 scenePermissions.OnMoveObject -= CanMoveObject;
398 scenePermissions.OnTakeObject -= CanTakeObject;
399 scenePermissions.OnTakeCopyObject -= CanTakeCopyObject;
400 scenePermissions.OnLinkObject -= CanLinkObject;
401 scenePermissions.OnDelinkObject -= CanDelinkObject;
402 scenePermissions.OnDeedObject -= CanDeedObject;
403
404 scenePermissions.OnSellGroupObject -= CanSellGroupObject;
405 scenePermissions.OnSellObjectByUserID -= CanSellObjectByUserID;
406 scenePermissions.OnSellObject -= CanSellObject;
407
408 scenePermissions.OnCreateObjectInventory -= CanCreateObjectInventory;
409 scenePermissions.OnEditObjectInventory -= CanEditObjectInventory;
410 scenePermissions.OnCopyObjectInventory -= CanCopyObjectInventory;
411 scenePermissions.OnDeleteObjectInventory -= CanDeleteObjectInventory;
412 scenePermissions.OnDoObjectInvToObjectInv -= CanDoObjectInvToObjectInv;
413 scenePermissions.OnDropInObjectInv -= CanDropInObjectInv;
414
415 scenePermissions.OnViewNotecard -= CanViewNotecard;
416 scenePermissions.OnViewScript -= CanViewScript;
417 scenePermissions.OnEditNotecard -= CanEditNotecard;
418 scenePermissions.OnEditScript -= CanEditScript;
419 scenePermissions.OnResetScript -= CanResetScript;
420 scenePermissions.OnRunScript -= CanRunScript;
421 scenePermissions.OnCompileScript -= CanCompileScript;
422
423 scenePermissions.OnCreateUserInventory -= CanCreateUserInventory;
424 scenePermissions.OnCopyUserInventory -= CanCopyUserInventory;
425 scenePermissions.OnEditUserInventory -= CanEditUserInventory;
426 scenePermissions.OnDeleteUserInventory -= CanDeleteUserInventory;
427
428 scenePermissions.OnControlPrimMedia -= CanControlPrimMedia;
429 scenePermissions.OnInteractWithPrimMedia -= CanInteractWithPrimMedia;
430
344 } 431 }
345 432
346 public void Close() 433 public void Close()
@@ -349,7 +436,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
349 436
350 public string Name 437 public string Name
351 { 438 {
352 get { return "PermissionsModule"; } 439 get { return "DefaultPermissionsModule"; }
353 } 440 }
354 441
355 public Type ReplaceableInterface 442 public Type ReplaceableInterface
@@ -439,7 +526,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
439 { 526 {
440 m_scene.EventManager.TriggerPermissionError(user, reason); 527 m_scene.EventManager.TriggerPermissionError(user, reason);
441 } 528 }
442 529
443 protected void DebugPermissionInformation(string permissionCalled) 530 protected void DebugPermissionInformation(string permissionCalled)
444 { 531 {
445 if (m_debugPermissions) 532 if (m_debugPermissions)
@@ -469,7 +556,37 @@ namespace OpenSim.Region.CoreModules.World.Permissions
469 556
470 return false; 557 return false;
471 } 558 }
472 559
560 protected bool GroupMemberPowers(UUID groupID, UUID userID, ref ulong powers)
561 {
562 powers = 0;
563 if (null == GroupsModule)
564 return false;
565
566 GroupMembershipData gmd = GroupsModule.GetMembershipData(groupID, userID);
567
568 if (gmd != null)
569 {
570 powers = gmd.GroupPowers;
571 return true;
572 }
573 return false;
574 }
575
576 protected bool GroupMemberPowers(UUID groupID, ScenePresence sp, ref ulong powers)
577 {
578 powers = 0;
579 IClientAPI client = sp.ControllingClient;
580 if (client == null)
581 return false;
582
583 if(!client.IsGroupMember(groupID))
584 return false;
585
586 powers = client.GetGroupPowers(groupID);
587 return true;
588 }
589
473 /// <summary> 590 /// <summary>
474 /// Parse a user set configuration setting 591 /// Parse a user set configuration setting
475 /// </summary> 592 /// </summary>
@@ -481,28 +598,28 @@ namespace OpenSim.Region.CoreModules.World.Permissions
481 { 598 {
482 UserSet userSet = defaultValue; 599 UserSet userSet = defaultValue;
483 600
484 string rawSetting = Util.GetConfigVarFromSections<string>(config, settingName, 601 string rawSetting = Util.GetConfigVarFromSections<string>(config, settingName,
485 new string[] {"Startup", "Permissions"}, defaultValue.ToString()); 602 new string[] {"Startup", "Permissions"}, defaultValue.ToString());
486 603
487 // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term 604 // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term
488 // this should disappear. 605 // this should disappear.
489 if ("gods" == rawSetting.ToLower()) 606 if ("gods" == rawSetting.ToLower())
490 rawSetting = UserSet.Administrators.ToString(); 607 rawSetting = UserSet.Administrators.ToString();
491 608
492 // Doing it this was so that we can do a case insensitive conversion 609 // Doing it this was so that we can do a case insensitive conversion
493 try 610 try
494 { 611 {
495 userSet = (UserSet)Enum.Parse(typeof(UserSet), rawSetting, true); 612 userSet = (UserSet)Enum.Parse(typeof(UserSet), rawSetting, true);
496 } 613 }
497 catch 614 catch
498 { 615 {
499 m_log.ErrorFormat( 616 m_log.ErrorFormat(
500 "[PERMISSIONS]: {0} is not a valid {1} value, setting to {2}", 617 "[PERMISSIONS]: {0} is not a valid {1} value, setting to {2}",
501 rawSetting, settingName, userSet); 618 rawSetting, settingName, userSet);
502 } 619 }
503 620
504 m_log.DebugFormat("[PERMISSIONS]: {0} {1}", settingName, userSet); 621 m_log.DebugFormat("[PERMISSIONS]: {0} {1}", settingName, userSet);
505 622
506 return userSet; 623 return userSet;
507 } 624 }
508 625
@@ -516,13 +633,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions
516 if (user == UUID.Zero) 633 if (user == UUID.Zero)
517 return false; 634 return false;
518 635
519 if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod) 636 if (m_RegionOwnerIsAdmin && m_scene.RegionInfo.EstateSettings.EstateOwner == user)
520 return true; 637 return true;
521 638
522 if (IsEstateManager(user) && m_RegionManagerIsGod) 639 if (m_RegionManagerIsAdmin && IsEstateManager(user))
523 return true; 640 return true;
524 641
525 if (IsGridGod(user, null)) 642 if (IsGridAdministrator(user))
526 return true; 643 return true;
527 644
528 return false; 645 return false;
@@ -534,18 +651,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
534 /// <param name="user">The user</param> 651 /// <param name="user">The user</param>
535 /// <param name="scene">Unused, can be null</param> 652 /// <param name="scene">Unused, can be null</param>
536 /// <returns></returns> 653 /// <returns></returns>
537 protected bool IsGridGod(UUID user, Scene scene) 654 protected bool IsGridAdministrator(UUID user)
538 { 655 {
539 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 656 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
540 if (m_bypassPermissions) return m_bypassPermissionsValue; 657 if (m_bypassPermissions) return m_bypassPermissionsValue;
541 658
542 if (user == UUID.Zero) return false; 659 if (user == UUID.Zero)
660 return false;
543 661
544 if (m_allowGridGods) 662 if (m_allowGridAdmins)
545 { 663 {
546 ScenePresence sp = m_scene.GetScenePresence(user); 664 ScenePresence sp = m_scene.GetScenePresence(user);
547 if (sp != null) 665 if (sp != null)
548 return (sp.UserLevel >= 200); 666 return (sp.GodController.UserLevel >= 200);
549 667
550 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user); 668 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user);
551 if (account != null) 669 if (account != null)
@@ -556,11 +674,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
556 } 674 }
557 675
558 protected bool IsFriendWithPerms(UUID user, UUID objectOwner) 676 protected bool IsFriendWithPerms(UUID user, UUID objectOwner)
559 { 677 {
560 if (user == UUID.Zero) 678 if (FriendsModule == null)
561 return false; 679 return false;
562 680
563 if (FriendsModule == null) 681 if (user == UUID.Zero)
564 return false; 682 return false;
565 683
566 int friendPerms = FriendsModule.GetRightsGrantedByFriend(user, objectOwner); 684 int friendPerms = FriendsModule.GetRightsGrantedByFriend(user, objectOwner);
@@ -570,7 +688,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
570 protected bool IsEstateManager(UUID user) 688 protected bool IsEstateManager(UUID user)
571 { 689 {
572 if (user == UUID.Zero) return false; 690 if (user == UUID.Zero) return false;
573 691
574 return m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(user); 692 return m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(user);
575 } 693 }
576 694
@@ -596,75 +714,178 @@ namespace OpenSim.Region.CoreModules.World.Permissions
596 714
597 #region Object Permissions 715 #region Object Permissions
598 716
599 public uint GenerateClientFlags(UUID user, UUID objID) 717 const uint DEFAULT_FLAGS = (uint)(
600 { 718 PrimFlags.ObjectCopy | // Tells client you can copy the object
601 // Here's the way this works, 719 PrimFlags.ObjectModify | // tells client you can modify the object
602 // ObjectFlags and Permission flags are two different enumerations 720 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
603 // ObjectFlags, however, tells the client to change what it will allow the user to do. 721 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
604 // So, that means that all of the permissions type ObjectFlags are /temporary/ and only 722 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
605 // supposed to be set when customizing the objectflags for the client. 723 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
724 PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object
725 );
726
727 const uint NOT_DEFAULT_FLAGS = (uint)~(
728 PrimFlags.ObjectCopy | // Tells client you can copy the object
729 PrimFlags.ObjectModify | // tells client you can modify the object
730 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
731 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
732 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
733 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
734 PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object
735 );
736
737 const uint EXTRAOWNERMASK = (uint)(
738 PrimFlags.ObjectYouOwner |
739 PrimFlags.ObjectAnyOwner
740 );
741
742 const uint EXTRAGODMASK = (uint)(
743 PrimFlags.ObjectYouOwner |
744 PrimFlags.ObjectAnyOwner |
745 PrimFlags.ObjectOwnerModify |
746 PrimFlags.ObjectModify |
747 PrimFlags.ObjectMove
748 );
749
750 const uint GOD_FLAGS = (uint)(
751 PrimFlags.ObjectCopy | // Tells client you can copy the object
752 PrimFlags.ObjectModify | // tells client you can modify the object
753 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
754 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
755 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
756 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
757 PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object
758 );
759
760 const uint LOCKED_GOD_FLAGS = (uint)(
761 PrimFlags.ObjectCopy | // Tells client you can copy the object
762 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
763 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
764 PrimFlags.ObjectAnyOwner // Tells client that someone owns the object
765 );
766
767 const uint SHAREDMASK = (uint)(
768 PermissionMask.Move |
769 PermissionMask.Modify |
770 PermissionMask.Copy
771 );
772
773 public uint GenerateClientFlags(SceneObjectPart task, ScenePresence sp, uint curEffectivePerms)
774 {
775 if(sp == null || task == null || curEffectivePerms == 0)
776 return 0;
606 777
607 // These temporary objectflags get computed and added in this function based on the 778 // Remove any of the objectFlags that are temporary. These will get added back if appropriate
608 // Permission mask that's appropriate! 779 uint objflags = curEffectivePerms & NOT_DEFAULT_FLAGS ;
609 // Outside of this method, they should never be added to objectflags!
610 // -teravus
611 780
612 SceneObjectPart task = m_scene.GetSceneObjectPart(objID); 781 uint returnMask;
613 782
614 // this shouldn't ever happen.. return no permissions/objectflags. 783 SceneObjectGroup grp = task.ParentGroup;
615 if (task == null) 784 if(grp == null)
616 return (uint)0; 785 return 0;
617 786
618 uint objflags = task.GetEffectiveObjectFlags(); 787 UUID taskOwnerID = task.OwnerID;
619 UUID objectOwner = task.OwnerID; 788 UUID spID = sp.UUID;
620 789
790 bool unlocked = (grp.RootPart.OwnerMask & (uint)PermissionMask.Move) != 0;
621 791
622 // Remove any of the objectFlags that are temporary. These will get added back if appropriate 792 if(sp.IsGod)
623 // in the next bit of code 793 {
624 794 // do locked on objects owned by admin
625 // libomv will moan about PrimFlags.ObjectYouOfficer being 795 if(!unlocked && spID == taskOwnerID)
626 // deprecated 796 return objflags | LOCKED_GOD_FLAGS;
627#pragma warning disable 0612 797 else
628 objflags &= (uint) 798 return objflags | GOD_FLAGS;
629 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object 799 }
630 PrimFlags.ObjectModify | // tells client you can modify the object 800
631 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) 801 //bypass option == owner rights
632 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it 802 if (m_bypassPermissions)
633 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object 803 {
634 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object 804 returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags, true); //??
635 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object 805 returnMask |= EXTRAOWNERMASK;
636 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set 806 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
637 ); 807 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
638#pragma warning restore 0612 808 return returnMask;
639 809 }
640 // Creating the three ObjectFlags options for this method to choose from. 810
641 // Customize the OwnerMask 811 // owner
642 uint objectOwnerMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); 812 if (spID == taskOwnerID)
643 objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify; 813 {
644 814 returnMask = ApplyObjectModifyMasks(grp.EffectiveOwnerPerms, objflags, unlocked);
645 // Customize the GroupMask 815 returnMask |= EXTRAOWNERMASK;
646 uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); 816 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
647 817 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
648 // Customize the EveryoneMask 818 return returnMask;
649 uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); 819 }
650 if (objectOwner != UUID.Zero) 820
651 objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; 821 // if not god or owner, do attachments as everyone
652 822 if(task.ParentGroup.IsAttachment)
653 PermissionClass permissionClass = GetPermissionClass(user, task); 823 {
654 824 returnMask = ApplyObjectModifyMasks(grp.EffectiveEveryOnePerms, objflags, unlocked);
655 switch (permissionClass) 825 if (taskOwnerID != UUID.Zero)
826 returnMask |= (uint)PrimFlags.ObjectAnyOwner;
827 return returnMask;
828 }
829
830 UUID taskGroupID = task.GroupID;
831 bool notGroupdOwned = taskOwnerID != taskGroupID;
832
833 // if friends with rights then owner
834 if (notGroupdOwned && IsFriendWithPerms(spID, taskOwnerID))
835 {
836 returnMask = ApplyObjectModifyMasks(grp.EffectiveOwnerPerms, objflags, unlocked);
837 returnMask |= EXTRAOWNERMASK;
838 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
839 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
840 return returnMask;
841 }
842
843 // group owned or shared ?
844 IClientAPI client = sp.ControllingClient;
845 ulong powers = 0;
846 if(taskGroupID != UUID.Zero && GroupMemberPowers(taskGroupID, sp, ref powers))
656 { 847 {
657 case PermissionClass.Owner: 848 if(notGroupdOwned)
658 return objectOwnerMask; 849 {
659 case PermissionClass.Group: 850 // group sharing or everyone
660 return objectGroupMask | objectEveryoneMask; 851 returnMask = ApplyObjectModifyMasks(grp.EffectiveGroupOrEveryOnePerms, objflags, unlocked);
661 case PermissionClass.Everyone: 852 if (taskOwnerID != UUID.Zero)
662 default: 853 returnMask |= (uint)PrimFlags.ObjectAnyOwner;
663 return objectEveryoneMask; 854 return returnMask;
855 }
856
857 // object is owned by group, check role powers
858 if((powers & (ulong)GroupPowers.ObjectManipulate) == 0)
859 {
860 // group sharing or everyone
861 returnMask = ApplyObjectModifyMasks(grp.EffectiveGroupOrEveryOnePerms, objflags, unlocked);
862 returnMask |=
863 (uint)PrimFlags.ObjectGroupOwned |
864 (uint)PrimFlags.ObjectAnyOwner;
865 return returnMask;
866 }
867
868 // we may have copy without transfer
869 uint grpEffectiveOwnerPerms = grp.EffectiveOwnerPerms;
870 if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
871 grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy;
872 returnMask = ApplyObjectModifyMasks(grpEffectiveOwnerPerms, objflags, unlocked);
873 returnMask |=
874 (uint)PrimFlags.ObjectGroupOwned |
875 (uint)PrimFlags.ObjectYouOwner;
876 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
877 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
878 return returnMask;
664 } 879 }
880
881 // fallback is everyone rights
882 returnMask = ApplyObjectModifyMasks(grp.EffectiveEveryOnePerms, objflags, unlocked);
883 if (taskOwnerID != UUID.Zero)
884 returnMask |= (uint)PrimFlags.ObjectAnyOwner;
885 return returnMask;
665 } 886 }
666 887
667 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) 888 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask, bool unlocked)
668 { 889 {
669 // We are adding the temporary objectflags to the object's objectflags based on the 890 // We are adding the temporary objectflags to the object's objectflags based on the
670 // permission flag given. These change the F flags on the client. 891 // permission flag given. These change the F flags on the client.
@@ -674,14 +895,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions
674 objectFlagsMask |= (uint)PrimFlags.ObjectCopy; 895 objectFlagsMask |= (uint)PrimFlags.ObjectCopy;
675 } 896 }
676 897
677 if ((setPermissionMask & (uint)PermissionMask.Move) != 0) 898 if (unlocked)
678 { 899 {
679 objectFlagsMask |= (uint)PrimFlags.ObjectMove; 900 if ((setPermissionMask & (uint)PermissionMask.Move) != 0)
680 } 901 {
902 objectFlagsMask |= (uint)PrimFlags.ObjectMove;
903 }
681 904
682 if ((setPermissionMask & (uint)PermissionMask.Modify) != 0) 905 if ((setPermissionMask & (uint)PermissionMask.Modify) != 0)
683 { 906 {
684 objectFlagsMask |= (uint)PrimFlags.ObjectModify; 907 objectFlagsMask |= (uint)PrimFlags.ObjectModify;
908 }
685 } 909 }
686 910
687 if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0) 911 if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0)
@@ -692,6 +916,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
692 return objectFlagsMask; 916 return objectFlagsMask;
693 } 917 }
694 918
919 // OARs still need this method that handles offline users
695 public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj) 920 public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj)
696 { 921 {
697 if (obj == null) 922 if (obj == null)
@@ -705,135 +930,199 @@ namespace OpenSim.Region.CoreModules.World.Permissions
705 if (user == objectOwner) 930 if (user == objectOwner)
706 return PermissionClass.Owner; 931 return PermissionClass.Owner;
707 932
708 if (IsFriendWithPerms(user, objectOwner))
709 return PermissionClass.Owner;
710
711 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
712 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
713 return PermissionClass.Owner;
714
715 // Admin should be able to edit anything in the sim (including admin objects) 933 // Admin should be able to edit anything in the sim (including admin objects)
716 if (IsAdministrator(user)) 934 if (IsAdministrator(user))
717 return PermissionClass.Owner; 935 return PermissionClass.Owner;
718 936
719 // Users should be able to edit what is over their land. 937 if(!obj.ParentGroup.IsAttachment)
720 Vector3 taskPos = obj.AbsolutePosition;
721 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
722 if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
723 { 938 {
724 // Admin objects should not be editable by the above 939 if (IsFriendWithPerms(user, objectOwner) )
725 if (!IsAdministrator(objectOwner))
726 return PermissionClass.Owner; 940 return PermissionClass.Owner;
727 }
728 941
729 // Group permissions 942 // Group permissions
730 if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0)) 943 if (obj.GroupID != UUID.Zero && IsGroupMember(obj.GroupID, user, 0))
731 return PermissionClass.Group; 944 return PermissionClass.Group;
945 }
732 946
733 return PermissionClass.Everyone; 947 return PermissionClass.Everyone;
734 } 948 }
735 949
736 /// <summary> 950 // get effective object permissions using user UUID. User rights will be fixed
737 /// General permissions checks for any operation involving an object. These supplement more specific checks 951 protected uint GetObjectPermissions(UUID currentUser, SceneObjectGroup group, bool denyOnLocked)
738 /// implemented by callers.
739 /// </summary>
740 /// <param name="currentUser"></param>
741 /// <param name="objId">This is a scene object group UUID</param>
742 /// <param name="denyOnLocked"></param>
743 /// <returns></returns>
744 protected bool GenericObjectPermission(UUID currentUser, UUID objId, bool denyOnLocked)
745 { 952 {
746 // Default: deny 953 if (group == null)
747 bool permission = false; 954 return 0;
748 bool locked = false;
749
750 SceneObjectPart part = m_scene.GetSceneObjectPart(objId);
751 955
752 if (part == null) 956 SceneObjectPart root = group.RootPart;
753 return false; 957 if (root == null)
754 958 return 0;
755 SceneObjectGroup group = part.ParentGroup;
756 959
757 UUID objectOwner = group.OwnerID; 960 UUID objectOwner = group.OwnerID;
758 locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); 961 bool locked = denyOnLocked && ((root.OwnerMask & (uint)PermissionMask.Move) == 0);
759 962
760 // People shouldn't be able to do anything with locked objects, except the Administrator 963 if (IsAdministrator(currentUser))
761 // The 'set permissions' runs through a different permission check, so when an object owner
762 // sets an object locked, the only thing that they can do is unlock it.
763 //
764 // Nobody but the object owner can set permissions on an object
765 //
766 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
767 { 964 {
768 return false; 965 // do lock on admin owned objects
966 if(locked && currentUser == objectOwner)
967 return (uint)(PermissionMask.AllEffective & ~(PermissionMask.Modify | PermissionMask.Move));
968 return (uint)PermissionMask.AllEffective;
769 } 969 }
770 970
771 // Object owners should be able to edit their own content 971 uint lockmask = (uint)PermissionMask.AllEffective;
972 if(locked)
973 lockmask &= ~(uint)(PermissionMask.Modify | PermissionMask.Move);
974
772 if (currentUser == objectOwner) 975 if (currentUser == objectOwner)
976 return group.EffectiveOwnerPerms & lockmask;
977
978 if (group.IsAttachment)
979 return 0;
980
981 UUID sogGroupID = group.GroupID;
982 bool notgroudOwned = sogGroupID != objectOwner;
983
984 if (notgroudOwned && IsFriendWithPerms(currentUser, objectOwner))
985 return group.EffectiveOwnerPerms & lockmask;
986
987 ulong powers = 0;
988 if (sogGroupID != UUID.Zero && GroupMemberPowers(sogGroupID, currentUser, ref powers))
773 { 989 {
774 // there is no way that later code can change this back to false 990 if(notgroudOwned)
775 // so just return true immediately and short circuit the more 991 return group.EffectiveGroupOrEveryOnePerms & lockmask;
776 // expensive group checks 992
777 return true; 993 if((powers & (ulong)GroupPowers.ObjectManipulate) == 0)
778 994 return group.EffectiveGroupOrEveryOnePerms & lockmask;
779 //permission = true; 995
996 uint grpEffectiveOwnerPerms = group.EffectiveOwnerPerms & lockmask;
997 if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
998 grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy;
999 return grpEffectiveOwnerPerms;
780 } 1000 }
781 else if (group.IsAttachment) 1001
1002 return group.EffectiveEveryOnePerms & lockmask;
1003 }
1004
1005 // get effective object permissions using present presence. So some may depend on requested rights (ie God)
1006 protected uint GetObjectPermissions(ScenePresence sp, SceneObjectGroup group, bool denyOnLocked)
1007 {
1008 if (sp == null || sp.IsDeleted || group == null || group.IsDeleted)
1009 return 0;
1010
1011 SceneObjectPart root = group.RootPart;
1012 if (root == null)
1013 return 0;
1014
1015 UUID spID = sp.UUID;
1016 UUID objectOwner = group.OwnerID;
1017
1018 bool locked = denyOnLocked && ((root.OwnerMask & (uint)PermissionMask.Move) == 0);
1019
1020 if (sp.IsGod)
782 { 1021 {
783 permission = false; 1022 if(locked && spID == objectOwner)
1023 return (uint)(PermissionMask.AllEffective & ~(PermissionMask.Modify | PermissionMask.Move));
1024 return (uint)PermissionMask.AllEffective;
784 } 1025 }
785 1026
786// m_log.DebugFormat( 1027 uint lockmask = (uint)PermissionMask.AllEffective;
787// "[PERMISSIONS]: group.GroupID = {0}, part.GroupMask = {1}, isGroupMember = {2} for {3}", 1028 if(locked)
788// group.GroupID, 1029 lockmask &= ~(uint)(PermissionMask.Modify | PermissionMask.Move);
789// m_scene.GetSceneObjectPart(objId).GroupMask, 1030
790// IsGroupMember(group.GroupID, currentUser, 0), 1031 if (spID == objectOwner)
791// currentUser); 1032 return group.EffectiveOwnerPerms & lockmask;
792 1033
793 // Group members should be able to edit group objects 1034 if (group.IsAttachment)
794 if ((group.GroupID != UUID.Zero) 1035 return 0;
795 && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) 1036
796 && IsGroupMember(group.GroupID, currentUser, 0)) 1037 UUID sogGroupID = group.GroupID;
797 { 1038 bool notgroudOwned = sogGroupID != objectOwner;
798 // Return immediately, so that the administrator can shares group objects
799 return true;
800 }
801 1039
802 // Friends with benefits should be able to edit the objects too 1040 if (notgroudOwned && IsFriendWithPerms(spID, objectOwner))
803 if (IsFriendWithPerms(currentUser, objectOwner)) 1041 return group.EffectiveOwnerPerms & lockmask;
804 {
805 // Return immediately, so that the administrator can share objects with friends
806 return true;
807 }
808
809 // Users should be able to edit what is over their land.
810 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y);
811 if ((parcel != null) && (parcel.LandData.OwnerID == currentUser))
812 {
813 permission = true;
814 }
815 1042
816 // Estate users should be able to edit anything in the sim 1043 ulong powers = 0;
817 if (IsEstateManager(currentUser)) 1044 if (sogGroupID != UUID.Zero && GroupMemberPowers(sogGroupID, sp, ref powers))
818 { 1045 {
819 permission = true; 1046 if(notgroudOwned)
1047 return group.EffectiveGroupOrEveryOnePerms & lockmask;
1048
1049 if((powers & (ulong)GroupPowers.ObjectManipulate) == 0)
1050 return group.EffectiveGroupOrEveryOnePerms & lockmask;
1051
1052 uint grpEffectiveOwnerPerms = group.EffectiveOwnerPerms & lockmask;
1053 if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1054 grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy;
1055 return grpEffectiveOwnerPerms;
820 } 1056 }
821 1057
822 // Admin objects should not be editable by the above 1058 return group.EffectiveEveryOnePerms & lockmask;
823 if (IsAdministrator(objectOwner)) 1059 }
1060
1061 private uint GetObjectItemPermissions(UUID userID, TaskInventoryItem ti)
1062 {
1063 UUID tiOwnerID = ti.OwnerID;
1064 if(tiOwnerID == userID)
1065 return ti.CurrentPermissions;
1066
1067 if(IsAdministrator(userID))
1068 return (uint)PermissionMask.AllEffective;
1069 // ??
1070 if (IsFriendWithPerms(userID, tiOwnerID))
1071 return ti.CurrentPermissions;
1072
1073 UUID tiGroupID = ti.GroupID;
1074 if(tiGroupID != UUID.Zero)
824 { 1075 {
825 permission = false; 1076 ulong powers = 0;
1077 if(GroupMemberPowers(tiGroupID, userID, ref powers))
1078 {
1079 if(tiGroupID == ti.OwnerID)
1080 {
1081 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1082 return ti.CurrentPermissions;
1083 }
1084 return ti.GroupPermissions;
1085 }
826 } 1086 }
827 1087
828 // Admin should be able to edit anything in the sim (including admin objects) 1088 return 0;
829 if (IsAdministrator(currentUser)) 1089 }
1090
1091 private uint GetObjectItemPermissions(ScenePresence sp, TaskInventoryItem ti, bool notEveryone)
1092 {
1093 UUID tiOwnerID = ti.OwnerID;
1094 UUID spID = sp.UUID;
1095
1096 if(tiOwnerID == spID)
1097 return ti.CurrentPermissions;
1098
1099 // ??
1100 if (IsFriendWithPerms(spID, tiOwnerID))
1101 return ti.CurrentPermissions;
1102
1103 UUID tiGroupID = ti.GroupID;
1104 if(tiGroupID != UUID.Zero)
830 { 1105 {
831 permission = true; 1106 ulong powers = 0;
1107 if(GroupMemberPowers(tiGroupID, spID, ref powers))
1108 {
1109 if(tiGroupID == ti.OwnerID)
1110 {
1111 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1112 return ti.CurrentPermissions;
1113 }
1114 uint p = ti.GroupPermissions;
1115 if(!notEveryone)
1116 p |= ti.EveryonePermissions;
1117 return p;
1118 }
832 } 1119 }
833 1120
834 return permission; 1121 if(notEveryone)
835 } 1122 return 0;
836 1123
1124 return ti.EveryonePermissions;
1125 }
837 #endregion 1126 #endregion
838 1127
839 #region Generic Permissions 1128 #region Generic Permissions
@@ -858,97 +1147,45 @@ namespace OpenSim.Region.CoreModules.World.Permissions
858 1147
859 public bool GenericEstatePermission(UUID user) 1148 public bool GenericEstatePermission(UUID user)
860 { 1149 {
861 // Default: deny
862 bool permission = false;
863
864 // Estate admins should be able to use estate tools 1150 // Estate admins should be able to use estate tools
865 if (IsEstateManager(user)) 1151 if (IsEstateManager(user))
866 permission = true; 1152 return true;
867 1153
868 // Administrators always have permission 1154 // Administrators always have permission
869 if (IsAdministrator(user)) 1155 if (IsAdministrator(user))
870 permission = true; 1156 return true;
871 1157
872 return permission; 1158 return false;
873 } 1159 }
874 1160
875 protected bool GenericParcelPermission(UUID user, ILandObject parcel, ulong groupPowers)
876 {
877 bool permission = false;
878
879 if (parcel.LandData.OwnerID == user)
880 {
881 permission = true;
882 }
883
884 if ((parcel.LandData.GroupID != UUID.Zero) && IsGroupMember(parcel.LandData.GroupID, user, groupPowers))
885 {
886 permission = true;
887 }
888
889 if (IsEstateManager(user))
890 {
891 permission = true;
892 }
893
894 if (IsAdministrator(user))
895 {
896 permission = true;
897 }
898
899 if (m_SimpleBuildPermissions &&
900 (parcel.LandData.Flags & (uint)ParcelFlags.UseAccessList) == 0 && parcel.IsInLandAccessList(user))
901 permission = true;
902
903 return permission;
904 }
905
906 protected bool GenericParcelOwnerPermission(UUID user, ILandObject parcel, ulong groupPowers, bool allowEstateManager) 1161 protected bool GenericParcelOwnerPermission(UUID user, ILandObject parcel, ulong groupPowers, bool allowEstateManager)
907 { 1162 {
908 if (parcel.LandData.OwnerID == user) 1163 if (parcel.LandData.OwnerID == user)
909 {
910 // Returning immediately so that group deeded objects on group deeded land don't trigger a NRE on
911 // the subsequent redundant checks when using lParcelMediaCommandList()
912 // See http://opensimulator.org/mantis/view.php?id=3999 for more details
913 return true; 1164 return true;
914 }
915 1165
916 if (parcel.LandData.IsGroupOwned && IsGroupMember(parcel.LandData.GroupID, user, groupPowers)) 1166 if (parcel.LandData.IsGroupOwned && IsGroupMember(parcel.LandData.GroupID, user, groupPowers))
917 {
918 return true; 1167 return true;
919 } 1168
920
921 if (allowEstateManager && IsEstateManager(user)) 1169 if (allowEstateManager && IsEstateManager(user))
922 {
923 return true; 1170 return true;
924 }
925 1171
926 if (IsAdministrator(user)) 1172 if (IsAdministrator(user))
927 {
928 return true; 1173 return true;
929 }
930 1174
931 return false; 1175 return false;
932 } 1176 }
933
934 protected bool GenericParcelPermission(UUID user, Vector3 pos, ulong groupPowers)
935 {
936 ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
937 if (parcel == null) return false;
938 return GenericParcelPermission(user, parcel, groupPowers);
939 }
940#endregion 1177#endregion
941 1178
942 #region Permission Checks 1179 #region Permission Checks
943 private bool CanAbandonParcel(UUID user, ILandObject parcel, Scene scene) 1180 private bool CanAbandonParcel(UUID user, ILandObject parcel)
944 { 1181 {
945 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1182 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
946 if (m_bypassPermissions) return m_bypassPermissionsValue; 1183 if (m_bypassPermissions) return m_bypassPermissionsValue;
947 1184
948 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandRelease, false); 1185 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandRelease, false);
949 } 1186 }
950 1187
951 private bool CanReclaimParcel(UUID user, ILandObject parcel, Scene scene) 1188 private bool CanReclaimParcel(UUID user, ILandObject parcel)
952 { 1189 {
953 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1190 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
954 if (m_bypassPermissions) return m_bypassPermissionsValue; 1191 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -956,108 +1193,252 @@ namespace OpenSim.Region.CoreModules.World.Permissions
956 return GenericParcelOwnerPermission(user, parcel, 0,true); 1193 return GenericParcelOwnerPermission(user, parcel, 0,true);
957 } 1194 }
958 1195
959 private bool CanDeedParcel(UUID user, ILandObject parcel, Scene scene) 1196 private bool CanDeedParcel(UUID user, ILandObject parcel)
960 { 1197 {
961 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1198 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
962 if (m_bypassPermissions) return m_bypassPermissionsValue; 1199 if (m_bypassPermissions) return m_bypassPermissionsValue;
963 1200
1201 if(parcel.LandData.GroupID == UUID.Zero)
1202 return false;
1203
1204 if (IsAdministrator(user))
1205 return true;
1206
964 if (parcel.LandData.OwnerID != user) // Only the owner can deed! 1207 if (parcel.LandData.OwnerID != user) // Only the owner can deed!
965 return false; 1208 return false;
966 1209
967 ScenePresence sp = scene.GetScenePresence(user); 1210 ScenePresence sp = m_scene.GetScenePresence(user);
968 IClientAPI client = sp.ControllingClient; 1211 if(sp == null)
1212 return false;
969 1213
1214 IClientAPI client = sp.ControllingClient;
970 if ((client.GetGroupPowers(parcel.LandData.GroupID) & (ulong)GroupPowers.LandDeed) == 0) 1215 if ((client.GetGroupPowers(parcel.LandData.GroupID) & (ulong)GroupPowers.LandDeed) == 0)
971 return false; 1216 return false;
972 1217
973 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandDeed, false); 1218 return true;
974 } 1219 }
975 1220
976 private bool CanDeedObject(UUID user, UUID group, Scene scene) 1221 private bool CanDeedObject(ScenePresence sp, SceneObjectGroup sog, UUID targetGroupID)
977 { 1222 {
978 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1223 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
979 if (m_bypassPermissions) return m_bypassPermissionsValue; 1224 if (m_bypassPermissions) return m_bypassPermissionsValue;
980 1225
981 ScenePresence sp = scene.GetScenePresence(user); 1226 if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted || targetGroupID == UUID.Zero)
982 IClientAPI client = sp.ControllingClient; 1227 return false;
1228
1229 // object has group already?
1230 if(sog.GroupID != targetGroupID)
1231 return false;
1232
1233 // is effectivelly shared?
1234 if(sog.EffectiveGroupPerms == 0)
1235 return false;
1236
1237 if(sp.IsGod)
1238 return true;
1239
1240 // owned by requester?
1241 if(sog.OwnerID != sp.UUID)
1242 return false;
1243
1244 // owner can transfer?
1245 if((sog.EffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1246 return false;
1247
1248 // group member ?
1249 ulong powers = 0;
1250 if(!GroupMemberPowers(targetGroupID, sp, ref powers))
1251 return false;
983 1252
984 if ((client.GetGroupPowers(group) & (ulong)GroupPowers.DeedObject) == 0) 1253 // has group rights?
1254 if ((powers & (ulong)GroupPowers.DeedObject) == 0)
985 return false; 1255 return false;
986 1256
987 return true; 1257 return true;
988 } 1258 }
989 1259
990 private bool IsGod(UUID user, Scene scene) 1260 private bool CanDuplicateObject(SceneObjectGroup sog, ScenePresence sp)
991 { 1261 {
992 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1262 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
993 if (m_bypassPermissions) return m_bypassPermissionsValue; 1263 if (m_bypassPermissions) return m_bypassPermissionsValue;
994 1264
995 return IsAdministrator(user); 1265 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1266 return false;
1267
1268 uint perms = GetObjectPermissions(sp, sog, false);
1269 if((perms & (uint)PermissionMask.Copy) == 0)
1270 return false;
1271
1272 if(sog.OwnerID != sp.UUID && (perms & (uint)PermissionMask.Transfer) == 0)
1273 return false;
1274
1275 //If they can rez, they can duplicate
1276 return CanRezObject(0, sp.UUID, sog.AbsolutePosition);
996 } 1277 }
997 1278
998 private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition) 1279 private bool CanDeleteObject(SceneObjectGroup sog, ScenePresence sp)
999 { 1280 {
1281 // ignoring locked. viewers should warn and ask for confirmation
1282
1000 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1283 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1001 if (m_bypassPermissions) return m_bypassPermissionsValue; 1284 if (m_bypassPermissions) return m_bypassPermissionsValue;
1002 1285
1003 if (!GenericObjectPermission(owner, objectID, true)) 1286 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1004 {
1005 //They can't even edit the object
1006 return false; 1287 return false;
1007 } 1288
1008 1289 if(sog.IsAttachment)
1009 SceneObjectPart part = scene.GetSceneObjectPart(objectID);
1010 if (part == null)
1011 return false; 1290 return false;
1012 1291
1013 if (part.OwnerID == owner) 1292 UUID sogOwnerID = sog.OwnerID;
1293 UUID spID = sp.UUID;
1294
1295 if(sogOwnerID == spID)
1296 return true;
1297
1298 if (sp.IsGod)
1299 return true;
1300
1301 if (IsFriendWithPerms(sog.UUID, sogOwnerID))
1302 return true;
1303
1304 UUID sogGroupID = sog.GroupID;
1305 if (sogGroupID != UUID.Zero)
1014 { 1306 {
1015 if ((part.OwnerMask & PERM_COPY) == 0) 1307 ulong powers = 0;
1016 return false; 1308 if(GroupMemberPowers(sogGroupID, sp, ref powers))
1309 {
1310 if(sogGroupID == sogOwnerID)
1311 {
1312 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1313 return true;
1314 }
1315 return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0;
1316 }
1017 } 1317 }
1018 else if (part.GroupID != UUID.Zero) 1318 return false;
1019 { 1319 }
1020 if ((part.OwnerID == part.GroupID) && ((owner != part.LastOwnerID) || ((part.GroupMask & PERM_TRANS) == 0)))
1021 return false;
1022 1320
1023 if ((part.GroupMask & PERM_COPY) == 0) 1321 private bool CanDeleteObjectByIDs(UUID objectID, UUID userID)
1024 return false; 1322 {
1323 // ignoring locked. viewers should warn and ask for confirmation
1324
1325 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1326 if (m_bypassPermissions) return m_bypassPermissionsValue;
1327
1328 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
1329 if (sog == null)
1330 return false;
1331
1332 if(sog.IsAttachment)
1333 return false;
1334
1335 UUID sogOwnerID = sog.OwnerID;
1336
1337 if(sogOwnerID == userID)
1338 return true;
1339
1340 if (IsAdministrator(userID))
1341 return true;
1342
1343 if (IsFriendWithPerms(objectID, sogOwnerID))
1344 return true;
1345
1346 UUID sogGroupID = sog.GroupID;
1347 if (sogGroupID != UUID.Zero)
1348 {
1349 ulong powers = 0;
1350 if(GroupMemberPowers(sogGroupID, userID, ref powers))
1351 {
1352 if(sogGroupID == sogOwnerID)
1353 {
1354 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1355 return true;
1356 }
1357 return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0;
1358 }
1025 } 1359 }
1026 1360 return false;
1027 //If they can rez, they can duplicate 1361 }
1028 return CanRezObject(objectCount, owner, objectPosition, scene); 1362
1363 private bool CanEditObjectByIDs(UUID objectID, UUID userID)
1364 {
1365 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1366 if (m_bypassPermissions) return m_bypassPermissionsValue;
1367
1368 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
1369 if (sog == null)
1370 return false;
1371
1372 uint perms = GetObjectPermissions(userID, sog, true);
1373 if((perms & (uint)PermissionMask.Modify) == 0)
1374 return false;
1375 return true;
1029 } 1376 }
1030 1377
1031 private bool CanDeleteObject(UUID objectID, UUID deleter, Scene scene) 1378 private bool CanEditObject(SceneObjectGroup sog, ScenePresence sp)
1032 { 1379 {
1033 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1380 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1034 if (m_bypassPermissions) return m_bypassPermissionsValue; 1381 if (m_bypassPermissions) return m_bypassPermissionsValue;
1035 1382
1036 return GenericObjectPermission(deleter, objectID, false); 1383 if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1384 return false;
1385
1386 uint perms = GetObjectPermissions(sp, sog, true);
1387 if((perms & (uint)PermissionMask.Modify) == 0)
1388 return false;
1389 return true;
1037 } 1390 }
1038 1391
1039 private bool CanEditObject(UUID objectID, UUID editorID, Scene scene) 1392 private bool CanEditObjectPerms(SceneObjectGroup sog, UUID userID)
1040 { 1393 {
1041 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1394 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1042 if (m_bypassPermissions) return m_bypassPermissionsValue; 1395 if (m_bypassPermissions) return m_bypassPermissionsValue;
1043 1396
1044 return GenericObjectPermission(editorID, objectID, false); 1397 if (sog == null)
1398 return false;
1399
1400 if(sog.OwnerID == userID || IsAdministrator(userID))
1401 return true;
1402
1403 UUID sogGroupID = sog.GroupID;
1404 if(sogGroupID == UUID.Zero || sogGroupID != sog.OwnerID)
1405 return false;
1406
1407 uint perms = sog.EffectiveOwnerPerms;
1408 if((perms & (uint)PermissionMask.Modify) == 0)
1409 return false;
1410
1411 ulong powers = 0;
1412 if(GroupMemberPowers(sogGroupID, userID, ref powers))
1413 {
1414 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1415 return true;
1416 }
1417
1418 return false;
1045 } 1419 }
1046 1420
1047 private bool CanEditObjectInventory(UUID objectID, UUID editorID, Scene scene) 1421 private bool CanEditObjectInventory(UUID objectID, UUID userID)
1048 { 1422 {
1049 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1423 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1050 if (m_bypassPermissions) return m_bypassPermissionsValue; 1424 if (m_bypassPermissions) return m_bypassPermissionsValue;
1051 1425
1052 return GenericObjectPermission(editorID, objectID, false); 1426 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
1427 if (sog == null)
1428 return false;
1429
1430 uint perms = GetObjectPermissions(userID, sog, true);
1431 if((perms & (uint)PermissionMask.Modify) == 0)
1432 return false;
1433 return true;
1053 } 1434 }
1054 1435
1055 private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene) 1436 private bool CanEditParcelProperties(UUID userID, ILandObject parcel, GroupPowers p, bool allowManager)
1056 { 1437 {
1057 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1438 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1058 if (m_bypassPermissions) return m_bypassPermissionsValue; 1439 if (m_bypassPermissions) return m_bypassPermissionsValue;
1059 1440
1060 return GenericParcelOwnerPermission(user, parcel, (ulong)p, false); 1441 return GenericParcelOwnerPermission(userID, parcel, (ulong)p, false);
1061 } 1442 }
1062 1443
1063 /// <summary> 1444 /// <summary>
@@ -1068,18 +1449,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1068 /// <param name="user"></param> 1449 /// <param name="user"></param>
1069 /// <param name="scene"></param> 1450 /// <param name="scene"></param>
1070 /// <returns></returns> 1451 /// <returns></returns>
1071 private bool CanEditScript(UUID script, UUID objectID, UUID user, Scene scene) 1452 private bool CanEditScript(UUID script, UUID objectID, UUID userID)
1072 { 1453 {
1073 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1454 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1074 if (m_bypassPermissions) return m_bypassPermissionsValue; 1455 if (m_bypassPermissions) return m_bypassPermissionsValue;
1075 1456
1076 if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(user)) 1457 if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(userID))
1077 return false; 1458 return false;
1078 1459
1079 // Ordinarily, if you can view it, you can edit it 1460 // Ordinarily, if you can view it, you can edit it
1080 // There is no viewing a no mod script 1461 // There is no viewing a no mod script
1081 // 1462 //
1082 return CanViewScript(script, objectID, user, scene); 1463 return CanViewScript(script, objectID, userID);
1083 } 1464 }
1084 1465
1085 /// <summary> 1466 /// <summary>
@@ -1090,7 +1471,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1090 /// <param name="user"></param> 1471 /// <param name="user"></param>
1091 /// <param name="scene"></param> 1472 /// <param name="scene"></param>
1092 /// <returns></returns> 1473 /// <returns></returns>
1093 private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) 1474 private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user)
1094 { 1475 {
1095 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1476 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1096 if (m_bypassPermissions) return m_bypassPermissionsValue; 1477 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1098,8 +1479,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1098 if (objectID == UUID.Zero) // User inventory 1479 if (objectID == UUID.Zero) // User inventory
1099 { 1480 {
1100 IInventoryService invService = m_scene.InventoryService; 1481 IInventoryService invService = m_scene.InventoryService;
1101 InventoryItemBase assetRequestItem = new InventoryItemBase(notecard, user); 1482 InventoryItemBase assetRequestItem = invService.GetItem(user, notecard);
1102 assetRequestItem = invService.GetItem(assetRequestItem);
1103 if (assetRequestItem == null && LibraryRootFolder != null) // Library item 1483 if (assetRequestItem == null && LibraryRootFolder != null) // Library item
1104 { 1484 {
1105 assetRequestItem = LibraryRootFolder.FindItem(notecard); 1485 assetRequestItem = LibraryRootFolder.FindItem(notecard);
@@ -1122,69 +1502,68 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1122 } 1502 }
1123 else // Prim inventory 1503 else // Prim inventory
1124 { 1504 {
1125 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 1505 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1126
1127 if (part == null) 1506 if (part == null)
1128 return false; 1507 return false;
1129 1508
1130 if (part.OwnerID != user) 1509 SceneObjectGroup sog = part.ParentGroup;
1131 { 1510 if (sog == null)
1132 if (part.GroupID == UUID.Zero) 1511 return false;
1133 return false;
1134 1512
1135 if (!IsGroupMember(part.GroupID, user, 0)) 1513 // check object mod right
1136 return false; 1514 uint perms = GetObjectPermissions(user, sog, true);
1137 1515 if((perms & (uint)PermissionMask.Modify) == 0)
1138 if ((part.GroupMask & (uint)PermissionMask.Modify) == 0)
1139 return false;
1140 }
1141 else
1142 {
1143 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1144 return false; 1516 return false;
1145 }
1146 1517
1147 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); 1518 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard);
1148
1149 if (ti == null) 1519 if (ti == null)
1150 return false; 1520 return false;
1151 1521
1152 if (ti.OwnerID != user) 1522 if (ti.OwnerID != user)
1153 { 1523 {
1154 if (ti.GroupID == UUID.Zero) 1524 UUID tiGroupID = ti.GroupID;
1525 if (tiGroupID == UUID.Zero)
1155 return false; 1526 return false;
1156 1527
1157 if (!IsGroupMember(ti.GroupID, user, 0)) 1528 ulong powers = 0;
1529 if(!GroupMemberPowers(tiGroupID, user, ref powers))
1158 return false; 1530 return false;
1531
1532 if(tiGroupID == ti.OwnerID && (powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1533 {
1534 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) ==
1535 ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy))
1536 return true;
1537 }
1538 if ((ti.GroupPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) ==
1539 ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy))
1540 return true;
1541 return false;
1159 } 1542 }
1160 1543
1161 // Require full perms 1544 // Require full perms
1162 if ((ti.CurrentPermissions & 1545 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) !=
1163 ((uint)PermissionMask.Modify | 1546 ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy))
1164 (uint)PermissionMask.Copy)) !=
1165 ((uint)PermissionMask.Modify |
1166 (uint)PermissionMask.Copy))
1167 return false; 1547 return false;
1168 } 1548 }
1169
1170 return true; 1549 return true;
1171 } 1550 }
1172 1551
1173 private bool CanInstantMessage(UUID user, UUID target, Scene startScene) 1552 private bool CanInstantMessage(UUID user, UUID target)
1174 { 1553 {
1175 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1554 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1176 if (m_bypassPermissions) return m_bypassPermissionsValue; 1555 if (m_bypassPermissions) return m_bypassPermissionsValue;
1177 1556
1178 // If the sender is an object, check owner instead 1557 // If the sender is an object, check owner instead
1179 // 1558 //
1180 SceneObjectPart part = startScene.GetSceneObjectPart(user); 1559 SceneObjectPart part = m_scene.GetSceneObjectPart(user);
1181 if (part != null) 1560 if (part != null)
1182 user = part.OwnerID; 1561 user = part.OwnerID;
1183 1562
1184 return GenericCommunicationPermission(user, target); 1563 return GenericCommunicationPermission(user, target);
1185 } 1564 }
1186 1565
1187 private bool CanInventoryTransfer(UUID user, UUID target, Scene startScene) 1566 private bool CanInventoryTransfer(UUID user, UUID target)
1188 { 1567 {
1189 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1568 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1190 if (m_bypassPermissions) return m_bypassPermissionsValue; 1569 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1192,7 +1571,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1192 return GenericCommunicationPermission(user, target); 1571 return GenericCommunicationPermission(user, target);
1193 } 1572 }
1194 1573
1195 private bool CanIssueEstateCommand(UUID user, Scene requestFromScene, bool ownerCommand) 1574 private bool CanIssueEstateCommand(UUID user, bool ownerCommand)
1196 { 1575 {
1197 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1576 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1198 if (m_bypassPermissions) return m_bypassPermissionsValue; 1577 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1200,174 +1579,161 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1200 if (IsAdministrator(user)) 1579 if (IsAdministrator(user))
1201 return true; 1580 return true;
1202 1581
1203 if (m_scene.RegionInfo.EstateSettings.IsEstateOwner(user))
1204 return true;
1205
1206 if (ownerCommand) 1582 if (ownerCommand)
1207 return false; 1583 return m_scene.RegionInfo.EstateSettings.IsEstateOwner(user);
1208 1584
1209 return GenericEstatePermission(user); 1585 return IsEstateManager(user);
1210 } 1586 }
1211 1587
1212 private bool CanMoveObject(UUID objectID, UUID moverID, Scene scene) 1588 private bool CanMoveObject(SceneObjectGroup sog, ScenePresence sp)
1213 { 1589 {
1214 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1590 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1591
1592 if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1593 return false;
1594
1215 if (m_bypassPermissions) 1595 if (m_bypassPermissions)
1216 { 1596 {
1217 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 1597 if (sog.OwnerID != sp.UUID && sog.IsAttachment)
1218 if (part.OwnerID != moverID) 1598 return false;
1219 {
1220 if (!part.ParentGroup.IsDeleted)
1221 {
1222 if (part.ParentGroup.IsAttachment)
1223 return false;
1224 }
1225 }
1226 return m_bypassPermissionsValue; 1599 return m_bypassPermissionsValue;
1227 } 1600 }
1228 1601
1229 bool permission = GenericObjectPermission(moverID, objectID, true); 1602 uint perms = GetObjectPermissions(sp, sog, true);
1230 if (!permission) 1603 if((perms & (uint)PermissionMask.Move) == 0)
1231 { 1604 return false;
1232 if (!m_scene.Entities.ContainsKey(objectID)) 1605 return true;
1233 { 1606 }
1234 return false;
1235 }
1236 1607
1237 // The client 1608 private bool CanObjectEntry(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint)
1238 // may request to edit linked parts, and therefore, it needs 1609 {
1239 // to also check for SceneObjectPart 1610 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1240 1611
1241 // If it's not an object, we cant edit it. 1612 float newX = newPoint.X;
1242 if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) 1613 float newY = newPoint.Y;
1243 {
1244 return false;
1245 }
1246 1614
1615 // allow outside region this is needed for crossings
1616 if (newX < -1f || newX > (m_scene.RegionInfo.RegionSizeX + 1.0f) ||
1617 newY < -1f || newY > (m_scene.RegionInfo.RegionSizeY + 1.0f) )
1618 return true;
1247 1619
1248 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; 1620 if(sog == null || sog.IsDeleted)
1621 return false;
1249 1622
1623 if (m_bypassPermissions)
1624 return m_bypassPermissionsValue;
1250 1625
1251 // UUID taskOwner = null; 1626 ILandObject parcel = m_scene.LandChannel.GetLandObject(newX, newY);
1252 // Added this because at this point in time it wouldn't be wise for 1627 if (parcel == null)
1253 // the administrator object permissions to take effect. 1628 return false;
1254 // UUID objectOwner = task.OwnerID;
1255 1629
1256 // Anyone can move 1630 if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowAPrimitiveEntry)) != 0)
1257 if ((task.RootPart.EveryoneMask & PERM_MOVE) != 0) 1631 return true;
1258 permission = true;
1259 1632
1260 // Locked 1633 if (!enteringRegion)
1261 if ((task.RootPart.OwnerMask & PERM_LOCKED) == 0)
1262 permission = false;
1263 }
1264 else
1265 { 1634 {
1266 bool locked = false; 1635 Vector3 oldPoint = sog.AbsolutePosition;
1267 if (!m_scene.Entities.ContainsKey(objectID)) 1636 ILandObject fromparcel = m_scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y);
1268 { 1637 if (fromparcel != null && fromparcel.Equals(parcel)) // it already entered parcel ????
1269 return false; 1638 return true;
1270 } 1639 }
1271
1272 // If it's not an object, we cant edit it.
1273 if ((!(m_scene.Entities[objectID] is SceneObjectGroup)))
1274 {
1275 return false;
1276 }
1277 1640
1278 SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objectID]; 1641 UUID userID = sog.OwnerID;
1642 LandData landdata = parcel.LandData;
1279 1643
1280 UUID objectOwner = group.OwnerID; 1644 if (landdata.OwnerID == userID)
1281 locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); 1645 return true;
1282 1646
1283 // This is an exception to the generic object permission. 1647 if (IsAdministrator(userID))
1284 // Administrators who lock their objects should not be able to move them, 1648 return true;
1285 // however generic object permission should return true.
1286 // This keeps locked objects from being affected by random click + drag actions by accident
1287 // and allows the administrator to grab or delete a locked object.
1288 1649
1289 // Administrators and estate managers are still able to click+grab locked objects not 1650 UUID landGroupID = landdata.GroupID;
1290 // owned by them in the scene 1651 if (landGroupID != UUID.Zero)
1291 // This is by design. 1652 {
1653 if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowGroupObjectEntry)) != 0)
1654 return IsGroupMember(landGroupID, userID, 0);
1292 1655
1293 if (locked && (moverID == objectOwner)) 1656 if (landdata.IsGroupOwned && IsGroupMember(landGroupID, userID, (ulong)GroupPowers.AllowRez))
1294 return false; 1657 return true;
1295 } 1658 }
1296 return permission; 1659
1660 //Otherwise, false!
1661 return false;
1297 } 1662 }
1298 1663
1299 private bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) 1664 private bool OnObjectEnterWithScripts(SceneObjectGroup sog, ILandObject parcel)
1300 { 1665 {
1301 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1666 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1302 if (m_bypassPermissions) return m_bypassPermissionsValue;
1303 1667
1304 if ((newPoint.X > 257f || newPoint.X < -1f || newPoint.Y > 257f || newPoint.Y < -1f)) 1668 if(sog == null || sog.IsDeleted)
1305 { 1669 return false;
1306 return true;
1307 }
1308 1670
1309 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; 1671 if (m_bypassPermissions)
1672 return m_bypassPermissionsValue;
1310 1673
1311 ILandObject land = m_scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); 1674 if (parcel == null)
1675 return true;
1312 1676
1313 if (!enteringRegion) 1677 int checkflags = ((int)ParcelFlags.AllowAPrimitiveEntry);
1314 { 1678 bool scripts = (sog.ScriptCount() > 0);
1315 ILandObject fromland = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); 1679 if(scripts)
1680 checkflags |= ((int)ParcelFlags.AllowOtherScripts);
1316 1681
1317 if (fromland == land) // Not entering 1682 if ((parcel.LandData.Flags & checkflags) == checkflags)
1318 return true; 1683 return true;
1319 }
1320 1684
1321 if (land == null) 1685 UUID userID = sog.OwnerID;
1322 { 1686 LandData landdata = parcel.LandData;
1323 return false;
1324 }
1325 1687
1326 if ((land.LandData.Flags & ((int)ParcelFlags.AllowAPrimitiveEntry)) != 0) 1688 if (landdata.OwnerID == userID)
1327 {
1328 return true; 1689 return true;
1329 }
1330 1690
1331 if (!m_scene.Entities.ContainsKey(objectID)) 1691 if (IsAdministrator(userID))
1332 { 1692 return true;
1333 return false;
1334 }
1335 1693
1336 // If it's not an object, we cant edit it. 1694 UUID landGroupID = landdata.GroupID;
1337 if (!(m_scene.Entities[objectID] is SceneObjectGroup)) 1695 if (landGroupID != UUID.Zero)
1338 { 1696 {
1339 return false; 1697 checkflags = (int)ParcelFlags.AllowGroupObjectEntry;
1340 } 1698 if(scripts)
1699 checkflags |= ((int)ParcelFlags.AllowGroupScripts);
1341 1700
1701 if ((parcel.LandData.Flags & checkflags) == checkflags)
1702 return IsGroupMember(landGroupID, userID, 0);
1342 1703
1343 if (GenericParcelPermission(task.OwnerID, newPoint, 0)) 1704 if (landdata.IsGroupOwned && IsGroupMember(landGroupID, userID, (ulong)GroupPowers.AllowRez))
1344 { 1705 return true;
1345 return true;
1346 } 1706 }
1347 1707
1348 //Otherwise, false! 1708 //Otherwise, false!
1349 return false; 1709 return false;
1350 } 1710 }
1351 1711
1352 private bool CanReturnObjects(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene) 1712 private bool CanReturnObjects(ILandObject land, ScenePresence sp, List<SceneObjectGroup> objects)
1353 { 1713 {
1354 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1714 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1355 if (m_bypassPermissions) return m_bypassPermissionsValue; 1715 if (m_bypassPermissions) return m_bypassPermissionsValue;
1356 1716
1357 GroupPowers powers; 1717 if(sp == null)
1358 ILandObject l; 1718 return true; // assuming that in this case rights are as owner
1359 1719
1360 ScenePresence sp = scene.GetScenePresence(user); 1720 UUID userID = sp.UUID;
1361 if (sp == null) 1721 bool isPrivUser = sp.IsGod || IsEstateManager(userID);
1362 return false;
1363 1722
1364 IClientAPI client = sp.ControllingClient; 1723 IClientAPI client = sp.ControllingClient;
1365 1724
1725 ulong powers = 0;
1726 ILandObject l;
1727
1366 foreach (SceneObjectGroup g in new List<SceneObjectGroup>(objects)) 1728 foreach (SceneObjectGroup g in new List<SceneObjectGroup>(objects))
1367 { 1729 {
1368 // Any user can return their own objects at any time 1730 if(g.IsAttachment)
1369 // 1731 {
1370 if (GenericObjectPermission(user, g.UUID, false)) 1732 objects.Remove(g);
1733 continue;
1734 }
1735
1736 if (isPrivUser || g.OwnerID == userID)
1371 continue; 1737 continue;
1372 1738
1373 // This is a short cut for efficiency. If land is non-null, 1739 // This is a short cut for efficiency. If land is non-null,
@@ -1381,39 +1747,40 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1381 else 1747 else
1382 { 1748 {
1383 Vector3 pos = g.AbsolutePosition; 1749 Vector3 pos = g.AbsolutePosition;
1384 1750 l = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
1385 l = scene.LandChannel.GetLandObject(pos.X, pos.Y);
1386 } 1751 }
1387 1752
1388 // If it's not over any land, then we can't do a thing 1753 // If it's not over any land, then we can't do a thing
1389 if (l == null) 1754 if (l == null || l.LandData == null)
1390 { 1755 {
1391 objects.Remove(g); 1756 objects.Remove(g);
1392 continue; 1757 continue;
1393 } 1758 }
1394 1759
1760 LandData ldata = l.LandData;
1395 // If we own the land outright, then allow 1761 // If we own the land outright, then allow
1396 // 1762 //
1397 if (l.LandData.OwnerID == user) 1763 if (ldata.OwnerID == userID)
1398 continue; 1764 continue;
1399 1765
1400 // Group voodoo 1766 // Group voodoo
1401 // 1767 //
1402 if (l.LandData.IsGroupOwned) 1768 if (ldata.IsGroupOwned)
1403 { 1769 {
1404 powers = (GroupPowers)client.GetGroupPowers(l.LandData.GroupID); 1770 UUID lGroupID = ldata.GroupID;
1405 // Not a group member, or no rights at all 1771 // Not a group member, or no rights at all
1406 // 1772 //
1407 if (powers == (GroupPowers)0) 1773 powers = client.GetGroupPowers(lGroupID);
1774 if(powers == 0)
1408 { 1775 {
1409 objects.Remove(g); 1776 objects.Remove(g);
1410 continue; 1777 continue;
1411 } 1778 }
1412 1779
1413 // Group deeded object? 1780 // Group deeded object?
1414 // 1781 //
1415 if (g.OwnerID == l.LandData.GroupID && 1782 if (g.OwnerID == lGroupID &&
1416 (powers & GroupPowers.ReturnGroupOwned) == (GroupPowers)0) 1783 (powers & (ulong)GroupPowers.ReturnGroupOwned) == 0)
1417 { 1784 {
1418 objects.Remove(g); 1785 objects.Remove(g);
1419 continue; 1786 continue;
@@ -1421,14 +1788,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1421 1788
1422 // Group set object? 1789 // Group set object?
1423 // 1790 //
1424 if (g.GroupID == l.LandData.GroupID && 1791 if (g.GroupID == lGroupID &&
1425 (powers & GroupPowers.ReturnGroupSet) == (GroupPowers)0) 1792 (powers & (ulong)GroupPowers.ReturnGroupSet) == 0)
1426 { 1793 {
1427 objects.Remove(g); 1794 objects.Remove(g);
1428 continue; 1795 continue;
1429 } 1796 }
1430 1797
1431 if ((powers & GroupPowers.ReturnNonGroup) == (GroupPowers)0) 1798 if ((powers & (ulong)GroupPowers.ReturnNonGroup) == 0)
1432 { 1799 {
1433 objects.Remove(g); 1800 objects.Remove(g);
1434 continue; 1801 continue;
@@ -1451,41 +1818,41 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1451 return true; 1818 return true;
1452 } 1819 }
1453 1820
1454 private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) 1821 private bool CanRezObject(int objectCount, UUID userID, Vector3 objectPosition)
1455 { 1822 {
1456 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1823 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1457 if (m_bypassPermissions) return m_bypassPermissionsValue; 1824 if (m_bypassPermissions)
1825 return m_bypassPermissionsValue;
1458 1826
1459// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name); 1827// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
1460 1828
1461 ILandObject parcel = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 1829 ILandObject parcel = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
1462 if (parcel == null) 1830 if (parcel == null || parcel.LandData == null)
1463 return false; 1831 return false;
1464 1832
1465 if ((parcel.LandData.Flags & (uint)ParcelFlags.CreateObjects) != 0) 1833 LandData landdata = parcel.LandData;
1466 { 1834 if ((userID == landdata.OwnerID))
1467 return true;
1468 }
1469 else if ((owner == parcel.LandData.OwnerID) || IsAdministrator(owner))
1470 {
1471 return true; 1835 return true;
1472 } 1836
1473 else if (((parcel.LandData.Flags & (uint)ParcelFlags.CreateGroupObjects) != 0) 1837 if ((landdata.Flags & (uint)ParcelFlags.CreateObjects) != 0)
1474 && (parcel.LandData.GroupID != UUID.Zero) && IsGroupMember(parcel.LandData.GroupID, owner, 0))
1475 {
1476 return true; 1838 return true;
1477 } 1839
1478 else if (parcel.LandData.GroupID != UUID.Zero && IsGroupMember(parcel.LandData.GroupID, owner, (ulong)GroupPowers.AllowRez)) 1840 if(IsAdministrator(userID))
1479 {
1480 return true; 1841 return true;
1481 } 1842
1482 else 1843 if(landdata.GroupID != UUID.Zero)
1483 { 1844 {
1484 return false; 1845 if ((landdata.Flags & (uint)ParcelFlags.CreateGroupObjects) != 0)
1846 return IsGroupMember(landdata.GroupID, userID, 0);
1847
1848 if (landdata.IsGroupOwned && IsGroupMember(landdata.GroupID, userID, (ulong)GroupPowers.AllowRez))
1849 return true;
1485 } 1850 }
1851
1852 return false;
1486 } 1853 }
1487 1854
1488 private bool CanRunConsoleCommand(UUID user, Scene requestFromScene) 1855 private bool CanRunConsoleCommand(UUID user)
1489 { 1856 {
1490 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1857 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1491 if (m_bypassPermissions) return m_bypassPermissionsValue; 1858 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1494,82 +1861,214 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1494 return IsAdministrator(user); 1861 return IsAdministrator(user);
1495 } 1862 }
1496 1863
1497 private bool CanRunScript(UUID script, UUID objectID, UUID user, Scene scene) 1864 private bool CanRunScript(TaskInventoryItem scriptitem, SceneObjectPart part)
1498 { 1865 {
1499 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1866 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1500 if (m_bypassPermissions) return m_bypassPermissionsValue; 1867 if (m_bypassPermissions) return m_bypassPermissionsValue;
1501 1868
1502 return true; 1869 if(scriptitem == null || part == null)
1870 return false;
1871
1872 SceneObjectGroup sog = part.ParentGroup;
1873 if(sog == null)
1874 return false;
1875
1876 Vector3 pos = sog.AbsolutePosition;
1877 ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
1878 if (parcel == null)
1879 return false;
1880
1881 LandData ldata = parcel.LandData;
1882 if(ldata == null)
1883 return false;
1884
1885 uint lflags = ldata.Flags;
1886
1887 if ((lflags & (uint)ParcelFlags.AllowOtherScripts) != 0)
1888 return true;
1889
1890 if ((part.OwnerID == ldata.OwnerID))
1891 return true;
1892
1893 if (((lflags & (uint)ParcelFlags.AllowGroupScripts) != 0)
1894 && (ldata.GroupID != UUID.Zero) && (ldata.GroupID == part.GroupID))
1895 return true;
1896
1897 return GenericEstatePermission(part.OwnerID);
1503 } 1898 }
1504 1899
1505 private bool CanSellParcel(UUID user, ILandObject parcel, Scene scene) 1900 private bool CanSellParcel(UUID user, ILandObject parcel)
1506 { 1901 {
1507 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1902 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1508 if (m_bypassPermissions) return m_bypassPermissionsValue; 1903 if (m_bypassPermissions) return m_bypassPermissionsValue;
1509 1904
1510 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandSetSale, false); 1905 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandSetSale, true);
1511 } 1906 }
1512 1907
1513 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) 1908 private bool CanSellGroupObject(UUID userID, UUID groupID)
1514 { 1909 {
1515 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1910 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1516 if (m_bypassPermissions) return m_bypassPermissionsValue; 1911 if (m_bypassPermissions) return m_bypassPermissionsValue;
1517 1912
1518 return GenericObjectPermission(stealer,objectID, false); 1913 return IsGroupMember(groupID, userID, (ulong)GroupPowers.ObjectSetForSale);
1519 } 1914 }
1520 1915
1521 private bool CanTakeCopyObject(UUID objectID, UUID userID, Scene inScene) 1916 private bool CanSellObjectByUserID(SceneObjectGroup sog, UUID userID, byte saleType)
1522 { 1917 {
1523 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1918 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1524 if (m_bypassPermissions) return m_bypassPermissionsValue; 1919 if (m_bypassPermissions) return m_bypassPermissionsValue;
1525 1920
1526 bool permission = GenericObjectPermission(userID, objectID, false); 1921 if (sog == null || sog.IsDeleted || userID == UUID.Zero)
1922 return false;
1527 1923
1528 SceneObjectGroup so = (SceneObjectGroup)m_scene.Entities[objectID]; 1924 // sell is not a attachment op
1925 if(sog.IsAttachment)
1926 return false;
1529 1927
1530 if (!permission) 1928 if(IsAdministrator(userID))
1531 { 1929 return true;
1532 if (!m_scene.Entities.ContainsKey(objectID))
1533 {
1534 return false;
1535 }
1536 1930
1537 // If it's not an object, we cant edit it. 1931 uint sogEffectiveOwnerPerms = sog.EffectiveOwnerPerms;
1538 if (!(m_scene.Entities[objectID] is SceneObjectGroup)) 1932 if((sogEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1539 { 1933 return false;
1540 return false;
1541 }
1542 1934
1543 // UUID taskOwner = null; 1935 if(saleType == (byte)SaleType.Copy &&
1544 // Added this because at this point in time it wouldn't be wise for 1936 (sogEffectiveOwnerPerms & (uint)PermissionMask.Copy) == 0)
1545 // the administrator object permissions to take effect. 1937 return false;
1546 // UUID objectOwner = task.OwnerID;
1547 1938
1548 if ((so.RootPart.EveryoneMask & PERM_COPY) != 0) 1939 UUID sogOwnerID = sog.OwnerID;
1549 permission = true; 1940
1550 } 1941 if(sogOwnerID == userID)
1942 return true;
1943
1944 // else only group owned can be sold by members with powers
1945 UUID sogGroupID = sog.GroupID;
1946 if(sog.OwnerID != sogGroupID || sogGroupID == UUID.Zero)
1947 return false;
1948
1949 return IsGroupMember(sogGroupID, userID, (ulong)GroupPowers.ObjectSetForSale);
1950 }
1951
1952 private bool CanSellObject(SceneObjectGroup sog, ScenePresence sp, byte saleType)
1953 {
1954 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1955 if (m_bypassPermissions) return m_bypassPermissionsValue;
1551 1956
1552 if (so.OwnerID != userID) 1957 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1958 return false;
1959
1960 // sell is not a attachment op
1961 if(sog.IsAttachment)
1962 return false;
1963
1964 if(sp.IsGod)
1965 return true;
1966
1967 uint sogEffectiveOwnerPerms = sog.EffectiveOwnerPerms;
1968 if((sogEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1969 return false;
1970
1971 if(saleType == (byte)SaleType.Copy &&
1972 (sogEffectiveOwnerPerms & (uint)PermissionMask.Copy) == 0)
1973 return false;
1974
1975 UUID userID = sp.UUID;
1976 UUID sogOwnerID = sog.OwnerID;
1977
1978 if(sogOwnerID == userID)
1979 return true;
1980
1981 // else only group owned can be sold by members with powers
1982 UUID sogGroupID = sog.GroupID;
1983 if(sog.OwnerID != sogGroupID || sogGroupID == UUID.Zero)
1984 return false;
1985
1986 ulong powers = 0;
1987 if(!GroupMemberPowers(sogGroupID, sp, ref powers))
1988 return false;
1989
1990 if((powers & (ulong)GroupPowers.ObjectSetForSale) == 0)
1991 return false;
1992
1993 return true;
1994 }
1995
1996 private bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp)
1997 {
1998 // ignore locked, viewers shell ask for confirmation
1999 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2000 if (m_bypassPermissions) return m_bypassPermissionsValue;
2001
2002 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
2003 return false;
2004
2005 // take is not a attachment op
2006 if(sog.IsAttachment)
2007 return false;
2008
2009 UUID sogOwnerID = sog.OwnerID;
2010 UUID spID = sp.UUID;
2011
2012 if(sogOwnerID == spID)
2013 return true;
2014
2015 if (sp.IsGod)
2016 return true;
2017
2018 if((sog.EffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
2019 return false;
2020
2021 if (IsFriendWithPerms(sog.UUID, sogOwnerID))
2022 return true;
2023
2024 UUID sogGroupID = sog.GroupID;
2025 if (sogGroupID != UUID.Zero)
1553 { 2026 {
1554 if ((so.GetEffectivePermissions() & (PERM_COPY | PERM_TRANS)) != (PERM_COPY | PERM_TRANS)) 2027 ulong powers = 0;
1555 permission = false; 2028 if(GroupMemberPowers(sogGroupID, sp, ref powers))
2029 {
2030 if(sogGroupID == sogOwnerID)
2031 {
2032 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
2033 return true;
2034 }
2035 return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0;
2036 }
1556 } 2037 }
1557 else 2038 return false;
2039 }
2040
2041 private bool CanTakeCopyObject(SceneObjectGroup sog, ScenePresence sp)
2042 {
2043 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2044 if (m_bypassPermissions) return m_bypassPermissionsValue;
2045
2046 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
2047 return false;
2048
2049 // refuse on attachments
2050 if(sog.IsAttachment && !sp.IsGod)
2051 return false;
2052
2053 uint perms = GetObjectPermissions(sp, sog, true);
2054 if((perms & (uint)PermissionMask.Copy) == 0)
1558 { 2055 {
1559 if ((so.GetEffectivePermissions() & PERM_COPY) != PERM_COPY) 2056 sp.ControllingClient.SendAgentAlertMessage("Copying this item has been denied by the permissions system", false);
1560 permission = false; 2057 return false;
1561 } 2058 }
1562 2059
1563 return permission; 2060 if(sog.OwnerID != sp.UUID && (perms & (uint)PermissionMask.Transfer) == 0)
2061 return false;
2062 return true;
1564 } 2063 }
1565 2064
1566 private bool CanTerraformLand(UUID user, Vector3 position, Scene requestFromScene) 2065 private bool CanTerraformLand(UUID userID, Vector3 position)
1567 { 2066 {
1568 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2067 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1569 if (m_bypassPermissions) return m_bypassPermissionsValue; 2068 if (m_bypassPermissions) return m_bypassPermissionsValue;
1570 2069
1571 // Estate override 2070 // Estate override
1572 if (GenericEstatePermission(user)) 2071 if (GenericEstatePermission(userID))
1573 return true; 2072 return true;
1574 2073
1575 float X = position.X; 2074 float X = position.X;
@@ -1587,13 +2086,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1587 ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y); 2086 ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y);
1588 if (parcel == null) 2087 if (parcel == null)
1589 return false; 2088 return false;
1590 2089
1591 // Others allowed to terraform? 2090 LandData landdata = parcel.LandData;
1592 if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowTerraform)) != 0) 2091 if (landdata == null)
2092 return false;
2093
2094 if ((landdata.Flags & ((int)ParcelFlags.AllowTerraform)) != 0)
1593 return true; 2095 return true;
1594 2096
1595 // Land owner can terraform too 2097 if(landdata.OwnerID == userID)
1596 if (parcel != null && GenericParcelPermission(user, parcel, (ulong)GroupPowers.AllowEditLand)) 2098 return true;
2099
2100 if (landdata.IsGroupOwned && parcel.LandData.GroupID != UUID.Zero &&
2101 IsGroupMember(landdata.GroupID, userID, (ulong)GroupPowers.AllowEditLand))
1597 return true; 2102 return true;
1598 2103
1599 return false; 2104 return false;
@@ -1607,16 +2112,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1607 /// <param name="user"></param> 2112 /// <param name="user"></param>
1608 /// <param name="scene"></param> 2113 /// <param name="scene"></param>
1609 /// <returns></returns> 2114 /// <returns></returns>
1610 private bool CanViewScript(UUID script, UUID objectID, UUID user, Scene scene) 2115 private bool CanViewScript(UUID script, UUID objectID, UUID userID)
1611 { 2116 {
1612 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2117 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1613 if (m_bypassPermissions) return m_bypassPermissionsValue; 2118 if (m_bypassPermissions) return m_bypassPermissionsValue;
1614 2119
2120 // A god is a god is a god
2121 if (IsAdministrator(userID))
2122 return true;
2123
1615 if (objectID == UUID.Zero) // User inventory 2124 if (objectID == UUID.Zero) // User inventory
1616 { 2125 {
1617 IInventoryService invService = m_scene.InventoryService; 2126 IInventoryService invService = m_scene.InventoryService;
1618 InventoryItemBase assetRequestItem = new InventoryItemBase(script, user); 2127 InventoryItemBase assetRequestItem = invService.GetItem(userID, script);
1619 assetRequestItem = invService.GetItem(assetRequestItem);
1620 if (assetRequestItem == null && LibraryRootFolder != null) // Library item 2128 if (assetRequestItem == null && LibraryRootFolder != null) // Library item
1621 { 2129 {
1622 assetRequestItem = LibraryRootFolder.FindItem(script); 2130 assetRequestItem = LibraryRootFolder.FindItem(script);
@@ -1636,60 +2144,53 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1636 // readable only if it's really full perms 2144 // readable only if it's really full perms
1637 // 2145 //
1638 if ((assetRequestItem.CurrentPermissions & 2146 if ((assetRequestItem.CurrentPermissions &
2147/*
1639 ((uint)PermissionMask.Modify | 2148 ((uint)PermissionMask.Modify |
1640 (uint)PermissionMask.Copy | 2149 (uint)PermissionMask.Copy |
1641 (uint)PermissionMask.Transfer)) != 2150 (uint)PermissionMask.Transfer)) !=
1642 ((uint)PermissionMask.Modify | 2151 ((uint)PermissionMask.Modify |
1643 (uint)PermissionMask.Copy | 2152 (uint)PermissionMask.Copy |
1644 (uint)PermissionMask.Transfer)) 2153 (uint)PermissionMask.Transfer))
2154*/
2155 (uint)(PermissionMask.Modify | PermissionMask.Copy)) !=
2156 (uint)(PermissionMask.Modify | PermissionMask.Copy))
1645 return false; 2157 return false;
1646 } 2158 }
1647 else // Prim inventory 2159 else // Prim inventory
1648 { 2160 {
1649 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 2161 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1650
1651 if (part == null) 2162 if (part == null)
1652 return false; 2163 return false;
1653
1654 if (part.OwnerID != user)
1655 {
1656 if (part.GroupID == UUID.Zero)
1657 return false;
1658 2164
1659 if (!IsGroupMember(part.GroupID, user, 0)) 2165 SceneObjectGroup sog = part.ParentGroup;
1660 return false; 2166 if (sog == null)
1661 2167 return false;
1662 if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) 2168
1663 return false; 2169 uint perms = GetObjectPermissions(userID, sog, true);
1664 } 2170 if((perms & (uint)PermissionMask.Modify) == 0)
1665 else 2171 return false;
1666 {
1667 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1668 return false;
1669 }
1670 2172
1671 TaskInventoryItem ti = part.Inventory.GetInventoryItem(script); 2173 TaskInventoryItem ti = part.Inventory.GetInventoryItem(script);
1672 2174
1673 if (ti == null) 2175// if (ti == null || ti.InvType != (int)InventoryType.LSL)
2176 if (ti == null) // legacy may not have type
1674 return false; 2177 return false;
1675 2178
1676 if (ti.OwnerID != user) 2179 uint itperms = GetObjectItemPermissions(userID, ti);
1677 {
1678 if (ti.GroupID == UUID.Zero)
1679 return false;
1680
1681 if (!IsGroupMember(ti.GroupID, user, 0))
1682 return false;
1683 }
1684 2180
1685 // Require full perms 2181 // Require full perms
1686 if ((ti.CurrentPermissions & 2182
1687 ((uint)PermissionMask.Modify | 2183 if ((itperms &
2184/*
2185 ((uint)(PermissionMask.Modify |
1688 (uint)PermissionMask.Copy | 2186 (uint)PermissionMask.Copy |
1689 (uint)PermissionMask.Transfer)) != 2187 (uint)PermissionMask.Transfer)) !=
1690 ((uint)PermissionMask.Modify | 2188 ((uint)PermissionMask.Modify |
1691 (uint)PermissionMask.Copy | 2189 (uint)PermissionMask.Copy |
1692 (uint)PermissionMask.Transfer)) 2190 (uint)PermissionMask.Transfer))
2191*/
2192 (uint)(PermissionMask.Modify | PermissionMask.Copy)) !=
2193 (uint)(PermissionMask.Modify | PermissionMask.Copy))
1693 return false; 2194 return false;
1694 } 2195 }
1695 2196
@@ -1704,16 +2205,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1704 /// <param name="user"></param> 2205 /// <param name="user"></param>
1705 /// <param name="scene"></param> 2206 /// <param name="scene"></param>
1706 /// <returns></returns> 2207 /// <returns></returns>
1707 private bool CanViewNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) 2208 private bool CanViewNotecard(UUID notecard, UUID objectID, UUID userID)
1708 { 2209 {
1709 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2210 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1710 if (m_bypassPermissions) return m_bypassPermissionsValue; 2211 if (m_bypassPermissions) return m_bypassPermissionsValue;
1711 2212
2213 // A god is a god is a god
2214 if (IsAdministrator(userID))
2215 return true;
2216
1712 if (objectID == UUID.Zero) // User inventory 2217 if (objectID == UUID.Zero) // User inventory
1713 { 2218 {
1714 IInventoryService invService = m_scene.InventoryService; 2219 IInventoryService invService = m_scene.InventoryService;
1715 InventoryItemBase assetRequestItem = new InventoryItemBase(notecard, user); 2220 InventoryItemBase assetRequestItem = invService.GetItem(userID, notecard);
1716 assetRequestItem = invService.GetItem(assetRequestItem);
1717 if (assetRequestItem == null && LibraryRootFolder != null) // Library item 2221 if (assetRequestItem == null && LibraryRootFolder != null) // Library item
1718 { 2222 {
1719 assetRequestItem = LibraryRootFolder.FindItem(notecard); 2223 assetRequestItem = LibraryRootFolder.FindItem(notecard);
@@ -1731,40 +2235,29 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1731 } 2235 }
1732 else // Prim inventory 2236 else // Prim inventory
1733 { 2237 {
1734 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 2238 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1735
1736 if (part == null) 2239 if (part == null)
1737 return false; 2240 return false;
1738
1739 if (part.OwnerID != user)
1740 {
1741 if (part.GroupID == UUID.Zero)
1742 return false;
1743
1744 if (!IsGroupMember(part.GroupID, user, 0))
1745 return false;
1746 }
1747 2241
1748 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) 2242 SceneObjectGroup sog = part.ParentGroup;
2243 if (sog == null)
2244 return false;
2245
2246 uint perms = GetObjectPermissions(userID, sog, true);
2247 if((perms & (uint)PermissionMask.Modify) == 0)
1749 return false; 2248 return false;
1750 2249
1751 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); 2250 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard);
1752 2251
2252// if (ti == null || ti.InvType != (int)InventoryType.Notecard)
1753 if (ti == null) 2253 if (ti == null)
1754 return false; 2254 return false;
1755 2255
1756 if (ti.OwnerID != user) 2256 uint itperms = GetObjectItemPermissions(userID, ti);
1757 {
1758 if (ti.GroupID == UUID.Zero)
1759 return false;
1760
1761 if (!IsGroupMember(ti.GroupID, user, 0))
1762 return false;
1763 }
1764 2257
1765 // Notecards are always readable unless no copy 2258 // Notecards are always readable unless no copy
1766 // 2259 //
1767 if ((ti.CurrentPermissions & 2260 if ((itperms &
1768 (uint)PermissionMask.Copy) != 2261 (uint)PermissionMask.Copy) !=
1769 (uint)PermissionMask.Copy) 2262 (uint)PermissionMask.Copy)
1770 return false; 2263 return false;
@@ -1780,7 +2273,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1780 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2273 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1781 if (m_bypassPermissions) return m_bypassPermissionsValue; 2274 if (m_bypassPermissions) return m_bypassPermissionsValue;
1782 2275
1783 return GenericObjectPermission(userID, objectID, false); 2276 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
2277 if (sog == null)
2278 return false;
2279
2280 uint perms = GetObjectPermissions(userID, sog, true);
2281 if((perms & (uint)PermissionMask.Modify) == 0)
2282 return false;
2283 return true;
1784 } 2284 }
1785 2285
1786 private bool CanDelinkObject(UUID userID, UUID objectID) 2286 private bool CanDelinkObject(UUID userID, UUID objectID)
@@ -1788,10 +2288,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1788 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2288 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1789 if (m_bypassPermissions) return m_bypassPermissionsValue; 2289 if (m_bypassPermissions) return m_bypassPermissionsValue;
1790 2290
1791 return GenericObjectPermission(userID, objectID, false); 2291 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
2292 if (sog == null)
2293 return false;
2294
2295 uint perms = GetObjectPermissions(userID, sog, true);
2296 if((perms & (uint)PermissionMask.Modify) == 0)
2297 return false;
2298 return true;
1792 } 2299 }
1793 2300
1794 private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) 2301 private bool CanBuyLand(UUID userID, ILandObject parcel)
1795 { 2302 {
1796 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2303 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1797 if (m_bypassPermissions) return m_bypassPermissionsValue; 2304 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1804,6 +2311,138 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1804 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2311 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1805 if (m_bypassPermissions) return m_bypassPermissionsValue; 2312 if (m_bypassPermissions) return m_bypassPermissionsValue;
1806 2313
2314 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
2315 if (part == null)
2316 return false;
2317
2318 SceneObjectGroup sog = part.ParentGroup;
2319 if (sog == null)
2320 return false;
2321
2322 if(sog.OwnerID == userID || IsAdministrator(userID))
2323 return true;
2324
2325 if(sog.IsAttachment)
2326 return false;
2327
2328 UUID sogGroupID = sog.GroupID;
2329
2330 if(sogGroupID == UUID.Zero || sogGroupID != sog.OwnerID)
2331 return false;
2332
2333 TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID);
2334 if(ti == null)
2335 return false;
2336
2337 ulong powers = 0;
2338 if(GroupMemberPowers(sogGroupID, userID, ref powers))
2339 {
2340 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
2341 return true;
2342
2343 if((ti.EveryonePermissions & (uint)PermissionMask.Copy) != 0)
2344 return true;
2345 }
2346 return false;
2347 }
2348
2349 // object inventory to object inventory item drag and drop
2350 private bool CanDoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart)
2351 {
2352 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2353
2354 if (sourcePart == null || destPart == null || item == null)
2355 return false;
2356
2357 if (m_bypassPermissions)
2358 return m_bypassPermissionsValue;
2359
2360 SceneObjectGroup srcsog = sourcePart.ParentGroup;
2361 SceneObjectGroup destsog = destPart.ParentGroup;
2362 if (srcsog == null || destsog == null)
2363 return false;
2364
2365 // dest is locked
2366 if((destsog.EffectiveOwnerPerms & (uint)PermissionMask.Move) == 0)
2367 return false;
2368
2369 uint itperms = item.CurrentPermissions;
2370
2371 // if item is no copy the source is modifed
2372 if((itperms & (uint)PermissionMask.Copy) == 0 && (srcsog.EffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0)
2373 return false;
2374
2375 UUID srcOwner = srcsog.OwnerID;
2376 UUID destOwner = destsog.OwnerID;
2377 bool notSameOwner = srcOwner != destOwner;
2378
2379 if(notSameOwner)
2380 {
2381 if((itperms & (uint)PermissionMask.Transfer) == 0)
2382 return false;
2383
2384 // scripts can't be droped
2385 if(item.InvType == (int)InventoryType.LSL)
2386 return false;
2387
2388 if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
2389 return false;
2390 }
2391 else
2392 {
2393 if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0 &&
2394 (destsog.EffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0)
2395 return false;
2396 }
2397
2398 return true;
2399 }
2400
2401 private bool CanDropInObjectInv(InventoryItemBase item, ScenePresence sp, SceneObjectPart destPart)
2402 {
2403 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2404
2405 if (sp == null || sp.IsDeleted || destPart == null || item == null)
2406 return false;
2407
2408 SceneObjectGroup destsog = destPart.ParentGroup;
2409 if (destsog == null || destsog.IsDeleted)
2410 return false;
2411
2412 if (m_bypassPermissions)
2413 return m_bypassPermissionsValue;
2414
2415 if(sp.IsGod)
2416 return true;
2417
2418 // dest is locked
2419 if((destsog.EffectiveOwnerPerms & (uint)PermissionMask.Move) == 0)
2420 return false;
2421
2422 UUID destOwner = destsog.OwnerID;
2423 UUID spID = sp.UUID;
2424 bool spNotOwner = spID != destOwner;
2425
2426 // scripts can't be droped
2427 if(spNotOwner && item.InvType == (int)InventoryType.LSL)
2428 return false;
2429
2430 if(spNotOwner || item.Owner != destOwner)
2431 {
2432 // no copy item will be moved if it has transfer
2433 uint itperms = item.CurrentPermissions;
2434 if((itperms & (uint)PermissionMask.Transfer) == 0)
2435 return false;
2436 }
2437
2438 // allowdrop is a root part thing and does bypass modify rights
2439 if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
2440 return true;
2441
2442 uint perms = GetObjectPermissions(spID, destsog, true);
2443 if((perms & (uint)PermissionMask.Modify) == 0)
2444 return false;
2445
1807 return true; 2446 return true;
1808 } 2447 }
1809 2448
@@ -1812,6 +2451,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1812 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2451 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1813 if (m_bypassPermissions) return m_bypassPermissionsValue; 2452 if (m_bypassPermissions) return m_bypassPermissionsValue;
1814 2453
2454 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
2455 if (part == null)
2456 return false;
2457
2458 SceneObjectGroup sog = part.ParentGroup;
2459 if (sog == null)
2460 return false;
2461
2462 uint perms = GetObjectPermissions(userID, sog, true);
2463 if((perms & (uint)PermissionMask.Modify) == 0)
2464 return false;
2465
2466 TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID);
2467 if(ti == null)
2468 return false;
2469
2470 //TODO item perm ?
1815 return true; 2471 return true;
1816 } 2472 }
1817 2473
@@ -1828,31 +2484,28 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1828 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2484 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1829 if (m_bypassPermissions) return m_bypassPermissionsValue; 2485 if (m_bypassPermissions) return m_bypassPermissionsValue;
1830 2486
1831 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1832 ScenePresence p = m_scene.GetScenePresence(userID); 2487 ScenePresence p = m_scene.GetScenePresence(userID);
1833 2488
1834 if (part == null || p == null) 2489 if (p == null)
2490 return false;
2491
2492 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
2493 if (sog == null)
2494 return false;
2495
2496 uint perms = GetObjectPermissions(userID, sog, true);
2497 if((perms & (uint)PermissionMask.Modify) == 0)
1835 return false; 2498 return false;
1836 2499
1837 if (!IsAdministrator(userID)) 2500 if ((int)InventoryType.LSL == invType)
1838 { 2501 {
1839 if (part.OwnerID != userID) 2502 if (m_allowedScriptCreators == UserSet.Administrators)
1840 { 2503 return false;
1841 // Group permissions
1842 if ((part.GroupID == UUID.Zero) || (p.ControllingClient.GetGroupPowers(part.GroupID) == 0) || ((part.GroupMask & (uint)PermissionMask.Modify) == 0))
1843 return false;
1844 } else {
1845 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1846 return false;
1847 }
1848 if ((int)InventoryType.LSL == invType)
1849 if (m_allowedScriptCreators == UserSet.Administrators)
1850 return false;
1851 } 2504 }
1852 2505
1853 return true; 2506 return true;
1854 } 2507 }
1855 2508
1856 /// <summary> 2509 /// <summary>
1857 /// Check whether the specified user is allowed to create the given inventory type in their inventory. 2510 /// Check whether the specified user is allowed to create the given inventory type in their inventory.
1858 /// </summary> 2511 /// </summary>
@@ -1867,10 +2520,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1867 if ((int)InventoryType.LSL == invType) 2520 if ((int)InventoryType.LSL == invType)
1868 if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID)) 2521 if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID))
1869 return false; 2522 return false;
1870 2523
1871 return true; 2524 return true;
1872 } 2525 }
1873 2526
1874 /// <summary> 2527 /// <summary>
1875 /// Check whether the specified user is allowed to copy the given inventory type in their inventory. 2528 /// Check whether the specified user is allowed to copy the given inventory type in their inventory.
1876 /// </summary> 2529 /// </summary>
@@ -1884,7 +2537,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1884 2537
1885 return true; 2538 return true;
1886 } 2539 }
1887 2540
1888 /// <summary> 2541 /// <summary>
1889 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory. 2542 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
1890 /// </summary> 2543 /// </summary>
@@ -1898,7 +2551,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1898 2551
1899 return true; 2552 return true;
1900 } 2553 }
1901 2554
1902 /// <summary> 2555 /// <summary>
1903 /// Check whether the specified user is allowed to delete the given inventory item from their own inventory. 2556 /// Check whether the specified user is allowed to delete the given inventory item from their own inventory.
1904 /// </summary> 2557 /// </summary>
@@ -1921,22 +2574,22 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1921 return true; 2574 return true;
1922 } 2575 }
1923 2576
1924 private bool CanResetScript(UUID prim, UUID script, UUID agentID, Scene scene) 2577 private bool CanResetScript(UUID primID, UUID script, UUID agentID)
1925 { 2578 {
1926 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2579 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1927 if (m_bypassPermissions) return m_bypassPermissionsValue; 2580 if (m_bypassPermissions) return m_bypassPermissionsValue;
1928 2581
1929 SceneObjectPart part = m_scene.GetSceneObjectPart(prim); 2582 SceneObjectGroup sog = m_scene.GetGroupByPrim(primID);
1930 2583 if (sog == null)
1931 // If we selected a sub-prim to reset, prim won't represent the object, but only a part. 2584 return false;
1932 // We have to check the permissions of the object, though.
1933 if (part.ParentID != 0) prim = part.ParentUUID;
1934 2585
1935 // You can reset the scripts in any object you can edit 2586 uint perms = GetObjectPermissions(agentID, sog, false);
1936 return GenericObjectPermission(agentID, prim, false); 2587 if((perms & (uint)PermissionMask.Modify) == 0) // ??
2588 return false;
2589 return true;
1937 } 2590 }
1938 2591
1939 private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) 2592 private bool CanCompileScript(UUID ownerUUID, int scriptType)
1940 { 2593 {
1941 //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType); 2594 //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType);
1942 switch (scriptType) { 2595 switch (scriptType) {
@@ -1970,64 +2623,71 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1970 } 2623 }
1971 return(false); 2624 return(false);
1972 } 2625 }
1973 2626
1974 private bool CanControlPrimMedia(UUID agentID, UUID primID, int face) 2627 private bool CanControlPrimMedia(UUID agentID, UUID primID, int face)
1975 { 2628 {
1976// m_log.DebugFormat( 2629// m_log.DebugFormat(
1977// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}", 2630// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}",
1978// agentID, primID, face); 2631// agentID, primID, face);
1979 2632
1980 if (null == MoapModule) 2633 if (null == MoapModule)
1981 return false; 2634 return false;
1982 2635
1983 SceneObjectPart part = m_scene.GetSceneObjectPart(primID); 2636 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
1984 if (null == part) 2637 if (null == part)
1985 return false; 2638 return false;
1986 2639
1987 MediaEntry me = MoapModule.GetMediaEntry(part, face); 2640 MediaEntry me = MoapModule.GetMediaEntry(part, face);
1988 2641
1989 // If there is no existing media entry then it can be controlled (in this context, created). 2642 // If there is no existing media entry then it can be controlled (in this context, created).
1990 if (null == me) 2643 if (null == me)
1991 return true; 2644 return true;
1992 2645
1993// m_log.DebugFormat( 2646// m_log.DebugFormat(
1994// "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}", 2647// "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}",
1995// agentID, primID, face, me.ControlPermissions); 2648// agentID, primID, face, me.ControlPermissions);
1996 2649
1997 return GenericObjectPermission(agentID, part.ParentGroup.UUID, true); 2650 SceneObjectGroup sog = part.ParentGroup;
2651 if (sog == null)
2652 return false;
2653
2654 uint perms = GetObjectPermissions(agentID, sog, false);
2655 if((perms & (uint)PermissionMask.Modify) == 0)
2656 return false;
2657 return true;
1998 } 2658 }
1999 2659
2000 private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face) 2660 private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face)
2001 { 2661 {
2002// m_log.DebugFormat( 2662// m_log.DebugFormat(
2003// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}", 2663// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}",
2004// agentID, primID, face); 2664// agentID, primID, face);
2005 2665
2006 if (null == MoapModule) 2666 if (null == MoapModule)
2007 return false; 2667 return false;
2008 2668
2009 SceneObjectPart part = m_scene.GetSceneObjectPart(primID); 2669 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
2010 if (null == part) 2670 if (null == part)
2011 return false; 2671 return false;
2012 2672
2013 MediaEntry me = MoapModule.GetMediaEntry(part, face); 2673 MediaEntry me = MoapModule.GetMediaEntry(part, face);
2014 2674
2015 // If there is no existing media entry then it can be controlled (in this context, created). 2675 // If there is no existing media entry then it can be controlled (in this context, created).
2016 if (null == me) 2676 if (null == me)
2017 return true; 2677 return true;
2018 2678
2019// m_log.DebugFormat( 2679// m_log.DebugFormat(
2020// "[PERMISSIONS]: Checking CanInteractWithPrimMedia for {0} on {1} face {2} with interact permissions {3}", 2680// "[PERMISSIONS]: Checking CanInteractWithPrimMedia for {0} on {1} face {2} with interact permissions {3}",
2021// agentID, primID, face, me.InteractPermissions); 2681// agentID, primID, face, me.InteractPermissions);
2022 2682
2023 return GenericPrimMediaPermission(part, agentID, me.InteractPermissions); 2683 return GenericPrimMediaPermission(part, agentID, me.InteractPermissions);
2024 } 2684 }
2025 2685
2026 private bool GenericPrimMediaPermission(SceneObjectPart part, UUID agentID, MediaPermission perms) 2686 private bool GenericPrimMediaPermission(SceneObjectPart part, UUID agentID, MediaPermission perms)
2027 { 2687 {
2028// if (IsAdministrator(agentID)) 2688// if (IsAdministrator(agentID))
2029// return true; 2689// return true;
2030 2690
2031 if ((perms & MediaPermission.Anyone) == MediaPermission.Anyone) 2691 if ((perms & MediaPermission.Anyone) == MediaPermission.Anyone)
2032 return true; 2692 return true;
2033 2693
@@ -2036,13 +2696,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions
2036 if (agentID == part.OwnerID) 2696 if (agentID == part.OwnerID)
2037 return true; 2697 return true;
2038 } 2698 }
2039 2699
2040 if ((perms & MediaPermission.Group) == MediaPermission.Group) 2700 if ((perms & MediaPermission.Group) == MediaPermission.Group)
2041 { 2701 {
2042 if (IsGroupMember(part.GroupID, agentID, 0)) 2702 if (IsGroupMember(part.GroupID, agentID, 0))
2043 return true; 2703 return true;
2044 } 2704 }
2045 2705
2046 return false; 2706 return false;
2047 } 2707 }
2048 } 2708 }
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
index bb4dcce..49246a2 100644
--- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using GridRegion = OpenSim.Services.Interfaces.GridRegion;
43 44
44namespace OpenSim.Region.CoreModules.World.Objects.Commands 45namespace OpenSim.Region.CoreModules.World.Objects.Commands
45{ 46{
@@ -53,24 +54,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
53 private ICommandConsole m_console; 54 private ICommandConsole m_console;
54 55
55 public string Name { get { return "Region Commands Module"; } } 56 public string Name { get { return "Region Commands Module"; } }
56 57
57 public Type ReplaceableInterface { get { return null; } } 58 public Type ReplaceableInterface { get { return null; } }
58 59
59 public void Initialise(IConfigSource source) 60 public void Initialise(IConfigSource source)
60 { 61 {
61// m_log.DebugFormat("[REGION COMMANDS MODULE]: INITIALIZED MODULE"); 62// m_log.DebugFormat("[REGION COMMANDS MODULE]: INITIALIZED MODULE");
62 } 63 }
63 64
64 public void PostInitialise() 65 public void PostInitialise()
65 { 66 {
66// m_log.DebugFormat("[REGION COMMANDS MODULE]: POST INITIALIZED MODULE"); 67// m_log.DebugFormat("[REGION COMMANDS MODULE]: POST INITIALIZED MODULE");
67 } 68 }
68 69
69 public void Close() 70 public void Close()
70 { 71 {
71// m_log.DebugFormat("[REGION COMMANDS MODULE]: CLOSED MODULE"); 72// m_log.DebugFormat("[REGION COMMANDS MODULE]: CLOSED MODULE");
72 } 73 }
73 74
74 public void AddRegion(Scene scene) 75 public void AddRegion(Scene scene)
75 { 76 {
76// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); 77// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
@@ -86,14 +87,14 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
86 m_console.Commands.AddCommand( 87 m_console.Commands.AddCommand(
87 "Regions", false, "show region", 88 "Regions", false, "show region",
88 "show region", 89 "show region",
89 "Show control information for the currently selected region (host name, max physical prim size, etc).", 90 "Show control information for the currently selected region (host name, max physical prim size, etc).",
90 "A synonym for \"region get\"", 91 "A synonym for \"region get\"",
91 HandleShowRegion); 92 HandleShowRegion);
92 93
93 m_console.Commands.AddCommand( 94 m_console.Commands.AddCommand(
94 "Regions", false, "region get", 95 "Regions", false, "region get",
95 "region get", 96 "region get",
96 "Show control information for the currently selected region (host name, max physical prim size, etc).", 97 "Show control information for the currently selected region (host name, max physical prim size, etc).",
97 "Some parameters can be set with the \"region set\" command.\n" 98 "Some parameters can be set with the \"region set\" command.\n"
98 + "Others must be changed via a viewer (usually via the region/estate dialog box).", 99 + "Others must be changed via a viewer (usually via the region/estate dialog box).",
99 HandleShowRegion); 100 HandleShowRegion);
@@ -107,6 +108,15 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
107 + "max-agent-limit <int> - Maximum root agent limit. agent-limit cannot exceed this." 108 + "max-agent-limit <int> - Maximum root agent limit. agent-limit cannot exceed this."
108 + " This is not persisted over restart - to set it every time you must add a MaxAgents entry to your regions file.", 109 + " This is not persisted over restart - to set it every time you must add a MaxAgents entry to your regions file.",
109 HandleRegionSet); 110 HandleRegionSet);
111
112 m_console.Commands.AddCommand("Regions", false, "show neighbours",
113 "show neighbours",
114 "Shows the local region neighbours", HandleShowNeighboursCommand);
115
116 m_console.Commands.AddCommand("Regions", false, "show regionsinview",
117 "show regionsinview",
118 "Shows regions that can be seen from a region", HandleShowRegionsInViewCommand);
119
110 } 120 }
111 121
112 public void RemoveRegion(Scene scene) 122 public void RemoveRegion(Scene scene)
@@ -194,7 +204,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
194 { 204 {
195 MainConsole.Instance.OutputFormat("Usage: region set <param> <value>"); 205 MainConsole.Instance.OutputFormat("Usage: region set <param> <value>");
196 return; 206 return;
197 } 207 }
198 208
199 string param = args[2]; 209 string param = args[2];
200 string rawValue = args[3]; 210 string rawValue = args[3];
@@ -215,7 +225,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
215 if (newValue > ri.AgentCapacity) 225 if (newValue > ri.AgentCapacity)
216 { 226 {
217 MainConsole.Instance.OutputFormat( 227 MainConsole.Instance.OutputFormat(
218 "Cannot set {0} to {1} in {2} as max-agent-limit is {3}", "agent-limit", 228 "Cannot set {0} to {1} in {2} as max-agent-limit is {3}", "agent-limit",
219 newValue, m_scene.Name, ri.AgentCapacity); 229 newValue, m_scene.Name, ri.AgentCapacity);
220 } 230 }
221 else 231 else
@@ -271,8 +281,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
271 float totalFrameTime = stats[8]; 281 float totalFrameTime = stats[8];
272// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator 282// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator
273 float physicsFrameTime = stats[10]; 283 float physicsFrameTime = stats[10];
274 float otherFrameTime = stats[11]; 284 float otherFrameTime = stats[12];
275// float imageFrameTime = stats.StatsBlock[12].StatValue; // Ignored 285// float imageFrameTime = stats.StatsBlock[11].StatValue; // Ignored
276 float inPacketsPerSecond = stats[13]; 286 float inPacketsPerSecond = stats[13];
277 float outPacketsPerSecond = stats[14]; 287 float outPacketsPerSecond = stats[14];
278 float unackedBytes = stats[15]; 288 float unackedBytes = stats[15];
@@ -280,7 +290,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
280 float pendingDownloads = stats[17]; 290 float pendingDownloads = stats[17];
281 float pendingUploads = stats[18]; 291 float pendingUploads = stats[18];
282 float activeScripts = stats[19]; 292 float activeScripts = stats[19];
283 float scriptLinesPerSecond = stats[20]; 293 float scriptLinesPerSecond = stats[23];
284 294
285 StringBuilder sb = new StringBuilder(); 295 StringBuilder sb = new StringBuilder();
286 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName); 296 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName);
@@ -309,5 +319,60 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
309 319
310 MainConsole.Instance.Output(sb.ToString()); 320 MainConsole.Instance.Output(sb.ToString());
311 } 321 }
322
323 public void HandleShowNeighboursCommand(string module, string[] cmdparams)
324 {
325 if(m_scene == null)
326 return;
327
328 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
329 return;
330
331 System.Text.StringBuilder caps = new System.Text.StringBuilder();
332
333 RegionInfo sr = m_scene.RegionInfo;
334 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", sr.RegionName, sr.RegionID);
335 List<GridRegion> regions = m_scene.GridService.GetNeighbours(sr.ScopeID, sr.RegionID);
336 foreach (GridRegion r in regions)
337 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
338
339 MainConsole.Instance.Output(caps.ToString());
340 }
341
342 public void HandleShowRegionsInViewCommand(string module, string[] cmdparams)
343 {
344 if(m_scene == null)
345 return;
346
347 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
348 return;
349
350 System.Text.StringBuilder caps = new System.Text.StringBuilder();
351 int maxview = (int)m_scene.MaxRegionViewDistance;
352 RegionInfo sr = m_scene.RegionInfo;
353 caps.AppendFormat("*** Regions that can be seen from {0} ({1}) (MaxRegionViewDistance {2}m) ***\n", sr.RegionName, sr.RegionID, maxview);
354 int startX = (int)sr.WorldLocX;
355 int endX = startX + (int)sr.RegionSizeX;
356 int startY = (int)sr.WorldLocY;
357 int endY = startY + (int)sr.RegionSizeY;
358 startX -= maxview;
359 if(startX < 0 )
360 startX = 0;
361 startY -= maxview;
362 if(startY < 0)
363 startY = 0;
364 endX += maxview;
365 endY += maxview;
366
367 List<GridRegion> regions = m_scene.GridService.GetRegionRange(sr.ScopeID, startX, endX, startY, endY);
368 foreach (GridRegion r in regions)
369 {
370 if(r.RegionHandle == sr.RegionHandle)
371 continue;
372 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
373 }
374
375 MainConsole.Instance.Output(caps.ToString());
376 }
312 } 377 }
313} \ No newline at end of file 378}
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 75a8295..bb3b860 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -29,6 +29,8 @@ using System;
29using System.Linq; 29using System.Linq;
30using System.Reflection; 30using System.Reflection;
31using System.Timers; 31using System.Timers;
32using System.IO;
33using System.Diagnostics;
32using System.Threading; 34using System.Threading;
33using System.Collections.Generic; 35using System.Collections.Generic;
34using log4net; 36using log4net;
@@ -57,30 +59,46 @@ namespace OpenSim.Region.CoreModules.World.Region
57 protected UUID m_Initiator; 59 protected UUID m_Initiator;
58 protected bool m_Notice = false; 60 protected bool m_Notice = false;
59 protected IDialogModule m_DialogModule = null; 61 protected IDialogModule m_DialogModule = null;
62 protected string m_MarkerPath = String.Empty;
63 private int[] m_CurrentAlerts = null;
64 protected bool m_shortCircuitDelays = false;
65 protected bool m_rebootAll = false;
60 66
61 public void Initialise(IConfigSource config) 67 public void Initialise(IConfigSource config)
62 { 68 {
69 IConfig restartConfig = config.Configs["RestartModule"];
70 if (restartConfig != null)
71 {
72 m_MarkerPath = restartConfig.GetString("MarkerPath", String.Empty);
73 }
74 IConfig startupConfig = config.Configs["Startup"];
75 m_shortCircuitDelays = startupConfig.GetBoolean("SkipDelayOnEmptyRegion", false);
76 m_rebootAll = startupConfig.GetBoolean("InworldRestartShutsDown", false);
63 } 77 }
64 78
65 public void AddRegion(Scene scene) 79 public void AddRegion(Scene scene)
66 { 80 {
81 if (m_MarkerPath != String.Empty)
82 File.Delete(Path.Combine(m_MarkerPath,
83 scene.RegionInfo.RegionID.ToString()));
84
67 m_Scene = scene; 85 m_Scene = scene;
68 86
69 scene.RegisterModuleInterface<IRestartModule>(this); 87 scene.RegisterModuleInterface<IRestartModule>(this);
70 MainConsole.Instance.Commands.AddCommand("Regions", 88 MainConsole.Instance.Commands.AddCommand("Regions",
71 false, "region restart bluebox", 89 false, "region restart bluebox",
72 "region restart bluebox <message> <delta seconds>+", 90 "region restart bluebox <message> <delta seconds>+",
73 "Schedule a region restart", 91 "Schedule a region restart",
74 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.", 92 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.",
75 HandleRegionRestart); 93 HandleRegionRestart);
76 94
77 MainConsole.Instance.Commands.AddCommand("Regions", 95 MainConsole.Instance.Commands.AddCommand("Regions",
78 false, "region restart notice", 96 false, "region restart notice",
79 "region restart notice <message> <delta seconds>+", 97 "region restart notice <message> <delta seconds>+",
80 "Schedule a region restart", 98 "Schedule a region restart",
81 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.", 99 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.",
82 HandleRegionRestart); 100 HandleRegionRestart);
83 101
84 MainConsole.Instance.Commands.AddCommand("Regions", 102 MainConsole.Instance.Commands.AddCommand("Regions",
85 false, "region restart abort", 103 false, "region restart abort",
86 "region restart abort [<message>]", 104 "region restart abort [<message>]",
@@ -118,10 +136,14 @@ namespace OpenSim.Region.CoreModules.World.Region
118 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice) 136 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice)
119 { 137 {
120 if (m_CountdownTimer != null) 138 if (m_CountdownTimer != null)
121 return; 139 {
140 m_CountdownTimer.Stop();
141 m_CountdownTimer = null;
142 }
122 143
123 if (alerts == null) 144 if (alerts == null)
124 { 145 {
146 CreateMarkerFile();
125 m_Scene.RestartNow(); 147 m_Scene.RestartNow();
126 return; 148 return;
127 } 149 }
@@ -129,25 +151,28 @@ namespace OpenSim.Region.CoreModules.World.Region
129 m_Message = message; 151 m_Message = message;
130 m_Initiator = initiator; 152 m_Initiator = initiator;
131 m_Notice = notice; 153 m_Notice = notice;
154 m_CurrentAlerts = alerts;
132 m_Alerts = new List<int>(alerts); 155 m_Alerts = new List<int>(alerts);
133 m_Alerts.Sort(); 156 m_Alerts.Sort();
134 m_Alerts.Reverse(); 157 m_Alerts.Reverse();
135 158
136 if (m_Alerts[0] == 0) 159 if (m_Alerts[0] == 0)
137 { 160 {
161 CreateMarkerFile();
138 m_Scene.RestartNow(); 162 m_Scene.RestartNow();
139 return; 163 return;
140 } 164 }
141 165
142 int nextInterval = DoOneNotice(); 166 int nextInterval = DoOneNotice(true);
143 167
144 SetTimer(nextInterval); 168 SetTimer(nextInterval);
145 } 169 }
146 170
147 public int DoOneNotice() 171 public int DoOneNotice(bool sendOut)
148 { 172 {
149 if (m_Alerts.Count == 0 || m_Alerts[0] == 0) 173 if (m_Alerts.Count == 0 || m_Alerts[0] == 0)
150 { 174 {
175 CreateMarkerFile();
151 m_Scene.RestartNow(); 176 m_Scene.RestartNow();
152 return 0; 177 return 0;
153 } 178 }
@@ -163,39 +188,42 @@ namespace OpenSim.Region.CoreModules.World.Region
163 nextAlert = m_Alerts[1]; 188 nextAlert = m_Alerts[1];
164 break; 189 break;
165 } 190 }
166 191
167 int currentAlert = m_Alerts[0]; 192 int currentAlert = m_Alerts[0];
168 193
169 m_Alerts.RemoveAt(0); 194 m_Alerts.RemoveAt(0);
170 195
171 int minutes = currentAlert / 60; 196 if (sendOut)
172 string currentAlertString = String.Empty;
173 if (minutes > 0)
174 { 197 {
175 if (minutes == 1) 198 int minutes = currentAlert / 60;
176 currentAlertString += "1 minute"; 199 string currentAlertString = String.Empty;
177 else 200 if (minutes > 0)
178 currentAlertString += String.Format("{0} minutes", minutes); 201 {
202 if (minutes == 1)
203 currentAlertString += "1 minute";
204 else
205 currentAlertString += String.Format("{0} minutes", minutes);
206 if ((currentAlert % 60) != 0)
207 currentAlertString += " and ";
208 }
179 if ((currentAlert % 60) != 0) 209 if ((currentAlert % 60) != 0)
180 currentAlertString += " and "; 210 {
181 } 211 int seconds = currentAlert % 60;
182 if ((currentAlert % 60) != 0) 212 if (seconds == 1)
183 { 213 currentAlertString += "1 second";
184 int seconds = currentAlert % 60; 214 else
185 if (seconds == 1) 215 currentAlertString += String.Format("{0} seconds", seconds);
186 currentAlertString += "1 second"; 216 }
187 else
188 currentAlertString += String.Format("{0} seconds", seconds);
189 }
190 217
191 string msg = String.Format(m_Message, currentAlertString); 218 string msg = String.Format(m_Message, currentAlertString);
192 219
193 if (m_DialogModule != null && msg != String.Empty) 220 if (m_DialogModule != null && msg != String.Empty)
194 { 221 {
195 if (m_Notice) 222 if (m_Notice)
196 m_DialogModule.SendGeneralAlert(msg); 223 m_DialogModule.SendGeneralAlert(msg);
197 else 224 else
198 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg); 225 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg);
226 }
199 } 227 }
200 228
201 return currentAlert - nextAlert; 229 return currentAlert - nextAlert;
@@ -219,14 +247,42 @@ namespace OpenSim.Region.CoreModules.World.Region
219 else 247 else
220 { 248 {
221 m_log.WarnFormat( 249 m_log.WarnFormat(
222 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval", 250 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
223 intervalSeconds, m_Scene.Name); 251 intervalSeconds, m_Scene.Name);
224 } 252 }
225 } 253 }
226 254
227 private void OnTimer(object source, ElapsedEventArgs e) 255 private void OnTimer(object source, ElapsedEventArgs e)
228 { 256 {
229 SetTimer(DoOneNotice()); 257 int nextInterval = DoOneNotice(true);
258 if (m_shortCircuitDelays)
259 {
260 if (CountAgents() == 0)
261 {
262 m_Scene.RestartNow();
263 return;
264 }
265 }
266
267 SetTimer(nextInterval);
268 }
269
270 public void DelayRestart(int seconds, string message)
271 {
272 if (m_CountdownTimer == null)
273 return;
274
275 m_CountdownTimer.Stop();
276 m_CountdownTimer = null;
277
278 m_Alerts = new List<int>(m_CurrentAlerts);
279 m_Alerts.Add(seconds);
280 m_Alerts.Sort();
281 m_Alerts.Reverse();
282
283 int nextInterval = DoOneNotice(false);
284
285 SetTimer(nextInterval);
230 } 286 }
231 287
232 public void AbortRestart(string message) 288 public void AbortRestart(string message)
@@ -236,10 +292,14 @@ namespace OpenSim.Region.CoreModules.World.Region
236 m_CountdownTimer.Stop(); 292 m_CountdownTimer.Stop();
237 m_CountdownTimer = null; 293 m_CountdownTimer = null;
238 if (m_DialogModule != null && message != String.Empty) 294 if (m_DialogModule != null && message != String.Empty)
239 m_DialogModule.SendGeneralAlert(message); 295 m_DialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
296 //m_DialogModule.SendGeneralAlert(message);
240 } 297 }
298 if (m_MarkerPath != String.Empty)
299 File.Delete(Path.Combine(m_MarkerPath,
300 m_Scene.RegionInfo.RegionID.ToString()));
241 } 301 }
242 302
243 private void HandleRegionRestart(string module, string[] args) 303 private void HandleRegionRestart(string module, string[] args)
244 { 304 {
245 if (!(MainConsole.Instance.ConsoleScene is Scene)) 305 if (!(MainConsole.Instance.ConsoleScene is Scene))
@@ -282,5 +342,55 @@ namespace OpenSim.Region.CoreModules.World.Region
282 342
283 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 343 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
284 } 344 }
345
346 protected void CreateMarkerFile()
347 {
348 if (m_MarkerPath == String.Empty)
349 return;
350
351 string path = Path.Combine(m_MarkerPath, m_Scene.RegionInfo.RegionID.ToString());
352 try
353 {
354 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
355 FileStream fs = File.Create(path);
356 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
357 Byte[] buf = enc.GetBytes(pidstring);
358 fs.Write(buf, 0, buf.Length);
359 fs.Close();
360 }
361 catch (Exception)
362 {
363 }
364 }
365
366 int CountAgents()
367 {
368 m_log.Info("[RESTART MODULE]: Counting affected avatars");
369 int agents = 0;
370
371 if (m_rebootAll)
372 {
373 foreach (Scene s in SceneManager.Instance.Scenes)
374 {
375 foreach (ScenePresence sp in s.GetScenePresences())
376 {
377 if (!sp.IsChildAgent && !sp.IsNPC)
378 agents++;
379 }
380 }
381 }
382 else
383 {
384 foreach (ScenePresence sp in m_Scene.GetScenePresences())
385 {
386 if (!sp.IsChildAgent && !sp.IsNPC)
387 agents++;
388 }
389 }
390
391 m_log.InfoFormat("[RESTART MODULE]: Avatars in region: {0}", agents);
392
393 return agents;
394 }
285 } 395 }
286} \ No newline at end of file 396}
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs
index 65f464a..52a80d6 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
69 MemoryStream stream = new MemoryStream(); 69 MemoryStream stream = new MemoryStream();
70 XmlTextWriter formatter = new XmlTextWriter(stream, Encoding.UTF8); 70 XmlTextWriter formatter = new XmlTextWriter(stream, Encoding.UTF8);
71 XmlDocument doc = new XmlDocument(); 71 XmlDocument doc = new XmlDocument();
72 72 doc.XmlResolver=null;
73 doc.LoadXml(xmlstream); 73 doc.LoadXml(xmlstream);
74 formatter.Formatting = Formatting.Indented; 74 formatter.Formatting = Formatting.Indented;
75 doc.WriteContentTo(formatter); 75 doc.WriteContentTo(formatter);
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
index e0247d9..c9bc335 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SerialiserModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SerialiserModule")]
46 public class SerialiserModule : ISharedRegionModule, IRegionSerialiserModule 46 public class SerialiserModule : ISharedRegionModule, IRegionSerialiserModule
47 { 47 {
48 private static readonly ILog m_log = 48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51// private Commander m_commander = new Commander("export"); 51// private Commander m_commander = new Commander("export");
@@ -55,15 +55,15 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
55 55
56 #region ISharedRegionModule Members 56 #region ISharedRegionModule Members
57 57
58 public Type ReplaceableInterface 58 public Type ReplaceableInterface
59 { 59 {
60 get { return null; } 60 get { return null; }
61 } 61 }
62 62
63 public void Initialise(IConfigSource source) 63 public void Initialise(IConfigSource source)
64 { 64 {
65 IConfig config = source.Configs["Serialiser"]; 65 IConfig config = source.Configs["Serialiser"];
66 if (config != null) 66 if (config != null)
67 { 67 {
68 m_savedir = config.GetString("save_dir", m_savedir); 68 m_savedir = config.GetString("save_dir", m_savedir);
69 } 69 }
@@ -150,7 +150,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
150 { 150 {
151 SceneXmlLoader.SavePrimsToXml2(scene, stream, min, max); 151 SceneXmlLoader.SavePrimsToXml2(scene, stream, min, max);
152 } 152 }
153 153
154 public void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName) 154 public void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName)
155 { 155 {
156 SceneXmlLoader.SaveNamedPrimsToXml2(scene, primName, fileName); 156 SceneXmlLoader.SaveNamedPrimsToXml2(scene, primName, fileName);
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index a5bb1a7..23475a1 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
43 [TestFixture] 43 [TestFixture]
44 public class SerialiserTests : OpenSimTestCase 44 public class SerialiserTests : OpenSimTestCase
45 { 45 {
46 private const string ObjectRootPartStubXml = 46 private const string ObjectRootPartStubXml =
47@"<SceneObjectGroup> 47@"<SceneObjectGroup>
48 <RootPart> 48 <RootPart>
49 <SceneObjectPart xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""> 49 <SceneObjectPart xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
@@ -149,9 +149,9 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
149 <llsd> 149 <llsd>
150 <map> 150 <map>
151 <key>MyNamespace</key> 151 <key>MyNamespace</key>
152 <map> 152 <map>
153 <key>MyStore</key> 153 <key>MyStore</key>
154 <map> 154 <map>
155 <key>the answer</key> 155 <key>the answer</key>
156 <integer>42</integer> 156 <integer>42</integer>
157 </map> 157 </map>
@@ -162,12 +162,12 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
162 </SceneObjectPart> 162 </SceneObjectPart>
163 </RootPart>"; 163 </RootPart>";
164 164
165 private const string ObjectWithNoOtherPartsXml = ObjectRootPartStubXml + 165 private const string ObjectWithNoOtherPartsXml = ObjectRootPartStubXml +
166@" 166@"
167 <OtherParts /> 167 <OtherParts />
168</SceneObjectGroup>"; 168</SceneObjectGroup>";
169 169
170 private const string ObjectWithOtherPartsXml = ObjectRootPartStubXml + 170 private const string ObjectWithOtherPartsXml = ObjectRootPartStubXml +
171@" 171@"
172 <OtherParts> 172 <OtherParts>
173 <Part> 173 <Part>
@@ -574,9 +574,9 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
574 <llsd> 574 <llsd>
575 <map> 575 <map>
576 <key>MyNamespace</key> 576 <key>MyNamespace</key>
577 <map> 577 <map>
578 <key>MyStore</key> 578 <key>MyStore</key>
579 <map> 579 <map>
580 <key>last words</key> 580 <key>last words</key>
581 <string>Rosebud</string> 581 <string>Rosebud</string>
582 </map> 582 </map>
@@ -636,7 +636,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
636 Assert.That(part.Name, Is.EqualTo("PrimMyRide")); 636 Assert.That(part.Name, Is.EqualTo("PrimMyRide"));
637 OSDMap store = part.DynAttrs.GetStore("MyNamespace", "MyStore"); 637 OSDMap store = part.DynAttrs.GetStore("MyNamespace", "MyStore");
638 Assert.AreEqual(42, store["the answer"].AsInteger()); 638 Assert.AreEqual(42, store["the answer"].AsInteger());
639 } 639 }
640 640
641 { 641 {
642 SceneObjectPart part = parts[1]; 642 SceneObjectPart part = parts[1];
@@ -720,10 +720,12 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
720 string xml = SceneObjectSerializer.ToOriginalXmlFormat(so); 720 string xml = SceneObjectSerializer.ToOriginalXmlFormat(so);
721 721
722 XmlTextReader xtr = new XmlTextReader(new StringReader(xml)); 722 XmlTextReader xtr = new XmlTextReader(new StringReader(xml));
723 xtr.ProhibitDtd = true;
724
723 xtr.ReadStartElement("SceneObjectGroup"); 725 xtr.ReadStartElement("SceneObjectGroup");
724 xtr.ReadStartElement("RootPart"); 726 xtr.ReadStartElement("RootPart");
725 xtr.ReadStartElement("SceneObjectPart"); 727 xtr.ReadStartElement("SceneObjectPart");
726 728
727 UUID uuid = UUID.Zero; 729 UUID uuid = UUID.Zero;
728 string name = null; 730 string name = null;
729 UUID creatorId = UUID.Zero; 731 UUID creatorId = UUID.Zero;
@@ -733,7 +735,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
733 { 735 {
734 if (xtr.NodeType != XmlNodeType.Element) 736 if (xtr.NodeType != XmlNodeType.Element)
735 continue; 737 continue;
736 738
737 switch (xtr.Name) 739 switch (xtr.Name)
738 { 740 {
739 case "UUID": 741 case "UUID":
@@ -831,9 +833,11 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
831 string xml2 = m_serialiserModule.SerializeGroupToXml2(so, options); 833 string xml2 = m_serialiserModule.SerializeGroupToXml2(so, options);
832 834
833 XmlTextReader xtr = new XmlTextReader(new StringReader(xml2)); 835 XmlTextReader xtr = new XmlTextReader(new StringReader(xml2));
836 xtr.ProhibitDtd = true;
837
834 xtr.ReadStartElement("SceneObjectGroup"); 838 xtr.ReadStartElement("SceneObjectGroup");
835 xtr.ReadStartElement("SceneObjectPart"); 839 xtr.ReadStartElement("SceneObjectPart");
836 840
837 UUID uuid = UUID.Zero; 841 UUID uuid = UUID.Zero;
838 string name = null; 842 string name = null;
839 UUID creatorId = UUID.Zero; 843 UUID creatorId = UUID.Zero;
@@ -843,7 +847,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
843 { 847 {
844 if (xtr.NodeType != XmlNodeType.Element) 848 if (xtr.NodeType != XmlNodeType.Element)
845 continue; 849 continue;
846 850
847 switch (xtr.Name) 851 switch (xtr.Name)
848 { 852 {
849 case "UUID": 853 case "UUID":
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index d093224..2b7db18 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -48,6 +48,18 @@ namespace OpenSim.Region.CoreModules.World.Sound
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 50
51 public enum SoundFlags: byte
52 {
53 NONE = 0,
54 LOOP = 1 << 0,
55 SYNC_MASTER = 1<<1,
56 SYNC_SLAVE = 1<<2,
57 SYNC_PENDING = 1<<3,
58 QUEUE = 1<<4,
59 STOP = 1<<5,
60 SYNC_MASK = SYNC_MASTER | SYNC_SLAVE | SYNC_PENDING
61 }
62
51 public bool Enabled { get; private set; } 63 public bool Enabled { get; private set; }
52 64
53 public float MaxDistance { get; private set; } 65 public float MaxDistance { get; private set; }
@@ -124,26 +136,30 @@ namespace OpenSim.Region.CoreModules.World.Sound
124 if (radius == 0) 136 if (radius == 0)
125 radius = MaxDistance; 137 radius = MaxDistance;
126 138
127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 139 if (part.SoundQueueing)
140 flags |= (byte)SoundFlags.QUEUE;
141
142 if (grp.IsAttachment)
128 { 143 {
129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 144 ScenePresence ssp = null;
130 if (dis > MaxDistance) // Max audio distance 145 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
131 return; 146 return;
132 147
133 if (grp.IsAttachment) 148 if (grp.HasPrivateAttachmentPoint)
134 { 149 {
135 if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID) 150 ssp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
136 return; 151 ownerID, (float)gain, flags);
137 152 return;
138 if (sp.ControllingClient.AgentId == grp.OwnerID)
139 dis = 0;
140 } 153 }
141 154
142 // Scale by distance 155 if (!ssp.ParcelAllowThisAvatarSounds)
143 double thisSpGain = gain * ((radius - dis) / radius); 156 return;
157 }
144 158
159 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
160 {
145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, 161 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
146 ownerID, (float)thisSpGain, flags); 162 ownerID, (float)gain, flags);
147 }); 163 });
148 } 164 }
149 165
@@ -151,20 +167,35 @@ namespace OpenSim.Region.CoreModules.World.Sound
151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 167 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
152 { 168 {
153 SceneObjectPart part; 169 SceneObjectPart part;
170 ScenePresence ssp = null;
154 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 171 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
155 { 172 {
156 ScenePresence sp; 173 if (!m_scene.TryGetScenePresence(ownerID, out ssp))
157 if (!m_scene.TryGetScenePresence(ownerID, out sp)) 174 return;
175 if (!ssp.ParcelAllowThisAvatarSounds)
158 return; 176 return;
159 } 177 }
160 else 178 else
161 { 179 {
162 SceneObjectGroup grp = part.ParentGroup; 180 SceneObjectGroup grp = part.ParentGroup;
163 181
164 if (grp.IsAttachment && grp.AttachmentPoint > 30) 182 if (grp.IsAttachment)
165 { 183 {
166 objectID = ownerID; 184 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
167 parentID = ownerID; 185 return;
186
187 if (!ssp.ParcelAllowThisAvatarSounds)
188 return;
189
190/* mantis 7942: coment out to allow trigger in HUDs to send sounds to all
191 if (grp.HasPrivateAttachmentPoint)
192 {
193 ssp.ControllingClient.SendTriggeredSound(soundId, ownerID,
194 objectID, parentID, handle, position,
195 (float)gain);
196 return;
197 }
198*/
168 } 199 }
169 } 200 }
170 201
@@ -174,16 +205,12 @@ namespace OpenSim.Region.CoreModules.World.Sound
174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 205 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
175 { 206 {
176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 207 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
177 208 if (dis > radius) // Max audio distance
178 if (dis > MaxDistance) // Max audio distance
179 return; 209 return;
180 210
181 // Scale by distance
182 double thisSpGain = gain * ((radius - dis) / radius);
183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID, 211 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position, 212 objectID, parentID, handle, position,
186 (float)thisSpGain); 213 (float)gain);
187 }); 214 });
188 } 215 }
189 216
@@ -198,40 +225,13 @@ namespace OpenSim.Region.CoreModules.World.Sound
198 225
199 private static void StopSound(SceneObjectPart m_host) 226 private static void StopSound(SceneObjectPart m_host)
200 { 227 {
201 m_host.AdjustSoundGain(0); 228// m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead 229 m_host.Sound = UUID.Zero;
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 230 m_host.SoundFlags = (byte)SoundFlags.STOP;
204 { 231 m_host.SoundRadius = 0;
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 232 m_host.SoundGain = 0;
206 { 233 m_host.ScheduleFullUpdate();
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) 234 m_host.SendFullUpdateToAllClients();
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
218 else
219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 } 235 }
236 236
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) 237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
248 248
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 { 250 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) 251 if (Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) < radius)
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); 252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 }); 253 });
254 } 254 }
@@ -262,21 +262,24 @@ namespace OpenSim.Region.CoreModules.World.Sound
262 // 20080530 Updated to remove code duplication 262 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work 263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID, 264 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster) 265 double volume, double radius, bool isMaster, bool isSlave)
266 { 266 {
267 SceneObjectPart m_host; 267 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) 268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return; 269 return;
270 270
271 byte iflags = 1; // looping
271 if (isMaster) 272 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 273 iflags |= (byte)SoundFlags.SYNC_MASTER;
273 274 // TODO check viewer seems to accept both
274 if (m_host.Sound != UUID.Zero) 275 if (isSlave)
275 StopSound(m_host); 276 iflags |= (byte)SoundFlags.SYNC_SLAVE;
277 if (m_host.SoundQueueing)
278 iflags |= (byte)SoundFlags.QUEUE;
276 279
277 m_host.Sound = soundID; 280 m_host.Sound = soundID;
278 m_host.SoundGain = volume; 281 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping 282 m_host.SoundFlags = iflags;
280 m_host.SoundRadius = radius; 283 m_host.SoundRadius = radius;
281 284
282 m_host.ScheduleFullUpdate(); 285 m_host.ScheduleFullUpdate();
@@ -301,41 +304,18 @@ namespace OpenSim.Region.CoreModules.World.Sound
301 Vector3 position = part.AbsolutePosition; // region local 304 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle; 305 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303 306
304 if (useMaster) 307 if(triggered)
305 { 308 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
328 else
329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else 309 else
334 { 310 {
335 if (triggered) 311 byte bflags = 0;
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); 312
337 else 313 if (isMaster)
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); 314 bflags |= (byte)SoundFlags.SYNC_MASTER;
315 // TODO check viewer seems to accept both
316 if (useMaster)
317 bflags |= (byte)SoundFlags.SYNC_SLAVE;
318 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, bflags, radius);
339 } 319 }
340 } 320 }
341 321
diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
index d0318eb..e2b3487 100644
--- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
@@ -77,7 +77,7 @@ namespace OpenSim.Region.CoreModules
77 // Number of virtual days to a virtual year 77 // Number of virtual days to a virtual year
78 private int m_YearLengthDays = 0; 78 private int m_YearLengthDays = 0;
79 79
80 // Ratio of Daylight hours to Night time hours. This is accomplished by shifting the 80 // Ratio of Daylight hours to Night time hours. This is accomplished by shifting the
81 // sun's orbit above the horizon 81 // sun's orbit above the horizon
82 private double m_HorizonShift = 0; 82 private double m_HorizonShift = 0;
83 83
@@ -162,7 +162,7 @@ namespace OpenSim.Region.CoreModules
162 // Determine the current "day" from current time, so we can use "today" 162 // Determine the current "day" from current time, so we can use "today"
163 // to determine Seasonal Tilt and what'not 163 // to determine Seasonal Tilt and what'not
164 164
165 // Integer math rounded is on purpose to drop fractional day, determines number 165 // Integer math rounded is on purpose to drop fractional day, determines number
166 // of virtual days since Epoch 166 // of virtual days since Epoch
167 PosTime = CurrentTime / SecondsPerSunCycle; 167 PosTime = CurrentTime / SecondsPerSunCycle;
168 168
@@ -343,7 +343,7 @@ namespace OpenSim.Region.CoreModules
343 m_log.Debug("[SUN]: Positional data updated every " + m_UpdateInterval + " frames"); 343 m_log.Debug("[SUN]: Positional data updated every " + m_UpdateInterval + " frames");
344 } 344 }
345 345
346 public Type ReplaceableInterface 346 public Type ReplaceableInterface
347 { 347 {
348 get { return null; } 348 get { return null; }
349 } 349 }
@@ -417,7 +417,7 @@ namespace OpenSim.Region.CoreModules
417 client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); 417 client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
418 } 418 }
419 } 419 }
420 } 420 }
421 421
422 public void SunUpdate() 422 public void SunUpdate()
423 { 423 {
@@ -464,7 +464,7 @@ namespace OpenSim.Region.CoreModules
464 464
465 while (sunFixedHour < 0) 465 while (sunFixedHour < 0)
466 sunFixedHour += 24; 466 sunFixedHour += 24;
467 467
468 m_SunFixedHour = sunFixedHour; 468 m_SunFixedHour = sunFixedHour;
469 m_SunFixed = fixedSun; 469 m_SunFixed = fixedSun;
470 470
@@ -516,7 +516,7 @@ namespace OpenSim.Region.CoreModules
516 516
517 case "current_time": 517 case "current_time":
518 return GetCurrentTimeAsLindenSunHour(); 518 return GetCurrentTimeAsLindenSunHour();
519 519
520 default: 520 default:
521 throw new Exception("Unknown sun parameter."); 521 throw new Exception("Unknown sun parameter.");
522 } 522 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
index 36917e9..b456aa1 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
64 64
65 for (int i = 0; i < rounds; i++) 65 for (int i = 0; i < rounds; i++)
66 { 66 {
67 smoothFunction.FloodEffect(map, bitmap, 1.0); 67 smoothFunction.FloodEffect(map, bitmap, 1.0, 0, map.Width - 1, 0, map.Height - 1);
68 } 68 }
69 } 69 }
70 70
@@ -99,7 +99,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
99 } 99 }
100 } 100 }
101 101
102 raiseFunction.FloodEffect(map, bitmap, height); 102 raiseFunction.FloodEffect(map, bitmap, height, 0, map.Width - 1, 0, map.Height - 1);
103 } 103 }
104 } 104 }
105 } 105 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
index dc76ad5..3222524 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
84 for (y = 0; y < map.Height; y++) 84 for (y = 0; y < map.Height; y++)
85 { 85 {
86 if (cliffMask[x, y]) 86 if (cliffMask[x, y])
87 eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1); 87 eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1,0,map.Width - 1,0,map.Height - 1);
88 } 88 }
89 } 89 }
90 90
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
index 89087b1..80396c4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
@@ -53,4 +53,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
53 53
54 #endregion 54 #endregion
55 } 55 }
56} \ No newline at end of file 56}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs
index fb57c82..ec2d085 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs
@@ -47,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
47 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
48 public override void SaveFile(string filename, ITerrainChannel map) 48 public override void SaveFile(string filename, ITerrainChannel map)
49 { 49 {
50 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
51 51 colours.Save(filename,ImageFormat.Bmp);
52 colours.Save(filename, ImageFormat.Bmp);
53 } 52 }
54 53
55 /// <summary> 54 /// <summary>
@@ -59,9 +58,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 /// <param name="map">The terrain channel being saved</param> 58 /// <param name="map">The terrain channel being saved</param>
60 public override void SaveStream(Stream stream, ITerrainChannel map) 59 public override void SaveStream(Stream stream, ITerrainChannel map)
61 { 60 {
62 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 61 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
63 62 colours.Save(stream,ImageFormat.Bmp);
64 colours.Save(stream, ImageFormat.Png);
65 } 63 }
66 64
67 /// <summary> 65 /// <summary>
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs
index 79cc50b..3843708 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs
@@ -36,9 +36,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
36 { 36 {
37 public override void SaveFile(string filename, ITerrainChannel map) 37 public override void SaveFile(string filename, ITerrainChannel map)
38 { 38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 39 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
40 40 colours.Save(filename,ImageFormat.Gif);
41 colours.Save(filename, ImageFormat.Gif);
42 } 41 }
43 42
44 /// <summary> 43 /// <summary>
@@ -48,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
48 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map) 48 public override void SaveStream(Stream stream, ITerrainChannel map)
50 { 49 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
52 51 colours.Save(stream,ImageFormat.Gif);
53 colours.Save(stream, ImageFormat.Gif);
54 } 52 }
55 53
56 public override string ToString() 54 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d5c77ec..bcd9dcd 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 /// <returns>A terrain channel generated from the image.</returns> 59 /// <returns>A terrain channel generated from the image.</returns>
60 public virtual ITerrainChannel LoadFile(string filename) 60 public virtual ITerrainChannel LoadFile(string filename)
61 { 61 {
62 using (Bitmap b = new Bitmap(filename)) 62 using(Bitmap b = new Bitmap(filename))
63 return LoadBitmap(b); 63 return LoadBitmap(b);
64 } 64 }
65 65
@@ -111,9 +111,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
111 /// <param name="map">The terrain channel being saved</param> 111 /// <param name="map">The terrain channel being saved</param>
112 public virtual void SaveFile(string filename, ITerrainChannel map) 112 public virtual void SaveFile(string filename, ITerrainChannel map)
113 { 113 {
114 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 114 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
115 115 colours.Save(filename,ImageFormat.Png);
116 colours.Save(filename, ImageFormat.Png);
117 } 116 }
118 117
119 /// <summary> 118 /// <summary>
@@ -123,12 +122,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
123 /// <param name="map">The terrain channel being saved</param> 122 /// <param name="map">The terrain channel being saved</param>
124 public virtual void SaveStream(Stream stream, ITerrainChannel map) 123 public virtual void SaveStream(Stream stream, ITerrainChannel map)
125 { 124 {
126 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 125 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
127 126 colours.Save(stream,ImageFormat.Png);
128 colours.Save(stream, ImageFormat.Png);
129 } 127 }
130 128
131 public virtual void SaveFile(ITerrainChannel m_channel, string filename, 129 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
132 int offsetX, int offsetY, 130 int offsetX, int offsetY,
133 int fileWidth, int fileHeight, 131 int fileWidth, int fileHeight,
134 int regionSizeX, int regionSizeY) 132 int regionSizeX, int regionSizeY)
@@ -162,13 +160,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
162 { 160 {
163 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY); 161 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
164 } 162 }
165 163
166 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel); 164 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel);
167 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY); 165 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY);
168 for (int x = 0; x < regionSizeX; x++) 166 for (int x = 0; x < regionSizeX; x++)
169 for (int y = 0; y < regionSizeY; y++) 167 for (int y = 0; y < regionSizeY; y++)
170 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y)); 168 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y));
171 169
172 Save(newBitmap, filename); 170 Save(newBitmap, filename);
173 } 171 }
174 finally 172 finally
@@ -213,8 +211,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
213 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns> 211 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns>
214 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) 212 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map)
215 { 213 {
214 // Bitmap bmp = new Bitmap(map.Width, map.Height, PixelFormat.Format24bppRgb);
216 Bitmap bmp = new Bitmap(map.Width, map.Height); 215 Bitmap bmp = new Bitmap(map.Width, map.Height);
217 216
217
218 const int pallete = 256; 218 const int pallete = 256;
219 219
220 Color[] grays = new Color[pallete]; 220 Color[] grays = new Color[pallete];
@@ -227,59 +227,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
227 { 227 {
228 for (int x = 0; x < map.Width; x++) 228 for (int x = 0; x < map.Width; x++)
229 { 229 {
230 // 512 is the largest possible height before colours clamp 230 // to change this, loading also needs change
231 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 128.0), 0.0) * (pallete - 1));
232
233 // Handle error conditions
234 if (colorindex > pallete - 1 || colorindex < 0)
235 bmp.SetPixel(x, map.Height - y - 1, Color.Red);
236 else
237 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
238 }
239 }
240 return bmp;
241 }
242
243 /// <summary>
244 /// Protected method, generates a coloured bitmap
245 /// image from a specified terrain channel.
246 /// </summary>
247 /// <param name="map">The terrain channel to export to bitmap</param>
248 /// <returns>A System.Drawing.Bitmap containing a coloured image</returns>
249 protected static Bitmap CreateBitmapFromMap(ITerrainChannel map)
250 {
251 int pallete;
252 Bitmap bmp;
253 Color[] colours;
254 231
255 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png")) 232 // int colorindex = (int)map[x, y]; // one to one conversion 0 - 255m range
256 { 233 // int colorindex = (int)map[x, y] / 2; // 0 - 510 range
257 pallete = gradientmapLd.Height;
258
259 bmp = new Bitmap(map.Width, map.Height);
260 colours = new Color[pallete];
261
262 for (int i = 0; i < pallete; i++)
263 {
264 colours[i] = gradientmapLd.GetPixel(0, i);
265 }
266 }
267 234
268 for (int y = 0; y < map.Height; y++) 235 int colorindex = (int)map[x, y] * 2; // the original 0 - 127.5 range
269 {
270 for (int x = 0; x < map.Width; x++)
271 {
272 // 512 is the largest possible height before colours clamp
273 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1));
274 236
275 // Handle error conditions 237 // clamp it not adding the red warning
276 if (colorindex > pallete - 1 || colorindex < 0) 238 if (colorindex < 0)
277 bmp.SetPixel(x, map.Height - y - 1, Color.Red); 239 colorindex = 0;
278 else 240 else if (colorindex >= pallete)
279 bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); 241 colorindex = pallete - 1;
242 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
280 } 243 }
281 } 244 }
282 return bmp; 245 return bmp;
283 } 246 }
284 } 247 }
285} 248}
249
250
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
index 9cc767a..d604dc7 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
@@ -59,9 +59,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 59
60 public void SaveFile(string filename, ITerrainChannel map) 60 public void SaveFile(string filename, ITerrainChannel map)
61 { 61 {
62 Bitmap colours = CreateBitmapFromMap(map); 62 using(Bitmap colours = CreateBitmapFromMap(map))
63 63 colours.Save(filename,ImageFormat.Jpeg);
64 colours.Save(filename, ImageFormat.Jpeg);
65 } 64 }
66 65
67 /// <summary> 66 /// <summary>
@@ -71,9 +70,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
71 /// <param name="map">The terrain channel being saved</param> 70 /// <param name="map">The terrain channel being saved</param>
72 public void SaveStream(Stream stream, ITerrainChannel map) 71 public void SaveStream(Stream stream, ITerrainChannel map)
73 { 72 {
74 Bitmap colours = CreateBitmapFromMap(map); 73 using(Bitmap colours = CreateBitmapFromMap(map))
75 74 colours.Save(stream,ImageFormat.Jpeg);
76 colours.Save(stream, ImageFormat.Jpeg);
77 } 75 }
78 76
79 public virtual void SaveFile(ITerrainChannel m_channel, string filename, 77 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
@@ -106,10 +104,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
106 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png")) 104 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png"))
107 { 105 {
108 pallete = gradientmapLd.Height; 106 pallete = gradientmapLd.Height;
109 107
110 bmp = new Bitmap(map.Width, map.Height); 108 bmp = new Bitmap(map.Width, map.Height);
111 colours = new Color[pallete]; 109 colours = new Color[pallete];
112 110
113 for (int i = 0; i < pallete; i++) 111 for (int i = 0; i < pallete; i++)
114 { 112 {
115 colours[i] = gradientmapLd.GetPixel(0, i); 113 colours[i] = gradientmapLd.GetPixel(0, i);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
index be1fb24..68d6ed2 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
@@ -57,6 +57,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
57 57
58 public LLRAW() 58 public LLRAW()
59 { 59 {
60 }
61
62 private void BuildLookupHeightTable()
63 {
60 LookupHeightTable = new HeightmapLookupValue[256 * 256]; 64 LookupHeightTable = new HeightmapLookupValue[256 * 256];
61 65
62 for (int i = 0; i < 256; i++) 66 for (int i = 0; i < 256; i++)
@@ -186,6 +190,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
186 190
187 public void SaveStream(Stream s, ITerrainChannel map) 191 public void SaveStream(Stream s, ITerrainChannel map)
188 { 192 {
193 if (LookupHeightTable == null)
194 BuildLookupHeightTable();
195
189 using (BinaryWriter binStream = new BinaryWriter(s)) 196 using (BinaryWriter binStream = new BinaryWriter(s))
190 { 197 {
191 // Output the calculated raw 198 // Output the calculated raw
@@ -241,6 +248,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
241 } 248 }
242 } 249 }
243 } 250 }
251 LookupHeightTable = null;
244 } 252 }
245 253
246 public string FileExtension 254 public string FileExtension
@@ -267,6 +275,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
267 public bool SupportsTileSave() 275 public bool SupportsTileSave()
268 { 276 {
269 return false; 277 return false;
270 } 278 }
271 } 279 }
272} \ No newline at end of file 280} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs
index c5c12ae..8ea8e9d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs
@@ -36,9 +36,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
36 { 36 {
37 public override void SaveFile(string filename, ITerrainChannel map) 37 public override void SaveFile(string filename, ITerrainChannel map)
38 { 38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 39 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
40 40 colours.Save(filename,ImageFormat.Png);
41 colours.Save(filename, ImageFormat.Png);
42 } 41 }
43 42
44 /// <summary> 43 /// <summary>
@@ -48,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
48 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map) 48 public override void SaveStream(Stream stream, ITerrainChannel map)
50 { 49 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
52 51 colours.Save(stream,ImageFormat.Png);
53 colours.Save(stream, ImageFormat.Png);
54 } 52 }
55 53
56 public override string ToString() 54 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
index b416b82..d103a6f 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
@@ -36,9 +36,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
36 { 36 {
37 public override void SaveFile(string filename, ITerrainChannel map) 37 public override void SaveFile(string filename, ITerrainChannel map)
38 { 38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 39 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
40 40 colours.Save(filename,ImageFormat.Tiff);
41 colours.Save(filename, ImageFormat.Tiff);
42 } 41 }
43 42
44 /// <summary> 43 /// <summary>
@@ -48,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
48 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map) 48 public override void SaveStream(Stream stream, ITerrainChannel map)
50 { 49 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
52 51 colours.Save(stream,ImageFormat.Tiff);
53 colours.Save(stream, ImageFormat.Tiff);
54 } 52 }
55 53
56 public override string ToString() 54 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
index 774e7b2..0c4171e 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
@@ -33,15 +33,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 double sum = 0.0; 39 double sum = 0.0;
39 double steps = 0.0; 40 double steps = 0.0;
40 41
41 int x, y; 42 int x, y;
42 for (x = 0; x < map.Width; x++) 43 for (x = startX; x <= endX; x++)
43 { 44 {
44 for (y = 0; y < map.Height; y++) 45 for (y = startY; y <= endY; y++)
45 { 46 {
46 if (fillArea[x, y]) 47 if (fillArea[x, y])
47 { 48 {
@@ -55,9 +56,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
55 56
56 double str = 0.1 * strength; // == 0.2 in the default client 57 double str = 0.1 * strength; // == 0.2 in the default client
57 58
58 for (x = 0; x < map.Width; x++) 59 for (x = startX; x <= endX; x++)
59 { 60 {
60 for (y = 0; y < map.Height; y++) 61 for (y = startY; y <= endY; y++)
61 { 62 {
62 if (fillArea[x, y]) 63 if (fillArea[x, y])
63 map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str); 64 map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
index 3e87390..a275a86 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
@@ -33,13 +33,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 int x; 39 int x,y;
39 for (x = 0; x < map.Width; x++) 40 for (x = startX; x <= endX; x++)
40 { 41 {
41 int y; 42 for (y = startY; y <= endY; y++)
42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 if (fillArea[x, y]) 44 if (fillArea[x, y])
45 { 45 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
index b6c635c..d634e8b 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
@@ -35,18 +35,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
35 { 35 {
36 #region ITerrainFloodEffect Members 36 #region ITerrainFloodEffect Members
37 37
38 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 38 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
39 int startX, int endX, int startY, int endY)
39 { 40 {
40 int x; 41 int x, y;
41 for (x = 0; x < map.Width; x++) 42 for (x = startX; x <= endX; x++)
42 { 43 {
43 int y; 44 for (y = startY; y <= endY; y++)
44 for (y = 0; y < map.Height; y++)
45 { 45 {
46 if (fillArea[x, y]) 46 if (fillArea[x, y])
47 { 47 {
48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0); 48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
49
50 map[x, y] += noise * strength; 49 map[x, y] += noise * strength;
51 } 50 }
52 } 51 }
@@ -55,4 +54,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
55 54
56 #endregion 55 #endregion
57 } 56 }
58} \ No newline at end of file 57}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
index 3bdc5e7..6ccd5df 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
@@ -33,13 +33,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 int x; 39 int x,y;
39 for (x = 0; x < map.Width; x++) 40 for (x = startX; x <= endX; x++)
40 { 41 {
41 int y; 42 for (y = startY; y <= endY; y++)
42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 if (fillArea[x, y]) 44 if (fillArea[x, y])
45 { 45 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
index c5527fa..4230133 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
@@ -46,13 +46,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
46 /// <param name="map">the current heightmap</param> 46 /// <param name="map">the current heightmap</param>
47 /// <param name="fillArea">array indicating which sections of the map are to be reverted</param> 47 /// <param name="fillArea">array indicating which sections of the map are to be reverted</param>
48 /// <param name="strength">unused</param> 48 /// <param name="strength">unused</param>
49 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 49 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
50 int startX, int endX, int startY, int endY)
50 { 51 {
51 int x; 52 int x, y;
52 for (x = 0; x < map.Width; x++) 53 for (x = startX; x <= endX; x++)
53 { 54 {
54 int y; 55 for (y = startY; y <= endY; y++)
55 for (y = 0; y < map.Height; y++)
56 { 56 {
57 if (fillArea[x, y]) 57 if (fillArea[x, y])
58 { 58 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
index 6b07747..6c0d60d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
@@ -33,16 +33,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 double area = strength; 39 double area = strength;
39 double step = strength / 4.0; 40 double step = strength / 4.0;
40 41
41 double[,] manipulate = new double[map.Width,map.Height]; 42 double[,] manipulate = new double[map.Width,map.Height];
42 int x, y; 43 int x, y;
43 for (x = 0; x < map.Width; x++) 44 for (x = startX; x <= endX; x++)
44 { 45 {
45 for (y = 0; y < map.Height; y++) 46 for (y = startY; y <= endY; y++)
46 { 47 {
47 if (!fillArea[x, y]) 48 if (!fillArea[x, y])
48 continue; 49 continue;
@@ -64,9 +65,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
64 manipulate[x, y] = average / avgsteps; 65 manipulate[x, y] = average / avgsteps;
65 } 66 }
66 } 67 }
67 for (x = 0; x < map.Width; x++) 68 for (x = startX; x <= endX; x++)
68 { 69 {
69 for (y = 0; y < map.Height; y++) 70 for (y = startY; y <= endY; y++)
70 { 71 {
71 if (!fillArea[x, y]) 72 if (!fillArea[x, y])
72 continue; 73 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
index 3984a30..f7be25f 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
@@ -32,6 +32,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
32{ 32{
33 public interface ITerrainFloodEffect 33 public interface ITerrainFloodEffect
34 { 34 {
35 void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength); 35 void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength,
36 int startX, int endX, int startY, int endY);
36 } 37 }
37} \ No newline at end of file 38} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
index 3ba3657..855d131 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
33 public interface ITerrainLoader 33 public interface ITerrainLoader
34 { 34 {
35 // Returns true if that extension can be used for terrain save-tile 35 // Returns true if that extension can be used for terrain save-tile
36 // (Look into each file in Region.CoreModules.World.Terrain.FileLoaders) 36 // (Look into each file in Region.CoreModules.World.Terrain.FileLoaders)
37 bool SupportsTileSave(); 37 bool SupportsTileSave();
38 38
39 string FileExtension { get; } 39 string FileExtension { get; }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
index b73defd..d0b05e4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
@@ -31,6 +31,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
31{ 31{
32 public interface ITerrainPaintableEffect 32 public interface ITerrainPaintableEffect
33 { 33 {
34 void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z, double strength, double duration); 34 void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z,
35 double strength, double duration, int startX, int endX, int startY, int endY);
35 } 36 }
36} 37}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
index 7a78cd8..7358ba3 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
@@ -151,7 +151,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
151 151
152 #region ITerrainPaintableEffect Members 152 #region ITerrainPaintableEffect Members
153 153
154 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 154 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
155 double strength, double duration, int startX, int endX, int startY, int endY)
155 { 156 {
156 strength = TerrainUtil.MetersToSphericalStrength(strength); 157 strength = TerrainUtil.MetersToSphericalStrength(strength);
157 158
@@ -163,18 +164,23 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
163 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height); 164 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height);
164 165
165 // Fill with rain 166 // Fill with rain
166 for (x = 0; x < water.Width; x++) 167 for (x = startX; x <= endX; x++)
167 for (y = 0; y < water.Height; y++) 168 {
168 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration); 169 for (y = startY; y <= endY; y++)
170 {
171 if (mask[x, y])
172 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
173 }
174 }
169 175
170 for (int i = 0; i < rounds; i++) 176 for (int i = 0; i < rounds; i++)
171 { 177 {
172 // Erode underlying terrain 178 // Erode underlying terrain
173 for (x = 0; x < water.Width; x++) 179 for (x = startX; x <= endX; x++)
174 { 180 {
175 for (y = 0; y < water.Height; y++) 181 for (y = startY; y <= endY; y++)
176 { 182 {
177 if (mask[x,y]) 183 if (mask[x, y])
178 { 184 {
179 const double solConst = (1.0 / rounds); 185 const double solConst = (1.0 / rounds);
180 double sedDelta = water[x, y] * solConst; 186 double sedDelta = water[x, y] * solConst;
@@ -185,9 +191,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
185 } 191 }
186 192
187 // Move water 193 // Move water
188 for (x = 0; x < water.Width; x++) 194 for (x = startX; x <= endX; x++)
189 { 195 {
190 for (y = 0; y < water.Height; y++) 196 for (y = startY; y <= endY; y++)
191 { 197 {
192 if (water[x, y] <= 0) 198 if (water[x, y] <= 0)
193 continue; 199 continue;
@@ -296,7 +302,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
296 double sedimentDeposit = sediment[x, y] - waterCapacity; 302 double sedimentDeposit = sediment[x, y] - waterCapacity;
297 if (sedimentDeposit > 0) 303 if (sedimentDeposit > 0)
298 { 304 {
299 if (mask[x,y]) 305 if (mask[x, y])
300 { 306 {
301 sediment[x, y] -= sedimentDeposit; 307 sediment[x, y] -= sedimentDeposit;
302 map[x, y] += sedimentDeposit; 308 map[x, y] += sedimentDeposit;
@@ -309,10 +315,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
309 // Deposit any remainder (should be minimal) 315 // Deposit any remainder (should be minimal)
310 for (x = 0; x < water.Width; x++) 316 for (x = 0; x < water.Width; x++)
311 for (y = 0; y < water.Height; y++) 317 for (y = 0; y < water.Height; y++)
312 if (mask[x,y] && sediment[x, y] > 0) 318 if (mask[x, y] && sediment[x, y] > 0)
313 map[x, y] += sediment[x, y]; 319 map[x, y] += sediment[x, y];
314 } 320 }
315
316 #endregion 321 #endregion
317 } 322 }
318} 323}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
index 9aa3dff..9d3d4cb 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
@@ -35,16 +35,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 { 35 {
36 #region ITerrainPaintableEffect Members 36 #region ITerrainPaintableEffect Members
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 strength = TerrainUtil.MetersToSphericalStrength(strength); 41 strength = TerrainUtil.MetersToSphericalStrength(strength);
41 42
42 int x, y; 43 int x, y;
43 44
44 // blend in map 45 // blend in map
45 for (x = 0; x < map.Width; x++) 46 for (x = startX; x <= endX; x++)
46 { 47 {
47 for (y = 0; y < map.Height; y++) 48 for (y = startY; y <= endY; y++)
48 { 49 {
49 if (!mask[x,y]) 50 if (!mask[x,y])
50 continue; 51 continue;
@@ -76,7 +77,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
76 { 77 {
77 map[x, y] += delta; 78 map[x, y] += delta;
78 } 79 }
79 80
80 } 81 }
81 } 82 }
82 } 83 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
index 68145f2..a88a022 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
@@ -34,34 +34,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
38 double strength, double duration, int startX, int endX, int startY, int endY)
38 { 39 {
39 int s = (int) (Math.Pow(2, strength) + 0.5); 40 int s = (int) (Math.Pow(2, strength) + 0.5);
40 41
41 int x; 42 int x, y;
42 int xFrom = (int)(rx-s+0.5);
43 int xTo = (int)(rx+s+0.5) + 1;
44 int yFrom = (int)(ry-s+0.5);
45 int yTo = (int)(ry+s+0.5) + 1;
46 43
47 if (xFrom < 0) 44 for (x = startX; x <= endX; x++)
48 xFrom = 0;
49
50 if (yFrom < 0)
51 yFrom = 0;
52
53 if (xTo > map.Width)
54 xTo = map.Width;
55
56 if (yTo > map.Width)
57 yTo = map.Width;
58
59 for (x = xFrom; x < xTo; x++)
60 { 45 {
61 int y; 46 for (y = startY; y <= endY; y++)
62 for (y = yFrom; y < yTo; y++)
63 { 47 {
64 if (!mask[x,y]) 48 if (!mask[x, y])
65 continue; 49 continue;
66 50
67 // Calculate a cos-sphere and add it to the heighmap 51 // Calculate a cos-sphere and add it to the heighmap
@@ -74,7 +58,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
74 map[x, y] = 0.0; 58 map[x, y] = 0.0;
75 else 59 else
76 map[x, y] = newz; 60 map[x, y] = newz;
77 } 61 }
78 } 62 }
79 } 63 }
80 64
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
index e7df3f8..46d47b4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
@@ -35,17 +35,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 { 35 {
36 #region ITerrainPaintableEffect Members 36 #region ITerrainPaintableEffect Members
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 strength = TerrainUtil.MetersToSphericalStrength(strength); 41 strength = TerrainUtil.MetersToSphericalStrength(strength);
41 42
42 int x; 43 int x, y;
43 for (x = 0; x < map.Width; x++) 44
45 for (x = startX; x <= endX; x++)
44 { 46 {
45 int y; 47 for (y = startY; y <= endY; y++)
46 for (y = 0; y < map.Height; y++)
47 { 48 {
48 if (!mask[x,y]) 49 if (!mask[x, y])
49 continue; 50 continue;
50 51
51 // Calculate a sphere and add it to the heighmap 52 // Calculate a sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
index b199df3..281690d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
@@ -152,18 +152,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
152 152
153 #region ITerrainPaintableEffect Members 153 #region ITerrainPaintableEffect Members
154 154
155 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 155 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
156 double strength, double duration, int startX, int endX, int startY, int endY)
156 { 157 {
157 strength = TerrainUtil.MetersToSphericalStrength(strength); 158 strength = TerrainUtil.MetersToSphericalStrength(strength);
158 159
159 int x; 160 int x, y;
160 161
161 for (x = 0; x < map.Width; x++) 162 for (x = startX; x <= endX; x++)
162 { 163 {
163 int y; 164 for (y = startY; y <= endY; y++)
164 for (y = 0; y < map.Height; y++)
165 { 165 {
166 if (!mask[x,y]) 166 if (!mask[x, y])
167 continue; 167 continue;
168 168
169 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 169 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
index bd9a8a0..5305cb4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
@@ -33,40 +33,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
33 public class RaiseSphere : ITerrainPaintableEffect 33 public class RaiseSphere : ITerrainPaintableEffect
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36
37 36
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 int s = (int) (Math.Pow(2, strength) + 0.5); 41 int s = (int) (Math.Pow(2, strength) + 0.5);
41 42
42 int x; 43 int x,y;
43 int xFrom = (int)(rx-s+0.5);
44 int xTo = (int)(rx+s+0.5) + 1;
45 int yFrom = (int)(ry-s+0.5);
46 int yTo = (int)(ry+s+0.5) + 1;
47
48 if (xFrom < 0)
49 xFrom = 0;
50
51 if (yFrom < 0)
52 yFrom = 0;
53
54 if (xTo > map.Width)
55 xTo = map.Width;
56
57 if (yTo > map.Width)
58 yTo = map.Width;
59 44
60 for (x = xFrom; x < xTo; x++) 45 for (x = startX; x <= endX; x++)
61 { 46 {
62 int y; 47 for (y = startY; y <= endY; y++)
63 for (y = yFrom; y < yTo; y++)
64 { 48 {
65 if (!mask[x,y]) 49 if (!mask[x, y])
66 continue; 50 continue;
67 51
68 // Calculate a cos-sphere and add it to the heighmap 52 // Calculate a cos-sphere and add it to the heighmap
69 double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry))); 53 double r = Math.Sqrt((x - rx) * (x - rx) + ((y - ry) * (y - ry)));
70 double z = Math.Cos(r * Math.PI / (s * 2)); 54 double z = Math.Cos(r * Math.PI / (s * 2));
71 if (z > 0.0) 55 if (z > 0.0)
72 map[x, y] += z * duration; 56 map[x, y] += z * duration;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
index 4b28275..ca30e9e 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
@@ -41,23 +41,23 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
41 41
42 #region ITerrainPaintableEffect Members 42 #region ITerrainPaintableEffect Members
43 43
44 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 44 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
45 double strength, double duration, int startX, int endX, int startY, int endY)
45 { 46 {
46 strength = TerrainUtil.MetersToSphericalStrength(strength); 47 strength = TerrainUtil.MetersToSphericalStrength(strength);
47 duration = 0.03; //MCP Should be read from ini file 48 duration = 0.03; //MCP Should be read from ini file
48 49
49 if (duration > 1.0) 50 if (duration > 1.0)
50 duration = 1.0; 51 duration = 1.0;
51 if (duration < 0) 52 if (duration < 0)
52 return; 53 return;
53 54
54 int x; 55 int x,y;
55 for (x = 0; x < map.Width; x++) 56 for (x = startX; x <= endX; x++)
56 { 57 {
57 int y; 58 for (y = startY; y <= endY; y++)
58 for (y = 0; y < map.Height; y++)
59 { 59 {
60 if (!mask[x,y]) 60 if (!mask[x, y])
61 continue; 61 continue;
62 62
63 // Calculate a sphere and add it to the heighmap 63 // Calculate a sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
index 4834c86..0342962 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
@@ -34,23 +34,27 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
38 double strength, double duration, int startX, int endX, int startY, int endY)
38 { 39 {
39 strength = TerrainUtil.MetersToSphericalStrength(strength); 40 strength = TerrainUtil.MetersToSphericalStrength(strength);
40 41
41 int x, y; 42 int x, y;
42 double[,] tweak = new double[map.Width,map.Height]; 43 double[,] tweak = new double[map.Width,map.Height];
43 44
44 double area = strength; 45 double area = strength;
45 double step = strength / 4.0; 46 double step = strength / 4.0;
46 duration = 0.03; //MCP Should be read from ini file 47 duration = 0.03; //MCP Should be read from ini file
47 48
48 49
49 // compute delta map 50 // compute delta map
50 for (x = 0; x < map.Width; x++) 51 for (x = startX; x <= endX; x++)
51 { 52 {
52 for (y = 0; y < map.Height; y++) 53 for (y = startY; y <= endY; y++)
53 { 54 {
55 if (!mask[x, y])
56 continue;
57
54 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 58 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
55 59
56 if (z > 0) // add in non-zero amount 60 if (z > 0) // add in non-zero amount
@@ -73,11 +77,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
73 } 77 }
74 } 78 }
75 // blend in map 79 // blend in map
76 for (x = 0; x < map.Width; x++) 80 for (x = startX; x <= endX; x++)
77 { 81 {
78 for (y = 0; y < map.Height; y++) 82 for (y = startY; y <= endY; y++)
79 { 83 {
80 if (!mask[x,y]) 84 if (!mask[x, y])
81 continue; 85 continue;
82 86
83 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 87 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
index f31c8b6..f52fe07 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
@@ -148,16 +148,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
148 148
149 #region ITerrainPaintableEffect Members 149 #region ITerrainPaintableEffect Members
150 150
151 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 151 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
152 double strength, double duration, int startX, int endX, int startY, int endY)
152 { 153 {
153 strength = TerrainUtil.MetersToSphericalStrength(strength); 154 strength = TerrainUtil.MetersToSphericalStrength(strength);
154 155
155 int x; 156 int x,y;
156 157
157 for (x = 0; x < map.Width; x++) 158 for (x = startX; x <= endX; x++)
158 { 159 {
159 int y; 160 for (y = startY; y <= endY; y++)
160 for (y = 0; y < map.Height; y++)
161 { 161 {
162 if (!mask[x,y]) 162 if (!mask[x,y])
163 continue; 163 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
index 7ebd08e..c6e992f 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
@@ -370,9 +370,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
370 } 370 }
371 return mask; 371 return mask;
372 } 372 }
373
374
375 } 373 }
376
377} 374}
378 375
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 932652c..6df0075 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Net; 31using System.Net;
32using System.Threading;
32 33
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
@@ -36,7 +37,6 @@ using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using Mono.Addins; 38using Mono.Addins;
38 39
39using OpenSim.Data;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
42using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 42using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
@@ -86,14 +86,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); 86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
89 private Dictionary<string, ITerrainEffect> m_plugineffects;
90 private Dictionary<string, ITerrainModifier> m_modifyOperations = 89 private Dictionary<string, ITerrainModifier> m_modifyOperations =
91 new Dictionary<string, ITerrainModifier>(); 90 new Dictionary<string, ITerrainModifier>();
91 private Dictionary<string, ITerrainEffect> m_plugineffects;
92 private ITerrainChannel m_channel; 92 private ITerrainChannel m_channel;
93 private ITerrainChannel m_revert; 93 private ITerrainChannel m_baked;
94 private Scene m_scene; 94 private Scene m_scene;
95 private volatile bool m_tainted; 95 private volatile bool m_tainted;
96 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); 96
97 private String m_InitialTerrain = "pinhead-island"; 97 private String m_InitialTerrain = "pinhead-island";
98 98
99 // If true, send terrain patch updates to clients based on their view distance 99 // If true, send terrain patch updates to clients based on their view distance
@@ -107,13 +107,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
107 private bool[,] updated; // for each patch, whether it needs to be sent to this client 107 private bool[,] updated; // for each patch, whether it needs to be sent to this client
108 private int updateCount; // number of patches that need to be sent 108 private int updateCount; // number of patches that need to be sent
109 public ScenePresence Presence; // a reference to the client to send to 109 public ScenePresence Presence; // a reference to the client to send to
110 public TerrainData Terrain; // reference to the underlying terrain 110 public bool sendAll;
111 public int sendAllcurrentX;
112 public int sendAllcurrentY;
113
114
111 public PatchUpdates(TerrainData terrData, ScenePresence pPresence) 115 public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
112 { 116 {
113 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize]; 117 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
114 updateCount = 0; 118 updateCount = 0;
115 Presence = pPresence; 119 Presence = pPresence;
116 Terrain = terrData;
117 // Initially, send all patches to the client 120 // Initially, send all patches to the client
118 SetAll(true); 121 SetAll(true);
119 } 122 }
@@ -146,12 +149,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
146 public void SetAll(bool state) 149 public void SetAll(bool state)
147 { 150 {
148 updateCount = 0; 151 updateCount = 0;
149 for(int xx = 0; xx < updated.GetLength(0); xx++) 152 for (int xx = 0; xx < updated.GetLength(0); xx++)
150 for(int yy = 0; yy < updated.GetLength(1); yy++) 153 for (int yy = 0; yy < updated.GetLength(1); yy++)
151 updated[xx, yy] = state; 154 updated[xx, yy] = state;
152 if (state) 155 if (state)
153 updateCount = updated.GetLength(0) * updated.GetLength(1); 156 updateCount = updated.GetLength(0) * updated.GetLength(1);
157 sendAllcurrentX = 0;
158 sendAllcurrentY = 0;
159 sendAll = true;
154 } 160 }
161
155 // Logically OR's the terrain data's patch taint map into this client's update map. 162 // Logically OR's the terrain data's patch taint map into this client's update map.
156 public void SetAll(TerrainData terrData) 163 public void SetAll(TerrainData terrData)
157 { 164 {
@@ -164,9 +171,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
164 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) 171 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
165 ); 172 );
166 } 173 }
167 for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) 174
175 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
168 { 176 {
169 for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) 177 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
170 { 178 {
171 // Only set tainted. The patch bit may be set if the patch was to be sent later. 179 // Only set tainted. The patch bit may be set if the patch was to be sent later.
172 if (terrData.IsTaintedAt(xx, yy, false)) 180 if (terrData.IsTaintedAt(xx, yy, false))
@@ -210,7 +218,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
210 if (terrainConfig != null) 218 if (terrainConfig != null)
211 { 219 {
212 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 220 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
213 m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance); 221 m_sendTerrainUpdatesByViewDistance =
222 terrainConfig.GetBoolean(
223 "SendTerrainUpdatesByViewDistance",m_sendTerrainUpdatesByViewDistance);
214 } 224 }
215 } 225 }
216 226
@@ -221,26 +231,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain
221 // Install terrain module in the simulator 231 // Install terrain module in the simulator
222 lock(m_scene) 232 lock(m_scene)
223 { 233 {
234 if(m_scene.Bakedmap != null)
235 {
236 m_baked = m_scene.Bakedmap;
237 }
224 if (m_scene.Heightmap == null) 238 if (m_scene.Heightmap == null)
225 { 239 {
226 m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX, 240 if(m_baked != null)
227 (int)m_scene.RegionInfo.RegionSizeY, 241 m_channel = m_baked.MakeCopy();
228 (int)m_scene.RegionInfo.RegionSizeZ); 242 else
243 m_channel = new TerrainChannel(m_InitialTerrain,
244 (int)m_scene.RegionInfo.RegionSizeX,
245 (int)m_scene.RegionInfo.RegionSizeY,
246 (int)m_scene.RegionInfo.RegionSizeZ);
229 m_scene.Heightmap = m_channel; 247 m_scene.Heightmap = m_channel;
230 UpdateRevertMap();
231 } 248 }
232 else 249 else
233 { 250 {
234 m_channel = m_scene.Heightmap; 251 m_channel = m_scene.Heightmap;
235 UpdateRevertMap();
236 } 252 }
253 if(m_baked == null)
254 UpdateBakedMap();
237 255
238 m_scene.RegisterModuleInterface<ITerrainModule>(this); 256 m_scene.RegisterModuleInterface<ITerrainModule>(this);
239 m_scene.EventManager.OnNewClient += EventManager_OnNewClient; 257 m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
240 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed; 258 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
241 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 259 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
242 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; 260 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
243 m_scene.EventManager.OnFrame += EventManager_OnFrame; 261 m_scene.EventManager.OnTerrainCheckUpdates += EventManager_TerrainCheckUpdates;
244 } 262 }
245 263
246 InstallDefaultEffects(); 264 InstallDefaultEffects();
@@ -279,7 +297,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
279 // remove the commands 297 // remove the commands
280 m_scene.UnregisterModuleCommander(m_commander.Name); 298 m_scene.UnregisterModuleCommander(m_commander.Name);
281 // remove the event-handlers 299 // remove the event-handlers
282 m_scene.EventManager.OnFrame -= EventManager_OnFrame; 300
301 m_scene.EventManager.OnTerrainCheckUpdates -= EventManager_TerrainCheckUpdates;
283 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick; 302 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick;
284 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; 303 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
285 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed; 304 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
@@ -334,7 +353,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
334 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); 353 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
335 m_scene.Heightmap = channel; 354 m_scene.Heightmap = channel;
336 m_channel = channel; 355 m_channel = channel;
337 UpdateRevertMap(); 356 UpdateBakedMap();
338 } 357 }
339 catch(NotImplementedException) 358 catch(NotImplementedException)
340 { 359 {
@@ -426,7 +445,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
426 { 445 {
427 ITerrainChannel channel = loader.Value.LoadStream(stream); 446 ITerrainChannel channel = loader.Value.LoadStream(stream);
428 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); 447 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
429 UpdateRevertMap(); 448 UpdateBakedMap();
430 } 449 }
431 catch(NotImplementedException) 450 catch(NotImplementedException)
432 { 451 {
@@ -444,6 +463,37 @@ namespace OpenSim.Region.CoreModules.World.Terrain
444 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); 463 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
445 } 464 }
446 465
466 public void LoadFromStream(string filename, Vector3 displacement,
467 float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Stream stream)
468 {
469 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
470 {
471 if (filename.EndsWith(loader.Key))
472 {
473 lock (m_scene)
474 {
475 try
476 {
477 ITerrainChannel channel = loader.Value.LoadStream(stream);
478 m_channel.MergeWithBounding(channel, displacement, rotationDegrees, boundingOrigin, boundingSize);
479 UpdateBakedMap();
480 }
481 catch (NotImplementedException)
482 {
483 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
484 " parser does not support file loading. (May be save only)");
485 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value));
486 }
487 }
488
489 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
490 return;
491 }
492 }
493 m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format.");
494 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
495 }
496
447 private static Stream URIFetch(Uri uri) 497 private static Stream URIFetch(Uri uri)
448 { 498 {
449 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 499 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
@@ -506,12 +556,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
506 556
507 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. 557 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
508 // ITerrainModule.TaintTerrain() 558 // ITerrainModule.TaintTerrain()
509 public void TaintTerrain() 559 public void TaintTerrain ()
510 { 560 {
511 lock(m_perClientPatchUpdates) 561 lock (m_perClientPatchUpdates)
512 { 562 {
513 // Set the flags for all clients so the tainted patches will be sent out 563 // Set the flags for all clients so the tainted patches will be sent out
514 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 564 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
515 { 565 {
516 pups.SetAll(m_scene.Heightmap.GetTerrainData()); 566 pups.SetAll(m_scene.Heightmap.GetTerrainData());
517 } 567 }
@@ -521,13 +571,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
521 // ITerrainModule.PushTerrain() 571 // ITerrainModule.PushTerrain()
522 public void PushTerrain(IClientAPI pClient) 572 public void PushTerrain(IClientAPI pClient)
523 { 573 {
524 // If view distance based, set the modified patch bits and the frame event will send the updates
525 if (m_sendTerrainUpdatesByViewDistance) 574 if (m_sendTerrainUpdatesByViewDistance)
526 { 575 {
527 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 576 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
528 if (presence != null) 577 if (presence != null)
529 { 578 {
530 lock(m_perClientPatchUpdates) 579 lock (m_perClientPatchUpdates)
531 { 580 {
532 PatchUpdates pups; 581 PatchUpdates pups;
533 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) 582 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
@@ -536,7 +585,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
536 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence); 585 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
537 m_perClientPatchUpdates.Add(presence.UUID, pups); 586 m_perClientPatchUpdates.Add(presence.UUID, pups);
538 } 587 }
539 // By setting all to modified, the next update tick will send the patches
540 pups.SetAll(true); 588 pups.SetAll(true);
541 } 589 }
542 } 590 }
@@ -547,6 +595,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
547 pClient.SendLayerData(new float[10]); 595 pClient.SendLayerData(new float[10]);
548 } 596 }
549 } 597 }
598
550 #region Plugin Loading Methods 599 #region Plugin Loading Methods
551 600
552 private void LoadPlugins() 601 private void LoadPlugins()
@@ -595,7 +644,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
595 { 644 {
596 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); 645 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
597 m_loaders[terLoader.FileExtension] = terLoader; 646 m_loaders[terLoader.FileExtension] = terLoader;
598 m_log.Info("L ... " + typeName); 647 m_log.Debug("L ... " + typeName);
599 } 648 }
600 } 649 }
601 catch(AmbiguousMatchException) 650 catch(AmbiguousMatchException)
@@ -611,12 +660,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
611 if (!m_plugineffects.ContainsKey(pluginName)) 660 if (!m_plugineffects.ContainsKey(pluginName))
612 { 661 {
613 m_plugineffects.Add(pluginName, effect); 662 m_plugineffects.Add(pluginName, effect);
614 m_log.Info("E ... " + pluginName); 663 m_log.Debug("E ... " + pluginName);
615 } 664 }
616 else 665 else
617 { 666 {
618 m_plugineffects[pluginName] = effect; 667 m_plugineffects[pluginName] = effect;
619 m_log.Info("E ... " + pluginName + " (Replaced)"); 668 m_log.Debug("E ... " + pluginName + " (Replaced)");
620 } 669 }
621 } 670 }
622 } 671 }
@@ -636,7 +685,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
636 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere(); 685 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere();
637 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere(); 686 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere();
638 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere(); 687 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere();
639 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert); 688 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
640 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere(); 689 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere();
641 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere(); 690 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere();
642 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere(); 691 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere();
@@ -647,9 +696,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
647 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea(); 696 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea();
648 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea(); 697 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea();
649 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); 698 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
650 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); 699 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
651 700
652 // Terrain Modifier operations 701 // Terrain Modifier operations
702
653 m_modifyOperations["min"] = new MinModifier(this); 703 m_modifyOperations["min"] = new MinModifier(this);
654 m_modifyOperations["max"] = new MaxModifier(this); 704 m_modifyOperations["max"] = new MaxModifier(this);
655 m_modifyOperations["raise"] = new RaiseModifier(this); 705 m_modifyOperations["raise"] = new RaiseModifier(this);
@@ -673,22 +723,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
673 } 723 }
674 724
675 /// <summary> 725 /// <summary>
676 /// Saves the current state of the region into the revert map buffer. 726 /// Saves the current state of the region into the baked map buffer.
727
677 /// </summary> 728 /// </summary>
678 public void UpdateRevertMap() 729 public void UpdateBakedMap()
679 { 730 {
680 /* 731 m_baked = m_channel.MakeCopy();
681 int x; 732 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
682 for (x = 0; x < m_channel.Width; x++) 733 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
683 { 734 m_scene.Bakedmap = m_baked;
684 int y; 735 m_scene.SaveBakedTerrain();
685 for (y = 0; y < m_channel.Height; y++)
686 {
687 m_revert[x, y] = m_channel[x, y];
688 }
689 }
690 */
691 m_revert = m_channel.MakeCopy();
692 } 736 }
693 737
694 /// <summary> 738 /// <summary>
@@ -715,11 +759,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
715 { 759 {
716 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 760 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
717 fileWidth, fileHeight, 761 fileWidth, fileHeight,
718 (int)m_scene.RegionInfo.RegionSizeX, 762 (int) m_scene.RegionInfo.RegionSizeX,
719 (int)m_scene.RegionInfo.RegionSizeY); 763 (int) m_scene.RegionInfo.RegionSizeY);
720 m_scene.Heightmap = channel; 764 m_scene.Heightmap = channel;
721 m_channel = channel; 765 m_channel = channel;
722 UpdateRevertMap(); 766 UpdateBakedMap();
723 } 767 }
724 768
725 return; 769 return;
@@ -781,39 +825,54 @@ namespace OpenSim.Region.CoreModules.World.Terrain
781 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave); 825 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave);
782 } 826 }
783 827
828
784 /// <summary> 829 /// <summary>
785 /// Called before processing of every simulation frame.
786 /// This is used to check to see of any of the terrain is tainted and, if so, schedule 830 /// This is used to check to see of any of the terrain is tainted and, if so, schedule
787 /// updates for all the presences. 831 /// updates for all the presences.
788 /// This also checks to see if there are updates that need to be sent for each presence. 832 /// This also checks to see if there are updates that need to be sent for each presence.
789 /// This is where the logic is to send terrain updates to clients. 833 /// This is where the logic is to send terrain updates to clients.
790 /// </summary> 834 /// </summary>
791 private void EventManager_OnFrame() 835 /// doing it async, since currently this is 2 heavy for heartbeat
836 private void EventManager_TerrainCheckUpdates()
792 { 837 {
793 TerrainData terrData = m_channel.GetTerrainData(); 838 Util.FireAndForget(
839 EventManager_TerrainCheckUpdatesAsync);
840 }
841
842 object TerrainCheckUpdatesLock = new object();
794 843
795 bool shouldTaint = false; 844 private void EventManager_TerrainCheckUpdatesAsync(object o)
796 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 845 {
846 // dont overlap execution
847 if(Monitor.TryEnter(TerrainCheckUpdatesLock))
797 { 848 {
798 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 849 // this needs fixing
850 TerrainData terrData = m_channel.GetTerrainData();
851
852 bool shouldTaint = false;
853 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
799 { 854 {
800 if (terrData.IsTaintedAt(x, y)) 855 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
801 { 856 {
802 // Found a patch that was modified. Push this flag into the clients. 857 if (terrData.IsTaintedAt(x, y,true))
803 SendToClients(terrData, x, y); 858 {
804 shouldTaint = true; 859 // Found a patch that was modified. Push this flag into the clients.
860 SendToClients(terrData, x, y);
861 shouldTaint = true;
862 }
805 } 863 }
806 } 864 }
807 }
808 865
809 // This event also causes changes to be sent to the clients 866 // This event also causes changes to be sent to the clients
810 CheckSendingPatchesToClients(); 867 CheckSendingPatchesToClients();
811 868
812 // If things changes, generate some events 869 // If things changes, generate some events
813 if (shouldTaint) 870 if (shouldTaint)
814 { 871 {
815 m_scene.EventManager.TriggerTerrainTainted(); 872 m_scene.EventManager.TriggerTerrainTainted();
816 m_tainted = true; 873 m_tainted = true;
874 }
875 Monitor.Exit(TerrainCheckUpdatesLock);
817 } 876 }
818 } 877 }
819 878
@@ -883,8 +942,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
883 presence.ControllingClient.OnLandUndo -= client_OnLandUndo; 942 presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
884 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 943 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
885 } 944 }
886 945 lock (m_perClientPatchUpdates)
887 lock(m_perClientPatchUpdates)
888 m_perClientPatchUpdates.Remove(client); 946 m_perClientPatchUpdates.Remove(client);
889 } 947 }
890 948
@@ -898,12 +956,33 @@ namespace OpenSim.Region.CoreModules.World.Terrain
898 TerrainData terrData = m_channel.GetTerrainData(); 956 TerrainData terrData = m_channel.GetTerrainData();
899 957
900 bool wasLimited = false; 958 bool wasLimited = false;
901 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 959 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
902 { 960 {
903 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 961 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
904 { 962 {
905 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) 963 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
906 { 964 {
965 // If we should respect the estate settings then
966 // fixup and height deltas that don't respect them.
967 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
968 wasLimited |= LimitChannelChanges(terrData, x, y);
969 }
970 }
971 }
972 return wasLimited;
973 }
974
975 private bool EnforceEstateLimits(int startX, int startY, int endX, int endY)
976 {
977 TerrainData terrData = m_channel.GetTerrainData();
978
979 bool wasLimited = false;
980 for (int x = startX; x <= endX; x += Constants.TerrainPatchSize)
981 {
982 for (int y = startX; y <= endY; y += Constants.TerrainPatchSize)
983 {
984 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
985 {
907 // If we should respect the estate settings then 986 // If we should respect the estate settings then
908 // fixup and height deltas that don't respect them. 987 // fixup and height deltas that don't respect them.
909 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. 988 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
@@ -926,13 +1005,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
926 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; 1005 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
927 1006
928 // loop through the height map for this patch and compare it against 1007 // loop through the height map for this patch and compare it against
929 // the revert map 1008 // the baked map
930 for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) 1009 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
931 { 1010 {
932 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 1011 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
933 { 1012 {
934 float requestedHeight = terrData[x, y]; 1013 float requestedHeight = terrData[x, y];
935 float bakedHeight = (float)m_revert[x, y]; 1014 float bakedHeight = (float)m_baked[x, y];
936 float requestedDelta = requestedHeight - bakedHeight; 1015 float requestedDelta = requestedHeight - bakedHeight;
937 1016
938 if (requestedDelta > maxDelta) 1017 if (requestedDelta > maxDelta)
@@ -953,15 +1032,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
953 1032
954 private void client_OnLandUndo(IClientAPI client) 1033 private void client_OnLandUndo(IClientAPI client)
955 { 1034 {
956 lock(m_undo)
957 {
958 if (m_undo.Count > 0)
959 {
960 LandUndoState goback = m_undo.Pop();
961 if (goback != null)
962 goback.PlaybackState();
963 }
964 }
965 } 1035 }
966 1036
967 /// <summary> 1037 /// <summary>
@@ -975,19 +1045,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
975 if (m_sendTerrainUpdatesByViewDistance) 1045 if (m_sendTerrainUpdatesByViewDistance)
976 { 1046 {
977 // Add that this patch needs to be sent to the accounting for each client. 1047 // Add that this patch needs to be sent to the accounting for each client.
978 lock(m_perClientPatchUpdates) 1048 lock (m_perClientPatchUpdates)
979 { 1049 {
980 m_scene.ForEachScenePresence(presence => 1050 m_scene.ForEachScenePresence(presence =>
981 {
982 PatchUpdates thisClientUpdates;
983 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
984 { 1051 {
985 // There is a ScenePresence without a send patch map. Create one. 1052 PatchUpdates thisClientUpdates;
986 thisClientUpdates = new PatchUpdates(terrData, presence); 1053 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
987 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates); 1054 {
1055 // There is a ScenePresence without a send patch map. Create one.
1056 thisClientUpdates = new PatchUpdates(terrData, presence);
1057 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
1058 }
1059 thisClientUpdates.SetByXY(x, y, true);
988 } 1060 }
989 thisClientUpdates.SetByXY(x, y, true);
990 }
991 ); 1061 );
992 } 1062 }
993 } 1063 }
@@ -998,7 +1068,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
998 //float[] heightMap = terrData.GetFloatsSerialized(); 1068 //float[] heightMap = terrData.GetFloatsSerialized();
999 float[] heightMap = new float[10]; 1069 float[] heightMap = new float[10];
1000 m_scene.ForEachClient( 1070 m_scene.ForEachClient(
1001 delegate(IClientAPI controller) 1071 delegate (IClientAPI controller)
1002 { 1072 {
1003 controller.SendLayerData(x / Constants.TerrainPatchSize, 1073 controller.SendLayerData(x / Constants.TerrainPatchSize,
1004 y / Constants.TerrainPatchSize, 1074 y / Constants.TerrainPatchSize,
@@ -1013,14 +1083,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1013 public int PatchX; 1083 public int PatchX;
1014 public int PatchY; 1084 public int PatchY;
1015 public float Dist; 1085 public float Dist;
1016
1017 public PatchesToSend(int pX, int pY, float pDist) 1086 public PatchesToSend(int pX, int pY, float pDist)
1018 { 1087 {
1019 PatchX = pX; 1088 PatchX = pX;
1020 PatchY = pY; 1089 PatchY = pY;
1021 Dist = pDist; 1090 Dist = pDist;
1022 } 1091 }
1023
1024 public int CompareTo(PatchesToSend other) 1092 public int CompareTo(PatchesToSend other)
1025 { 1093 {
1026 return Dist.CompareTo(other.Dist); 1094 return Dist.CompareTo(other.Dist);
@@ -1029,113 +1097,216 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1029 1097
1030 // Called each frame time to see if there are any patches to send to any of the 1098 // Called each frame time to see if there are any patches to send to any of the
1031 // ScenePresences. 1099 // ScenePresences.
1032 // We know this is only called if we are doing view distance patch sending so some
1033 // tests are not made.
1034 // Loop through all the per-client info and send any patches necessary. 1100 // Loop through all the per-client info and send any patches necessary.
1035 private void CheckSendingPatchesToClients() 1101 private void CheckSendingPatchesToClients()
1036 { 1102 {
1037 lock(m_perClientPatchUpdates) 1103 lock (m_perClientPatchUpdates)
1038 { 1104 {
1039 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 1105 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
1040 { 1106 {
1107 if(pups.Presence.IsDeleted)
1108 continue;
1109
1110 // limit rate acording to udp land queue state
1111 if (!pups.Presence.ControllingClient.CanSendLayerData())
1112 continue;
1113
1041 if (pups.HasUpdates()) 1114 if (pups.HasUpdates())
1042 { 1115 {
1043 // There is something that could be sent to this client. 1116 if (m_sendTerrainUpdatesByViewDistance)
1044 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1045 if (toSend.Count > 0)
1046 { 1117 {
1047 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}", 1118 // There is something that could be sent to this client.
1048 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName); 1119 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1049 // Sort the patches to send by the distance from the presence 1120 if (toSend.Count > 0)
1050 toSend.Sort();
1051 /* old way that sent individual patches
1052 foreach (PatchesToSend pts in toSend)
1053 {
1054 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1055 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1056 }
1057 */
1058
1059 // new way that sends all patches to the protocol so they can be sent in one block
1060 int[] xPieces = new int[toSend.Count];
1061 int[] yPieces = new int[toSend.Count];
1062 float[] patchPieces = new float[toSend.Count * 2];
1063 int pieceIndex = 0;
1064 foreach(PatchesToSend pts in toSend)
1065 { 1121 {
1066 patchPieces[pieceIndex++] = pts.PatchX; 1122 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
1067 patchPieces[pieceIndex++] = pts.PatchY; 1123 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
1124 // Sort the patches to send by the distance from the presence
1125 toSend.Sort();
1126 /*
1127 foreach (PatchesToSend pts in toSend)
1128 {
1129 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1130 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1131 }
1132 */
1133
1134 float[] patchPieces = new float[toSend.Count * 2];
1135 int pieceIndex = 0;
1136 foreach (PatchesToSend pts in toSend)
1137 {
1138 patchPieces[pieceIndex++] = pts.PatchX;
1139 patchPieces[pieceIndex++] = pts.PatchY;
1140 }
1141 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
1068 } 1142 }
1069 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces); 1143 if (pups.sendAll && toSend.Count < 1024)
1144 SendAllModifiedPatchs(pups);
1145 }
1146 else
1147 SendAllModifiedPatchs(pups);
1148 }
1149 }
1150 }
1151 }
1152 private void SendAllModifiedPatchs(PatchUpdates pups)
1153 {
1154 if (!pups.sendAll) // sanity
1155 return;
1156
1157 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1158 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1159
1160 if (pups.sendAllcurrentX >= limitX && pups.sendAllcurrentY >= limitY)
1161 {
1162 pups.sendAll = false;
1163 pups.sendAllcurrentX = 0;
1164 pups.sendAllcurrentY = 0;
1165 return;
1166 }
1167
1168 int npatchs = 0;
1169 List<PatchesToSend> patchs = new List<PatchesToSend>();
1170 int x = pups.sendAllcurrentX;
1171 int y = pups.sendAllcurrentY;
1172 // send it in the order viewer draws it
1173 // even if not best for memory scan
1174 for (; y < limitY; y++)
1175 {
1176 for (; x < limitX; x++)
1177 {
1178 if (pups.GetByPatch(x, y))
1179 {
1180 pups.SetByPatch(x, y, false);
1181 patchs.Add(new PatchesToSend(x, y, 0));
1182 if (++npatchs >= 128)
1183 {
1184 x++;
1185 break;
1070 } 1186 }
1071 } 1187 }
1072 } 1188 }
1189 if (npatchs >= 128)
1190 break;
1191 x = 0;
1192 }
1193
1194 if (x >= limitX && y >= limitY)
1195 {
1196 pups.sendAll = false;
1197 pups.sendAllcurrentX = 0;
1198 pups.sendAllcurrentY = 0;
1199 }
1200 else
1201 {
1202 pups.sendAllcurrentX = x;
1203 pups.sendAllcurrentY = y;
1204 }
1205
1206 npatchs = patchs.Count;
1207 if (npatchs > 0)
1208 {
1209 int[] xPieces = new int[npatchs];
1210 int[] yPieces = new int[npatchs];
1211 float[] patchPieces = new float[npatchs * 2];
1212 int pieceIndex = 0;
1213 foreach (PatchesToSend pts in patchs)
1214 {
1215 patchPieces[pieceIndex++] = pts.PatchX;
1216 patchPieces[pieceIndex++] = pts.PatchY;
1217 }
1218 pups.Presence.ControllingClient.SendLayerData(-npatchs, 0, patchPieces);
1073 } 1219 }
1074 } 1220 }
1075 1221
1076 // Compute a list of modified patches that are within our view distance.
1077 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups) 1222 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
1078 { 1223 {
1079 List<PatchesToSend> ret = new List<PatchesToSend>(); 1224 List<PatchesToSend> ret = new List<PatchesToSend>();
1080 1225
1226 int npatchs = 0;
1227
1081 ScenePresence presence = pups.Presence; 1228 ScenePresence presence = pups.Presence;
1082 if (presence == null) 1229 if (presence == null)
1083 return ret; 1230 return ret;
1084 1231
1085 Vector3 presencePos = presence.AbsolutePosition; 1232 float minz = presence.AbsolutePosition.Z;
1086 1233 if (presence.CameraPosition.Z < minz)
1087 // Before this distance check, the whole region just showed up. Adding the distance 1234 minz = presence.CameraPosition.Z;
1088 // check causes different things to happen for the current and adjacent regions. 1235
1089 // So, to keep legacy views, if the region is legacy sized, don't do distance check. 1236 // this limit should be max terrainheight + max draw
1090 bool isLegacySizedRegion = pups.Terrain.SizeX == Constants.RegionSize && pups.Terrain.SizeY == Constants.RegionSize; 1237 if (minz > 1500f)
1091 bool shouldCheckViewDistance = m_sendTerrainUpdatesByViewDistance && !isLegacySizedRegion; 1238 return ret;
1092 1239
1093 int startX = 0; 1240 int DrawDistance = (int)presence.DrawDistance;
1094 int endX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize; 1241
1095 int startY = 0; 1242 DrawDistance = DrawDistance / Constants.TerrainPatchSize;
1096 int endY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize; 1243
1097 1244 int testposX;
1098 // The following only reduces the size of area scanned for updates. Only significant for very large varregions. 1245 int testposY;
1099 if (shouldCheckViewDistance) 1246
1100 { 1247 if (Math.Abs(presence.AbsolutePosition.X - presence.CameraPosition.X) > 30
1101 // Compute the area of patches within our draw distance 1248 || Math.Abs(presence.AbsolutePosition.Y - presence.CameraPosition.Y) > 30)
1102 startX = (((int)(presencePos.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1249 {
1103 startX = Math.Max(startX, 0); 1250 testposX = (int)presence.CameraPosition.X / Constants.TerrainPatchSize;
1104 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1251 testposY = (int)presence.CameraPosition.Y / Constants.TerrainPatchSize;
1105 startY = (((int)(presencePos.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1252 }
1106 startY = Math.Max(startY, 0); 1253 else
1107 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1254 {
1108 endX = (((int)(presencePos.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1255 testposX = (int)presence.AbsolutePosition.X / Constants.TerrainPatchSize;
1109 endX = Math.Max(endX, 0); 1256 testposY = (int)presence.AbsolutePosition.Y / Constants.TerrainPatchSize;
1110 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1257 }
1111 endY = (((int)(presencePos.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1258 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1112 endY = Math.Max(endY, 0); 1259 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1113 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1260
1114 } 1261 // Compute the area of patches within our draw distance
1115 1262 int startX = testposX - DrawDistance;
1116 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, cpos={4}, isChild={5}, start=<{6},{7}>, end=<{8},{9}>", 1263 if (startX < 0)
1117 // LogHeader, m_scene.RegionInfo.RegionName, 1264 startX = 0;
1118 // presence.DrawDistance, presencePos, presence.CameraPosition, 1265 else if (startX >= limitX)
1119 // isLegacySizeChildRegion, 1266 startX = limitX - 1;
1120 // startX, startY, endX, endY); 1267
1121 for(int x = startX; x < endX; x++) 1268 int startY = testposY - DrawDistance;
1122 { 1269 if (startY < 0)
1123 for(int y = startY; y < endY; y++) 1270 startY = 0;
1271 else if (startY >= limitY)
1272 startY = limitY - 1;
1273
1274 int endX = testposX + DrawDistance;
1275 if (endX < 0)
1276 endX = 0;
1277 else if (endX > limitX)
1278 endX = limitX;
1279
1280 int endY = testposY + DrawDistance;
1281 if (endY < 0)
1282 endY = 0;
1283 else if (endY > limitY)
1284 endY = limitY;
1285
1286 int distx;
1287 int disty;
1288 int distsq;
1289
1290 DrawDistance *= DrawDistance;
1291
1292 for (int x = startX; x < endX; x++)
1293 {
1294 for (int y = startY; y < endY; y++)
1124 { 1295 {
1125 //Need to make sure we don't send the same ones over and over
1126 Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
1127 if (pups.GetByPatch(x, y)) 1296 if (pups.GetByPatch(x, y))
1128 { 1297 {
1129 //Check which has less distance, camera or avatar position, both have to be done. 1298 distx = x - testposX;
1130 //Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off 1299 disty = y - testposY;
1131 if (!shouldCheckViewDistance 1300 distsq = distx * distx + disty * disty;
1132 || Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50) 1301 if (distsq < DrawDistance)
1133 || Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
1134 { 1302 {
1135 //They can see it, send it to them
1136 pups.SetByPatch(x, y, false); 1303 pups.SetByPatch(x, y, false);
1137 float dist = Vector3.DistanceSquared(presencePos, patchPos); 1304 ret.Add(new PatchesToSend(x, y, (float)distsq));
1138 ret.Add(new PatchesToSend(x, y, dist)); 1305 if (npatchs++ > 1024)
1306 {
1307 y = endY;
1308 x = endX;
1309 }
1139 } 1310 }
1140 } 1311 }
1141 } 1312 }
@@ -1161,33 +1332,44 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1161 int zx = (int)(west + 0.5); 1332 int zx = (int)(west + 0.5);
1162 int zy = (int)(north + 0.5); 1333 int zy = (int)(north + 0.5);
1163 1334
1164 int dx; 1335 int startX = zx - n;
1165 for(dx=-n; dx<=n; dx++) 1336 if (startX < 0)
1337 startX = 0;
1338
1339 int startY = zy - n;
1340 if (startY < 0)
1341 startY = 0;
1342
1343 int endX = zx + n;
1344 if (endX >= m_channel.Width)
1345 endX = m_channel.Width - 1;
1346 int endY = zy + n;
1347 if (endY >= m_channel.Height)
1348 endY = m_channel.Height - 1;
1349
1350 int x, y;
1351
1352 for (x = startX; x <= endX; x++)
1166 { 1353 {
1167 int dy; 1354 for (y = startY; y <= endY; y++)
1168 for(dy=-n; dy<=n; dy++)
1169 { 1355 {
1170 int x = zx + dx; 1356 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1171 int y = zy + dy;
1172 if (x >= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height)
1173 { 1357 {
1174 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) 1358 allowMask[x, y] = true;
1175 { 1359 allowed = true;
1176 allowMask[x, y] = true;
1177 allowed = true;
1178 }
1179 } 1360 }
1180 } 1361 }
1181 } 1362 }
1182 if (allowed) 1363 if (allowed)
1183 { 1364 {
1184 StoreUndoState(); 1365 StoreUndoState();
1185 m_painteffects[(StandardTerrainEffects)action].PaintEffect( 1366 m_painteffects[(StandardTerrainEffects) action].PaintEffect(
1186 m_channel, allowMask, west, south, height, size, seconds); 1367 m_channel, allowMask, west, south, height, size, seconds,
1368 startX, endX, startY, endY);
1187 1369
1188 //revert changes outside estate limits 1370 //block changes outside estate limits
1189 if (!god) 1371 if (!god)
1190 EnforceEstateLimits(); 1372 EnforceEstateLimits(startX, endX, startY, endY);
1191 } 1373 }
1192 } 1374 }
1193 else 1375 else
@@ -1202,22 +1384,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1202 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; 1384 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
1203 fillArea.Initialize(); 1385 fillArea.Initialize();
1204 1386
1205 int x; 1387 int startX = (int)west;
1206 for(x = 0; x < m_channel.Width; x++) 1388 int startY = (int)south;
1389 int endX = (int)east;
1390 int endY = (int)north;
1391
1392 if (startX < 0)
1393 startX = 0;
1394 else if (startX >= m_channel.Width)
1395 startX = m_channel.Width - 1;
1396
1397 if (endX < 0)
1398 endX = 0;
1399 else if (endX >= m_channel.Width)
1400 endX = m_channel.Width - 1;
1401
1402 if (startY < 0)
1403 startY = 0;
1404 else if (startY >= m_channel.Height)
1405 startY = m_channel.Height - 1;
1406
1407 if (endY < 0)
1408 endY = 0;
1409 else if (endY >= m_channel.Height)
1410 endY = m_channel.Height - 1;
1411
1412
1413 int x, y;
1414
1415 for (x = startX; x <= endX; x++)
1207 { 1416 {
1208 int y; 1417 for (y = startY; y <= endY; y++)
1209 for(y = 0; y < m_channel.Height; y++)
1210 { 1418 {
1211 if (x < east && x > west) 1419 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1212 { 1420 {
1213 if (y < north && y > south) 1421 fillArea[x, y] = true;
1214 { 1422 allowed = true;
1215 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1216 {
1217 fillArea[x, y] = true;
1218 allowed = true;
1219 }
1220 }
1221 } 1423 }
1222 } 1424 }
1223 } 1425 }
@@ -1225,11 +1427,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1225 if (allowed) 1427 if (allowed)
1226 { 1428 {
1227 StoreUndoState(); 1429 StoreUndoState();
1228 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size); 1430 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size,
1431 startX, endX, startY, endY);
1229 1432
1230 //revert changes outside estate limits 1433 //block changes outside estate limits
1231 if (!god) 1434 if (!god)
1232 EnforceEstateLimits(); 1435 EnforceEstateLimits(startX, endX, startY, endY);
1233 } 1436 }
1234 } 1437 }
1235 else 1438 else
@@ -1260,37 +1463,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1260 1463
1261 private void StoreUndoState() 1464 private void StoreUndoState()
1262 { 1465 {
1263 lock(m_undo)
1264 {
1265 if (m_undo.Count > 0)
1266 {
1267 LandUndoState last = m_undo.Peek();
1268 if (last != null)
1269 {
1270 if (last.Compare(m_channel))
1271 return;
1272 }
1273 }
1274
1275 LandUndoState nUndo = new LandUndoState(this, m_channel);
1276 m_undo.Push(nUndo);
1277 }
1278 } 1466 }
1279 1467
1280 #region Console Commands 1468 #region Console Commands
1281 1469
1282 private void InterfaceLoadFile(Object[] args) 1470 private void InterfaceLoadFile(Object[] args)
1283 { 1471 {
1284 LoadFromFile((string)args[0]); 1472 LoadFromFile((string) args[0]);
1285 } 1473 }
1286 1474
1287 private void InterfaceLoadTileFile(Object[] args) 1475 private void InterfaceLoadTileFile(Object[] args)
1288 { 1476 {
1289 LoadFromFile((string)args[0], 1477 LoadFromFile((string) args[0],
1290 (int)args[1], 1478 (int) args[1],
1291 (int)args[2], 1479 (int) args[2],
1292 (int)args[3], 1480 (int) args[3],
1293 (int)args[4]); 1481 (int) args[4]);
1294 } 1482 }
1295 1483
1296 private void InterfaceSaveFile(Object[] args) 1484 private void InterfaceSaveFile(Object[] args)
@@ -1309,15 +1497,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1309 1497
1310 private void InterfaceBakeTerrain(Object[] args) 1498 private void InterfaceBakeTerrain(Object[] args)
1311 { 1499 {
1312 UpdateRevertMap(); 1500 UpdateBakedMap();
1313 } 1501 }
1314 1502
1315 private void InterfaceRevertTerrain(Object[] args) 1503 private void InterfaceRevertTerrain(Object[] args)
1316 { 1504 {
1317 int x, y; 1505 int x, y;
1318 for(x = 0; x < m_channel.Width; x++) 1506 for (x = 0; x < m_channel.Width; x++)
1319 for(y = 0; y < m_channel.Height; y++) 1507 for (y = 0; y < m_channel.Height; y++)
1320 m_channel[x, y] = m_revert[x, y]; 1508 m_channel[x, y] = m_baked[x, y];
1321 1509
1322 } 1510 }
1323 1511
@@ -1327,9 +1515,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1327 1515
1328 if (direction.ToLower().StartsWith("y")) 1516 if (direction.ToLower().StartsWith("y"))
1329 { 1517 {
1330 for(int x = 0; x < m_channel.Width; x++) 1518 for (int x = 0; x < m_channel.Width; x++)
1331 { 1519 {
1332 for(int y = 0; y < m_channel.Height / 2; y++) 1520 for (int y = 0; y < m_channel.Height / 2; y++)
1333 { 1521 {
1334 double height = m_channel[x, y]; 1522 double height = m_channel[x, y];
1335 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; 1523 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
@@ -1341,9 +1529,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1341 } 1529 }
1342 else if (direction.ToLower().StartsWith("x")) 1530 else if (direction.ToLower().StartsWith("x"))
1343 { 1531 {
1344 for(int y = 0; y < m_channel.Height; y++) 1532 for (int y = 0; y < m_channel.Height; y++)
1345 { 1533 {
1346 for(int x = 0; x < m_channel.Width / 2; x++) 1534 for (int x = 0; x < m_channel.Width / 2; x++)
1347 { 1535 {
1348 double height = m_channel[x, y]; 1536 double height = m_channel[x, y];
1349 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; 1537 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
@@ -1415,50 +1603,57 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1415 } 1603 }
1416 1604
1417 } 1605 }
1418
1419 } 1606 }
1420 1607
1421 private void InterfaceElevateTerrain(Object[] args) 1608 private void InterfaceElevateTerrain(Object[] args)
1422 { 1609 {
1610 double val = (double)args[0];
1611
1423 int x, y; 1612 int x, y;
1424 for(x = 0; x < m_channel.Width; x++) 1613 for (x = 0; x < m_channel.Width; x++)
1425 for(y = 0; y < m_channel.Height; y++) 1614 for (y = 0; y < m_channel.Height; y++)
1426 m_channel[x, y] += (double)args[0]; 1615 m_channel[x, y] += val;
1427 } 1616 }
1428 1617
1429 private void InterfaceMultiplyTerrain(Object[] args) 1618 private void InterfaceMultiplyTerrain(Object[] args)
1430 { 1619 {
1431 int x, y; 1620 int x, y;
1432 for(x = 0; x < m_channel.Width; x++) 1621 double val = (double)args[0];
1433 for(y = 0; y < m_channel.Height; y++) 1622
1434 m_channel[x, y] *= (double)args[0]; 1623 for (x = 0; x < m_channel.Width; x++)
1624 for (y = 0; y < m_channel.Height; y++)
1625 m_channel[x, y] *= val;
1435 } 1626 }
1436 1627
1437 private void InterfaceLowerTerrain(Object[] args) 1628 private void InterfaceLowerTerrain(Object[] args)
1438 { 1629 {
1439 int x, y; 1630 int x, y;
1440 for(x = 0; x < m_channel.Width; x++) 1631 double val = (double)args[0];
1441 for(y = 0; y < m_channel.Height; y++) 1632
1442 m_channel[x, y] -= (double)args[0]; 1633 for (x = 0; x < m_channel.Width; x++)
1634 for (y = 0; y < m_channel.Height; y++)
1635 m_channel[x, y] -= val;
1443 } 1636 }
1444 1637
1445 public void InterfaceFillTerrain(Object[] args) 1638 public void InterfaceFillTerrain(Object[] args)
1446 { 1639 {
1447 int x, y; 1640 int x, y;
1641 double val = (double)args[0];
1448 1642
1449 for(x = 0; x < m_channel.Width; x++) 1643 for (x = 0; x < m_channel.Width; x++)
1450 for(y = 0; y < m_channel.Height; y++) 1644 for (y = 0; y < m_channel.Height; y++)
1451 m_channel[x, y] = (double)args[0]; 1645 m_channel[x, y] = val;
1452 } 1646 }
1453 1647
1454 private void InterfaceMinTerrain(Object[] args) 1648 private void InterfaceMinTerrain(Object[] args)
1455 { 1649 {
1456 int x, y; 1650 int x, y;
1457 for(x = 0; x < m_channel.Width; x++) 1651 double val = (double)args[0];
1652 for (x = 0; x < m_channel.Width; x++)
1458 { 1653 {
1459 for(y = 0; y < m_channel.Height; y++) 1654 for(y = 0; y < m_channel.Height; y++)
1460 { 1655 {
1461 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1656 m_channel[x, y] = Math.Max(val, m_channel[x, y]);
1462 } 1657 }
1463 } 1658 }
1464 } 1659 }
@@ -1466,11 +1661,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1466 private void InterfaceMaxTerrain(Object[] args) 1661 private void InterfaceMaxTerrain(Object[] args)
1467 { 1662 {
1468 int x, y; 1663 int x, y;
1469 for(x = 0; x < m_channel.Width; x++) 1664 double val = (double)args[0];
1665 for (x = 0; x < m_channel.Width; x++)
1470 { 1666 {
1471 for(y = 0; y < m_channel.Height; y++) 1667 for(y = 0; y < m_channel.Height; y++)
1472 { 1668 {
1473 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1669 m_channel[x, y] = Math.Min(val, m_channel[x, y]);
1474 } 1670 }
1475 } 1671 }
1476 } 1672 }
@@ -1620,9 +1816,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1620 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); 1816 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");
1621 1817
1622 Command bakeRegionCommand = 1818 Command bakeRegionCommand =
1623 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); 1819 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions baked map.");
1624 Command revertRegionCommand = 1820 Command revertRegionCommand =
1625 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); 1821 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the baked map terrain into the regions heightmap.");
1626 1822
1627 Command flipCommand = 1823 Command flipCommand =
1628 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis"); 1824 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis");
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs
index 0563ad0..6a832bc 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs
@@ -45,8 +45,8 @@ namespace OpenSim.Region.CoreModules.Terrain.Tests
45 //UUID userId = TestHelpers.ParseTail(0x1); 45 //UUID userId = TestHelpers.ParseTail(0x1);
46 46
47 TerrainModule tm = new TerrainModule(); 47 TerrainModule tm = new TerrainModule();
48 Scene scene = new SceneHelpers().SetupScene(); 48 Scene scene = new SceneHelpers().SetupScene();
49 SceneHelpers.SetupSceneModules(scene, tm); 49 SceneHelpers.SetupSceneModules(scene, tm);
50 50
51 // Fillheight of 30 51 // Fillheight of 30
52 { 52 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index 29e80ef..8e77962 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -60,12 +60,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
60 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize); 60 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
61 ITerrainPaintableEffect effect = new RaiseSphere(); 61 ITerrainPaintableEffect effect = new RaiseSphere();
62 62
63 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0); 63 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
64 0, midRegion - 1,0, (int)Constants.RegionSize -1);
64 Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128)."); 65 Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
65 Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128)."); 66 Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
66 Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128)."); 67 Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
67 Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128)."); 68 Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128).");
68 Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128)."); 69// Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128).");
69 // 70 //
70 // Test LowerSphere 71 // Test LowerSphere
71 // 72 //
@@ -79,13 +80,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
79 } 80 }
80 effect = new LowerSphere(); 81 effect = new LowerSphere();
81 82
82 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0); 83 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
84 0, (int)Constants.RegionSize -1,0, (int)Constants.RegionSize -1);
83 Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128)."); 85 Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
84 Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128)."); 86 Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
85 Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128)."); 87 Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
86 Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128)."); 88 Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128).");
87 Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128)."); 89 Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128).");
88 Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128)."); 90// Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128).");
89 } 91 }
90 92
91 [Test] 93 [Test]
diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
index 3f5d375..4cee7a5 100644
--- a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
+++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
@@ -39,14 +39,14 @@ namespace OpenSim.Region.CoreModules.World.Vegetation
39{ 39{
40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VegetationModule")] 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VegetationModule")]
41 public class VegetationModule : INonSharedRegionModule, IVegetationModule 41 public class VegetationModule : INonSharedRegionModule, IVegetationModule
42 { 42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 44
45 protected Scene m_scene; 45 protected Scene m_scene;
46 46
47 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree }; 47 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree };
48 public PCode[] CreationCapabilities { get { return creationCapabilities; } } 48 public PCode[] CreationCapabilities { get { return creationCapabilities; } }
49 49
50 public void Initialise(IConfigSource source) 50 public void Initialise(IConfigSource source)
51 { 51 {
52 } 52 }
@@ -83,10 +83,10 @@ namespace OpenSim.Region.CoreModules.World.Vegetation
83 treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree; 83 treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree;
84 treeShape.Scale = scale; 84 treeShape.Scale = scale;
85 treeShape.State = (byte)treeType; 85 treeShape.State = (byte)treeType;
86 86
87 return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); 87 return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape);
88 } 88 }
89 89
90 public SceneObjectGroup CreateEntity( 90 public SceneObjectGroup CreateEntity(
91 UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 91 UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
92 { 92 {
@@ -95,22 +95,23 @@ namespace OpenSim.Region.CoreModules.World.Vegetation
95 m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); 95 m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name);
96 return null; 96 return null;
97 } 97 }
98 98
99 SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); 99 SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
100 SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID); 100 SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID);
101 101
102 // if grass or tree, make phantom 102 // if grass or tree, make phantom
103 //rootPart.TrimPermissions(); 103 //rootPart.TrimPermissions();
104 rootPart.AddFlag(PrimFlags.Phantom); 104 rootPart.AddFlag(PrimFlags.Phantom);
105 if (rootPart.Shape.PCode != (byte)PCode.Grass) 105 if (rootPart.Shape.PCode != (byte)PCode.Grass)
106 AdaptTree(ref shape); 106 AdaptTree(ref shape);
107 107
108 m_scene.AddNewSceneObject(sceneObject, true);
109 sceneObject.SetGroup(groupID, null); 108 sceneObject.SetGroup(groupID, null);
110 109 m_scene.AddNewSceneObject(sceneObject, true);
110 sceneObject.InvalidateDeepEffectivePerms();
111
111 return sceneObject; 112 return sceneObject;
112 } 113 }
113 114
114 protected void AdaptTree(ref PrimitiveBaseShape tree) 115 protected void AdaptTree(ref PrimitiveBaseShape tree)
115 { 116 {
116 // Tree size has to be adapted depending on its type 117 // Tree size has to be adapted depending on its type
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 9534ad3..226b330 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -79,6 +79,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting 79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting
80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger. 80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger.
81 /// </remarks> 81 /// </remarks>
82
82 public static Bitmap Splat(ITerrainChannel terrain, 83 public static Bitmap Splat(ITerrainChannel terrain,
83 UUID[] textureIDs, float[] startHeights, float[] heightRanges, 84 UUID[] textureIDs, float[] startHeights, float[] heightRanges,
84 Vector3d regionPosition, IAssetService assetService, bool textureTerrain) 85 Vector3d regionPosition, IAssetService assetService, bool textureTerrain)
@@ -129,8 +130,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
129 asset = assetService.Get(textureIDs[i].ToString()); 130 asset = assetService.Get(textureIDs[i].ToString());
130 if (asset != null) 131 if (asset != null)
131 { 132 {
132// m_log.DebugFormat( 133 // m_log.DebugFormat(
133// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); 134 // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
134 135
135 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 136 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
136 catch (Exception ex) 137 catch (Exception ex)
@@ -140,7 +141,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
140 } 141 }
141 142
142 if (detailTexture[i] != null) 143 if (detailTexture[i] != null)
143 { 144 {
144 // Make sure this texture is the correct size, otherwise resize 145 // Make sure this texture is the correct size, otherwise resize
145 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) 146 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
146 { 147 {
@@ -225,7 +226,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
225 float pctX = (float)x / 255f; 226 float pctX = (float)x / 255f;
226 float pctY = (float)y / 255f; 227 float pctY = (float)y / 255f;
227 228
228 // Use bilinear interpolation between the four corners of start height and 229 // Use bilinear interpolation between the four corners of start height and
229 // height range to select the current values at this position 230 // height range to select the current values at this position
230 float startHeight = ImageUtils.Bilinear( 231 float startHeight = ImageUtils.Bilinear(
231 startHeights[0], 232 startHeights[0],
@@ -256,7 +257,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
256 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; 257 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
257 float noise = (lowFreq + highFreq) * 2f; 258 float noise = (lowFreq + highFreq) * 2f;
258 259
259 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it 260 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
260 float layer = ((height + noise - startHeight) / heightRange) * 4f; 261 float layer = ((height + noise - startHeight) / heightRange) * 4f;
261 if (Single.IsNaN(layer)) 262 if (Single.IsNaN(layer))
262 layer = 0f; 263 layer = 0f;
@@ -352,7 +353,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
352 b.Dispose(); 353 b.Dispose();
353 return result; 354 return result;
354 } 355 }
355
356 public static Bitmap SplatSimple(float[] heightmap) 356 public static Bitmap SplatSimple(float[] heightmap)
357 { 357 {
358 const float BASE_HSV_H = 93f / 360f; 358 const float BASE_HSV_H = 93f / 360f;
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 383a67f..d094bee 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -35,14 +35,14 @@ using System.Reflection;
35using CSJ2K; 35using CSJ2K;
36using Nini.Config; 36using Nini.Config;
37using log4net; 37using log4net;
38using Rednettle.Warp3D; 38using Warp3D;
39using Mono.Addins; 39using Mono.Addins;
40 40
41using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.PhysicsModules.SharedBase; 44//using OpenSim.Region.PhysicsModules.SharedBase;
45using OpenSim.Services.Interfaces; 45//using OpenSim.Services.Interfaces;
46 46
47using OpenMetaverse; 47using OpenMetaverse;
48using OpenMetaverse.Assets; 48using OpenMetaverse.Assets;
@@ -51,6 +51,7 @@ using OpenMetaverse.Rendering;
51using OpenMetaverse.StructuredData; 51using OpenMetaverse.StructuredData;
52 52
53using WarpRenderer = global::Warp3D.Warp3D; 53using WarpRenderer = global::Warp3D.Warp3D;
54using System.Drawing.Drawing2D;
54 55
55namespace OpenSim.Region.CoreModules.World.Warp3DMap 56namespace OpenSim.Region.CoreModules.World.Warp3DMap
56{ 57{
@@ -76,10 +77,19 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
76 private bool m_texturePrims = true; // true if should texture the rendered prims 77 private bool m_texturePrims = true; // true if should texture the rendered prims
77 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it 78 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it
78 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes 79 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes
79 private bool m_useAntiAliasing = false; // true if to anti-alias the rendered image 80 private String m_cacheDirectory = "";
80
81 private bool m_Enabled = false; 81 private bool m_Enabled = false;
82 82
83// private bool m_enable_date = false;
84// private bool m_enable_regionName = false;
85 private bool m_enable_regionPosition = false;
86 private bool m_enable_refreshEveryMonth = false;
87// private bool m_enable_HostedBy = false;
88// private String m_enable_HostedByText = "";
89
90 // private Bitmap lastImage = null;
91 private DateTime lastImageTime = DateTime.MinValue;
92
83 #region Region Module interface 93 #region Region Module interface
84 94
85 public void Initialise(IConfigSource source) 95 public void Initialise(IConfigSource source)
@@ -94,9 +104,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
94 104
95 m_Enabled = true; 105 m_Enabled = true;
96 106
97 m_drawPrimVolume 107 m_drawPrimVolume
98 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); 108 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
99 m_textureTerrain 109 m_textureTerrain
100 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain); 110 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
101 m_texturePrims 111 m_texturePrims
102 = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims); 112 = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
@@ -104,9 +114,19 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
104 = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize); 114 = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
105 m_renderMeshes 115 m_renderMeshes
106 = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes); 116 = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
107 m_useAntiAliasing 117 m_cacheDirectory
108 = Util.GetConfigVarFromSections<bool>(m_config, "UseAntiAliasing", configSections, m_useAntiAliasing); 118 = Util.GetConfigVarFromSections<string>(m_config, "CacheDirectory", configSections, System.IO.Path.Combine(Util.cacheDir(), "MapImageCache"));
109 119
120
121// m_enable_date = Util.GetConfigVarFromSections<bool>(m_config, "enableDate", configSections, false);
122// m_enable_regionName = Util.GetConfigVarFromSections<bool>(m_config, "enableName", configSections, false);
123 m_enable_regionPosition = Util.GetConfigVarFromSections<bool>(m_config, "enablePosition", configSections, false);
124 m_enable_refreshEveryMonth = Util.GetConfigVarFromSections<bool>(m_config, "RefreshEveryMonth", configSections, true);
125// m_enable_HostedBy = Util.GetConfigVarFromSections<bool>(m_config, "enableHostedBy", configSections, false);
126// m_enable_HostedByText = Util.GetConfigVarFromSections<String>(m_config, "HosterText", configSections, String.Empty);
127
128 if (!Directory.Exists(m_cacheDirectory))
129 Directory.CreateDirectory(m_cacheDirectory);
110 } 130 }
111 131
112 public void AddRegion(Scene scene) 132 public void AddRegion(Scene scene)
@@ -118,14 +138,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
118 138
119 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 139 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
120 if (renderers.Count > 0) 140 if (renderers.Count > 0)
121 { 141 m_log.Info("[MAPTILE]: Loaded prim mesher " + renderers[0]);
122 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
123 m_log.DebugFormat("[WARP 3D IMAGE MODULE]: Loaded prim mesher {0}", m_primMesher);
124 }
125 else 142 else
126 { 143 m_log.Info("[MAPTILE]: No prim mesher loaded, prim rendering will be disabled");
127 m_log.Debug("[WARP 3D IMAGE MODULE]: No prim mesher loaded, prim rendering will be disabled");
128 }
129 144
130 m_scene.RegisterModuleInterface<IMapImageGenerator>(this); 145 m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
131 } 146 }
@@ -155,21 +170,149 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
155 #endregion 170 #endregion
156 171
157 #region IMapImageGenerator Members 172 #region IMapImageGenerator Members
173/*
174 public static string fillInt(int _i, int _l)
175 {
176 String _return = _i.ToString();
177
178 while(_return.Length < _l)
179 {
180 _return = 0 + _return;
181 }
182
183 return _return;
184 }
185
186 public static int getCurrentUnixTime()
187 {
188 return (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
189 }
190
191 public static String unixTimeToDateString(int unixTime)
192 {
193 DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
194 long unixTimeStampInTicks = (long)(unixTime * TimeSpan.TicksPerSecond);
195 DateTime _date = new DateTime(unixStart.Ticks + unixTimeStampInTicks, System.DateTimeKind.Utc);
158 196
197 return fillInt(_date.Day, 2) + "." + fillInt(_date.Month, 2) + "." + fillInt(_date.Year, 4) + " " + fillInt(_date.Hour, 2) + ":" + fillInt(_date.Minute, 2);
198 }
199
200 private void writeDateOnMap(ref Bitmap _map)
201 {
202 RectangleF rectf = new RectangleF(2, 1, 200, 25);
203
204 Graphics g = Graphics.FromImage(_map);
205 g.SmoothingMode = SmoothingMode.AntiAlias;
206 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
207 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
208 g.DrawString(unixTimeToDateString(getCurrentUnixTime()), new Font("Arial", 8), Brushes.White, rectf);
209 g.Flush();
210 }
211
212 private void writeNameOnMap(ref Bitmap _map)
213 {
214 RectangleF rectf = new RectangleF(2, m_scene.RegionInfo.RegionSizeX - 15, 200, 25);
215
216 Graphics g = Graphics.FromImage(_map);
217 g.SmoothingMode = SmoothingMode.AntiAlias;
218 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
219 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
220 g.DrawString(m_scene.Name, new Font("Arial", 8), Brushes.White, rectf);
221 g.Flush();
222 }
223*/
224 private void writePositionOnMap(ref Bitmap _map)
225 {
226 RectangleF rectf = new RectangleF(m_scene.RegionInfo.RegionSizeY - 75, m_scene.RegionInfo.RegionSizeX - 15, 80, 25);
227
228 Graphics g = Graphics.FromImage(_map);
229 g.SmoothingMode = SmoothingMode.AntiAlias;
230 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
231 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
232 g.DrawString("<" + m_scene.RegionInfo.RegionLocX + " " + m_scene.RegionInfo.RegionLocY + ">", new Font("Arial", 8), Brushes.White, rectf);
233 g.Flush();
234 }
235/*
236 private void writeHostedByOnMap(ref Bitmap _map)
237 {
238 RectangleF rectf = new RectangleF(2, m_scene.RegionInfo.RegionSizeX - 15, 200, 25);
239
240 Graphics g = Graphics.FromImage(_map);
241 g.SmoothingMode = SmoothingMode.AntiAlias;
242 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
243 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
244 g.DrawString(m_enable_HostedByText, new Font("Arial", 8), Brushes.Gray, rectf);
245 g.Flush();
246 }
247*/
248 public Bitmap CreateMapTileForce()
249 {
250 m_log.Info("[MAPTILE]: Forcing a map tile regenerate.");
251 File.Delete(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
252 return CreateMapTile();
253 }
159 public Bitmap CreateMapTile() 254 public Bitmap CreateMapTile()
160 { 255 {
161 // Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); 256 if ((File.GetCreationTime(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")).Month != DateTime.Now.Month) && (m_enable_refreshEveryMonth == true))
162 // Camera above the middle of the region 257 {
163 Vector3 camPos = new Vector3( 258 m_log.InfoFormat("[MAPTILE]: Clearing old map tile out of cache {0} {1}.",
164 m_scene.RegionInfo.RegionSizeX/2 - 0.5f, 259 File.GetCreationTime(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")).Month, DateTime.Now.Month);
165 m_scene.RegionInfo.RegionSizeY/2 - 0.5f, 260 File.Delete(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
166 221.7025033688163f); 261 }
167 // Viewport viewing down onto the region 262
168 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, 263 if(File.Exists(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")))
169 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, 264 {
170 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY ); 265 return new Bitmap(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
171 // Fill the viewport and return the image 266 }
172 return CreateMapTile(viewport, false); 267 else
268 {
269 m_log.Info("[MAPTILE]: Actually generating a map tile.");
270 /* this must be on all map, not just its image
271 if ((DateTime.Now - lastImageTime).TotalSeconds < 3600)
272 {
273 return (Bitmap)lastImage.Clone();
274 }
275 */
276
277 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
278 if (renderers.Count > 0)
279 {
280 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
281 }
282
283 Vector3 camPos = new Vector3(
284 m_scene.RegionInfo.RegionSizeX / 2 - 0.5f,
285 m_scene.RegionInfo.RegionSizeY / 2 - 0.5f,
286 221.7025033688163f);
287 // Viewport viewing down onto the region
288 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
289 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
290 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY);
291
292 Bitmap tile = CreateMapTile(viewport, false);
293
294// if (m_enable_date)
295// writeDateOnMap(ref tile);
296
297// if (m_enable_regionName)
298// writeNameOnMap(ref tile);
299
300 if (m_enable_regionPosition)
301 writePositionOnMap(ref tile);
302
303// if (m_enable_HostedBy)
304// writeHostedByOnMap(ref tile);
305
306 tile.Save(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
307 m_primMesher = null;
308 return tile;
309
310 /*
311 lastImage = tile;
312 lastImageTime = DateTime.Now;
313 return (Bitmap)lastImage.Clone();
314 */
315 }
173 } 316 }
174 317
175 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 318 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
@@ -185,21 +328,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
185 int width = viewport.Width; 328 int width = viewport.Width;
186 int height = viewport.Height; 329 int height = viewport.Height;
187 330
188 if (m_useAntiAliasing)
189 {
190 width *= 2;
191 height *= 2;
192 }
193
194 WarpRenderer renderer = new WarpRenderer(); 331 WarpRenderer renderer = new WarpRenderer();
195 332
196 renderer.CreateScene(width, height); 333 if(!renderer.CreateScene(width, height))
197 renderer.Scene.autoCalcNormals = false; 334 return new Bitmap(width,height);
198 335
199 #region Camera 336 #region Camera
200 337
201 warp_Vector pos = ConvertVector(viewport.Position); 338 warp_Vector pos = ConvertVector(viewport.Position);
202 pos.z -= 0.001f; // Works around an issue with the Warp3D camera
203 warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection)); 339 warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection));
204 340
205 renderer.Scene.defaultCamera.setPos(pos); 341 renderer.Scene.defaultCamera.setPos(pos);
@@ -207,9 +343,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
207 343
208 if (viewport.Orthographic) 344 if (viewport.Orthographic)
209 { 345 {
210 renderer.Scene.defaultCamera.isOrthographic = true; 346 renderer.Scene.defaultCamera.setOrthographic(true,viewport.OrthoWindowWidth, viewport.OrthoWindowHeight);
211 renderer.Scene.defaultCamera.orthoViewWidth = viewport.OrthoWindowWidth;
212 renderer.Scene.defaultCamera.orthoViewHeight = viewport.OrthoWindowHeight;
213 } 347 }
214 else 348 else
215 { 349 {
@@ -231,24 +365,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
231 renderer.Render(); 365 renderer.Render();
232 Bitmap bitmap = renderer.Scene.getImage(); 366 Bitmap bitmap = renderer.Scene.getImage();
233 367
234 if (m_useAntiAliasing) 368 renderer.Scene.destroy();
235 { 369 renderer.Reset();
236 using (Bitmap origBitmap = bitmap)
237 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
238 }
239
240 // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
241 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
242 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
243 // this map tile simply takes a lot of memory.
244 foreach (var o in renderer.Scene.objectData.Values)
245 {
246 warp_Object obj = (warp_Object)o;
247 obj.vertexData = null;
248 obj.triangleData = null;
249 }
250
251 renderer.Scene.removeAllObjects();
252 renderer = null; 370 renderer = null;
253 viewport = null; 371 viewport = null;
254 372
@@ -284,16 +402,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
284 { 402 {
285 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 403 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
286 404
287 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
288 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
289 waterHeight,
290 m_scene.RegionInfo.RegionSizeY/2 - 0.5f );
291
292 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR)); 405 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR));
293 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif 406 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif
294 waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); 407 waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f));
295 renderer.Scene.addMaterial("WaterColor", waterColorMaterial); 408 renderer.Scene.addMaterial("WaterColor", waterColorMaterial);
296 renderer.SetObjectMaterial("Water", "WaterColor"); 409
410 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / 256; x++)
411 {
412 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / 256; y++)
413 {
414 renderer.AddPlane("Water-" + x + "-" + y, 256);
415 renderer.Scene.sceneobject("Water-" + x + "-" + y).setPos(256 * x, waterHeight, 256 * y);
416 renderer.SetObjectMaterial("Water-" + x + "-" + y, "WaterColor");
417 }
418 }
297 } 419 }
298 420
299 // Add a terrain to the renderer. 421 // Add a terrain to the renderer.
@@ -303,53 +425,53 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
303 { 425 {
304 ITerrainChannel terrain = m_scene.Heightmap; 426 ITerrainChannel terrain = m_scene.Heightmap;
305 427
428 float regionsx = m_scene.RegionInfo.RegionSizeX;
429 float regionsy = m_scene.RegionInfo.RegionSizeY;
430
306 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding 431 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
307 float diff = (float)m_scene.RegionInfo.RegionSizeX / 256f; 432 float diff = regionsx / 256f;
433
434 int npointsx =(int)(regionsx / diff);
435 int npointsy =(int)(regionsy / diff);
308 436
309 warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2); 437 float invsx = 1.0f / regionsx;
438 float invsy = 1.0f / (float)m_scene.RegionInfo.RegionSizeY;
310 439
311 // Create all the vertices for the terrain 440 // Create all the vertices for the terrain
312 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff) 441 warp_Object obj = new warp_Object();
442 for (float y = 0; y < regionsy; y += diff)
313 { 443 {
314 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff) 444 for (float x = 0; x < regionsx; x += diff)
315 { 445 {
316 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]); 446 warp_Vector pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]);
317 obj.addVertex(new warp_Vertex(pos, 447 obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy));
318 x / (float)m_scene.RegionInfo.RegionSizeX,
319 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY) );
320 } 448 }
321 } 449 }
322 450
323 // Now that we have all the vertices, make another pass and create 451 // Now that we have all the vertices, make another pass and
324 // the normals for each of the surface triangles and 452 // create the list of triangle indices.
325 // create the list of triangle indices. 453 float invdiff = 1.0f / diff;
326 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff) 454 int limx = npointsx - 1;
455 int limy = npointsy - 1;
456 for (float y = 0; y < regionsy; y += diff)
327 { 457 {
328 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff) 458 for (float x = 0; x < regionsx; x += diff)
329 { 459 {
330 float newX = x / diff; 460 float newX = x * invdiff;
331 float newY = y / diff; 461 float newY = y * invdiff;
332 if (newX < 255 && newY < 255) 462 if (newX < limx && newY < limy)
333 { 463 {
334 int v = (int)newY * 256 + (int)newX; 464 int v = (int)newY * npointsx + (int)newX;
335
336 // Normal for a triangle made up of three adjacent vertices
337 Vector3 v1 = new Vector3(newX, newY, (float)terrain[(int)x, (int)y]);
338 Vector3 v2 = new Vector3(newX + 1, newY, (float)terrain[(int)(x + 1), (int)y]);
339 Vector3 v3 = new Vector3(newX, newY + 1, (float)terrain[(int)x, ((int)(y + 1))]);
340 warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
341 norm = norm.reverse();
342 obj.vertex(v).n = norm;
343 465
344 // Make two triangles for each of the squares in the grid of vertices 466 // Make two triangles for each of the squares in the grid of vertices
345 obj.addTriangle( 467 obj.addTriangle(
346 v, 468 v,
347 v + 1, 469 v + 1,
348 v + 256); 470 v + npointsx);
349 471
350 obj.addTriangle( 472 obj.addTriangle(
351 v + 256 + 1, 473 v + npointsx + 1,
352 v + 256, 474 v + npointsx,
353 v + 1); 475 v + 1);
354 } 476 }
355 } 477 }
@@ -382,18 +504,15 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
382 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); 504 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
383 505
384 warp_Texture texture; 506 warp_Texture texture;
385 using ( 507 using (Bitmap image = TerrainSplat.Splat(
386 Bitmap image 508 terrain, textureIDs, startHeights, heightRanges,
387 = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges,
388 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) 509 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
389 {
390 texture = new warp_Texture(image); 510 texture = new warp_Texture(image);
391 }
392 511
393 warp_Material material = new warp_Material(texture); 512 warp_Material material = new warp_Material(texture);
394 material.setReflectivity(50); 513 material.setReflectivity(50);
395 renderer.Scene.addMaterial("TerrainColor", material); 514 renderer.Scene.addMaterial("TerrainColor", material);
396 renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif 515 renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif
397 renderer.SetObjectMaterial("Terrain", "TerrainColor"); 516 renderer.SetObjectMaterial("Terrain", "TerrainColor");
398 } 517 }
399 518
@@ -414,11 +533,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
414 private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, 533 private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim,
415 bool useTextures) 534 bool useTextures)
416 { 535 {
417 const float MIN_SIZE = 2f; 536 const float MIN_SIZE_SQUARE = 4f;
418 537
419 if ((PCode)prim.Shape.PCode != PCode.Prim) 538 if ((PCode)prim.Shape.PCode != PCode.Prim)
420 return; 539 return;
421 if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE) 540 float primScaleLenSquared = prim.Scale.LengthSquared();
541
542 if (primScaleLenSquared < MIN_SIZE_SQUARE)
422 return; 543 return;
423 544
424 FacetedMesh renderMesh = null; 545 FacetedMesh renderMesh = null;
@@ -454,11 +575,11 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
454 sculpt.Dispose(); 575 sculpt.Dispose();
455 } 576 }
456 } 577 }
457 catch (Exception e) 578 catch /*(Exception e)*/
458 { 579 {
459 Vector3 objectPos = prim.ParentGroup.RootPart.AbsolutePosition; 580 Vector3 objectPos = prim.ParentGroup.RootPart.AbsolutePosition;
460//// TODO - print out owner of SceneObjectPart prim. 581//// TODO - print out owner of SceneObjectPart prim.
461 m_log.Warn(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0} @ {1},{2},{3} - {4}.", 582 m_log.Error(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0} @ {1},{2},{3} - {4}.",
462 omvPrim.Sculpt.SculptTexture, objectPos.X, objectPos.Y, objectPos.Z, 583 omvPrim.Sculpt.SculptTexture, objectPos.X, objectPos.Y, objectPos.Z,
463 prim.ParentGroup.RootPart.Name)); 584 prim.ParentGroup.RootPart.Name));
464 } 585 }
@@ -477,20 +598,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
477 if (renderMesh == null) 598 if (renderMesh == null)
478 return; 599 return;
479 600
480 warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
481 warp_Quaternion primRot = ConvertQuaternion(prim.RotationOffset);
482
483 warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);
484
485 if (prim.ParentID != 0)
486 {
487 SceneObjectGroup group = m_scene.SceneGraph.GetGroupByPrim(prim.LocalId);
488 if (group != null)
489 m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootPart.RotationOffset)));
490 }
491
492 warp_Vector primScale = ConvertVector(prim.Scale);
493
494 string primID = prim.UUID.ToString(); 601 string primID = prim.UUID.ToString();
495 602
496 // Create the prim faces 603 // Create the prim faces
@@ -498,27 +605,18 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
498 for (int i = 0; i < renderMesh.Faces.Count; i++) 605 for (int i = 0; i < renderMesh.Faces.Count; i++)
499 { 606 {
500 Face face = renderMesh.Faces[i]; 607 Face face = renderMesh.Faces[i];
501 string meshName = primID + "-Face-" + i.ToString(); 608 string meshName = primID + i.ToString();
502 609
503 // Avoid adding duplicate meshes to the scene 610 // Avoid adding duplicate meshes to the scene
504 if (renderer.Scene.objectData.ContainsKey(meshName)) 611 if (renderer.Scene.objectData.ContainsKey(meshName))
505 {
506 continue; 612 continue;
507 }
508
509 warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count / 3);
510 613
614 warp_Object faceObj = new warp_Object();
511 for (int j = 0; j < face.Vertices.Count; j++) 615 for (int j = 0; j < face.Vertices.Count; j++)
512 { 616 {
513 Vertex v = face.Vertices[j]; 617 Vertex v = face.Vertices[j];
514
515 warp_Vector pos = ConvertVector(v.Position); 618 warp_Vector pos = ConvertVector(v.Position);
516 warp_Vector norm = ConvertVector(v.Normal); 619 warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y);
517
518 if (prim.Shape.SculptTexture == UUID.Zero)
519 norm = norm.reverse();
520 warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y);
521
522 faceObj.addVertex(vert); 620 faceObj.addVertex(vert);
523 } 621 }
524 622
@@ -533,17 +631,19 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
533 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); 631 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
534 Color4 faceColor = GetFaceColor(teFace); 632 Color4 faceColor = GetFaceColor(teFace);
535 string materialName = String.Empty; 633 string materialName = String.Empty;
536 if (m_texturePrims && prim.Scale.LengthSquared() > m_texturePrimSize*m_texturePrimSize) 634 if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize)
537 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); 635 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
538 else 636 else
539 materialName = GetOrCreateMaterial(renderer, faceColor); 637 materialName = GetOrCreateMaterial(renderer, faceColor);
540 638
639 warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
640 warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation());
641 warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);
541 faceObj.transform(m); 642 faceObj.transform(m);
542 faceObj.setPos(primPos); 643 faceObj.setPos(primPos);
543 faceObj.scaleSelf(primScale.x, primScale.y, primScale.z); 644 faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y);
544 645
545 renderer.Scene.addObject(meshName, faceObj); 646 renderer.Scene.addObject(meshName, faceObj);
546
547 renderer.SetObjectMaterial(meshName, materialName); 647 renderer.SetObjectMaterial(meshName, materialName);
548 } 648 }
549 } 649 }
@@ -576,7 +676,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
576 676
577 if (!fetched) 677 if (!fetched)
578 { 678 {
579 // Fetch the texture, decode and get the average color, 679 // Fetch the texture, decode and get the average color,
580 // then save it to a temporary metadata asset 680 // then save it to a temporary metadata asset
581 AssetBase textureAsset = m_scene.AssetService.Get(face.TextureID.ToString()); 681 AssetBase textureAsset = m_scene.AssetService.Get(face.TextureID.ToString());
582 if (textureAsset != null) 682 if (textureAsset != null)
@@ -659,9 +759,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
659 using (Bitmap img = (Bitmap)imgDecoder.DecodeToImage(asset)) 759 using (Bitmap img = (Bitmap)imgDecoder.DecodeToImage(asset))
660 ret = new warp_Texture(img); 760 ret = new warp_Texture(img);
661 } 761 }
662 catch (Exception e) 762 catch /*(Exception e)*/
663 { 763 {
664 m_log.Warn(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0}, exception ", id), e); 764 m_log.Debug(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0}, exception ", id));
665 } 765 }
666 } 766 }
667 767
@@ -671,7 +771,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
671 #endregion Rendering Methods 771 #endregion Rendering Methods
672 772
673 #region Static Helpers 773 #region Static Helpers
674
675 // Note: axis change. 774 // Note: axis change.
676 private static warp_Vector ConvertVector(float x, float y, float z) 775 private static warp_Vector ConvertVector(float x, float y, float z)
677 { 776 {
@@ -725,10 +824,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
725 { 824 {
726 width = bitmap.Width; 825 width = bitmap.Width;
727 height = bitmap.Height; 826 height = bitmap.Height;
728 827
729 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); 828 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
730 pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; 829 pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
731 830
732 // Sum up the individual channels 831 // Sum up the individual channels
733 unsafe 832 unsafe
734 { 833 {
@@ -737,7 +836,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
737 for (int y = 0; y < height; y++) 836 for (int y = 0; y < height; y++)
738 { 837 {
739 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 838 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
740 839
741 for (int x = 0; x < width; x++) 840 for (int x = 0; x < width; x++)
742 { 841 {
743 b += row[x * pixelBytes + 0]; 842 b += row[x * pixelBytes + 0];
@@ -752,7 +851,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
752 for (int y = 0; y < height; y++) 851 for (int y = 0; y < height; y++)
753 { 852 {
754 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 853 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
755 854
756 for (int x = 0; x < width; x++) 855 for (int x = 0; x < width; x++)
757 { 856 {
758 b += row[x * pixelBytes + 0]; 857 b += row[x * pixelBytes + 0];
@@ -780,7 +879,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
780 } 879 }
781 catch (Exception ex) 880 catch (Exception ex)
782 { 881 {
783 m_log.WarnFormat( 882 m_log.DebugFormat(
784 "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", 883 "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}",
785 textureID, j2kData.Length, ex.Message); 884 textureID, j2kData.Length, ex.Message);
786 885
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
index 6af4050..a2b44df 100644
--- a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
50 private float m_avgDirection = 0.0f; // Average direction of the wind in degrees 50 private float m_avgDirection = 0.0f; // Average direction of the wind in degrees
51 private float m_varStrength = 5.0f; // Max Strength Variance 51 private float m_varStrength = 5.0f; // Max Strength Variance
52 private float m_varDirection = 30.0f;// Max Direction Variance 52 private float m_varDirection = 30.0f;// Max Direction Variance
53 private float m_rateChange = 1.0f; // 53 private float m_rateChange = 1.0f; //
54 54
55 private Vector2 m_curPredominateWind = new Vector2(); 55 private Vector2 m_curPredominateWind = new Vector2();
56 56
@@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
70 70
71 public void Initialise() 71 public void Initialise()
72 { 72 {
73 73
74 } 74 }
75 75
76 #endregion 76 #endregion
@@ -103,7 +103,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
103 } 103 }
104 } 104 }
105 105
106 public void WindUpdate(uint frame) 106 public bool WindUpdate(uint frame)
107 { 107 {
108 double avgAng = m_avgDirection * (Math.PI/180.0f); 108 double avgAng = m_avgDirection * (Math.PI/180.0f);
109 double varDir = m_varDirection * (Math.PI/180.0f); 109 double varDir = m_varDirection * (Math.PI/180.0f);
@@ -111,7 +111,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
111 // Prevailing wind algorithm 111 // Prevailing wind algorithm
112 // Inspired by Kanker Greenacre 112 // Inspired by Kanker Greenacre
113 113
114 // TODO: 114 // TODO:
115 // * This should probably be based on in-world time. 115 // * This should probably be based on in-world time.
116 // * should probably move all these local variables to class members and constants 116 // * should probably move all these local variables to class members and constants
117 double time = DateTime.Now.TimeOfDay.Seconds / 86400.0f; 117 double time = DateTime.Now.TimeOfDay.Seconds / 86400.0f;
@@ -125,10 +125,8 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
125 offset = Math.Sin(theta) * Math.Sin(theta*4) + (Math.Sin(theta*13) / 3); 125 offset = Math.Sin(theta) * Math.Sin(theta*4) + (Math.Sin(theta*13) / 3);
126 double windSpeed = m_avgStrength + (m_varStrength * offset); 126 double windSpeed = m_avgStrength + (m_varStrength * offset);
127 127
128 if (windSpeed<0) 128 if (windSpeed < 0)
129 windSpeed=0; 129 windSpeed = -windSpeed;
130
131
132 130
133 m_curPredominateWind.X = (float)Math.Cos(windDir); 131 m_curPredominateWind.X = (float)Math.Cos(windDir);
134 m_curPredominateWind.Y = (float)Math.Sin(windDir); 132 m_curPredominateWind.Y = (float)Math.Sin(windDir);
@@ -144,6 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
144 m_windSpeeds[y * 16 + x] = m_curPredominateWind; 142 m_windSpeeds[y * 16 + x] = m_curPredominateWind;
145 } 143 }
146 } 144 }
145 return true;
147 } 146 }
148 147
149 public Vector3 WindSpeed(float fX, float fY, float fZ) 148 public Vector3 WindSpeed(float fX, float fY, float fZ)
@@ -158,9 +157,9 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
158 157
159 public string Description 158 public string Description
160 { 159 {
161 get 160 get
162 { 161 {
163 return "Provides a predominate wind direction that can change within configured variances for direction and speed."; 162 return "Provides a predominate wind direction that can change within configured variances for direction and speed.";
164 } 163 }
165 } 164 }
166 165
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
index fcb0c10..d2ff7b3 100644
--- a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
@@ -82,22 +82,23 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
82 } 82 }
83 } 83 }
84 84
85 public void WindUpdate(uint frame) 85 public bool WindUpdate(uint frame)
86 { 86 {
87 //Make sure our object is valid (we haven't been disposed of yet) 87 //Make sure our object is valid (we haven't been disposed of yet)
88 if (m_windSpeeds != null) 88 if (m_windSpeeds == null)
89 return false;
90
91 for (int y = 0; y < 16; y++)
89 { 92 {
90 for (int y = 0; y < 16; y++) 93 for (int x = 0; x < 16; x++)
91 { 94 {
92 for (int x = 0; x < 16; x++) 95 m_windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1
93 { 96 m_windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1
94 m_windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 97 m_windSpeeds[y * 16 + x].X *= m_strength;
95 m_windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 98 m_windSpeeds[y * 16 + x].Y *= m_strength;
96 m_windSpeeds[y * 16 + x].X *= m_strength;
97 m_windSpeeds[y * 16 + x].Y *= m_strength;
98 }
99 } 99 }
100 } 100 }
101 return true;
101 } 102 }
102 103
103 public Vector3 WindSpeed(float fX, float fY, float fZ) 104 public Vector3 WindSpeed(float fX, float fY, float fZ)
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index 35014f5..96ba003 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -46,11 +46,13 @@ namespace OpenSim.Region.CoreModules
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private uint m_frame = 0; 48 private uint m_frame = 0;
49 private uint m_frameLastUpdateClientArray = 0; 49 private int m_dataVersion = 0;
50// private int m_regionID = 0;
50 private int m_frameUpdateRate = 150; 51 private int m_frameUpdateRate = 150;
51 //private Random m_rndnums = new Random(Environment.TickCount); 52 //private Random m_rndnums = new Random(Environment.TickCount);
52 private Scene m_scene = null; 53 private Scene m_scene = null;
53 private bool m_ready = false; 54 private bool m_ready = false;
55 private bool m_inUpdate = false;
54 56
55 private bool m_enabled = false; 57 private bool m_enabled = false;
56 private IConfig m_windConfig; 58 private IConfig m_windConfig;
@@ -96,11 +98,10 @@ namespace OpenSim.Region.CoreModules
96 98
97 m_scene = scene; 99 m_scene = scene;
98 m_frame = 0; 100 m_frame = 0;
99
100 // Register all the Wind Model Plug-ins 101 // Register all the Wind Model Plug-ins
101 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule", false)) 102 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule", false))
102 { 103 {
103 m_log.InfoFormat("[WIND] Found Plugin: {0}", windPlugin.Name); 104 m_log.DebugFormat("[WIND] Found Plugin: {0}", windPlugin.Name);
104 m_availableWindPlugins.Add(windPlugin.Name, windPlugin); 105 m_availableWindPlugins.Add(windPlugin.Name, windPlugin);
105 } 106 }
106 107
@@ -109,7 +110,7 @@ namespace OpenSim.Region.CoreModules
109 { 110 {
110 m_activeWindPlugin = m_availableWindPlugins[m_dWindPluginName]; 111 m_activeWindPlugin = m_availableWindPlugins[m_dWindPluginName];
111 112
112 m_log.InfoFormat("[WIND] {0} plugin found, initializing.", m_dWindPluginName); 113 m_log.DebugFormat("[WIND] {0} plugin found, initializing.", m_dWindPluginName);
113 114
114 if (m_windConfig != null) 115 if (m_windConfig != null)
115 { 116 {
@@ -118,7 +119,6 @@ namespace OpenSim.Region.CoreModules
118 } 119 }
119 } 120 }
120 121
121
122 // if the plug-in wasn't found, default to no wind. 122 // if the plug-in wasn't found, default to no wind.
123 if (m_activeWindPlugin == null) 123 if (m_activeWindPlugin == null)
124 { 124 {
@@ -154,14 +154,14 @@ namespace OpenSim.Region.CoreModules
154 154
155 // Register event handlers for when Avatars enter the region, and frame ticks 155 // Register event handlers for when Avatars enter the region, and frame ticks
156 m_scene.EventManager.OnFrame += WindUpdate; 156 m_scene.EventManager.OnFrame += WindUpdate;
157 m_scene.EventManager.OnMakeRootAgent += OnAgentEnteredRegion;
158 157
159 // Register the wind module 158 // Register the wind module
160 m_scene.RegisterModuleInterface<IWindModule>(this); 159 m_scene.RegisterModuleInterface<IWindModule>(this);
161 160
162 // Generate initial wind values 161 // Generate initial wind values
163 GenWindPos(); 162 GenWind();
164 163 // hopefully this will not be the same for all regions on same instance
164 m_dataVersion = (int)m_scene.AllocateLocalId();
165 // Mark Module Ready for duty 165 // Mark Module Ready for duty
166 m_ready = true; 166 m_ready = true;
167 } 167 }
@@ -184,7 +184,7 @@ namespace OpenSim.Region.CoreModules
184 184
185 // Remove our hooks 185 // Remove our hooks
186 m_scene.EventManager.OnFrame -= WindUpdate; 186 m_scene.EventManager.OnFrame -= WindUpdate;
187 m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion; 187// m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion;
188 188
189 } 189 }
190 190
@@ -351,7 +351,7 @@ namespace OpenSim.Region.CoreModules
351 #region IWindModule Methods 351 #region IWindModule Methods
352 352
353 /// <summary> 353 /// <summary>
354 /// Retrieve the wind speed at the given region coordinate. This 354 /// Retrieve the wind speed at the given region coordinate. This
355 /// implimentation ignores Z. 355 /// implimentation ignores Z.
356 /// </summary> 356 /// </summary>
357 /// <param name="x">0...255</param> 357 /// <param name="x">0...255</param>
@@ -396,7 +396,7 @@ namespace OpenSim.Region.CoreModules
396 396
397 public string WindActiveModelPluginName 397 public string WindActiveModelPluginName
398 { 398 {
399 get 399 get
400 { 400 {
401 if (m_activeWindPlugin != null) 401 if (m_activeWindPlugin != null)
402 { 402 {
@@ -416,67 +416,43 @@ namespace OpenSim.Region.CoreModules
416 /// </summary> 416 /// </summary>
417 public void WindUpdate() 417 public void WindUpdate()
418 { 418 {
419 if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready) 419 if ((!m_ready || m_inUpdate || (m_frame++ % m_frameUpdateRate) != 0))
420 {
421 return; 420 return;
422 }
423
424 GenWindPos();
425
426 SendWindAllClients();
427 }
428 421
429 public void OnAgentEnteredRegion(ScenePresence avatar) 422 m_inUpdate = true;
430 { 423 Util.FireAndForget(delegate
431 if (m_ready)
432 { 424 {
433 if (m_activeWindPlugin != null) 425 try
434 { 426 {
435 // Ask wind plugin to generate a LL wind array to be cached locally 427 GenWind();
436 // Try not to update this too often, as it may involve array copies 428 m_scene.ForEachClient(delegate(IClientAPI client)
437 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
438 { 429 {
439 windSpeeds = m_activeWindPlugin.WindLLClientArray(); 430 client.SendWindData(m_dataVersion, windSpeeds);
440 m_frameLastUpdateClientArray = m_frame; 431 });
441 }
442 }
443
444 avatar.ControllingClient.SendWindData(windSpeeds);
445 }
446 }
447 432
448 private void SendWindAllClients() 433 }
449 { 434 finally
450 if (m_ready)
451 {
452 if (m_scene.GetRootAgentCount() > 0)
453 { 435 {
454 // Ask wind plugin to generate a LL wind array to be cached locally 436 m_inUpdate = false;
455 // Try not to update this too often, as it may involve array copies
456 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
457 {
458 windSpeeds = m_activeWindPlugin.WindLLClientArray();
459 m_frameLastUpdateClientArray = m_frame;
460 }
461
462 m_scene.ForEachRootClient(delegate(IClientAPI client)
463 {
464 client.SendWindData(windSpeeds);
465 });
466 } 437 }
467 } 438 },
439 null, "WindModuleUpdate");
468 } 440 }
441
469 /// <summary> 442 /// <summary>
470 /// Calculate the sun's orbital position and its velocity. 443 /// Calculate new wind
444 /// returns false if no change
471 /// </summary> 445 /// </summary>
472 446
473 private void GenWindPos() 447 private bool GenWind()
474 { 448 {
475 if (m_activeWindPlugin != null) 449 if (m_activeWindPlugin != null && m_activeWindPlugin.WindUpdate(m_frame))
476 { 450 {
477 // Tell Wind Plugin to update it's wind data 451 windSpeeds = m_activeWindPlugin.WindLLClientArray();
478 m_activeWindPlugin.WindUpdate(m_frame); 452 m_dataVersion++;
453 return true;
479 } 454 }
455 return false;
480 } 456 }
481 } 457 }
482} 458}
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index d862f18..5876df3 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -128,109 +128,116 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 m_Clients.Add(remoteClient.AgentId); 128 m_Clients.Add(remoteClient.AgentId);
129 } 129 }
130 130
131 try 131 OnMapNameRequest(remoteClient, mapName, flags);
132 {
133 OnMapNameRequest(remoteClient, mapName, flags);
134 }
135 finally
136 {
137 lock (m_Clients)
138 m_Clients.Remove(remoteClient.AgentId);
139 }
140 } 132 }
141 133
142 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 134 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
143 { 135 {
144 List<MapBlockData> blocks = new List<MapBlockData>(); 136 Util.FireAndForget(x =>
145 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
146 { 137 {
147 // final block, closing the search result 138 try
148 AddFinalBlock(blocks); 139 {
140 List<MapBlockData> blocks = new List<MapBlockData>();
141 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
142 {
143 // final block, closing the search result
144 AddFinalBlock(blocks,mapName);
149 145
150 // flags are agent flags sent from the viewer. 146 // flags are agent flags sent from the viewer.
151 // they have different values depending on different viewers, apparently 147 // they have different values depending on different viewers, apparently
152 remoteClient.SendMapBlock(blocks, flags); 148 remoteClient.SendMapBlock(blocks, flags);
153 remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); 149 remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
154 return; 150 return;
155 } 151 }
156 152
153 //m_log.DebugFormat("MAP NAME=({0})", mapName);
157 154
158 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); 155 // Hack to get around the fact that ll V3 now drops the port from the
159 156 // map name. See https://jira.secondlife.com/browse/VWR-28570
160 string mapNameOrig = mapName; 157 //
161 if (regionInfos.Count == 0) 158 // Caller, use this magic form instead:
162 { 159 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128
163 // Hack to get around the fact that ll V3 now drops the port from the 160 // or url encode if possible.
164 // map name. See https://jira.secondlife.com/browse/VWR-28570 161 // the hacks we do with this viewer...
165 // 162 //
166 // Caller, use this magic form instead: 163 bool needOriginalName = false;
167 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128 164 string mapNameOrig = mapName;
168 // or url encode if possible. 165 if (mapName.Contains("|"))
169 // the hacks we do with this viewer...
170 //
171 if (mapName.Contains("|"))
172 mapName = mapName.Replace('|', ':');
173 if (mapName.Contains("+"))
174 mapName = mapName.Replace('+', ' ');
175 if (mapName.Contains("!"))
176 mapName = mapName.Replace('!', '/');
177
178 if (mapName != mapNameOrig)
179 regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
180 }
181
182 m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags);
183
184 if (regionInfos.Count > 0)
185 {
186 foreach (GridRegion info in regionInfos)
187 {
188 if ((flags & 2) == 2) // V2 sends this
189 { 166 {
190 List<MapBlockData> datas = WorldMap.Map2BlockFromGridRegion(info, flags); 167 mapName = mapName.Replace('|', ':');
191 // ugh! V2-3 is very sensitive about the result being 168 needOriginalName = true;
192 // exactly the same as the requested name
193 if (regionInfos.Count == 1 && (mapName != mapNameOrig))
194 datas.ForEach(d => d.Name = mapNameOrig);
195
196 blocks.AddRange(datas);
197 } 169 }
198 else 170 if (mapName.Contains("+"))
199 { 171 {
200 MapBlockData data = WorldMap.MapBlockFromGridRegion(info, flags); 172 mapName = mapName.Replace('+', ' ');
201 blocks.Add(data); 173 needOriginalName = true;
202 } 174 }
203 } 175 if (mapName.Contains("!"))
204 } 176 {
177 mapName = mapName.Replace('!', '/');
178 needOriginalName = true;
179 }
180 if (mapName.Contains("."))
181 needOriginalName = true;
205 182
206 // final block, closing the search result 183 // try to fetch from GridServer
207 AddFinalBlock(blocks); 184 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
185 // if (regionInfos.Count == 0)
186 // remoteClient.SendAlertMessage("Hyperlink could not be established.");
208 187
209 // flags are agent flags sent from the viewer. 188 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
210 // they have different values depending on different viewers, apparently
211 remoteClient.SendMapBlock(blocks, flags);
212 189
213 // send extra user messages for V3 190 MapBlockData data;
214 // because the UI is very confusing 191 if (regionInfos != null && regionInfos.Count > 0)
215 // while we don't fix the hard-coded urls 192 {
216 if (flags == 2) 193 foreach (GridRegion info in regionInfos)
217 { 194 {
218 if (regionInfos.Count == 0) 195 data = new MapBlockData();
219 remoteClient.SendAlertMessage("No regions found with that name."); 196 data.Agents = 0;
220 // this seems unnecessary because found regions will show up in the search results 197 data.Access = info.Access;
221 //else if (regionInfos.Count == 1) 198 MapBlockData block = new MapBlockData();
222 // remoteClient.SendAlertMessage("Region found!"); 199 WorldMap.MapBlockFromGridRegion(block, info, flags);
223 } 200
201 if (flags == 2 && regionInfos.Count == 1 && needOriginalName)
202 block.Name = mapNameOrig;
203 blocks.Add(block);
204 }
205 }
206
207 // final block, closing the search result
208 AddFinalBlock(blocks,mapNameOrig);
209
210 // flags are agent flags sent from the viewer.
211 // they have different values depending on different viewers, apparently
212 remoteClient.SendMapBlock(blocks, flags);
213
214 // send extra user messages for V3
215 // because the UI is very confusing
216 // while we don't fix the hard-coded urls
217 if (flags == 2)
218 {
219 if (regionInfos == null || regionInfos.Count == 0)
220 remoteClient.SendAgentAlertMessage("No regions found with that name.", true);
221 // else if (regionInfos.Count == 1)
222 // remoteClient.SendAgentAlertMessage("Region found!", false);
223 }
224 }
225 finally
226 {
227 lock (m_Clients)
228 m_Clients.Remove(remoteClient.AgentId);
229 }
230 });
224 } 231 }
225 232
226 private void AddFinalBlock(List<MapBlockData> blocks) 233 private void AddFinalBlock(List<MapBlockData> blocks,string name)
227 { 234 {
228 // final block, closing the search result 235 // final block, closing the search result
229 MapBlockData data = new MapBlockData(); 236 MapBlockData data = new MapBlockData();
230 data.Agents = 0; 237 data.Agents = 0;
231 data.Access = (byte)SimAccess.NonExistent; 238 data.Access = (byte)SimAccess.NonExistent;
232 data.MapImageId = UUID.Zero; 239 data.MapImageId = UUID.Zero;
233 data.Name = ""; 240 data.Name = name;
234 data.RegionFlags = 0; 241 data.RegionFlags = 0;
235 data.WaterHeight = 0; // not used 242 data.WaterHeight = 0; // not used
236 data.X = 0; 243 data.X = 0;
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index db1187e..94072a5 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -66,32 +66,34 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
66 66
67 private static readonly string DEFAULT_WORLD_MAP_EXPORT_PATH = "exportmap.jpg"; 67 private static readonly string DEFAULT_WORLD_MAP_EXPORT_PATH = "exportmap.jpg";
68 private static readonly UUID STOP_UUID = UUID.Random(); 68 private static readonly UUID STOP_UUID = UUID.Random();
69 private static readonly string m_mapLayerPath = "0001/"; 69
70 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
71
72 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
73 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
70 74
71 private IMapImageGenerator m_mapImageGenerator; 75 private IMapImageGenerator m_mapImageGenerator;
72 private IMapImageUploadModule m_mapImageServiceModule; 76 private IMapImageUploadModule m_mapImageServiceModule;
73 77
74 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
75
76 protected Scene m_scene; 78 protected Scene m_scene;
77 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 79 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
78 private int cachedTime = 0;
79 private int blacklistTimeout = 10*60*1000; // 10 minutes
80 private byte[] myMapImageJPEG; 80 private byte[] myMapImageJPEG;
81 protected volatile bool m_Enabled = false; 81 protected volatile bool m_Enabled = false;
82 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>(); 82 private ExpiringCache<string, int> m_blacklistedurls = new ExpiringCache<string, int>();
83 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 83 private ExpiringCache<ulong, int> m_blacklistedregions = new ExpiringCache<ulong, int>();
84 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 84 private ExpiringCache<ulong, string> m_cachedRegionMapItemsAddress = new ExpiringCache<ulong, string>();
85 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 85 private ExpiringCache<ulong, OSDMap> m_cachedRegionMapItemsResponses =
86 new ExpiringCache<ulong, OSDMap>();
86 private List<UUID> m_rootAgents = new List<UUID>(); 87 private List<UUID> m_rootAgents = new List<UUID>();
87 private volatile bool threadrunning = false; 88 private volatile bool threadrunning = false;
88 89 // expire time for the blacklists in seconds
89 private IServiceThrottleModule m_ServiceThrottle; 90 private double expireBlackListTime = 600.0; // 10 minutes
90 91 // expire mapItems responses time in seconds. Throttles requests to regions that do answer
92 private const double expireResponsesTime = 120.0; // 2 minutes ?
91 //private int CacheRegionsDistance = 256; 93 //private int CacheRegionsDistance = 256;
92 94
93 #region INonSharedRegionModule Members 95 #region INonSharedRegionModule Members
94 public virtual void Initialise (IConfigSource config) 96 public virtual void Initialise(IConfigSource config)
95 { 97 {
96 string[] configSections = new string[] { "Map", "Startup" }; 98 string[] configSections = new string[] { "Map", "Startup" };
97 99
@@ -99,8 +101,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
99 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") 101 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
100 m_Enabled = true; 102 m_Enabled = true;
101 103
102 blacklistTimeout 104 expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
103 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
104 } 105 }
105 106
106 public virtual void AddRegion(Scene scene) 107 public virtual void AddRegion(Scene scene)
@@ -128,7 +129,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 } 129 }
129 } 130 }
130 131
131 public virtual void RemoveRegion (Scene scene) 132 public virtual void RemoveRegion(Scene scene)
132 { 133 {
133 if (!m_Enabled) 134 if (!m_Enabled)
134 return; 135 return;
@@ -141,13 +142,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
141 } 142 }
142 } 143 }
143 144
144 public virtual void RegionLoaded (Scene scene) 145 public virtual void RegionLoaded(Scene scene)
145 { 146 {
146 if (!m_Enabled) 147 if (!m_Enabled)
147 return; 148 return;
148 149
149 m_ServiceThrottle = scene.RequestModuleInterface<IServiceThrottleModule>();
150
151 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>(); 150 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>();
152 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>(); 151 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>();
153 } 152 }
@@ -177,16 +176,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
177 regionimage = regionimage.Replace("-", ""); 176 regionimage = regionimage.Replace("-", "");
178 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage); 177 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage);
179 178
179/*
180 MainServer.Instance.AddHTTPHandler(regionimage, 180 MainServer.Instance.AddHTTPHandler(regionimage,
181 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions() 181 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
182 { 182 {
183 AllowXForwardedFor = false, 183 AllowXForwardedFor = false,
184 ForgetTimeSpan = TimeSpan.FromMinutes(2), 184 ForgetTimeSpan = TimeSpan.FromMinutes(2),
185 MaxRequestsInTimeframe = 4, 185 MaxRequestsInTimeframe = 4,
186 ReportingName = "MAPDOSPROTECTOR", 186 ReportingName = "MAPDOSPROTECTOR",
187 RequestTimeSpan = TimeSpan.FromSeconds(10), 187 RequestTimeSpan = TimeSpan.FromSeconds(10),
188 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod 188 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
189 }).Process); 189 }).Process);
190*/
191
192 MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage);
190 MainServer.Instance.AddLLSDHandler( 193 MainServer.Instance.AddLLSDHandler(
191 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 194 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
192 195
@@ -197,13 +200,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
197 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; 200 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
198 m_scene.EventManager.OnRegionUp += OnRegionUp; 201 m_scene.EventManager.OnRegionUp += OnRegionUp;
199 202
200// StartThread(new object()); 203 StartThread(new object());
201 } 204 }
202 205
203 // this has to be called with a lock on m_scene 206 // this has to be called with a lock on m_scene
204 protected virtual void RemoveHandlers() 207 protected virtual void RemoveHandlers()
205 { 208 {
206// StopThread(); 209 StopThread();
207 210
208 m_scene.EventManager.OnRegionUp -= OnRegionUp; 211 m_scene.EventManager.OnRegionUp -= OnRegionUp;
209 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent; 212 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent;
@@ -212,6 +215,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
212 m_scene.EventManager.OnNewClient -= OnNewClient; 215 m_scene.EventManager.OnNewClient -= OnNewClient;
213 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 216 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
214 217
218 m_scene.UnregisterModuleInterface<IWorldMapModule>(this);
219
215 string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); 220 string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString();
216 regionimage = regionimage.Replace("-", ""); 221 regionimage = regionimage.Replace("-", "");
217 MainServer.Instance.RemoveLLSDHandler("/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), 222 MainServer.Instance.RemoveLLSDHandler("/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(),
@@ -222,12 +227,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
222 public void OnRegisterCaps(UUID agentID, Caps caps) 227 public void OnRegisterCaps(UUID agentID, Caps caps)
223 { 228 {
224 //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 229 //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
225 string capsBase = "/CAPS/" + caps.CapsObjectPath; 230 string capspath = "/CAPS/" + UUID.Random();
226 caps.RegisterHandler( 231 caps.RegisterHandler(
227 "MapLayer", 232 "MapLayer",
228 new RestStreamHandler( 233 new RestStreamHandler(
229 "POST", 234 "POST",
230 capsBase + m_mapLayerPath, 235 capspath,
231 (request, path, param, httpRequest, httpResponse) 236 (request, path, param, httpRequest, httpResponse)
232 => MapLayerRequest(request, path, param, agentID, caps), 237 => MapLayerRequest(request, path, param, agentID, caps),
233 "MapLayer", 238 "MapLayer",
@@ -246,6 +251,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
246 public string MapLayerRequest(string request, string path, string param, 251 public string MapLayerRequest(string request, string path, string param,
247 UUID agentID, Caps caps) 252 UUID agentID, Caps caps)
248 { 253 {
254 // not sure about this....
255
249 //try 256 //try
250 // 257 //
251 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", 258 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
@@ -261,54 +268,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
261 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is 268 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
262 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. 269 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
263 270
264 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 271 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
265 { 272 //{
266 ScenePresence avatarPresence = null; 273 // ScenePresence avatarPresence = null;
267 274
268 m_scene.TryGetScenePresence(agentID, out avatarPresence); 275 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
269 276
270 if (avatarPresence != null) 277 // if (avatarPresence != null)
271 { 278 // {
272 bool lookup = false; 279 // bool lookup = false;
273 280
274 lock (cachedMapBlocks) 281 // lock (cachedMapBlocks)
275 { 282 // {
276 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 283 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
277 { 284 // {
278 List<MapBlockData> mapBlocks; 285 // List<MapBlockData> mapBlocks;
279 286
280 mapBlocks = cachedMapBlocks; 287 // mapBlocks = cachedMapBlocks;
281 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 288 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
282 } 289 // }
283 else 290 // else
284 { 291 // {
285 lookup = true; 292 // lookup = true;
286 } 293 // }
287 } 294 // }
288 if (lookup) 295 // if (lookup)
289 { 296 // {
290 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 297 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
291 298
292 // Get regions that are within 8 regions of here 299 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
293 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 300 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
294 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 8), 301 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
295 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 8), 302 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
296 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 8), 303 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
297 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 8) ); 304 // foreach (GridRegion r in regions)
298 foreach (GridRegion r in regions) 305 // {
299 { 306 // MapBlockData block = new MapBlockData();
300 MapBlockData block = MapBlockFromGridRegion(r, 0); 307 // MapBlockFromGridRegion(block, r, 0);
301 mapBlocks.Add(block); 308 // mapBlocks.Add(block);
302 } 309 // }
303 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 310 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
304 311
305 lock (cachedMapBlocks) 312 // lock (cachedMapBlocks)
306 cachedMapBlocks = mapBlocks; 313 // cachedMapBlocks = mapBlocks;
307 314
308 cachedTime = Util.UnixTimeSinceEpoch(); 315 // cachedTime = Util.UnixTimeSinceEpoch();
309 } 316 // }
310 } 317 // }
311 } 318 //}
312 319
313 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 320 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
314 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 321 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -334,9 +341,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
334 /// <returns></returns> 341 /// <returns></returns>
335 protected static OSDMapLayer GetOSDMapLayerResponse() 342 protected static OSDMapLayer GetOSDMapLayerResponse()
336 { 343 {
344 // not sure about this.... 2048 or master 5000 and hack above?
345
337 OSDMapLayer mapLayer = new OSDMapLayer(); 346 OSDMapLayer mapLayer = new OSDMapLayer();
338 mapLayer.Right = 5000; 347 mapLayer.Right = 2048;
339 mapLayer.Top = 5000; 348 mapLayer.Top = 2048;
340 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 349 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
341 350
342 return mapLayer; 351 return mapLayer;
@@ -365,6 +374,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
365 { 374 {
366 m_rootAgents.Remove(AgentId); 375 m_rootAgents.Remove(AgentId);
367 } 376 }
377 lock (m_mapBlockRequestEvent)
378 {
379 if (m_mapBlockRequests.ContainsKey(AgentId))
380 m_mapBlockRequests.Remove(AgentId);
381 }
368 } 382 }
369 #endregion 383 #endregion
370 384
@@ -379,14 +393,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
379 if (threadrunning) return; 393 if (threadrunning) return;
380 threadrunning = true; 394 threadrunning = true;
381 395
382// m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread"); 396 // m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread");
383 397
384 WorkManager.StartThread( 398 WorkManager.StartThread(
385 process, 399 process,
386 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName), 400 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName),
387 ThreadPriority.BelowNormal, 401 ThreadPriority.BelowNormal,
388 true, 402 true,
389 true); 403 false);
404 WorkManager.StartThread(
405 MapBlockSendThread,
406 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
407 ThreadPriority.BelowNormal,
408 true,
409 false);
390 } 410 }
391 411
392 /// <summary> 412 /// <summary>
@@ -396,13 +416,29 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
396 { 416 {
397 MapRequestState st = new MapRequestState(); 417 MapRequestState st = new MapRequestState();
398 st.agentID = STOP_UUID; 418 st.agentID = STOP_UUID;
399 st.EstateID=0; 419 st.EstateID = 0;
400 st.flags=0; 420 st.flags = 0;
401 st.godlike=false; 421 st.godlike = false;
402 st.itemtype=0; 422 st.itemtype = 0;
403 st.regionhandle=0; 423 st.regionhandle = 0;
404 424
405 requests.Enqueue(st); 425 requests.Enqueue(st);
426
427 MapBlockRequestData req = new MapBlockRequestData();
428
429 req.client = null;
430 req.minX = 0;
431 req.maxX = 0;
432 req.minY = 0;
433 req.maxY = 0;
434 req.flags = 0;
435
436 lock (m_mapBlockRequestEvent)
437 {
438 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
439 m_mapBlockRequests[UUID.Zero].Enqueue(req);
440 m_mapBlockRequestEvent.Set();
441 }
406 } 442 }
407 443
408 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 444 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -415,315 +451,371 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
415 if (!m_rootAgents.Contains(remoteClient.AgentId)) 451 if (!m_rootAgents.Contains(remoteClient.AgentId))
416 return; 452 return;
417 } 453 }
454
455 // local or remote request?
456 if (regionhandle != 0 && regionhandle != m_scene.RegionInfo.RegionHandle)
457 {
458 // its Remote Map Item Request
459 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes.
460 RequestMapItems("", remoteClient.AgentId, flags, EstateID, godlike, itemtype, regionhandle);
461 return;
462 }
463
418 uint xstart = 0; 464 uint xstart = 0;
419 uint ystart = 0; 465 uint ystart = 0;
420 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); 466 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
421 if (itemtype == (int)GridItemType.AgentLocations) 467
468 // its about this region...
469
470 List<mapItemReply> mapitems = new List<mapItemReply>();
471 mapItemReply mapitem = new mapItemReply();
472
473 // viewers only ask for green dots to each region now
474 // except at login with regionhandle 0
475 // possible on some other rare ocasions
476 // use previus hack of sending all items with the green dots
477
478 bool adultRegion;
479 if (regionhandle == 0)
422 { 480 {
423 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 481 switch (itemtype)
424 { 482 {
425 // Just requesting map info about the current, local region 483 case (int)GridItemType.AgentLocations:
426 int tc = Environment.TickCount; 484 // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
427 List<mapItemReply> mapitems = new List<mapItemReply>(); 485
428 mapItemReply mapitem = new mapItemReply(); 486 int tc = Environment.TickCount;
429 if (m_scene.GetRootAgentCount() <= 1) 487 if (m_scene.GetRootAgentCount() <= 1)
430 { 488 {
431 mapitem = new mapItemReply( 489 mapitem = new mapItemReply(
432 xstart + 1, 490 xstart + 1,
433 ystart + 1, 491 ystart + 1,
434 UUID.Zero, 492 UUID.Zero,
435 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 493 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
436 0, 0); 494 0, 0);
437 mapitems.Add(mapitem); 495 mapitems.Add(mapitem);
438 } 496 }
439 else 497 else
440 {
441 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
442 { 498 {
499 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
500 {
443 // Don't send a green dot for yourself 501 // Don't send a green dot for yourself
444 if (sp.UUID != remoteClient.AgentId) 502 if (sp.UUID != remoteClient.AgentId)
445 { 503 {
446 mapitem = new mapItemReply( 504 mapitem = new mapItemReply(
447 xstart + (uint)sp.AbsolutePosition.X, 505 xstart + (uint)sp.AbsolutePosition.X,
448 ystart + (uint)sp.AbsolutePosition.Y, 506 ystart + (uint)sp.AbsolutePosition.Y,
449 UUID.Zero, 507 UUID.Zero,
450 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 508 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
451 1, 0); 509 1, 0);
452 mapitems.Add(mapitem); 510 mapitems.Add(mapitem);
453 } 511 }
454 }); 512 });
455 } 513 }
456 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 514 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
457 } 515 break;
458 else
459 {
460 // Remote Map Item Request
461 516
462 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 517 case (int)GridItemType.Telehub:
463 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 518 // Service 1 (MAP_ITEM_TELEHUB)
464 } 519
465 } 520 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
466 else if (itemtype == (int)GridItemType.LandForSale) // Service 7 (MAP_ITEM_LAND_FOR_SALE) 521 if (sog != null)
467 {
468 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
469 {
470 // Parcels
471 ILandChannel landChannel = m_scene.LandChannel;
472 List<ILandObject> parcels = landChannel.AllParcels();
473
474 // Local Map Item Request
475 List<mapItemReply> mapitems = new List<mapItemReply>();
476 mapItemReply mapitem = new mapItemReply();
477 if ((parcels != null) && (parcels.Count >= 1))
478 {
479 foreach (ILandObject parcel_interface in parcels)
480 { 522 {
481 // Play it safe 523 mapitem = new mapItemReply(
482 if (!(parcel_interface is LandObject)) 524 xstart + (uint)sog.AbsolutePosition.X,
483 continue; 525 ystart + (uint)sog.AbsolutePosition.Y,
526 UUID.Zero,
527 sog.Name,
528 0, // color (not used)
529 0 // 0 = telehub / 1 = infohub
530 );
531 mapitems.Add(mapitem);
532 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
533 }
534 break;
484 535
485 LandObject land = (LandObject)parcel_interface; 536 case (int)GridItemType.AdultLandForSale:
486 LandData parcel = land.LandData; 537 case (int)GridItemType.LandForSale:
487 538
488 // Show land for sale 539 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
489 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale) 540 adultRegion = m_scene.RegionInfo.RegionSettings.Maturity == 2;
490 { 541 if (adultRegion)
491 Vector3 min = parcel.AABBMin; 542 {
492 Vector3 max = parcel.AABBMax; 543 if (itemtype == (int)GridItemType.LandForSale)
493 float x = (min.X+max.X)/2; 544 break;
494 float y = (min.Y+max.Y)/2; 545 }
546 else
547 {
548 if (itemtype == (int)GridItemType.AdultLandForSale)
549 break;
550 }
495 551
496 mapitem = new mapItemReply( 552 // Parcels
553 ILandChannel landChannel = m_scene.LandChannel;
554 List<ILandObject> parcels = landChannel.AllParcels();
555
556 if ((parcels != null) && (parcels.Count >= 1))
557 {
558 foreach (ILandObject parcel_interface in parcels)
559 {
560 // Play it safe
561 if (!(parcel_interface is LandObject))
562 continue;
563
564 LandObject land = (LandObject)parcel_interface;
565 LandData parcel = land.LandData;
566
567 // Show land for sale
568 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
569 {
570 Vector3 min = parcel.AABBMin;
571 Vector3 max = parcel.AABBMax;
572 float x = (min.X + max.X) / 2;
573 float y = (min.Y + max.Y) / 2;
574 mapitem = new mapItemReply(
497 xstart + (uint)x, 575 xstart + (uint)x,
498 ystart + (uint)y, 576 ystart + (uint)y,
499 parcel.GlobalID, 577 parcel.GlobalID,
500 parcel.Name, 578 parcel.Name,
501 parcel.Area, 579 parcel.Area,
502 parcel.SalePrice 580 parcel.SalePrice
503 ); 581 );
504 mapitems.Add(mapitem); 582 mapitems.Add(mapitem);
583 }
505 } 584 }
506 } 585 }
507 } 586 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
508 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 587 break;
509 }
510 else
511 {
512 // Remote Map Item Request
513 588
514 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 589 case (uint)GridItemType.PgEvent:
515 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 590 case (uint)GridItemType.MatureEvent:
591 case (uint)GridItemType.AdultEvent:
592 case (uint)GridItemType.Classified:
593 case (uint)GridItemType.Popular:
594 // TODO
595 // just dont not cry about them
596 break;
597
598 default:
599 // unkown map item type
600 m_log.DebugFormat("[WORLD MAP]: Unknown MapItem type {1}", itemtype);
601 break;
516 } 602 }
517 } 603 }
518 else if (itemtype == (int)GridItemType.Telehub) // Service 1 (MAP_ITEM_TELEHUB) 604 else
519 { 605 {
520 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 606 // send all items till we get a better fix
521 {
522 List<mapItemReply> mapitems = new List<mapItemReply>();
523 mapItemReply mapitem = new mapItemReply();
524 607
525 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject); 608 // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
526 if (sog != null)
527 {
528 mapitem = new mapItemReply(
529 xstart + (uint)sog.AbsolutePosition.X,
530 ystart + (uint)sog.AbsolutePosition.Y,
531 UUID.Zero,
532 sog.Name,
533 0, // color (not used)
534 0 // 0 = telehub / 1 = infohub
535 );
536 mapitems.Add(mapitem);
537 609
538 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 610 int tc = Environment.TickCount;
539 } 611 if (m_scene.GetRootAgentCount() <= 1)
612 {
613 mapitem = new mapItemReply(
614 xstart + 1,
615 ystart + 1,
616 UUID.Zero,
617 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
618 0, 0);
619 mapitems.Add(mapitem);
540 } 620 }
541 else 621 else
542 { 622 {
543 // Remote Map Item Request 623 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
544 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 624 {
625 // Don't send a green dot for yourself
626 if (sp.UUID != remoteClient.AgentId)
627 {
628 mapitem = new mapItemReply(
629 xstart + (uint)sp.AbsolutePosition.X,
630 ystart + (uint)sp.AbsolutePosition.Y,
631 UUID.Zero,
632 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
633 1, 0);
634 mapitems.Add(mapitem);
635 }
636 });
545 } 637 }
546 } 638 remoteClient.SendMapItemReply(mapitems.ToArray(), 6, flags);
547 } 639 mapitems.Clear();
548 640
549 private int nAsyncRequests = 0; 641 // Service 1 (MAP_ITEM_TELEHUB)
550 /// <summary> 642
551 /// Processing thread main() loop for doing remote mapitem requests 643 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
552 /// </summary> 644 if (sog != null)
553 public void process()
554 {
555 //const int MAX_ASYNC_REQUESTS = 20;
556 try
557 {
558 while (true)
559 { 645 {
560 MapRequestState st = requests.Dequeue(1000); 646 mapitem = new mapItemReply(
647 xstart + (uint)sog.AbsolutePosition.X,
648 ystart + (uint)sog.AbsolutePosition.Y,
649 UUID.Zero,
650 sog.Name,
651 0, // color (not used)
652 0 // 0 = telehub / 1 = infohub
653 );
654 mapitems.Add(mapitem);
655 remoteClient.SendMapItemReply(mapitems.ToArray(), 1, flags);
656 mapitems.Clear();
657 }
561 658
562 // end gracefully 659 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
563 if (st.agentID == STOP_UUID)
564 break;
565 660
566 if (st.agentID != UUID.Zero) 661 uint its = 7;
662 if (m_scene.RegionInfo.RegionSettings.Maturity == 2)
663 its = 10;
664
665 // Parcels
666 ILandChannel landChannel = m_scene.LandChannel;
667 List<ILandObject> parcels = landChannel.AllParcels();
668
669 if ((parcels != null) && (parcels.Count >= 1))
670 {
671 foreach (ILandObject parcel_interface in parcels)
567 { 672 {
568 bool dorequest = true; 673 // Play it safe
569 lock (m_rootAgents) 674 if (!(parcel_interface is LandObject))
570 { 675 continue;
571 if (!m_rootAgents.Contains(st.agentID)) 676
572 dorequest = false; 677 LandObject land = (LandObject)parcel_interface;
573 } 678 LandData parcel = land.LandData;
574 679
575 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 680 // Show land for sale
681 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
576 { 682 {
577 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 683 Vector3 min = parcel.AABBMin;
578 Thread.Sleep(80); 684 Vector3 max = parcel.AABBMax;
579 685 float x = (min.X + max.X) / 2;
580 RequestMapItemsDelegate d = RequestMapItemsAsync; 686 float y = (min.Y + max.Y) / 2;
581 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); 687 mapitem = new mapItemReply(
582 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); 688 xstart + (uint)x,
583 //RequestMapItemsCompleted(response); 689 ystart + (uint)y,
584 Interlocked.Increment(ref nAsyncRequests); 690 parcel.GlobalID,
691 parcel.Name,
692 parcel.Area,
693 parcel.SalePrice
694 );
695 mapitems.Add(mapitem);
585 } 696 }
586 } 697 }
587 698 if(mapitems.Count >0)
588 Watchdog.UpdateThread(); 699 remoteClient.SendMapItemReply(mapitems.ToArray(), its, flags);
700 mapitems.Clear();
589 } 701 }
590 } 702 }
591 catch (Exception e)
592 {
593 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
594 }
595
596 threadrunning = false;
597 Watchdog.RemoveThread();
598 } 703 }
599 704
600 const int MAX_ASYNC_REQUESTS = 20; 705 private int nAsyncRequests = 0;
601
602 /// <summary> 706 /// <summary>
603 /// Enqueues the map item request into the services throttle processing thread 707 /// Processing thread main() loop for doing remote mapitem requests
604 /// </summary> 708 /// </summary>
605 /// <param name="state"></param> 709 public void process()
606 public void EnqueueMapItemRequest(MapRequestState st)
607 { 710 {
711 const int MAX_ASYNC_REQUESTS = 20;
712 ScenePresence av = null;
713 MapRequestState st = null;
608 714
609 m_ServiceThrottle.Enqueue("map-item", st.regionhandle.ToString() + st.agentID.ToString(), delegate 715 try
610 { 716 {
611 if (st.agentID != UUID.Zero) 717 while (true)
612 { 718 {
613 bool dorequest = true; 719 av = null;
614 lock (m_rootAgents) 720 st = null;
615 {
616 if (!m_rootAgents.Contains(st.agentID))
617 dorequest = false;
618 }
619 721
620 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 722 st = requests.Dequeue(4500);
621 { 723 Watchdog.UpdateThread();
622 if (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
623 {
624 // AH!!! Recursive !
625 // Put this request back in the queue and return
626 EnqueueMapItemRequest(st);
627 return;
628 }
629 724
630 RequestMapItemsDelegate d = RequestMapItemsAsync; 725 if (st == null || st.agentID == UUID.Zero)
631 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); 726 continue;
632 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
633 //RequestMapItemsCompleted(response);
634 Interlocked.Increment(ref nAsyncRequests);
635 }
636 }
637 });
638 }
639 727
640 /// <summary> 728 // end gracefully
641 /// Sends the mapitem response to the IClientAPI 729 if (st.agentID == STOP_UUID)
642 /// </summary> 730 break;
643 /// <param name="response">The OSDMap Response for the mapitem</param>
644 private void RequestMapItemsCompleted(IAsyncResult iar)
645 {
646 AsyncResult result = (AsyncResult)iar;
647 RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
648 731
649 OSDMap response = (OSDMap)icon.EndInvoke(iar); 732 // agent gone?
650 733
651 Interlocked.Decrement(ref nAsyncRequests); 734 m_scene.TryGetScenePresence(st.agentID, out av);
735 if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
736 continue;
652 737
653 if (!response.ContainsKey("requestID")) 738 // region unreachable?
654 return; 739 if (m_blacklistedregions.Contains(st.regionhandle))
740 continue;
655 741
656 UUID requestID = response["requestID"].AsUUID(); 742 bool dorequest = true;
743 OSDMap responseMap = null;
657 744
658 if (requestID != UUID.Zero) 745 // check if we are already serving this region
659 { 746 lock (m_cachedRegionMapItemsResponses)
660 MapRequestState mrs = new MapRequestState();
661 mrs.agentID = UUID.Zero;
662 lock (m_openRequests)
663 {
664 if (m_openRequests.ContainsKey(requestID))
665 { 747 {
666 mrs = m_openRequests[requestID]; 748 if (m_cachedRegionMapItemsResponses.Contains(st.regionhandle))
667 m_openRequests.Remove(requestID); 749 {
750 m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out responseMap);
751 dorequest = false;
752 }
753 else
754 m_cachedRegionMapItemsResponses.Add(st.regionhandle, null, expireResponsesTime); // a bit more time for the access
668 } 755 }
669 }
670 756
671 if (mrs.agentID != UUID.Zero) 757 if (dorequest)
672 {
673 ScenePresence av = null;
674 m_scene.TryGetScenePresence(mrs.agentID, out av);
675 if (av != null)
676 { 758 {
677 if (response.ContainsKey(mrs.itemtype.ToString())) 759 // nothig for region, fire a request
760 Interlocked.Increment(ref nAsyncRequests);
761 MapRequestState rst = st;
762 Util.FireAndForget(x =>
678 { 763 {
679 List<mapItemReply> returnitems = new List<mapItemReply>(); 764 RequestMapItemsAsync(rst.agentID, rst.flags, rst.EstateID, rst.godlike, rst.itemtype, rst.regionhandle);
680 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; 765 });
681 for (int i = 0; i < itemarray.Count; i++) 766 }
682 { 767 else
683 OSDMap mapitem = (OSDMap)itemarray[i]; 768 {
684 mapItemReply mi = new mapItemReply(); 769 // do we have the response?
685 mi.FromOSD(mapitem); 770 if (responseMap != null)
686 returnitems.Add(mi);
687 }
688 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
689 }
690
691 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
692 uint itemtype = (uint)GridItemType.LandForSale;
693
694 if (response.ContainsKey(itemtype.ToString()))
695 { 771 {
696 List<mapItemReply> returnitems = new List<mapItemReply>(); 772 if(av!=null)
697 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
698 for (int i = 0; i < itemarray.Count; i++)
699 { 773 {
700 OSDMap mapitem = (OSDMap)itemarray[i]; 774 // this will mainly only send green dots now
701 mapItemReply mi = new mapItemReply(); 775 if (responseMap.ContainsKey(st.itemtype.ToString()))
702 mi.FromOSD(mapitem); 776 {
703 returnitems.Add(mi); 777 List<mapItemReply> returnitems = new List<mapItemReply>();
778 OSDArray itemarray = (OSDArray)responseMap[st.itemtype.ToString()];
779 for (int i = 0; i < itemarray.Count; i++)
780 {
781 OSDMap mapitem = (OSDMap)itemarray[i];
782 mapItemReply mi = new mapItemReply();
783 mi.x = (uint)mapitem["X"].AsInteger();
784 mi.y = (uint)mapitem["Y"].AsInteger();
785 mi.id = mapitem["ID"].AsUUID();
786 mi.Extra = mapitem["Extra"].AsInteger();
787 mi.Extra2 = mapitem["Extra2"].AsInteger();
788 mi.name = mapitem["Name"].AsString();
789 returnitems.Add(mi);
790 }
791 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), st.itemtype, st.flags & 0xffff);
792 }
704 } 793 }
705 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
706 } 794 }
707 795 else
708 // Service 1 (MAP_ITEM_TELEHUB)
709 itemtype = (uint)GridItemType.Telehub;
710
711 if (response.ContainsKey(itemtype.ToString()))
712 { 796 {
713 List<mapItemReply> returnitems = new List<mapItemReply>(); 797 // request still beeing processed, enqueue it back
714 OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; 798 requests.Enqueue(st);
715 for (int i = 0; i < itemarray.Count; i++) 799 if (requests.Count() < 3)
716 { 800 Thread.Sleep(100);
717 OSDMap mapitem = (OSDMap)itemarray[i];
718 mapItemReply mi = new mapItemReply();
719 mi.FromOSD(mapitem);
720 returnitems.Add(mi);
721 }
722 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
723 } 801 }
724 } 802 }
803
804 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
805 {
806 Thread.Sleep(100);
807 Watchdog.UpdateThread();
808 }
725 } 809 }
726 } 810 }
811
812 catch (Exception e)
813 {
814 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
815 }
816
817 threadrunning = false;
818 Watchdog.RemoveThread();
727 } 819 }
728 820
729 /// <summary> 821 /// <summary>
@@ -746,11 +838,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
746 st.godlike = godlike; 838 st.godlike = godlike;
747 st.itemtype = itemtype; 839 st.itemtype = itemtype;
748 st.regionhandle = regionhandle; 840 st.regionhandle = regionhandle;
749 EnqueueMapItemRequest(st); 841
842 requests.Enqueue(st);
750 } 843 }
751 844
752 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags, 845 uint[] itemTypesForcedSend = new uint[] { 6, 1, 7, 10 }; // green dots, infohub, land sells
753 uint EstateID, bool godlike, uint itemtype, ulong regionhandle); 846
754 /// <summary> 847 /// <summary>
755 /// Does the actual remote mapitem request 848 /// Does the actual remote mapitem request
756 /// This should be called from an asynchronous thread 849 /// This should be called from an asynchronous thread
@@ -765,94 +858,55 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
765 /// <param name="itemtype">passed in from packet</param> 858 /// <param name="itemtype">passed in from packet</param>
766 /// <param name="regionhandle">Region we're looking up</param> 859 /// <param name="regionhandle">Region we're looking up</param>
767 /// <returns></returns> 860 /// <returns></returns>
768 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 861 private void RequestMapItemsAsync(UUID id, uint flags,
769 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 862 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
770 { 863 {
771// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 864 // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
772 865
773 string httpserver = ""; 866 string httpserver = "";
774 bool blacklisted = false; 867 bool blacklisted = false;
775 lock (m_blacklistedregions)
776 {
777 if (m_blacklistedregions.ContainsKey(regionhandle))
778 {
779 if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout))
780 {
781 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle);
782 868
783 m_blacklistedregions.Remove(regionhandle); 869 lock (m_blacklistedregions)
784 } 870 blacklisted = m_blacklistedregions.Contains(regionhandle);
785 else
786 blacklisted = true;
787 }
788 }
789 871
790 if (blacklisted) 872 if (blacklisted)
791 return new OSDMap(); 873 {
874 Interlocked.Decrement(ref nAsyncRequests);
875 return;
876 }
792 877
793 UUID requestID = UUID.Random(); 878 UUID requestID = UUID.Random();
794 lock (m_cachedRegionMapItemsAddress) 879 lock (m_cachedRegionMapItemsAddress)
795 { 880 m_cachedRegionMapItemsAddress.TryGetValue(regionhandle, out httpserver);
796 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 881
797 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 882 if (httpserver == null || httpserver.Length == 0)
798 }
799 if (httpserver.Length == 0)
800 { 883 {
801 uint x = 0, y = 0; 884 uint x = 0, y = 0;
802 Util.RegionHandleToWorldLoc(regionhandle, out x, out y); 885 Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
886
803 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 887 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
804 888
805 if (mreg != null) 889 if (mreg != null)
806 { 890 {
807 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); 891 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString();
808 lock (m_cachedRegionMapItemsAddress) 892 lock (m_cachedRegionMapItemsAddress)
809 { 893 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle, httpserver, 2.0 * expireBlackListTime);
810 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
811 m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver);
812 }
813 }
814 else
815 {
816 lock (m_blacklistedregions)
817 {
818 if (!m_blacklistedregions.ContainsKey(regionhandle))
819 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
820 }
821 //m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString());
822 } 894 }
823 } 895 }
824 896
825 blacklisted = false;
826 lock (m_blacklistedurls) 897 lock (m_blacklistedurls)
827 { 898 {
828 if (m_blacklistedurls.ContainsKey(httpserver)) 899 if (httpserver == null || httpserver.Length == 0 || m_blacklistedurls.Contains(httpserver))
829 { 900 {
830 if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) 901 // Can't find the http server or its blocked
831 { 902 lock (m_blacklistedregions)
832 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver); 903 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
833 904
834 m_blacklistedurls.Remove(httpserver); 905 Interlocked.Decrement(ref nAsyncRequests);
835 } 906 return;
836 else
837 blacklisted = true;
838 } 907 }
839 } 908 }
840 909
841 // Can't find the http server
842 if (httpserver.Length == 0 || blacklisted)
843 return new OSDMap();
844
845 MapRequestState mrs = new MapRequestState();
846 mrs.agentID = id;
847 mrs.EstateID = EstateID;
848 mrs.flags = flags;
849 mrs.godlike = godlike;
850 mrs.itemtype=itemtype;
851 mrs.regionhandle = regionhandle;
852
853 lock (m_openRequests)
854 m_openRequests.Add(requestID, mrs);
855
856 WebRequest mapitemsrequest = null; 910 WebRequest mapitemsrequest = null;
857 try 911 try
858 { 912 {
@@ -861,132 +915,144 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
861 catch (Exception e) 915 catch (Exception e)
862 { 916 {
863 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 917 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
864 return new OSDMap(); 918 Interlocked.Decrement(ref nAsyncRequests);
919 return;
865 } 920 }
866 921
867 mapitemsrequest.Method = "POST"; 922 mapitemsrequest.Method = "POST";
868 mapitemsrequest.ContentType = "application/xml+llsd"; 923 mapitemsrequest.ContentType = "application/xml+llsd";
869 OSDMap RAMap = new OSDMap();
870 924
925 OSDMap RAMap = new OSDMap();
871 // string RAMapString = RAMap.ToString(); 926 // string RAMapString = RAMap.ToString();
872 OSD LLSDofRAMap = RAMap; // RENAME if this works 927 OSD LLSDofRAMap = RAMap; // RENAME if this works
873 928
874 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); 929 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
930
875 OSDMap responseMap = new OSDMap(); 931 OSDMap responseMap = new OSDMap();
876 responseMap["requestID"] = OSD.FromUUID(requestID);
877 932
878 Stream os = null;
879 try 933 try
880 { // send the Post 934 { // send the Post
881 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send 935 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
882 os = mapitemsrequest.GetRequestStream(); 936 using (Stream os = mapitemsrequest.GetRequestStream())
883 os.Write(buffer, 0, buffer.Length); //Send it 937 os.Write(buffer, 0, buffer.Length); //Send it
884 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver); 938 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver);
885 } 939 }
886 catch (WebException ex) 940 catch (WebException ex)
887 { 941 {
888 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 942 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
889 responseMap["connect"] = OSD.FromBoolean(false); 943 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
890 lock (m_blacklistedurls) 944 lock (m_blacklistedurls)
891 { 945 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
892 if (!m_blacklistedurls.ContainsKey(httpserver)) 946 lock (m_blacklistedregions)
893 m_blacklistedurls.Add(httpserver, Environment.TickCount); 947 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
894 }
895
896 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
897 948
898 return responseMap; 949 Interlocked.Decrement(ref nAsyncRequests);
950 return;
899 } 951 }
900 catch 952 catch
901 { 953 {
902 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 954 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
903 responseMap["connect"] = OSD.FromBoolean(false); 955 Interlocked.Decrement(ref nAsyncRequests);
904 return responseMap; 956 return;
905 }
906 finally
907 {
908 if (os != null)
909 os.Dispose();
910 } 957 }
911 958
912 string response_mapItems_reply = null; 959 string response_mapItems_reply = null;
913 { 960 { // get the response
914 try 961 try
915 { 962 {
916 using (WebResponse webResponse = mapitemsrequest.GetResponse()) 963 using (WebResponse webResponse = mapitemsrequest.GetResponse())
917 { 964 {
918 if (webResponse != null) 965 if (webResponse != null)
919 { 966 {
920 using (Stream s = webResponse.GetResponseStream()) 967 using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
921 using (StreamReader sr = new StreamReader(s)) 968 {
922 response_mapItems_reply = sr.ReadToEnd().Trim(); 969 response_mapItems_reply = sr.ReadToEnd().Trim();
970 }
923 } 971 }
924 else 972 else
925 { 973 {
926 return new OSDMap(); 974 Interlocked.Decrement(ref nAsyncRequests);
927 } 975 return;
928 } 976 }
977 }
929 } 978 }
930 catch (WebException) 979 catch (WebException)
931 { 980 {
932 responseMap["connect"] = OSD.FromBoolean(false);
933 lock (m_blacklistedurls) 981 lock (m_blacklistedurls)
934 { 982 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
935 if (!m_blacklistedurls.ContainsKey(httpserver)) 983 lock (m_blacklistedregions)
936 m_blacklistedurls.Add(httpserver, Environment.TickCount); 984 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
937 }
938 985
939 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 986 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
940 987
941 return responseMap; 988 Interlocked.Decrement(ref nAsyncRequests);
989 return;
942 } 990 }
943 catch 991 catch
944 { 992 {
945 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 993 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
946 responseMap["connect"] = OSD.FromBoolean(false);
947 lock (m_blacklistedregions) 994 lock (m_blacklistedregions)
948 { 995 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
949 if (!m_blacklistedregions.ContainsKey(regionhandle))
950 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
951 }
952 996
953 return responseMap; 997 Interlocked.Decrement(ref nAsyncRequests);
998 return;
954 } 999 }
955 1000
956 OSD rezResponse = null;
957 try 1001 try
958 { 1002 {
959 rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply); 1003 responseMap = (OSDMap)OSDParser.DeserializeLLSDXml(response_mapItems_reply);
960
961 responseMap = (OSDMap)rezResponse;
962 responseMap["requestID"] = OSD.FromUUID(requestID);
963 } 1004 }
964 catch (Exception ex) 1005 catch (Exception ex)
965 { 1006 {
966 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 1007 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
967 responseMap["connect"] = OSD.FromBoolean(false);
968
969 lock (m_blacklistedregions) 1008 lock (m_blacklistedregions)
970 { 1009 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
971 if (!m_blacklistedregions.ContainsKey(regionhandle))
972 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
973 }
974 1010
975 return responseMap; 1011 Interlocked.Decrement(ref nAsyncRequests);
1012 return;
976 } 1013 }
977 } 1014 }
978 1015
979 if (!responseMap.ContainsKey(itemtype.ToString())) // remote sim doesnt have the stated region handle 1016 // cache the response that may include other valid items
1017 lock (m_cachedRegionMapItemsResponses)
1018 m_cachedRegionMapItemsResponses.AddOrUpdate(regionhandle, responseMap, expireResponsesTime);
1019
1020 flags &= 0xffff;
1021
1022 if (id != UUID.Zero)
980 { 1023 {
981 m_log.DebugFormat("[WORLD MAP]: Remote sim does not have the stated region. Blacklisting."); 1024 ScenePresence av = null;
982 lock (m_blacklistedregions) 1025 m_scene.TryGetScenePresence(id, out av);
1026 if (av != null && !av.IsChildAgent && !av.IsDeleted && !av.IsInTransit)
983 { 1027 {
984 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1028 // send all the items or viewers will never ask for them, except green dots
985 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 1029 foreach (uint itfs in itemTypesForcedSend)
1030 {
1031 if (responseMap.ContainsKey(itfs.ToString()))
1032 {
1033 List<mapItemReply> returnitems = new List<mapItemReply>();
1034// OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
1035 OSDArray itemarray = (OSDArray)responseMap[itfs.ToString()];
1036 for (int i = 0; i < itemarray.Count; i++)
1037 {
1038 OSDMap mapitem = (OSDMap)itemarray[i];
1039 mapItemReply mi = new mapItemReply();
1040 mi.x = (uint)mapitem["X"].AsInteger();
1041 mi.y = (uint)mapitem["Y"].AsInteger();
1042 mi.id = mapitem["ID"].AsUUID();
1043 mi.Extra = mapitem["Extra"].AsInteger();
1044 mi.Extra2 = mapitem["Extra2"].AsInteger();
1045 mi.name = mapitem["Name"].AsString();
1046 returnitems.Add(mi);
1047 }
1048// av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
1049 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itfs, flags);
1050 }
1051 }
986 } 1052 }
987 } 1053 }
988 1054
989 return responseMap; 1055 Interlocked.Decrement(ref nAsyncRequests);
990 } 1056 }
991 1057
992 /// <summary> 1058 /// <summary>
@@ -996,87 +1062,196 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
996 /// <param name="minY"></param> 1062 /// <param name="minY"></param>
997 /// <param name="maxX"></param> 1063 /// <param name="maxX"></param>
998 /// <param name="maxY"></param> 1064 /// <param name="maxY"></param>
999 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1065 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1066 {
1067// m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
1068
1069 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1070 }
1071
1072 private const double SPAMBLOCKTIMEms = 300000; // 5 minutes
1073 private Dictionary<UUID,double> spamBlocked = new Dictionary<UUID,double>();
1074
1075 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1000 { 1076 {
1001 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 1077 // anti spam because of FireStorm 4.7.7 absurd request repeat rates
1078 // possible others
1079
1080 double now = Util.GetTimeStampMS();
1081 UUID agentID = remoteClient.AgentId;
1082
1083 lock (m_mapBlockRequestEvent)
1002 { 1084 {
1003 List<MapBlockData> response = new List<MapBlockData>(); 1085 if(spamBlocked.ContainsKey(agentID))
1004
1005 // this should return one mapblock at most. It is triggered by a click
1006 // on an unloaded square.
1007 // But make sure: Look whether the one we requested is in there
1008 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1009 (int)Util.RegionToWorldLoc((uint)minX), (int)Util.RegionToWorldLoc((uint)maxX),
1010 (int)Util.RegionToWorldLoc((uint)minY), (int)Util.RegionToWorldLoc((uint)maxY) );
1011
1012 m_log.DebugFormat("[WORLD MAP MODULE] RequestMapBlocks min=<{0},{1}>, max=<{2},{3}>, flag={4}, cntFound={5}",
1013 minX, minY, maxX, maxY, flag.ToString("X"), regions.Count);
1014 if (regions != null)
1015 { 1086 {
1016 foreach (GridRegion r in regions) 1087 if(spamBlocked[agentID] < now &&
1088 (!m_mapBlockRequests.ContainsKey(agentID) ||
1089 m_mapBlockRequests[agentID].Count == 0 ))
1017 { 1090 {
1018 if (r.RegionLocX == Util.RegionToWorldLoc((uint)minX) 1091 spamBlocked.Remove(agentID);
1019 && r.RegionLocY == Util.RegionToWorldLoc((uint)minY) ) 1092 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", agentID);
1093 }
1094 else
1095 return new List<MapBlockData>();
1096 }
1097 else
1098 {
1099 // ugly slow expire spammers
1100 if(spamBlocked.Count > 0)
1101 {
1102 UUID k = UUID.Zero;
1103 bool expireone = false;
1104 foreach(UUID k2 in spamBlocked.Keys)
1020 { 1105 {
1021 // found it => add it to response 1106 if(spamBlocked[k2] < now &&
1022 // Version 2 viewers can handle the larger regions 1107 (!m_mapBlockRequests.ContainsKey(k2) ||
1023 if ((flag & 2) == 2) 1108 m_mapBlockRequests[k2].Count == 0 ))
1024 response.AddRange(Map2BlockFromGridRegion(r, flag)); 1109 {
1025 else 1110 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", k2);
1026 response.Add(MapBlockFromGridRegion(r, flag)); 1111 k = k2;
1027 break; 1112 expireone = true;
1113 }
1114 break; // doing one at a time
1028 } 1115 }
1116 if(expireone)
1117 spamBlocked.Remove(k);
1029 } 1118 }
1030 } 1119 }
1031 1120
1032 if (response.Count == 0) 1121// m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
1122
1123 MapBlockRequestData req = new MapBlockRequestData();
1124
1125 req.client = remoteClient;
1126 req.minX = minX;
1127 req.maxX = maxX;
1128 req.minY = minY;
1129 req.maxY = maxY;
1130 req.flags = flag;
1131
1132 if (!m_mapBlockRequests.ContainsKey(agentID))
1133 m_mapBlockRequests[agentID] = new Queue<MapBlockRequestData>();
1134 if(m_mapBlockRequests[agentID].Count < 150 )
1135 m_mapBlockRequests[agentID].Enqueue(req);
1136 else
1033 { 1137 {
1034 // response still empty => couldn't find the map-tile the user clicked on => tell the client 1138 spamBlocked[agentID] = now + SPAMBLOCKTIMEms;
1035 MapBlockData block = new MapBlockData(); 1139 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks blocking spammer {0} for {1} s",agentID, SPAMBLOCKTIMEms/1000.0);
1036 block.X = (ushort)minX;
1037 block.Y = (ushort)minY;
1038 block.Access = (byte)SimAccess.Down; // means 'simulator is offline'
1039 // block.Access = (byte)SimAccess.NonExistent;
1040 response.Add(block);
1041 } 1140 }
1042 // The lower 16 bits are an unsigned int16 1141 m_mapBlockRequestEvent.Set();
1043 remoteClient.SendMapBlock(response, flag & 0xffff);
1044 } 1142 }
1045 else 1143
1144 return new List<MapBlockData>();
1145 }
1146
1147 protected void MapBlockSendThread()
1148 {
1149 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1150 while (true)
1046 { 1151 {
1047 // normal mapblock request. Use the provided values 1152 while(!m_mapBlockRequestEvent.WaitOne(4900))
1048 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); 1153 {
1154 Watchdog.UpdateThread();
1155 if(m_scene == null)
1156 return;
1157 }
1158 Watchdog.UpdateThread();
1159 lock (m_mapBlockRequestEvent)
1160 {
1161 int total = 0;
1162 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
1163 {
1164 if (q.Count > 0)
1165 thisRunData.Add(q.Dequeue());
1166
1167 total += q.Count;
1168 }
1169
1170 if (total == 0)
1171 m_mapBlockRequestEvent.Reset();
1172 }
1173
1174 if(thisRunData.Count > 0)
1175 {
1176 foreach (MapBlockRequestData req in thisRunData)
1177 {
1178 // Null client stops thread
1179 if (req.client == null)
1180 return;
1181
1182 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
1183 }
1184
1185 thisRunData.Clear();
1186 }
1187
1188 Thread.Sleep(50);
1049 } 1189 }
1050 } 1190 }
1051 1191
1052 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1192 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1053 { 1193 {
1194 List<MapBlockData> allBlocks = new List<MapBlockData>();
1054 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1195 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1055 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1196 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1056 (int)Util.RegionToWorldLoc((uint)(minX - 4)), (int)Util.RegionToWorldLoc((uint)(maxX + 4)), 1197 minX * (int)Constants.RegionSize,
1057 (int)Util.RegionToWorldLoc((uint)(minY - 4)), (int)Util.RegionToWorldLoc((uint)(maxY + 4)) ); 1198 maxX * (int)Constants.RegionSize,
1058 //m_log.DebugFormat("{0} GetAndSendBlocks. min=<{1},{2}>, max=<{3},{4}>, cntFound={5}", 1199 minY * (int)Constants.RegionSize,
1059 // LogHeader, minX, minY, maxX, maxY, regions.Count); 1200 maxY * (int)Constants.RegionSize);
1201
1202 // only send a negative answer for a single region request
1203 // corresponding to a click on the map. Current viewers
1204 // keep displaying "loading.." without this
1205 if (regions.Count == 0 && (flag & 0x10000) != 0 && minX == maxX && minY == maxY)
1206 {
1207 MapBlockData block = new MapBlockData();
1208 block.X = (ushort)minX;
1209 block.Y = (ushort)minY;
1210 block.MapImageId = UUID.Zero;
1211 block.Access = (byte)SimAccess.NonExistent;
1212 allBlocks.Add(block);
1213 mapBlocks.Add(block);
1214 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1215 return allBlocks;
1216 }
1217
1218 flag &= 0xffff;
1219
1060 foreach (GridRegion r in regions) 1220 foreach (GridRegion r in regions)
1061 { 1221 {
1062 // Version 2 viewers can handle the larger regions 1222 if (r == null)
1063 if ((flag & 2) == 2) 1223 continue;
1064 mapBlocks.AddRange(Map2BlockFromGridRegion(r, flag)); 1224 MapBlockData block = new MapBlockData();
1065 else 1225 MapBlockFromGridRegion(block, r, flag);
1066 mapBlocks.Add(MapBlockFromGridRegion(r, flag)); 1226 mapBlocks.Add(block);
1227 allBlocks.Add(block);
1228
1229 if (mapBlocks.Count >= 10)
1230 {
1231 remoteClient.SendMapBlock(mapBlocks, flag);
1232 mapBlocks.Clear();
1233 Thread.Sleep(50);
1234 }
1067 } 1235 }
1068 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1236 if (mapBlocks.Count > 0)
1237 remoteClient.SendMapBlock(mapBlocks, flag);
1069 1238
1070 return mapBlocks; 1239 return allBlocks;
1071 } 1240 }
1072 1241
1073 // Fill a passed MapBlockData from a GridRegion 1242 public void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
1074 public MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag)
1075 { 1243 {
1076 MapBlockData block = new MapBlockData(); 1244 if (r == null)
1245 {
1246 // we should not get here ??
1247// block.Access = (byte)SimAccess.Down; this is for a grid reply on r
1248 block.Access = (byte)SimAccess.NonExistent;
1249 block.MapImageId = UUID.Zero;
1250 return;
1251 }
1077 1252
1078 block.Access = r.Access; 1253 block.Access = r.Access;
1079 switch (flag & 0xffff) 1254 switch (flag)
1080 { 1255 {
1081 case 0: 1256 case 0:
1082 block.MapImageId = r.TerrainImage; 1257 block.MapImageId = r.TerrainImage;
@@ -1089,50 +1264,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1089 break; 1264 break;
1090 } 1265 }
1091 block.Name = r.RegionName; 1266 block.Name = r.RegionName;
1092 block.X = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocX); 1267 block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
1093 block.Y = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocY); 1268 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1094 block.SizeX = (ushort) r.RegionSizeX; 1269 block.SizeX = (ushort)r.RegionSizeX;
1095 block.SizeY = (ushort) r.RegionSizeY; 1270 block.SizeY = (ushort)r.RegionSizeY;
1096
1097 return block;
1098 }
1099 1271
1100 public List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag)
1101 {
1102 List<MapBlockData> blocks = new List<MapBlockData>();
1103 MapBlockData block = new MapBlockData();
1104 if (r == null)
1105 {
1106 block.Access = (byte)SimAccess.Down;
1107 block.MapImageId = UUID.Zero;
1108 blocks.Add(block);
1109 }
1110 else
1111 {
1112 block.Access = r.Access;
1113 switch (flag & 0xffff)
1114 {
1115 case 0:
1116 block.MapImageId = r.TerrainImage;
1117 break;
1118 case 2:
1119 block.MapImageId = r.ParcelImage;
1120 break;
1121 default:
1122 block.MapImageId = UUID.Zero;
1123 break;
1124 }
1125 block.Name = r.RegionName;
1126 block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
1127 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1128 block.SizeX = (ushort)r.RegionSizeX;
1129 block.SizeY = (ushort)r.RegionSizeY;
1130 blocks.Add(block);
1131 }
1132 return blocks;
1133 } 1272 }
1134 1273
1135
1136 public Hashtable OnHTTPThrottled(Hashtable keysvals) 1274 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1137 { 1275 {
1138 Hashtable reply = new Hashtable(); 1276 Hashtable reply = new Hashtable();
@@ -1145,67 +1283,71 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1145 1283
1146 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1284 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1147 { 1285 {
1148 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1149 Hashtable reply = new Hashtable(); 1286 Hashtable reply = new Hashtable();
1150 int statuscode = 200; 1287 int statuscode = 200;
1151 byte[] jpeg = new byte[0]; 1288 byte[] jpeg = new byte[0];
1152 1289
1153 if (myMapImageJPEG.Length == 0) 1290 if (m_scene.RegionInfo.RegionSettings.TerrainImageID != UUID.Zero)
1154 { 1291 {
1155 MemoryStream imgstream = null; 1292 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1156 Bitmap mapTexture = new Bitmap(1,1);
1157 ManagedImage managedImage;
1158 Image image = (Image)mapTexture;
1159 1293
1160 try 1294 if (myMapImageJPEG.Length == 0)
1161 { 1295 {
1162 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data 1296 MemoryStream imgstream = null;
1297 Bitmap mapTexture = new Bitmap(1, 1);
1298 ManagedImage managedImage;
1299 Image image = (Image)mapTexture;
1163 1300
1164 imgstream = new MemoryStream(); 1301 try
1302 {
1303 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
1165 1304
1166 // non-async because we know we have the asset immediately. 1305 imgstream = new MemoryStream();
1167 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1168 1306
1169 // Decode image to System.Drawing.Image 1307 // non-async because we know we have the asset immediately.
1170 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) 1308 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1171 {
1172 // Save to bitmap
1173 mapTexture = new Bitmap(image);
1174 1309
1175 EncoderParameters myEncoderParameters = new EncoderParameters(); 1310 // Decode image to System.Drawing.Image
1176 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); 1311 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
1312 {
1313 // Save to bitmap
1314 mapTexture = new Bitmap(image);
1177 1315
1178 // Save bitmap to stream 1316 EncoderParameters myEncoderParameters = new EncoderParameters();
1179 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters); 1317 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
1180 1318
1181 // Write the stream to a byte array for output 1319 // Save bitmap to stream
1182 jpeg = imgstream.ToArray(); 1320 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
1183 myMapImageJPEG = jpeg; 1321
1322 // Write the stream to a byte array for output
1323 jpeg = imgstream.ToArray();
1324 myMapImageJPEG = jpeg;
1325 }
1184 } 1326 }
1185 } 1327 catch (Exception)
1186 catch (Exception) 1328 {
1187 { 1329 // Dummy!
1188 // Dummy! 1330 m_log.Warn("[WORLD MAP]: Unable to generate Map image");
1189 m_log.Warn("[WORLD MAP]: Unable to generate Map image"); 1331 }
1190 } 1332 finally
1191 finally 1333 {
1192 { 1334 // Reclaim memory, these are unmanaged resources
1193 // Reclaim memory, these are unmanaged resources 1335 // If we encountered an exception, one or more of these will be null
1194 // If we encountered an exception, one or more of these will be null 1336 if (mapTexture != null)
1195 if (mapTexture != null) 1337 mapTexture.Dispose();
1196 mapTexture.Dispose();
1197 1338
1198 if (image != null) 1339 if (image != null)
1199 image.Dispose(); 1340 image.Dispose();
1200 1341
1201 if (imgstream != null) 1342 if (imgstream != null)
1202 imgstream.Dispose(); 1343 imgstream.Dispose();
1344 }
1345 }
1346 else
1347 {
1348 // Use cached version so we don't have to loose our mind
1349 jpeg = myMapImageJPEG;
1203 } 1350 }
1204 }
1205 else
1206 {
1207 // Use cached version so we don't have to loose our mind
1208 jpeg = myMapImageJPEG;
1209 } 1351 }
1210 1352
1211 reply["str_response_string"] = Convert.ToBase64String(jpeg); 1353 reply["str_response_string"] = Convert.ToBase64String(jpeg);
@@ -1267,22 +1409,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1267 1409
1268 foreach (GridRegion r in regions) 1410 foreach (GridRegion r in regions)
1269 { 1411 {
1270 MapBlockData mapBlock = MapBlockFromGridRegion(r, 0); 1412 MapBlockData mapBlock = new MapBlockData();
1413 MapBlockFromGridRegion(mapBlock, r, 0);
1271 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString()); 1414 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1272 1415
1273 if (texAsset != null) 1416 if (texAsset != null)
1274 { 1417 {
1275 textures.Add(texAsset); 1418 textures.Add(texAsset);
1276 } 1419 }
1277 //else
1278 //{
1279 // // WHAT?!? This doesn't seem right. Commenting (diva)
1280 // texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1281 // if (texAsset != null)
1282 // {
1283 // textures.Add(texAsset);
1284 // }
1285 //}
1286 } 1420 }
1287 1421
1288 foreach (AssetBase asset in textures) 1422 foreach (AssetBase asset in textures)
@@ -1308,6 +1442,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1308 1442
1309 mapTexture.Save(exportPath, ImageFormat.Jpeg); 1443 mapTexture.Save(exportPath, ImageFormat.Jpeg);
1310 1444
1445 g.Dispose();
1446 mapTexture.Dispose();
1447 sea.Dispose();
1448
1311 m_log.InfoFormat( 1449 m_log.InfoFormat(
1312 "[WORLD MAP]: Successfully exported world map for {0} to {1}", 1450 "[WORLD MAP]: Successfully exported world map for {0} to {1}",
1313 m_scene.RegionInfo.RegionName, exportPath); 1451 m_scene.RegionInfo.RegionName, exportPath);
@@ -1320,17 +1458,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1320 if (consoleScene != null && consoleScene != m_scene) 1458 if (consoleScene != null && consoleScene != m_scene)
1321 return; 1459 return;
1322 1460
1323 if (m_mapImageGenerator == null) 1461 GenerateMaptileForce();
1324 {
1325 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1326 return;
1327 }
1328
1329 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1330 {
1331 GenerateMaptile(mapbmp);
1332 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1333 }
1334 } 1462 }
1335 1463
1336 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1464 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
@@ -1338,9 +1466,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1338 uint xstart = 0; 1466 uint xstart = 0;
1339 uint ystart = 0; 1467 uint ystart = 0;
1340 1468
1341 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); 1469 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
1342 // m_log.DebugFormat("{0} HandleRemoteMapItemRequest. loc=<{1},{2}>",
1343 // LogHeader, Util.WorldToRegionLoc(xstart), Util.WorldToRegionLoc(ystart));
1344 1470
1345 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots) 1471 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)
1346 1472
@@ -1362,8 +1488,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1362 } 1488 }
1363 else 1489 else
1364 { 1490 {
1365 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1491 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1366 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1492 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
1367 { 1493 {
1368 OSDMap responsemapdata = new OSDMap(); 1494 OSDMap responsemapdata = new OSDMap();
1369 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X)); 1495 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X));
@@ -1377,28 +1503,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1377 responsemap["6"] = responsearr; 1503 responsemap["6"] = responsearr;
1378 } 1504 }
1379 1505
1380 // Service 7 (MAP_ITEM_LAND_FOR_SALE) 1506 // Service 7/10 (MAP_ITEM_LAND_FOR_SALE/ADULT)
1381 1507
1382 ILandChannel landChannel = m_scene.LandChannel; 1508 ILandChannel landChannel = m_scene.LandChannel;
1383 List<ILandObject> parcels = landChannel.AllParcels(); 1509 List<ILandObject> parcels = landChannel.AllParcels();
1384 1510
1385 if ((parcels == null) || (parcels.Count == 0)) 1511 if ((parcels != null) && (parcels.Count >= 0))
1386 {
1387 OSDMap responsemapdata = new OSDMap();
1388 responsemapdata["X"] = OSD.FromInteger((int)(xstart + 1));
1389 responsemapdata["Y"] = OSD.FromInteger((int)(ystart + 1));
1390 responsemapdata["ID"] = OSD.FromUUID(UUID.Zero);
1391 responsemapdata["Name"] = OSD.FromString("");
1392 responsemapdata["Extra"] = OSD.FromInteger(0);
1393 responsemapdata["Extra2"] = OSD.FromInteger(0);
1394 OSDArray responsearr = new OSDArray();
1395 responsearr.Add(responsemapdata);
1396
1397 responsemap["7"] = responsearr;
1398 }
1399 else
1400 { 1512 {
1401 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1513 OSDArray responsearr = new OSDArray(parcels.Count);
1402 foreach (ILandObject parcel_interface in parcels) 1514 foreach (ILandObject parcel_interface in parcels)
1403 { 1515 {
1404 // Play it safe 1516 // Play it safe
@@ -1413,8 +1525,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1413 { 1525 {
1414 Vector3 min = parcel.AABBMin; 1526 Vector3 min = parcel.AABBMin;
1415 Vector3 max = parcel.AABBMax; 1527 Vector3 max = parcel.AABBMax;
1416 float x = (min.X+max.X)/2; 1528 float x = (min.X + max.X) / 2;
1417 float y = (min.Y+max.Y)/2; 1529 float y = (min.Y + max.Y) / 2;
1418 1530
1419 OSDMap responsemapdata = new OSDMap(); 1531 OSDMap responsemapdata = new OSDMap();
1420 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x)); 1532 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x));
@@ -1427,7 +1539,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1427 responsearr.Add(responsemapdata); 1539 responsearr.Add(responsemapdata);
1428 } 1540 }
1429 } 1541 }
1430 responsemap["7"] = responsearr; 1542
1543 if(responsearr.Count > 0)
1544 {
1545 if(m_scene.RegionInfo.RegionSettings.Maturity == 2)
1546 responsemap["10"] = responsearr;
1547 else
1548 responsemap["7"] = responsearr;
1549 }
1431 } 1550 }
1432 1551
1433 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero) 1552 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
@@ -1453,61 +1572,138 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1453 return responsemap; 1572 return responsemap;
1454 } 1573 }
1455 1574
1575 private void GenerateMaptileForce()
1576 {
1577 // Cannot create a map for a nonexistent heightmap
1578 if (m_scene.Heightmap == null)
1579 return;
1580
1581 if (m_mapImageGenerator == null)
1582 {
1583 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1584 return;
1585 }
1586 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name);
1587
1588 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTileForce())
1589 {
1590 GenerateMaptile(mapbmp);
1591
1592 if (m_mapImageServiceModule != null)
1593 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1594 }
1595 }
1596
1456 public void GenerateMaptile() 1597 public void GenerateMaptile()
1457 { 1598 {
1458 // Cannot create a map for a nonexistent heightmap 1599 // Cannot create a map for a nonexistent heightmap
1459 if (m_scene.Heightmap == null) 1600 if (m_scene.Heightmap == null)
1460 return; 1601 return;
1461 1602
1603 if (m_mapImageGenerator == null)
1604 {
1605 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1606 return;
1607 }
1462 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name); 1608 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name);
1463 1609
1464 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile()) 1610 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1465 { 1611 {
1466 // V1 (This Module)
1467 GenerateMaptile(mapbmp); 1612 GenerateMaptile(mapbmp);
1468 1613
1469 // v2/3 (MapImageServiceModule) 1614 if (m_mapImageServiceModule != null)
1470 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp); 1615 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1471 } 1616 }
1472 } 1617 }
1473 1618
1474 private void GenerateMaptile(Bitmap mapbmp) 1619 private void GenerateMaptile(Bitmap mapbmp)
1475 { 1620 {
1476 byte[] data; 1621 bool needRegionSave = false;
1477 1622
1478 try 1623 // remove old assets
1624 UUID lastID = m_scene.RegionInfo.RegionSettings.TerrainImageID;
1625 if (lastID != UUID.Zero)
1479 { 1626 {
1480 data = OpenJPEG.EncodeFromImage(mapbmp, true); 1627 m_scene.AssetService.Delete(lastID.ToString());
1628 m_scene.RegionInfo.RegionSettings.TerrainImageID = UUID.Zero;
1629 myMapImageJPEG = new byte[0];
1630 needRegionSave = true;
1481 } 1631 }
1482 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke 1632
1633 lastID = m_scene.RegionInfo.RegionSettings.ParcelImageID;
1634 if (lastID != UUID.Zero)
1483 { 1635 {
1484 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e); 1636 m_scene.AssetService.Delete(lastID.ToString());
1485 return; 1637 m_scene.RegionInfo.RegionSettings.ParcelImageID = UUID.Zero;
1638 needRegionSave = true;
1486 } 1639 }
1487 1640
1488 byte[] overlay = GenerateOverlay(); 1641 if(mapbmp != null)
1642 {
1643 try
1644 {
1645 byte[] data;
1489 1646
1490 UUID terrainImageID = UUID.Random(); 1647 // if large region limit its size since new viewers will not use it
1491 UUID parcelImageID = UUID.Zero; 1648 // but it is still usable for ossl
1649 if(m_scene.RegionInfo.RegionSizeX > Constants.RegionSize ||
1650 m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1651 {
1652 int bx = mapbmp.Width;
1653 int by = mapbmp.Height;
1654 int mb = bx;
1655 if(mb < by)
1656 mb = by;
1657 if(mb > Constants.RegionSize && mb > 0)
1658 {
1659 float scale = (float)Constants.RegionSize/(float)mb;
1660 Size newsize = new Size();
1661 newsize.Width = (int)(bx * scale);
1662 newsize.Height = (int)(by * scale);
1492 1663
1493 AssetBase asset = new AssetBase( 1664 using(Bitmap scaledbmp = new Bitmap(mapbmp,newsize))
1494 terrainImageID, 1665 data = OpenJPEG.EncodeFromImage(scaledbmp, true);
1495 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(), 1666 }
1496 (sbyte)AssetType.Texture, 1667 else
1497 m_scene.RegionInfo.RegionID.ToString()); 1668 data = OpenJPEG.EncodeFromImage(mapbmp, true);
1498 asset.Data = data; 1669 }
1499 asset.Description = m_scene.RegionInfo.RegionName; 1670 else
1500 asset.Temporary = false; 1671 data = OpenJPEG.EncodeFromImage(mapbmp, true);
1501 asset.Flags = AssetFlags.Maptile;
1502 1672
1503 // Store the new one 1673 if (data != null && data.Length > 0)
1504 m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName); 1674 {
1505 1675 UUID terrainImageID = UUID.Random();
1506 m_scene.AssetService.Store(asset); 1676
1677 AssetBase asset = new AssetBase(
1678 terrainImageID,
1679 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(),
1680 (sbyte)AssetType.Texture,
1681 m_scene.RegionInfo.RegionID.ToString());
1682 asset.Data = data;
1683 asset.Description = m_scene.RegionInfo.RegionName;
1684 asset.Temporary = false;
1685 asset.Flags = AssetFlags.Maptile;
1686
1687 // Store the new one
1688 m_log.DebugFormat("[WORLD MAP]: Storing map image {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
1689
1690 m_scene.AssetService.Store(asset);
1691
1692 m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID;
1693 needRegionSave = true;
1694 }
1695 }
1696 catch (Exception e)
1697 {
1698 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e);
1699 }
1700 }
1507 1701
1702 // V2/3 still seem to need this, or we are missing something somewhere
1703 byte[] overlay = GenerateOverlay();
1508 if (overlay != null) 1704 if (overlay != null)
1509 { 1705 {
1510 parcelImageID = UUID.Random(); 1706 UUID parcelImageID = UUID.Random();
1511 1707
1512 AssetBase parcels = new AssetBase( 1708 AssetBase parcels = new AssetBase(
1513 parcelImageID, 1709 parcelImageID,
@@ -1520,20 +1716,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1520 parcels.Flags = AssetFlags.Maptile; 1716 parcels.Flags = AssetFlags.Maptile;
1521 1717
1522 m_scene.AssetService.Store(parcels); 1718 m_scene.AssetService.Store(parcels);
1719
1720 m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID;
1721 needRegionSave = true;
1523 } 1722 }
1524 1723
1525 // Switch to the new one 1724 if (needRegionSave)
1526 UUID lastTerrainImageID = m_scene.RegionInfo.RegionSettings.TerrainImageID; 1725 m_scene.RegionInfo.RegionSettings.Save();
1527 UUID lastParcelImageID = m_scene.RegionInfo.RegionSettings.ParcelImageID;
1528 m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID;
1529 m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID;
1530 m_scene.RegionInfo.RegionSettings.Save();
1531
1532 // Delete the old one
1533 // m_log.DebugFormat("[WORLDMAP]: Deleting old map tile {0}", lastTerrainImageID);
1534 m_scene.AssetService.Delete(lastTerrainImageID.ToString());
1535 if (lastParcelImageID != UUID.Zero)
1536 m_scene.AssetService.Delete(lastParcelImageID.ToString());
1537 } 1726 }
1538 1727
1539 private void MakeRootAgent(ScenePresence avatar) 1728 private void MakeRootAgent(ScenePresence avatar)
@@ -1553,6 +1742,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1553 { 1742 {
1554 m_rootAgents.Remove(avatar.UUID); 1743 m_rootAgents.Remove(avatar.UUID);
1555 } 1744 }
1745
1746 lock (m_mapBlockRequestEvent)
1747 {
1748 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1749 m_mapBlockRequests.Remove(avatar.UUID);
1750 }
1556 } 1751 }
1557 1752
1558 public void OnRegionUp(GridRegion otherRegion) 1753 public void OnRegionUp(GridRegion otherRegion)
@@ -1562,46 +1757,67 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1562 1757
1563 lock (m_blacklistedregions) 1758 lock (m_blacklistedregions)
1564 { 1759 {
1565 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1760 if (m_blacklistedregions.Contains(regionhandle))
1566 m_blacklistedregions.Remove(regionhandle); 1761 m_blacklistedregions.Remove(regionhandle);
1567 } 1762 }
1568 1763
1569 lock (m_blacklistedurls) 1764 lock (m_blacklistedurls)
1570 { 1765 {
1571 if (m_blacklistedurls.ContainsKey(httpserver)) 1766 if (m_blacklistedurls.Contains(httpserver))
1572 m_blacklistedurls.Remove(httpserver); 1767 m_blacklistedurls.Remove(httpserver);
1573 } 1768 }
1574 1769
1575 lock (m_cachedRegionMapItemsAddress) 1770 lock (m_cachedRegionMapItemsAddress)
1576 { 1771 {
1577 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 1772 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle,
1578 m_cachedRegionMapItemsAddress.Remove(regionhandle); 1773 httpserver, 5.0 * expireBlackListTime);
1579 } 1774 }
1580 } 1775 }
1581 1776
1582 private Byte[] GenerateOverlay() 1777 private Byte[] GenerateOverlay()
1583 { 1778 {
1779 int landTileSize = LandManagementModule.LandUnit;
1780
1584 // These need to be ints for bitmap generation 1781 // These need to be ints for bitmap generation
1585 int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX; 1782 int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
1586 int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
1587
1588 int landTileSize = LandManagementModule.LandUnit;
1589 int regionLandTilesX = regionSizeX / landTileSize; 1783 int regionLandTilesX = regionSizeX / landTileSize;
1784
1785 int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
1590 int regionLandTilesY = regionSizeY / landTileSize; 1786 int regionLandTilesY = regionSizeY / landTileSize;
1591 1787
1592 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY)) 1788 bool landForSale = false;
1789 ILandObject land;
1790
1791 // scan terrain avoiding potencial merges of large bitmaps
1792 //TODO create the sell bitmap at landchannel / landmaster ?
1793 // and auction also, still not suported
1794
1795 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY];
1796 for (int x = 0, xx = 0; x < regionLandTilesX; x++ ,xx += landTileSize)
1593 { 1797 {
1594 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY]; 1798 for (int y = 0, yy = 0; y < regionLandTilesY; y++, yy += landTileSize)
1595 for (int x = 0; x < regionLandTilesX; x++)
1596 { 1799 {
1597 for (int y = 0; y < regionLandTilesY; y++) 1800 land = m_scene.LandChannel.GetLandObject(xx, yy);
1801 if (land != null && (land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1802 {
1803 saleBitmap[x, y] = true;
1804 landForSale = true;
1805 }
1806 else
1598 saleBitmap[x, y] = false; 1807 saleBitmap[x, y] = false;
1599 } 1808 }
1809 }
1600 1810
1601 bool landForSale = false; 1811 if (!landForSale)
1812 {
1813 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1814 return null;
1815 }
1602 1816
1603 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); 1817 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1604 1818
1819 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY))
1820 {
1605 Color background = Color.FromArgb(0, 0, 0, 0); 1821 Color background = Color.FromArgb(0, 0, 0, 0);
1606 1822
1607 using (Graphics g = Graphics.FromImage(overlay)) 1823 using (Graphics g = Graphics.FromImage(overlay))
@@ -1609,36 +1825,19 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1609 using (SolidBrush transparent = new SolidBrush(background)) 1825 using (SolidBrush transparent = new SolidBrush(background))
1610 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY); 1826 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY);
1611 1827
1612 foreach (ILandObject land in parcels) 1828 // make it a bit transparent
1613 { 1829 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(192, 249, 223, 9)))
1614 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1615 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1616 {
1617 landForSale = true;
1618
1619 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
1620 }
1621 }
1622
1623 if (!landForSale)
1624 { 1830 {
1625 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName); 1831 for (int x = 0; x < regionLandTilesX; x++)
1626 return null;
1627 }
1628
1629 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1630
1631 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)))
1632 {
1633 for (int x = 0 ; x < regionLandTilesX ; x++)
1634 { 1832 {
1635 for (int y = 0 ; y < regionLandTilesY ; y++) 1833 for (int y = 0; y < regionLandTilesY; y++)
1636 { 1834 {
1637 if (saleBitmap[x, y]) 1835 if (saleBitmap[x, y])
1638 g.FillRectangle( 1836 g.FillRectangle(
1639 yellow, x * landTileSize, 1837 yellow,
1640 regionSizeX - landTileSize - (y * landTileSize), 1838 x * landTileSize,
1641 landTileSize, 1839 regionSizeX - landTileSize - (y * landTileSize),
1840 landTileSize,
1642 landTileSize); 1841 landTileSize);
1643 } 1842 }
1644 } 1843 }
@@ -1659,7 +1858,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1659 } 1858 }
1660 } 1859 }
1661 1860
1662 public struct MapRequestState 1861 public class MapRequestState
1663 { 1862 {
1664 public UUID agentID; 1863 public UUID agentID;
1665 public uint flags; 1864 public uint flags;
@@ -1668,4 +1867,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1668 public uint itemtype; 1867 public uint itemtype;
1669 public ulong regionhandle; 1868 public ulong regionhandle;
1670 } 1869 }
1870
1871 public struct MapBlockRequestData
1872 {
1873 public IClientAPI client;
1874 public int minX;
1875 public int minY;
1876 public int maxX;
1877 public int maxY;
1878 public uint flags;
1879 }
1671} 1880}