Cleaning up some things.
This commit is contained in:
@ -3,7 +3,7 @@ using System.Xml;
|
||||
|
||||
namespace RobloxFiles.XmlFormat
|
||||
{
|
||||
public static class XmlDataReader
|
||||
public static class XmlRobloxFileReader
|
||||
{
|
||||
private static Func<string, Exception> createErrorHandler(string label)
|
||||
{
|
||||
@ -59,10 +59,12 @@ namespace RobloxFiles.XmlFormat
|
||||
|
||||
if (tokenHandler != null)
|
||||
{
|
||||
Property prop = new Property();
|
||||
prop.Name = propName.InnerText;
|
||||
prop.Instance = instance;
|
||||
prop.XmlToken = propType;
|
||||
Property prop = new Property()
|
||||
{
|
||||
Name = propName.InnerText,
|
||||
Instance = instance,
|
||||
XmlToken = propType
|
||||
};
|
||||
|
||||
if (!tokenHandler.ReadProperty(prop, propNode))
|
||||
Console.WriteLine("Could not read property: " + prop.GetFullName() + '!');
|
||||
@ -88,19 +90,20 @@ namespace RobloxFiles.XmlFormat
|
||||
if (classToken == null)
|
||||
throw error("Got an Item without a defined 'class' attribute!");
|
||||
|
||||
Instance inst = new Instance(classToken.InnerText);
|
||||
Instance inst = new Instance() { ClassName = classToken.InnerText };
|
||||
|
||||
// The 'referent' attribute is optional, but should be defined if a Ref property needs to link to this Instance.
|
||||
XmlNode refToken = instNode.Attributes.GetNamedItem("referent");
|
||||
|
||||
if (refToken != null && file != null)
|
||||
{
|
||||
string refId = refToken.InnerText;
|
||||
string referent = refToken.InnerText;
|
||||
inst.XmlReferent = referent;
|
||||
|
||||
if (file.Instances.ContainsKey(refId))
|
||||
if (file.Instances.ContainsKey(referent))
|
||||
throw error("Got an Item with a duplicate 'referent' attribute!");
|
||||
|
||||
file.Instances.Add(refId, inst);
|
||||
file.Instances.Add(referent, inst);
|
||||
}
|
||||
|
||||
// Process the child nodes of this instance.
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
@ -7,19 +8,18 @@ using RobloxFiles.XmlFormat.PropertyTokens;
|
||||
|
||||
namespace RobloxFiles.XmlFormat
|
||||
{
|
||||
public static class XmlDataWriter
|
||||
public static class XmlRobloxFileWriter
|
||||
{
|
||||
public static XmlWriterSettings Settings = new XmlWriterSettings()
|
||||
public static readonly XmlWriterSettings Settings = new XmlWriterSettings()
|
||||
{
|
||||
Indent = true,
|
||||
IndentChars = "\t",
|
||||
NewLineChars = "\r\n",
|
||||
Encoding = Encoding.UTF8,
|
||||
OmitXmlDeclaration = true,
|
||||
NamespaceHandling = NamespaceHandling.Default
|
||||
OmitXmlDeclaration = true
|
||||
};
|
||||
|
||||
private static string CreateReferent()
|
||||
public static string CreateReferent()
|
||||
{
|
||||
Guid referentGuid = Guid.NewGuid();
|
||||
|
||||
@ -40,21 +40,18 @@ namespace RobloxFiles.XmlFormat
|
||||
foreach (Instance child in inst.GetChildren())
|
||||
RecordInstances(file, child);
|
||||
|
||||
string referent = CreateReferent();
|
||||
file.Instances.Add(referent, inst);
|
||||
inst.XmlReferent = referent;
|
||||
if (inst.XmlReferent == "")
|
||||
inst.XmlReferent = CreateReferent();
|
||||
|
||||
file.Instances.Add(inst.XmlReferent, inst);
|
||||
}
|
||||
|
||||
public static XmlElement CreateRobloxElement(XmlDocument doc)
|
||||
{
|
||||
XmlElement roblox = doc.CreateElement("roblox");
|
||||
doc.AppendChild(roblox);
|
||||
|
||||
roblox.SetAttribute("xmlns:xmime", "http://www.w3.org/2005/05/xmlmime");
|
||||
roblox.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
|
||||
roblox.SetAttribute("xsi:noNamespaceSchemaLocation", "http://www.roblox.com/roblox.xsd");
|
||||
roblox.SetAttribute("version", "4");
|
||||
|
||||
doc.AppendChild(roblox);
|
||||
|
||||
XmlElement externalNull = doc.CreateElement("External");
|
||||
roblox.AppendChild(externalNull);
|
||||
externalNull.InnerText = "null";
|
||||
@ -150,7 +147,7 @@ namespace RobloxFiles.XmlFormat
|
||||
instNode.AppendChild(propsNode);
|
||||
|
||||
var props = instance.Properties;
|
||||
|
||||
|
||||
foreach (string propName in props.Keys)
|
||||
{
|
||||
Property prop = props[propName];
|
||||
@ -182,7 +179,7 @@ namespace RobloxFiles.XmlFormat
|
||||
string data = file.SharedStrings[md5];
|
||||
byte[] buffer = Convert.FromBase64String(data);
|
||||
|
||||
bufferProp.SetRawBuffer(buffer);
|
||||
bufferProp.RawBuffer = buffer;
|
||||
binaryWriter.WriteProperty(bufferProp, doc, sharedString);
|
||||
|
||||
sharedStrings.AppendChild(sharedString);
|
12
XmlFormat/PropertyTokens/IXmlPropertyToken.cs
Normal file
12
XmlFormat/PropertyTokens/IXmlPropertyToken.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Xml;
|
||||
|
||||
namespace RobloxFiles.XmlFormat
|
||||
{
|
||||
public interface IXmlPropertyToken
|
||||
{
|
||||
string Token { get; }
|
||||
|
||||
bool ReadProperty(Property prop, XmlNode token);
|
||||
void WriteProperty(Property prop, XmlDocument doc, XmlNode node);
|
||||
}
|
||||
}
|
@ -15,14 +15,14 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
|
||||
prop.Value = base64;
|
||||
|
||||
byte[] buffer = Convert.FromBase64String(base64);
|
||||
prop.SetRawBuffer(buffer);
|
||||
prop.RawBuffer = buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void WriteProperty(Property prop, XmlDocument doc, XmlNode node)
|
||||
{
|
||||
byte[] data = prop.GetRawBuffer();
|
||||
byte[] data = prop.RawBuffer;
|
||||
string value = Convert.ToBase64String(data);
|
||||
|
||||
if (value.Length > 72)
|
@ -22,7 +22,7 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
|
||||
{
|
||||
// Roblox technically doesn't support this anymore, but load it anyway :P
|
||||
byte[] buffer = Convert.FromBase64String(content);
|
||||
prop.SetRawBuffer(buffer);
|
||||
prop.RawBuffer = buffer;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
|
||||
{
|
||||
return XmlPropertyTokens.ReadPropertyGeneric<int>(prop, PropertyType.Int, token);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void WriteProperty(Property prop, XmlDocument doc, XmlNode node)
|
@ -78,6 +78,7 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
|
||||
|
||||
XmlElement element = doc.CreateElement(elementType);
|
||||
element.InnerText = value.ToInvariantString();
|
||||
|
||||
node.AppendChild(element);
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
|
||||
read[i] = Vector3Token.ReadVector3(fieldToken);
|
||||
}
|
||||
|
||||
Vector3 origin = read[0],
|
||||
Vector3 origin = read[0],
|
||||
direction = read[1];
|
||||
|
||||
Ray ray = new Ray(origin, direction);
|
||||
@ -42,11 +42,12 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
|
||||
Ray ray = prop.Value as Ray;
|
||||
|
||||
XmlElement origin = doc.CreateElement("origin");
|
||||
Vector3Token.WriteVector3(doc, origin, ray.Origin);
|
||||
node.AppendChild(origin);
|
||||
|
||||
XmlElement direction = doc.CreateElement("direction");
|
||||
|
||||
Vector3Token.WriteVector3(doc, origin, ray.Origin);
|
||||
Vector3Token.WriteVector3(doc, direction, ray.Direction);
|
||||
|
||||
node.AppendChild(origin);
|
||||
node.AppendChild(direction);
|
||||
}
|
||||
}
|
@ -4,8 +4,6 @@ using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
using RobloxFiles;
|
||||
|
||||
namespace RobloxFiles.XmlFormat
|
||||
{
|
||||
public static class XmlPropertyTokens
|
||||
@ -60,7 +58,6 @@ namespace RobloxFiles.XmlFormat
|
||||
}
|
||||
|
||||
prop.Type = propType;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
@ -8,23 +8,22 @@ using System.Xml;
|
||||
|
||||
namespace RobloxFiles.XmlFormat
|
||||
{
|
||||
public class XmlRobloxFile : IRobloxFile
|
||||
public class XmlRobloxFile : RobloxFile
|
||||
{
|
||||
// IRobloxFile
|
||||
internal readonly Instance XmlContents = new Instance("Folder", "XmlRobloxFile");
|
||||
public Instance Contents => XmlContents;
|
||||
|
||||
// Runtime Specific
|
||||
public readonly XmlDocument Root = new XmlDocument();
|
||||
|
||||
public Dictionary<string, Instance> Instances = new Dictionary<string, Instance>();
|
||||
public Dictionary<string, string> SharedStrings = new Dictionary<string, string>();
|
||||
|
||||
public void ReadFile(byte[] buffer)
|
||||
{
|
||||
Instances.Clear();
|
||||
SharedStrings.Clear();
|
||||
internal Dictionary<string, Instance> Instances = new Dictionary<string, Instance>();
|
||||
internal Dictionary<string, string> SharedStrings = new Dictionary<string, string>();
|
||||
|
||||
internal XmlRobloxFile()
|
||||
{
|
||||
Name = "XmlRobloxFile";
|
||||
ParentLocked = true;
|
||||
}
|
||||
|
||||
protected override void ReadFile(byte[] buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
string xml = Encoding.UTF8.GetString(buffer);
|
||||
@ -53,22 +52,22 @@ namespace RobloxFiles.XmlFormat
|
||||
{
|
||||
if (child.Name == "Item")
|
||||
{
|
||||
Instance item = XmlDataReader.ReadInstance(child, this);
|
||||
item.Parent = XmlContents;
|
||||
Instance item = XmlRobloxFileReader.ReadInstance(child, this);
|
||||
item.Parent = this;
|
||||
}
|
||||
else if (child.Name == "SharedStrings")
|
||||
{
|
||||
XmlDataReader.ReadSharedStrings(child, this);
|
||||
XmlRobloxFileReader.ReadSharedStrings(child, this);
|
||||
}
|
||||
}
|
||||
|
||||
// Query the properties.
|
||||
var props = Instances.Values
|
||||
var allProps = Instances.Values
|
||||
.SelectMany(inst => inst.Properties)
|
||||
.Select(pair => pair.Value);
|
||||
|
||||
// Resolve referent properties.
|
||||
var refProps = props.Where(prop => prop.Type == PropertyType.Ref);
|
||||
var refProps = allProps.Where(prop => prop.Type == PropertyType.Ref);
|
||||
|
||||
foreach (Property refProp in refProps)
|
||||
{
|
||||
@ -87,7 +86,7 @@ namespace RobloxFiles.XmlFormat
|
||||
}
|
||||
|
||||
// Resolve shared strings.
|
||||
var sharedProps = props.Where(prop => prop.Type == PropertyType.SharedString);
|
||||
var sharedProps = allProps.Where(prop => prop.Type == PropertyType.SharedString);
|
||||
|
||||
foreach (Property sharedProp in sharedProps)
|
||||
{
|
||||
@ -99,13 +98,13 @@ namespace RobloxFiles.XmlFormat
|
||||
sharedProp.Value = value;
|
||||
|
||||
byte[] data = Convert.FromBase64String(value);
|
||||
sharedProp.SetRawBuffer(data);
|
||||
|
||||
continue;
|
||||
sharedProp.RawBuffer = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
string name = sharedProp.GetFullName();
|
||||
Console.WriteLine("XmlRobloxFile: Could not resolve shared string for {0}", name);
|
||||
}
|
||||
|
||||
string name = sharedProp.GetFullName();
|
||||
Console.WriteLine("XmlRobloxFile: Could not resolve shared string for {0}", name);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -114,38 +113,41 @@ namespace RobloxFiles.XmlFormat
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteFile(Stream stream)
|
||||
public override void Save(Stream stream)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
XmlElement roblox = XmlDataWriter.CreateRobloxElement(doc);
|
||||
|
||||
XmlElement roblox = doc.CreateElement("roblox");
|
||||
roblox.SetAttribute("version", "4");
|
||||
doc.AppendChild(roblox);
|
||||
|
||||
Instances.Clear();
|
||||
SharedStrings.Clear();
|
||||
|
||||
Instance[] topLevelItems = Contents.GetChildren();
|
||||
Instance[] children = GetChildren();
|
||||
|
||||
// First, record all of the instances.
|
||||
foreach (Instance inst in topLevelItems)
|
||||
XmlDataWriter.RecordInstances(this, inst);
|
||||
foreach (Instance inst in children)
|
||||
XmlRobloxFileWriter.RecordInstances(this, inst);
|
||||
|
||||
// Now append them into the document.
|
||||
foreach (Instance inst in Contents.GetChildren())
|
||||
foreach (Instance inst in children)
|
||||
{
|
||||
XmlNode instNode = XmlDataWriter.WriteInstance(inst, doc, this);
|
||||
XmlNode instNode = XmlRobloxFileWriter.WriteInstance(inst, doc, this);
|
||||
roblox.AppendChild(instNode);
|
||||
}
|
||||
|
||||
// Append the shared strings.
|
||||
if (SharedStrings.Count > 0)
|
||||
{
|
||||
XmlNode sharedStrings = XmlDataWriter.WriteSharedStrings(doc, this);
|
||||
XmlNode sharedStrings = XmlRobloxFileWriter.WriteSharedStrings(doc, this);
|
||||
roblox.AppendChild(sharedStrings);
|
||||
}
|
||||
|
||||
// Write the XML file.
|
||||
using (StringWriter buffer = new StringWriter())
|
||||
{
|
||||
XmlWriterSettings settings = XmlDataWriter.Settings;
|
||||
XmlWriterSettings settings = XmlRobloxFileWriter.Settings;
|
||||
|
||||
using (XmlWriter xmlWriter = XmlWriter.Create(buffer, settings))
|
||||
doc.WriteContentTo(xmlWriter);
|
||||
|
Reference in New Issue
Block a user