From f0ea8eb53463fe7e228537779f3f700bc6ecb74d Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Tue, 30 Dec 2008 19:00:19 +0000 Subject: * Implement saving of region settings in OAR files * This means that you can now save terrain textures, water height, etc. * Estate settings are not supported * Older OAR files without these settings can still be loaded --- .../Modules/World/Archiver/ArchiveConstants.cs | 5 + .../Modules/World/Archiver/ArchiveReadRequest.cs | 72 ++++++ .../World/Archiver/ArchiveWriteRequestExecution.cs | 14 +- .../Archiver/ArchiveWriteRequestPreparation.cs | 33 ++- .../World/Archiver/RegionSettingsSerializer.cs | 258 +++++++++++++++++++++ .../Modules/World/Archiver/TarArchiveWriter.cs | 2 +- 6 files changed, 371 insertions(+), 13 deletions(-) create mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs (limited to 'OpenSim/Region/Environment/Modules/World/Archiver') diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs index b2e006a..4151c88 100644 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs +++ b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs @@ -59,6 +59,11 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver /// Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. /// public static readonly string TERRAINS_PATH = "terrains/"; + + /// + /// Path for region settings. + /// + public static readonly string SETTINGS_PATH = "settings/"; /// /// The character the separates the uuid from extension information in an archived asset filename diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs index e04662f..a5b5917 100644 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs @@ -69,6 +69,12 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver private void DearchiveRegion() { + // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions + DearchiveRegion0DotStar(); + } + + private void DearchiveRegion0DotStar() + { TarArchiveReader archive = new TarArchiveReader( new GZipStream(GetStream(m_loadPath), CompressionMode.Decompress)); @@ -107,6 +113,10 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver { LoadTerrain(filePath, data); } + else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) + { + LoadRegionSettings(filePath, data); + } } //m_log.Debug("[ARCHIVER]: Reached end of archive"); @@ -267,6 +277,68 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver return false; } } + + /// + /// Load region settings data + /// + /// + /// + /// + /// true if settings were loaded successfully, false otherwise + /// + private bool LoadRegionSettings(string settingsPath, byte[] data) + { + RegionSettings loadedRegionSettings; + + try + { + loadedRegionSettings = RegionSettingsSerializer.Deserialize(data); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}", + settingsPath, e); + return false; + } + + RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; + + 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; + 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; + + IEstateModule estateModule = m_scene.RequestModuleInterface(); + estateModule.sendRegionHandshakeToAll(); + + return true; + } /// /// Load terrain data diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs index 73fa5d2..b410e55 100644 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs +++ b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs @@ -56,20 +56,20 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver protected ITerrainModule m_terrainModule; protected IRegionSerialiserModule m_serialiser; protected List m_sceneObjects; - protected string m_sceneName; + protected RegionInfo m_regionInfo; protected string m_savePath; public ArchiveWriteRequestExecution( List sceneObjects, ITerrainModule terrainModule, IRegionSerialiserModule serialiser, - string sceneName, + RegionInfo regionInfo, string savePath) { m_sceneObjects = sceneObjects; m_terrainModule = terrainModule; m_serialiser = serialiser; - m_sceneName = sceneName; + m_regionInfo = regionInfo; m_savePath = savePath; } @@ -90,9 +90,13 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver // Write out control file archive.AddFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile()); + + // Write out region settings + string settingsPath = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_regionInfo.RegionName); + archive.AddFile(settingsPath, RegionSettingsSerializer.Serialize(m_regionInfo.RegionSettings)); // Write out terrain - string terrainPath = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_sceneName); + string terrainPath = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_regionInfo.RegionName); MemoryStream ms = new MemoryStream(); m_terrainModule.SaveToStream(terrainPath, ms); archive.AddFile(terrainPath, ms.ToArray()); @@ -137,7 +141,7 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver xtw.WriteStartDocument(); xtw.WriteStartElement("archive"); xtw.WriteAttributeString("major_version", "0"); - xtw.WriteAttributeString("minor_version", "1"); + xtw.WriteAttributeString("minor_version", "2"); xtw.WriteEndElement(); xtw.Flush(); diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs index 58e8f55..7c1d015 100644 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -204,9 +204,7 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver // Get the prim's default texture. This will be used for faces which don't have their own texture assetUuids[textureEntry.DefaultTexture.TextureID] = 1; - - if (part.Shape.SculptTexture != UUID.Zero) - assetUuids[part.Shape.SculptTexture] = 1; + // XXX: Not a great way to iterate through face textures, but there's no // other method available to tell how many faces there actually are //int i = 0; @@ -218,7 +216,12 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver assetUuids[texture.TextureID] = 1; } } + + // If the prim is a sculpt then preserve this information too + if (part.Shape.SculptTexture != UUID.Zero) + assetUuids[part.Shape.SculptTexture] = 1; + // Now analyze this prim's inventory items to preserve all the uuids that they reference foreach (TaskInventoryItem tii in part.TaskInventory.Values) { //m_log.DebugFormat("[ARCHIVER]: Analysing item asset type {0}", tii.Type); @@ -239,10 +242,10 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver { GetSceneObjectAssetUuids(tii.AssetID, assetUuids); } - else - { + //else + //{ //m_log.DebugFormat("[ARCHIVER]: Recording asset {0} in object {1}", tii.AssetID, part.UUID); - } + //} } } } @@ -283,6 +286,21 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver m_log.DebugFormat( "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", sceneObjects.Count, assetUuids.Count); + + // Make sure that we also request terrain texture assets + RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; + + if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) + assetUuids[regionSettings.TerrainTexture1] = 1; + + if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) + assetUuids[regionSettings.TerrainTexture2] = 1; + + if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) + assetUuids[regionSettings.TerrainTexture3] = 1; + + if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) + assetUuids[regionSettings.TerrainTexture4] = 1; // Asynchronously request all the assets required to perform this archive operation ArchiveWriteRequestExecution awre @@ -290,8 +308,9 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver sceneObjects, m_scene.RequestModuleInterface(), m_scene.RequestModuleInterface(), - m_scene.RegionInfo.RegionName, + m_scene.RegionInfo, m_savePath); + new AssetsRequest(assetUuids.Keys, m_scene.AssetCache, awre.ReceivedAllAssets).Execute(); } } diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs b/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs new file mode 100644 index 0000000..e12d0ec --- /dev/null +++ b/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs @@ -0,0 +1,258 @@ +/* + * 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 OpenSim 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.IO; +using System.Text; +using System.Xml; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Environment.Modules.World.Archiver +{ + /// + /// Serialize and deserialize region settings for an archive file format. + /// + /// We didn't simply use automatic .NET serializagion for OpenSim.Framework.RegionSettings since this is really + /// a file format rather than an object serialization. + /// TODO: However, we could still have used separate non-framework classes here to read and write the xml + /// automatically rather than laboriously doing it by hand using XmlTextReader and Writer. Should switch to this + /// in the future. + public class RegionSettingsSerializer + { + protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); + + /// + /// Deserialize region settings + /// + /// + /// + /// + public static RegionSettings Deserialize(byte[] serializedSettings) + { + return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length)); + } + + /// + /// Deserialize region settings + /// + /// + /// + /// + public static RegionSettings Deserialize(string serializedSettings) + { + RegionSettings settings = new RegionSettings(); + + StringReader sr = new StringReader(serializedSettings); + XmlTextReader xtr = new XmlTextReader(sr); + + xtr.ReadStartElement("RegionSettings"); + + xtr.ReadStartElement("General"); + + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + switch (xtr.Name) + { + case "AllowDamage": + settings.AllowDamage = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "AllowLandResell": + settings.AllowLandResell = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "AllowLandJoinDivide": + settings.AllowLandJoinDivide = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "BlockFly": + settings.BlockFly = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "BlockLandShowInSearch": + settings.BlockShowInSearch = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "BlockTerraform": + settings.BlockTerraform = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "DisableCollisions": + settings.DisableCollisions = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "DisablePhysics": + settings.DisablePhysics = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "DisableScripts": + settings.DisableScripts = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "MaturityRating": + settings.Maturity = int.Parse(xtr.ReadElementContentAsString()); + break; + case "RestrictPushing": + settings.RestrictPushing = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "AgentLimit": + settings.AgentLimit = int.Parse(xtr.ReadElementContentAsString()); + break; + case "ObjectBonus": + settings.ObjectBonus = double.Parse(xtr.ReadElementContentAsString()); + break; + } + } + + xtr.ReadEndElement(); + xtr.ReadStartElement("GroundTextures"); + + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + switch (xtr.Name) + { + case "Texture1": + settings.TerrainTexture1 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "Texture2": + settings.TerrainTexture2 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "Texture3": + settings.TerrainTexture3 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "Texture4": + settings.TerrainTexture4 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowSW": + settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowNW": + settings.Elevation1NW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowSE": + settings.Elevation1SE = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowNE": + settings.Elevation1NE = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighSW": + settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighNW": + settings.Elevation2NW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighSE": + settings.Elevation2SE = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighNE": + settings.Elevation2NE = double.Parse(xtr.ReadElementContentAsString()); + break; + } + } + + xtr.ReadEndElement(); + xtr.ReadStartElement("Terrain"); + + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + switch (xtr.Name) + { + case "WaterHeight": + settings.WaterHeight = double.Parse(xtr.ReadElementContentAsString()); + break; + case "TerrainRaiseLimit": + settings.TerrainRaiseLimit = double.Parse(xtr.ReadElementContentAsString()); + break; + case "TerrainLowerLimit": + settings.TerrainLowerLimit = double.Parse(xtr.ReadElementContentAsString()); + break; + case "UseEstateSun": + settings.UseEstateSun = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "FixedSun": + settings.FixedSun = bool.Parse(xtr.ReadElementContentAsString()); + break; + } + } + + xtr.Close(); + sr.Close(); + + return settings; + } + + public static string Serialize(RegionSettings settings) + { + StringWriter sw = new StringWriter(); + XmlTextWriter xtw = new XmlTextWriter(sw); + xtw.Formatting = Formatting.Indented; + xtw.WriteStartDocument(); + + xtw.WriteStartElement("RegionSettings"); + + xtw.WriteStartElement("General"); + xtw.WriteElementString("AllowDamage", settings.AllowDamage.ToString()); + xtw.WriteElementString("AllowLandResell", settings.AllowLandResell.ToString()); + xtw.WriteElementString("AllowLandJoinDivide", settings.AllowLandJoinDivide.ToString()); + xtw.WriteElementString("BlockFly", settings.BlockFly.ToString()); + xtw.WriteElementString("BlockLandShowInSearch", settings.BlockShowInSearch.ToString()); + xtw.WriteElementString("BlockTerraform", settings.BlockTerraform.ToString()); + xtw.WriteElementString("DisableCollisions", settings.DisableCollisions.ToString()); + xtw.WriteElementString("DisablePhysics", settings.DisablePhysics.ToString()); + xtw.WriteElementString("DisableScripts", settings.DisableScripts.ToString()); + xtw.WriteElementString("MaturityRating", settings.Maturity.ToString()); + xtw.WriteElementString("RestrictPushing", settings.RestrictPushing.ToString()); + xtw.WriteElementString("AgentLimit", settings.AgentLimit.ToString()); + xtw.WriteElementString("ObjectBonus", settings.ObjectBonus.ToString()); + xtw.WriteEndElement(); + + xtw.WriteStartElement("GroundTextures"); + xtw.WriteElementString("Texture1", settings.TerrainTexture1.ToString()); + xtw.WriteElementString("Texture2", settings.TerrainTexture2.ToString()); + xtw.WriteElementString("Texture3", settings.TerrainTexture3.ToString()); + xtw.WriteElementString("Texture4", settings.TerrainTexture4.ToString()); + xtw.WriteElementString("ElevationLowSW", settings.Elevation1SW.ToString()); + xtw.WriteElementString("ElevationLowNW", settings.Elevation1NW.ToString()); + xtw.WriteElementString("ElevationLowSE", settings.Elevation1SE.ToString()); + xtw.WriteElementString("ElevationLowNE", settings.Elevation1NE.ToString()); + xtw.WriteElementString("ElevationHighSW", settings.Elevation2SW.ToString()); + xtw.WriteElementString("ElevationHighNW", settings.Elevation2NW.ToString()); + xtw.WriteElementString("ElevationHighSE", settings.Elevation2SE.ToString()); + xtw.WriteElementString("ElevationHighNE", settings.Elevation2NE.ToString()); + xtw.WriteEndElement(); + + xtw.WriteStartElement("Terrain"); + xtw.WriteElementString("WaterHeight", settings.WaterHeight.ToString()); + xtw.WriteElementString("TerrainRaiseLimit", settings.TerrainRaiseLimit.ToString()); + xtw.WriteElementString("TerrainLowerLimit", settings.TerrainLowerLimit.ToString()); + xtw.WriteElementString("UseEstateSun", settings.UseEstateSun.ToString()); + xtw.WriteElementString("FixedSun", settings.FixedSun.ToString()); + // XXX: Need to expose interface to get sun phase information from sun module + // xtw.WriteStartElement("SunPhase", + xtw.WriteEndElement(); + + xtw.WriteEndElement(); + + xtw.Close(); + sw.Close(); + + return sw.ToString(); + } + } +} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs b/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs index 83b9250..d4a8a46 100644 --- a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs +++ b/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs @@ -43,7 +43,7 @@ namespace OpenSim.Region.Environment protected Dictionary m_files = new Dictionary(); - protected static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); + protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); /// /// Add a directory to the tar archive. We can only handle one path level right now! -- cgit v1.1