diff --git a/BinaryFormat/Chunks/INST.cs b/BinaryFormat/Chunks/INST.cs index 5b53b03..b4a208b 100644 --- a/BinaryFormat/Chunks/INST.cs +++ b/BinaryFormat/Chunks/INST.cs @@ -33,9 +33,7 @@ namespace RobloxFiles.BinaryFormat.Chunks if (instType == null) { - if (RobloxFile.LogErrors) - Console.Error.WriteLine($"INST - Unknown class: {ClassName} while reading INST chunk."); - + RobloxFile.LogError($"INST - Unknown class: {ClassName} while reading INST chunk."); return; } diff --git a/BinaryFormat/Chunks/PRNT.cs b/BinaryFormat/Chunks/PRNT.cs index ce2e244..2f862c4 100644 --- a/BinaryFormat/Chunks/PRNT.cs +++ b/BinaryFormat/Chunks/PRNT.cs @@ -33,17 +33,13 @@ namespace RobloxFiles.BinaryFormat.Chunks if (child == null) { - if (RobloxFile.LogErrors) - Console.Error.WriteLine($"PRNT: could not parent {childId} to {parentId} because child {childId} was null."); - + RobloxFile.LogError($"PRNT: could not parent {childId} to {parentId} because child {childId} was null."); continue; } if (parentId >= 0 && parent == null) { - if (RobloxFile.LogErrors) - Console.Error.WriteLine($"PRNT: could not parent {childId} to {parentId} because parent {parentId} was null."); - + RobloxFile.LogError($"PRNT: could not parent {childId} to {parentId} because parent {parentId} was null."); continue; } diff --git a/BinaryFormat/Chunks/PROP.cs b/BinaryFormat/Chunks/PROP.cs index e7d5e13..6f255a4 100644 --- a/BinaryFormat/Chunks/PROP.cs +++ b/BinaryFormat/Chunks/PROP.cs @@ -58,9 +58,7 @@ namespace RobloxFiles.BinaryFormat.Chunks if (instance == null) { - if (RobloxFile.LogErrors) - Console.Error.WriteLine($"PROP: No instance @{id} for property {ClassName}.{Name}"); - + RobloxFile.LogError($"PROP: No instance @{id} for property {ClassName}.{Name}"); continue; } @@ -368,9 +366,7 @@ namespace RobloxFiles.BinaryFormat.Chunks if (info == null) { - if (RobloxFile.LogErrors) - Console.Error.WriteLine($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); - + RobloxFile.LogError($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); return value; } @@ -378,9 +374,7 @@ namespace RobloxFiles.BinaryFormat.Chunks } catch { - if (RobloxFile.LogErrors) - Console.Error.WriteLine($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); - + RobloxFile.LogError($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); return value; } }); @@ -545,9 +539,7 @@ namespace RobloxFiles.BinaryFormat.Chunks break; default: - if (RobloxFile.LogErrors) - Console.Error.WriteLine("Unhandled property type: {0}!", Type); - + RobloxFile.LogError($"Unhandled property type: {Type}!"); break; // } diff --git a/DataTypes/CFrame.cs b/DataTypes/CFrame.cs index 5521edc..e229f88 100644 --- a/DataTypes/CFrame.cs +++ b/DataTypes/CFrame.cs @@ -181,7 +181,7 @@ namespace RobloxFiles.DataTypes internal CFrame(Attribute attr) { Vector3 pos = new Vector3(attr); - byte rawOrientId = attr.readByte(); + byte rawOrientId = attr.ReadByte(); if (rawOrientId > 0) { diff --git a/DataTypes/Vector2int16.cs b/DataTypes/Vector2int16.cs index 6b91dea..3b25585 100644 --- a/DataTypes/Vector2int16.cs +++ b/DataTypes/Vector2int16.cs @@ -21,8 +21,8 @@ namespace RobloxFiles.DataTypes internal Vector2int16(Attribute attr) { - X = attr.readShort(); - Y = attr.readShort(); + X = attr.ReadShort(); + Y = attr.ReadShort(); } private delegate Vector2int16 Operator(Vector2int16 a, Vector2int16 b); diff --git a/DataTypes/Vector3int16.cs b/DataTypes/Vector3int16.cs index 6acdb35..7d89efe 100644 --- a/DataTypes/Vector3int16.cs +++ b/DataTypes/Vector3int16.cs @@ -27,9 +27,9 @@ namespace RobloxFiles.DataTypes internal Vector3int16(Attribute attr) { - X = attr.readShort(); - Y = attr.readShort(); - Z = attr.readShort(); + X = attr.ReadShort(); + Y = attr.ReadShort(); + Z = attr.ReadShort(); } private delegate Vector3int16 Operator(Vector3int16 a, Vector3int16 b); diff --git a/Generated/Classes.cs b/Generated/Classes.cs index cc96ac4..db77343 100644 --- a/Generated/Classes.cs +++ b/Generated/Classes.cs @@ -1,5 +1,5 @@ // Auto-generated list of creatable Roblox classes. -// Updated as of 0.460.0.416222 +// Updated as of 0.462.0.416719 using System; @@ -732,6 +732,14 @@ namespace RobloxFiles public Vector3 Torque_ = new Vector3(); } + public class UniversalConstraint : Constraint + { + public bool LimitsEnabled; + public float MaxAngle = 45; + public float Radius = 0.2f; + public float Restitution; + } + public class VectorForce : Constraint { public bool ApplyAtCenterOfMass; diff --git a/Generated/Enums.cs b/Generated/Enums.cs index 968cfc1..3267663 100644 --- a/Generated/Enums.cs +++ b/Generated/Enums.cs @@ -1,5 +1,5 @@ // Auto-generated list of Roblox enums. -// Updated as of 0.460.0.416222 +// Updated as of 0.462.0.416719 namespace RobloxFiles.Enums { diff --git a/RobloxFile.cs b/RobloxFile.cs index aba5b69..9ac246c 100644 --- a/RobloxFile.cs +++ b/RobloxFile.cs @@ -137,5 +137,17 @@ namespace RobloxFiles { return Task.Run(() => Save(filePath)); } + + /// + /// Logs an error that occurred while opening a RobloxFile if logs are enabled. + /// + /// + internal static void LogError(string message) + { + if (!LogErrors) + return; + + Console.Error.WriteLine(message); + } } } diff --git a/RobloxFileFormat.dll b/RobloxFileFormat.dll index dfa80cb..67bf028 100644 Binary files a/RobloxFileFormat.dll and b/RobloxFileFormat.dll differ diff --git a/Tree/Attributes.cs b/Tree/Attributes.cs index 6494dcc..6e926ff 100644 --- a/Tree/Attributes.cs +++ b/Tree/Attributes.cs @@ -57,9 +57,9 @@ namespace RobloxFiles // internal BinaryWriter writer; internal int ReadInt() => reader.ReadInt32(); - internal byte readByte() => reader.ReadByte(); - internal bool readBool() => reader.ReadBoolean(); - internal short readShort() => reader.ReadInt16(); + internal byte ReadByte() => reader.ReadByte(); + internal bool ReadBool() => reader.ReadBoolean(); + internal short ReadShort() => reader.ReadInt16(); internal float ReadFloat() => reader.ReadSingle(); internal double ReadDouble() => reader.ReadDouble(); internal string ReadString() => reader.ReadString(true); @@ -103,14 +103,13 @@ namespace RobloxFiles switch (DataType) { - ////////////////////////// case AttributeType.Null: break; case AttributeType.String: Value = ReadString(); break; case AttributeType.Bool: - Value = readBool(); + Value = ReadBool(); break; case AttributeType.Int: Value = ReadInt(); @@ -185,7 +184,7 @@ namespace RobloxFiles Value = new Rect(this); break; case AttributeType.PhysicalProperties: - bool custom = readBool(); + bool custom = ReadBool(); if (custom) Value = new PhysicalProperties(this); @@ -197,9 +196,7 @@ namespace RobloxFiles case AttributeType.Region3int16: Value = new Region3int16(this); break; - default: - throw new InvalidDataException($"Cannot handle AttributeType {DataType}!"); - ////////////////////////// + default: throw new InvalidDataException($"Cannot handle AttributeType {DataType}!"); } reader = null; diff --git a/Tree/Instance.cs b/Tree/Instance.cs index 65e319f..eff3d12 100644 --- a/Tree/Instance.cs +++ b/Tree/Instance.cs @@ -18,6 +18,7 @@ namespace RobloxFiles public Instance() { Name = ClassName; + RefreshProperties(); } /// The ClassName of this Instance. @@ -506,12 +507,11 @@ namespace RobloxFiles /// A reference to the property that will be added. internal void AddProperty(ref Property prop) { + string name = prop.Name; + RemoveProperty(name); + prop.Instance = this; - - if (props.ContainsKey(prop.Name)) - props.Remove(prop.Name); - - props.Add(prop.Name, prop); + props.Add(name, prop); } /// diff --git a/Tree/Property.cs b/Tree/Property.cs index 6e406fa..7a4f4ab 100644 --- a/Tree/Property.cs +++ b/Tree/Property.cs @@ -211,10 +211,7 @@ namespace RobloxFiles } else { - if (!RobloxFile.LogErrors) - return false; - - Console.Error.WriteLine($"RobloxFiles.Property - Property {Instance.ClassName}.{Name} does not exist!"); + RobloxFile.LogError($"RobloxFiles.Property - Property {Instance.ClassName}.{Name} does not exist!"); } } } @@ -248,10 +245,7 @@ namespace RobloxFiles } catch { - if (!RobloxFile.LogErrors) - return; - - Console.Error.WriteLine($"RobloxFiles.Property - Failed to cast value {value} into property {Instance.ClassName}.{Name}"); + RobloxFile.LogError($"RobloxFiles.Property - Failed to cast value {value} into property {Instance.ClassName}.{Name}"); } } else if (valueType != null) @@ -267,10 +261,7 @@ namespace RobloxFiles } catch { - if (!RobloxFile.LogErrors) - return; - - Console.Error.WriteLine($"RobloxFiles.Property - Failed to implicitly cast value {value} into property {Instance.ClassName}.{Name}"); + RobloxFile.LogError($"RobloxFiles.Property - Failed to implicitly cast value {value} into property {Instance.ClassName}.{Name}"); } } } diff --git a/XmlFormat/IO/XmlFileReader.cs b/XmlFormat/IO/XmlFileReader.cs index 74f8119..1ab4806 100644 --- a/XmlFormat/IO/XmlFileReader.cs +++ b/XmlFormat/IO/XmlFileReader.cs @@ -109,7 +109,7 @@ namespace RobloxFiles.XmlFormat if (!tokenHandler.ReadProperty(prop, propNode) && RobloxFile.LogErrors) { var readError = error($"Could not read property: {prop.GetFullName()}!"); - Console.Error.WriteLine(readError.Message); + RobloxFile.LogError(readError.Message); } instance.AddProperty(ref prop); @@ -117,7 +117,7 @@ namespace RobloxFiles.XmlFormat else if (RobloxFile.LogErrors) { var tokenError = error($"No {nameof(IXmlPropertyToken)} found for property type: {propType}!"); - Console.Error.WriteLine(tokenError.Message); + RobloxFile.LogError(tokenError.Message); } } } @@ -142,7 +142,7 @@ namespace RobloxFiles.XmlFormat if (RobloxFile.LogErrors) { var typeError = error($"Unknown class {className} while reading Item."); - Console.Error.WriteLine(typeError.Message); + RobloxFile.LogError(typeError.Message); } return null; diff --git a/XmlFormat/IO/XmlFileWriter.cs b/XmlFormat/IO/XmlFileWriter.cs index dffd385..fe7e4f2 100644 --- a/XmlFormat/IO/XmlFileWriter.cs +++ b/XmlFormat/IO/XmlFileWriter.cs @@ -94,9 +94,7 @@ namespace RobloxFiles.XmlFormat if (handler == null) { - if (RobloxFile.LogErrors) - Console.Error.WriteLine("XmlDataWriter.WriteProperty: No token handler found for property type: {0}", propType); - + RobloxFile.LogError($"XmlRobloxFileWriter.WriteProperty: No token handler found for property type: {propType}"); return null; } diff --git a/XmlFormat/Tokens/Content.cs b/XmlFormat/Tokens/Content.cs index e1073bf..df83b82 100644 --- a/XmlFormat/Tokens/Content.cs +++ b/XmlFormat/Tokens/Content.cs @@ -30,10 +30,7 @@ namespace RobloxFiles.XmlFormat.PropertyTokens } catch { - if (!RobloxFile.LogErrors) - return true; - - Console.Error.WriteLine("ContentToken: Got illegal base64 string: {0}", data); + RobloxFile.LogError($"ContentToken: Got illegal base64 string: {data}"); } } } diff --git a/XmlFormat/XmlRobloxFile.cs b/XmlFormat/XmlRobloxFile.cs index ab8ce26..f727cae 100644 --- a/XmlFormat/XmlRobloxFile.cs +++ b/XmlFormat/XmlRobloxFile.cs @@ -97,11 +97,7 @@ namespace RobloxFiles } else if (refId != "null") { - string name = refProp.GetFullName(); - - if (LogErrors) - Console.Error.WriteLine("XmlRobloxFile: Could not resolve reference for {0}", name); - + LogError($"XmlRobloxFile: Could not resolve reference for {refProp.GetFullName()}"); refProp.Value = null; } } @@ -112,6 +108,14 @@ namespace RobloxFiles foreach (Property sharedProp in sharedProps) { SharedString shared = sharedProp.CastValue(); + + if (shared == null) + { + var nullBuffer = Array.Empty(); + shared = SharedString.FromBuffer(nullBuffer); + sharedProp.Value = shared; + } + SharedStrings.Add(shared.Key); } }