Cleaning up some things.

This commit is contained in:
CloneTrooper1019
2019-05-18 23:44:51 -05:00
parent 34642f5656
commit 9c3a673d95
47 changed files with 303 additions and 351 deletions

View File

@ -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.

View File

@ -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);

View 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);
}
}

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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)

View File

@ -78,6 +78,7 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
XmlElement element = doc.CreateElement(elementType);
element.InnerText = value.ToInvariantString();
node.AppendChild(element);
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);