ArchiveReadRequest.cs 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.IO;
  30. using System.IO.Compression;
  31. using System.Net;
  32. using System.Reflection;
  33. using System.Text;
  34. using System.Xml;
  35. using log4net;
  36. using OpenMetaverse;
  37. using OpenSim.Framework;
  38. using OpenSim.Framework.Monitoring;
  39. using OpenSim.Framework.Serialization;
  40. using OpenSim.Framework.Serialization.External;
  41. using OpenSim.Region.CoreModules.World.Terrain;
  42. using OpenSim.Region.CoreModules.World.Land;
  43. using OpenSim.Region.Framework.Interfaces;
  44. using OpenSim.Region.Framework.Scenes;
  45. using OpenSim.Region.Framework.Scenes.Serialization;
  46. using OpenSim.Services.Interfaces;
  47. using System.Threading;
  48. namespace OpenSim.Region.CoreModules.World.Archiver
  49. {
  50. /// <summary>
  51. /// Handles an individual archive read request
  52. /// </summary>
  53. public class ArchiveReadRequest
  54. {
  55. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  56. /// <summary>
  57. /// Contains data used while dearchiving a single scene.
  58. /// </summary>
  59. private class DearchiveContext
  60. {
  61. public Scene Scene { get; set; }
  62. public List<string> SerialisedSceneObjects { get; set; }
  63. public List<string> SerialisedParcels { get; set; }
  64. public List<SceneObjectGroup> SceneObjects { get; set; }
  65. public DearchiveContext(Scene scene)
  66. {
  67. Scene = scene;
  68. SerialisedSceneObjects = new List<string>();
  69. SerialisedParcels = new List<string>();
  70. SceneObjects = new List<SceneObjectGroup>();
  71. }
  72. }
  73. /// <summary>
  74. /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
  75. /// bumps here should be compatible.
  76. /// </summary>
  77. public static int MAX_MAJOR_VERSION = 1;
  78. /// <summary>
  79. /// Has the control file been loaded for this archive?
  80. /// </summary>
  81. public bool ControlFileLoaded { get; private set; }
  82. protected string m_loadPath;
  83. protected Scene m_rootScene;
  84. protected Stream m_loadStream;
  85. protected Guid m_requestId;
  86. protected string m_errorMessage;
  87. /// <value>
  88. /// Should the archive being loaded be merged with what is already on the region?
  89. /// Merging usually suppresses terrain and parcel loading
  90. /// </value>
  91. protected bool m_merge;
  92. /// <value>
  93. /// If true, force the loading of terrain from the oar file
  94. /// </value>
  95. protected bool m_forceTerrain;
  96. /// <value>
  97. /// If true, force the loading of parcels from the oar file
  98. /// </value>
  99. protected bool m_forceParcels;
  100. /// <value>
  101. /// Should we ignore any assets when reloading the archive?
  102. /// </value>
  103. protected bool m_skipAssets;
  104. /// <value>
  105. /// Displacement added to each object as it is added to the world
  106. /// </value>
  107. protected Vector3 m_displacement = Vector3.Zero;
  108. /// <value>
  109. /// Rotation (in radians) to apply to the objects as they are loaded.
  110. /// </value>
  111. protected float m_rotation = 0f;
  112. /// <value>
  113. /// original oar region size. not using Constants.RegionSize
  114. /// </value>
  115. protected Vector3 m_incomingRegionSize = new Vector3(256f, 256f, float.MaxValue);
  116. /// <value>
  117. /// Center around which to apply the rotation relative to the original oar position
  118. /// </value>
  119. protected Vector3 m_rotationCenter = new Vector3(128f, 128f, 0f);
  120. /// <value>
  121. /// Corner 1 of a bounding cuboid which specifies which objects we load from the oar
  122. /// </value>
  123. protected Vector3 m_boundingOrigin = Vector3.Zero;
  124. /// <value>
  125. /// Size of a bounding cuboid which specifies which objects we load from the oar
  126. /// </value>
  127. protected Vector3 m_boundingSize = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, float.MaxValue);
  128. protected bool m_noObjects = false;
  129. protected bool m_boundingBox = false;
  130. protected bool m_debug = false;
  131. /// <summary>
  132. /// Used to cache lookups for valid uuids.
  133. /// </summary>
  134. private IDictionary<UUID, bool> m_validUserUuids = new Dictionary<UUID, bool>();
  135. private IUserManagement m_UserMan;
  136. private IUserManagement UserManager
  137. {
  138. get
  139. {
  140. if (m_UserMan == null)
  141. {
  142. m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>();
  143. }
  144. return m_UserMan;
  145. }
  146. }
  147. /// <summary>
  148. /// Used to cache lookups for valid groups.
  149. /// </summary>
  150. private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
  151. private IGroupsModule m_groupsModule;
  152. private IAssetService m_assetService = null;
  153. private UUID m_defaultUser;
  154. public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options)
  155. {
  156. m_rootScene = scene;
  157. if (options.ContainsKey("default-user"))
  158. {
  159. m_defaultUser = (UUID)options["default-user"];
  160. m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString());
  161. }
  162. else
  163. {
  164. m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
  165. }
  166. m_loadPath = loadPath;
  167. try
  168. {
  169. m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
  170. }
  171. catch (EntryPointNotFoundException e)
  172. {
  173. m_log.ErrorFormat(
  174. "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
  175. + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
  176. m_log.Error(e);
  177. }
  178. m_errorMessage = String.Empty;
  179. m_merge = options.ContainsKey("merge");
  180. m_forceTerrain = options.ContainsKey("force-terrain");
  181. m_forceParcels = options.ContainsKey("force-parcels");
  182. m_noObjects = options.ContainsKey("no-objects");
  183. m_skipAssets = options.ContainsKey("skipAssets");
  184. m_requestId = requestId;
  185. m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
  186. m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
  187. m_boundingOrigin = Vector3.Zero;
  188. m_boundingSize = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, float.MaxValue);
  189. if (options.ContainsKey("bounding-origin"))
  190. {
  191. Vector3 boOption = (Vector3)options["bounding-origin"];
  192. if (boOption != m_boundingOrigin)
  193. {
  194. m_boundingOrigin = boOption;
  195. }
  196. m_boundingBox = true;
  197. }
  198. if (options.ContainsKey("bounding-size"))
  199. {
  200. Vector3 bsOption = (Vector3)options["bounding-size"];
  201. bool clip = false;
  202. if (bsOption.X <= 0 || bsOption.X > m_boundingSize.X)
  203. {
  204. bsOption.X = m_boundingSize.X;
  205. clip = true;
  206. }
  207. if (bsOption.Y <= 0 || bsOption.Y > m_boundingSize.Y)
  208. {
  209. bsOption.Y = m_boundingSize.Y;
  210. clip = true;
  211. }
  212. if (bsOption != m_boundingSize)
  213. {
  214. m_boundingSize = bsOption;
  215. m_boundingBox = true;
  216. }
  217. if (clip) m_log.InfoFormat("[ARCHIVER]: The bounding cube specified is larger than the destination region! Clipping to {0}.", m_boundingSize.ToString());
  218. }
  219. m_debug = options.ContainsKey("debug");
  220. // Zero can never be a valid user id (or group)
  221. m_validUserUuids[UUID.Zero] = false;
  222. m_validGroupUuids[UUID.Zero] = false;
  223. m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
  224. m_assetService = m_rootScene.AssetService;
  225. }
  226. public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object> options)
  227. {
  228. m_rootScene = scene;
  229. m_loadPath = null;
  230. m_loadStream = loadStream;
  231. m_skipAssets = options.ContainsKey("skipAssets");
  232. m_merge = options.ContainsKey("merge");
  233. m_requestId = requestId;
  234. m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
  235. // Zero can never be a valid user id
  236. m_validUserUuids[UUID.Zero] = false;
  237. m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
  238. m_assetService = m_rootScene.AssetService;
  239. }
  240. /// <summary>
  241. /// Dearchive the region embodied in this request.
  242. /// </summary>
  243. public void DearchiveRegion()
  244. {
  245. int successfulAssetRestores = 0;
  246. int failedAssetRestores = 0;
  247. DearchiveScenesInfo dearchivedScenes;
  248. // We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
  249. // Therefore, we have to keep track of the dearchive context of all the scenes.
  250. Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>();
  251. string fullPath = "NONE";
  252. TarArchiveReader archive = null;
  253. byte[] data;
  254. TarArchiveReader.TarEntryType entryType;
  255. try
  256. {
  257. FindAndLoadControlFile(out archive, out dearchivedScenes);
  258. while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
  259. {
  260. //m_log.DebugFormat(
  261. // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
  262. if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
  263. continue;
  264. // Find the scene that this file belongs to
  265. Scene scene;
  266. string filePath;
  267. if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath))
  268. continue; // this file belongs to a region that we're not loading
  269. DearchiveContext sceneContext = null;
  270. if (scene != null)
  271. {
  272. if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext))
  273. {
  274. sceneContext = new DearchiveContext(scene);
  275. sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext);
  276. }
  277. }
  278. // Process the file
  279. if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH) && !m_noObjects)
  280. {
  281. sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
  282. }
  283. else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
  284. {
  285. if (LoadAsset(filePath, data))
  286. successfulAssetRestores++;
  287. else
  288. failedAssetRestores++;
  289. if ((successfulAssetRestores + failedAssetRestores) % 250 == 0)
  290. m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets...");
  291. }
  292. else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH) && (!m_merge || m_forceTerrain))
  293. {
  294. LoadTerrain(scene, filePath, data);
  295. }
  296. else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
  297. {
  298. LoadRegionSettings(scene, filePath, data, dearchivedScenes);
  299. }
  300. else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH) && (!m_merge || m_forceParcels))
  301. {
  302. sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
  303. }
  304. else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
  305. {
  306. // Ignore, because we already read the control file
  307. }
  308. }
  309. //m_log.Debug("[ARCHIVER]: Reached end of archive");
  310. }
  311. catch (Exception e)
  312. {
  313. m_log.Error(
  314. String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e);
  315. m_errorMessage += e.ToString();
  316. m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
  317. return;
  318. }
  319. finally
  320. {
  321. if (archive != null)
  322. archive.Close();
  323. }
  324. if (!m_skipAssets)
  325. {
  326. m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores);
  327. if (failedAssetRestores > 0)
  328. {
  329. m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores);
  330. m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores);
  331. }
  332. }
  333. foreach (DearchiveContext sceneContext in sceneContexts.Values)
  334. {
  335. m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
  336. if (!m_merge)
  337. {
  338. m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
  339. sceneContext.Scene.DeleteAllSceneObjects();
  340. }
  341. try
  342. {
  343. LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
  344. LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
  345. // Inform any interested parties that the region has changed. We waited until now so that all
  346. // of the region's objects will be loaded when we send this notification.
  347. IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
  348. if (estateModule != null)
  349. estateModule.TriggerRegionInfoChange();
  350. }
  351. catch (Exception e)
  352. {
  353. m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e);
  354. m_errorMessage += e.ToString();
  355. m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
  356. return;
  357. }
  358. }
  359. // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
  360. // that users can enter the scene. If we allow the scripts to start in the loop above
  361. // then they significantly increase the time until the OAR finishes loading.
  362. WorkManager.RunInThread(o =>
  363. {
  364. Thread.Sleep(15000);
  365. m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
  366. foreach (DearchiveContext sceneContext in sceneContexts.Values)
  367. {
  368. foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
  369. {
  370. sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
  371. sceneObject.ResumeScripts();
  372. }
  373. sceneContext.SceneObjects.Clear();
  374. }
  375. }, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId));
  376. m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
  377. m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage);
  378. }
  379. /// <summary>
  380. /// Searches through the files in the archive for the control file, and reads it.
  381. /// We must read the control file first, in order to know which regions are available.
  382. /// </summary>
  383. /// <remarks>
  384. /// In most cases the control file *is* first, since that's how we create archives. However,
  385. /// it's possible that someone rewrote the archive externally so we can't rely on this fact.
  386. /// </remarks>
  387. /// <param name="archive"></param>
  388. /// <param name="dearchivedScenes"></param>
  389. private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes)
  390. {
  391. archive = new TarArchiveReader(m_loadStream);
  392. dearchivedScenes = new DearchiveScenesInfo();
  393. string filePath;
  394. byte[] data;
  395. TarArchiveReader.TarEntryType entryType;
  396. bool firstFile = true;
  397. while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
  398. {
  399. if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
  400. continue;
  401. if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
  402. {
  403. LoadControlFile(filePath, data, dearchivedScenes);
  404. // Find which scenes are available in the simulator
  405. ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup();
  406. SceneManager.Instance.ForEachScene(delegate(Scene scene2)
  407. {
  408. simulatorScenes.AddScene(scene2);
  409. });
  410. simulatorScenes.CalcSceneLocations();
  411. dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes);
  412. // If the control file wasn't the first file then reset the read pointer
  413. if (!firstFile)
  414. {
  415. m_log.Warn("[ARCHIVER]: Control file wasn't the first file in the archive");
  416. if (m_loadStream.CanSeek)
  417. {
  418. m_loadStream.Seek(0, SeekOrigin.Begin);
  419. }
  420. else if (m_loadPath != null)
  421. {
  422. archive.Close();
  423. archive = null;
  424. m_loadStream.Close();
  425. m_loadStream = null;
  426. m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress);
  427. archive = new TarArchiveReader(m_loadStream);
  428. }
  429. else
  430. {
  431. // There isn't currently a scenario where this happens, but it's best to add a check just in case
  432. throw new Exception("[ARCHIVER]: Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
  433. }
  434. }
  435. return;
  436. }
  437. firstFile = false;
  438. }
  439. throw new Exception("[ARCHIVER]: Control file not found");
  440. }
  441. /// <summary>
  442. /// Load serialized scene objects.
  443. /// </summary>
  444. protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects)
  445. {
  446. // Reload serialized prims
  447. m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
  448. // Convert rotation to radians
  449. double rotation = Math.PI * m_rotation / 180f;
  450. OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, (float)rotation);
  451. UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
  452. IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
  453. int sceneObjectsLoadedCount = 0;
  454. Vector3 boundingExtent = new Vector3(m_boundingOrigin.X + m_boundingSize.X, m_boundingOrigin.Y + m_boundingSize.Y, m_boundingOrigin.Z + m_boundingSize.Z);
  455. foreach (string serialisedSceneObject in serialisedSceneObjects)
  456. {
  457. /*
  458. m_log.DebugFormat("[ARCHIVER]: Loading xml with raw size {0}", serialisedSceneObject.Length);
  459. // Really large xml files (multi megabyte) appear to cause
  460. // memory problems
  461. // when loading the xml. But don't enable this check yet
  462. if (serialisedSceneObject.Length > 5000000)
  463. {
  464. m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);");
  465. continue;
  466. }
  467. */
  468. SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
  469. Vector3 pos = sceneObject.AbsolutePosition;
  470. if (m_debug)
  471. m_log.DebugFormat("[ARCHIVER]: Loading object from OAR with original scene position {0}.", pos.ToString());
  472. // Happily this does not do much to the object since it hasn't been added to the scene yet
  473. if (!sceneObject.IsAttachment)
  474. {
  475. if (m_rotation != 0f)
  476. {
  477. //fix the rotation center to the middle of the incoming region now as it's otherwise hopelessly confusing on varRegions
  478. //as it only works with objects and terrain (using old Merge method) and not parcels
  479. m_rotationCenter.X = m_incomingRegionSize.X / 2;
  480. m_rotationCenter.Y = m_incomingRegionSize.Y / 2;
  481. // Rotate the object
  482. sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
  483. // Get object position relative to rotation axis
  484. Vector3 offset = pos - m_rotationCenter;
  485. // Rotate the object position
  486. offset *= rot;
  487. // Restore the object position back to relative to the region
  488. pos = m_rotationCenter + offset;
  489. if (m_debug) m_log.DebugFormat("[ARCHIVER]: After rotation, object from OAR is at scene position {0}.", pos.ToString());
  490. }
  491. if (m_boundingBox)
  492. {
  493. if (pos.X < m_boundingOrigin.X || pos.X >= boundingExtent.X
  494. || pos.Y < m_boundingOrigin.Y || pos.Y >= boundingExtent.Y
  495. || pos.Z < m_boundingOrigin.Z || pos.Z >= boundingExtent.Z)
  496. {
  497. if (m_debug) m_log.DebugFormat("[ARCHIVER]: Skipping object from OAR in scene because it's position {0} is outside of bounding cube.", pos.ToString());
  498. continue;
  499. }
  500. //adjust object position to be relative to <0,0> so we can apply the displacement
  501. pos.X -= m_boundingOrigin.X;
  502. pos.Y -= m_boundingOrigin.Y;
  503. }
  504. if (m_displacement != Vector3.Zero)
  505. {
  506. pos += m_displacement;
  507. if (m_debug) m_log.DebugFormat("[ARCHIVER]: After displacement, object from OAR is at scene position {0}.", pos.ToString());
  508. }
  509. sceneObject.AbsolutePosition = pos;
  510. }
  511. if (m_debug)
  512. m_log.DebugFormat("[ARCHIVER]: Placing object from OAR in scene at position {0}. ", pos.ToString());
  513. bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
  514. // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
  515. // on the same region server and multiple examples a single object archive to be imported
  516. // to the same scene (when this is possible).
  517. sceneObject.ResetIDs();
  518. if (isTelehub)
  519. {
  520. // Change the Telehub Object to the new UUID
  521. scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
  522. scene.RegionInfo.RegionSettings.Save();
  523. oldTelehubUUID = UUID.Zero;
  524. }
  525. ModifySceneObject(scene, sceneObject);
  526. if (scene.AddRestoredSceneObject(sceneObject, true, false))
  527. {
  528. sceneObjectsLoadedCount++;
  529. sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0);
  530. sceneObject.ResumeScripts();
  531. }
  532. }
  533. m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjectsLoadedCount);
  534. int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;
  535. if (ignoredObjects > 0)
  536. m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene or were out of bounds", ignoredObjects);
  537. if (oldTelehubUUID != UUID.Zero)
  538. {
  539. m_log.WarnFormat("[ARCHIVER]: Telehub object not found: {0}", oldTelehubUUID);
  540. scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
  541. scene.RegionInfo.RegionSettings.ClearSpawnPoints();
  542. }
  543. }
  544. /// <summary>
  545. /// Optionally modify a loaded SceneObjectGroup. Currently this just ensures that the
  546. /// User IDs and Group IDs are valid, but other manipulations could be done as well.
  547. /// </summary>
  548. private void ModifySceneObject(Scene scene, SceneObjectGroup sceneObject)
  549. {
  550. // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
  551. // or creator data is present. Otherwise, use the estate owner instead.
  552. foreach (SceneObjectPart part in sceneObject.Parts)
  553. {
  554. if (string.IsNullOrEmpty(part.CreatorData))
  555. {
  556. if (!ResolveUserUuid(scene, part.CreatorID))
  557. part.CreatorID = m_defaultUser;
  558. }
  559. if (UserManager != null)
  560. UserManager.AddUser(part.CreatorID, part.CreatorData);
  561. if (!(ResolveUserUuid(scene, part.OwnerID) || ResolveGroupUuid(part.OwnerID)))
  562. part.OwnerID = m_defaultUser;
  563. if (!(ResolveUserUuid(scene, part.LastOwnerID) || ResolveGroupUuid(part.LastOwnerID)))
  564. part.LastOwnerID = m_defaultUser;
  565. if (!ResolveGroupUuid(part.GroupID))
  566. part.GroupID = UUID.Zero;
  567. // And zap any troublesome sit target information
  568. // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
  569. // part.SitTargetPosition = new Vector3(0, 0, 0);
  570. // Fix ownership/creator of inventory items
  571. // Not doing so results in inventory items
  572. // being no copy/no mod for everyone
  573. lock (part.TaskInventory)
  574. {
  575. /* avination code disabled for opensim
  576. // And zap any troublesome sit target information
  577. part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
  578. part.SitTargetPosition = new Vector3(0, 0, 0);
  579. */
  580. // Fix ownership/creator of inventory items
  581. // Not doing so results in inventory items
  582. // being no copy/no mod for everyone
  583. part.TaskInventory.LockItemsForRead(true);
  584. TaskInventoryDictionary inv = part.TaskInventory;
  585. foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
  586. {
  587. if (!(ResolveUserUuid(scene, kvp.Value.OwnerID) || ResolveGroupUuid(kvp.Value.OwnerID)))
  588. {
  589. kvp.Value.OwnerID = m_defaultUser;
  590. }
  591. if (string.IsNullOrEmpty(kvp.Value.CreatorData))
  592. {
  593. if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
  594. kvp.Value.CreatorID = m_defaultUser;
  595. }
  596. if (UserManager != null)
  597. UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
  598. if (!ResolveGroupUuid(kvp.Value.GroupID))
  599. kvp.Value.GroupID = UUID.Zero;
  600. }
  601. part.TaskInventory.LockItemsForRead(false);
  602. }
  603. }
  604. }
  605. /// <summary>
  606. /// Load serialized parcels.
  607. /// </summary>
  608. /// <param name="scene"></param>
  609. /// <param name="serialisedParcels"></param>
  610. protected void LoadParcels(Scene scene, List<string> serialisedParcels)
  611. {
  612. // Reload serialized parcels
  613. m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
  614. List<LandData> landData = new List<LandData>();
  615. ILandObject landObject = scene.RequestModuleInterface<ILandObject>();
  616. List<ILandObject> parcels;
  617. Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
  618. Vector2 displacement = new Vector2(m_displacement.X, m_displacement.Y);
  619. Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
  620. Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
  621. Vector2 regionSize = new Vector2(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY);
  622. // Gather any existing parcels before we add any more. Later as we add parcels we can check if the new parcel
  623. // data overlays any of the old data, and we can modify and remove (if empty) the old parcel so that there's no conflict
  624. parcels = scene.LandChannel.AllParcels();
  625. foreach (string serialisedParcel in serialisedParcels)
  626. {
  627. LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
  628. bool overrideRegionSize = true; //use the src land parcel data size not the dst region size
  629. bool isEmptyNow;
  630. Vector3 AABBMin;
  631. Vector3 AABBMax;
  632. // create a new LandObject that we can use to manipulate the incoming source parcel data
  633. // this is ok, but just beware that some of the LandObject functions (that we haven't used here) still
  634. // assume we're always using the destination region size
  635. LandData ld = new LandData();
  636. landObject = new LandObject(ld, scene);
  637. landObject.LandData = parcel;
  638. bool[,] srcLandBitmap = landObject.ConvertBytesToLandBitmap(overrideRegionSize);
  639. if (landObject.IsLandBitmapEmpty(srcLandBitmap))
  640. {
  641. m_log.InfoFormat("[ARCHIVER]: Skipping source parcel {0} with GlobalID: {1} LocalID: {2} that has no claimed land.",
  642. parcel.Name, parcel.GlobalID, parcel.LocalID);
  643. continue;
  644. }
  645. //m_log.DebugFormat("[ARCHIVER]: Showing claimed land for source parcel: {0} with GlobalID: {1} LocalID: {2}.",
  646. // parcel.Name, parcel.GlobalID, parcel.LocalID);
  647. //landObject.DebugLandBitmap(srcLandBitmap);
  648. bool[,] dstLandBitmap = landObject.RemapLandBitmap(srcLandBitmap, displacement, m_rotation, boundingOrigin, boundingSize, regionSize, out isEmptyNow, out AABBMin, out AABBMax);
  649. if (isEmptyNow)
  650. {
  651. m_log.WarnFormat("[ARCHIVER]: Not adding destination parcel {0} with GlobalID: {1} LocalID: {2} because, after applying rotation, bounding and displacement, it has no claimed land.",
  652. parcel.Name, parcel.GlobalID, parcel.LocalID);
  653. continue;
  654. }
  655. //m_log.DebugFormat("[ARCHIVER]: Showing claimed land for destination parcel: {0} with GlobalID: {1} LocalID: {2} after applying rotation, bounding and displacement.",
  656. // parcel.Name, parcel.GlobalID, parcel.LocalID);
  657. //landObject.DebugLandBitmap(dstLandBitmap);
  658. landObject.LandBitmap = dstLandBitmap;
  659. parcel.Bitmap = landObject.ConvertLandBitmapToBytes();
  660. parcel.AABBMin = AABBMin;
  661. parcel.AABBMax = AABBMax;
  662. if (m_merge)
  663. {
  664. // give the remapped parcel a new GlobalID, in case we're using the same OAR twice and a bounding cube, displacement and --merge
  665. parcel.GlobalID = UUID.Random();
  666. //now check if the area of this new incoming parcel overlays an area in any existing parcels
  667. //and if so modify or lose the existing parcels
  668. for (int i = 0; i < parcels.Count; i++)
  669. {
  670. if (parcels[i] != null)
  671. {
  672. bool[,] modLandBitmap = parcels[i].ConvertBytesToLandBitmap(overrideRegionSize);
  673. modLandBitmap = parcels[i].RemoveFromLandBitmap(modLandBitmap, dstLandBitmap, out isEmptyNow, out AABBMin, out AABBMax);
  674. if (isEmptyNow)
  675. {
  676. parcels[i] = null;
  677. }
  678. else
  679. {
  680. parcels[i].LandBitmap = modLandBitmap;
  681. parcels[i].LandData.Bitmap = parcels[i].ConvertLandBitmapToBytes();
  682. parcels[i].LandData.AABBMin = AABBMin;
  683. parcels[i].LandData.AABBMax = AABBMax;
  684. }
  685. }
  686. }
  687. }
  688. // Validate User and Group UUID's
  689. if (!ResolveGroupUuid(parcel.GroupID))
  690. parcel.GroupID = UUID.Zero;
  691. if (parcel.IsGroupOwned)
  692. {
  693. if (parcel.GroupID != UUID.Zero)
  694. {
  695. // In group-owned parcels, OwnerID=GroupID. This should already be the case, but let's make sure.
  696. parcel.OwnerID = parcel.GroupID;
  697. }
  698. else
  699. {
  700. parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
  701. parcel.IsGroupOwned = false;
  702. }
  703. }
  704. else
  705. {
  706. if (!ResolveUserUuid(scene, parcel.OwnerID))
  707. parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
  708. }
  709. List<LandAccessEntry> accessList = new List<LandAccessEntry>();
  710. foreach (LandAccessEntry entry in parcel.ParcelAccessList)
  711. {
  712. if (ResolveUserUuid(scene, entry.AgentID))
  713. accessList.Add(entry);
  714. // else, drop this access rule
  715. }
  716. parcel.ParcelAccessList = accessList;
  717. if (m_debug) m_log.DebugFormat("[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
  718. parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
  719. landData.Add(parcel);
  720. }
  721. if (m_merge)
  722. {
  723. for (int i = 0; i < parcels.Count; i++) //if merging then we need to also add back in any existing parcels
  724. {
  725. if (parcels[i] != null) landData.Add(parcels[i].LandData);
  726. }
  727. }
  728. m_log.InfoFormat("[ARCHIVER]: Clearing {0} parcels.", parcels.Count);
  729. bool setupDefaultParcel = (landData.Count == 0);
  730. scene.LandChannel.Clear(setupDefaultParcel);
  731. scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
  732. m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
  733. }
  734. /// <summary>
  735. /// Look up the given user id to check whether it's one that is valid for this grid.
  736. /// </summary>
  737. /// <param name="scene"></param>
  738. /// <param name="uuid"></param>
  739. /// <returns></returns>
  740. private bool ResolveUserUuid(Scene scene, UUID uuid)
  741. {
  742. lock (m_validUserUuids)
  743. {
  744. if (!m_validUserUuids.ContainsKey(uuid))
  745. {
  746. // Note: we call GetUserAccount() inside the lock because this UserID is likely
  747. // to occur many times, and we only want to query the users service once.
  748. UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid);
  749. m_validUserUuids.Add(uuid, account != null);
  750. }
  751. return m_validUserUuids[uuid];
  752. }
  753. }
  754. /// <summary>
  755. /// Look up the given group id to check whether it's one that is valid for this grid.
  756. /// </summary>
  757. /// <param name="uuid"></param>
  758. /// <returns></returns>
  759. private bool ResolveGroupUuid(UUID uuid)
  760. {
  761. lock (m_validGroupUuids)
  762. {
  763. if (!m_validGroupUuids.ContainsKey(uuid))
  764. {
  765. bool exists;
  766. if (m_groupsModule == null)
  767. {
  768. exists = false;
  769. }
  770. else
  771. {
  772. // Note: we call GetGroupRecord() inside the lock because this GroupID is likely
  773. // to occur many times, and we only want to query the groups service once.
  774. exists = (m_groupsModule.GetGroupRecord(uuid) != null);
  775. }
  776. m_validGroupUuids.Add(uuid, exists);
  777. }
  778. return m_validGroupUuids[uuid];
  779. }
  780. }
  781. /// Load an asset
  782. /// </summary>
  783. /// <param name="assetFilename"></param>
  784. /// <param name="data"></param>
  785. /// <returns>true if asset was successfully loaded, false otherwise</returns>
  786. private bool LoadAsset(string assetPath, byte[] data)
  787. {
  788. // Right now we're nastily obtaining the UUID from the filename
  789. string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
  790. int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
  791. if (i == -1)
  792. {
  793. m_log.ErrorFormat(
  794. "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping",
  795. assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
  796. return false;
  797. }
  798. string extension = filename.Substring(i);
  799. string uuid = filename.Remove(filename.Length - extension.Length);
  800. if (m_assetService.GetMetadata(uuid) != null)
  801. {
  802. sbyte asype = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
  803. if(asype == -2)
  804. {
  805. }
  806. // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
  807. return true;
  808. }
  809. if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
  810. {
  811. sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
  812. if(assetType == -2)
  813. {
  814. }
  815. if (assetType == (sbyte)AssetType.Unknown)
  816. {
  817. m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
  818. }
  819. else if (assetType == (sbyte)AssetType.Object)
  820. {
  821. data = SceneObjectSerializer.ModifySerializedObject(UUID.Parse(uuid), data,
  822. sog =>
  823. {
  824. ModifySceneObject(m_rootScene, sog);
  825. return true;
  826. });
  827. if (data == null)
  828. return false;
  829. }
  830. //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
  831. AssetBase asset = new AssetBase(new UUID(uuid), String.Empty, assetType, UUID.Zero.ToString());
  832. asset.Data = data;
  833. // We're relying on the asset service to do the sensible thing and not store the asset if it already
  834. // exists.
  835. m_assetService.Store(asset);
  836. /**
  837. * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
  838. * it might be best done when dearchive takes place on a separate thread
  839. if (asset.Type=AssetType.Texture)
  840. {
  841. IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
  842. if (cacheLayerDecode != null)
  843. cacheLayerDecode.syncdecode(asset.FullID, asset.Data);
  844. }
  845. */
  846. return true;
  847. }
  848. else
  849. {
  850. m_log.ErrorFormat(
  851. "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
  852. assetPath, extension);
  853. return false;
  854. }
  855. }
  856. /// <summary>
  857. /// Load region settings data
  858. /// </summary>
  859. /// <param name="scene"></param>
  860. /// <param name="settingsPath"></param>
  861. /// <param name="data"></param>
  862. /// <param name="dearchivedScenes"></param>
  863. /// <returns>
  864. /// true if settings were loaded successfully, false otherwise
  865. /// </returns>
  866. private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes)
  867. {
  868. RegionSettings loadedRegionSettings;
  869. try
  870. {
  871. loadedRegionSettings = RegionSettingsSerializer.Deserialize(data);
  872. }
  873. catch (Exception e)
  874. {
  875. m_log.ErrorFormat(
  876. "[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}",
  877. settingsPath, e);
  878. return false;
  879. }
  880. RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings;
  881. currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
  882. currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
  883. currentRegionSettings.AllowLandJoinDivide = loadedRegionSettings.AllowLandJoinDivide;
  884. currentRegionSettings.AllowLandResell = loadedRegionSettings.AllowLandResell;
  885. currentRegionSettings.BlockFly = loadedRegionSettings.BlockFly;
  886. currentRegionSettings.BlockShowInSearch = loadedRegionSettings.BlockShowInSearch;
  887. currentRegionSettings.BlockTerraform = loadedRegionSettings.BlockTerraform;
  888. currentRegionSettings.DisableCollisions = loadedRegionSettings.DisableCollisions;
  889. currentRegionSettings.DisablePhysics = loadedRegionSettings.DisablePhysics;
  890. currentRegionSettings.DisableScripts = loadedRegionSettings.DisableScripts;
  891. currentRegionSettings.Elevation1NE = loadedRegionSettings.Elevation1NE;
  892. currentRegionSettings.Elevation1NW = loadedRegionSettings.Elevation1NW;
  893. currentRegionSettings.Elevation1SE = loadedRegionSettings.Elevation1SE;
  894. currentRegionSettings.Elevation1SW = loadedRegionSettings.Elevation1SW;
  895. currentRegionSettings.Elevation2NE = loadedRegionSettings.Elevation2NE;
  896. currentRegionSettings.Elevation2NW = loadedRegionSettings.Elevation2NW;
  897. currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE;
  898. currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW;
  899. currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun;
  900. currentRegionSettings.SunPosition = loadedRegionSettings.SunPosition;
  901. currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus;
  902. currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing;
  903. currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit;
  904. currentRegionSettings.TerrainRaiseLimit = loadedRegionSettings.TerrainRaiseLimit;
  905. currentRegionSettings.TerrainTexture1 = loadedRegionSettings.TerrainTexture1;
  906. currentRegionSettings.TerrainTexture2 = loadedRegionSettings.TerrainTexture2;
  907. currentRegionSettings.TerrainTexture3 = loadedRegionSettings.TerrainTexture3;
  908. currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4;
  909. currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun;
  910. currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight;
  911. currentRegionSettings.TelehubObject = loadedRegionSettings.TelehubObject;
  912. currentRegionSettings.ClearSpawnPoints();
  913. foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
  914. currentRegionSettings.AddSpawnPoint(sp);
  915. currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
  916. currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
  917. currentRegionSettings.Save();
  918. scene.TriggerEstateSunUpdate();
  919. IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
  920. if (estateModule != null)
  921. estateModule.sendRegionHandshakeToAll();
  922. return true;
  923. }
  924. /// <summary>
  925. /// Load terrain data
  926. /// </summary>
  927. /// <param name="scene"></param>
  928. /// <param name="terrainPath"></param>
  929. /// <param name="data"></param>
  930. /// <returns>
  931. /// true if terrain was resolved successfully, false otherwise.
  932. /// </returns>
  933. private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
  934. {
  935. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  936. using (MemoryStream ms = new MemoryStream(data))
  937. {
  938. if (m_displacement != Vector3.Zero || m_rotation != 0f || m_boundingBox)
  939. {
  940. Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
  941. Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
  942. terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, boundingOrigin, boundingSize, ms); ;
  943. }
  944. else
  945. {
  946. terrainModule.LoadFromStream(terrainPath, ms);
  947. }
  948. }
  949. m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath);
  950. return true;
  951. }
  952. /// <summary>
  953. /// Load oar control file
  954. /// </summary>
  955. /// <param name="path"></param>
  956. /// <param name="data"></param>
  957. /// <param name="dearchivedScenes"></param>
  958. public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
  959. {
  960. XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
  961. XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
  962. XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
  963. // Loaded metadata will be empty if no information exists in the archive
  964. dearchivedScenes.LoadedCreationDateTime = 0;
  965. dearchivedScenes.DefaultOriginalID = "";
  966. bool multiRegion = false;
  967. while (xtr.Read())
  968. {
  969. if (xtr.NodeType == XmlNodeType.Element)
  970. {
  971. if (xtr.Name.ToString() == "archive")
  972. {
  973. int majorVersion = int.Parse(xtr["major_version"]);
  974. int minorVersion = int.Parse(xtr["minor_version"]);
  975. string version = string.Format("{0}.{1}", majorVersion, minorVersion);
  976. if (majorVersion > MAX_MAJOR_VERSION)
  977. {
  978. throw new Exception(
  979. string.Format(
  980. "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",
  981. majorVersion, MAX_MAJOR_VERSION));
  982. }
  983. m_log.InfoFormat("[ARCHIVER]: Loading OAR with version {0}", version);
  984. }
  985. else if (xtr.Name.ToString() == "datetime")
  986. {
  987. int value;
  988. if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
  989. dearchivedScenes.LoadedCreationDateTime = value;
  990. }
  991. else if (xtr.Name.ToString() == "row")
  992. {
  993. multiRegion = true;
  994. dearchivedScenes.StartRow();
  995. }
  996. else if (xtr.Name.ToString() == "region")
  997. {
  998. dearchivedScenes.StartRegion();
  999. }
  1000. else if (xtr.Name.ToString() == "id")
  1001. {
  1002. string id = xtr.ReadElementContentAsString();
  1003. dearchivedScenes.DefaultOriginalID = id;
  1004. if(multiRegion)
  1005. dearchivedScenes.SetRegionOriginalID(id);
  1006. }
  1007. else if (xtr.Name.ToString() == "dir")
  1008. {
  1009. dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
  1010. }
  1011. else if (xtr.Name.ToString() == "size_in_meters")
  1012. {
  1013. Vector3 value;
  1014. string size = "<" + xtr.ReadElementContentAsString() + ",0>";
  1015. if (Vector3.TryParse(size, out value))
  1016. {
  1017. m_incomingRegionSize = value;
  1018. if(multiRegion)
  1019. dearchivedScenes.SetRegionSize(m_incomingRegionSize);
  1020. m_log.DebugFormat("[ARCHIVER]: Found region_size info {0}",
  1021. m_incomingRegionSize.ToString());
  1022. }
  1023. }
  1024. }
  1025. }
  1026. dearchivedScenes.MultiRegionFormat = multiRegion;
  1027. if (!multiRegion)
  1028. {
  1029. // Add the single scene
  1030. dearchivedScenes.StartRow();
  1031. dearchivedScenes.StartRegion();
  1032. dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
  1033. dearchivedScenes.SetRegionDirectory("");
  1034. dearchivedScenes.SetRegionSize(m_incomingRegionSize);
  1035. }
  1036. ControlFileLoaded = true;
  1037. if(xtr != null)
  1038. xtr.Close();
  1039. return dearchivedScenes;
  1040. }
  1041. }
  1042. }