diff --git a/BinaryFormat/Chunks/PROP.cs b/BinaryFormat/Chunks/PROP.cs index 6f255a4..ece1580 100644 --- a/BinaryFormat/Chunks/PROP.cs +++ b/BinaryFormat/Chunks/PROP.cs @@ -805,16 +805,11 @@ namespace RobloxFiles.BinaryFormat.Chunks { CFrame value = null; - if (prop.Value is Quaternion) - { - Quaternion q = prop.CastValue(); + if (prop.Value is Quaternion q) value = q.ToCFrame(); - } else - { value = prop.CastValue(); - } - + Vector3 pos = value.Position; CFrame_X.Add(pos.X); CFrame_Y.Add(pos.Y); @@ -856,15 +851,15 @@ namespace RobloxFiles.BinaryFormat.Chunks props.ForEach(prop => { - if (prop.Value is uint) + if (prop.Value is uint raw) { - uint raw = prop.CastValue(); Enums.Add(raw); return; } int signed = (int)prop.Value; uint value = (uint)signed; + Enums.Add(value); }); @@ -1103,8 +1098,8 @@ namespace RobloxFiles.BinaryFormat.Chunks object value = prop?.Value; string str = value?.ToInvariantString() ?? "null"; - if (value is byte[]) - str = Convert.ToBase64String(value as byte[]); + if (value is byte[] buffer) + str = Convert.ToBase64String(buffer); if (str.Length > 25) str = str.Substring(0, 22) + "..."; diff --git a/DataTypes/BrickColor.cs b/DataTypes/BrickColor.cs index 18a7830..7342e9a 100644 --- a/DataTypes/BrickColor.cs +++ b/DataTypes/BrickColor.cs @@ -54,10 +54,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is BrickColor)) + if (!(obj is BrickColor bc)) return false; - var bc = obj as BrickColor; return Number == bc.Number; } diff --git a/DataTypes/CFrame.cs b/DataTypes/CFrame.cs index e229f88..c93f867 100644 --- a/DataTypes/CFrame.cs +++ b/DataTypes/CFrame.cs @@ -51,10 +51,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is CFrame)) + if (!(obj is CFrame other)) return false; - var other = obj as CFrame; var compA = GetComponents(); var compB = other.GetComponents(); @@ -420,13 +419,24 @@ namespace RobloxFiles.DataTypes return new float[] { m14, m24, m34, m11, m12, m13, m21, m22, m23, m31, m32, m33 }; } + public EulerAngles ToEulerAngles() => new EulerAngles + { + Yaw = (float)Math.Asin(m13), + Pitch = (float)Math.Atan2(-m23, m33), + Roll = (float)Math.Atan2(-m12, m11), + }; + + [Obsolete] public float[] ToEulerAnglesXYZ() { - float x = (float)Math.Atan2(-m23, m33); - float y = (float)Math.Asin(m13); - float z = (float)Math.Atan2(-m12, m11); + var result = ToEulerAngles(); - return new float[] { x, y, z }; + return new float[] + { + result.Pitch, + result.Yaw, + result.Roll + }; } public bool IsAxisAligned() diff --git a/DataTypes/Color3.cs b/DataTypes/Color3.cs index fc7d271..8491369 100644 --- a/DataTypes/Color3.cs +++ b/DataTypes/Color3.cs @@ -25,11 +25,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is Color3)) + if (!(obj is Color3 other)) return false; - var other = obj as Color3; - if (!R.Equals(other.R)) return false; diff --git a/DataTypes/ColorSequence.cs b/DataTypes/ColorSequence.cs index 8a8fb8d..8c0b177 100644 --- a/DataTypes/ColorSequence.cs +++ b/DataTypes/ColorSequence.cs @@ -40,10 +40,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is ColorSequence)) + if (!(obj is ColorSequence colorSeq)) return false; - var colorSeq = obj as ColorSequence; var otherKeys = colorSeq.Keypoints; if (Keypoints.Length != otherKeys.Length) diff --git a/DataTypes/ColorSequenceKeypoint.cs b/DataTypes/ColorSequenceKeypoint.cs index cc64b9c..857515f 100644 --- a/DataTypes/ColorSequenceKeypoint.cs +++ b/DataTypes/ColorSequenceKeypoint.cs @@ -37,11 +37,9 @@ public override bool Equals(object obj) { - if (!(obj is ColorSequenceKeypoint)) + if (!(obj is ColorSequenceKeypoint otherKey)) return false; - var otherKey = obj as ColorSequenceKeypoint; - if (!Time.Equals(otherKey.Time)) return false; diff --git a/DataTypes/Content.cs b/DataTypes/Content.cs index 5499792..4940a94 100644 --- a/DataTypes/Content.cs +++ b/DataTypes/Content.cs @@ -31,10 +31,9 @@ public override bool Equals(object obj) { - if (!(obj is Content)) + if (!(obj is Content content)) return false; - var content = obj as Content; return Url.Equals(content.Url); } } diff --git a/DataTypes/EulerAngles.cs b/DataTypes/EulerAngles.cs new file mode 100644 index 0000000..d5c02c0 --- /dev/null +++ b/DataTypes/EulerAngles.cs @@ -0,0 +1,9 @@ +namespace RobloxFiles.DataTypes +{ + public struct EulerAngles + { + public float Yaw; + public float Pitch; + public float Roll; + } +} diff --git a/DataTypes/NumberRange.cs b/DataTypes/NumberRange.cs index 37eb928..0375865 100644 --- a/DataTypes/NumberRange.cs +++ b/DataTypes/NumberRange.cs @@ -36,11 +36,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is NumberRange)) + if (!(obj is NumberRange other)) return false; - var other = obj as NumberRange; - if (!Min.Equals(other.Min)) return false; diff --git a/DataTypes/NumberSequence.cs b/DataTypes/NumberSequence.cs index 09e5303..c6f0b7c 100644 --- a/DataTypes/NumberSequence.cs +++ b/DataTypes/NumberSequence.cs @@ -75,11 +75,10 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is NumberSequence)) + if (!(obj is NumberSequence numberSeq)) return false; - var colorSeq = obj as NumberSequence; - var otherKeys = colorSeq.Keypoints; + var otherKeys = numberSeq.Keypoints; if (Keypoints.Length != otherKeys.Length) return false; diff --git a/DataTypes/NumberSequenceKeypoint.cs b/DataTypes/NumberSequenceKeypoint.cs index 8f04af3..acc5b57 100644 --- a/DataTypes/NumberSequenceKeypoint.cs +++ b/DataTypes/NumberSequenceKeypoint.cs @@ -36,11 +36,9 @@ public override bool Equals(object obj) { - if (!(obj is NumberSequenceKeypoint)) + if (!(obj is NumberSequenceKeypoint otherKey)) return false; - var otherKey = obj as NumberSequenceKeypoint; - if (!Time.Equals(otherKey.Time)) return false; diff --git a/DataTypes/PhysicalProperties.cs b/DataTypes/PhysicalProperties.cs index 48e90af..1225ae1 100644 --- a/DataTypes/PhysicalProperties.cs +++ b/DataTypes/PhysicalProperties.cs @@ -60,11 +60,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is PhysicalProperties)) + if (!(obj is PhysicalProperties other)) return false; - var other = obj as PhysicalProperties; - if (!Density.Equals(other.Density)) return false; diff --git a/DataTypes/ProtectedString.cs b/DataTypes/ProtectedString.cs index 2b11f4e..43e8e2f 100644 --- a/DataTypes/ProtectedString.cs +++ b/DataTypes/ProtectedString.cs @@ -54,10 +54,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is ProtectedString)) + if (!(obj is ProtectedString other)) return false; - var other = obj as ProtectedString; var otherBuffer = other.RawBuffer; if (RawBuffer.Length != otherBuffer.Length) diff --git a/DataTypes/Quaternion.cs b/DataTypes/Quaternion.cs index 5dc9336..8e1073e 100644 --- a/DataTypes/Quaternion.cs +++ b/DataTypes/Quaternion.cs @@ -134,21 +134,21 @@ namespace RobloxFiles.DataTypes public CFrame ToCFrame() { - float xc = X * 2f; - float yc = Y * 2f; - float zc = Z * 2f; + float xc = X * 2f, + yc = Y * 2f, + zc = Z * 2f; - float xx = X * xc; - float xy = X * yc; - float xz = X * zc; + float xx = X * xc, + xy = X * yc, + xz = X * zc; - float wx = W * xc; - float wy = W * yc; - float wz = W * zc; + float wx = W * xc, + wy = W * yc, + wz = W * zc; - float yy = Y * yc; - float yz = Y * zc; - float zz = Z * zc; + float yy = Y * yc, + yz = Y * zc, + zz = Z * zc; return new CFrame ( @@ -195,15 +195,33 @@ namespace RobloxFiles.DataTypes public static Quaternion operator *(Quaternion a, Quaternion b) { - Vector3 v1 = new Vector3(a.X, a.Y, a.Z); - float s1 = a.W; + Vector3 v1 = new Vector3(a.X, a.Y, a.Z), + v2 = new Vector3(b.X, b.Y, b.Z); - Vector3 v2 = new Vector3(b.X, b.Y, b.Z); - float s2 = b.W; + float s1 = a.W, + s2 = b.W; return new Quaternion(s1 * v2 + s2 * v1 + v1.Cross(v2), s1 * s2 - v1.Dot(v2)); } + public EulerAngles ToEulerAngles() + { + var angles = new EulerAngles(); + + double sinr_cosp = 2 * (W * X + Y * Z); + double cosr_cosp = 1 - 2 * (X * X + Y * Y); + angles.Roll = (float)Math.Atan2(sinr_cosp, cosr_cosp); + + double sinp = 2 * (W * Y - Z * X); + angles.Pitch = (float)Math.Asin(sinp); + + double siny_cosp = 2 * (W * Z + X * Y); + double cosy_cosp = 1 - 2 * (Y * Y + Z * Z); + angles.Yaw = (float)Math.Atan2(siny_cosp, cosy_cosp); + + return angles; + } + public override int GetHashCode() { int hash = X.GetHashCode() @@ -216,11 +234,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is Quaternion)) + if (!(obj is Quaternion other)) return false; - var other = obj as Quaternion; - if (!X.Equals(other.X)) return false; diff --git a/DataTypes/Ray.cs b/DataTypes/Ray.cs index fb82d8e..e16559f 100644 --- a/DataTypes/Ray.cs +++ b/DataTypes/Ray.cs @@ -53,11 +53,9 @@ public override bool Equals(object obj) { - if (!(obj is Ray)) + if (!(obj is Ray other)) return false; - var other = obj as Ray; - if (!Origin.Equals(other.Origin)) return false; diff --git a/DataTypes/Rect.cs b/DataTypes/Rect.cs index 3793ed1..884c5cd 100644 --- a/DataTypes/Rect.cs +++ b/DataTypes/Rect.cs @@ -38,11 +38,9 @@ public override bool Equals(object obj) { - if (!(obj is Rect)) + if (!(obj is Rect other)) return false; - var other = obj as Rect; - if (!Min.Equals(other.Min)) return false; diff --git a/DataTypes/Region3.cs b/DataTypes/Region3.cs index 9297416..fabb333 100644 --- a/DataTypes/Region3.cs +++ b/DataTypes/Region3.cs @@ -52,11 +52,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is Region3)) + if (!(obj is Region3 other)) return false; - var other = obj as Region3; - if (!Min.Equals(other.Min)) return false; diff --git a/DataTypes/Region3int16.cs b/DataTypes/Region3int16.cs index 33a5d8e..198ca75 100644 --- a/DataTypes/Region3int16.cs +++ b/DataTypes/Region3int16.cs @@ -27,11 +27,9 @@ public override bool Equals(object obj) { - if (!(obj is Region3int16)) + if (!(obj is Region3int16 other)) return false; - var other = obj as Region3int16; - if (!Min.Equals(other.Min)) return false; diff --git a/DataTypes/SharedString.cs b/DataTypes/SharedString.cs index 2727aaa..74dab1f 100644 --- a/DataTypes/SharedString.cs +++ b/DataTypes/SharedString.cs @@ -30,10 +30,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is SharedString)) + if (!(obj is SharedString other)) return false; - var other = (obj as SharedString); return Key.Equals(other.Key); } diff --git a/DataTypes/UDim.cs b/DataTypes/UDim.cs index b69c62c..f492243 100644 --- a/DataTypes/UDim.cs +++ b/DataTypes/UDim.cs @@ -39,11 +39,9 @@ public override bool Equals(object obj) { - if (!(obj is UDim)) + if (!(obj is UDim other)) return false; - var other = obj as UDim; - if (!Scale.Equals(other.Scale)) return false; diff --git a/DataTypes/UDim2.cs b/DataTypes/UDim2.cs index 5292488..ff878f4 100644 --- a/DataTypes/UDim2.cs +++ b/DataTypes/UDim2.cs @@ -47,11 +47,9 @@ public override bool Equals(object obj) { - if (!(obj is UDim2)) + if (!(obj is UDim2 other)) return false; - var other = obj as UDim2; - if (!X.Equals(other.X)) return false; diff --git a/DataTypes/Vector2.cs b/DataTypes/Vector2.cs index 307750e..72a3c6e 100644 --- a/DataTypes/Vector2.cs +++ b/DataTypes/Vector2.cs @@ -114,11 +114,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is Vector2)) + if (!(obj is Vector2 other)) return false; - var other = obj as Vector2; - if (!X.Equals(other.X)) return false; diff --git a/DataTypes/Vector2int16.cs b/DataTypes/Vector2int16.cs index 3b25585..23eb9a4 100644 --- a/DataTypes/Vector2int16.cs +++ b/DataTypes/Vector2int16.cs @@ -76,11 +76,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is Vector2int16)) + if (!(obj is Vector2int16 other)) return false; - var other = obj as Vector2int16; - if (!X.Equals(other.X)) return false; diff --git a/DataTypes/Vector3.cs b/DataTypes/Vector3.cs index bc41d8f..ffb97ad 100644 --- a/DataTypes/Vector3.cs +++ b/DataTypes/Vector3.cs @@ -171,11 +171,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is Vector3)) + if (!(obj is Vector3 other)) return false; - var other = obj as Vector3; - if (!X.Equals(other.X)) return false; diff --git a/DataTypes/Vector3int16.cs b/DataTypes/Vector3int16.cs index 7d89efe..1851956 100644 --- a/DataTypes/Vector3int16.cs +++ b/DataTypes/Vector3int16.cs @@ -84,11 +84,9 @@ namespace RobloxFiles.DataTypes public override bool Equals(object obj) { - if (!(obj is Vector3int16)) + if (!(obj is Vector3int16 other)) return false; - var other = obj as Vector3int16; - if (!X.Equals(other.X)) return false; diff --git a/Plugins/GenerateApiDump.rbxm b/Plugins/GenerateApiDump.rbxm index 7f3ebf9..e6a7253 100644 Binary files a/Plugins/GenerateApiDump.rbxm and b/Plugins/GenerateApiDump.rbxm differ diff --git a/Plugins/GenerateApiDump/PropertyPatches.lua b/Plugins/GenerateApiDump/PropertyPatches.lua index b5b2d29..5a306cb 100644 --- a/Plugins/GenerateApiDump/PropertyPatches.lua +++ b/Plugins/GenerateApiDump/PropertyPatches.lua @@ -6,6 +6,32 @@ local function UseColor3(propName) } end +local function TryDefineEnum(enumName) + local gotEnum, enum = pcall(function () + return Enum[enumName] + end) + + if gotEnum then + return "Enum:" .. tostring(enum) + end +end + +local function TryGetEnumItem(enumName, itemName) + local gotEnum, enum = pcall(function () + return Enum[enumName] + end) + + if gotEnum then + local gotEnumItem, item = pcall(function () + return enum[itemName] + end) + + if gotEnumItem then + return item + end + end +end + local GuiTextMixIn = { Add = { Transparency = "float" }; @@ -121,14 +147,14 @@ return { Add = { - LODX = "Enum:LevelOfDetailSetting"; - LODY = "Enum:LevelOfDetailSetting"; + LODX = TryDefineEnum("LevelOfDetailSetting"); + LODY = TryDefineEnum("LevelOfDetailSetting"); }; - Defaults = + Defaults = { - LODX = Enum.LevelOfDetailSetting.High; - LODY = Enum.LevelOfDetailSetting.High; + LODX = TryGetEnumItem("LevelOfDetailSetting", "High"); + LODY = TryGetEnumItem("LevelOfDetailSetting", "High"); }; }; @@ -282,12 +308,12 @@ return { Add = { - Technology = "Enum:Technology"; + Technology = TryDefineEnum("Technology"); }; Defaults = { - Technology = Enum.Technology.Compatibility; + Technology = TryGetEnumItem("Technology", "Compatibility"); }; }; @@ -485,7 +511,7 @@ return { MaxDistance = "xmlRead_MaxDistance_3"; xmlRead_MinDistance_3 = "EmitterSize"; - + RollOffMinDistance = "EmitterSize"; MinDistance = "EmitterSize"; Pitch = "PlaybackSpeed"; }; @@ -649,7 +675,7 @@ return StreamingMinRadius = "int"; StreamingTargetRadius = "int"; - StreamingPauseMode = "Enum:StreamingPauseMode"; + StreamingPauseMode = TryDefineEnum("StreamingPauseMode"); TerrainWeldsFixed = "bool"; }; @@ -661,10 +687,11 @@ return StreamingMinRadius = 64; StreamingTargetRadius = 1024; - StreamingPauseMode = Enum.StreamingPauseMode.Default; + StreamingPauseMode = TryGetEnumItem("StreamingPauseMode", "Default"); TerrainWeldsFixed = true; - MeshPartHeads = Enum.MeshPartHeads.Default; + MeshPartHeads = TryGetEnumItem("MeshPartHeads", "Default"); + MeshPartHeadsAndAccessories = TryGetEnumItem("MeshPartHeadsAndAccessories", "Default"); } } } \ No newline at end of file diff --git a/Plugins/GenerateApiDump/init.server.lua b/Plugins/GenerateApiDump/init.server.lua index f4933a9..5d465c3 100644 --- a/Plugins/GenerateApiDump/init.server.lua +++ b/Plugins/GenerateApiDump/init.server.lua @@ -77,8 +77,6 @@ local function exportStream(label) export.Source = results export.Name = label export.Parent = workspace - - plugin:OpenScript(export) end if isCoreScript then diff --git a/RobloxFileFormat.csproj b/RobloxFileFormat.csproj index 1fad478..7a1eb54 100644 --- a/RobloxFileFormat.csproj +++ b/RobloxFileFormat.csproj @@ -123,6 +123,7 @@ + diff --git a/RobloxFileFormat.dll b/RobloxFileFormat.dll index aae00fc..eec8cfd 100644 Binary files a/RobloxFileFormat.dll and b/RobloxFileFormat.dll differ diff --git a/Tree/Instance.cs b/Tree/Instance.cs index eff3d12..567bcb4 100644 --- a/Tree/Instance.cs +++ b/Tree/Instance.cs @@ -60,8 +60,8 @@ namespace RobloxFiles /// Indicates whether this Instance has been destroyed. public bool Destroyed { get; internal set; } - /// A list of CollectionService tags assigned to this Instance. - public List Tags { get; } = new List(); + /// A hashset of CollectionService tags assigned to this Instance. + public HashSet Tags { get; } = new HashSet(); /// The attributes defined for this Instance. public Attributes Attributes { get; private set; } @@ -100,7 +100,7 @@ namespace RobloxFiles { int length = value.Length; - List buffer = new List(); + var buffer = new List(); Tags.Clear(); for (int i = 0; i < length; i++) diff --git a/Tree/Property.cs b/Tree/Property.cs index 7a4f4ab..de8375b 100644 --- a/Tree/Property.cs +++ b/Tree/Property.cs @@ -104,10 +104,8 @@ namespace RobloxFiles return; } - if (RawValue is SharedString) + if (RawValue is SharedString sharedString) { - var sharedString = CastValue(); - if (sharedString != null) { RawBuffer = sharedString.SharedValue; @@ -115,10 +113,8 @@ namespace RobloxFiles } } - if (RawValue is ProtectedString) + if (RawValue is ProtectedString protectedString) { - var protectedString = CastValue(); - if (protectedString != null) { RawBuffer = protectedString.RawBuffer; @@ -222,9 +218,8 @@ namespace RobloxFiles { if (Instance != null) { - if (Name == "Tags" && value is byte[]) + if (Name == "Tags" && value is byte[] data) { - byte[] data = value as byte[]; Instance.SerializedTags = data; } else diff --git a/Utility/DefaultProperty.cs b/Utility/DefaultProperty.cs index 5c18cf7..942e124 100644 --- a/Utility/DefaultProperty.cs +++ b/Utility/DefaultProperty.cs @@ -7,8 +7,8 @@ namespace RobloxFiles.Utility { static class DefaultProperty { - private static Dictionary ClassMap; - private static HashSet Refreshed = new HashSet(); + private static readonly Dictionary ClassMap; + private static readonly HashSet Refreshed = new HashSet(); static DefaultProperty() { diff --git a/Utility/ImplicitMember.cs b/Utility/ImplicitMember.cs index 9ceedf4..7dfa553 100644 --- a/Utility/ImplicitMember.cs +++ b/Utility/ImplicitMember.cs @@ -40,16 +40,10 @@ namespace RobloxFiles.Utility { Type result = null; - if (member is FieldInfo) - { - var field = member as FieldInfo; + if (member is FieldInfo field) result = field.FieldType; - } - else if (member is PropertyInfo) - { - var prop = member as PropertyInfo; + else if (member is PropertyInfo prop) result = prop.PropertyType; - } return result; } @@ -57,32 +51,22 @@ namespace RobloxFiles.Utility public object GetValue(object obj) { - if (member is FieldInfo) - { - var field = member as FieldInfo; + if (member is FieldInfo field) return field.GetValue(obj); - } - else if (member is PropertyInfo) - { - var prop = member as PropertyInfo; + else if (member is PropertyInfo prop) return prop.GetValue(obj); - } - + return null; } public void SetValue(object obj, object value) { - if (member is FieldInfo) - { - var field = member as FieldInfo; + if (member is FieldInfo field) field.SetValue(obj, value); - } - else if (member is PropertyInfo) - { - var prop = member as PropertyInfo; + else if (member is PropertyInfo prop) prop.SetValue(obj, value); - } + + RobloxFile.LogError("Unknown field in ImplicitMember.SetValue"); } } }