using AnotherReplayReader.ReplayFile; using Pfim; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; using TechnologyAssembler.Core.IO; namespace AnotherReplayReader { internal sealed class MinimapReader { public static readonly IReadOnlyDictionary FormatMapper = new Dictionary { { ImageFormat.Rgb24, PixelFormats.Bgr24 }, { ImageFormat.Rgba32, PixelFormats.Bgr32 }, { ImageFormat.Rgb8, PixelFormats.Gray8 }, { ImageFormat.R5g5b5a1, PixelFormats.Bgr555 }, { ImageFormat.R5g5b5, PixelFormats.Bgr555 }, { ImageFormat.R5g6b5, PixelFormats.Bgr565 }, }; private readonly BigMinimapCache _cache; private readonly string _mapFolderPath; private readonly string _modFolderPath; public MinimapReader(BigMinimapCache cache, string mapFolderPath, string modFolderPath) { _cache = cache; _mapFolderPath = mapFolderPath; _modFolderPath = modFolderPath; } public Task TryReadTargaAsync(Replay replay, double dpiX = 96.0, double dpiY = 96.0) { var mapPath = replay.MapPath.TrimEnd('/'); var mapName = mapPath.Substring(mapPath.LastIndexOf('/') + 1); var minimapPath = $"{mapPath}/{mapName}_art.tga"; return Task.Run(() => TryReadTarga(minimapPath, replay.Mod, dpiX, dpiY)); } public BitmapSource? TryReadTarga(string path, Mod mod, double dpiX = 96.0, double dpiY = 96.0) { using var targa = TryGetTarga(path, mod); if (targa == null) { return null; } try { var bitmap = BitmapSource.Create(targa.Width, targa.Height, dpiX, dpiY, FormatMapper[targa.Format], null, targa.Data, targa.Stride); bitmap.Freeze(); return bitmap; } catch (Exception exception) { Debug.Instance.DebugMessage += $"Exception creating BitmapSource from minimap:\r\n {exception}\r\n"; return null; } } private Targa? TryGetTarga(string path, Mod mod) { const string customMapPrefix = "data/maps/internal/"; if (Directory.Exists(_mapFolderPath) && path.StartsWith(customMapPrefix)) { var minimapPath = Path.Combine(_mapFolderPath, path.Substring(customMapPrefix.Length)); if (File.Exists(minimapPath)) { return Targa.Create(File.ReadAllBytes(minimapPath), new PfimConfig()); } } if (!mod.IsRA3) { var modSkudefPaths = Enumerable.Empty(); foreach (var subFolder in Directory.EnumerateDirectories(_modFolderPath)) { modSkudefPaths = modSkudefPaths.Concat(Directory.EnumerateFiles(subFolder, $"{mod.ModName}_{mod.ModVersion}.SkuDef")); } DronePlatform.BuildTechnologyAssembler(); foreach (var modSkudefPath in modSkudefPaths) { try { using var fs = new SkuDefFileSystemProvider("modConfig", modSkudefPath); if (!fs.FileExists(path)) { continue; } using var stream = fs.OpenStream(path, VirtualFileModeType.Open); return Targa.Create(stream, new PfimConfig()); } catch (Exception exception) { Debug.Instance.DebugMessage += $"Exception when reading minimap from mod bigs:\r\n {exception}\r\n"; } } } if (_cache != null && _cache.TryGetEntry(path, out var big)) { using (big) { return Targa.Create(big, new PfimConfig()); } } return null; } } }