private static void Main(string[] args) { var mode = Mode.Unknown; string baseName = ""; bool showHelp = false; bool verbose = false; bool useMultiExporting = true; var options = new OptionSet() { { "i|import|fcb", "convert XML to FCB", v => mode = v != null ? Mode.Import : mode }, { "e|export|xml", "convert FCB to XML", v => mode = v != null ? Mode.Export : mode }, { "b|base-name=", "when converting, use specified base name instead of file name", v => baseName = v }, { "nme|no-multi-export", "when exporting, disable multi-exporting of entitylibrary and lib files", v => useMultiExporting = v == null }, { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (mode == Mode.Unknown && extras.Count >= 1) { var extension = Path.GetExtension(extras[0]); if (string.IsNullOrEmpty(extension) == false) { extension = extension.ToLowerInvariant(); } if (extension == ".fcb" || extension == ".obj" || extension == ".lib") { mode = Mode.Export; } else if (extension == ".xml") { mode = Mode.Import; } } if (showHelp == true || mode == Mode.Unknown || extras.Count < 1 || extras.Count > 2) { Console.WriteLine("Usage: {0} [OPTIONS]+ input [output]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } if (verbose == true) { Console.WriteLine("Loading project..."); } var manager = ProjectData.Manager.Load(); if (manager.ActiveProject == null) { Console.WriteLine("Warning: no active project loaded."); return; } var project = manager.ActiveProject; if (verbose == true) { Console.WriteLine("Loading binary class and object definitions..."); } BinaryObjectInfo.InfoManager infoManager; if (System.Diagnostics.Debugger.IsAttached == false) { try { infoManager = BinaryObjectInfo.InfoManager.Load(project.ListsPath); } catch (BinaryObjectInfo.LoadException e) { Console.WriteLine("Failed to load binary definitions!"); Console.WriteLine(" {0}", e.Message); return; } catch (BinaryObjectInfo.XmlLoadException e) { Console.WriteLine("Failed to load binary definitions!"); Console.WriteLine(" in \"{0}\"", e.FilePath); Console.WriteLine(" {0}", e.Message); return; } catch (Exception e) { Console.WriteLine("Exception while loading binary definitions!"); Console.WriteLine(); Console.WriteLine("{0}", e); return; } } else { infoManager = BinaryObjectInfo.InfoManager.Load(project.ListsPath); } if (mode == Mode.Import) { string inputPath = extras[0]; string outputPath; if (extras.Count > 1) { outputPath = extras[1]; } else { outputPath = Path.ChangeExtension(inputPath, null); outputPath += "_converted.fcb"; } var basePath = Path.ChangeExtension(inputPath, null); inputPath = Path.GetFullPath(inputPath); outputPath = Path.GetFullPath(outputPath); basePath = Path.GetFullPath(basePath); var bof = new BinaryObjectFile(); using (var input = File.OpenRead(inputPath)) { var doc = new XPathDocument(input); var nav = doc.CreateNavigator(); var root = nav.SelectSingleNode("/object"); if (root == null) { throw new FormatException(); } if (string.IsNullOrEmpty(baseName) == true) { var baseNameFromObject = root.GetAttribute("def", ""); if (string.IsNullOrEmpty(baseNameFromObject) == false) { baseName = baseNameFromObject; } else { baseName = GetBaseNameFromPath(inputPath); } } if (verbose == true) { Console.WriteLine("Reading XML..."); } var objectFileDef = infoManager.GetObjectFileDefinition(baseName); if (objectFileDef == null) { Console.WriteLine("Warning: could not find binary object file definition '{0}'", baseName); } var importing = new Importing(infoManager); var classDef = objectFileDef != null ? objectFileDef.Object : null; bof.Root = importing.Import(classDef, basePath, root); } if (verbose == true) { Console.WriteLine("Writing FCB..."); } using (var output = File.Create(outputPath)) { bof.Serialize(output); } } else if (mode == Mode.Export) { HashFinder.Load(manager.ActiveProject.ListsPath); string inputPath = extras[0]; string outputPath; string basePath; if (extras.Count > 1) { outputPath = extras[1]; basePath = Path.ChangeExtension(outputPath, null); } else { outputPath = Path.ChangeExtension(inputPath, null); outputPath += "_converted"; basePath = outputPath; outputPath += ".xml"; } if (string.IsNullOrEmpty(baseName) == true) { baseName = GetBaseNameFromPath(inputPath); } if (string.IsNullOrEmpty(baseName) == true) { throw new InvalidOperationException(); } inputPath = Path.GetFullPath(inputPath); outputPath = Path.GetFullPath(outputPath); basePath = Path.GetFullPath(basePath); var objectFileDef = infoManager.GetObjectFileDefinition(baseName); if (objectFileDef == null) { Console.WriteLine("Warning: could not find binary object file definition '{0}'", baseName); } if (verbose == true) { Console.WriteLine("Reading FCB..."); } var bof = new BinaryObjectFile(); using (var input = File.OpenRead(inputPath)) { bof.Deserialize(input); } if (verbose == true) { Console.WriteLine("Writing XML..."); } if (useMultiExporting == true && Exporting.IsSuitableForEntityLibraryMultiExport(bof) == true) { Exporting.MultiExportEntityLibrary(objectFileDef, basePath, outputPath, infoManager, bof); } else if (useMultiExporting == true && Exporting.IsSuitableForLibraryMultiExport(bof) == true) { Exporting.MultiExportLibrary(objectFileDef, basePath, outputPath, infoManager, bof); } else if (useMultiExporting == true && Exporting.IsSuitableForNomadObjectTemplatesMultiExport(bof) == true) { Exporting.MultiExportNomadObjectTemplates(objectFileDef, basePath, outputPath, infoManager, bof); } else { Exporting.Export(objectFileDef, outputPath, infoManager, bof); } } else { throw new InvalidOperationException(); } }
private static void WriteNode(InfoManager infoManager, XmlWriter writer, IEnumerable <BinaryObject> parentChain, BinaryObject node, ClassDefinition def, ObjectFileDefinition objectFileDef) { var chain = parentChain.Concat(new[] { node }); var originalDef = def; if (def != null && def.ClassFieldHash.HasValue == true) { if (node.Fields.ContainsKey(def.ClassFieldHash.Value) == true) { var hash = FieldTypeDeserializers.Deserialize <uint>(FieldType.UInt32, node.Fields[def.ClassFieldHash.Value]); def = infoManager.GetClassDefinition(hash); } } writer.WriteStartElement("object"); if (originalDef != null && originalDef.Name != null && originalDef.Hash == node.NameHash) { writer.WriteAttributeString("name", originalDef.Name); } else if (def != null && def.Name != null && def.Hash == node.NameHash) { writer.WriteAttributeString("name", def.Name); } else if (HashFinder.TryGetValue(node.NameHash, out var hashValue)) { writer.WriteAttributeString("name", hashValue); } else { writer.WriteAttributeString("hash", node.NameHash.ToString("X8")); } if (objectFileDef != null && string.IsNullOrEmpty(objectFileDef.Name) == false) { writer.WriteAttributeString("def", objectFileDef.Name); } if (node.Fields != null) { foreach (var kv in node.Fields) { writer.WriteStartElement("field"); var fieldDef = def != null?def.GetFieldDefinition(kv.Key, chain) : null; if (fieldDef != null && fieldDef.Name != null && fieldDef.Hash == kv.Key) { writer.WriteAttributeString("name", fieldDef.Name); } else if (HashFinder.TryGetValue(kv.Key, out var hashValue)) { writer.WriteAttributeString("name", hashValue); } else { writer.WriteAttributeString("hash", kv.Key.ToString("X8")); } if (fieldDef == null) { writer.WriteAttributeString("type", FieldType.BinHex.GetString()); writer.WriteBinHex(kv.Value, 0, kv.Value.Length); } else { writer.WriteAttributeString("type", fieldDef.Type.GetString()); if (fieldDef.ArrayType != FieldType.Invalid) { writer.WriteAttributeString("array_type", fieldDef.ArrayType.GetString()); } FieldTypeDeserializers.Deserialize(writer, fieldDef, kv.Value); } writer.WriteEndElement(); } } if (def == null || def.DynamicNestedClasses == false) { foreach (var childNode in node.Children) { var childDef = def != null?def.GetObjectDefinition(childNode.NameHash, chain) : null; WriteNode(infoManager, writer, chain, childNode, childDef, null); } } else if (def.DynamicNestedClasses == true) { foreach (var childNode in node.Children) { var childDef = infoManager.GetClassDefinition(childNode.NameHash); WriteNode(infoManager, writer, chain, childNode, childDef, null); } } writer.WriteEndElement(); }