/// <summary> /// Loads an .mbin file and returns an NMSTemplate which can be either used as-is, or cast to a specific type. /// </summary> /// <param name="path">File path to the .mbin to be loaded into memory.</param> /// <returns>NMSTemplate</returns> public static NMSTemplate LoadMbin(string path) { MBINFile mbin = new MBINFile(path); if (!mbin.Load() || !mbin.Header.IsValid) { throw new InvalidDataException("Not a valid MBIN file!"); } NMSTemplate data = null; try { data = mbin.GetData(); if (data is null) { throw new InvalidDataException("Invalid MBIN data."); } } catch (Exception e) { throw new MbinException($"Failed to read {mbin.Header.GetXMLTemplateName()} from MBIN.", e, path); } mbin.Dispose(); return(data); }
private static void WarnBroken(string msg, string filePath, MBINFile mbin, NMSTemplate data = null, ulong expectedGUID = 0L) { #if ERROR_ON_BROKEN if (mbin != null) { throw new MbinException(msg, filePath, mbin); } throw new ExmlException(msg, filePath, data); #endif Async.SynchronizeTask(errorLock, ref errorTask, () => { warnedFiles.Add(filePath); warnings.Add(msg); if (Logger.LogStream.BaseStream.Position != lastPosition) { msg = $"\n{msg}"; } Logger.LogWarning($"{msg}"); using (var indentInfo = new Logger.IndentScope()) { Logger.LogMessage(false, Console.Out, null, ""); // newline, console only Logger.LogMessage(Console.Out, $"[INFO]: {filePath}"); if (mbin != null) { Logger.LogMessage(false, Console.Out, null, ""); // newline, console only Logger.LogMessage(null, "INFO", $"{CommandLine.GetFileInfo( mbin )}"); if (expectedGUID != 0L) { Logger.LogMessage(null, "EXPECTED INFO", $"GUID: {expectedGUID:X}\n"); } } //Logger.LogMessage( true, Console.Out, null, "" ); // newline, console and log } lastPosition = Logger.LogStream.BaseStream.Position; }); }
public void IterateFields(NMSTemplate data, Type type, TreeViewItem destinationControl) { IOrderedEnumerable <System.Reflection.FieldInfo> fields = type.GetFields().OrderBy(field => field.MetadataToken); foreach (FieldInfo fieldInfo in fields) { Debug.WriteLine($"type = {fieldInfo.FieldType}, name = {fieldInfo.Name}, value = {fieldInfo.GetValue(data)}"); //write all fields to debug //Check for NMSAttribute ignore -code by @GaticusHax var attributes = (NMSAttribute[])fieldInfo.GetCustomAttributes(typeof(NMSAttribute), false); libMBIN.Models.NMSAttribute attrib = null; if (attributes.Length > 0) { attrib = attributes[0]; } bool ignore = false; if (attrib != null) { ignore = attrib.Ignore; } if (!ignore) { AddField(destinationControl, data, fieldInfo); } } }
public void TestTemplateSizes() { var table = new TemplateSizes.Table(); using (StreamReader streamIn = new StreamReader(GetTablePath())) { table.Load(streamIn); } var doneTemplates = new List <string>(); foreach (var record in table) { if (!NMSTemplate.NMSTemplateMap.ContainsKey(record.TemplateName)) { Debug.WriteLine($"TestTemplateSizes: size 0x{record.TemplateSize:X} defined for missing template {record.TemplateName}!"); continue; } int size = NMSTemplate.GetTemplateDataSize(record.TemplateName); Assert.AreEqual(record.TemplateSize, size, $"template {record.TemplateName} size 0x{record.TemplateSize:X} != 0x{size:X}"); doneTemplates.Add(record.TemplateName); } foreach (var template in NMSTemplate.NMSTemplateMap) { if (!doneTemplates.Contains(template.Key)) { Debug.WriteLine($"TestTemplateSizes: no size defined for template {template.Key}!"); } } }
//This is the function called when we click the loadMBIN button. public void LoadMBIN() { System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog(); openFileDialog.Filter = "MBIN Files | *.mbin; *.MBIN"; if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { _mbinPath = openFileDialog.FileName; Debug.WriteLine(_mbinPath.ToString()); NMSTemplate template = null; using (MBINFile mbin = new MBINFile(_mbinPath)) { mbin.Load(); template = mbin.GetData(); } if (template != null) { //We now handle the formatting in this custom control, which is loaded into the MainWindowView when done. MBinViewer = new MBinViewModel(template); } } else { Debug.WriteLine("No MBIN Selected"); } }
public void TestTemplateSizes() { var doneTemplates = new List <string>(); foreach (var template in NMSTemplate.NMSTemplateMap) { if (!templateSizes.ContainsKey(template.Key)) { Debug.WriteLine($"TestTemplateSizes: no size defined for template {template.Key}!"); continue; } var templateSize = NMSTemplate.GetTemplateDataSize(template.Key); var templateExpectedSize = templateSizes[template.Key]; Assert.AreEqual(templateExpectedSize, templateSize, $"template {template.Key} size 0x{templateSize:X} != 0x{templateExpectedSize:X}"); doneTemplates.Add(template.Key); } foreach (var template in templateSizes) { if (!doneTemplates.Contains(template.Key)) { Debug.WriteLine($"TestTemplateSizes: size 0x{template.Value:X} defined for missing template {template.Key}!"); } } }
private static NMSTemplate ReadTemplateFromXmlReader(XmlReader reader) { EXmlData root = (EXmlData)Serializer.Deserialize(reader); NMSTemplate rootTemplate = NMSTemplate.DeserializeEXml(root); return(rootTemplate); }
/// <summary> /// Writes the NMSTemplate object to an .exml file. /// </summary> /// <param name="outputpath">The location to write the .exml file.</param> /// <param name="hideVersionInfo">If true, version info is not written to the EXML file.</param> public static string WriteTemplate(NMSTemplate template, bool hideVersionInfo) { var origCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; var xmlSettings = new XmlWriterSettings { Indent = true, Encoding = Encoding.UTF8 }; using (var stringWriter = new EncodedStringWriter(Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter, xmlSettings)) { string ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); if (!hideVersionInfo) { xmlTextWriter.WriteComment(String.Format("File created using MBINCompiler version ({0})", ver.Substring(0, ver.Length - 2))); } var data = template.SerializeEXml(false); Serializer.Serialize(xmlTextWriter, data, Namespaces); xmlTextWriter.Flush(); var xmlData = stringWriter.GetStringBuilder().ToString(); Thread.CurrentThread.CurrentCulture = origCulture; return(xmlData); } }
public void SetData(NMSTemplate template) { _io.Stream.SetLength(0x60); _io.Stream.Position = 0x60; _io.Writer.Write(template.SerializeBytes()); Header.TemplateName = "c" + template.GetType().Name; }
public void TestOffsetOf() { Assert.AreEqual(0xB8, NMSTemplate.OffsetOf("GcAIShipSpawnData", "ChildSpawns")); Assert.AreEqual(0x8C, NMSTemplate.OffsetOf("GcAIShipSpawnData", "Spread")); Assert.AreEqual(0x1C, NMSTemplate.OffsetOf("GcCreatureDebugSpawnData", "SmoothTime")); Assert.AreEqual(0x0, NMSTemplate.OffsetOf("GcCustomisationColourPalettes", "ColourPalettes")); Assert.AreEqual(0x4510, NMSTemplate.OffsetOf("GcCustomisationColourPalettes", "ExtraData")); Assert.AreEqual(0x1C9C, NMSTemplate.OffsetOf("GcGameplayGlobals", "WeaponSpawnAltObject")); }
private static NMSTemplate ReadTemplateFromXmlReader(XmlReader reader, out string templateName) { EXmlData root = (EXmlData)Serializer.Deserialize(reader); templateName = root?.Template; NMSTemplate rootTemplate = NMSTemplate.DeserializeEXml(root); return(rootTemplate); }
public bool Load() { if (_io.Stream.Length < 0x60) { return(false); } _io.Stream.Position = 0; Header = (MBINHeader)NMSTemplate.DeserializeBinaryTemplate(_io.Reader, "MBINHeader"); return(true); }
static void ExtractMBinFile(FileInfo inputFile, string outputFileName) { using var mbinFile = new MBINFile(inputFile.FullName); using var outputFile = File.Create(outputFileName); using var sw = new StreamWriter(outputFile); if (!(mbinFile.Load() && mbinFile.Header.IsValid)) { throw new InvalidDataException("Invalid File"); } var type = NMSTemplate.GetTemplateType(mbinFile.Header.GetXMLTemplateName()); if (type == null) { throw new NullReferenceException(); } var nms = (NMSAttribute)(type.GetCustomAttributes(typeof(NMSAttribute), false)?[0] ?? null); var broken = nms.Broken; // GUID's for the old files ulong[] UnsupportedGUIDs = new ulong[] { }; var mismatch = (mbinFile.Header.TemplateGUID != nms.GUID); bool unsupported = (UnsupportedGUIDs.Contains(mbinFile.Header.TemplateGUID)); if (broken) { var previousColour = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("File is broken"); Console.ForegroundColor = previousColour; } else if (unsupported) { var previousColour = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("File is Unsupported"); Console.ForegroundColor = previousColour; } else if (mismatch) { var previousColour = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("File is Mismatched"); Console.ForegroundColor = previousColour; } var data = mbinFile.GetData(); sw.Write(EXmlFile.WriteTemplate(data)); sw.Flush(); }
public static void Align(this BinaryWriter writer, int alignBy, string name) { long offset = writer.BaseStream.Position; long mod = offset % alignBy; if (mod != 0) { writer.Write(new byte[alignBy - mod]); NMSTemplate.DebugLogTemplate($"[C] aligned {name} to offset 0x{writer.BaseStream.Position:X}"); } }
public void SetData(NMSTemplate template) { _io.Stream.SetLength(0x60); _io.Stream.Position = 0x60; byte[] data = template.SerializeBytes(); _io.Writer.Write(data); FileLength = (ulong)data.LongLength; Header.TemplateName = "c" + template.GetType().Name; }
public ActionTrigger(GcActionTrigger at) { _template = at; //Populate Actions Actions = new List <Action>(); foreach (NMSTemplate t in at.Action) { if (t is GcNodeActivationAction) { Actions.Add(new NodeActivationAction(t)); } else if (t is GcGoToStateAction) { Actions.Add(new GoToStateAction(t)); } else if (t is GcPlayAnimAction) { Actions.Add(new PlayAnimAction(t)); } else if (t is EmptyNode) { continue; } else { Console.WriteLine("Non Implemented Action"); } } //Set Trigger if (at.Trigger is GcPlayerNearbyEvent) { Trigger = new PlayerNearbyEventTrigger(at.Trigger); } else if (at.Trigger is GcStateTimeEvent) { Trigger = new StateTimeEventTrigger(at.Trigger); } else if (at.Trigger is GcAnimFrameEvent) { Trigger = new AnimFrameEventTrigger(at.Trigger); } else { Console.WriteLine("Non Implemented Trigger"); Trigger = null; } }
public static string WriteTemplate(NMSTemplate template) { var xmlSettings = new XmlWriterSettings { Indent = true, Encoding = Encoding.UTF8 }; using (var stringWriter = new EncodedStringWriter(Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter, xmlSettings)) { EXmlData data = template.SerializeEXml(); Serializer.Serialize(xmlTextWriter, data, Namespaces); xmlTextWriter.Flush(); return(stringWriter.GetStringBuilder().ToString()); } }
public void SetData(NMSTemplate template) { _io.Stream.SetLength(0x60); _io.Stream.Position = 0x60; /* * // if we want to get the file size: * byte[] data = template.SerializeBytes(); * _io.Writer.Write(data); * * this.FileLength = (ulong)data.LongLength; */ // otherwise just do: _io.Writer.Write(template.SerializeBytes()); Header.TemplateName = "c" + template.GetType().Name; }
public static List <MBINField> GetMBINFields(Stream file) { NMSTemplate template = null; using (libMBIN.MBINFile mbin = new libMBIN.MBINFile(file)) { mbin.Load(); // load the header information from the file template = mbin.GetData(); // populate the data struct. } if (template != null) { return(IterateFields(template, template.GetType())); } else { Helpers.BasicDialogBox("MBIN Loading Error...", "Unable to load the MBIN!"); return(null); } }
public static List <MBINField> IterateFields(NMSTemplate data, Type type) { List <MBINField> mbinContents = new List <MBINField>(); IOrderedEnumerable <FieldInfo> fields = type.GetFields().OrderBy(field => field.MetadataToken); if (fields != null) { foreach (FieldInfo fieldInfo in fields) { Debug.WriteLine($"type = {fieldInfo.FieldType}, name = {fieldInfo.Name}, value = {fieldInfo.GetValue(data)}"); //write all fields to debug //Check for NMSAttribute ignore -code by @GaticusHax var attributes = (NMSAttribute[])fieldInfo.GetCustomAttributes(typeof(NMSAttribute), false); // libMBIN.Models.NMSAttribute attrib = null; // if (attributes.Length > 0) { attrib = attributes[0]; // } bool ignore = false; // if (attrib != null) { ignore = attrib.Ignore; // } if (!ignore) // Add the field to the mbinContents list { // mbinContents.Add(new MBINField // { // Name = fieldInfo.Name, // Value = fieldInfo.GetValue(data).ToString(), // NMSType = fieldInfo.FieldType.ToString() // }); // } // } } else { // Helpers.BasicDialogBox("Error Getting Fields...", "Couldn't get the fields for some reason.\n Data: " + data.ToString() + "\n Will return blank List"); mbinContents = null; } return(mbinContents); }
public void GenerateTemplateSizeTable() { string dataDir = Database.Utils.GetDirectory(libMBIN.Version.NMSVersion); var table = new TemplateSizes.Table(); string logPath = Path.Combine(dataDir, "TemplateSizes.tsv"); foreach (var type in NMSTemplate.NMSTemplateMap.Values) { NMSTemplate template = Activator.CreateInstance(type) as NMSTemplate; table.Add(new TemplateSizes.Record(type.Name, template.GetDataSize())); } Utils.SetFileReadOnly(logPath, false); using (var streamOut = new StreamWriter(logPath)) { streamOut.WriteLine("# Tab-separated values. Open with a spreadsheet app such as Excel.\n"); streamOut.WriteLine("# READ-ONLY. DO NOT MODIFY OR DELETE.\n"); table.Save(streamOut); } Utils.SetFileReadOnly(logPath, true); }
/// <summary> /// Loads a file and returns an NMSTemplate which can be either used as-is, or cast to a specific type. /// The path to either an .exml or .mbin can be provided here and the correct method will be selected automatically. /// </summary> /// <param name="file">File path to the .exml or .mbin to be loaded into memory.</param> /// <returns>NMSTemplate</returns> public static NMSTemplate LoadFile(string file) { NMSTemplate data = null; if (Path.HasExtension(file)) { string x = Path.GetExtension(file).ToUpper(); if (x == ".EXML") { data = LoadExml(file); } else if (x == ".MBIN" || x == ".PC") { data = LoadMbin(file); } else { throw new InvalidDataException($"{file} does not have a supported file type. File type must be one of .exml or .mbin"); } } return(data); }
public void OpenGEOMDATAFilewithlibMBIN() { string filepath = "E:\\SteamLibrary1\\steamapps\\common\\No Man's Sky\\GAMEDATA\\MODELS\\COMMON\\CHARACTERS\\ASTRONAUT\\ASTRONAUT01.GEOMETRY.MBIN.PC"; //string filepath = "E:\\SteamLibrary1\\steamapps\\common\\No Man's Sky\\GAMEDATA\\MODELS\\COMMON\\CHARACTERS\\ASTRONAUT\\ASTRONAUT01.SCENE.EXML"; //Try to read EXML //TkSceneNodeData t = (TkSceneNodeData)libMBIN.EXmlFile.ReadTemplate(filepath); //Console.WriteLine("All Good Loading", t.Name); try { libMBIN.MBINFile mbinf = new libMBIN.MBINFile(filepath); mbinf.Load(); NMSTemplate template = mbinf.GetData(); mbinf.Dispose(); Console.WriteLine("All Good Loading"); } catch (Exception ex) { Console.WriteLine("Something Went Wrong"); Assert.Fail(); } }
public bool Load(bool getVersion = false) { _io.Stream.Position = 0; Header = (MBINHeader)NMSTemplate.DeserializeBinaryTemplate(_io.Reader, "MBINHeader"); if (getVersion) { string mbinVer = Header.Tag; Console.WriteLine(mbinVer.Substring(8)); } else { if (Header.Tag.Contains("MBIN")) // check whether the file has been generated by MBINCompiler basically { string ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); if (Header.Tag != String.Format("MBINCver{0}", ver.Substring(0, ver.Length - 2))) { Console.WriteLine("Incorrect version"); return(false); } } } return(true); }
/// <summary>Convert EXML to MBIN</summary> /// <param name="fIn">Source file</param> /// <param name="msOut">Output stream</param> /// <param name="fileOut">Output file path. Passed through as the return value. For geometry files, ".PC" will be appended.</param> /// <returns>fileOut</returns> private static string ConvertEXML(string inputPath, FileStream fIn, MemoryStream msOut, string fileOut) { string templateName; NMSTemplate data = null; try { data = EXmlFile.ReadTemplateFromStream(fIn, out templateName); Type type = NMSTemplate.GetTemplateType(templateName); var nms = (NMSAttribute)(data.GetType().GetCustomAttributes(typeof(NMSAttribute), false)?[0] ?? null); if (nms.Broken) { FileIsBroken(inputPath, data); } if (data is null) { throw new InvalidDataException($"Failed to deserialize EXML."); } if (data is libMBIN.NMS.Toolkit.TkGeometryData | data is libMBIN.NMS.Toolkit.TkGeometryStreamData) { fileOut += ".PC"; } var mbin = new MBINFile(msOut) { Header = new MBINHeader() }; mbin.Header.SetDefaults(data.GetType(), FormatVersion); mbin.SetData(data); mbin.Save(); } catch (Exception e) { throw new ExmlException(e, fIn.Name, data); } return(fileOut); }
//public bool Load(bool getVersion = false) public bool Load() { _io.Stream.Position = 0; Header = (MBINHeader)NMSTemplate.DeserializeBinaryTemplate(_io.Reader, "MBINHeader"); //if (getVersion) //{ // string mbinVer = Header.GetMBINVersion(); // Console.WriteLine(mbinVer.Substring(8)); //} /*else * { * if (Header.Tag == 0x726576434E49424D) // check whether the file has been generated by MBINCompiler basically * { * string ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); * if (Header.Tag != String.Format("MBINCver{0}", ver.Substring(0, ver.Length - 2))) * { * Console.WriteLine("Incorrect version"); * return false; * } * } * }*/ return(true); }
// ===================== // = Main Program Loop = // ===================== public TreeView ParseMbin(string mbinPath) { // going to use the type from the Tuple created in loadMbin NMSTemplate template = null; using (libMBIN.MBINFile mbin = new libMBIN.MBINFile(mbinPath)) { mbin.Load(); // load the header information from the file template = mbin.GetData(); // populate the data struct. } if (template != null) { TreeViewItem root = new TreeViewItem(); mainTree.Items.Add(root); IterateFields(template, template.GetType(), root); return(mainTree); } else { MessageBox.Show($"Unable to load file!\n{mbinPath}", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error); return(null); } }
public static string WriteTemplate(NMSTemplate template) { var origCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; var xmlSettings = new XmlWriterSettings { Indent = true, Encoding = Encoding.UTF8 }; using (var stringWriter = new EncodedStringWriter(Encoding.UTF8)) using (var xmlTextWriter = XmlWriter.Create(stringWriter, xmlSettings)) { var data = template.SerializeEXml(false); Serializer.Serialize(xmlTextWriter, data, Namespaces); xmlTextWriter.Flush(); var xmlData = stringWriter.GetStringBuilder().ToString(); Thread.CurrentThread.CurrentCulture = origCulture; return(xmlData); } }
public NMSTemplate GetData() { _io.Stream.Position = 0x60; return(NMSTemplate.DeserializeBinaryTemplate(_io.Reader, Header.GetXMLTemplateName())); }
private static string GetString(ulong readGUID, ulong expectedGUID, NMSTemplate template) { return($"Mismatch between GUID for struct {template.GetType().Name}.\n" + $"GUID read: {readGUID.ToString()}, expected GUID: {expectedGUID.ToString()}."); }