Large scale refactor to add class support!
Instance classes are now strongly typed with real property fields that are derived from the JSON API Dump! This required a lot of reworking across the board: - Classes and Enums are auto-generated in the 'Generated' folder now. This is done using a custom built-in plugin, which can be found in the Plugins folder of this project. - Property objects are now tied to .NET's reflection system. Reading and writing from them will try to redirect into a field of the Instance they are bound to. - Property types that were loosely defined now have proper data types (such as Color3uint8, Content, ProtectedString, SharedString, etc) - Fixed an error with the CFrame directional vectors. - The binary PRNT chunk now writes instances in child->parent order. - Enums are now generated correctly, with up-to-date values. - INST chunks are now referred to as 'Classes' instead of 'Types'. - Unary operator added to Vector2 and Vector3. - CollectionService tags can now be manipulated per-instance using the Instance.Tags member. - The Instance.Archivable property now works correctly. - XML files now save/load metadata correctly. - Cleaned up the property tokens directory. I probably missed a few things, but that's a general overview of everything that changed.
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
@ -16,10 +18,15 @@ namespace RobloxFiles.BinaryFormat
|
||||
public string ChunkType { get; private set; }
|
||||
public long ChunkStart { get; private set; }
|
||||
|
||||
public Dictionary<string, INST> TypeMap;
|
||||
public Dictionary<string, INST> ClassMap;
|
||||
public readonly BinaryRobloxFile File;
|
||||
|
||||
// Instances in parent->child order
|
||||
public List<Instance> Instances;
|
||||
|
||||
// Instances in child->parent order
|
||||
public List<Instance> PostInstances;
|
||||
|
||||
public BinaryRobloxFileWriter(BinaryRobloxFile file, Stream workBuffer = null) : base(workBuffer ?? new MemoryStream())
|
||||
{
|
||||
File = file;
|
||||
@ -28,7 +35,9 @@ namespace RobloxFiles.BinaryFormat
|
||||
ChunkType = "";
|
||||
|
||||
Instances = new List<Instance>();
|
||||
TypeMap = new Dictionary<string, INST>();
|
||||
PostInstances = new List<Instance>();
|
||||
|
||||
ClassMap = new Dictionary<string, INST>();
|
||||
}
|
||||
|
||||
private static byte[] GetBytes<T>(T value, int bufferSize, IntPtr converter)
|
||||
@ -144,36 +153,64 @@ namespace RobloxFiles.BinaryFormat
|
||||
{
|
||||
foreach (Instance instance in instances)
|
||||
{
|
||||
int instId = (int)(File.NumInstances++);
|
||||
if (!instance.Archivable)
|
||||
continue;
|
||||
|
||||
int instId = (int)(File.NumInstances++);
|
||||
instance.Referent = instId.ToString();
|
||||
Instances.Add(instance);
|
||||
|
||||
string className = instance.ClassName;
|
||||
INST inst = null;
|
||||
|
||||
if (!TypeMap.ContainsKey(className))
|
||||
if (!ClassMap.ContainsKey(className))
|
||||
{
|
||||
inst = new INST()
|
||||
{
|
||||
TypeName = className,
|
||||
ClassName = className,
|
||||
InstanceIds = new List<int>(),
|
||||
IsService = instance.IsService
|
||||
};
|
||||
|
||||
TypeMap.Add(className, inst);
|
||||
ClassMap.Add(className, inst);
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = TypeMap[className];
|
||||
inst = ClassMap[className];
|
||||
}
|
||||
|
||||
inst.NumInstances++;
|
||||
inst.InstanceIds.Add(instId);
|
||||
|
||||
RecordInstances(instance.GetChildren());
|
||||
PostInstances.Add(instance);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ApplyClassMap()
|
||||
{
|
||||
File.Instances = Instances.ToArray();
|
||||
|
||||
var classNames = ClassMap
|
||||
.Select(type => type.Key)
|
||||
.ToList();
|
||||
|
||||
classNames.Sort(StringComparer.Ordinal);
|
||||
|
||||
var classes = classNames
|
||||
.Select(className => ClassMap[className])
|
||||
.ToArray();
|
||||
|
||||
for (int i = 0; i < classes.Length; i++, File.NumClasses++)
|
||||
{
|
||||
string className = classNames[i];
|
||||
|
||||
INST inst = ClassMap[className];
|
||||
inst.ClassIndex = i;
|
||||
}
|
||||
|
||||
File.Classes = classes;
|
||||
}
|
||||
|
||||
// Marks that we are writing a chunk.
|
||||
public bool StartWritingChunk(string chunkType)
|
||||
@ -236,5 +273,19 @@ namespace RobloxFiles.BinaryFormat
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public void SaveChunk(IBinaryFileChunk handler)
|
||||
{
|
||||
var chunk = handler.SaveAsChunk(this);
|
||||
File.Chunks.Add(chunk);
|
||||
}
|
||||
|
||||
public BinaryRobloxFileChunk WriteEndChunk()
|
||||
{
|
||||
StartWritingChunk("END\0");
|
||||
WriteString("</roblox>", true);
|
||||
|
||||
return FinishWritingChunk(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user