/* * 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. * * Neither the name of the OpenSimulator Project nor the * 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. */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; using System.Drawing; using log4net; using System.Reflection; using OpenSim.Framework.Serialization; namespace OpenSim.Region.CoreModules.World.Archiver { /// /// The regions included in an OAR file. /// public class DearchiveScenesInfo { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// /// One region in the archive. /// public class RegionInfo { /// /// The subdirectory in which the region is stored. /// public string Directory { get; set; } /// /// The region's coordinates (relative to the South-West corner of the block). /// public Point Location { get; set; } /// /// The UUID of the original scene from which this archived region was saved. /// public string OriginalID { get; set; } /// /// The scene in the current simulator into which this region is loaded. /// If null then the region doesn't have a corresponding scene, and it won't be loaded. /// public Scene Scene { get; set; } /// /// The size of the region being loaded. /// public Vector3 RegionSize { get; set; } public RegionInfo() { RegionSize = new Vector3(256f,256f,float.MaxValue); } } /// /// Whether this archive uses the multi-region format. /// public Boolean MultiRegionFormat { get; set; } /// /// Maps (Region directory -> region) /// protected Dictionary m_directory2region = new Dictionary(); /// /// Maps (UUID of the scene in the simulator where the region will be loaded -> region) /// protected Dictionary m_newId2region = new Dictionary(); public int LoadedCreationDateTime { get; set; } public string DefaultOriginalID { get; set; } // These variables are used while reading the archive control file protected int? m_curY = null; protected int? m_curX = null; protected RegionInfo m_curRegion; public DearchiveScenesInfo() { MultiRegionFormat = false; } // The following methods are used while reading the archive control file public void StartRow() { m_curY = (m_curY == null) ? 0 : m_curY + 1; m_curX = null; } public void StartRegion() { m_curX = (m_curX == null) ? 0 : m_curX + 1; // Note: this doesn't mean we have a real region in this location; this could just be a "hole" } public void SetRegionOriginalID(string id) { m_curRegion = new RegionInfo(); int x = (int)((m_curX == null) ? 0 : m_curX); int y = (int)((m_curY == null) ? 0 : m_curY); m_curRegion.Location = new Point(x, y); m_curRegion.OriginalID = id; // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called } public void SetRegionDirectory(string directory) { if(m_curRegion != null) { m_curRegion.Directory = directory; m_directory2region[directory] = m_curRegion; } } public void SetRegionSize(Vector3 size) { if(m_curRegion != null) m_curRegion.RegionSize = size; } /// /// Sets all the scenes present in the simulator. /// /// /// This method matches regions in the archive to scenes in the simulator according to /// their relative position. We only load regions if there's an existing Scene in the /// grid location where the region should be loaded. /// /// The scene where the Load OAR operation was run /// All the scenes in the simulator public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes) { foreach (RegionInfo archivedRegion in m_directory2region.Values) { Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY); location.Offset(archivedRegion.Location); Scene scene; if (simulatorScenes.TryGetScene(location, out scene)) { archivedRegion.Scene = scene; m_newId2region[scene.RegionInfo.RegionID] = archivedRegion; } else { m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}", archivedRegion.Directory, location.X, location.Y); } } } /// /// Returns the archived region according to the path of a file in the archive. /// Also, converts the full path into a path that is relative to the region's directory. /// /// The path of a file in the archive /// The corresponding Scene, or null if none /// The path relative to the region's directory. (Or the original /// path, if this file doesn't belong to a region.) /// True: use this file; False: skip it public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath) { scene = null; relativePath = fullPath; if (!MultiRegionFormat) { if (m_newId2region.Count > 0) scene = m_newId2region.First().Value.Scene; return true; } if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH)) return true; // this file doesn't belong to a region string[] parts = fullPath.Split(new Char[] { '/' }, 3); if (parts.Length != 3) return false; string regionDirectory = parts[1]; relativePath = parts[2]; RegionInfo region; if (m_directory2region.TryGetValue(regionDirectory, out region)) { scene = region.Scene; return (scene != null); } else { return false; } } /// /// Returns the original UUID of a region (from the simulator where the OAR was saved), /// given the UUID of the scene it was loaded into in the current simulator. /// /// /// public string GetOriginalRegionID(UUID newID) { RegionInfo region; if (m_newId2region.TryGetValue(newID, out region)) return region.OriginalID; else return DefaultOriginalID; } /// /// Returns the scenes that have been (or will be) loaded. /// /// public List GetLoadedScenes() { return m_newId2region.Keys.ToList(); } public int GetScenesCount() { return m_directory2region.Count; } } }