AnotherReplayReader/MinimapReader.cs

118 lines
4.3 KiB
C#

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<ImageFormat, PixelFormat> FormatMapper = new Dictionary<ImageFormat, PixelFormat>
{
{ 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<BitmapSource?> 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<string>();
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;
}
}
}