using System; using System.IO; using System.Text; using System.Threading.Tasks; using RobloxFiles.BinaryFormat; using RobloxFiles.XmlFormat; namespace RobloxFiles { /// /// Represents a loaded *.rbxl/*.rbxm Roblox file. /// All of the surface-level Instances are stored in the RobloxFile's 'Contents' property. /// public class RobloxFile : IRobloxFile { /// /// Indicates if this RobloxFile has loaded data already. /// public bool Initialized { get; private set; } /// /// A reference to the inner IRobloxFile implementation that this RobloxFile opened with. /// It can be a BinaryRobloxFile, or an XmlRobloxFile. /// public IRobloxFile InnerFile { get; private set; } /// /// A reference to a Folder Instance that stores all of the contents that were loaded. /// public Instance Contents => InnerFile.Contents; /// /// Initializes the RobloxFile from the provided buffer, if it hasn't been Initialized yet. /// /// public void ReadFile(byte[] buffer) { if (!Initialized) { if (buffer.Length > 14) { string header = Encoding.UTF7.GetString(buffer, 0, 14); IRobloxFile file = null; if (header == BinaryRobloxFile.MagicHeader) file = new BinaryRobloxFile(); else if (header.StartsWith(" /// Creates a RobloxFile from a provided byte sequence that represents the file. /// /// private RobloxFile(byte[] buffer) { ReadFile(buffer); } /// /// Opens a Roblox file from a byte sequence that represents the file. /// /// A byte sequence that represents the file. public static RobloxFile Open(byte[] buffer) { return new RobloxFile(buffer); } /// /// Opens a Roblox file by reading from a provided Stream. /// /// The stream to read the Roblox file from. public static RobloxFile Open(Stream stream) { byte[] buffer; using (MemoryStream memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); buffer = memoryStream.ToArray(); } return Open(buffer); } /// /// Opens a Roblox file from a provided file path. /// /// A path to a Roblox file to be opened. public static RobloxFile Open(string filePath) { byte[] buffer = File.ReadAllBytes(filePath); return Open(buffer); } /// /// Creates and runs a Task to open a Roblox file from a byte sequence that represents the file. /// /// A byte sequence that represents the file. public static Task OpenAsync(byte[] buffer) { return Task.Run(() => Open(buffer)); } /// /// Creates and runs a Task to open a Roblox file using a provided Stream. /// /// The stream to read the Roblox file from. public static Task OpenAsync(Stream stream) { return Task.Run(() => Open(stream)); } /// /// Opens a Roblox file from a provided file path. /// /// A path to a Roblox file to be opened. public static Task OpenAsync(string filePath) { return Task.Run(() => Open(filePath)); } /// /// Allows you to access a child/descendant of this file's contents, and/or one of its properties. /// The provided string should be a period-separated (.) path to what you wish to access. /// This will throw an exception if any part of the path cannot be found. /// /// ~ Examples ~ /// var terrain = robloxFile["Workspace.Terrain"] as Instance; /// var currentCamera = robloxFile["Workspace.CurrentCamera"] as Property; /// /// public object this[string accessor] => Contents[accessor]; } }