/// <summary>
        ///     Initializes a new instance of the <see cref="ARealmReversed" /> class.
        /// </summary>
        /// <param name="gameDirectory">Directory of the game installation.</param>
        /// <param name="storeFile">File used for storing definitions and history.</param>
        /// <param name="language">Initial language to use.</param>
        /// <param name="libraFile">Location of the Libra Eorzea database file, or <c>null</c> if it should not be used.</param>
        public ARealmReversed(DirectoryInfo gameDirectory, FileInfo storeFile, Language language, FileInfo libraFile)
        {
            // Fix for being referenced in a .Net Core 2.1+ application (https://stackoverflow.com/questions/50449314/ibm437-is-not-a-supported-encoding-name => https://stackoverflow.com/questions/44659499/epplus-error-reading-file)
            // PM> dotnet add package System.Text.Encoding.CodePages
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            _GameDirectory = gameDirectory;
            _Packs         = new PackCollection(Path.Combine(gameDirectory.FullName, "game", "sqpack"));
            _GameData      = new XivCollection(Packs, libraFile)
            {
                ActiveLanguage = language
            };

            _GameVersion         = File.ReadAllText(Path.Combine(gameDirectory.FullName, "game", "ffxivgame.ver"));
            _StateFile           = storeFile;
            _GameData.Definition = ReadDefinition();

            using (ZipFile zipFile = new ZipFile(StateFile.FullName, ZipEncoding)) {
                if (!zipFile.ContainsEntry(VersionFile))
                {
                    Setup(zipFile);
                }
            }

            _GameData.Definition.Compile();
        }
Esempio n. 2
0
        public ISheet GetSheet(string name)
        {
            const string ExHPathFormat = "exd/{0}.exh";

            if (_Sheets.TryGetValue(name, out var sheetRef) && sheetRef.TryGetTarget(out var sheet))
            {
                return(sheet);
            }

            //name = FixName(name);
            if (!_AvailableSheets.Contains(name))
            {
                throw new KeyNotFoundException($"Unknown sheet '{name}'");
            }

            var exhPath = string.Format(ExHPathFormat, name);
            var exh     = PackCollection.GetFile(exhPath);

            var header = CreateHeader(name, exh);

            sheet = CreateSheet(header);

            _Sheets.GetOrAdd(name, n => new WeakReference <ISheet>(sheet)).SetTarget(sheet);
            return(sheet);
        }
Esempio n. 3
0
        public ISheet GetSheet(string name)
        {
            const string ExHPathFormat = "exd/{0}.exh";

            //name = FixName(name);
            if (!_AvailableSheets.Contains(name))
            {
                throw new KeyNotFoundException();
            }

            ISheet sheet;
            WeakReference <ISheet> sheetRef;

            if (_Sheets.TryGetValue(name, out sheetRef) && sheetRef.TryGetTarget(out sheet))
            {
                return(sheet);
            }

            var exhPath = string.Format(ExHPathFormat, name);
            var exh     = PackCollection.GetFile(exhPath);

            var header = CreateHeader(name, exh);

            sheet = CreateSheet(header);

            if (_Sheets.ContainsKey(name))
            {
                _Sheets[name].SetTarget(sheet);
            }
            else
            {
                _Sheets.Add(name, new WeakReference <ISheet>(sheet));
            }
            return(sheet);
        }
Esempio n. 4
0
        /// <summary>
        ///     Update to the current version.
        /// </summary>
        /// <param name="detectDataChanges">Boolean indicating whether the update should also look for changes in data.</param>
        /// <param name="progress">Optional object to which update progress is reported.</param>
        /// <returns>Returns the <see cref="UpdateReport" /> containing all changes.</returns>
        /// <exception cref="InvalidOperationException">Definition is up-to-date.</exception>
        public UpdateReport Update(bool detectDataChanges, IProgress <UpdateProgress> progress = null)
        {
            if (DefinitionVersion == GameVersion)
            {
                throw new InvalidOperationException();
            }

            var previousVersion = DefinitionVersion;

            var exdPackId          = new PackIdentifier("exd", PackIdentifier.DefaultExpansion, 0);
            var exdPack            = Packs.GetPack(exdPackId);
            var exdOldKeepInMemory = exdPack.KeepInMemory;

            exdPack.KeepInMemory = true;

            string       tempPath = null;
            UpdateReport report;

            try {
                using (var zip = new ZipFile(StateFile.FullName, ZipEncoding)) {
                    tempPath = ExtractPacks(zip, previousVersion);
                    var previousPack = new PackCollection(Path.Combine(tempPath, previousVersion));
                    previousPack.GetPack(exdPackId).KeepInMemory = true;
                    var previousDefinition = ReadDefinition(zip);

                    var updater = new RelationUpdater(previousPack, previousDefinition, Packs, GameVersion, progress);

                    var changes = updater.Update(detectDataChanges);
                    report = new UpdateReport(previousVersion, GameVersion, changes);

                    var definition = updater.Updated;

                    StorePacks(zip);
                    StoreDefinition(zip, definition, DefinitionFile);
                    StoreDefinition(zip, definition, string.Format("{0}/{1}", definition.Version, DefinitionFile));
                    StoreReport(zip, report);
                    zip.Save();

                    GameData.Definition = definition;
                    GameData.Definition.Compile();
                }
            } finally {
                if (exdPack != null)
                {
                    exdPack.KeepInMemory = exdOldKeepInMemory;
                }
                if (tempPath != null)
                {
                    try {
                        Directory.Delete(tempPath, true);
                    } catch {
                        Console.Error.WriteLine("Failed to delete temporary directory {0}.", tempPath);
                    }
                }
            }
            return(report);
        }
Esempio n. 5
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="XivCollection" /> class.
 /// </summary>
 /// <param name="packCollection">The <see cref="PackCollection" /> to use to access game data.</param>
 /// <param name="libraDatabase"><see cref="FileInfo"/> of the Libra Eorzea database file, or <c>null</c> if Libra data should be disabled.</param>
 public XivCollection(PackCollection packCollection, System.IO.FileInfo libraDatabase)
     : base(packCollection)
 {
     if (libraDatabase != null && libraDatabase.Exists)
     {
         const string LibraConnectionStringFormat = @"metadata=res://*/Libra.LibraModel.csdl|res://*/Libra.LibraModel.ssdl|res://*/Libra.LibraModel.msl;provider=System.Data.SQLite.EF6;provider connection string='data source=""{0}""'";
         string       connStr = string.Format(LibraConnectionStringFormat, libraDatabase.FullName);
         _Libra = new Libra.Entities(connStr);
     }
 }
Esempio n. 6
0
        private void BuildIndex()
        {
            var exRoot = PackCollection.GetFile("exd/root.exl");

            var available = new List <string>();

            using (var ms = new MemoryStream(exRoot.GetData())) {
                using (var s = new StreamReader(ms, Encoding.ASCII)) {
                    s.ReadLine(); // EXLT,2

                    while (!s.EndOfStream)
                    {
                        var line = s.ReadLine();
                        if (string.IsNullOrWhiteSpace(line))
                        {
                            continue;
                        }

                        var split = line.Split(',');
                        if (split.Length != 2)
                        {
                            continue;
                        }

// TODO: Had problem handling negative numbers.
// I'm not sure if it is due to .net core's int.Parse or
// if it is another different from .net core that makes
// this numbers negative.. keeping this for the moment
                        var format = new NumberFormatInfo();
                        format.NegativeSign           = "-";
                        format.NumberNegativePattern  = 1;
                        format.NumberDecimalSeparator = ".";

                        var name = split[0];
                        var id   = int.Parse(split[1], System.Globalization.NumberStyles.AllowLeadingSign, format);

                        available.Add(name);
                        if (id >= 0)
                        {
                            _SheetIdentifiers.Add(id, name);
                        }
                    }
                }
            }

            _AvailableSheets = new HashSet <string>(available);
        }
Esempio n. 7
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="ARealmReversed" /> class.
        /// </summary>
        /// <param name="gameDirectory">Directory of the game installation.</param>
        /// <param name="storeFile">File used for storing definitions and history.</param>
        /// <param name="language">Initial language to use.</param>
        /// <param name="libraFile">Location of the Libra Eorzea database file, or <c>null</c> if it should not be used.</param>
        public ARealmReversed(DirectoryInfo gameDirectory, FileInfo storeFile, Language language, FileInfo libraFile)
        {
            _GameDirectory = gameDirectory;
            _Packs         = new PackCollection(Path.Combine(gameDirectory.FullName, "game", "sqpack"));
            _GameData      = new XivCollection(Packs, libraFile)
            {
                ActiveLanguage = language
            };

            _GameVersion = File.ReadAllText(Path.Combine(gameDirectory.FullName, "game", "ffxivgame.ver"));
            _StateFile   = storeFile;

            using (var zipFile = new ZipFile(StateFile.FullName, ZipEncoding)) {
                if (zipFile.ContainsEntry(VersionFile))
                {
                    RelationDefinition fsDef = null, zipDef = null;
                    DateTime           fsMod = DateTime.MinValue, zipMod = DateTime.MinValue;
                    if (!TryGetDefinitionVersion(zipFile, GameVersion, out zipDef, out zipMod))
                    {
                        zipDef = ReadDefinition(zipFile, DefinitionFile, out zipMod);
                    }
                    if (!TryGetDefinitionFromFileSystem(out fsDef, out fsMod))
                    {
                        fsDef = null;
                    }

                    if (fsDef != null && fsMod > zipMod)
                    {
                        fsDef.Version        = GameVersion;
                        _GameData.Definition = fsDef;
                        StoreDefinition(zipFile, fsDef, DefinitionFile);
                        zipFile.Save();
                    }
                    else
                    {
                        _GameData.Definition = zipDef;
                    }
                }
                else
                {
                    _GameData.Definition = Setup(zipFile);
                }
            }

            _GameData.Definition.Compile();
        }
Esempio n. 8
0
        public RelationUpdater(PackCollection previousPacks,
                               RelationDefinition previousDefinition,
                               PackCollection updatedPacks,
                               string updatedVersion,
                               IProgress <UpdateProgress> progress)
        {
            _Progress = progress ?? new NullProgress();

            _Previous = new RelationalExCollection(previousPacks);
            Previous  = previousDefinition;

            _Updated = new RelationalExCollection(updatedPacks);
            Updated  = new RelationDefinition {
                Version = updatedVersion
            };

            _Previous.ActiveLanguage = UsedLanguage;
            _Updated.ActiveLanguage  = UsedLanguage;
        }
Esempio n. 9
0
        /// <summary>
        ///     Get the model for a specific QWord, character type, and the current <see cref="EquipSlot" />.
        /// </summary>
        /// <param name="key">The identifier of the model.</param>
        /// <param name="characterType">Character type to get the model for.</param>
        /// <param name="materialVersion">When this method returns, contains the variant contained within <c>key</c>.</param>
        /// <returns>Returns the <see cref="Model" /> for the specified <c>key</c> and <c>characterType</c>.</returns>
        public ModelDefinition GetModel(Quad key, int characterType, out Graphics.ImcVariant variant)
        {
            variant = Graphics.ImcVariant.Default;

            if (!ModelHelpers.TryGetValue(Key, out ModelHelper helper))
            {
                return(null);
            }
            if (helper == null)
            {
                return(null);
            }

            PackCollection packs = Collection.Collection.PackCollection;

            int variantIndex = (int)((key.ToInt64() >> (helper.VariantIndexWord * 16)) & 0xFFFF);

            string imcPath = string.Format(helper.ImcFileFormat, key.Value1, key.Value2, key.Value3, key.Value4, characterType);

            if (!packs.TryGetFile(imcPath, out File imcBase))
            {
                return(null);
            }

            ImcFile imc = new Graphics.ImcFile(imcBase);

            variant = imc.GetVariant(helper.ImcPartKey, variantIndex);

            IO.File modelBase = null;
            while (!packs.TryGetFile(string.Format(helper.ModelFileFormat, key.Value1, key.Value2, key.Value3, key.Value4, characterType), out modelBase) && CharacterTypeFallback.TryGetValue(characterType, out characterType))
            {
            }

            ModelFile asModel = modelBase as Graphics.ModelFile;

            if (asModel == null)
            {
                return(null);
            }
            return(asModel.GetModelDefinition());
        }
Esempio n. 10
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="ARealmReversed" /> class.
        /// </summary>
        /// <param name="gameDirectory">Directory of the game installation.</param>
        /// <param name="storeFile">File used for storing definitions and history.</param>
        /// <param name="language">Initial language to use.</param>
        /// <param name="libraFile">Location of the Libra Eorzea database file, or <c>null</c> if it should not be used.</param>
        public ARealmReversed(DirectoryInfo gameDirectory, FileInfo storeFile, Language language, FileInfo libraFile)
        {
            _GameDirectory = gameDirectory;
            _Packs         = new PackCollection(Path.Combine(gameDirectory.FullName, "game", "sqpack"));
            _GameData      = new XivCollection(Packs, libraFile)
            {
                ActiveLanguage = language
            };

            _GameVersion         = File.ReadAllText(Path.Combine(gameDirectory.FullName, "game", "ffxivgame.ver"));
            _StateFile           = storeFile;
            _GameData.Definition = ReadDefinition();

            using (var zipFile = new ZipFile(StateFile.FullName, ZipEncoding)) {
                if (!zipFile.ContainsEntry(VersionFile))
                {
                    Setup(zipFile);
                }
            }

            _GameData.Definition.Compile();
        }
Esempio n. 11
0
        private void BuildIndex()
        {
            var exRoot = PackCollection.GetFile("exd/root.exl");

            var available = new List <string>();

            using (var ms = new MemoryStream(exRoot.GetData())) {
                using (var s = new StreamReader(ms, Encoding.ASCII)) {
                    s.ReadLine(); // EXLT,2

                    while (!s.EndOfStream)
                    {
                        var line = s.ReadLine();
                        if (string.IsNullOrWhiteSpace(line))
                        {
                            continue;
                        }

                        var split = line.Split(',');
                        if (split.Length != 2)
                        {
                            continue;
                        }

                        var name = split[0];
                        var id   = int.Parse(split[1]);

                        available.Add(name);
                        if (id >= 0)
                        {
                            _SheetIdentifiers.Add(id, name);
                        }
                    }
                }
            }

            _AvailableSheets = new HashSet <string>(available);
        }
Esempio n. 12
0
        public ExCollection(PackCollection packCollection)
        {
            PackCollection = packCollection;

            BuildIndex();
        }
Esempio n. 13
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="XivCollection" /> class.
 /// </summary>
 /// <param name="packCollection">The <see cref="PackCollection" /> to use to access game data.</param>
 public XivCollection(PackCollection packCollection) : this(packCollection, null)
 {
 }
Esempio n. 14
0
        /// <summary>
        ///     Update to the current version.
        /// </summary>
        /// <param name="detectDataChanges">Boolean indicating whether the update should also look for changes in data.</param>
        /// <param name="progress">Optional object to which update progress is reported.</param>
        /// <returns>Returns the <see cref="UpdateReport" /> containing all changes.</returns>
        /// <exception cref="InvalidOperationException">Definition is up-to-date.</exception>
        public UpdateReport Update(bool detectDataChanges, IProgress <UpdateProgress> progress = null)
        {
            if (DefinitionVersion == GameVersion)
            {
                throw new InvalidOperationException();
            }

            var previousVersion = DefinitionVersion;

            var exdPackId          = new PackIdentifier("exd", PackIdentifier.DefaultExpansion, 0);
            var exdPack            = Packs.GetPack(exdPackId);
            var exdOldKeepInMemory = exdPack.KeepInMemory;

            exdPack.KeepInMemory = true;

            string       tempPath = null;
            UpdateReport report;

            try {
                using (var zip = new ZipFile(StateFile.FullName, ZipEncoding)) {
                    tempPath = ExtractPacks(zip, previousVersion);
                    var previousPack = new PackCollection(Path.Combine(tempPath, previousVersion));
                    previousPack.GetPack(exdPackId).KeepInMemory = true;

                    RelationDefinition previousDefinition;
                    if (previousVersion == _GameData.Definition.Version)
                    {
                        // Override previous definition when current definition version matches.
                        // Definitions may have changed since this was recorded and we want to compare that.
                        previousDefinition = _GameData.Definition;
                    }
                    else
                    {
                        // Otherwise, read the previous definition from the zip.
                        previousDefinition = ReadDefinition(zip, previousVersion);
                    }

                    var updater = new RelationUpdater(previousPack, previousDefinition, Packs, GameVersion, progress);

                    var changes = updater.Update(detectDataChanges);
                    report = new UpdateReport(previousVersion, GameVersion, changes);

                    var definition = updater.Updated;

                    StorePacks(zip);
                    StoreDefinitionInZip(zip, definition);
                    StoreDefinitionOnFilesystem(definition, "");

                    if (Debugger.IsAttached)
                    {
                        // Little QOL path - when updating with the debugger attached,
                        // also write to the project definitions path so no need to copy
                        // them manually afterward.
                        var projectDefinitionsPath = "../../../SaintCoinach";
                        if (Directory.Exists(projectDefinitionsPath))
                        {
                            StoreDefinitionOnFilesystem(definition, projectDefinitionsPath);
                        }
                    }

                    StoreReport(zip, report);
                    UpdateVersion(zip);
                    zip.Save();

                    GameData.Definition = definition;
                    GameData.Definition.Compile();
                }
            } finally {
                if (exdPack != null)
                {
                    exdPack.KeepInMemory = exdOldKeepInMemory;
                }
                if (tempPath != null)
                {
                    try {
                        Directory.Delete(tempPath, true);
                    } catch {
                        Console.Error.WriteLine("Failed to delete temporary directory {0}.", tempPath);
                    }
                }
            }
            return(report);
        }
 public RelationalExCollection(PackCollection packCollection) : base(packCollection)
 {
 }