2009-02-12 09:53:12 +00:00
/ *
2008-05-30 08:35:57 +00:00
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-05-30 08:35:57 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2009-02-12 18:59:45 +00:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.IO.Compression ;
using System.Net ;
using System.Reflection ;
using System.Text ;
2009-06-03 12:48:04 +00:00
using System.Xml ;
2009-02-12 18:59:45 +00:00
using log4net ;
using OpenMetaverse ;
using OpenSim.Framework ;
2009-03-16 00:12:25 +00:00
using OpenSim.Framework.Serialization ;
2009-03-27 18:13:34 +00:00
using OpenSim.Framework.Serialization.External ;
2009-02-12 18:59:45 +00:00
using OpenSim.Region.CoreModules.World.Terrain ;
using OpenSim.Region.Framework.Interfaces ;
using OpenSim.Region.Framework.Scenes ;
2012-05-15 22:43:59 +00:00
using OpenSim.Region.Framework.Scenes.Serialization ;
2010-01-10 18:40:07 +00:00
using OpenSim.Services.Interfaces ;
2012-07-24 16:48:08 +00:00
using System.Threading ;
2009-02-12 18:59:45 +00:00
2009-02-10 13:10:57 +00:00
namespace OpenSim.Region.CoreModules.World.Archiver
2008-05-30 08:35:57 +00:00
{
/// <summary>
/// Handles an individual archive read request
/// </summary>
public class ArchiveReadRequest
{
2008-06-04 09:59:27 +00:00
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2012-07-24 16:48:08 +00:00
/// <summary>
/// Contains data used while dearchiving a single scene.
/// </summary>
private class DearchiveContext
{
public Scene Scene { get ; set ; }
public List < string > SerialisedSceneObjects { get ; set ; }
public List < string > SerialisedParcels { get ; set ; }
public List < SceneObjectGroup > SceneObjects { get ; set ; }
public DearchiveContext ( Scene scene )
{
Scene = scene ;
SerialisedSceneObjects = new List < string > ( ) ;
SerialisedParcels = new List < string > ( ) ;
SceneObjects = new List < SceneObjectGroup > ( ) ;
}
}
2010-10-16 03:59:51 +00:00
2012-07-24 16:48:08 +00:00
2010-10-16 03:59:51 +00:00
/// <summary>
2010-10-22 18:30:15 +00:00
/// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
2010-10-16 03:59:51 +00:00
/// bumps here should be compatible.
/// </summary>
2010-11-20 02:59:21 +00:00
public static int MAX_MAJOR_VERSION = 1 ;
2011-04-18 21:35:33 +00:00
/// <summary>
/// Has the control file been loaded for this archive?
/// </summary>
2012-07-24 16:48:08 +00:00
public bool ControlFileLoaded { get ; private set ; }
2008-06-04 09:59:27 +00:00
2012-07-24 16:48:08 +00:00
protected string m_loadPath ;
protected Scene m_rootScene ;
2010-04-16 21:29:11 +00:00
protected Stream m_loadStream ;
protected Guid m_requestId ;
protected string m_errorMessage ;
2009-03-16 00:12:25 +00:00
2009-02-10 18:43:36 +00:00
/// <value>
/// Should the archive being loaded be merged with what is already on the region?
2014-01-19 20:45:16 +00:00
/// Merging usually suppresses terrain and parcel loading
2009-02-10 18:43:36 +00:00
/// </value>
2010-04-16 21:29:11 +00:00
protected bool m_merge ;
2014-01-19 19:03:08 +00:00
/// <value>
2014-01-19 20:45:16 +00:00
/// If true, force the loading of terrain from the oar file
2014-01-19 19:03:08 +00:00
/// </value>
2014-01-19 20:45:16 +00:00
protected bool m_forceTerrain ;
2014-01-19 19:03:08 +00:00
/// <value>
2014-01-19 20:45:16 +00:00
/// If true, force the loading of parcels from the oar file
2014-01-19 19:03:08 +00:00
/// </value>
2014-01-19 20:45:16 +00:00
protected bool m_forceParcels ;
2014-01-19 19:03:08 +00:00
2010-04-16 21:29:11 +00:00
/// <value>
/// Should we ignore any assets when reloading the archive?
/// </value>
protected bool m_skipAssets ;
2008-08-18 00:39:10 +00:00
2014-01-19 18:09:43 +00:00
/// <value>
/// Displacement added to each object as it is added to the world
/// </value>
2014-01-19 19:03:08 +00:00
protected Vector3 m_displacement = Vector3 . Zero ;
2014-01-19 18:09:43 +00:00
2014-01-19 20:45:16 +00:00
/// <value>
2014-02-02 19:17:49 +00:00
/// Rotation (in radians) to apply to the objects as they are loaded.
2014-01-19 20:45:16 +00:00
/// </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 ) ;
2014-02-03 06:16:01 +00:00
protected bool m_noObjects = false ;
2008-08-09 22:04:42 +00:00
/// <summary>
/// Used to cache lookups for valid uuids.
/// </summary>
2008-09-06 07:52:41 +00:00
private IDictionary < UUID , bool > m_validUserUuids = new Dictionary < UUID , bool > ( ) ;
2008-05-30 08:35:57 +00:00
2010-11-21 21:16:52 +00:00
private IUserManagement m_UserMan ;
private IUserManagement UserManager
{
get
{
if ( m_UserMan = = null )
{
2012-07-24 16:48:08 +00:00
m_UserMan = m_rootScene . RequestModuleInterface < IUserManagement > ( ) ;
2010-11-21 21:16:52 +00:00
}
return m_UserMan ;
}
}
2012-08-20 20:58:18 +00:00
/// <summary>
/// Used to cache lookups for valid groups.
/// </summary>
private IDictionary < UUID , bool > m_validGroupUuids = new Dictionary < UUID , bool > ( ) ;
private IGroupsModule m_groupsModule ;
2012-07-24 16:48:08 +00:00
private IAssetService m_assetService = null ;
2014-01-19 19:03:08 +00:00
public ArchiveReadRequest ( Scene scene , string loadPath , Guid requestId , Dictionary < string , object > options )
2008-05-30 08:35:57 +00:00
{
2012-07-24 16:48:08 +00:00
m_rootScene = scene ;
2010-02-19 22:30:46 +00:00
2012-07-24 16:48:08 +00:00
m_loadPath = loadPath ;
2010-02-19 22:30:46 +00:00
try
{
2010-05-28 18:21:00 +00:00
m_loadStream = new GZipStream ( ArchiveHelpers . GetStream ( loadPath ) , CompressionMode . Decompress ) ;
2010-02-19 22:30:46 +00:00
}
catch ( EntryPointNotFoundException e )
{
m_log . ErrorFormat (
"[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
+ "If you've manually installed Mono, have you appropriately updated zlib1g as well?" ) ;
m_log . Error ( e ) ;
}
2009-01-28 09:22:12 +00:00
m_errorMessage = String . Empty ;
2014-01-19 19:03:08 +00:00
m_merge = options . ContainsKey ( "merge" ) ;
2014-02-02 20:21:18 +00:00
m_forceTerrain = options . ContainsKey ( "force-terrain" ) ;
m_forceParcels = options . ContainsKey ( "force-parcels" ) ;
2014-02-03 06:16:01 +00:00
m_noObjects = options . ContainsKey ( "no-objects" ) ;
2014-01-19 19:03:08 +00:00
m_skipAssets = options . ContainsKey ( "skipAssets" ) ;
2009-04-15 19:12:37 +00:00
m_requestId = requestId ;
2014-01-19 19:03:08 +00:00
m_displacement = options . ContainsKey ( "displacement" ) ? ( Vector3 ) options [ "displacement" ] : Vector3 . Zero ;
2014-01-19 20:45:16 +00:00
m_rotation = options . ContainsKey ( "rotation" ) ? ( float ) options [ "rotation" ] : 0f ;
2014-02-02 20:21:18 +00:00
m_rotationCenter = options . ContainsKey ( "rotation-center" ) ? ( Vector3 ) options [ "rotation-center" ]
2014-02-02 19:17:49 +00:00
: new Vector3 ( scene . RegionInfo . RegionSizeX / 2f , scene . RegionInfo . RegionSizeY / 2f , 0f ) ;
2012-01-28 02:21:41 +00:00
// Zero can never be a valid user id
m_validUserUuids [ UUID . Zero ] = false ;
2012-08-20 20:58:18 +00:00
2012-07-24 16:48:08 +00:00
m_groupsModule = m_rootScene . RequestModuleInterface < IGroupsModule > ( ) ;
m_assetService = m_rootScene . AssetService ;
2008-05-30 08:35:57 +00:00
}
2009-02-04 00:01:36 +00:00
2014-01-19 19:03:08 +00:00
public ArchiveReadRequest ( Scene scene , Stream loadStream , Guid requestId , Dictionary < string , object > options )
2009-01-23 17:07:37 +00:00
{
2012-07-24 16:48:08 +00:00
m_rootScene = scene ;
m_loadPath = null ;
2009-01-23 17:07:37 +00:00
m_loadStream = loadStream ;
2014-01-19 19:03:08 +00:00
m_skipAssets = options . ContainsKey ( "skipAssets" ) ;
m_merge = options . ContainsKey ( "merge" ) ;
2009-04-15 19:12:37 +00:00
m_requestId = requestId ;
2012-01-28 02:21:41 +00:00
// Zero can never be a valid user id
m_validUserUuids [ UUID . Zero ] = false ;
2012-08-20 20:58:18 +00:00
2012-07-24 16:48:08 +00:00
m_groupsModule = m_rootScene . RequestModuleInterface < IGroupsModule > ( ) ;
m_assetService = m_rootScene . AssetService ;
2009-02-04 00:01:36 +00:00
}
2008-06-04 09:59:27 +00:00
2009-01-23 17:07:37 +00:00
/// <summary>
/// Dearchive the region embodied in this request.
/// </summary>
public void DearchiveRegion ( )
2008-08-18 00:39:10 +00:00
{
2009-01-28 09:22:12 +00:00
int successfulAssetRestores = 0 ;
int failedAssetRestores = 0 ;
2009-11-24 17:47:09 +00:00
2012-07-24 16:48:08 +00:00
DearchiveScenesInfo dearchivedScenes ;
// We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
// Therefore, we have to keep track of the dearchive context of all the scenes.
Dictionary < UUID , DearchiveContext > sceneContexts = new Dictionary < UUID , DearchiveContext > ( ) ;
string fullPath = "NONE" ;
TarArchiveReader archive = null ;
2009-11-24 17:47:09 +00:00
byte [ ] data ;
TarArchiveReader . TarEntryType entryType ;
2012-07-24 16:48:08 +00:00
2009-01-28 09:22:12 +00:00
try
{
2012-07-24 16:48:08 +00:00
FindAndLoadControlFile ( out archive , out dearchivedScenes ) ;
while ( ( data = archive . ReadEntry ( out fullPath , out entryType ) ) ! = null )
2009-09-30 16:00:09 +00:00
{
2009-04-28 19:54:57 +00:00
//m_log.DebugFormat(
// "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
2009-04-28 19:40:02 +00:00
if ( TarArchiveReader . TarEntryType . TYPE_DIRECTORY = = entryType )
2009-09-30 16:00:09 +00:00
continue ;
2009-03-16 00:12:25 +00:00
2012-07-24 16:48:08 +00:00
// Find the scene that this file belongs to
Scene scene ;
string filePath ;
if ( ! dearchivedScenes . GetRegionFromPath ( fullPath , out scene , out filePath ) )
continue ; // this file belongs to a region that we're not loading
DearchiveContext sceneContext = null ;
if ( scene ! = null )
{
if ( ! sceneContexts . TryGetValue ( scene . RegionInfo . RegionID , out sceneContext ) )
{
sceneContext = new DearchiveContext ( scene ) ;
sceneContexts . Add ( scene . RegionInfo . RegionID , sceneContext ) ;
}
}
// Process the file
2014-02-03 06:16:01 +00:00
if ( filePath . StartsWith ( ArchiveConstants . OBJECTS_PATH ) & & ! m_noObjects )
2009-01-28 09:22:12 +00:00
{
2012-07-24 16:48:08 +00:00
sceneContext . SerialisedSceneObjects . Add ( Encoding . UTF8 . GetString ( data ) ) ;
2009-01-28 09:22:12 +00:00
}
2010-04-16 21:29:11 +00:00
else if ( filePath . StartsWith ( ArchiveConstants . ASSETS_PATH ) & & ! m_skipAssets )
2009-01-28 09:22:12 +00:00
{
if ( LoadAsset ( filePath , data ) )
successfulAssetRestores + + ;
else
failedAssetRestores + + ;
2009-10-29 08:46:58 +00:00
if ( ( successfulAssetRestores + failedAssetRestores ) % 250 = = 0 )
m_log . Debug ( "[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets..." ) ;
2009-01-28 09:22:12 +00:00
}
2014-01-19 20:45:16 +00:00
else if ( filePath . StartsWith ( ArchiveConstants . TERRAINS_PATH ) & & ( ! m_merge | | m_forceTerrain ) )
2009-01-28 09:22:12 +00:00
{
2012-07-24 16:48:08 +00:00
LoadTerrain ( scene , filePath , data ) ;
2009-01-28 09:22:12 +00:00
}
2009-02-10 18:43:36 +00:00
else if ( ! m_merge & & filePath . StartsWith ( ArchiveConstants . SETTINGS_PATH ) )
2009-01-28 09:22:12 +00:00
{
2012-07-24 16:48:08 +00:00
LoadRegionSettings ( scene , filePath , data , dearchivedScenes ) ;
2009-06-12 14:18:01 +00:00
}
2014-01-19 20:45:16 +00:00
else if ( filePath . StartsWith ( ArchiveConstants . LANDDATA_PATH ) & & ( ! m_merge | | m_forceParcels ) )
2009-10-02 09:10:52 +00:00
{
2012-07-24 16:48:08 +00:00
sceneContext . SerialisedParcels . Add ( Encoding . UTF8 . GetString ( data ) ) ;
2009-10-02 09:10:52 +00:00
}
2009-06-12 14:18:01 +00:00
else if ( filePath = = ArchiveConstants . CONTROL_FILE_PATH )
{
2012-07-24 16:48:08 +00:00
// Ignore, because we already read the control file
2009-01-28 09:22:12 +00:00
}
2008-12-30 19:00:19 +00:00
}
2009-02-04 00:01:36 +00:00
2009-01-28 09:22:12 +00:00
//m_log.Debug("[ARCHIVER]: Reached end of archive");
}
catch ( Exception e )
{
2012-07-24 16:48:08 +00:00
m_log . Error (
String . Format ( "[ARCHIVER]: Aborting load with error in archive file {0} " , fullPath ) , e ) ;
2009-01-28 09:22:12 +00:00
m_errorMessage + = e . ToString ( ) ;
2012-07-24 16:48:08 +00:00
m_rootScene . EventManager . TriggerOarFileLoaded ( m_requestId , new List < UUID > ( ) , m_errorMessage ) ;
2009-01-28 09:22:12 +00:00
return ;
}
2009-11-24 17:47:09 +00:00
finally
{
2012-07-24 16:48:08 +00:00
if ( archive ! = null )
archive . Close ( ) ;
2009-11-24 17:47:09 +00:00
}
2008-08-18 00:39:10 +00:00
2010-04-16 21:29:11 +00:00
if ( ! m_skipAssets )
2009-01-28 09:22:12 +00:00
{
2010-04-16 21:29:11 +00:00
m_log . InfoFormat ( "[ARCHIVER]: Restored {0} assets" , successfulAssetRestores ) ;
if ( failedAssetRestores > 0 )
{
m_log . ErrorFormat ( "[ARCHIVER]: Failed to load {0} assets" , failedAssetRestores ) ;
m_errorMessage + = String . Format ( "Failed to load {0} assets" , failedAssetRestores ) ;
}
2009-01-28 09:22:12 +00:00
}
2009-02-04 00:01:36 +00:00
2012-07-24 16:48:08 +00:00
foreach ( DearchiveContext sceneContext in sceneContexts . Values )
2009-02-10 18:43:36 +00:00
{
2012-10-19 01:54:13 +00:00
m_log . InfoFormat ( "[ARCHIVER]: Loading region {0}" , sceneContext . Scene . RegionInfo . RegionName ) ;
2012-07-24 16:48:08 +00:00
if ( ! m_merge )
{
m_log . Info ( "[ARCHIVER]: Clearing all existing scene objects" ) ;
sceneContext . Scene . DeleteAllSceneObjects ( ) ;
}
try
{
LoadParcels ( sceneContext . Scene , sceneContext . SerialisedParcels ) ;
LoadObjects ( sceneContext . Scene , sceneContext . SerialisedSceneObjects , sceneContext . SceneObjects ) ;
// Inform any interested parties that the region has changed. We waited until now so that all
// of the region's objects will be loaded when we send this notification.
IEstateModule estateModule = sceneContext . Scene . RequestModuleInterface < IEstateModule > ( ) ;
if ( estateModule ! = null )
estateModule . TriggerRegionInfoChange ( ) ;
}
catch ( Exception e )
{
m_log . Error ( "[ARCHIVER]: Error loading parcels or objects " , e ) ;
m_errorMessage + = e . ToString ( ) ;
m_rootScene . EventManager . TriggerOarFileLoaded ( m_requestId , new List < UUID > ( ) , m_errorMessage ) ;
return ;
}
2009-02-10 18:43:36 +00:00
}
2009-02-04 00:01:36 +00:00
2012-07-24 16:48:08 +00:00
// Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
// that users can enter the scene. If we allow the scripts to start in the loop above
// then they significantly increase the time until the OAR finishes loading.
Util . FireAndForget ( delegate ( object o )
{
Thread . Sleep ( 15000 ) ;
2012-10-19 01:54:13 +00:00
m_log . Info ( "[ARCHIVER]: Starting scripts in scene objects" ) ;
2012-07-24 16:48:08 +00:00
foreach ( DearchiveContext sceneContext in sceneContexts . Values )
{
foreach ( SceneObjectGroup sceneObject in sceneContext . SceneObjects )
{
sceneObject . CreateScriptInstances ( 0 , false , sceneContext . Scene . DefaultScriptEngine , 0 ) ; // StateSource.RegionStart
sceneObject . ResumeScripts ( ) ;
}
sceneContext . SceneObjects . Clear ( ) ;
}
} ) ;
2009-10-02 09:10:52 +00:00
2011-01-27 21:07:21 +00:00
m_log . InfoFormat ( "[ARCHIVER]: Successfully loaded archive" ) ;
2009-10-02 09:10:52 +00:00
2012-07-24 16:48:08 +00:00
m_rootScene . EventManager . TriggerOarFileLoaded ( m_requestId , dearchivedScenes . GetLoadedScenes ( ) , m_errorMessage ) ;
}
/// <summary>
/// Searches through the files in the archive for the control file, and reads it.
/// We must read the control file first, in order to know which regions are available.
/// </summary>
/// <remarks>
/// In most cases the control file *is* first, since that's how we create archives. However,
/// it's possible that someone rewrote the archive externally so we can't rely on this fact.
/// </remarks>
/// <param name="archive"></param>
/// <param name="dearchivedScenes"></param>
private void FindAndLoadControlFile ( out TarArchiveReader archive , out DearchiveScenesInfo dearchivedScenes )
{
archive = new TarArchiveReader ( m_loadStream ) ;
dearchivedScenes = new DearchiveScenesInfo ( ) ;
string filePath ;
byte [ ] data ;
TarArchiveReader . TarEntryType entryType ;
bool firstFile = true ;
while ( ( data = archive . ReadEntry ( out filePath , out entryType ) ) ! = null )
{
if ( TarArchiveReader . TarEntryType . TYPE_DIRECTORY = = entryType )
continue ;
if ( filePath = = ArchiveConstants . CONTROL_FILE_PATH )
{
LoadControlFile ( filePath , data , dearchivedScenes ) ;
// Find which scenes are available in the simulator
ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup ( ) ;
SceneManager . Instance . ForEachScene ( delegate ( Scene scene2 )
{
simulatorScenes . AddScene ( scene2 ) ;
} ) ;
simulatorScenes . CalcSceneLocations ( ) ;
dearchivedScenes . SetSimulatorScenes ( m_rootScene , simulatorScenes ) ;
// If the control file wasn't the first file then reset the read pointer
if ( ! firstFile )
{
m_log . Warn ( "Control file wasn't the first file in the archive" ) ;
if ( m_loadStream . CanSeek )
{
m_loadStream . Seek ( 0 , SeekOrigin . Begin ) ;
}
else if ( m_loadPath ! = null )
{
archive . Close ( ) ;
archive = null ;
m_loadStream . Close ( ) ;
m_loadStream = null ;
m_loadStream = new GZipStream ( ArchiveHelpers . GetStream ( m_loadPath ) , CompressionMode . Decompress ) ;
archive = new TarArchiveReader ( m_loadStream ) ;
}
else
{
// There isn't currently a scenario where this happens, but it's best to add a check just in case
throw new Exception ( "Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking" ) ;
}
}
return ;
}
firstFile = false ;
}
throw new Exception ( "Control file not found" ) ;
2011-01-27 21:07:21 +00:00
}
/// <summary>
/// Load serialized scene objects.
/// </summary>
2012-07-24 16:48:08 +00:00
protected void LoadObjects ( Scene scene , List < string > serialisedSceneObjects , List < SceneObjectGroup > sceneObjects )
2011-01-27 21:07:21 +00:00
{
2008-05-30 16:08:28 +00:00
// Reload serialized prims
2008-07-13 00:18:29 +00:00
m_log . InfoFormat ( "[ARCHIVER]: Loading {0} scene objects. Please wait." , serialisedSceneObjects . Count ) ;
2008-06-04 09:59:27 +00:00
2014-02-02 19:17:49 +00:00
OpenMetaverse . Quaternion rot = OpenMetaverse . Quaternion . CreateFromAxisAngle ( 0 , 0 , 1 , m_rotation ) ;
2014-01-19 20:45:16 +00:00
2012-07-24 16:48:08 +00:00
UUID oldTelehubUUID = scene . RegionInfo . RegionSettings . TelehubObject ;
2012-05-03 16:38:35 +00:00
2012-07-24 16:48:08 +00:00
IRegionSerialiserModule serialiser = scene . RequestModuleInterface < IRegionSerialiserModule > ( ) ;
2009-09-30 16:00:09 +00:00
int sceneObjectsLoadedCount = 0 ;
2008-06-21 21:20:59 +00:00
2008-06-21 23:45:22 +00:00
foreach ( string serialisedSceneObject in serialisedSceneObjects )
2008-08-18 00:39:10 +00:00
{
2009-03-24 21:05:20 +00:00
/ *
2009-03-24 20:48:27 +00:00
m_log . DebugFormat ( "[ARCHIVER]: Loading xml with raw size {0}" , serialisedSceneObject . Length ) ;
// Really large xml files (multi megabyte) appear to cause
// memory problems
// when loading the xml. But don't enable this check yet
2009-03-24 21:05:20 +00:00
2009-03-24 20:48:27 +00:00
if ( serialisedSceneObject . Length > 5000000 )
{
m_log . Error ( "[ARCHIVER]: Ignoring xml since size > 5000000);" ) ;
continue ;
}
2009-03-24 21:05:20 +00:00
* /
2009-03-24 20:48:27 +00:00
2012-05-15 23:10:42 +00:00
SceneObjectGroup sceneObject = serialiser . DeserializeGroupFromXml2 ( serialisedSceneObject ) ;
2008-08-18 00:39:10 +00:00
2014-01-19 18:09:43 +00:00
// Happily this does not do much to the object since it hasn't been added to the scene yet
2014-02-16 01:10:20 +00:00
if ( ! sceneObject . IsAttachment )
2014-01-19 20:45:16 +00:00
{
2014-02-02 19:17:49 +00:00
if ( m_displacement ! = Vector3 . Zero | | m_rotation ! = 0f )
2014-01-19 20:45:16 +00:00
{
2014-02-02 19:17:49 +00:00
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 ;
2014-01-19 20:45:16 +00:00
}
}
2014-01-19 18:09:43 +00:00
2012-07-24 16:48:08 +00:00
bool isTelehub = ( sceneObject . UUID = = oldTelehubUUID ) & & ( oldTelehubUUID ! = UUID . Zero ) ;
2012-05-03 16:38:35 +00:00
2008-07-21 21:10:15 +00:00
// For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
// on the same region server and multiple examples a single object archive to be imported
// to the same scene (when this is possible).
sceneObject . ResetIDs ( ) ;
2008-08-18 00:39:10 +00:00
2012-05-03 16:38:35 +00:00
if ( isTelehub )
{
// Change the Telehub Object to the new UUID
2012-07-24 16:48:08 +00:00
scene . RegionInfo . RegionSettings . TelehubObject = sceneObject . UUID ;
scene . RegionInfo . RegionSettings . Save ( ) ;
2012-05-03 16:38:35 +00:00
oldTelehubUUID = UUID . Zero ;
}
2013-11-18 10:53:11 +00:00
ModifySceneObject ( scene , sceneObject ) ;
2008-08-18 00:39:10 +00:00
2012-07-24 16:48:08 +00:00
if ( scene . AddRestoredSceneObject ( sceneObject , true , false ) )
2008-08-18 00:39:10 +00:00
{
2009-03-24 20:48:27 +00:00
sceneObjectsLoadedCount + + ;
2012-07-24 16:48:08 +00:00
sceneObject . CreateScriptInstances ( 0 , false , scene . DefaultScriptEngine , 0 ) ;
2010-04-19 05:29:26 +00:00
sceneObject . ResumeScripts ( ) ;
2008-07-14 16:44:50 +00:00
}
2008-08-18 00:39:10 +00:00
}
2009-03-24 20:48:27 +00:00
m_log . InfoFormat ( "[ARCHIVER]: Restored {0} scene objects to the scene" , sceneObjectsLoadedCount ) ;
2008-08-18 00:39:10 +00:00
2009-03-24 20:48:27 +00:00
int ignoredObjects = serialisedSceneObjects . Count - sceneObjectsLoadedCount ;
2008-08-18 00:39:10 +00:00
2008-07-12 22:14:38 +00:00
if ( ignoredObjects > 0 )
2012-05-03 16:38:35 +00:00
m_log . WarnFormat ( "[ARCHIVER]: Ignored {0} scene objects that already existed in the scene" , ignoredObjects ) ;
if ( oldTelehubUUID ! = UUID . Zero )
{
m_log . WarnFormat ( "Telehub object not found: {0}" , oldTelehubUUID ) ;
2012-07-24 16:48:08 +00:00
scene . RegionInfo . RegionSettings . TelehubObject = UUID . Zero ;
scene . RegionInfo . RegionSettings . ClearSpawnPoints ( ) ;
2012-05-03 16:38:35 +00:00
}
2011-01-27 21:07:21 +00:00
}
2013-11-18 10:53:11 +00:00
/// <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 = 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 )
{
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 ;
}
}
}
}
2011-01-27 21:07:21 +00:00
/// <summary>
/// Load serialized parcels.
/// </summary>
2012-07-24 16:48:08 +00:00
/// <param name="scene"></param>
2011-01-27 21:07:21 +00:00
/// <param name="serialisedParcels"></param>
2012-07-24 16:48:08 +00:00
protected void LoadParcels ( Scene scene , List < string > serialisedParcels )
2011-01-27 21:07:21 +00:00
{
// Reload serialized parcels
m_log . InfoFormat ( "[ARCHIVER]: Loading {0} parcels. Please wait." , serialisedParcels . Count ) ;
List < LandData > landData = new List < LandData > ( ) ;
foreach ( string serialisedParcel in serialisedParcels )
{
LandData parcel = LandDataSerializer . Deserialize ( serialisedParcel ) ;
2014-01-19 20:45:16 +00:00
if ( m_displacement ! = Vector3 . Zero )
{
Vector3 parcelDisp = new Vector3 ( m_displacement . X , m_displacement . Y , 0f ) ;
parcel . AABBMin + = parcelDisp ;
parcel . AABBMax + = parcelDisp ;
}
2012-08-20 20:58:18 +00:00
// Validate User and Group UUID's
2012-11-24 02:43:31 +00:00
if ( parcel . IsGroupOwned )
{
if ( ! ResolveGroupUuid ( parcel . GroupID ) )
{
parcel . OwnerID = m_rootScene . RegionInfo . EstateSettings . EstateOwner ;
parcel . GroupID = UUID . Zero ;
parcel . IsGroupOwned = false ;
}
}
else
2012-08-20 20:58:18 +00:00
{
2012-11-24 02:43:31 +00:00
if ( ! ResolveUserUuid ( scene , parcel . OwnerID ) )
parcel . OwnerID = m_rootScene . RegionInfo . EstateSettings . EstateOwner ;
if ( ! ResolveGroupUuid ( parcel . GroupID ) )
parcel . GroupID = UUID . Zero ;
2012-08-20 20:58:18 +00:00
}
List < LandAccessEntry > accessList = new List < LandAccessEntry > ( ) ;
foreach ( LandAccessEntry entry in parcel . ParcelAccessList )
{
2012-07-24 16:48:08 +00:00
if ( ResolveUserUuid ( scene , entry . AgentID ) )
2012-08-20 20:58:18 +00:00
accessList . Add ( entry ) ;
// else, drop this access rule
}
parcel . ParcelAccessList = accessList ;
2011-01-27 21:07:21 +00:00
// m_log.DebugFormat(
2012-11-24 02:43:31 +00:00
// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
2011-01-27 21:07:21 +00:00
landData . Add ( parcel ) ;
}
2011-05-12 11:42:28 +00:00
if ( ! m_merge )
{
bool setupDefaultParcel = ( landData . Count = = 0 ) ;
2012-07-24 16:48:08 +00:00
scene . LandChannel . Clear ( setupDefaultParcel ) ;
2011-05-12 11:42:28 +00:00
}
2011-01-27 21:07:21 +00:00
2012-07-24 16:48:08 +00:00
scene . EventManager . TriggerIncomingLandDataFromStorage ( landData ) ;
2011-05-12 11:42:28 +00:00
m_log . InfoFormat ( "[ARCHIVER]: Restored {0} parcels." , landData . Count ) ;
2008-05-30 08:35:57 +00:00
}
2008-08-18 00:39:10 +00:00
2008-08-09 22:04:42 +00:00
/// <summary>
/// Look up the given user id to check whether it's one that is valid for this grid.
/// </summary>
2012-07-24 16:48:08 +00:00
/// <param name="scene"></param>
2008-08-09 22:04:42 +00:00
/// <param name="uuid"></param>
/// <returns></returns>
2012-07-24 16:48:08 +00:00
private bool ResolveUserUuid ( Scene scene , UUID uuid )
2008-08-09 22:04:42 +00:00
{
2012-08-09 11:51:05 +00:00
lock ( m_validUserUuids )
2008-08-09 22:04:42 +00:00
{
2012-08-09 11:51:05 +00:00
if ( ! m_validUserUuids . ContainsKey ( uuid ) )
{
// Note: we call GetUserAccount() inside the lock because this UserID is likely
// to occur many times, and we only want to query the users service once.
UserAccount account = scene . UserAccountService . GetUserAccount ( scene . RegionInfo . ScopeID , uuid ) ;
m_validUserUuids . Add ( uuid , account ! = null ) ;
}
2008-08-18 00:39:10 +00:00
2012-08-09 11:51:05 +00:00
return m_validUserUuids [ uuid ] ;
}
2008-08-09 22:04:42 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-27 20:08:29 +00:00
/// <summary>
2012-08-20 20:58:18 +00:00
/// Look up the given group id to check whether it's one that is valid for this grid.
/// </summary>
/// <param name="uuid"></param>
/// <returns></returns>
private bool ResolveGroupUuid ( UUID uuid )
{
if ( uuid = = UUID . Zero )
return true ; // this means the object has no group
2012-08-09 11:51:05 +00:00
lock ( m_validGroupUuids )
2012-08-20 20:58:18 +00:00
{
2012-08-09 11:51:05 +00:00
if ( ! m_validGroupUuids . ContainsKey ( uuid ) )
{
bool exists ;
if ( m_groupsModule = = null )
{
exists = false ;
}
else
{
// Note: we call GetGroupRecord() inside the lock because this GroupID is likely
// to occur many times, and we only want to query the groups service once.
exists = ( m_groupsModule . GetGroupRecord ( uuid ) ! = null ) ;
}
m_validGroupUuids . Add ( uuid , exists ) ;
}
2012-08-20 20:58:18 +00:00
2012-08-09 11:51:05 +00:00
return m_validGroupUuids [ uuid ] ;
2012-08-20 20:58:18 +00:00
}
}
2008-06-29 20:08:58 +00:00
/// Load an asset
2008-06-27 20:08:29 +00:00
/// </summary>
/// <param name="assetFilename"></param>
/// <param name="data"></param>
/// <returns>true if asset was successfully loaded, false otherwise</returns>
2008-08-09 22:04:42 +00:00
private bool LoadAsset ( string assetPath , byte [ ] data )
2008-06-27 20:08:29 +00:00
{
2008-09-06 07:52:41 +00:00
// Right now we're nastily obtaining the UUID from the filename
2008-06-27 20:08:29 +00:00
string filename = assetPath . Remove ( 0 , ArchiveConstants . ASSETS_PATH . Length ) ;
2008-08-26 18:14:10 +00:00
int i = filename . LastIndexOf ( ArchiveConstants . ASSET_EXTENSION_SEPARATOR ) ;
2008-08-28 14:41:54 +00:00
2008-08-26 18:14:10 +00:00
if ( i = = - 1 )
{
m_log . ErrorFormat (
"[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping" ,
assetPath , ArchiveConstants . ASSET_EXTENSION_SEPARATOR ) ;
2008-08-28 14:41:54 +00:00
2008-08-26 18:14:10 +00:00
return false ;
}
2008-08-28 14:41:54 +00:00
2008-08-26 18:14:10 +00:00
string extension = filename . Substring ( i ) ;
2008-08-18 00:39:10 +00:00
string uuid = filename . Remove ( filename . Length - extension . Length ) ;
2012-07-24 16:48:08 +00:00
if ( m_assetService . GetMetadata ( uuid ) ! = null )
2012-01-11 00:26:01 +00:00
{
// m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
return true ;
}
2008-06-27 20:08:29 +00:00
if ( ArchiveConstants . EXTENSION_TO_ASSET_TYPE . ContainsKey ( extension ) )
{
sbyte assetType = ArchiveConstants . EXTENSION_TO_ASSET_TYPE [ extension ] ;
2008-08-18 00:39:10 +00:00
2009-11-05 21:10:58 +00:00
if ( assetType = = ( sbyte ) AssetType . Unknown )
2013-11-18 10:53:11 +00:00
{
2009-11-05 21:10:58 +00:00
m_log . WarnFormat ( "[ARCHIVER]: Importing {0} byte asset {1} with unknown type" , data . Length , uuid ) ;
2013-11-18 10:53:11 +00:00
}
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 ;
}
2009-11-05 21:10:58 +00:00
2008-07-13 00:18:29 +00:00
//m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
2008-08-18 00:39:10 +00:00
2010-02-22 22:18:59 +00:00
AssetBase asset = new AssetBase ( new UUID ( uuid ) , String . Empty , assetType , UUID . Zero . ToString ( ) ) ;
2008-06-27 20:08:29 +00:00
asset . Data = data ;
2008-08-18 00:39:10 +00:00
2009-06-01 16:00:46 +00:00
// We're relying on the asset service to do the sensible thing and not store the asset if it already
// exists.
2012-07-24 16:48:08 +00:00
m_assetService . Store ( asset ) ;
2009-02-04 00:01:36 +00:00
/ * *
2009-01-23 20:38:44 +00:00
* Create layers on decode for image assets . This is likely to significantly increase the time to load archives so
* it might be best done when dearchive takes place on a separate thread
if ( asset . Type = AssetType . Texture )
{
IJ2KDecoder cacheLayerDecode = scene . RequestModuleInterface < IJ2KDecoder > ( ) ;
if ( cacheLayerDecode ! = null )
cacheLayerDecode . syncdecode ( asset . FullID , asset . Data ) ;
}
* /
2008-08-18 00:39:10 +00:00
2008-06-27 20:08:29 +00:00
return true ;
}
else
{
m_log . ErrorFormat (
2008-06-29 20:08:58 +00:00
"[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}" ,
2008-06-27 20:08:29 +00:00
assetPath , extension ) ;
2008-08-18 00:39:10 +00:00
2008-06-27 20:08:29 +00:00
return false ;
}
2008-06-29 20:08:58 +00:00
}
2009-02-04 00:01:36 +00:00
2008-12-30 19:00:19 +00:00
/// <summary>
/// Load region settings data
/// </summary>
2012-07-24 16:48:08 +00:00
/// <param name="scene"></param>
2008-12-30 19:00:19 +00:00
/// <param name="settingsPath"></param>
/// <param name="data"></param>
2012-07-24 16:48:08 +00:00
/// <param name="dearchivedScenes"></param>
2008-12-30 19:00:19 +00:00
/// <returns>
/// true if settings were loaded successfully, false otherwise
/// </returns>
2012-07-24 16:48:08 +00:00
private bool LoadRegionSettings ( Scene scene , string settingsPath , byte [ ] data , DearchiveScenesInfo dearchivedScenes )
2008-12-30 19:00:19 +00:00
{
RegionSettings loadedRegionSettings ;
2009-02-04 00:01:36 +00:00
2008-12-30 19:00:19 +00:00
try
{
loadedRegionSettings = RegionSettingsSerializer . Deserialize ( data ) ;
}
catch ( Exception e )
{
m_log . ErrorFormat (
2009-02-04 00:01:36 +00:00
"[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}" ,
2008-12-30 19:00:19 +00:00
settingsPath , e ) ;
return false ;
}
2009-02-04 00:01:36 +00:00
2012-07-24 16:48:08 +00:00
RegionSettings currentRegionSettings = scene . RegionInfo . RegionSettings ;
2009-02-04 00:01:36 +00:00
2008-12-30 19:00:19 +00:00
currentRegionSettings . AgentLimit = loadedRegionSettings . AgentLimit ;
currentRegionSettings . AllowDamage = loadedRegionSettings . AllowDamage ;
currentRegionSettings . AllowLandJoinDivide = loadedRegionSettings . AllowLandJoinDivide ;
currentRegionSettings . AllowLandResell = loadedRegionSettings . AllowLandResell ;
currentRegionSettings . BlockFly = loadedRegionSettings . BlockFly ;
currentRegionSettings . BlockShowInSearch = loadedRegionSettings . BlockShowInSearch ;
currentRegionSettings . BlockTerraform = loadedRegionSettings . BlockTerraform ;
currentRegionSettings . DisableCollisions = loadedRegionSettings . DisableCollisions ;
currentRegionSettings . DisablePhysics = loadedRegionSettings . DisablePhysics ;
currentRegionSettings . DisableScripts = loadedRegionSettings . DisableScripts ;
currentRegionSettings . Elevation1NE = loadedRegionSettings . Elevation1NE ;
currentRegionSettings . Elevation1NW = loadedRegionSettings . Elevation1NW ;
currentRegionSettings . Elevation1SE = loadedRegionSettings . Elevation1SE ;
currentRegionSettings . Elevation1SW = loadedRegionSettings . Elevation1SW ;
currentRegionSettings . Elevation2NE = loadedRegionSettings . Elevation2NE ;
currentRegionSettings . Elevation2NW = loadedRegionSettings . Elevation2NW ;
currentRegionSettings . Elevation2SE = loadedRegionSettings . Elevation2SE ;
currentRegionSettings . Elevation2SW = loadedRegionSettings . Elevation2SW ;
currentRegionSettings . FixedSun = loadedRegionSettings . FixedSun ;
2011-05-20 09:52:09 +00:00
currentRegionSettings . SunPosition = loadedRegionSettings . SunPosition ;
2008-12-30 19:00:19 +00:00
currentRegionSettings . ObjectBonus = loadedRegionSettings . ObjectBonus ;
currentRegionSettings . RestrictPushing = loadedRegionSettings . RestrictPushing ;
currentRegionSettings . TerrainLowerLimit = loadedRegionSettings . TerrainLowerLimit ;
currentRegionSettings . TerrainRaiseLimit = loadedRegionSettings . TerrainRaiseLimit ;
currentRegionSettings . TerrainTexture1 = loadedRegionSettings . TerrainTexture1 ;
currentRegionSettings . TerrainTexture2 = loadedRegionSettings . TerrainTexture2 ;
currentRegionSettings . TerrainTexture3 = loadedRegionSettings . TerrainTexture3 ;
currentRegionSettings . TerrainTexture4 = loadedRegionSettings . TerrainTexture4 ;
currentRegionSettings . UseEstateSun = loadedRegionSettings . UseEstateSun ;
currentRegionSettings . WaterHeight = loadedRegionSettings . WaterHeight ;
2012-05-03 16:38:35 +00:00
currentRegionSettings . TelehubObject = loadedRegionSettings . TelehubObject ;
currentRegionSettings . ClearSpawnPoints ( ) ;
foreach ( SpawnPoint sp in loadedRegionSettings . SpawnPoints ( ) )
currentRegionSettings . AddSpawnPoint ( sp ) ;
2010-02-26 18:30:05 +00:00
2012-07-24 16:48:08 +00:00
currentRegionSettings . LoadedCreationDateTime = dearchivedScenes . LoadedCreationDateTime ;
currentRegionSettings . LoadedCreationID = dearchivedScenes . GetOriginalRegionID ( scene . RegionInfo . RegionID ) . ToString ( ) ;
2010-02-26 18:30:05 +00:00
currentRegionSettings . Save ( ) ;
2011-05-20 09:52:09 +00:00
2012-07-24 16:48:08 +00:00
scene . TriggerEstateSunUpdate ( ) ;
2010-01-22 16:22:23 +00:00
2012-07-24 16:48:08 +00:00
IEstateModule estateModule = scene . RequestModuleInterface < IEstateModule > ( ) ;
2010-01-22 16:22:23 +00:00
if ( estateModule ! = null )
estateModule . sendRegionHandshakeToAll ( ) ;
2009-02-04 00:01:36 +00:00
2008-12-30 19:00:19 +00:00
return true ;
}
2008-08-18 00:39:10 +00:00
2008-06-29 20:08:58 +00:00
/// <summary>
/// Load terrain data
/// </summary>
2012-07-24 16:48:08 +00:00
/// <param name="scene"></param>
2008-06-29 20:08:58 +00:00
/// <param name="terrainPath"></param>
/// <param name="data"></param>
/// <returns>
/// true if terrain was resolved successfully, false otherwise.
/// </returns>
2012-07-24 16:48:08 +00:00
private bool LoadTerrain ( Scene scene , string terrainPath , byte [ ] data )
2008-06-29 20:08:58 +00:00
{
2012-07-24 16:48:08 +00:00
ITerrainModule terrainModule = scene . RequestModuleInterface < ITerrainModule > ( ) ;
2008-08-18 00:39:10 +00:00
2008-06-29 20:08:58 +00:00
MemoryStream ms = new MemoryStream ( data ) ;
2014-02-02 19:17:49 +00:00
if ( m_displacement ! = Vector3 . Zero | | m_rotation ! = 0f )
2014-01-19 18:09:43 +00:00
{
2014-02-02 19:17:49 +00:00
Vector2 rotationCenter = new Vector2 ( m_rotationCenter . X , m_rotationCenter . Y ) ;
terrainModule . LoadFromStream ( terrainPath , m_displacement , m_rotation , rotationCenter , ms ) ;
2014-01-19 18:09:43 +00:00
}
else
{
terrainModule . LoadFromStream ( terrainPath , ms ) ;
}
2008-06-29 20:08:58 +00:00
ms . Close ( ) ;
2008-08-18 00:39:10 +00:00
2008-07-13 00:18:29 +00:00
m_log . DebugFormat ( "[ARCHIVER]: Restored terrain {0}" , terrainPath ) ;
2008-08-18 00:39:10 +00:00
2008-06-29 20:08:58 +00:00
return true ;
}
2008-10-30 15:31:44 +00:00
2009-06-03 12:48:04 +00:00
/// <summary>
2009-06-12 14:18:01 +00:00
/// Load oar control file
2009-06-03 12:48:04 +00:00
/// </summary>
2009-06-12 14:18:01 +00:00
/// <param name="path"></param>
2009-06-03 12:48:04 +00:00
/// <param name="data"></param>
2012-07-24 16:48:08 +00:00
/// <param name="dearchivedScenes"></param>
public DearchiveScenesInfo LoadControlFile ( string path , byte [ ] data , DearchiveScenesInfo dearchivedScenes )
2009-06-03 12:48:04 +00:00
{
2010-10-22 17:47:38 +00:00
XmlNamespaceManager nsmgr = new XmlNamespaceManager ( new NameTable ( ) ) ;
2009-06-03 12:48:04 +00:00
XmlParserContext context = new XmlParserContext ( null , nsmgr , null , XmlSpace . None ) ;
2010-10-22 17:47:38 +00:00
XmlTextReader xtr = new XmlTextReader ( Encoding . ASCII . GetString ( data ) , XmlNodeType . Document , context ) ;
2009-06-03 12:48:04 +00:00
2012-07-24 16:48:08 +00:00
// Loaded metadata will be empty if no information exists in the archive
dearchivedScenes . LoadedCreationDateTime = 0 ;
dearchivedScenes . DefaultOriginalID = "" ;
2009-06-03 12:48:04 +00:00
2012-07-24 16:48:08 +00:00
bool multiRegion = false ;
2009-06-03 12:48:04 +00:00
while ( xtr . Read ( ) )
{
if ( xtr . NodeType = = XmlNodeType . Element )
{
2010-10-16 03:59:51 +00:00
if ( xtr . Name . ToString ( ) = = "archive" )
{
int majorVersion = int . Parse ( xtr [ "major_version" ] ) ;
int minorVersion = int . Parse ( xtr [ "minor_version" ] ) ;
string version = string . Format ( "{0}.{1}" , majorVersion , minorVersion ) ;
if ( majorVersion > MAX_MAJOR_VERSION )
{
throw new Exception (
string . Format (
"The OAR you are trying to load has major version number of {0} but this version of OpenSim can only load OARs with major version number {1} and below" ,
majorVersion , MAX_MAJOR_VERSION ) ) ;
}
m_log . InfoFormat ( "[ARCHIVER]: Loading OAR with version {0}" , version ) ;
}
2009-06-29 15:05:12 +00:00
if ( xtr . Name . ToString ( ) = = "datetime" )
2009-06-03 12:48:04 +00:00
{
2009-06-29 15:05:12 +00:00
int value ;
if ( Int32 . TryParse ( xtr . ReadElementContentAsString ( ) , out value ) )
2012-07-24 16:48:08 +00:00
dearchivedScenes . LoadedCreationDateTime = value ;
2009-06-03 12:48:04 +00:00
}
2012-07-24 16:48:08 +00:00
else if ( xtr . Name . ToString ( ) = = "row" )
{
multiRegion = true ;
dearchivedScenes . StartRow ( ) ;
}
else if ( xtr . Name . ToString ( ) = = "region" )
2009-06-03 12:48:04 +00:00
{
2012-07-24 16:48:08 +00:00
dearchivedScenes . StartRegion ( ) ;
}
else if ( xtr . Name . ToString ( ) = = "id" )
{
string id = xtr . ReadElementContentAsString ( ) ;
dearchivedScenes . DefaultOriginalID = id ;
if ( multiRegion )
dearchivedScenes . SetRegionOriginalID ( id ) ;
}
else if ( xtr . Name . ToString ( ) = = "dir" )
{
dearchivedScenes . SetRegionDirectory ( xtr . ReadElementContentAsString ( ) ) ;
2009-06-03 12:48:04 +00:00
}
}
}
2012-07-24 16:48:08 +00:00
dearchivedScenes . MultiRegionFormat = multiRegion ;
if ( ! multiRegion )
{
// Add the single scene
dearchivedScenes . StartRow ( ) ;
dearchivedScenes . StartRegion ( ) ;
dearchivedScenes . SetRegionOriginalID ( dearchivedScenes . DefaultOriginalID ) ;
dearchivedScenes . SetRegionDirectory ( "" ) ;
}
2011-04-18 21:35:33 +00:00
ControlFileLoaded = true ;
2012-07-24 16:48:08 +00:00
return dearchivedScenes ;
2009-06-03 12:48:04 +00:00
}
2008-05-30 08:35:57 +00:00
}
2013-11-18 10:53:11 +00:00
}