diff --git a/BinaryFormat/BinaryRobloxFile.cs b/BinaryFormat/BinaryRobloxFile.cs index dc253ff..ac43750 100644 --- a/BinaryFormat/BinaryRobloxFile.cs +++ b/BinaryFormat/BinaryRobloxFile.cs @@ -32,7 +32,7 @@ namespace RobloxFiles.BinaryFormat public Dictionary Metadata => META?.Data; public bool HasSharedStrings => (SSTR != null); - public Dictionary SharedStrings => SSTR?.Strings; + public IReadOnlyDictionary SharedStrings => SSTR?.Strings; internal BinaryRobloxFile() { @@ -130,21 +130,8 @@ namespace RobloxFiles.BinaryFormat NumInstances = 0; NumTypes = 0; - - if (HasSharedStrings) - { - SSTR.NumHashes = 0; - SSTR.Lookup.Clear(); - SSTR.Strings.Clear(); - } - - // Write the META chunk. - if (HasMetadata) - { - var metaChunk = META.SaveAsChunk(writer); - Chunks.Add(metaChunk); - } - + SSTR = null; + // Record all instances and types. writer.RecordInstances(Children); @@ -185,6 +172,13 @@ namespace RobloxFiles.BinaryFormat Chunks.Insert(0, sharedStrings); } + // Write the META chunk. + if (HasMetadata) + { + var metaChunk = META.SaveAsChunk(writer); + Chunks.Insert(0, metaChunk); + } + // Write the END_ chunk. writer.StartWritingChunk("END\0"); writer.WriteString("", true); diff --git a/BinaryFormat/Chunks/PROP.cs b/BinaryFormat/Chunks/PROP.cs index 8f5c730..0299827 100644 --- a/BinaryFormat/Chunks/PROP.cs +++ b/BinaryFormat/Chunks/PROP.cs @@ -510,9 +510,16 @@ namespace RobloxFiles.BinaryFormat.Chunks case PropertyType.String: props.ForEach(prop => { - byte[] rawBuffer = prop.RawBuffer; - writer.Write(rawBuffer.Length); - writer.Write(rawBuffer); + byte[] buffer = prop.HasRawBuffer ? prop.RawBuffer : null; + + if (buffer == null) + { + string value = prop.CastValue(); + buffer = Encoding.UTF8.GetBytes(value); + } + + writer.Write(buffer.Length); + writer.Write(buffer); }); break; diff --git a/BinaryFormat/Chunks/SSTR.cs b/BinaryFormat/Chunks/SSTR.cs index 87da5bb..54f02ea 100644 --- a/BinaryFormat/Chunks/SSTR.cs +++ b/BinaryFormat/Chunks/SSTR.cs @@ -45,13 +45,15 @@ namespace RobloxFiles.BinaryFormat.Chunks foreach (var pair in Lookup) { string key = pair.Key; + byte[] md5 = Convert.FromBase64String(key); - - uint id = pair.Value; - string value = Strings[id]; - writer.Write(md5); - writer.WriteString(value); + + string value = Strings[pair.Value]; + byte[] buffer = Convert.FromBase64String(value); + + writer.Write(buffer.Length); + writer.Write(buffer); } return writer.FinishWritingChunk(); diff --git a/Tree/Property.cs b/Tree/Property.cs index a7807bf..707d62b 100644 --- a/Tree/Property.cs +++ b/Tree/Property.cs @@ -44,12 +44,53 @@ namespace RobloxFiles public Instance Instance { get; internal set; } public PropertyType Type; - public object Value; public string XmlToken = ""; - public byte[] RawBuffer { get; internal set; } + public byte[] RawBuffer; internal BinaryRobloxFileWriter CurrentWriter; + internal object RawValue; + + private void ImproviseRawBuffer() + { + switch (Type) + { + case PropertyType.Int: + RawBuffer = BitConverter.GetBytes((int)Value); + break; + case PropertyType.Int64: + RawBuffer = BitConverter.GetBytes((long)Value); + break; + case PropertyType.Bool: + RawBuffer = BitConverter.GetBytes((bool)Value); + break; + case PropertyType.Float: + RawBuffer = BitConverter.GetBytes((float)Value); + break; + case PropertyType.Double: + RawBuffer = BitConverter.GetBytes((double)Value); + break; + case PropertyType.SharedString: + RawBuffer = Convert.FromBase64String((string)Value); + break; + // + } + } + + public object Value + { + get + { + return RawValue; + } + set + { + RawValue = value; + RawBuffer = null; + + ImproviseRawBuffer(); + } + } public bool HasRawBuffer { @@ -58,27 +99,7 @@ namespace RobloxFiles if (RawBuffer == null && Value != null) { // Improvise what the buffer should be if this is a primitive. - switch (Type) - { - case PropertyType.Int: - RawBuffer = BitConverter.GetBytes((int)Value); - break; - case PropertyType.Int64: - RawBuffer = BitConverter.GetBytes((long)Value); - break; - case PropertyType.Bool: - RawBuffer = BitConverter.GetBytes((bool)Value); - break; - case PropertyType.Float: - RawBuffer = BitConverter.GetBytes((float)Value); - break; - case PropertyType.Double: - RawBuffer = BitConverter.GetBytes((double)Value); - break; - case PropertyType.SharedString: - RawBuffer = Convert.FromBase64String((string)Value); - break; - } + ImproviseRawBuffer(); } return (RawBuffer != null); @@ -138,8 +159,8 @@ namespace RobloxFiles throw new Exception("Property.CurrentWriter must be set to use WriteValue"); T value = CastValue(); - byte[] bytes = BinaryRobloxFileWriter.GetBytes(value); + CurrentWriter.Write(bytes); } }