コード例 #1
0
        private static void Main(string[] args)
        {
            var  mode             = Mode.Unknown;
            bool showHelp         = false;
            var  typeLibraryPaths = new List <string>();

            var options = new OptionSet
            {
                // ReSharper disable AccessToModifiedClosure
                { "e|export", "convert from binary to XML", v => SetOption(v, ref mode, Mode.Export) },
                { "i|import", "convert from XML to binary", v => SetOption(v, ref mode, Mode.Import) },
                // ReSharper restore AccessToModifiedClosure
                { "t|type-library=", "load type library from file", v => typeLibraryPaths.Add(v) },
                { "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 (extension != null && extension.ToLowerInvariant() == ".xml")
                {
                    mode = Mode.Import;
                }
                else
                {
                    mode = Mode.Export;
                }
            }

            if (extras.Count < 1 || extras.Count > 2 ||
                showHelp == true ||
                mode == Mode.Unknown)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ [-e] input_adf [output_xml]", GetExecutableName());
                Console.WriteLine("       {0} [OPTIONS]+ [-i] input_xml [output_adf]", GetExecutableName());
                Console.WriteLine("Convert an ADF file between binary and XML format.");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            var runtime = new RuntimeTypeLibrary();

            foreach (var typeLibraryPath in typeLibraryPaths)
            {
                var adf = new FileFormats.AdfFile("");

                using (var input = File.OpenRead(typeLibraryPath))
                {
                    adf.Deserialize(input);
                }

                runtime.AddTypeDefinitions(adf);
            }

            if (mode == Mode.Export)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".xml");

                using (var input = File.OpenRead(inputPath))
                {
                    var adf = new AdfFile(Path.GetExtension(inputPath));
                    adf.Deserialize(input);
                    runtime.AddTypeDefinitions(adf);


                    var settings = new XmlWriterSettings
                    {
                        Indent          = true,
                        IndentChars     = "    ",
                        CheckCharacters = false,
                    };

                    using (var output = File.Create(outputPath))
                    {
                        var writer = XmlWriter.Create(output, settings);
                        Exporter.Export(adf, writer /*, runtime, input, writer*/);
                        writer.Flush();
                    }
                }
            }
            else if (mode == Mode.Import)
            {
                string inputPath = extras[0];

                using (var input = File.OpenRead(inputPath))
                {
                    var doc = new XPathDocument(input);
                    var nav = doc.CreateNavigator();

                    var root = nav.SelectSingleNode("/adf");
                    if (root == null)
                    {
                        throw new FormatException();
                    }

                    // retrieve the original extension as stored in the XML file
                    var    outputExtension = root.GetAttribute("extension", "");
                    string outputPath      = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, outputExtension);


                    AdfFile adf = Importer.Import(root);

                    using (var output = File.Create(outputPath))
                    {
                        output.Position = adf.EstimateHeaderSize();
                        adf.Serialize(output, 0);
                    }
                }
            }
        }
コード例 #2
0
        private static void Main(string[] args)
        {
            var  mode     = Mode.Unknown;
            bool showHelp = false;

            var options = new OptionSet
            {
                // ReSharper disable AccessToModifiedClosure
                { "e|export", "convert from binary to JSON", v => SetOption(v, ref mode, Mode.Export) },
                { "i|import", "convert from JSON to binary", v => SetOption(v, ref mode, Mode.Import) },
                // ReSharper restore AccessToModifiedClosure
                { "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 (extension != null && extension.ToLowerInvariant() == ".json")
                {
                    mode = Mode.Import;
                }
                else
                {
                    mode = Mode.Export;
                }
            }

            if (extras.Count < 1 || extras.Count > 2 ||
                showHelp == true ||
                mode == Mode.Unknown)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ [-e] input_upgrade_onlinec [output_json]", GetExecutableName());
                Console.WriteLine("       {0} [OPTIONS]+ [-i] input_json [output_upgrade_onlinec]", GetExecutableName());
                Console.WriteLine("Convert an upgrade file between binary and JSON format.");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (mode == Mode.Export)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".json");

                var adf      = new FileFormats.AdfFile();
                var itemRoot = new UpgradeRoot();

                using (var input = File.OpenRead(inputPath))
                {
                    adf.Deserialize(input);

                    var itemRootInfo = adf.InstanceInfos.FirstOrDefault(i => i.Name == "Profile");
                    if (itemRootInfo.TypeHash != UpgradeRoot.TypeHash)
                    {
                        throw new FormatException();
                    }

                    input.Position = itemRootInfo.Offset;
                    itemRoot.Deserialize(input, adf.Endian);
                }

                using (var output = File.Create(outputPath))
                    using (var textWriter = new StreamWriter(output))
                        using (var writer = new JsonTextWriter(textWriter))
                        {
                            writer.Indentation = 2;
                            writer.IndentChar  = ' ';
                            writer.Formatting  = Formatting.Indented;

                            var jsonItems = itemRoot.Upgrades.Select(
                                u =>
                            {
                                var jsonItem = new UpgradeRootJson.Upgrade()
                                {
                                    Name           = ResolveHash(adf, u.Name),
                                    TaskGroup      = ResolveHash(adf, u.TaskGroup),
                                    StarThreshold  = u.StarThreshold,
                                    Cost           = u.Cost,
                                    Ability        = ResolveHash(adf, u.Ability),
                                    UIName         = ResolveHash(adf, u.UIName),
                                    UIDescription  = ResolveHash(adf, u.UIDescription),
                                    UIDisplayOrder = u.UIDisplayOrder,
                                    UIImage        = u.UIImage,
                                    UIVideo        = u.UIVideo,
                                    UITreeName     = ResolveHash(adf, u.UITreeName),
                                    UITreeOrder    = u.UITreeOrder,
                                };
                                jsonItem.Prerequisites.AddRange(u.Prerequisites.Select(f => ResolveHash(adf, f)));
                                return(jsonItem);
                            }).ToArray();

                            var serializer = JsonSerializer.Create();
                            serializer.Serialize(writer, jsonItems);
                        }
            }
            else if (mode == Mode.Import)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".onlinec");

                var adf = new AdfFile()
                {
                    Endian = Endian.Little,
                };
                var itemRoot = new UpgradeRoot();

                using (var input = File.OpenRead(inputPath))
                    using (var textReader = new StreamReader(input))
                        using (var reader = new JsonTextReader(textReader))
                        {
                            var serializer = JsonSerializer.Create();
                            var jsonItems  = serializer.Deserialize <UpgradeRootJson.Upgrade[]>(reader);

                            itemRoot.Upgrades.AddRange(jsonItems.Select(
                                                           ju => new UpgradeRoot.Upgrade()
                            {
                                Name           = ComputeHash(adf, ju.Name),
                                TaskGroup      = ComputeHash(adf, ju.TaskGroup),
                                StarThreshold  = ju.StarThreshold,
                                Prerequisites  = ju.Prerequisites.Select(f => ComputeHash(adf, f)).ToArray(),
                                Cost           = ju.Cost,
                                Ability        = ComputeHash(adf, ju.Ability),
                                UIName         = ComputeHash(adf, ju.UIName),
                                UIDescription  = ComputeHash(adf, ju.UIDescription),
                                UIDisplayOrder = ju.UIDisplayOrder,
                                UIImage        = ju.UIImage,
                                UIVideo        = ju.UIVideo,
                                UITreeName     = ComputeHash(adf, ju.UITreeName),
                                UITreeOrder    = ju.UITreeOrder,
                            }));
                        }

                using (var output = File.Create(outputPath))
                {
                    using (var data = new MemoryStream())
                    {
                        itemRoot.Serialize(data, adf.Endian);
                        data.Flush();
                        data.Position = 0;

                        output.Position = adf.EstimateHeaderSize();
                        var itemRootPosition = output.Position;
                        output.WriteFromStream(data, data.Length);

                        adf.InstanceInfos.Add(new AdfFile.InstanceInfo()
                        {
                            Name     = "Profile",
                            NameHash = "Profile".HashJenkins(),
                            Offset   = (uint)itemRootPosition,
                            Size     = (uint)data.Length,
                            TypeHash = UpgradeRoot.TypeHash,
                        });

                        adf.Serialize(output, 0);
                    }
                }
            }
            else
            {
                throw new NotSupportedException();
            }
        }
コード例 #3
0
        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage:");
                Console.WriteLine("  {0}  file.stringlookup", GetExecutableName());
                Console.WriteLine("  {0}  file.xml", GetExecutableName());
                return;
            }

            string inputPath = args[0];

            if (Path.GetExtension(inputPath).ToLowerInvariant() == ".xml") // IMPORT
            {
                using (var input = File.OpenRead(inputPath))
                {
                    var doc = new XPathDocument(input);
                    var nav = doc.CreateNavigator();

                    var root = nav.SelectSingleNode("/string-lookup");
                    if (root == null)
                    {
                        throw new FormatException();
                    }

                    // retrieve the original extension as stored in the XML file
                    var    outputExtension = root.GetAttribute("extension", "");
                    string outputPath      = Path.ChangeExtension(inputPath, outputExtension);


                    AdfFile adf = Importer.Import(root);

                    using (var output = File.Create(outputPath))
                    {
                        output.Position = adf.EstimateHeaderSize();
                        adf.Serialize(output, 0);
                    }
                }
            }
            else // EXPORT (to XML)
            {
                string outputPath = Path.ChangeExtension(inputPath, ".xml");
                using (var input = File.OpenRead(inputPath))
                {
                    var adf = new AdfFile(Path.GetExtension(inputPath));
                    adf.Deserialize(input);
                    var settings = new XmlWriterSettings
                    {
                        Indent          = true,
                        IndentChars     = "    ",
                        CheckCharacters = false,
                    };

                    using (var output = File.Create(outputPath))
                    {
                        var writer = XmlWriter.Create(output, settings);
                        Exporter.Export(adf, writer);
                        writer.Flush();
                    }
                }
            }
        }
コード例 #4
0
        private static void Main(string[] args)
        {
            var  mode     = Mode.Unknown;
            bool showHelp = false;

            var options = new OptionSet
            {
                // ReSharper disable AccessToModifiedClosure
                { "e|export", "convert from binary to JSON", v => SetOption(v, ref mode, Mode.Export) },
                { "i|import", "convert from JSON to binary", v => SetOption(v, ref mode, Mode.Import) },
                // ReSharper restore AccessToModifiedClosure
                { "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 (extension != null && extension.ToLowerInvariant() == ".json")
                {
                    mode = Mode.Import;
                }
                else
                {
                    mode = Mode.Export;
                }
            }

            if (extras.Count < 1 || extras.Count > 2 ||
                showHelp == true ||
                mode == Mode.Unknown)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ [-e] input_item_onlinec [output_json]", GetExecutableName());
                Console.WriteLine("       {0} [OPTIONS]+ [-i] input_json [output_item_onlinec]", GetExecutableName());
                Console.WriteLine("Convert an item file between binary and JSON format.");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (mode == Mode.Export)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".json");

                var adf      = new AdfFile();
                var itemRoot = new ItemRoot();

                using (var input = File.OpenRead(inputPath))
                {
                    adf.Deserialize(input);

                    var itemRootInfo = adf.InstanceInfos.FirstOrDefault(i => i.Name == "Profile");
                    if (itemRootInfo.TypeHash != ItemRoot.TypeHash)
                    {
                        throw new FormatException();
                    }

                    input.Position = itemRootInfo.Offset;
                    itemRoot.Deserialize(input, adf.Endian);
                }

                using (var output = File.Create(outputPath))
                    using (var textWriter = new StreamWriter(output))
                        using (var writer = new JsonTextWriter(textWriter))
                        {
                            writer.Indentation = 2;
                            writer.IndentChar  = ' ';
                            writer.Formatting  = Formatting.Indented;

                            var jsonItems = itemRoot.Items.Select(
                                i =>
                            {
                                var jsonItem = new ItemRootJson.Item()
                                {
                                    Name              = ResolveHash(adf, i.Name),
                                    BaseName          = ResolveHash(adf, i.BaseName),
                                    Type              = i.Type,
                                    Purchasable       = i.Purchasable,
                                    Consumable        = i.Consumable,
                                    Rewardable        = i.Rewardable,
                                    Collectable       = i.Collectable,
                                    Region            = ResolveHash(adf, i.Region),
                                    RebelDropTimer    = i.RebelDropTimer,
                                    MaxInventory      = i.MaxInventory,
                                    UIType            = (UIItemType)i.UIType,
                                    UIFlag            = (UIItemSubtype)i.UIFlag,
                                    UIDisplayOrder    = i.UIDisplayOrder,
                                    UIName            = ResolveHash(adf, i.UIName),
                                    UIDescription     = ResolveHash(adf, i.UIDescription),
                                    UITypeDescription = ResolveHash(adf, i.UITypeDescription),
                                    UIFlagDescription = ResolveHash(adf, i.UIFlagDescription),
                                    UIImagePath       = i.UIImagePath,
                                    UIVideoPath       = i.UIVideoPath,
                                    UIPar0            = i.UIPar0,
                                    UIPar1            = i.UIPar1,
                                    UIPar2            = i.UIPar2,
                                    UIPar3            = i.UIPar3,
                                    UIPar4            = i.UIPar4,
                                };
                                jsonItem.Feats.AddRange(i.Feats.Select(f => ResolveHash(adf, f)));
                                return(jsonItem);
                            }).ToArray();

                            var serializer = JsonSerializer.Create();
                            serializer.Serialize(writer, jsonItems);
                        }
            }
            else if (mode == Mode.Import)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".onlinec");

                var adf = new AdfFile()
                {
                    Endian = Endian.Little,
                };
                var itemRoot = new ItemRoot();

                using (var input = File.OpenRead(inputPath))
                    using (var textReader = new StreamReader(input))
                        using (var reader = new JsonTextReader(textReader))
                        {
                            var serializer = JsonSerializer.Create();
                            var jsonItems  = serializer.Deserialize <ItemRootJson.Item[]>(reader);

                            itemRoot.Items.AddRange(jsonItems.Select(
                                                        ji => new ItemRoot.Item()
                            {
                                Name              = ComputeHash(adf, ji.Name),
                                BaseName          = ComputeHash(adf, ji.BaseName),
                                Type              = ji.Type,
                                Purchasable       = ji.Purchasable,
                                Consumable        = ji.Consumable,
                                Rewardable        = ji.Rewardable,
                                Collectable       = ji.Collectable,
                                Feats             = ji.Feats.Select(f => ComputeHash(adf, f)).ToArray(),
                                Region            = ComputeHash(adf, ji.Region),
                                RebelDropTimer    = ji.RebelDropTimer,
                                MaxInventory      = ji.MaxInventory,
                                UIType            = (int)ji.UIType,
                                UIFlag            = (int)ji.UIFlag,
                                UIDisplayOrder    = ji.UIDisplayOrder,
                                UIName            = ComputeHash(adf, ji.UIName),
                                UIDescription     = ComputeHash(adf, ji.UIDescription),
                                UITypeDescription = ComputeHash(adf, ji.UITypeDescription),
                                UIFlagDescription = ComputeHash(adf, ji.UIFlagDescription),
                                UIImagePath       = ji.UIImagePath,
                                UIVideoPath       = ji.UIVideoPath,
                                UIPar0            = ji.UIPar0,
                                UIPar1            = ji.UIPar1,
                                UIPar2            = ji.UIPar2,
                                UIPar3            = ji.UIPar3,
                                UIPar4            = ji.UIPar4,
                            }));
                        }

                using (var output = File.Create(outputPath))
                {
                    using (var data = new MemoryStream())
                    {
                        itemRoot.Serialize(data, adf.Endian);
                        data.Flush();
                        data.Position = 0;

                        output.Position = adf.EstimateHeaderSize();
                        var itemRootPosition = output.Position;
                        output.WriteFromStream(data, data.Length);

                        adf.InstanceInfos.Add(new AdfFile.InstanceInfo()
                        {
                            Name     = "Profile",
                            NameHash = "Profile".HashJenkins(),
                            Offset   = (uint)itemRootPosition,
                            Size     = (uint)data.Length,
                            TypeHash = ItemRoot.TypeHash,
                        });

                        adf.Serialize(output, 0);
                    }
                }
            }
            else
            {
                throw new NotSupportedException();
            }
        }
コード例 #5
0
        private static void Main(string[] args)
        {
            var  mode     = Mode.Unknown;
            bool showHelp = false;

            var options = new OptionSet
            {
                // ReSharper disable AccessToModifiedClosure
                { "e|export", "convert from binary to JSON", v => SetOption(v, ref mode, Mode.Export) },
                { "i|import", "convert from JSON to binary", v => SetOption(v, ref mode, Mode.Import) },
                // ReSharper restore AccessToModifiedClosure
                { "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 (extension != null && extension.ToLowerInvariant() == ".json")
                {
                    mode = Mode.Import;
                }
                else
                {
                    mode = Mode.Export;
                }
            }

            if (extras.Count < 1 || extras.Count > 2 ||
                showHelp == true ||
                mode == Mode.Unknown)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ [-e] task.onlinec [output_json]", GetExecutableName());
                Console.WriteLine("       {0} [OPTIONS]+ [-i] input_json [task.onlinec]", GetExecutableName());
                Console.WriteLine("Convert an task file between binary and JSON format.");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (mode == Mode.Export)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".json");

                var adf      = new AdfFile();
                var taskRoot = new TaskRoot();

                using (var input = File.OpenRead(inputPath))
                {
                    adf.Deserialize(input);

                    var taskRootInfo = adf.InstanceInfos.FirstOrDefault(i => i.Name == "Profile");
                    if (taskRootInfo.TypeHash != TaskRoot.TypeHash)
                    {
                        throw new FormatException();
                    }

                    input.Position = taskRootInfo.Offset;
                    taskRoot.Deserialize(input, adf.Endian);
                }

                using (var output = File.Create(outputPath))
                    using (var textWriter = new StreamWriter(output))
                        using (var writer = new JsonTextWriter(textWriter))
                        {
                            writer.Indentation = 2;
                            writer.IndentChar  = ' ';
                            writer.Formatting  = Formatting.Indented;

                            var jsonTasks = taskRoot.Tasks.Select(
                                t =>
                            {
                                var jsonTask = new TaskRootJson.Task()
                                {
                                    Name                      = ResolveHash(adf, t.Name),
                                    TaskGroup                 = ResolveHash(adf, t.TaskGroup),
                                    Type                      = t.Type,
                                    ProvinceWeight            = t.ProvinceWeight,
                                    LiberationPercent         = t.LiberationPercent,
                                    RepeatableRewardSemantics = t.RepeatableRewardSemantics,
                                    RepeatableReward          = new TaskRootJson.Reward()
                                    {
                                        Skillpoints         = t.RepeatableReward.Skillpoints,
                                        Chaos               = t.RepeatableReward.Chaos,
                                        ItemRewardSemantics = t.RepeatableReward.ItemRewardSemantics,
                                    },
                                    HasChurch     = t.HasChurch,
                                    ShownOnMap    = t.ShownOnMap,
                                    UIName        = ResolveHash(adf, t.UIName),
                                    UIDescription = ResolveHash(adf, t.UIDescription),
                                    UITip         = ResolveHash(adf, t.UITip),
                                    UIOrderHint   = t.UIOrderHint,
                                };
                                if (t.RepeatableReward.Items != null)
                                {
                                    jsonTask.RepeatableReward.Items.AddRange(
                                        t.RepeatableReward.Items.Select(i => new TaskRootJson.ItemReward()
                                    {
                                        Item      = ResolveHash(adf, i.Item),
                                        Permanent = i.Permanent,
                                        Duration  = i.Duration,
                                        Quantity  = i.Quantity,
                                        Delivery  = i.Delivery,
                                    }));
                                }
                                if (t.RewardThresholds != null)
                                {
                                    jsonTask.RewardThresholds.AddRange(
                                        t.RewardThresholds.Select(
                                            rt =>
                                    {
                                        var jsonRewardThreshold = new TaskRootJson.RewardThreshold()
                                        {
                                            Threshold = rt.Threshold,
                                            Reward    = new TaskRootJson.Reward()
                                            {
                                                Skillpoints         = rt.Reward.Skillpoints,
                                                Chaos               = rt.Reward.Chaos,
                                                ItemRewardSemantics = rt.Reward.ItemRewardSemantics,
                                            },
                                        };
                                        if (rt.Reward.Items != null)
                                        {
                                            jsonRewardThreshold.Reward.Items.AddRange(
                                                rt.Reward.Items.Select(i => new TaskRootJson.ItemReward()
                                            {
                                                Item      = ResolveHash(adf, i.Item),
                                                Permanent = i.Permanent,
                                                Duration  = i.Duration,
                                                Quantity  = i.Quantity,
                                                Delivery  = i.Delivery,
                                            }));
                                        }
                                        return(jsonRewardThreshold);
                                    }));
                                }
                                if (t.Prerequisites != null)
                                {
                                    jsonTask.Prerequisites.AddRange(
                                        t.Prerequisites.Select(p => new TaskRootJson.Prerequisite()
                                    {
                                        Name        = ResolveHash(adf, p.Name),
                                        RewardIndex = p.RewardIndex,
                                        Tag         = ResolveHash(adf, p.Tag),
                                    }));
                                }
                                return(jsonTask);
                            }).ToArray();

                            var serializer = JsonSerializer.Create();
                            serializer.Serialize(writer, jsonTasks);
                        }
            }
            else if (mode == Mode.Import)
            {
                string inputPath  = extras[0];
                string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".onlinec");

                var adf = new AdfFile()
                {
                    Endian = Endian.Little,
                };
                var taskRoot = new TaskRoot();

                using (var input = File.OpenRead(inputPath))
                    using (var textReader = new StreamReader(input))
                        using (var reader = new JsonTextReader(textReader))
                        {
                            var serializer = JsonSerializer.Create();
                            var jsonTasks  = serializer.Deserialize <TaskRootJson.Task[]>(reader);

                            taskRoot.Tasks.AddRange(jsonTasks.Select(
                                                        jt =>
                            {
                                var task = new TaskRoot.Task()
                                {
                                    Name                      = ComputeHash(adf, jt.Name),
                                    TaskGroup                 = ComputeHash(adf, jt.TaskGroup),
                                    Type                      = jt.Type,
                                    ProvinceWeight            = jt.ProvinceWeight,
                                    LiberationPercent         = jt.LiberationPercent,
                                    RepeatableRewardSemantics = jt.RepeatableRewardSemantics,
                                    RepeatableReward          = new TaskRoot.Reward()
                                    {
                                        Skillpoints         = jt.RepeatableReward.Skillpoints,
                                        Chaos               = jt.RepeatableReward.Chaos,
                                        ItemRewardSemantics = jt.RepeatableReward.ItemRewardSemantics,
                                    },
                                    HasChurch     = jt.HasChurch,
                                    ShownOnMap    = jt.ShownOnMap,
                                    UIName        = ComputeHash(adf, jt.UIName),
                                    UIDescription = ComputeHash(adf, jt.UIDescription),
                                    UITip         = ComputeHash(adf, jt.UITip),
                                    UIOrderHint   = jt.UIOrderHint,
                                };
                                task.RepeatableReward.Items =
                                    jt.RepeatableReward.Items.Select(ji => new TaskRoot.ItemReward()
                                {
                                    Item      = ComputeHash(adf, ji.Item),
                                    Permanent = ji.Permanent,
                                    Duration  = ji.Duration,
                                    Quantity  = ji.Quantity,
                                    Delivery  = ji.Delivery,
                                }).ToArray();
                                task.RewardThresholds =
                                    jt.RewardThresholds.Select(
                                        jrt =>
                                {
                                    var rewardThreshold = new TaskRoot.RewardThreshold()
                                    {
                                        Threshold = jrt.Threshold,
                                        Reward    = new TaskRoot.Reward()
                                        {
                                            Skillpoints         = jrt.Reward.Skillpoints,
                                            Chaos               = jrt.Reward.Chaos,
                                            ItemRewardSemantics = jrt.Reward.ItemRewardSemantics,
                                        },
                                    };
                                    rewardThreshold.Reward.Items =
                                        jrt.Reward.Items.Select(ji => new TaskRoot.ItemReward()
                                    {
                                        Item      = ComputeHash(adf, ji.Item),
                                        Permanent = ji.Permanent,
                                        Duration  = ji.Duration,
                                        Quantity  = ji.Quantity,
                                        Delivery  = ji.Delivery,
                                    }).ToArray();
                                    return(rewardThreshold);
                                }).ToArray();
                                task.Prerequisites =
                                    jt.Prerequisites.Select(jp => new TaskRoot.Prerequisite()
                                {
                                    Name        = ComputeHash(adf, jp.Name),
                                    RewardIndex = jp.RewardIndex,
                                    Tag         = ComputeHash(adf, jp.Tag),
                                }).ToArray();
                                return(task);
                            }));
                        }

                using (var output = File.Create(outputPath))
                {
                    using (var data = new MemoryStream())
                    {
                        taskRoot.Serialize(data, adf.Endian);
                        data.Flush();
                        data.Position = 0;

                        output.Position = adf.EstimateHeaderSize();
                        var itemRootPosition = output.Position;
                        output.WriteFromStream(data, data.Length);

                        adf.InstanceInfos.Add(new AdfFile.InstanceInfo()
                        {
                            Name     = "Profile",
                            NameHash = "Profile".HashJenkins(),
                            Offset   = (uint)itemRootPosition,
                            Size     = (uint)data.Length,
                            TypeHash = TaskRoot.TypeHash,
                        });

                        adf.Serialize(output, 0);
                    }
                }
            }
            else
            {
                throw new NotSupportedException();
            }
        }