Files
libremetaverse/Programs/Simian/Archiving/OarFile.cs
John Hurliman 70fe1f8f2a [Simian]
* Initial framework support for multiple simulators. Currently only the first region config is loaded, but the framework is there
* Big reorganization of config and data files
* Started renaming extensions that handle LLUDP packets to start with the LL prefix. Work in progress
* Initial SSL support

git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@2482 52acb1d6-8a22-11de-b505-999d5b087335
2009-03-12 23:02:42 +00:00

330 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Xml;
using OpenMetaverse;
namespace Simian
{
public class Linkset
{
public SimulationObject Parent;
public List<SimulationObject> Children;
}
public class OarFile
{
enum ProfileShape : byte
{
Circle = 0,
Square = 1,
IsometricTriangle = 2,
EquilateralTriangle = 3,
RightTriangle = 4,
HalfCircle = 5
}
public static void PackageArchive(string directoryName, string filename)
{
const string ARCHIVE_XML = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<archive major_version=\"0\" minor_version=\"1\" />";
TarArchiveWriter archive = new TarArchiveWriter(new GZipStream(new FileStream(filename, FileMode.Create), CompressionMode.Compress));
// Create the archive.xml file
archive.WriteFile("archive.xml", ARCHIVE_XML);
// Add the assets
string[] files = Directory.GetFiles(directoryName + "/assets");
foreach (string file in files)
archive.WriteFile("assets/" + Path.GetFileName(file), File.ReadAllBytes(file));
// Add the objects
files = Directory.GetFiles(directoryName + "/objects");
foreach (string file in files)
archive.WriteFile("objects/" + Path.GetFileName(file), File.ReadAllBytes(file));
// Add the terrain(s)
files = Directory.GetFiles(directoryName + "/terrains");
foreach (string file in files)
archive.WriteFile("terrains/" + Path.GetFileName(file), File.ReadAllBytes(file));
archive.Close();
}
public static void SavePrims(ISceneProvider scene, string primsPath, string assetsPath, string textureCacheFolder)
{
Dictionary<UUID, UUID> textureList = new Dictionary<UUID, UUID>();
// Delete all of the old linkset files
try { Directory.Delete(primsPath, true); }
catch (Exception) { }
// Create a new folder for the linkset files
try { Directory.CreateDirectory(primsPath); }
catch (Exception ex)
{
Logger.Log("Failed saving prims: " + ex.Message, Helpers.LogLevel.Error);
return;
}
// Copy the double dictionary to a temporary list for iterating
List<SimulationObject> primList = new List<SimulationObject>();
scene.ForEachObject(delegate(SimulationObject prim)
{
if (!(prim.Prim is Avatar))
primList.Add(prim);
});
foreach (SimulationObject p in primList)
{
if (p.Prim.ParentID == 0)
{
Linkset linkset = new Linkset();
linkset.Parent = p;
linkset.Children = p.GetChildren();
SaveLinkset(linkset, Path.Combine(primsPath, "Primitive_" + linkset.Parent.Prim.ID.ToString() + ".xml"));
}
// Add all of the textures on this prim to the save list
for (int i = 0; i < p.Prim.Textures.FaceTextures.Length; i++)
{
Primitive.TextureEntryFace face = p.Prim.Textures.FaceTextures[i];
if (face != null && !textureList.ContainsKey(face.TextureID))
textureList.Add(face.TextureID, face.TextureID);
}
}
SaveTextures(new List<UUID>(textureList.Keys), assetsPath, textureCacheFolder);
}
public static void SaveTextures(IList<UUID> textures, string assetsPath, string textureCacheFolder)
{
int count = 0;
// Delete the assets folder
try { Directory.Delete(assetsPath, true); }
catch (Exception) { }
// Create a new assets folder
try { Directory.CreateDirectory(assetsPath); }
catch (Exception ex)
{
Logger.Log("Failed saving assets: " + ex.Message, Helpers.LogLevel.Error);
return;
}
// Create a map of all of the textures in the cache
string[] files = Directory.GetFiles(textureCacheFolder, "*.texture", SearchOption.TopDirectoryOnly);
Dictionary<UUID, string> idToFiles = new Dictionary<UUID, string>(files.Length);
for (int i = 0; i < files.Length; i++)
{
string file = files[i];
UUID id;
if (UUID.TryParse(Path.GetFileNameWithoutExtension(file), out id))
idToFiles[id] = file;
}
for (int i = 0; i < textures.Count; i++)
{
UUID texture = textures[i];
if (idToFiles.ContainsKey(texture))
{
try
{
File.Copy(idToFiles[texture], Path.Combine(assetsPath, texture.ToString() + "_texture.jp2"));
++count;
}
catch (Exception ex)
{
Logger.Log("Failed to save texture " + texture.ToString() + ": " + ex.Message, Helpers.LogLevel.Error);
}
}
else
{
Logger.Log("Skipping missing texture " + texture.ToString(), Helpers.LogLevel.Warning);
}
}
Logger.Log("Copied " + count + " textures to the asset archive folder", Helpers.LogLevel.Info);
}
static void SaveLinkset(Linkset linkset, string filename)
{
try
{
using (StreamWriter stream = new StreamWriter(filename))
{
XmlTextWriter writer = new XmlTextWriter(stream);
SOGToXml2(writer, linkset);
writer.Flush();
}
}
catch (Exception ex)
{
Logger.Log("Failed saving linkset: " + ex.Message, Helpers.LogLevel.Error);
}
}
static void SOGToXml2(XmlTextWriter writer, Linkset linkset)
{
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
SOPToXml(writer, linkset.Parent, null);
writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
foreach (SimulationObject child in linkset.Children)
SOPToXml(writer, child, linkset.Parent);
writer.WriteEndElement();
writer.WriteEndElement();
}
static void SOPToXml(XmlTextWriter writer, SimulationObject prim, SimulationObject parent)
{
writer.WriteStartElement("SceneObjectPart");
writer.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
writer.WriteAttributeString("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
WriteUUID(writer, "CreatorID", prim.Prim.Properties.CreatorID);
WriteUUID(writer, "FolderID", prim.Prim.Properties.FolderID);
writer.WriteElementString("InventorySerial", prim.Prim.Properties.InventorySerial.ToString());
writer.WriteStartElement("TaskInventory"); writer.WriteEndElement();
writer.WriteElementString("ObjectFlags", ((int)prim.Prim.Flags).ToString());
WriteUUID(writer, "UUID", prim.Prim.ID);
writer.WriteElementString("LocalId", prim.Prim.LocalID.ToString());
writer.WriteElementString("Name", prim.Prim.Properties.Name);
writer.WriteElementString("Material", ((int)prim.Prim.PrimData.Material).ToString());
writer.WriteElementString("RegionHandle", prim.Prim.RegionHandle.ToString());
writer.WriteElementString("ScriptAccessPin", "0");
Vector3 groupPosition;
if (parent == null)
groupPosition = prim.Prim.Position;
else
groupPosition = parent.Prim.Position;
WriteVector(writer, "GroupPosition", groupPosition);
if (prim.Prim.ParentID == 0)
WriteVector(writer, "OffsetPosition", Vector3.Zero);
else
WriteVector(writer, "OffsetPosition", prim.Prim.Position);
WriteQuaternion(writer, "RotationOffset", prim.Prim.Rotation);
WriteVector(writer, "Velocity", Vector3.Zero);
WriteVector(writer, "RotationalVelocity", Vector3.Zero);
WriteVector(writer, "AngularVelocity", prim.Prim.AngularVelocity);
WriteVector(writer, "Acceleration", Vector3.Zero);
writer.WriteElementString("Description", prim.Prim.Properties.Description);
writer.WriteStartElement("Color");
writer.WriteElementString("R", prim.Prim.TextColor.R.ToString());
writer.WriteElementString("G", prim.Prim.TextColor.G.ToString());
writer.WriteElementString("B", prim.Prim.TextColor.B.ToString());
writer.WriteElementString("A", prim.Prim.TextColor.G.ToString());
writer.WriteEndElement();
writer.WriteElementString("Text", prim.Prim.Text);
writer.WriteElementString("SitName", prim.Prim.Properties.SitName);
writer.WriteElementString("TouchName", prim.Prim.Properties.TouchName);
writer.WriteElementString("LinkNum", prim.LinkNumber.ToString());
writer.WriteElementString("ClickAction", ((int)prim.Prim.ClickAction).ToString());
writer.WriteStartElement("Shape");
writer.WriteElementString("PathBegin", Primitive.PackBeginCut(prim.Prim.PrimData.PathBegin).ToString());
writer.WriteElementString("PathCurve", ((byte)prim.Prim.PrimData.PathCurve).ToString());
writer.WriteElementString("PathEnd", Primitive.PackEndCut(prim.Prim.PrimData.PathEnd).ToString());
writer.WriteElementString("PathRadiusOffset", Primitive.PackPathTwist(prim.Prim.PrimData.PathRadiusOffset).ToString());
writer.WriteElementString("PathRevolutions", Primitive.PackPathRevolutions(prim.Prim.PrimData.PathRevolutions).ToString());
writer.WriteElementString("PathScaleX", Primitive.PackPathScale(prim.Prim.PrimData.PathScaleX).ToString());
writer.WriteElementString("PathScaleY", Primitive.PackPathScale(prim.Prim.PrimData.PathScaleY).ToString());
writer.WriteElementString("PathShearX", ((byte)Primitive.PackPathShear(prim.Prim.PrimData.PathShearX)).ToString());
writer.WriteElementString("PathShearY", ((byte)Primitive.PackPathShear(prim.Prim.PrimData.PathShearY)).ToString());
writer.WriteElementString("PathSkew", Primitive.PackPathTwist(prim.Prim.PrimData.PathSkew).ToString());
writer.WriteElementString("PathTaperX", Primitive.PackPathTaper(prim.Prim.PrimData.PathTaperX).ToString());
writer.WriteElementString("PathTaperY", Primitive.PackPathTaper(prim.Prim.PrimData.PathTaperY).ToString());
writer.WriteElementString("PathTwist", Primitive.PackPathTwist(prim.Prim.PrimData.PathTwist).ToString());
writer.WriteElementString("PathTwistBegin", Primitive.PackPathTwist(prim.Prim.PrimData.PathTwistBegin).ToString());
writer.WriteElementString("PCode", ((byte)prim.Prim.PrimData.PCode).ToString());
writer.WriteElementString("ProfileBegin", Primitive.PackBeginCut(prim.Prim.PrimData.ProfileBegin).ToString());
writer.WriteElementString("ProfileEnd", Primitive.PackEndCut(prim.Prim.PrimData.ProfileEnd).ToString());
writer.WriteElementString("ProfileHollow", Primitive.PackProfileHollow(prim.Prim.PrimData.ProfileHollow).ToString());
WriteVector(writer, "Scale", prim.Prim.Scale);
writer.WriteElementString("State", prim.Prim.PrimData.State.ToString());
ProfileShape shape = (ProfileShape)prim.Prim.PrimData.ProfileCurve;
writer.WriteElementString("ProfileShape", shape.ToString());
writer.WriteElementString("HollowShape", prim.Prim.PrimData.ProfileHole.ToString());
writer.WriteElementString("ProfileCurve", prim.Prim.PrimData.profileCurve.ToString());
writer.WriteStartElement("TextureEntry");
byte[] te;
if (prim.Prim.Textures != null)
te = prim.Prim.Textures.GetBytes();
else
te = Utils.EmptyBytes;
writer.WriteBase64(te, 0, te.Length);
writer.WriteEndElement();
// FIXME: ExtraParams
writer.WriteStartElement("ExtraParams"); writer.WriteEndElement();
writer.WriteEndElement();
WriteVector(writer, "Scale", prim.Prim.Scale);
writer.WriteElementString("UpdateFlag", "0");
WriteVector(writer, "SitTargetOrientation", Vector3.UnitZ); // TODO: Is this really a vector and not a quaternion?
WriteVector(writer, "SitTargetPosition", prim.SitPosition);
WriteVector(writer, "SitTargetPositionLL", prim.SitPosition);
WriteQuaternion(writer, "SitTargetOrientationLL", prim.SitRotation);
writer.WriteElementString("ParentID", prim.Prim.ParentID.ToString());
writer.WriteElementString("CreationDate", ((int)Utils.DateTimeToUnixTime(prim.Prim.Properties.CreationDate)).ToString());
writer.WriteElementString("Category", ((int)prim.Prim.Properties.Category).ToString());
writer.WriteElementString("SalePrice", prim.Prim.Properties.SalePrice.ToString());
writer.WriteElementString("ObjectSaleType", ((int)prim.Prim.Properties.SaleType).ToString());
writer.WriteElementString("OwnershipCost", prim.Prim.Properties.OwnershipCost.ToString());
WriteUUID(writer, "GroupID", prim.Prim.GroupID);
WriteUUID(writer, "OwnerID", prim.Prim.OwnerID);
WriteUUID(writer, "LastOwnerID", prim.Prim.Properties.LastOwnerID);
writer.WriteElementString("BaseMask", ((uint)PermissionMask.All).ToString());
writer.WriteElementString("OwnerMask", ((uint)PermissionMask.All).ToString());
writer.WriteElementString("GroupMask", ((uint)PermissionMask.All).ToString());
writer.WriteElementString("EveryoneMask", ((uint)PermissionMask.All).ToString());
writer.WriteElementString("NextOwnerMask", ((uint)PermissionMask.All).ToString());
writer.WriteElementString("Flags", "None");
WriteUUID(writer, "SitTargetAvatar", UUID.Zero);
writer.WriteEndElement();
}
static void WriteUUID(XmlTextWriter writer, string name, UUID id)
{
writer.WriteStartElement(name);
writer.WriteElementString("UUID", id.ToString());
writer.WriteEndElement();
}
static void WriteVector(XmlTextWriter writer, string name, Vector3 vec)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString());
writer.WriteElementString("Y", vec.Y.ToString());
writer.WriteElementString("Z", vec.Z.ToString());
writer.WriteEndElement();
}
static void WriteQuaternion(XmlTextWriter writer, string name, Quaternion quat)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString());
writer.WriteElementString("Y", quat.Y.ToString());
writer.WriteElementString("Z", quat.Z.ToString());
writer.WriteElementString("W", quat.W.ToString());
writer.WriteEndElement();
}
}
}