aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorUbitUmarov2015-08-24 17:05:16 +0100
committerUbitUmarov2015-08-24 17:05:16 +0100
commit3829df10595911de9ed1ce2f7b6cdd205828f8d0 (patch)
treed95d15c35695f6fa4dc4a6623294b307a7aee493
parent rename ImapTileModule as IMAPImageUploadModule to match core (diff)
downloadopensim-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
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs5
-rw-r--r--OpenSim/Region/Application/OpenSim.cs24
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs289
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs118
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs17
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs198
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs28
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs65
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;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40 40
41using OpenMetaverse;
42
41namespace OpenSim.Region.CoreModules.World.Archiver 43namespace 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;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31 31
32using OpenMetaverse;
33
32namespace OpenSim.Region.Framework.Interfaces 34namespace 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