diff --git a/BinaryFormat/Chunks/PROP.cs b/BinaryFormat/Chunks/PROP.cs index a18ef82..756f137 100644 --- a/BinaryFormat/Chunks/PROP.cs +++ b/BinaryFormat/Chunks/PROP.cs @@ -328,23 +328,8 @@ namespace RobloxFiles.BinaryFormat.Chunks { // Make sure this value is in a safe range. int orientId = (rawOrientId - 1) % 36; - - NormalId xColumn = (NormalId)(orientId / 6); - Vector3 R0 = Vector3.FromNormalId(xColumn); - - NormalId yColumn = (NormalId)(orientId % 6); - Vector3 R1 = Vector3.FromNormalId(yColumn); - - // Compute R2 using the cross product of R0 and R1. - Vector3 R2 = R0.Cross(R1); - - // Generate the rotation matrix. - matrices[i] = new float[9] - { - R0.X, R0.Y, R0.Z, - R1.X, R1.Y, R1.Z, - R2.X, R2.Y, R2.Z, - }; + var cf = CFrame.FromOrientId(orientId); + matrices[i] = cf.GetComponents(); } else if (Type == PropertyType.Quaternion) { diff --git a/DataTypes/CFrame.cs b/DataTypes/CFrame.cs index ac3720e..ce672cb 100644 --- a/DataTypes/CFrame.cs +++ b/DataTypes/CFrame.cs @@ -1,4 +1,5 @@ -using System; +using RobloxFiles.Enums; +using System; using System.Diagnostics.Contracts; namespace RobloxFiles.DataTypes @@ -447,5 +448,25 @@ namespace RobloxFiles.DataTypes return orientId; } + + internal static CFrame FromOrientId(int orientId) + { + var xColumn = (NormalId)(orientId / 6); + var yColumn = (NormalId)(orientId % 6); + + var R0 = Vector3.FromNormalId(xColumn); + var R1 = Vector3.FromNormalId(yColumn); + var R2 = R0.Cross(R1); + + var matrix = new float[12] + { + 0, 0, 0, + R0.X, R0.Y, R0.Z, + R1.X, R1.Y, R1.Z, + R2.X, R2.Y, R2.Z + }; + + return new CFrame(matrix); + } } } \ No newline at end of file diff --git a/Generated/Classes.cs b/Generated/Classes.cs index 37bf586..dae0a49 100644 --- a/Generated/Classes.cs +++ b/Generated/Classes.cs @@ -4318,6 +4318,24 @@ namespace RobloxFiles { } + public class BubbleChatConfiguration : TextChatConfigurations + { + public string AdorneeName = "HumanoidRootPart"; + public Color3 BackgroundColor3 = Color3.FromRGB(250, 250, 250); + public double BackgroundTransparency = 0.1; + public float BubbleDuration = 15; + public float BubblesSpacing = 6; + public bool Enabled = true; + public Font Font = Font.GothamMedium; + public FontFace FontFace = FontFace.FromEnum(Enums.Font.GothamMedium); + public Vector3 LocalPlayerStudsOffset = Vector3.zero; + public float MaxDistance = 100; + public float MinimizeDistance = 40; + public Color3 TextColor3 = Color3.FromRGB(57, 59, 61); + public long TextSize = 16; + public float VerticalStudsOffset = 0; + } + public class ChatInputBarConfiguration : TextChatConfigurations { public Color3 BackgroundColor3 = Color3.FromRGB(25, 27, 29); diff --git a/Plugins/.vscode/tasks.json b/Plugins/.vscode/tasks.json deleted file mode 100644 index af3f11b..0000000 --- a/Plugins/.vscode/tasks.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "version": "2.0.0", - - "tasks": - [ - { - "type": "shell", - "label": "Build Plugin", - "command": "rojo build --output GenerateApiDump.rbxm", - - "group": "build" - }, - - { - "type": "shell", - "label": "Build and Test Plugin", - - "command": "powershell -ExecutionPolicy ByPass -File DeployToStudio.ps1", - "dependsOn": ["Build Plugin"], - - "group": - { - "kind": "build", - "isDefault": true - } - } - ] -} \ No newline at end of file diff --git a/Plugins/DeployToStudio.ps1 b/Plugins/DeployToStudio.ps1 deleted file mode 100644 index 0a0955d..0000000 --- a/Plugins/DeployToStudio.ps1 +++ /dev/null @@ -1,4 +0,0 @@ -$pluginName = "GenerateApiDump.rbxm" -$destPath = "$env:localappdata\Roblox\Plugins\" + $pluginName - -Copy-Item -Path $pluginName -Destination $destPath \ No newline at end of file diff --git a/Plugins/GenerateApiDump.rbxm b/Plugins/GenerateApiDump.rbxm deleted file mode 100644 index dad68dc..0000000 Binary files a/Plugins/GenerateApiDump.rbxm and /dev/null differ diff --git a/Plugins/GenerateApiDump/init.server.lua b/Plugins/GenerateApiDump/init.server.lua index 27fb13b..4af52a2 100644 --- a/Plugins/GenerateApiDump/init.server.lua +++ b/Plugins/GenerateApiDump/init.server.lua @@ -14,6 +14,7 @@ local singletons = { ParabolaAdornment = Instance.new("BoxHandleAdornment"), -- close enough StarterPlayerScripts = StarterPlayer:WaitForChild("StarterPlayerScripts"), StarterCharacterScripts = StarterPlayer:WaitForChild("StarterCharacterScripts"), + BubbleChatConfiguration = TextChatService:WaitForChild("BubbleChatConfiguration", 10), ChatWindowConfiguration = TextChatService:WaitForChild("ChatWindowConfiguration", 10), ChatInputBarConfiguration = TextChatService:WaitForChild("ChatInputBarConfiguration", 10), } diff --git a/Plugins/make b/Plugins/make new file mode 100644 index 0000000..a6b5713 --- /dev/null +++ b/Plugins/make @@ -0,0 +1,2 @@ +#!/bin/sh +rojo build --output $LOCALAPPDATA/Roblox/Plugins/GenerateApiDump.rbxm \ No newline at end of file diff --git a/RobloxFileFormat.dll b/RobloxFileFormat.dll index 5cc0e0e..8a07ee0 100644 Binary files a/RobloxFileFormat.dll and b/RobloxFileFormat.dll differ diff --git a/Tokens/CFrame.cs b/Tokens/CFrame.cs index 842085e..4ec7ac7 100644 --- a/Tokens/CFrame.cs +++ b/Tokens/CFrame.cs @@ -1,12 +1,23 @@ -using System.Xml; +using System; +using System.Runtime.Remoting.Messaging; +using System.Xml; using RobloxFiles.DataTypes; +using RobloxFiles.Enums; namespace RobloxFiles.Tokens { - public class CFrameToken : IXmlPropertyToken + public class CFrameToken : IXmlPropertyToken, IAttributeToken { public string XmlPropertyToken => "CoordinateFrame; CFrame"; - private static readonly string[] Coords = new string[12] { "X", "Y", "Z", "R00", "R01", "R02", "R10", "R11", "R12", "R20", "R21", "R22"}; + public AttributeType AttributeType => AttributeType.CFrame; + + private static readonly string[] Coords = new string[12] + { + "X", "Y", "Z", + "R00", "R01", "R02", + "R10", "R11", "R12", + "R20", "R21", "R22" + }; public static CFrame ReadCFrame(XmlNode token) { @@ -65,5 +76,52 @@ namespace RobloxFiles.Tokens CFrame value = prop.Value as CFrame; WriteCFrame(value, doc, node); } + + public CFrame ReadAttribute(RbxAttribute attribute) + { + float x = attribute.ReadFloat(), + y = attribute.ReadFloat(), + z = attribute.ReadFloat(); + + var rawOrientId = attribute.ReadByte(); + var pos = new Vector3(x, y, z); + + if (rawOrientId > 0) + { + int orientId = (rawOrientId - 1) % 36; + return CFrame.FromOrientId(orientId) + pos; + } + else + { + float[] matrix = new float[12]; + + for (int i = 3; i < 12; i++) + matrix[i] = attribute.ReadFloat(); + + return new CFrame(matrix) + pos; + } + } + + public void WriteAttribute(RbxAttribute attribute, CFrame value) + { + Vector3 pos = value.Position; + attribute.WriteFloat(pos.X); + attribute.WriteFloat(pos.Y); + attribute.WriteFloat(pos.Z); + + int orientId = value.GetOrientId(); + attribute.WriteByte((byte)(orientId + 1)); + + if (orientId == -1) + { + float[] components = value.GetComponents(); + + for (int i = 3; i < 12; i++) + { + float component = components[i]; + attribute.WriteFloat(component); + } + } + } } } diff --git a/Tokens/Enum.cs b/Tokens/Enum.cs index 3109346..8a86a46 100644 --- a/Tokens/Enum.cs +++ b/Tokens/Enum.cs @@ -1,8 +1,8 @@ using System; using System.Diagnostics.Contracts; -using System.Reflection; using System.Xml; +using RobloxFiles.Utility; using RobloxFiles.XmlFormat; namespace RobloxFiles.Tokens @@ -19,12 +19,11 @@ namespace RobloxFiles.Tokens { Instance inst = prop.Instance; Type instType = inst?.GetType(); - - FieldInfo info = instType.GetField(prop.Name, Property.BindingFlags); + var info = ImplicitMember.Get(instType, prop.Name); if (info != null) { - Type enumType = info.FieldType; + Type enumType = info.MemberType; string item = value.ToInvariantString(); prop.Type = PropertyType.Enum; diff --git a/Tokens/Font.cs b/Tokens/Font.cs index fcd392f..977efb4 100644 --- a/Tokens/Font.cs +++ b/Tokens/Font.cs @@ -42,16 +42,19 @@ namespace RobloxFiles.Tokens var weight = (uint)font.Weight; string family = font.Family; - string contentType = "null"; + string familyType = "null"; + + string cachedType = "null"; + string cachedId = font.CachedFaceId; if (family.Length > 0) - contentType = "url"; + familyType = "url"; - var contentNode = doc.CreateElement(contentType); - contentNode.InnerText = family; + if (cachedId.Length > 0) + cachedType = "url"; var familyNode = doc.CreateElement("Family"); - familyNode.AppendChild(contentNode); + familyNode.InnerText = $"<{familyType}>{family}"; node.AppendChild(familyNode); var weightNode = doc.CreateElement("Weight"); @@ -61,6 +64,10 @@ namespace RobloxFiles.Tokens var styleNode = doc.CreateElement("Style"); styleNode.InnerText = $"{font.Style}"; node.AppendChild(styleNode); + + var cacheNode = doc.CreateElement("CachedFaceId"); + cacheNode.InnerText = $"<{cachedType}>{cachedId}"; + node.AppendChild(cacheNode); } public FontFace ReadAttribute(RbxAttribute attribute) diff --git a/Tree/Attributes.cs b/Tree/Attributes.cs index 3cee16c..e2b7df1 100644 --- a/Tree/Attributes.cs +++ b/Tree/Attributes.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.Serialization; using System.Text; namespace RobloxFiles @@ -33,7 +32,7 @@ namespace RobloxFiles Vector3 = 17, // Vector2int16 = 18, // Vector3int16 = 19, - // CFrame = 20, + CFrame = 20, // Enum = 21, NumberSequence = 23, // NumberSequenceKeypoint = 24, @@ -154,6 +153,7 @@ namespace RobloxFiles internal string ReadString() => Reader.ReadString(true); internal void WriteInt(int value) => Writer.Write(value); + internal void WriteByte(byte value) => Writer.Write(value); internal void WriteBool(bool value) => Writer.Write(value); internal void WriteFloat(float value) => Writer.Write(value); internal void WriteDouble(double value) => Writer.Write(value); diff --git a/Tree/Instance.cs b/Tree/Instance.cs index 3ad9566..3031505 100644 --- a/Tree/Instance.cs +++ b/Tree/Instance.cs @@ -45,6 +45,9 @@ namespace RobloxFiles /// The source AssetId this instance was created in. public long SourceAssetId = -1; + /// A unique identifier declared for the history of this instance. + public UniqueId HistoryId; + /// A unique identifier declared for this instance. public UniqueId UniqueId; diff --git a/UnitTest/Files/Binary.rbxl b/UnitTest/Files/Binary.rbxl index e5b9828..26ed08c 100644 Binary files a/UnitTest/Files/Binary.rbxl and b/UnitTest/Files/Binary.rbxl differ