Example #1
0
        internal void Initialize(AssetStore assetStore)
        {
            // We need to check if there is an existing MapCache.ini file and if yes,
            // load it so that we can figure out which entries are outdated.
            // Then we need to update these entries, update the file, and parse it
            // again. In order to do that we first load it in a temporary scope.
            assetStore.PushScope();

            var mapCacheIniEntry = _contentManager.UserDataFileSystem.GetFile(MapCacheIniPath);

            if (mapCacheIniEntry != null)
            {
                _contentManager.LoadIniFile(mapCacheIniEntry);
            }

            // for each map, check if it was modified and the MapCache needs to be updated.
            var mapCacheEntries = new Dictionary <string, MapCache>();

            foreach (var mapEntry in EnumerateMaps())
            {
                var buildMapCache = false;
                var mapCache      = assetStore.MapCaches.GetByName(mapEntry.FullFilePath);
                var fileInfo      = new FileInfo(mapEntry.FullFilePath);

                if (mapCache == null)
                {
                    // new map
                    buildMapCache = true;
                }
                else
                {
                    var timestamp = DateTime.FromFileTime((((long)mapCache.TimestampHi) << 32) | (uint)mapCache.TimestampLo);

                    // TODO: Should we check the CRC here as well?
                    // If yes, which implementation should we use?
                    if (fileInfo.LastWriteTime != timestamp &&
                        fileInfo.Length != mapCache.FileSize)
                    {
                        // existing map modified
                        buildMapCache = true;
                    }
                }

                if (buildMapCache)
                {
                    mapCache = BuildMapCache(mapEntry, fileInfo, assetStore);
                }

                mapCacheEntries.Add(mapEntry.FullFilePath, mapCache);
            }

            // Get rid of the old MapCaches, generate the file based on
            // the updated ones and load it again, this time for real.
            assetStore.PopScope();

            var fullMapCacheIniPath = Path.Combine(_contentManager.UserDataFileSystem.RootDirectory, MapCacheIniPath);

            GenerateMapCacheIniFile(fullMapCacheIniPath, mapCacheEntries);

            mapCacheIniEntry = new FileSystemEntry(
                _contentManager.UserDataFileSystem,
                MapCacheIniPath,
                (uint)new FileInfo(fullMapCacheIniPath).Length,
                () => File.OpenRead(fullMapCacheIniPath));

            _contentManager.UserDataFileSystem.Update(mapCacheIniEntry);
            _contentManager.LoadIniFile(mapCacheIniEntry);
        }
Example #2
0
        public void CanReadIniFiles()
        {
            var gameDefinitions = new[]
            {
                GameDefinition.FromGame(SageGame.CncGenerals),
                GameDefinition.FromGame(SageGame.CncGeneralsZeroHour),
                GameDefinition.FromGame(SageGame.Bfme),
                GameDefinition.FromGame(SageGame.Bfme2),
                GameDefinition.FromGame(SageGame.Bfme2Rotwk),
            };

            using var graphicsDevice = GraphicsDeviceUtility.CreateGraphicsDevice(null, null);

            using var standardGraphicsResources = new StandardGraphicsResources(graphicsDevice);
            using var shaderSetStore            = new ShaderSetStore(graphicsDevice, RenderPipeline.GameOutputDescription);
            using var shaderResources           = new ShaderResourceManager(graphicsDevice, standardGraphicsResources, shaderSetStore);
            var graphicsLoadContext = new GraphicsLoadContext(graphicsDevice, standardGraphicsResources, shaderResources, shaderSetStore);

            foreach (var gameDefinition in gameDefinitions)
            {
                foreach (var installation in InstallationLocators.FindAllInstallations(gameDefinition))
                {
                    using var fileSystem = installation.CreateFileSystem();

                    var assetStore = new AssetStore(
                        gameDefinition.Game,
                        fileSystem,
                        LanguageUtility.ReadCurrentLanguage(gameDefinition, fileSystem),
                        graphicsDevice,
                        standardGraphicsResources,
                        shaderResources,
                        shaderSetStore,
                        gameDefinition.CreateAssetLoadStrategy());

                    assetStore.PushScope();

                    var dataContext = new IniDataContext();

                    void LoadIniFile(FileSystemEntry entry)
                    {
                        var parser = new IniParser(
                            entry,
                            assetStore,
                            gameDefinition.Game,
                            dataContext,
                            LocaleSpecificEncoding);

                        parser.ParseFile();
                    }

                    switch (gameDefinition.Game)
                    {
                    case SageGame.Bfme:
                    case SageGame.Bfme2:
                    case SageGame.Bfme2Rotwk:
                        LoadIniFile(fileSystem.GetFile(@"Data\INI\GameData.ini"));
                        break;
                    }

                    foreach (var file in fileSystem.GetFilesInDirectory("", $"*.ini", SearchOption.AllDirectories))
                    {
                        var filename = Path.GetFileName(file.FilePath).ToLowerInvariant();

                        switch (filename)
                        {
                        case "webpages.ini":               // Don't care about this

                        case "buttonsets.ini":             // Doesn't seem to be used?
                        case "scripts.ini":                // Only needed by World Builder?
                        case "commandmapdebug.ini":        // Only applies to DEBUG and INTERNAL builds
                        case "fxparticlesystemcustom.ini": // Don't know if this is used, it uses Emitter property not used elsewhere
                        case "lightpoints.ini":            // Don't know if this is used.

                        //added in BFME and subsequent games
                        case "optionregistry.ini":   // Don't know if this is used
                        case "localization.ini":     // Don't know if we need this
                            continue;

                        case "credits.ini":
                            if (gameDefinition.Game == SageGame.Bfme2Rotwk)     //corrupted in rotwk (start of the block is commented out)
                            {
                                continue;
                            }
                            break;

                        //mods specific

                        //edain mod
                        case "einstellungen.ini":
                        case "einstellungendeakt.ini":
                        case "einstellungenedain.ini":
                        case "news.ini":
                            continue;

                        //unofficial patch 2.02
                        case "desktop.ini":     //got into a big file somehow
                        case "2.01.ini":
                        case "disable timer.ini":
                        case "enable timer.ini":
                        case "old music.ini":
                            continue;

                        default:
                            if (filename.StartsWith("2.02"))
                            {
                                continue;
                            }
                            break;
                        }

                        _output.WriteLine($"Reading file {file.FilePath}.");

                        LoadIniFile(file);
                    }
                }
            }
        }