233 lines
8.9 KiB
C#
233 lines
8.9 KiB
C#
/*
|
|
* 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
|
|
{
|
|
/// <summary>
|
|
/// The regions included in an OAR file.
|
|
/// </summary>
|
|
public class DearchiveScenesInfo
|
|
{
|
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
/// <summary>
|
|
/// One region in the archive.
|
|
/// </summary>
|
|
public class RegionInfo
|
|
{
|
|
/// <summary>
|
|
/// The subdirectory in which the region is stored.
|
|
/// </summary>
|
|
public string Directory { get; set; }
|
|
|
|
/// <summary>
|
|
/// The region's coordinates (relative to the South-West corner of the block).
|
|
/// </summary>
|
|
public Point Location { get; set; }
|
|
|
|
/// <summary>
|
|
/// The UUID of the original scene from which this archived region was saved.
|
|
/// </summary>
|
|
public string OriginalID { get; set; }
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public Scene Scene { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether this archive uses the multi-region format.
|
|
/// </summary>
|
|
public Boolean MultiRegionFormat { get; set; }
|
|
|
|
/// <summary>
|
|
/// Maps (Region directory -> region)
|
|
/// </summary>
|
|
protected Dictionary<string, RegionInfo> m_directory2region = new Dictionary<string, RegionInfo>();
|
|
|
|
/// <summary>
|
|
/// Maps (UUID of the scene in the simulator where the region will be loaded -> region)
|
|
/// </summary>
|
|
protected Dictionary<UUID, RegionInfo> m_newId2region = new Dictionary<UUID, RegionInfo>();
|
|
|
|
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();
|
|
m_curRegion.Location = new Point((int)m_curX, (int)m_curY);
|
|
m_curRegion.OriginalID = id;
|
|
// 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
|
|
}
|
|
|
|
public void SetRegionDirectory(string directory)
|
|
{
|
|
m_curRegion.Directory = directory;
|
|
m_directory2region[directory] = m_curRegion;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Sets all the scenes present in the simulator.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// 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.
|
|
/// </remarks>
|
|
/// <param name="rootScene">The scene where the Load OAR operation was run</param>
|
|
/// <param name="simulatorScenes">All the scenes in the simulator</param>
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="fullPath">The path of a file in the archive</param>
|
|
/// <param name="scene">The corresponding Scene, or null if none</param>
|
|
/// <param name="relativePath">The path relative to the region's directory. (Or the original
|
|
/// path, if this file doesn't belong to a region.)</param>
|
|
/// <returns>True: use this file; False: skip it</returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="newID"></param>
|
|
/// <returns></returns>
|
|
public string GetOriginalRegionID(UUID newID)
|
|
{
|
|
RegionInfo region;
|
|
if (m_newId2region.TryGetValue(newID, out region))
|
|
return region.OriginalID;
|
|
else
|
|
return DefaultOriginalID;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the scenes that have been (or will be) loaded.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public List<UUID> GetLoadedScenes()
|
|
{
|
|
return m_newId2region.Keys.ToList();
|
|
}
|
|
|
|
}
|
|
}
|