diff options
author | UbitUmarov | 2015-08-24 17:05:16 +0100 |
---|---|---|
committer | UbitUmarov | 2015-08-24 17:05:16 +0100 |
commit | 3829df10595911de9ed1ce2f7b6cdd205828f8d0 (patch) | |
tree | d95d15c35695f6fa4dc4a6623294b307a7aee493 | |
parent | rename ImapTileModule as IMAPImageUploadModule to match core (diff) | |
download | opensim-SC-3829df10595911de9ed1ce2f7b6cdd205828f8d0.zip opensim-SC-3829df10595911de9ed1ce2f7b6cdd205828f8d0.tar.gz opensim-SC-3829df10595911de9ed1ce2f7b6cdd205828f8d0.tar.bz2 opensim-SC-3829df10595911de9ed1ce2f7b6cdd205828f8d0.tar.xz |
try to implement core load oar options
9 files changed, 539 insertions, 207 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index c416e88..589307a 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs | |||
@@ -1619,8 +1619,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
1619 | } | 1619 | } |
1620 | 1620 | ||
1621 | IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>(); | 1621 | IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>(); |
1622 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); | ||
1623 | if (mergeOar) archiveOptions.Add("merge", null); | ||
1624 | if (skipAssets) archiveOptions.Add("skipAssets", null); | ||
1622 | if (archiver != null) | 1625 | if (archiver != null) |
1623 | archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty); | 1626 | archiver.DearchiveRegion(filename, Guid.Empty, archiveOptions); |
1624 | else | 1627 | else |
1625 | throw new Exception("Archiver module not present for scene"); | 1628 | throw new Exception("Archiver module not present for scene"); |
1626 | 1629 | ||
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index b9b9cd0..1e6ef3b 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -267,12 +267,26 @@ namespace OpenSim | |||
267 | SavePrimsXml2); | 267 | SavePrimsXml2); |
268 | 268 | ||
269 | m_console.Commands.AddCommand("Archiving", false, "load oar", | 269 | m_console.Commands.AddCommand("Archiving", false, "load oar", |
270 | "load oar [--merge] [--skip-assets] [<OAR path>]", | 270 | |
271 | "load oar [--merge] [--skip-assets]" | ||
272 | + " [--default-user \"User Name\"]" | ||
273 | + " [--force-terrain] [--force-parcels]" | ||
274 | + " [--no-objects]" | ||
275 | + " [--rotation degrees] [--rotation-center \"<x,y,z>\"]" | ||
276 | + " [--displacement \"<x,y,z>\"]" | ||
277 | + " [<OAR path>]", | ||
271 | "Load a region's data from an OAR archive.", | 278 | "Load a region's data from an OAR archive.", |
272 | "--merge will merge the OAR with the existing scene." + Environment.NewLine | 279 | "--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading).\n" |
273 | + "--skip-assets will load the OAR but ignore the assets it contains." + Environment.NewLine | 280 | + "--default-user will use this user for any objects with an owner whose UUID is not found in the grid.\n" |
274 | + "The path can be either a filesystem location or a URI." | 281 | + "--displacement will add this value to the position of every object loaded.\n" |
275 | + " If this is not given then the command looks for an OAR named region.oar in the current directory.", | 282 | + "--force-terrain forces the loading of terrain from the oar (undoes suppression done by --merge).\n" |
283 | + "--force-parcels forces the loading of parcels from the oar (undoes suppression done by --merge).\n" | ||
284 | + "--no-objects suppresses the addition of any objects (good for loading only the terrain).\n" | ||
285 | + "--rotation specified rotation to be applied to the oar. Specified in degrees.\n" | ||
286 | + "--rotation-center Location (relative to original OAR) to apply rotation. Default is <128,128,0>.\n" | ||
287 | + "--skip-assets will load the OAR but ignore the assets it contains.\n\n" | ||
288 | + "The path can be either a filesystem location or a URI.\n" | ||
289 | + " If this is not given then the command looks for an OAR named region.oar in the current directory.", | ||
276 | LoadOar); | 290 | LoadOar); |
277 | 291 | ||
278 | m_console.Commands.AddCommand("Archiving", false, "save oar", | 292 | m_console.Commands.AddCommand("Archiving", false, "save oar", |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index efc4998..5d41125 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | |||
@@ -100,10 +100,37 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
100 | protected bool m_merge; | 100 | protected bool m_merge; |
101 | 101 | ||
102 | /// <value> | 102 | /// <value> |
103 | /// If true, force the loading of terrain from the oar file | ||
104 | /// </value> | ||
105 | protected bool m_forceTerrain; | ||
106 | |||
107 | /// <value> | ||
108 | /// If true, force the loading of parcels from the oar file | ||
109 | /// </value> | ||
110 | protected bool m_forceParcels; | ||
111 | |||
112 | /// <value> | ||
103 | /// Should we ignore any assets when reloading the archive? | 113 | /// Should we ignore any assets when reloading the archive? |
104 | /// </value> | 114 | /// </value> |
105 | protected bool m_skipAssets; | 115 | protected bool m_skipAssets; |
106 | 116 | ||
117 | /// <value> | ||
118 | /// Displacement added to each object as it is added to the world | ||
119 | /// </value> | ||
120 | protected Vector3 m_displacement = Vector3.Zero; | ||
121 | |||
122 | /// <value> | ||
123 | /// Rotation (in radians) to apply to the objects as they are loaded. | ||
124 | /// </value> | ||
125 | protected float m_rotation = 0f; | ||
126 | |||
127 | /// <value> | ||
128 | /// Center around which to apply the rotation relative to the origional oar position | ||
129 | /// </value> | ||
130 | protected Vector3 m_rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f); | ||
131 | |||
132 | protected bool m_noObjects = false; | ||
133 | |||
107 | /// <summary> | 134 | /// <summary> |
108 | /// Used to cache lookups for valid uuids. | 135 | /// Used to cache lookups for valid uuids. |
109 | /// </summary> | 136 | /// </summary> |
@@ -131,11 +158,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
131 | 158 | ||
132 | private IAssetService m_assetService = null; | 159 | private IAssetService m_assetService = null; |
133 | 160 | ||
161 | private UUID m_defaultUser; | ||
134 | 162 | ||
135 | public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) | 163 | public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options) |
136 | { | 164 | { |
137 | m_rootScene = scene; | 165 | m_rootScene = scene; |
138 | 166 | ||
167 | if (options.ContainsKey("default-user")) | ||
168 | { | ||
169 | m_defaultUser = (UUID)options["default-user"]; | ||
170 | m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString()); | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; | ||
175 | } | ||
176 | |||
139 | m_loadPath = loadPath; | 177 | m_loadPath = loadPath; |
140 | try | 178 | try |
141 | { | 179 | { |
@@ -148,28 +186,42 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
148 | + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); | 186 | + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); |
149 | m_log.Error(e); | 187 | m_log.Error(e); |
150 | } | 188 | } |
151 | 189 | ||
152 | m_errorMessage = String.Empty; | 190 | m_errorMessage = String.Empty; |
153 | m_merge = merge; | 191 | |
154 | m_skipAssets = skipAssets; | 192 | m_merge = options.ContainsKey("merge"); |
193 | m_forceTerrain = options.ContainsKey("force-terrain"); | ||
194 | m_forceParcels = options.ContainsKey("force-parcels"); | ||
195 | m_noObjects = options.ContainsKey("no-objects"); | ||
196 | m_skipAssets = options.ContainsKey("skipAssets"); | ||
155 | m_requestId = requestId; | 197 | m_requestId = requestId; |
198 | m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero; | ||
199 | m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f; | ||
200 | m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"] | ||
201 | : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f); | ||
156 | 202 | ||
157 | // Zero can never be a valid user id | 203 | m_requestId = requestId; |
204 | |||
205 | // Zero can never be a valid user id (or group) | ||
158 | m_validUserUuids[UUID.Zero] = false; | 206 | m_validUserUuids[UUID.Zero] = false; |
207 | m_validGroupUuids[UUID.Zero] = false; | ||
208 | |||
159 | 209 | ||
160 | m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>(); | 210 | m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>(); |
161 | m_assetService = m_rootScene.AssetService; | 211 | m_assetService = m_rootScene.AssetService; |
162 | } | 212 | } |
163 | 213 | ||
164 | public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) | 214 | public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object> options) |
165 | { | 215 | { |
166 | m_rootScene = scene; | 216 | m_rootScene = scene; |
167 | m_loadPath = null; | 217 | m_loadPath = null; |
168 | m_loadStream = loadStream; | 218 | m_loadStream = loadStream; |
169 | m_merge = merge; | 219 | m_skipAssets = options.ContainsKey("skipAssets"); |
170 | m_skipAssets = skipAssets; | 220 | m_merge = options.ContainsKey("merge"); |
171 | m_requestId = requestId; | 221 | m_requestId = requestId; |
172 | 222 | ||
223 | m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; | ||
224 | |||
173 | // Zero can never be a valid user id | 225 | // Zero can never be a valid user id |
174 | m_validUserUuids[UUID.Zero] = false; | 226 | m_validUserUuids[UUID.Zero] = false; |
175 | 227 | ||
@@ -229,7 +281,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
229 | 281 | ||
230 | // Process the file | 282 | // Process the file |
231 | 283 | ||
232 | if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) | 284 | if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH) && !m_noObjects) |
233 | { | 285 | { |
234 | sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); | 286 | sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); |
235 | } | 287 | } |
@@ -243,15 +295,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
243 | if ((successfulAssetRestores + failedAssetRestores) % 250 == 0) | 295 | if ((successfulAssetRestores + failedAssetRestores) % 250 == 0) |
244 | m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets..."); | 296 | m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets..."); |
245 | } | 297 | } |
246 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) | 298 | else if ((!m_merge || m_forceTerrain) && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) |
247 | { | 299 | { |
248 | LoadTerrain(scene, filePath, data); | 300 | LoadTerrain(scene, filePath, data); |
249 | } | 301 | } |
250 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) | 302 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) |
251 | { | 303 | { |
252 | LoadRegionSettings(scene, filePath, data, dearchivedScenes); | 304 | LoadRegionSettings(scene, filePath, data, dearchivedScenes); |
253 | } | 305 | } |
254 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) | 306 | else if ((!m_merge || m_forceParcels) && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) |
255 | { | 307 | { |
256 | sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); | 308 | sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); |
257 | } | 309 | } |
@@ -422,6 +474,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
422 | // Reload serialized prims | 474 | // Reload serialized prims |
423 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); | 475 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); |
424 | 476 | ||
477 | OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation); | ||
478 | |||
425 | UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; | 479 | UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; |
426 | 480 | ||
427 | IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); | 481 | IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); |
@@ -445,6 +499,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
445 | 499 | ||
446 | SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); | 500 | SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); |
447 | 501 | ||
502 | // Happily this does not do much to the object since it hasn't been added to the scene yet | ||
503 | if (!sceneObject.IsAttachment) | ||
504 | { | ||
505 | if (m_displacement != Vector3.Zero || m_rotation != 0f) | ||
506 | { | ||
507 | Vector3 pos = sceneObject.AbsolutePosition; | ||
508 | if (m_rotation != 0f) | ||
509 | { | ||
510 | // Rotate the object | ||
511 | sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation; | ||
512 | // Get object position relative to rotation axis | ||
513 | Vector3 offset = pos - m_rotationCenter; | ||
514 | // Rotate the object position | ||
515 | offset *= rot; | ||
516 | // Restore the object position back to relative to the region | ||
517 | pos = m_rotationCenter + offset; | ||
518 | } | ||
519 | if (m_displacement != Vector3.Zero) | ||
520 | { | ||
521 | pos += m_displacement; | ||
522 | } | ||
523 | sceneObject.AbsolutePosition = pos; | ||
524 | } | ||
525 | } | ||
526 | |||
448 | bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); | 527 | bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); |
449 | 528 | ||
450 | // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned | 529 | // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned |
@@ -460,76 +539,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
460 | oldTelehubUUID = UUID.Zero; | 539 | oldTelehubUUID = UUID.Zero; |
461 | } | 540 | } |
462 | 541 | ||
463 | // Try to retain the original creator/owner/lastowner if their uuid is present on this grid | 542 | ModifySceneObject(scene, sceneObject); |
464 | // or creator data is present. Otherwise, use the estate owner instead. | ||
465 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
466 | { | ||
467 | if (string.IsNullOrEmpty(part.CreatorData)) | ||
468 | { | ||
469 | if (!ResolveUserUuid(scene, part.CreatorID)) | ||
470 | part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
471 | } | ||
472 | if (UserManager != null) | ||
473 | UserManager.AddUser(part.CreatorID, part.CreatorData); | ||
474 | |||
475 | if (!ResolveUserUuid(scene, part.OwnerID)) | ||
476 | part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
477 | 543 | ||
478 | if (!ResolveUserUuid(scene, part.LastOwnerID)) | ||
479 | part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
480 | |||
481 | if (!ResolveGroupUuid(part.GroupID)) | ||
482 | part.GroupID = UUID.Zero; | ||
483 | |||
484 | // And zap any troublesome sit target information | ||
485 | // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); | ||
486 | // part.SitTargetPosition = new Vector3(0, 0, 0); | ||
487 | |||
488 | // Fix ownership/creator of inventory items | ||
489 | // Not doing so results in inventory items | ||
490 | // being no copy/no mod for everyone | ||
491 | lock (part.TaskInventory) | ||
492 | { | ||
493 | if (!ResolveUserUuid(scene, part.CreatorID)) | ||
494 | part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
495 | |||
496 | if (!ResolveUserUuid(scene, part.OwnerID)) | ||
497 | part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
498 | |||
499 | if (!ResolveUserUuid(scene, part.LastOwnerID)) | ||
500 | part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
501 | |||
502 | // And zap any troublesome sit target information | ||
503 | part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); | ||
504 | part.SitTargetPosition = new Vector3(0, 0, 0); | ||
505 | |||
506 | // Fix ownership/creator of inventory items | ||
507 | // Not doing so results in inventory items | ||
508 | // being no copy/no mod for everyone | ||
509 | part.TaskInventory.LockItemsForRead(true); | ||
510 | TaskInventoryDictionary inv = part.TaskInventory; | ||
511 | foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) | ||
512 | { | ||
513 | if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) | ||
514 | { | ||
515 | kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
516 | } | ||
517 | |||
518 | if (string.IsNullOrEmpty(kvp.Value.CreatorData)) | ||
519 | { | ||
520 | if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) | ||
521 | kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; | ||
522 | } | ||
523 | |||
524 | if (UserManager != null) | ||
525 | UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); | ||
526 | |||
527 | if (!ResolveGroupUuid(kvp.Value.GroupID)) | ||
528 | kvp.Value.GroupID = UUID.Zero; | ||
529 | } | ||
530 | part.TaskInventory.LockItemsForRead(false); | ||
531 | } | ||
532 | } | ||
533 | 544 | ||
534 | if (scene.AddRestoredSceneObject(sceneObject, true, false)) | 545 | if (scene.AddRestoredSceneObject(sceneObject, true, false)) |
535 | { | 546 | { |
@@ -553,7 +564,76 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
553 | scene.RegionInfo.RegionSettings.ClearSpawnPoints(); | 564 | scene.RegionInfo.RegionSettings.ClearSpawnPoints(); |
554 | } | 565 | } |
555 | } | 566 | } |
556 | 567 | ||
568 | /// <summary> | ||
569 | /// Optionally modify a loaded SceneObjectGroup. Currently this just ensures that the | ||
570 | /// User IDs and Group IDs are valid, but other manipulations could be done as well. | ||
571 | /// </summary> | ||
572 | private void ModifySceneObject(Scene scene, SceneObjectGroup sceneObject) | ||
573 | { | ||
574 | // Try to retain the original creator/owner/lastowner if their uuid is present on this grid | ||
575 | // or creator data is present. Otherwise, use the estate owner instead. | ||
576 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
577 | { | ||
578 | if (string.IsNullOrEmpty(part.CreatorData)) | ||
579 | { | ||
580 | if (!ResolveUserUuid(scene, part.CreatorID)) | ||
581 | part.CreatorID = m_defaultUser; | ||
582 | } | ||
583 | if (UserManager != null) | ||
584 | UserManager.AddUser(part.CreatorID, part.CreatorData); | ||
585 | |||
586 | if (!(ResolveUserUuid(scene, part.OwnerID) || ResolveGroupUuid(part.OwnerID))) | ||
587 | part.OwnerID = m_defaultUser; | ||
588 | |||
589 | if (!(ResolveUserUuid(scene, part.LastOwnerID) || ResolveGroupUuid(part.LastOwnerID))) | ||
590 | part.LastOwnerID = m_defaultUser; | ||
591 | |||
592 | if (!ResolveGroupUuid(part.GroupID)) | ||
593 | part.GroupID = UUID.Zero; | ||
594 | |||
595 | // And zap any troublesome sit target information | ||
596 | // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); | ||
597 | // part.SitTargetPosition = new Vector3(0, 0, 0); | ||
598 | |||
599 | // Fix ownership/creator of inventory items | ||
600 | // Not doing so results in inventory items | ||
601 | // being no copy/no mod for everyone | ||
602 | lock (part.TaskInventory) | ||
603 | { | ||
604 | // And zap any troublesome sit target information | ||
605 | part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); | ||
606 | part.SitTargetPosition = new Vector3(0, 0, 0); | ||
607 | |||
608 | // Fix ownership/creator of inventory items | ||
609 | // Not doing so results in inventory items | ||
610 | // being no copy/no mod for everyone | ||
611 | part.TaskInventory.LockItemsForRead(true); | ||
612 | TaskInventoryDictionary inv = part.TaskInventory; | ||
613 | foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) | ||
614 | { | ||
615 | if (!(ResolveUserUuid(scene, kvp.Value.OwnerID) || ResolveGroupUuid(kvp.Value.OwnerID))) | ||
616 | { | ||
617 | kvp.Value.OwnerID = m_defaultUser; | ||
618 | } | ||
619 | |||
620 | if (string.IsNullOrEmpty(kvp.Value.CreatorData)) | ||
621 | { | ||
622 | if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) | ||
623 | kvp.Value.CreatorID = m_defaultUser; | ||
624 | } | ||
625 | |||
626 | if (UserManager != null) | ||
627 | UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); | ||
628 | |||
629 | if (!ResolveGroupUuid(kvp.Value.GroupID)) | ||
630 | kvp.Value.GroupID = UUID.Zero; | ||
631 | } | ||
632 | part.TaskInventory.LockItemsForRead(false); | ||
633 | } | ||
634 | } | ||
635 | } | ||
636 | |||
557 | /// <summary> | 637 | /// <summary> |
558 | /// Load serialized parcels. | 638 | /// Load serialized parcels. |
559 | /// </summary> | 639 | /// </summary> |
@@ -567,14 +647,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
567 | foreach (string serialisedParcel in serialisedParcels) | 647 | foreach (string serialisedParcel in serialisedParcels) |
568 | { | 648 | { |
569 | LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); | 649 | LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); |
570 | 650 | ||
651 | if (m_displacement != Vector3.Zero) | ||
652 | { | ||
653 | Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f); | ||
654 | parcel.AABBMin += parcelDisp; | ||
655 | parcel.AABBMax += parcelDisp; | ||
656 | } | ||
657 | |||
571 | // Validate User and Group UUID's | 658 | // Validate User and Group UUID's |
572 | 659 | ||
573 | if (parcel.IsGroupOwned) | 660 | if (parcel.IsGroupOwned) |
574 | { | 661 | { |
575 | if (!ResolveGroupUuid(parcel.GroupID)) | 662 | if (!ResolveGroupUuid(parcel.GroupID)) |
576 | { | 663 | { |
577 | parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; | 664 | parcel.OwnerID = m_defaultUser; |
578 | parcel.GroupID = UUID.Zero; | 665 | parcel.GroupID = UUID.Zero; |
579 | parcel.IsGroupOwned = false; | 666 | parcel.IsGroupOwned = false; |
580 | } | 667 | } |
@@ -582,7 +669,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
582 | else | 669 | else |
583 | { | 670 | { |
584 | if (!ResolveUserUuid(scene, parcel.OwnerID)) | 671 | if (!ResolveUserUuid(scene, parcel.OwnerID)) |
585 | parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; | 672 | parcel.OwnerID = m_defaultUser; |
586 | 673 | ||
587 | if (!ResolveGroupUuid(parcel.GroupID)) | 674 | if (!ResolveGroupUuid(parcel.GroupID)) |
588 | parcel.GroupID = UUID.Zero; | 675 | parcel.GroupID = UUID.Zero; |
@@ -702,8 +789,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
702 | sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; | 789 | sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; |
703 | 790 | ||
704 | if (assetType == (sbyte)AssetType.Unknown) | 791 | if (assetType == (sbyte)AssetType.Unknown) |
792 | { | ||
705 | m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid); | 793 | m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid); |
706 | 794 | } | |
795 | else if (assetType == (sbyte)AssetType.Object) | ||
796 | { | ||
797 | data = SceneObjectSerializer.ModifySerializedObject(UUID.Parse(uuid), data, | ||
798 | sog => | ||
799 | { | ||
800 | ModifySceneObject(m_rootScene, sog); | ||
801 | return true; | ||
802 | }); | ||
803 | |||
804 | if (data == null) | ||
805 | return false; | ||
806 | } | ||
707 | //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); | 807 | //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); |
708 | 808 | ||
709 | AssetBase asset = new AssetBase(new UUID(uuid), String.Empty, assetType, UUID.Zero.ToString()); | 809 | AssetBase asset = new AssetBase(new UUID(uuid), String.Empty, assetType, UUID.Zero.ToString()); |
@@ -825,10 +925,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
825 | private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) | 925 | private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) |
826 | { | 926 | { |
827 | ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); | 927 | ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); |
828 | 928 | ||
829 | MemoryStream ms = new MemoryStream(data); | 929 | using (MemoryStream ms = new MemoryStream(data)) |
830 | terrainModule.LoadFromStream(terrainPath, ms); | 930 | { |
831 | ms.Close(); | 931 | if (m_displacement != Vector3.Zero || m_rotation != 0f) |
932 | { | ||
933 | Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y); | ||
934 | terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms); | ||
935 | } | ||
936 | else | ||
937 | { | ||
938 | terrainModule.LoadFromStream(terrainPath, ms); | ||
939 | } | ||
940 | } | ||
832 | 941 | ||
833 | m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath); | 942 | m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath); |
834 | 943 | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 1be6386..8a8e392 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs | |||
@@ -38,6 +38,8 @@ using OpenSim.Framework.Console; | |||
38 | using OpenSim.Region.Framework.Interfaces; | 38 | using OpenSim.Region.Framework.Interfaces; |
39 | using OpenSim.Region.Framework.Scenes; | 39 | using OpenSim.Region.Framework.Scenes; |
40 | 40 | ||
41 | using OpenMetaverse; | ||
42 | |||
41 | namespace OpenSim.Region.CoreModules.World.Archiver | 43 | namespace OpenSim.Region.CoreModules.World.Archiver |
42 | { | 44 | { |
43 | /// <summary> | 45 | /// <summary> |
@@ -101,9 +103,64 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
101 | { | 103 | { |
102 | bool mergeOar = false; | 104 | bool mergeOar = false; |
103 | bool skipAssets = false; | 105 | bool skipAssets = false; |
104 | 106 | bool forceTerrain = false; | |
105 | OptionSet options = new OptionSet().Add("m|merge", delegate (string v) { mergeOar = v != null; }); | 107 | bool forceParcels = false; |
106 | options.Add("s|skip-assets", delegate (string v) { skipAssets = v != null; }); | 108 | bool noObjects = false; |
109 | Vector3 displacement = new Vector3(0f, 0f, 0f); | ||
110 | String defaultUser = ""; | ||
111 | float rotation = 0f; | ||
112 | Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0); | ||
113 | |||
114 | OptionSet options = new OptionSet(); | ||
115 | options.Add("m|merge", delegate(string v) { mergeOar = (v != null); }); | ||
116 | options.Add("s|skip-assets", delegate(string v) { skipAssets = (v != null); }); | ||
117 | options.Add("force-terrain", delegate(string v) { forceTerrain = (v != null); }); | ||
118 | options.Add("forceterrain", delegate(string v) { forceTerrain = (v != null); }); // downward compatibility | ||
119 | options.Add("force-parcels", delegate(string v) { forceParcels = (v != null); }); | ||
120 | options.Add("forceparcels", delegate(string v) { forceParcels = (v != null); }); // downward compatibility | ||
121 | options.Add("no-objects", delegate(string v) { noObjects = (v != null); }); | ||
122 | options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; }); | ||
123 | options.Add("displacement=", delegate(string v) | ||
124 | { | ||
125 | try | ||
126 | { | ||
127 | displacement = v == null ? Vector3.Zero : Vector3.Parse(v); | ||
128 | } | ||
129 | catch | ||
130 | { | ||
131 | m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing displacement"); | ||
132 | m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --displacement \"<128,128,0>\""); | ||
133 | return; | ||
134 | } | ||
135 | }); | ||
136 | options.Add("rotation=", delegate(string v) | ||
137 | { | ||
138 | try | ||
139 | { | ||
140 | rotation = v == null ? 0f : float.Parse(v); | ||
141 | } | ||
142 | catch | ||
143 | { | ||
144 | m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation"); | ||
145 | m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45"); | ||
146 | return; | ||
147 | } | ||
148 | // Convert to radians for internals | ||
149 | rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI; | ||
150 | }); | ||
151 | options.Add("rotation-center=", delegate(string v) | ||
152 | { | ||
153 | try | ||
154 | { | ||
155 | rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v); | ||
156 | } | ||
157 | catch | ||
158 | { | ||
159 | m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation displacement"); | ||
160 | m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --rotation-center \"<128,128,0>\""); | ||
161 | return; | ||
162 | } | ||
163 | }); | ||
107 | 164 | ||
108 | // Send a message to the region ready module | 165 | // Send a message to the region ready module |
109 | /* bluewall* Disable this for the time being | 166 | /* bluewall* Disable this for the time being |
@@ -122,13 +179,44 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
122 | // foreach (string param in mainParams) | 179 | // foreach (string param in mainParams) |
123 | // m_log.DebugFormat("GOT PARAM [{0}]", param); | 180 | // m_log.DebugFormat("GOT PARAM [{0}]", param); |
124 | 181 | ||
182 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); | ||
183 | if (mergeOar) archiveOptions.Add("merge", null); | ||
184 | if (skipAssets) archiveOptions.Add("skipAssets", null); | ||
185 | if (forceTerrain) archiveOptions.Add("force-terrain", null); | ||
186 | if (forceParcels) archiveOptions.Add("force-parcels", null); | ||
187 | if (noObjects) archiveOptions.Add("no-objects", null); | ||
188 | if (defaultUser != "") | ||
189 | { | ||
190 | UUID defaultUserUUID = UUID.Zero; | ||
191 | try | ||
192 | { | ||
193 | defaultUserUUID = Scene.UserManagementModule.GetUserIdByName(defaultUser); | ||
194 | } | ||
195 | catch | ||
196 | { | ||
197 | m_log.ErrorFormat("[ARCHIVER MODULE] default user must be in format \"First Last\"", defaultUser); | ||
198 | } | ||
199 | if (defaultUserUUID == UUID.Zero) | ||
200 | { | ||
201 | m_log.ErrorFormat("[ARCHIVER MODULE] cannot find specified default user {0}", defaultUser); | ||
202 | return; | ||
203 | } | ||
204 | else | ||
205 | { | ||
206 | archiveOptions.Add("default-user", defaultUserUUID); | ||
207 | } | ||
208 | } | ||
209 | archiveOptions.Add("displacement", displacement); | ||
210 | archiveOptions.Add("rotation", rotation); | ||
211 | archiveOptions.Add("rotation-center", rotationCenter); | ||
212 | |||
125 | if (mainParams.Count > 2) | 213 | if (mainParams.Count > 2) |
126 | { | 214 | { |
127 | DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); | 215 | DearchiveRegion(mainParams[2], Guid.Empty, archiveOptions); |
128 | } | 216 | } |
129 | else | 217 | else |
130 | { | 218 | { |
131 | DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, mergeOar, skipAssets, Guid.Empty); | 219 | DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, Guid.Empty, archiveOptions); |
132 | } | 220 | } |
133 | } | 221 | } |
134 | 222 | ||
@@ -198,25 +286,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
198 | 286 | ||
199 | public void DearchiveRegion(string loadPath) | 287 | public void DearchiveRegion(string loadPath) |
200 | { | 288 | { |
201 | DearchiveRegion(loadPath, false, false, Guid.Empty); | 289 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); |
290 | DearchiveRegion(loadPath, Guid.Empty, archiveOptions); | ||
202 | } | 291 | } |
203 | 292 | ||
204 | public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId) | 293 | public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string, object> options) |
205 | { | 294 | { |
206 | m_log.InfoFormat( | 295 | m_log.InfoFormat( |
207 | "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath); | 296 | "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath); |
208 | 297 | ||
209 | new ArchiveReadRequest(Scene, loadPath, merge, skipAssets, requestId).DearchiveRegion(); | 298 | new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion(); |
210 | } | 299 | } |
211 | 300 | ||
212 | public void DearchiveRegion(Stream loadStream) | 301 | public void DearchiveRegion(Stream loadStream) |
213 | { | 302 | { |
214 | DearchiveRegion(loadStream, false, false, Guid.Empty); | 303 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); |
304 | DearchiveRegion(loadStream, Guid.Empty, archiveOptions); | ||
215 | } | 305 | } |
216 | 306 | ||
217 | public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId) | 307 | public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options) |
218 | { | 308 | { |
219 | new ArchiveReadRequest(Scene, loadStream, merge, skipAssets, requestId).DearchiveRegion(); | 309 | new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion(); |
220 | } | 310 | } |
221 | } | 311 | } |
222 | } | 312 | } |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index eec1cec..53f41f9 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | |||
@@ -224,8 +224,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
224 | 224 | ||
225 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); | 225 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); |
226 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); | 226 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); |
227 | 227 | ||
228 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); | 228 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); |
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); |
@@ -308,8 +309,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
308 | 309 | ||
309 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); | 310 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); |
310 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); | 311 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); |
311 | 312 | ||
312 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); | 313 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); |
314 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); | ||
313 | arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); | 315 | arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); |
314 | 316 | ||
315 | Assert.That(arr.ControlFileLoaded, Is.True); | 317 | Assert.That(arr.ControlFileLoaded, Is.True); |
@@ -752,7 +754,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
752 | byte[] archive = archiveWriteStream.ToArray(); | 754 | byte[] archive = archiveWriteStream.ToArray(); |
753 | MemoryStream archiveReadStream = new MemoryStream(archive); | 755 | MemoryStream archiveReadStream = new MemoryStream(archive); |
754 | 756 | ||
755 | m_archiverModule.DearchiveRegion(archiveReadStream, true, false, Guid.Empty); | 757 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); |
758 | archiveOptions.Add("merge", null); | ||
759 | m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions); | ||
756 | 760 | ||
757 | SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name); | 761 | SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name); |
758 | Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); | 762 | Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); |
@@ -860,7 +864,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
860 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); | 864 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); |
861 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); | 865 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); |
862 | 866 | ||
863 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); | 867 | Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); |
868 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); | ||
864 | arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); | 869 | arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); |
865 | 870 | ||
866 | Assert.That(arr.ControlFileLoaded, Is.True); | 871 | Assert.That(arr.ControlFileLoaded, Is.True); |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 4aee6a5..83bbf79 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | |||
@@ -570,17 +570,54 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
570 | new_land.LandData.LocalID = newLandLocalID; | 570 | new_land.LandData.LocalID = newLandLocalID; |
571 | 571 | ||
572 | bool[,] landBitmap = new_land.GetLandBitmap(); | 572 | bool[,] landBitmap = new_land.GetLandBitmap(); |
573 | for (int x = 0; x < landBitmap.GetLength(0); x++) | 573 | if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1)) |
574 | { | 574 | { |
575 | for (int y = 0; y < landBitmap.GetLength(1); y++) | 575 | // Going to variable sized regions can cause mismatches |
576 | m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})", | ||
577 | LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1)); | ||
578 | } | ||
579 | else | ||
580 | { | ||
581 | // If other land objects still believe that they occupy any parts of the same space, | ||
582 | // then do not allow the add to proceed. | ||
583 | for (int x = 0; x < landBitmap.GetLength(0); x++) | ||
584 | { | ||
585 | for (int y = 0; y < landBitmap.GetLength(1); y++) | ||
586 | { | ||
587 | if (landBitmap[x, y]) | ||
588 | { | ||
589 | int lastRecordedLandId = m_landIDList[x, y]; | ||
590 | |||
591 | if (lastRecordedLandId > 0) | ||
592 | { | ||
593 | ILandObject lastRecordedLo = m_landList[lastRecordedLandId]; | ||
594 | |||
595 | if (lastRecordedLo.LandBitmap[x, y]) | ||
596 | { | ||
597 | m_log.ErrorFormat( | ||
598 | "{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}", | ||
599 | LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y, | ||
600 | lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name); | ||
601 | |||
602 | return null; | ||
603 | } | ||
604 | } | ||
605 | } | ||
606 | } | ||
607 | } | ||
608 | |||
609 | for (int x = 0; x < landBitmap.GetLength(0); x++) | ||
576 | { | 610 | { |
577 | if (landBitmap[x, y]) | 611 | for (int y = 0; y < landBitmap.GetLength(1); y++) |
578 | { | 612 | { |
579 | // m_log.DebugFormat( | 613 | if (landBitmap[x, y]) |
580 | // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", | 614 | { |
581 | // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); | 615 | // m_log.DebugFormat( |
582 | 616 | // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", | |
583 | m_landIDList[x, y] = newLandLocalID; | 617 | // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); |
618 | |||
619 | m_landIDList[x, y] = newLandLocalID; | ||
620 | } | ||
584 | } | 621 | } |
585 | } | 622 | } |
586 | } | 623 | } |
@@ -693,47 +730,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
693 | /// <returns>Land object at the point supplied</returns> | 730 | /// <returns>Land object at the point supplied</returns> |
694 | public ILandObject GetLandObject(float x_float, float y_float) | 731 | public ILandObject GetLandObject(float x_float, float y_float) |
695 | { | 732 | { |
696 | int x; | 733 | return GetLandObject((int)x_float, (int)y_float, true); |
697 | int y; | ||
698 | |||
699 | if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0) | ||
700 | return null; | ||
701 | |||
702 | try | ||
703 | { | ||
704 | x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit)); | ||
705 | y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit)); | ||
706 | } | ||
707 | catch (OverflowException) | ||
708 | { | ||
709 | return null; | ||
710 | } | ||
711 | |||
712 | if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit) | ||
713 | || y >= (m_scene.RegionInfo.RegionSizeY / landUnit) | ||
714 | || x < 0 | ||
715 | || y < 0) | ||
716 | { | ||
717 | return null; | ||
718 | } | ||
719 | |||
720 | lock (m_landList) | ||
721 | { | ||
722 | // Corner case. If an autoreturn happens during sim startup | ||
723 | // we will come here with the list uninitialized | ||
724 | // | ||
725 | // int landId = m_landIDList[x, y]; | ||
726 | |||
727 | // if (landId == 0) | ||
728 | // m_log.DebugFormat( | ||
729 | // "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}", | ||
730 | // x, y, m_scene.RegionInfo.RegionName); | ||
731 | |||
732 | if (m_landList.ContainsKey(m_landIDList[x, y])) | ||
733 | return m_landList[m_landIDList[x, y]]; | ||
734 | |||
735 | return null; | ||
736 | } | ||
737 | } | 734 | } |
738 | 735 | ||
739 | // if x,y is off region this will return the parcel at cliped x,y | 736 | // if x,y is off region this will return the parcel at cliped x,y |
@@ -768,29 +765,47 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
768 | 765 | ||
769 | public ILandObject GetLandObject(int x, int y) | 766 | public ILandObject GetLandObject(int x, int y) |
770 | { | 767 | { |
768 | return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */); | ||
769 | } | ||
770 | |||
771 | public ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds) | ||
772 | { | ||
771 | if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) | 773 | if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) |
772 | { | 774 | { |
773 | // These exceptions here will cause a lot of complaints from the users specifically because | 775 | // These exceptions here will cause a lot of complaints from the users specifically because |
774 | // they happen every time at border crossings | 776 | // they happen every time at border crossings |
775 | throw new Exception("Error: Parcel not found at point " + x + ", " + y); | 777 | if (returnNullIfLandObjectOutsideBounds) |
778 | return null; | ||
779 | else | ||
780 | throw new Exception("Error: Parcel not found at point " + x + ", " + y); | ||
776 | } | 781 | } |
777 | 782 | ||
778 | lock (m_landIDList) | 783 | lock (m_landIDList) |
779 | { | 784 | { |
780 | try | 785 | try |
781 | { | 786 | { |
782 | //if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4])) | ||
783 | return m_landList[m_landIDList[x / 4, y / 4]]; | 787 | return m_landList[m_landIDList[x / 4, y / 4]]; |
784 | //else | ||
785 | // return null; | ||
786 | } | 788 | } |
787 | catch (IndexOutOfRangeException) | 789 | catch (IndexOutOfRangeException) |
788 | { | 790 | { |
789 | return null; | 791 | return null; |
790 | } | 792 | } |
791 | } | 793 | } |
792 | } | 794 | } |
793 | 795 | ||
796 | // Create a 'parcel is here' bitmap for the parcel identified by the passed landID | ||
797 | private bool[,] CreateBitmapForID(int landID) | ||
798 | { | ||
799 | bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)]; | ||
800 | |||
801 | for (int xx = 0; xx < m_landIDList.GetLength(0); xx++) | ||
802 | for (int yy = 0; yy < m_landIDList.GetLength(0); yy++) | ||
803 | if (m_landIDList[xx, yy] == landID) | ||
804 | ret[xx, yy] = true; | ||
805 | |||
806 | return ret; | ||
807 | } | ||
808 | |||
794 | #endregion | 809 | #endregion |
795 | 810 | ||
796 | #region Parcel Modification | 811 | #region Parcel Modification |
@@ -1432,29 +1447,66 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1432 | 1447 | ||
1433 | public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) | 1448 | public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) |
1434 | { | 1449 | { |
1435 | Dictionary<int, ILandObject> landworkList; | ||
1436 | // move to work pointer since we are deleting it all | ||
1437 | lock (m_landList) | 1450 | lock (m_landList) |
1438 | { | 1451 | { |
1439 | landworkList = m_landList; | 1452 | for (int i = 0; i < data.Count; i++) |
1440 | m_landList = new Dictionary<int, ILandObject>(); | 1453 | IncomingLandObjectFromStorage(data[i]); |
1441 | } | ||
1442 | 1454 | ||
1443 | //Remove all the land objects in the sim and then process our new data | 1455 | // Layer data is in landUnit (4m) chunks |
1444 | foreach (int n in landworkList.Keys) | 1456 | for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); y++) |
1445 | { | 1457 | { |
1446 | m_scene.EventManager.TriggerLandObjectRemoved(landworkList[n].LandData.GlobalID); | 1458 | for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); x++) |
1447 | } | 1459 | { |
1448 | landworkList.Clear(); | 1460 | if (m_landIDList[x, y] == 0) |
1461 | { | ||
1462 | if (m_landList.Count == 1) | ||
1463 | { | ||
1464 | m_log.DebugFormat( | ||
1465 | "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}", | ||
1466 | LogHeader, x, y, m_scene.Name); | ||
1449 | 1467 | ||
1450 | lock (m_landList) | 1468 | int onlyParcelID = 0; |
1451 | { | 1469 | ILandObject onlyLandObject = null; |
1452 | m_landIDList.Initialize(); | 1470 | foreach (KeyValuePair<int, ILandObject> kvp in m_landList) |
1453 | m_landList.Clear(); | 1471 | { |
1454 | } | 1472 | onlyParcelID = kvp.Key; |
1473 | onlyLandObject = kvp.Value; | ||
1474 | break; | ||
1475 | } | ||
1455 | 1476 | ||
1456 | for (int i = 0; i < data.Count; i++) | 1477 | // There is only one parcel. Grow it to fill all the unallocated spaces. |
1457 | IncomingLandObjectFromStorage(data[i]); | 1478 | for (int xx = 0; xx < m_landIDList.GetLength(0); xx++) |
1479 | for (int yy = 0; yy < m_landIDList.GetLength(1); yy++) | ||
1480 | if (m_landIDList[xx, yy] == 0) | ||
1481 | m_landIDList[xx, yy] = onlyParcelID; | ||
1482 | |||
1483 | onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID); | ||
1484 | } | ||
1485 | else if (m_landList.Count > 1) | ||
1486 | { | ||
1487 | m_log.DebugFormat( | ||
1488 | "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}", | ||
1489 | LogHeader, x, y, m_scene.Name); | ||
1490 | |||
1491 | // There are several other parcels so we must create a new one for the unassigned space | ||
1492 | ILandObject newLand = new LandObject(UUID.Zero, false, m_scene); | ||
1493 | // Claim all the unclaimed "0" ids | ||
1494 | newLand.SetLandBitmap(CreateBitmapForID(0)); | ||
1495 | newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; | ||
1496 | newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); | ||
1497 | newLand = AddLandObject(newLand); | ||
1498 | } | ||
1499 | else | ||
1500 | { | ||
1501 | // We should never reach this point as the separate code path when no land data exists should have fired instead. | ||
1502 | m_log.WarnFormat( | ||
1503 | "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", | ||
1504 | LogHeader, m_scene.Name); | ||
1505 | } | ||
1506 | } | ||
1507 | } | ||
1508 | } | ||
1509 | } | ||
1458 | } | 1510 | } |
1459 | 1511 | ||
1460 | public void IncomingLandObjectFromStorage(LandData data) | 1512 | public void IncomingLandObjectFromStorage(LandData data) |
@@ -1464,7 +1516,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1464 | new_land.LandData = data.Copy(); | 1516 | new_land.LandData = data.Copy(); |
1465 | new_land.SetLandBitmapFromByteArray(); | 1517 | new_land.SetLandBitmapFromByteArray(); |
1466 | AddLandObject(new_land); | 1518 | AddLandObject(new_land); |
1467 | new_land.SendLandUpdateToAvatarsOverMe(); | 1519 | // new_land.SendLandUpdateToAvatarsOverMe(); |
1468 | } | 1520 | } |
1469 | 1521 | ||
1470 | public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) | 1522 | public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) |
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs index 3fafc47..ed93916 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs | |||
@@ -29,6 +29,8 @@ using System; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | 30 | using System.IO; |
31 | 31 | ||
32 | using OpenMetaverse; | ||
33 | |||
32 | namespace OpenSim.Region.Framework.Interfaces | 34 | namespace OpenSim.Region.Framework.Interfaces |
33 | { | 35 | { |
34 | /// <summary> | 36 | /// <summary> |
@@ -100,16 +102,11 @@ namespace OpenSim.Region.Framework.Interfaces | |||
100 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. | 102 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. |
101 | /// | 103 | /// |
102 | /// <param name="loadPath"></param> | 104 | /// <param name="loadPath"></param> |
103 | /// <param name="merge"> | ||
104 | /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region | ||
105 | /// settings in the archive will be ignored. | ||
106 | /// </param> | ||
107 | /// <param name="skipAssets"> | ||
108 | /// If true, the archive is loaded without loading any assets contained within it. This is useful if the | ||
109 | /// assets are already known to be present in the grid's asset service. | ||
110 | /// </param> | ||
111 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> | 105 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> |
112 | void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId); | 106 | /// <param name="options"> |
107 | /// Dictionary of options. | ||
108 | /// </param> | ||
109 | void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options); | ||
113 | 110 | ||
114 | /// <summary> | 111 | /// <summary> |
115 | /// Dearchive a region from a stream. This replaces the existing scene. | 112 | /// Dearchive a region from a stream. This replaces the existing scene. |
@@ -127,15 +124,10 @@ namespace OpenSim.Region.Framework.Interfaces | |||
127 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. | 124 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. |
128 | /// | 125 | /// |
129 | /// <param name="loadStream"></param> | 126 | /// <param name="loadStream"></param> |
130 | /// <param name="merge"> | ||
131 | /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region | ||
132 | /// settings in the archive will be ignored. | ||
133 | /// </param> | ||
134 | /// <param name="skipAssets"> | ||
135 | /// If true, the archive is loaded without loading any assets contained within it. This is useful if the | ||
136 | /// assets are already known to be present in the grid's asset service. | ||
137 | /// </param | ||
138 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> | 127 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> |
139 | void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId); | 128 | /// <param name="options"> |
129 | /// Dictionary of options. | ||
130 | /// </param> | ||
131 | void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options); | ||
140 | } | 132 | } |
141 | } | 133 | } |
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs index 4e2f4e1..595e031 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs | |||
@@ -59,6 +59,8 @@ namespace OpenSim.Region.Framework.Interfaces | |||
59 | /// <param name="stream"></param> | 59 | /// <param name="stream"></param> |
60 | void LoadFromStream(string filename, Stream stream); | 60 | void LoadFromStream(string filename, Stream stream); |
61 | void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); | 61 | void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); |
62 | void LoadFromStream(string filename, Vector3 displacement, | ||
63 | float radianRotation, Vector2 rotationDisplacement, Stream stream); | ||
62 | /// <summary> | 64 | /// <summary> |
63 | /// Save a terrain to a stream. | 65 | /// Save a terrain to a stream. |
64 | /// </summary> | 66 | /// </summary> |
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 40e88f1..3d14943 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -299,6 +299,71 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
299 | } | 299 | } |
300 | } | 300 | } |
301 | 301 | ||
302 | /// <summary> | ||
303 | /// Modifies a SceneObjectGroup. | ||
304 | /// </summary> | ||
305 | /// <param name="sog">The object</param> | ||
306 | /// <returns>Whether the object was actually modified</returns> | ||
307 | public delegate bool SceneObjectModifier(SceneObjectGroup sog); | ||
308 | |||
309 | /// <summary> | ||
310 | /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing. | ||
311 | /// </summary> | ||
312 | /// <param name="assetId">The object's UUID</param> | ||
313 | /// <param name="data">Serialized data</param> | ||
314 | /// <param name="modifier">The function to run on each SceneObjectGroup</param> | ||
315 | /// <returns>The new serialized object's data, or null if an error occurred</returns> | ||
316 | public static byte[] ModifySerializedObject(UUID assetId, byte[] data, SceneObjectModifier modifier) | ||
317 | { | ||
318 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | ||
319 | CoalescedSceneObjects coa = null; | ||
320 | |||
321 | string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data)); | ||
322 | |||
323 | if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) | ||
324 | { | ||
325 | // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); | ||
326 | |||
327 | if (coa.Objects.Count == 0) | ||
328 | { | ||
329 | m_log.WarnFormat("[SERIALIZER]: Aborting load of coalesced object from asset {0} as it has zero loaded components", assetId); | ||
330 | return null; | ||
331 | } | ||
332 | |||
333 | sceneObjects.AddRange(coa.Objects); | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | SceneObjectGroup deserializedObject = FromOriginalXmlFormat(xmlData); | ||
338 | |||
339 | if (deserializedObject != null) | ||
340 | { | ||
341 | sceneObjects.Add(deserializedObject); | ||
342 | } | ||
343 | else | ||
344 | { | ||
345 | m_log.WarnFormat("[SERIALIZER]: Aborting load of object from asset {0} as deserialization failed", assetId); | ||
346 | return null; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | bool modified = false; | ||
351 | foreach (SceneObjectGroup sog in sceneObjects) | ||
352 | { | ||
353 | if (modifier(sog)) | ||
354 | modified = true; | ||
355 | } | ||
356 | |||
357 | if (modified) | ||
358 | { | ||
359 | if (coa != null) | ||
360 | data = Utils.StringToBytes(CoalescedSceneObjectsSerializer.ToXml(coa)); | ||
361 | else | ||
362 | data = Utils.StringToBytes(ToOriginalXmlFormat(sceneObjects[0])); | ||
363 | } | ||
364 | |||
365 | return data; | ||
366 | } | ||
302 | 367 | ||
303 | #region manual serialization | 368 | #region manual serialization |
304 | 369 | ||