try to implement core load oar options
parent
cbc569a1e0
commit
3829df1059
|
@ -1619,8 +1619,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||||
}
|
}
|
||||||
|
|
||||||
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
|
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
|
||||||
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
if (mergeOar) archiveOptions.Add("merge", null);
|
||||||
|
if (skipAssets) archiveOptions.Add("skipAssets", null);
|
||||||
if (archiver != null)
|
if (archiver != null)
|
||||||
archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty);
|
archiver.DearchiveRegion(filename, Guid.Empty, archiveOptions);
|
||||||
else
|
else
|
||||||
throw new Exception("Archiver module not present for scene");
|
throw new Exception("Archiver module not present for scene");
|
||||||
|
|
||||||
|
|
|
@ -267,11 +267,25 @@ namespace OpenSim
|
||||||
SavePrimsXml2);
|
SavePrimsXml2);
|
||||||
|
|
||||||
m_console.Commands.AddCommand("Archiving", false, "load oar",
|
m_console.Commands.AddCommand("Archiving", false, "load oar",
|
||||||
"load oar [--merge] [--skip-assets] [<OAR path>]",
|
|
||||||
|
"load oar [--merge] [--skip-assets]"
|
||||||
|
+ " [--default-user \"User Name\"]"
|
||||||
|
+ " [--force-terrain] [--force-parcels]"
|
||||||
|
+ " [--no-objects]"
|
||||||
|
+ " [--rotation degrees] [--rotation-center \"<x,y,z>\"]"
|
||||||
|
+ " [--displacement \"<x,y,z>\"]"
|
||||||
|
+ " [<OAR path>]",
|
||||||
"Load a region's data from an OAR archive.",
|
"Load a region's data from an OAR archive.",
|
||||||
"--merge will merge the OAR with the existing scene." + Environment.NewLine
|
"--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading).\n"
|
||||||
+ "--skip-assets will load the OAR but ignore the assets it contains." + Environment.NewLine
|
+ "--default-user will use this user for any objects with an owner whose UUID is not found in the grid.\n"
|
||||||
+ "The path can be either a filesystem location or a URI."
|
+ "--displacement will add this value to the position of every object loaded.\n"
|
||||||
|
+ "--force-terrain forces the loading of terrain from the oar (undoes suppression done by --merge).\n"
|
||||||
|
+ "--force-parcels forces the loading of parcels from the oar (undoes suppression done by --merge).\n"
|
||||||
|
+ "--no-objects suppresses the addition of any objects (good for loading only the terrain).\n"
|
||||||
|
+ "--rotation specified rotation to be applied to the oar. Specified in degrees.\n"
|
||||||
|
+ "--rotation-center Location (relative to original OAR) to apply rotation. Default is <128,128,0>.\n"
|
||||||
|
+ "--skip-assets will load the OAR but ignore the assets it contains.\n\n"
|
||||||
|
+ "The path can be either a filesystem location or a URI.\n"
|
||||||
+ " If this is not given then the command looks for an OAR named region.oar in the current directory.",
|
+ " If this is not given then the command looks for an OAR named region.oar in the current directory.",
|
||||||
LoadOar);
|
LoadOar);
|
||||||
|
|
||||||
|
|
|
@ -99,11 +99,38 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
/// </value>
|
/// </value>
|
||||||
protected bool m_merge;
|
protected bool m_merge;
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// If true, force the loading of terrain from the oar file
|
||||||
|
/// </value>
|
||||||
|
protected bool m_forceTerrain;
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// If true, force the loading of parcels from the oar file
|
||||||
|
/// </value>
|
||||||
|
protected bool m_forceParcels;
|
||||||
|
|
||||||
/// <value>
|
/// <value>
|
||||||
/// Should we ignore any assets when reloading the archive?
|
/// Should we ignore any assets when reloading the archive?
|
||||||
/// </value>
|
/// </value>
|
||||||
protected bool m_skipAssets;
|
protected bool m_skipAssets;
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// Displacement added to each object as it is added to the world
|
||||||
|
/// </value>
|
||||||
|
protected Vector3 m_displacement = Vector3.Zero;
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// Rotation (in radians) to apply to the objects as they are loaded.
|
||||||
|
/// </value>
|
||||||
|
protected float m_rotation = 0f;
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// Center around which to apply the rotation relative to the origional oar position
|
||||||
|
/// </value>
|
||||||
|
protected Vector3 m_rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f);
|
||||||
|
|
||||||
|
protected bool m_noObjects = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to cache lookups for valid uuids.
|
/// Used to cache lookups for valid uuids.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -131,11 +158,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
|
|
||||||
private IAssetService m_assetService = null;
|
private IAssetService m_assetService = null;
|
||||||
|
|
||||||
|
private UUID m_defaultUser;
|
||||||
|
|
||||||
public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
|
public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options)
|
||||||
{
|
{
|
||||||
m_rootScene = scene;
|
m_rootScene = scene;
|
||||||
|
|
||||||
|
if (options.ContainsKey("default-user"))
|
||||||
|
{
|
||||||
|
m_defaultUser = (UUID)options["default-user"];
|
||||||
|
m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||||
|
}
|
||||||
|
|
||||||
m_loadPath = loadPath;
|
m_loadPath = loadPath;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -150,26 +188,40 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
}
|
}
|
||||||
|
|
||||||
m_errorMessage = String.Empty;
|
m_errorMessage = String.Empty;
|
||||||
m_merge = merge;
|
|
||||||
m_skipAssets = skipAssets;
|
m_merge = options.ContainsKey("merge");
|
||||||
|
m_forceTerrain = options.ContainsKey("force-terrain");
|
||||||
|
m_forceParcels = options.ContainsKey("force-parcels");
|
||||||
|
m_noObjects = options.ContainsKey("no-objects");
|
||||||
|
m_skipAssets = options.ContainsKey("skipAssets");
|
||||||
|
m_requestId = requestId;
|
||||||
|
m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
|
||||||
|
m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
|
||||||
|
m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
|
||||||
|
: new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
|
||||||
|
|
||||||
m_requestId = requestId;
|
m_requestId = requestId;
|
||||||
|
|
||||||
// Zero can never be a valid user id
|
// Zero can never be a valid user id (or group)
|
||||||
m_validUserUuids[UUID.Zero] = false;
|
m_validUserUuids[UUID.Zero] = false;
|
||||||
|
m_validGroupUuids[UUID.Zero] = false;
|
||||||
|
|
||||||
|
|
||||||
m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
|
m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
|
||||||
m_assetService = m_rootScene.AssetService;
|
m_assetService = m_rootScene.AssetService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
|
public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object> options)
|
||||||
{
|
{
|
||||||
m_rootScene = scene;
|
m_rootScene = scene;
|
||||||
m_loadPath = null;
|
m_loadPath = null;
|
||||||
m_loadStream = loadStream;
|
m_loadStream = loadStream;
|
||||||
m_merge = merge;
|
m_skipAssets = options.ContainsKey("skipAssets");
|
||||||
m_skipAssets = skipAssets;
|
m_merge = options.ContainsKey("merge");
|
||||||
m_requestId = requestId;
|
m_requestId = requestId;
|
||||||
|
|
||||||
|
m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||||
|
|
||||||
// Zero can never be a valid user id
|
// Zero can never be a valid user id
|
||||||
m_validUserUuids[UUID.Zero] = false;
|
m_validUserUuids[UUID.Zero] = false;
|
||||||
|
|
||||||
|
@ -229,7 +281,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
|
|
||||||
// Process the file
|
// Process the file
|
||||||
|
|
||||||
if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
|
if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH) && !m_noObjects)
|
||||||
{
|
{
|
||||||
sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
|
sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
|
||||||
}
|
}
|
||||||
|
@ -243,7 +295,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
if ((successfulAssetRestores + failedAssetRestores) % 250 == 0)
|
if ((successfulAssetRestores + failedAssetRestores) % 250 == 0)
|
||||||
m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets...");
|
m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets...");
|
||||||
}
|
}
|
||||||
else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
|
else if ((!m_merge || m_forceTerrain) && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
|
||||||
{
|
{
|
||||||
LoadTerrain(scene, filePath, data);
|
LoadTerrain(scene, filePath, data);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +303,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
{
|
{
|
||||||
LoadRegionSettings(scene, filePath, data, dearchivedScenes);
|
LoadRegionSettings(scene, filePath, data, dearchivedScenes);
|
||||||
}
|
}
|
||||||
else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
|
else if ((!m_merge || m_forceParcels) && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
|
||||||
{
|
{
|
||||||
sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
|
sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
|
||||||
}
|
}
|
||||||
|
@ -422,6 +474,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
// Reload serialized prims
|
// Reload serialized prims
|
||||||
m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
|
m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
|
||||||
|
|
||||||
|
OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation);
|
||||||
|
|
||||||
UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
|
UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
|
||||||
|
|
||||||
IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
|
IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
|
||||||
|
@ -445,6 +499,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
|
|
||||||
SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
|
SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
|
||||||
|
|
||||||
|
// Happily this does not do much to the object since it hasn't been added to the scene yet
|
||||||
|
if (!sceneObject.IsAttachment)
|
||||||
|
{
|
||||||
|
if (m_displacement != Vector3.Zero || m_rotation != 0f)
|
||||||
|
{
|
||||||
|
Vector3 pos = sceneObject.AbsolutePosition;
|
||||||
|
if (m_rotation != 0f)
|
||||||
|
{
|
||||||
|
// Rotate the object
|
||||||
|
sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
|
||||||
|
// Get object position relative to rotation axis
|
||||||
|
Vector3 offset = pos - m_rotationCenter;
|
||||||
|
// Rotate the object position
|
||||||
|
offset *= rot;
|
||||||
|
// Restore the object position back to relative to the region
|
||||||
|
pos = m_rotationCenter + offset;
|
||||||
|
}
|
||||||
|
if (m_displacement != Vector3.Zero)
|
||||||
|
{
|
||||||
|
pos += m_displacement;
|
||||||
|
}
|
||||||
|
sceneObject.AbsolutePosition = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
|
bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
|
||||||
|
|
||||||
// For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
|
// 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
|
||||||
oldTelehubUUID = UUID.Zero;
|
oldTelehubUUID = UUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to retain the original creator/owner/lastowner if their uuid is present on this grid
|
ModifySceneObject(scene, sceneObject);
|
||||||
// or creator data is present. Otherwise, use the estate owner instead.
|
|
||||||
foreach (SceneObjectPart part in sceneObject.Parts)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(part.CreatorData))
|
|
||||||
{
|
|
||||||
if (!ResolveUserUuid(scene, part.CreatorID))
|
|
||||||
part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
}
|
|
||||||
if (UserManager != null)
|
|
||||||
UserManager.AddUser(part.CreatorID, part.CreatorData);
|
|
||||||
|
|
||||||
if (!ResolveUserUuid(scene, part.OwnerID))
|
|
||||||
part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
|
|
||||||
if (!ResolveUserUuid(scene, part.LastOwnerID))
|
|
||||||
part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
|
|
||||||
if (!ResolveGroupUuid(part.GroupID))
|
|
||||||
part.GroupID = UUID.Zero;
|
|
||||||
|
|
||||||
// And zap any troublesome sit target information
|
|
||||||
// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
|
|
||||||
// part.SitTargetPosition = new Vector3(0, 0, 0);
|
|
||||||
|
|
||||||
// Fix ownership/creator of inventory items
|
|
||||||
// Not doing so results in inventory items
|
|
||||||
// being no copy/no mod for everyone
|
|
||||||
lock (part.TaskInventory)
|
|
||||||
{
|
|
||||||
if (!ResolveUserUuid(scene, part.CreatorID))
|
|
||||||
part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
|
|
||||||
if (!ResolveUserUuid(scene, part.OwnerID))
|
|
||||||
part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
|
|
||||||
if (!ResolveUserUuid(scene, part.LastOwnerID))
|
|
||||||
part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
|
|
||||||
// And zap any troublesome sit target information
|
|
||||||
part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
|
|
||||||
part.SitTargetPosition = new Vector3(0, 0, 0);
|
|
||||||
|
|
||||||
// Fix ownership/creator of inventory items
|
|
||||||
// Not doing so results in inventory items
|
|
||||||
// being no copy/no mod for everyone
|
|
||||||
part.TaskInventory.LockItemsForRead(true);
|
|
||||||
TaskInventoryDictionary inv = part.TaskInventory;
|
|
||||||
foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
|
|
||||||
{
|
|
||||||
if (!ResolveUserUuid(scene, kvp.Value.OwnerID))
|
|
||||||
{
|
|
||||||
kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(kvp.Value.CreatorData))
|
|
||||||
{
|
|
||||||
if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
|
|
||||||
kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UserManager != null)
|
|
||||||
UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
|
|
||||||
|
|
||||||
if (!ResolveGroupUuid(kvp.Value.GroupID))
|
|
||||||
kvp.Value.GroupID = UUID.Zero;
|
|
||||||
}
|
|
||||||
part.TaskInventory.LockItemsForRead(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scene.AddRestoredSceneObject(sceneObject, true, false))
|
if (scene.AddRestoredSceneObject(sceneObject, true, false))
|
||||||
{
|
{
|
||||||
|
@ -554,6 +565,75 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optionally modify a loaded SceneObjectGroup. Currently this just ensures that the
|
||||||
|
/// User IDs and Group IDs are valid, but other manipulations could be done as well.
|
||||||
|
/// </summary>
|
||||||
|
private void ModifySceneObject(Scene scene, SceneObjectGroup sceneObject)
|
||||||
|
{
|
||||||
|
// Try to retain the original creator/owner/lastowner if their uuid is present on this grid
|
||||||
|
// or creator data is present. Otherwise, use the estate owner instead.
|
||||||
|
foreach (SceneObjectPart part in sceneObject.Parts)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(part.CreatorData))
|
||||||
|
{
|
||||||
|
if (!ResolveUserUuid(scene, part.CreatorID))
|
||||||
|
part.CreatorID = m_defaultUser;
|
||||||
|
}
|
||||||
|
if (UserManager != null)
|
||||||
|
UserManager.AddUser(part.CreatorID, part.CreatorData);
|
||||||
|
|
||||||
|
if (!(ResolveUserUuid(scene, part.OwnerID) || ResolveGroupUuid(part.OwnerID)))
|
||||||
|
part.OwnerID = m_defaultUser;
|
||||||
|
|
||||||
|
if (!(ResolveUserUuid(scene, part.LastOwnerID) || ResolveGroupUuid(part.LastOwnerID)))
|
||||||
|
part.LastOwnerID = m_defaultUser;
|
||||||
|
|
||||||
|
if (!ResolveGroupUuid(part.GroupID))
|
||||||
|
part.GroupID = UUID.Zero;
|
||||||
|
|
||||||
|
// And zap any troublesome sit target information
|
||||||
|
// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
|
||||||
|
// part.SitTargetPosition = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
// Fix ownership/creator of inventory items
|
||||||
|
// Not doing so results in inventory items
|
||||||
|
// being no copy/no mod for everyone
|
||||||
|
lock (part.TaskInventory)
|
||||||
|
{
|
||||||
|
// And zap any troublesome sit target information
|
||||||
|
part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
|
||||||
|
part.SitTargetPosition = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
// Fix ownership/creator of inventory items
|
||||||
|
// Not doing so results in inventory items
|
||||||
|
// being no copy/no mod for everyone
|
||||||
|
part.TaskInventory.LockItemsForRead(true);
|
||||||
|
TaskInventoryDictionary inv = part.TaskInventory;
|
||||||
|
foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
|
||||||
|
{
|
||||||
|
if (!(ResolveUserUuid(scene, kvp.Value.OwnerID) || ResolveGroupUuid(kvp.Value.OwnerID)))
|
||||||
|
{
|
||||||
|
kvp.Value.OwnerID = m_defaultUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(kvp.Value.CreatorData))
|
||||||
|
{
|
||||||
|
if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
|
||||||
|
kvp.Value.CreatorID = m_defaultUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserManager != null)
|
||||||
|
UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
|
||||||
|
|
||||||
|
if (!ResolveGroupUuid(kvp.Value.GroupID))
|
||||||
|
kvp.Value.GroupID = UUID.Zero;
|
||||||
|
}
|
||||||
|
part.TaskInventory.LockItemsForRead(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load serialized parcels.
|
/// Load serialized parcels.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -568,13 +648,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
{
|
{
|
||||||
LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
|
LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
|
||||||
|
|
||||||
|
if (m_displacement != Vector3.Zero)
|
||||||
|
{
|
||||||
|
Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
|
||||||
|
parcel.AABBMin += parcelDisp;
|
||||||
|
parcel.AABBMax += parcelDisp;
|
||||||
|
}
|
||||||
|
|
||||||
// Validate User and Group UUID's
|
// Validate User and Group UUID's
|
||||||
|
|
||||||
if (parcel.IsGroupOwned)
|
if (parcel.IsGroupOwned)
|
||||||
{
|
{
|
||||||
if (!ResolveGroupUuid(parcel.GroupID))
|
if (!ResolveGroupUuid(parcel.GroupID))
|
||||||
{
|
{
|
||||||
parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
|
parcel.OwnerID = m_defaultUser;
|
||||||
parcel.GroupID = UUID.Zero;
|
parcel.GroupID = UUID.Zero;
|
||||||
parcel.IsGroupOwned = false;
|
parcel.IsGroupOwned = false;
|
||||||
}
|
}
|
||||||
|
@ -582,7 +669,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!ResolveUserUuid(scene, parcel.OwnerID))
|
if (!ResolveUserUuid(scene, parcel.OwnerID))
|
||||||
parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
|
parcel.OwnerID = m_defaultUser;
|
||||||
|
|
||||||
if (!ResolveGroupUuid(parcel.GroupID))
|
if (!ResolveGroupUuid(parcel.GroupID))
|
||||||
parcel.GroupID = UUID.Zero;
|
parcel.GroupID = UUID.Zero;
|
||||||
|
@ -702,8 +789,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
|
sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
|
||||||
|
|
||||||
if (assetType == (sbyte)AssetType.Unknown)
|
if (assetType == (sbyte)AssetType.Unknown)
|
||||||
|
{
|
||||||
m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
|
m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
|
||||||
|
}
|
||||||
|
else if (assetType == (sbyte)AssetType.Object)
|
||||||
|
{
|
||||||
|
data = SceneObjectSerializer.ModifySerializedObject(UUID.Parse(uuid), data,
|
||||||
|
sog =>
|
||||||
|
{
|
||||||
|
ModifySceneObject(m_rootScene, sog);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data == null)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
//m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
|
//m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
|
||||||
|
|
||||||
AssetBase asset = new AssetBase(new UUID(uuid), String.Empty, assetType, UUID.Zero.ToString());
|
AssetBase asset = new AssetBase(new UUID(uuid), String.Empty, assetType, UUID.Zero.ToString());
|
||||||
|
@ -826,9 +926,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
{
|
{
|
||||||
ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
|
ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
|
||||||
|
|
||||||
MemoryStream ms = new MemoryStream(data);
|
using (MemoryStream ms = new MemoryStream(data))
|
||||||
|
{
|
||||||
|
if (m_displacement != Vector3.Zero || m_rotation != 0f)
|
||||||
|
{
|
||||||
|
Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y);
|
||||||
|
terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
terrainModule.LoadFromStream(terrainPath, ms);
|
terrainModule.LoadFromStream(terrainPath, ms);
|
||||||
ms.Close();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath);
|
m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath);
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.World.Archiver
|
namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -101,9 +103,64 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
{
|
{
|
||||||
bool mergeOar = false;
|
bool mergeOar = false;
|
||||||
bool skipAssets = false;
|
bool skipAssets = false;
|
||||||
|
bool forceTerrain = false;
|
||||||
|
bool forceParcels = false;
|
||||||
|
bool noObjects = false;
|
||||||
|
Vector3 displacement = new Vector3(0f, 0f, 0f);
|
||||||
|
String defaultUser = "";
|
||||||
|
float rotation = 0f;
|
||||||
|
Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0);
|
||||||
|
|
||||||
OptionSet options = new OptionSet().Add("m|merge", delegate (string v) { mergeOar = v != null; });
|
OptionSet options = new OptionSet();
|
||||||
options.Add("s|skip-assets", delegate (string v) { skipAssets = v != null; });
|
options.Add("m|merge", delegate(string v) { mergeOar = (v != null); });
|
||||||
|
options.Add("s|skip-assets", delegate(string v) { skipAssets = (v != null); });
|
||||||
|
options.Add("force-terrain", delegate(string v) { forceTerrain = (v != null); });
|
||||||
|
options.Add("forceterrain", delegate(string v) { forceTerrain = (v != null); }); // downward compatibility
|
||||||
|
options.Add("force-parcels", delegate(string v) { forceParcels = (v != null); });
|
||||||
|
options.Add("forceparcels", delegate(string v) { forceParcels = (v != null); }); // downward compatibility
|
||||||
|
options.Add("no-objects", delegate(string v) { noObjects = (v != null); });
|
||||||
|
options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; });
|
||||||
|
options.Add("displacement=", delegate(string v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
displacement = v == null ? Vector3.Zero : Vector3.Parse(v);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing displacement");
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --displacement \"<128,128,0>\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
options.Add("rotation=", delegate(string v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
rotation = v == null ? 0f : float.Parse(v);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation");
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Convert to radians for internals
|
||||||
|
rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI;
|
||||||
|
});
|
||||||
|
options.Add("rotation-center=", delegate(string v)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation displacement");
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --rotation-center \"<128,128,0>\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Send a message to the region ready module
|
// Send a message to the region ready module
|
||||||
/* bluewall* Disable this for the time being
|
/* bluewall* Disable this for the time being
|
||||||
|
@ -122,13 +179,44 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
// foreach (string param in mainParams)
|
// foreach (string param in mainParams)
|
||||||
// m_log.DebugFormat("GOT PARAM [{0}]", param);
|
// m_log.DebugFormat("GOT PARAM [{0}]", param);
|
||||||
|
|
||||||
if (mainParams.Count > 2)
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
if (mergeOar) archiveOptions.Add("merge", null);
|
||||||
|
if (skipAssets) archiveOptions.Add("skipAssets", null);
|
||||||
|
if (forceTerrain) archiveOptions.Add("force-terrain", null);
|
||||||
|
if (forceParcels) archiveOptions.Add("force-parcels", null);
|
||||||
|
if (noObjects) archiveOptions.Add("no-objects", null);
|
||||||
|
if (defaultUser != "")
|
||||||
{
|
{
|
||||||
DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty);
|
UUID defaultUserUUID = UUID.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
defaultUserUUID = Scene.UserManagementModule.GetUserIdByName(defaultUser);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] default user must be in format \"First Last\"", defaultUser);
|
||||||
|
}
|
||||||
|
if (defaultUserUUID == UUID.Zero)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[ARCHIVER MODULE] cannot find specified default user {0}", defaultUser);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, mergeOar, skipAssets, Guid.Empty);
|
archiveOptions.Add("default-user", defaultUserUUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
archiveOptions.Add("displacement", displacement);
|
||||||
|
archiveOptions.Add("rotation", rotation);
|
||||||
|
archiveOptions.Add("rotation-center", rotationCenter);
|
||||||
|
|
||||||
|
if (mainParams.Count > 2)
|
||||||
|
{
|
||||||
|
DearchiveRegion(mainParams[2], Guid.Empty, archiveOptions);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, Guid.Empty, archiveOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,25 +286,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
|
|
||||||
public void DearchiveRegion(string loadPath)
|
public void DearchiveRegion(string loadPath)
|
||||||
{
|
{
|
||||||
DearchiveRegion(loadPath, false, false, Guid.Empty);
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
DearchiveRegion(loadPath, Guid.Empty, archiveOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId)
|
public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string, object> options)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat(
|
m_log.InfoFormat(
|
||||||
"[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
|
"[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
|
||||||
|
|
||||||
new ArchiveReadRequest(Scene, loadPath, merge, skipAssets, requestId).DearchiveRegion();
|
new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DearchiveRegion(Stream loadStream)
|
public void DearchiveRegion(Stream loadStream)
|
||||||
{
|
{
|
||||||
DearchiveRegion(loadStream, false, false, Guid.Empty);
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
DearchiveRegion(loadStream, Guid.Empty, archiveOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId)
|
public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options)
|
||||||
{
|
{
|
||||||
new ArchiveReadRequest(Scene, loadStream, merge, skipAssets, requestId).DearchiveRegion();
|
new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,7 +225,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||||
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
|
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
|
||||||
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
||||||
|
|
||||||
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
|
||||||
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
||||||
|
|
||||||
Assert.That(arr.ControlFileLoaded, Is.True);
|
Assert.That(arr.ControlFileLoaded, Is.True);
|
||||||
|
@ -309,7 +310,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||||
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
|
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
|
||||||
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
||||||
|
|
||||||
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
|
||||||
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
||||||
|
|
||||||
Assert.That(arr.ControlFileLoaded, Is.True);
|
Assert.That(arr.ControlFileLoaded, Is.True);
|
||||||
|
@ -752,7 +754,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||||
byte[] archive = archiveWriteStream.ToArray();
|
byte[] archive = archiveWriteStream.ToArray();
|
||||||
MemoryStream archiveReadStream = new MemoryStream(archive);
|
MemoryStream archiveReadStream = new MemoryStream(archive);
|
||||||
|
|
||||||
m_archiverModule.DearchiveRegion(archiveReadStream, true, false, Guid.Empty);
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
archiveOptions.Add("merge", null);
|
||||||
|
m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions);
|
||||||
|
|
||||||
SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
|
SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
|
||||||
Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
|
Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
|
||||||
|
@ -860,7 +864,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||||
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
|
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
|
||||||
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
||||||
|
|
||||||
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
|
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
|
||||||
|
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
|
||||||
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
||||||
|
|
||||||
Assert.That(arr.ControlFileLoaded, Is.True);
|
Assert.That(arr.ControlFileLoaded, Is.True);
|
||||||
|
|
|
@ -570,20 +570,57 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
new_land.LandData.LocalID = newLandLocalID;
|
new_land.LandData.LocalID = newLandLocalID;
|
||||||
|
|
||||||
bool[,] landBitmap = new_land.GetLandBitmap();
|
bool[,] landBitmap = new_land.GetLandBitmap();
|
||||||
|
if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
|
||||||
|
{
|
||||||
|
// Going to variable sized regions can cause mismatches
|
||||||
|
m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
|
||||||
|
LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If other land objects still believe that they occupy any parts of the same space,
|
||||||
|
// then do not allow the add to proceed.
|
||||||
for (int x = 0; x < landBitmap.GetLength(0); x++)
|
for (int x = 0; x < landBitmap.GetLength(0); x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < landBitmap.GetLength(1); y++)
|
for (int y = 0; y < landBitmap.GetLength(1); y++)
|
||||||
{
|
{
|
||||||
if (landBitmap[x, y])
|
if (landBitmap[x, y])
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
int lastRecordedLandId = m_landIDList[x, y];
|
||||||
// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
|
|
||||||
// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
|
if (lastRecordedLandId > 0)
|
||||||
|
{
|
||||||
|
ILandObject lastRecordedLo = m_landList[lastRecordedLandId];
|
||||||
|
|
||||||
|
if (lastRecordedLo.LandBitmap[x, y])
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"{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}",
|
||||||
|
LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y,
|
||||||
|
lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < landBitmap.GetLength(0); x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < landBitmap.GetLength(1); y++)
|
||||||
|
{
|
||||||
|
if (landBitmap[x, y])
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
|
||||||
|
// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
m_landIDList[x, y] = newLandLocalID;
|
m_landIDList[x, y] = newLandLocalID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_landList.Add(newLandLocalID, new_land);
|
m_landList.Add(newLandLocalID, new_land);
|
||||||
}
|
}
|
||||||
|
@ -693,47 +730,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
/// <returns>Land object at the point supplied</returns>
|
/// <returns>Land object at the point supplied</returns>
|
||||||
public ILandObject GetLandObject(float x_float, float y_float)
|
public ILandObject GetLandObject(float x_float, float y_float)
|
||||||
{
|
{
|
||||||
int x;
|
return GetLandObject((int)x_float, (int)y_float, true);
|
||||||
int y;
|
|
||||||
|
|
||||||
if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
|
|
||||||
y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
|
|
||||||
}
|
|
||||||
catch (OverflowException)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
|
|
||||||
|| y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
|
|
||||||
|| x < 0
|
|
||||||
|| y < 0)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (m_landList)
|
|
||||||
{
|
|
||||||
// Corner case. If an autoreturn happens during sim startup
|
|
||||||
// we will come here with the list uninitialized
|
|
||||||
//
|
|
||||||
// int landId = m_landIDList[x, y];
|
|
||||||
|
|
||||||
// if (landId == 0)
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}",
|
|
||||||
// x, y, m_scene.RegionInfo.RegionName);
|
|
||||||
|
|
||||||
if (m_landList.ContainsKey(m_landIDList[x, y]))
|
|
||||||
return m_landList[m_landIDList[x, y]];
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if x,y is off region this will return the parcel at cliped x,y
|
// if x,y is off region this will return the parcel at cliped x,y
|
||||||
|
@ -767,11 +764,19 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILandObject GetLandObject(int x, int y)
|
public ILandObject GetLandObject(int x, int y)
|
||||||
|
{
|
||||||
|
return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds)
|
||||||
{
|
{
|
||||||
if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
|
if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
|
||||||
{
|
{
|
||||||
// These exceptions here will cause a lot of complaints from the users specifically because
|
// These exceptions here will cause a lot of complaints from the users specifically because
|
||||||
// they happen every time at border crossings
|
// they happen every time at border crossings
|
||||||
|
if (returnNullIfLandObjectOutsideBounds)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
throw new Exception("Error: Parcel not found at point " + x + ", " + y);
|
throw new Exception("Error: Parcel not found at point " + x + ", " + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,10 +784,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4]))
|
|
||||||
return m_landList[m_landIDList[x / 4, y / 4]];
|
return m_landList[m_landIDList[x / 4, y / 4]];
|
||||||
//else
|
|
||||||
// return null;
|
|
||||||
}
|
}
|
||||||
catch (IndexOutOfRangeException)
|
catch (IndexOutOfRangeException)
|
||||||
{
|
{
|
||||||
|
@ -791,6 +793,19 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a 'parcel is here' bitmap for the parcel identified by the passed landID
|
||||||
|
private bool[,] CreateBitmapForID(int landID)
|
||||||
|
{
|
||||||
|
bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)];
|
||||||
|
|
||||||
|
for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
|
||||||
|
for (int yy = 0; yy < m_landIDList.GetLength(0); yy++)
|
||||||
|
if (m_landIDList[xx, yy] == landID)
|
||||||
|
ret[xx, yy] = true;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Parcel Modification
|
#region Parcel Modification
|
||||||
|
@ -1432,29 +1447,66 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
|
|
||||||
public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
|
public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
|
||||||
{
|
{
|
||||||
Dictionary<int, ILandObject> landworkList;
|
|
||||||
// move to work pointer since we are deleting it all
|
|
||||||
lock (m_landList)
|
lock (m_landList)
|
||||||
{
|
{
|
||||||
landworkList = m_landList;
|
|
||||||
m_landList = new Dictionary<int, ILandObject>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove all the land objects in the sim and then process our new data
|
|
||||||
foreach (int n in landworkList.Keys)
|
|
||||||
{
|
|
||||||
m_scene.EventManager.TriggerLandObjectRemoved(landworkList[n].LandData.GlobalID);
|
|
||||||
}
|
|
||||||
landworkList.Clear();
|
|
||||||
|
|
||||||
lock (m_landList)
|
|
||||||
{
|
|
||||||
m_landIDList.Initialize();
|
|
||||||
m_landList.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < data.Count; i++)
|
for (int i = 0; i < data.Count; i++)
|
||||||
IncomingLandObjectFromStorage(data[i]);
|
IncomingLandObjectFromStorage(data[i]);
|
||||||
|
|
||||||
|
// Layer data is in landUnit (4m) chunks
|
||||||
|
for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); x++)
|
||||||
|
{
|
||||||
|
if (m_landIDList[x, y] == 0)
|
||||||
|
{
|
||||||
|
if (m_landList.Count == 1)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}",
|
||||||
|
LogHeader, x, y, m_scene.Name);
|
||||||
|
|
||||||
|
int onlyParcelID = 0;
|
||||||
|
ILandObject onlyLandObject = null;
|
||||||
|
foreach (KeyValuePair<int, ILandObject> kvp in m_landList)
|
||||||
|
{
|
||||||
|
onlyParcelID = kvp.Key;
|
||||||
|
onlyLandObject = kvp.Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is only one parcel. Grow it to fill all the unallocated spaces.
|
||||||
|
for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
|
||||||
|
for (int yy = 0; yy < m_landIDList.GetLength(1); yy++)
|
||||||
|
if (m_landIDList[xx, yy] == 0)
|
||||||
|
m_landIDList[xx, yy] = onlyParcelID;
|
||||||
|
|
||||||
|
onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID);
|
||||||
|
}
|
||||||
|
else if (m_landList.Count > 1)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}",
|
||||||
|
LogHeader, x, y, m_scene.Name);
|
||||||
|
|
||||||
|
// There are several other parcels so we must create a new one for the unassigned space
|
||||||
|
ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
|
||||||
|
// Claim all the unclaimed "0" ids
|
||||||
|
newLand.SetLandBitmap(CreateBitmapForID(0));
|
||||||
|
newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||||
|
newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
|
||||||
|
newLand = AddLandObject(newLand);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We should never reach this point as the separate code path when no land data exists should have fired instead.
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present",
|
||||||
|
LogHeader, m_scene.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void IncomingLandObjectFromStorage(LandData data)
|
public void IncomingLandObjectFromStorage(LandData data)
|
||||||
|
@ -1464,7 +1516,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
new_land.LandData = data.Copy();
|
new_land.LandData = data.Copy();
|
||||||
new_land.SetLandBitmapFromByteArray();
|
new_land.SetLandBitmapFromByteArray();
|
||||||
AddLandObject(new_land);
|
AddLandObject(new_land);
|
||||||
new_land.SendLandUpdateToAvatarsOverMe();
|
// new_land.SendLandUpdateToAvatarsOverMe();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
|
public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
|
||||||
|
|
|
@ -29,6 +29,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Interfaces
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -100,16 +102,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
|
/// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
|
||||||
///
|
///
|
||||||
/// <param name="loadPath"></param>
|
/// <param name="loadPath"></param>
|
||||||
/// <param name="merge">
|
|
||||||
/// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region
|
|
||||||
/// settings in the archive will be ignored.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="skipAssets">
|
|
||||||
/// If true, the archive is loaded without loading any assets contained within it. This is useful if the
|
|
||||||
/// assets are already known to be present in the grid's asset service.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
|
/// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
|
||||||
void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId);
|
/// <param name="options">
|
||||||
|
/// Dictionary of options.
|
||||||
|
/// </param>
|
||||||
|
void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dearchive a region from a stream. This replaces the existing scene.
|
/// Dearchive a region from a stream. This replaces the existing scene.
|
||||||
|
@ -127,15 +124,10 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
|
/// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
|
||||||
///
|
///
|
||||||
/// <param name="loadStream"></param>
|
/// <param name="loadStream"></param>
|
||||||
/// <param name="merge">
|
|
||||||
/// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region
|
|
||||||
/// settings in the archive will be ignored.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="skipAssets">
|
|
||||||
/// If true, the archive is loaded without loading any assets contained within it. This is useful if the
|
|
||||||
/// assets are already known to be present in the grid's asset service.
|
|
||||||
/// </param
|
|
||||||
/// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
|
/// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
|
||||||
void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId);
|
/// <param name="options">
|
||||||
|
/// Dictionary of options.
|
||||||
|
/// </param>
|
||||||
|
void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// <param name="stream"></param>
|
/// <param name="stream"></param>
|
||||||
void LoadFromStream(string filename, Stream stream);
|
void LoadFromStream(string filename, Stream stream);
|
||||||
void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
|
void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
|
||||||
|
void LoadFromStream(string filename, Vector3 displacement,
|
||||||
|
float radianRotation, Vector2 rotationDisplacement, Stream stream);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save a terrain to a stream.
|
/// Save a terrain to a stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -299,6 +299,71 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modifies a SceneObjectGroup.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sog">The object</param>
|
||||||
|
/// <returns>Whether the object was actually modified</returns>
|
||||||
|
public delegate bool SceneObjectModifier(SceneObjectGroup sog);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assetId">The object's UUID</param>
|
||||||
|
/// <param name="data">Serialized data</param>
|
||||||
|
/// <param name="modifier">The function to run on each SceneObjectGroup</param>
|
||||||
|
/// <returns>The new serialized object's data, or null if an error occurred</returns>
|
||||||
|
public static byte[] ModifySerializedObject(UUID assetId, byte[] data, SceneObjectModifier modifier)
|
||||||
|
{
|
||||||
|
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
|
||||||
|
CoalescedSceneObjects coa = null;
|
||||||
|
|
||||||
|
string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data));
|
||||||
|
|
||||||
|
if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa))
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count);
|
||||||
|
|
||||||
|
if (coa.Objects.Count == 0)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[SERIALIZER]: Aborting load of coalesced object from asset {0} as it has zero loaded components", assetId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneObjects.AddRange(coa.Objects);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SceneObjectGroup deserializedObject = FromOriginalXmlFormat(xmlData);
|
||||||
|
|
||||||
|
if (deserializedObject != null)
|
||||||
|
{
|
||||||
|
sceneObjects.Add(deserializedObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[SERIALIZER]: Aborting load of object from asset {0} as deserialization failed", assetId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
foreach (SceneObjectGroup sog in sceneObjects)
|
||||||
|
{
|
||||||
|
if (modifier(sog))
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modified)
|
||||||
|
{
|
||||||
|
if (coa != null)
|
||||||
|
data = Utils.StringToBytes(CoalescedSceneObjectsSerializer.ToXml(coa));
|
||||||
|
else
|
||||||
|
data = Utils.StringToBytes(ToOriginalXmlFormat(sceneObjects[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
#region manual serialization
|
#region manual serialization
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue