Patcher.Data.Plugins.Plugin.Save C# (CSharp) Method

Save() public method

public Save ( IEnumerable removeMasters ) : void
removeMasters IEnumerable
return void
        public void Save(IEnumerable<string> removeMasters)
        {
            Log.Info("Saving plugin " + fileName);

            byte thisPluginNumber = context.Plugins.GetPluginNumber(this);

            // Collect all masters (Always add the main plugin as master)
            HashSet<byte> collectedMasters = new HashSet<byte>() { 0 };

            // Collect all referenced form IDs
            HashSet<uint> referencedFormIds = GetReferencedFormIds();

            foreach (var id in referencedFormIds)
            {
                if (!context.Forms.Contains(id))
                {
                    //Log.Warning("Unable to determine the master of unresolved reference [0x{0:X8}].", id);
                    // Skip unresolved references, a warning will be issued while writing

                    // Handle unresolved references as best as possible, derive plugin number from formId and add it as a master
                    byte assumedPluginNumber = (byte)(id >> 24);
                    if (assumedPluginNumber != thisPluginNumber)
                        if (!collectedMasters.Contains(assumedPluginNumber))
                            collectedMasters.Add(assumedPluginNumber);

                    Log.Warning("Assumed unresolved form {0:X8} plugin {1}.", id, context.Plugins[assumedPluginNumber].FileName);
                }
                else
                {
                    var form = context.Forms[id];

                    // Find the original form
                    // to add the original plugin which adds it as the master and not the last plugin which edits the referenced form
                    while (form.OverridesForm != null)
                        form = form.OverridesForm;

                    // Add if not of the current plugin
                    if (form.PluginNumber != thisPluginNumber)
                        if (!collectedMasters.Contains(form.PluginNumber))
                            collectedMasters.Add(form.PluginNumber);
                }
            }

            // Form IDs this plugin is overriding
            var overridenForms = Forms.Where(f => f.IsOverriding);
            foreach (var form in overridenForms)
            {
                // Go through all overriden forms until the original form
                var overridenForm = form.OverridesForm;
                while (overridenForm != null)
                {
                    if (!collectedMasters.Contains(overridenForm.PluginNumber))
                        collectedMasters.Add(overridenForm.PluginNumber);

                    // Next overriden form by this form
                    overridenForm = overridenForm.OverridesForm;
                }
            }

            // Add masters (will be sorted by pluginNumber)
            foreach (var number in collectedMasters.OrderBy(i => i))
            {
                var masterFileName = context.Plugins[number].FileName;

                // Force remove masters
                if (removeMasters != null && removeMasters.Contains(masterFileName))
                    continue;

                // Already added (when appending)
                if (header.GetMasterFiles().Contains(masterFileName))
                    continue;

                header.AddMasterFile(masterFileName);
                Log.Fine("Added master: {0}", masterFileName);
            }

            //// Make a backup of existing file
            //string backupPath = null;
            //if (File.Exists(path))
            //{
            //    backupPath = path + "-" + (ulong)DateTime.Now.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
            //    File.Move(path, backupPath);
            //}

            if (!Forms.Any())
            {
                Log.Warning("No forms to write. Empty plugin will be generated.");
            }

            int count = 0;
            long total = Forms.Count();

            using (var progress = Display.StartProgress("Saving plugin"))
            {
                // Save plugin to memory stream
                using (var stream = new MemoryStream())
                {
                    using (var writer = context.CreateWriter(stream))
                    {
                        // Prepare reference mapper
                        writer.ReferenceMapper = new PluginReferenceMapper(this);

                        // Write header
                        header.PluginVersion = context.GetLatestPluginVersion();
                        writer.WriteHeader(header);
                        Log.Fine("Written header record");

                        // Write forms by type
                        foreach (var type in context.Forms.GetFormKinds())
                        {
                            var formOfType = Forms.Where(f => f.FormKind == type);
                            if (formOfType.Any())
                                Log.Fine("Writting {0}", type);

                            foreach (var form in formOfType)
                            {
                                writer.WriteRecord(form.Record, form.FormId);
                                count++;

                                progress.Update(count, total, "{0}:{1}", FileName, type);
                            }
                        }

                        Log.Fine("Written {0} form(s)", count);

                        writer.Close();

                        // Write memory stream to file
                        // only if changed
                        stream.Position = 0;
                        var file = context.DataFileProvider.GetDataFile(FileMode.Create, fileName);
                        if (!file.CopyFrom(stream, true))
                        {
                            Log.Info("New plugin content is the same as that of the existing plugin.");
                        }
                    }
                }
            }

            Log.Info("Plugin saved");
        }