static unsafe void ExportStructDump() { Directory.CreateDirectory(OutputDirectory); var flags = TransferInstructionFlags.SerializeGameRelease; using var tw = new StreamWriter(Path.Combine(OutputDirectory, "structs.dump")); for (int i = 0; i < RuntimeTypes.Count; i++) { var type = RuntimeTypes.Types[i]; var iter = type; var inheritance = string.Empty; while (true) { inheritance += Marshal.PtrToStringAnsi(iter->ClassName); if (iter->Base == null) { break; } inheritance += " <- "; iter = iter->Base; } tw.WriteLine("\n// classID{{{0}}}: {1}", (int)type->PersistentTypeID, inheritance); iter = type; while (iter->IsAbstract) { tw.WriteLine("// {0} is abstract", Marshal.PtrToStringAnsi(iter->ClassName)); if (iter->Base == null) { break; } iter = iter->Base; } var obj = NativeObject.GetOrProduce(*iter); if (obj == null) { continue; } var tree = new TypeTree(); tree.Init(); if (obj->GetTypeTree(flags, ref tree)) { TypeTreeUtility.CreateTextDump(tree, tw); } NativeObject.DestroyIfNotSingletonOrPersistent(obj); } }
public static unsafe void WriteDataFile(TransferInstructionFlags flags, BinaryWriter bw) { foreach (char c in Application.unityVersion) { bw.Write((byte)c); } bw.Write((byte)0); bw.Write((int)Application.platform); bw.Write((byte)1); // hasTypeTrees var countPosition = (int)bw.BaseStream.Position; var typeCount = 0; foreach (ref var type in Rtti.RuntimeTypes) { ref var iter = ref type; while (iter.IsAbstract) { if (iter.BaseClass == null) { goto NextType; } iter = ref *iter.BaseClass; } var obj = NativeObject.GetOrProduce(iter); if (obj == null) { continue; } if (obj->TryGetTypeTree(flags, out var tree)) { // Shouldn't this write type.PersistentTypeID instead? // I'm leaving it as iter.PersistentTypeID for consistency // with existing C++ code that generates structs.dat bw.Write((int)iter.PersistentTypeID); // GUID for (int i = 0, n = iter.PersistentTypeID < 0 ? 0x20 : 0x10; i < n; i++) { bw.Write((byte)0); } tree.Write(bw); typeCount++; } NativeObject.DestroyTemporary(obj); NextType: continue; }
static unsafe void ExportStructData() { Directory.CreateDirectory(OutputDirectory); var flags = TransferInstructionFlags.SerializeGameRelease; using var bw = new BinaryWriter(File.OpenWrite(Path.Combine(OutputDirectory, "structs.dat"))); foreach (char c in Application.unityVersion) { bw.Write((byte)c); } bw.Write((byte)0); bw.Write((int)Application.platform); bw.Write((byte)1); // hasTypeTrees var countPosition = (int)bw.BaseStream.Position; var typeCount = 0; for (int i = 0; i < RuntimeTypes.Count; i++) { var type = RuntimeTypes.Types[i]; var iter = type; while (iter->IsAbstract) { if (iter->Base == null) { goto NextType; } iter = iter->Base; } var obj = NativeObject.GetOrProduce(*iter); if (obj == null) { continue; } var tree = new TypeTree(); tree.Init(); if (obj->GetTypeTree(flags, ref tree)) { // Shouldn't this write type.PersistentTypeID instead? // I'm leaving it as iter.PersistentTypeID for consistency // with existing C++ code that generates structs.dat bw.Write((int)iter->PersistentTypeID); // GUID for (int j = 0, n = (int)iter->PersistentTypeID < 0 ? 0x20 : 0x10; j < n; ++j) { bw.Write((byte)0); } TypeTreeUtility.CreateBinaryDump(tree, bw); typeCount++; } NativeObject.DestroyIfNotSingletonOrPersistent(obj); NextType: continue; } bw.Seek(countPosition, SeekOrigin.Begin); bw.Write(typeCount); }