Пример #1
0
        ImportInternal(string iniFile, bool returnUnmergedFMsList = false, FieldsToImport?fields = null)
        {
            string[] lines = await Task.Run(() => File.ReadAllLines(iniFile));

            var fms = new List <FanMission>();

            ImportError error = await Task.Run(() =>
            {
                bool archiveDirRead = false;
                string archiveDir   = "";

                for (int i = 0; i < lines.Length; i++)
                {
                    string line = lines[i];

                    #region Read archive directory

                    if (!archiveDirRead && line == "[Config]")
                    {
                        while (i < lines.Length - 1)
                        {
                            string lc = lines[i + 1];
                            if (lc.StartsWithFast_NoNullChecks("ArchiveRoot="))
                            {
                                archiveDir = lc.Substring(12).Trim();
                                break;
                            }
                            else if (!lc.IsEmpty() && lc[0] == '[' && lc[lc.Length - 1] == ']')
                            {
                                break;
                            }
                            i++;
                        }

                        if (archiveDir.IsEmpty())
                        {
                            return(ImportError.NoArchiveDirsFound);
                        }

                        i = -1;
                        archiveDirRead = true;
                        continue;
                    }

                    #endregion

                    #region Read FM entries

                    // MUST CHECK archiveDirRead OR IT ADDS EVERY FM TWICE!
                    if (archiveDirRead &&
                        line.Length >= 5 && line[0] == '[' && line[1] == 'F' && line[2] == 'M' && line[3] == '=')
                    {
                        // NOTE: There can be a problem like:
                        // installed name is CoolMission[1]
                        // it gets written like [FM=CoolMission[1]]
                        // it gets read and all [ and ] chars are removed
                        // it gets written back out like [FM=CoolMission1]
                        // Rare I guess, so just ignore?
                        string instName = line.Substring(4, line.Length - 5);

                        var fm = new FanMission {
                            InstalledDir = instName
                        };

                        // Unfortunately NDL doesn't store its archive names, so we have to do a file search
                        // similar to DarkLoader
                        try
                        {
                            // NDL always searches subdirectories as well
                            foreach (string f in Directory.EnumerateFiles(archiveDir, "*", SearchOption.AllDirectories))
                            {
                                // @DIRSEP: '/' conversion due to string.ContainsI()
                                if (!f.ToForwardSlashes().ContainsI("/.fix/"))
                                {
                                    string fn = Path.GetFileNameWithoutExtension(f);
                                    if (fn.ToInstDirNameNDL().EqualsI(instName) || fn.EqualsI(instName))
                                    {
                                        fm.Archive = Path.GetFileName(f);
                                        break;
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Log("Exception in NewDarkLoader archive dir file enumeration", ex);
                        }

                        while (i < lines.Length - 1)
                        {
                            string lineFM = lines[i + 1];
                            if (lineFM.StartsWithFast_NoNullChecks("NiceName="))
                            {
                                fm.Title = lineFM.Substring(9);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("ReleaseDate="))
                            {
                                fm.ReleaseDate.UnixDateString = lineFM.Substring(12);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("LastCompleted="))
                            {
                                fm.LastPlayed.UnixDateString = lineFM.Substring(14);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Finished="))
                            {
                                uint.TryParse(lineFM.Substring(9), out uint result);
                                // result will be 0 on fail, which is the empty value so it's fine
                                fm.FinishedOn = result;
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Rating="))
                            {
                                fm.Rating = int.TryParse(lineFM.Substring(7), out int result) ? result : -1;
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Comment="))
                            {
                                fm.Comment = lineFM.Substring(8);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("ModExclude="))
                            {
                                string val = lineFM.Substring(11);
                                if (val == "*")
                                {
                                    fm.DisableAllMods = true;
                                }
                                else
                                {
                                    fm.DisabledMods = val;
                                }
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Tags="))
                            {
                                string val = lineFM.Substring(5);
                                if (!val.IsEmpty() && val != "[none]")
                                {
                                    fm.TagsString = val;
                                }
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("InfoFile="))
                            {
                                fm.SelectedReadme = lineFM.Substring(9);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("FMSize="))
                            {
                                ulong.TryParse(lineFM.Substring(7), out ulong result);
                                fm.SizeBytes = result;
                            }
                            else if (!lineFM.IsEmpty() && lineFM[0] == '[' && lineFM[lineFM.Length - 1] == ']')
                            {
                                break;
                            }
                            i++;
                        }

                        fms.Add(fm);
                    }

                    #endregion
                }

                return(ImportError.None);
            });

            if (error != ImportError.None)
            {
                return(error, fms);
            }

            var importedFMs = returnUnmergedFMsList
                ? fms
                : ImportCommon.MergeImportedFMData(ImportType.NewDarkLoader, fms, fields);

            return(ImportError.None, importedFMs);
        }
Пример #2
0
        ImportInternal(string iniFile, bool importFMData, bool importSaves, bool returnUnmergedFMsList = false,
                       FieldsToImport?fields = null)
        {
            string[] lines = await Task.Run(() => File.ReadAllLines(iniFile));

            var fms = new List <FanMission>();

            var error = ImportError.None;

            if (importFMData)
            {
                bool missionDirsRead = false;
                var  archiveDirs     = new List <string>();

                error = await Task.Run(() =>
                {
                    try
                    {
                        for (int i = 0; i < lines.Length; i++)
                        {
                            string line   = lines[i];
                            string lineTS = line.TrimStart();
                            string lineTB = lineTS.TrimEnd();

                            #region Read archive directories

                            // We need to know the archive dirs before doing anything, because we may need to recreate
                            // some lossy names (if any bad chars have been removed by DarkLoader).
                            if (!missionDirsRead && lineTB == "[mission directories]")
                            {
                                while (i < lines.Length - 1)
                                {
                                    string lt = lines[i + 1].Trim();
                                    if (!lt.IsEmpty() && lt[0] != '[' && lt.EndsWith("=1"))
                                    {
                                        archiveDirs.Add(lt.Substring(0, lt.Length - 2));
                                    }
                                    else if (!lt.IsEmpty() && lt[0] == '[' && lt[lt.Length - 1] == ']')
                                    {
                                        break;
                                    }
                                    i++;
                                }

                                if (archiveDirs.Count == 0 || archiveDirs.All(x => x.IsWhiteSpace()))
                                {
                                    return(ImportError.NoArchiveDirsFound);
                                }

                                // Restart from the beginning of the file, this time skipping anything that isn't an
                                // FM entry
                                i = -1;
                                missionDirsRead = true;
                                continue;
                            }

                            #endregion

                            #region Read FM entries

                            // MUST CHECK missionDirsRead OR IT ADDS EVERY FM TWICE!
                            if (missionDirsRead &&
                                !NonFMHeaders.Contains(lineTB) && lineTB.Length > 0 && lineTB[0] == '[' &&
                                lineTB[lineTB.Length - 1] == ']' && lineTB.Contains('.') &&
                                DarkLoaderFMRegex.Match(lineTB).Success)
                            {
                                int lastIndexDot = lineTB.LastIndexOf('.');
                                string archive   = lineTB.Substring(1, lastIndexDot - 1);
                                string size      = lineTB.Substring(lastIndexDot + 1, lineTB.Length - lastIndexDot - 2);

                                foreach (string dir in archiveDirs)
                                {
                                    if (!Directory.Exists(dir))
                                    {
                                        continue;
                                    }
                                    try
                                    {
                                        // DarkLoader only does zip format
                                        foreach (string f in FastIO.GetFilesTopOnly(dir, "*.zip"))
                                        {
                                            string fn = Path.GetFileNameWithoutExtension(f);
                                            if (RemoveDLArchiveBadChars(fn).EqualsI(archive))
                                            {
                                                archive = fn;
                                                goto breakout;
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Log("Exception in DarkLoader archive dir file enumeration", ex);
                                    }
                                }

breakout:

                                // Add .zip back on; required because everything expects it, and furthermore if there's
                                // a dot anywhere in the name then everything after it will be treated as the extension
                                // and is liable to be lopped off at any time
                                archive += ".zip";

                                ulong.TryParse(size, out ulong sizeBytes);
                                var fm = new FanMission
                                {
                                    Archive      = archive,
                                    InstalledDir = archive.ToInstDirNameFMSel(),
                                    SizeBytes    = sizeBytes
                                };

                                // We don't import game type, because DarkLoader by default gets it wrong for NewDark
                                // FMs (the user could have changed it manually in the ini file, and in fact it's
                                // somewhat likely they would have done so, but still, better to just scan for it
                                // ourselves later)

                                while (i < lines.Length - 1)
                                {
                                    string lts = lines[i + 1].TrimStart();
                                    string ltb = lts.TrimEnd();

                                    if (lts.StartsWith("comment=\""))
                                    {
                                        string comment = ltb.Substring(9);
                                        if (comment.Length >= 2 && comment[comment.Length - 1] == '\"')
                                        {
                                            comment    = comment.Substring(0, comment.Length - 1);
                                            fm.Comment = DLUnescapeChars(comment);
                                        }
                                    }
                                    else if (lts.StartsWith("title=\""))
                                    {
                                        string title = ltb.Substring(7);
                                        if (title.Length >= 2 && title[title.Length - 1] == '\"')
                                        {
                                            title    = title.Substring(0, title.Length - 1);
                                            fm.Title = DLUnescapeChars(title);
                                        }
                                    }
                                    else if (lts.StartsWith("misdate="))
                                    {
                                        ulong.TryParse(ltb.Substring(8), out ulong result);
                                        try
                                        {
                                            var date = new DateTime(1899, 12, 30).AddDays(result);
                                            fm.ReleaseDate.DateTime = date.Year > 1998 ? date : (DateTime?)null;
                                        }
                                        catch (ArgumentOutOfRangeException)
                                        {
                                            fm.ReleaseDate.DateTime = null;
                                        }
                                    }
                                    else if (lts.StartsWith("date="))
                                    {
                                        ulong.TryParse(ltb.Substring(5), out ulong result);
                                        try
                                        {
                                            var date = new DateTime(1899, 12, 30).AddDays(result);
                                            fm.LastPlayed.DateTime = date.Year > 1998 ? date : (DateTime?)null;
                                        }
                                        catch (ArgumentOutOfRangeException)
                                        {
                                            fm.LastPlayed.DateTime = null;
                                        }
                                    }
                                    else if (lts.StartsWith("finished="))
                                    {
                                        uint.TryParse(ltb.Substring(9), out uint result);
                                        // result will be 0 on fail, which is the empty value so it's fine
                                        fm.FinishedOn = result;
                                    }
                                    else if (!ltb.IsEmpty() && ltb[0] == '[' && ltb[ltb.Length - 1] == ']')
                                    {
                                        break;
                                    }
                                    i++;
                                }

                                fms.Add(fm);
                            }

                            #endregion
                        }
                        return(ImportError.None);
                    }
                    catch (Exception ex)
                    {
                        Log("Exception in " + nameof(ImportDarkLoader) + "." + nameof(ImportInternal), ex);
                        return(ImportError.Unknown);
                    }
                    finally
                    {
                        Core.View.InvokeSync(new Action(Core.View.HideProgressBox));
                    }
                });
            }

            if (error != ImportError.None)
            {
                return(error, fms);
            }

            if (importSaves)
            {
                bool success = await ImportSaves(lines);
            }

            var importedFMs = returnUnmergedFMsList
                ? fms
                : ImportCommon.MergeImportedFMData(ImportType.DarkLoader, fms, fields);

            return(ImportError.None, importedFMs);
        }
Пример #3
0
        ImportInternal(string iniFile, bool returnUnmergedFMsList = false, FieldsToImport?fields = null)
        {
            string[] lines = await Task.Run(() => File.ReadAllLines(iniFile));

            var fms = new List <FanMission>();

            await Task.Run(() =>
            {
                for (int i = 0; i < lines.Length; i++)
                {
                    string line = lines[i];

                    if (line.Length >= 5 && line[0] == '[' && line[1] == 'F' && line[2] == 'M' && line[3] == '=')
                    {
                        string instName = line.Substring(4, line.Length - 5);

                        var fm = new FanMission {
                            InstalledDir = instName
                        };

                        while (i < lines.Length - 1)
                        {
                            string lineFM = lines[i + 1];
                            if (lineFM.StartsWithFast_NoNullChecks("NiceName="))
                            {
                                fm.Title = lineFM.Substring(9);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Archive="))
                            {
                                fm.Archive = lineFM.Substring(8);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("ReleaseDate="))
                            {
                                fm.ReleaseDate.UnixDateString = lineFM.Substring(12);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("LastStarted="))
                            {
                                fm.LastPlayed.UnixDateString = lineFM.Substring(12);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Completed="))
                            {
                                int.TryParse(lineFM.Substring(10), out int result);
                                // Unfortunately FMSel doesn't let you choose the difficulty you finished on, so
                                // we have to have this fallback value as a best-effort thing.
                                if (result > 0)
                                {
                                    fm.FinishedOnUnknown = true;
                                }
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Rating="))
                            {
                                fm.Rating = int.TryParse(lineFM.Substring(7), out int result) ? result : -1;
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Notes="))
                            {
                                fm.Comment = lineFM.Substring(6).Replace(@"\n", @"\r\n");
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("ModExclude="))
                            {
                                string val = lineFM.Substring(11);
                                if (val == "*")
                                {
                                    fm.DisableAllMods = true;
                                }
                                else
                                {
                                    fm.DisabledMods = val;
                                }
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("Tags="))
                            {
                                fm.TagsString = lineFM.Substring(5);
                            }
                            else if (lineFM.StartsWithFast_NoNullChecks("InfoFile="))
                            {
                                fm.SelectedReadme = lineFM.Substring(9);
                            }
                            else if (!lineFM.IsEmpty() && lineFM[0] == '[' && lineFM[lineFM.Length - 1] == ']')
                            {
                                break;
                            }
                            i++;
                        }

                        fms.Add(fm);
                    }
                }
            });

            var importedFMs = returnUnmergedFMsList
                ? fms
                : ImportCommon.MergeImportedFMData(ImportType.FMSel, fms, fields);

            return(ImportError.None, importedFMs);
        }