232 lines
7.8 KiB
C#
232 lines
7.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Win32;
|
|
using OpenSage.FileFormats.Big;
|
|
|
|
namespace AnotherReplayReader
|
|
{
|
|
internal sealed class BigMinimapCache
|
|
{
|
|
private sealed class CacheAdapter
|
|
{
|
|
public List<string> Bigs { get; set; }
|
|
public Dictionary<string, string> MapsToBigs { get; set; }
|
|
|
|
public CacheAdapter()
|
|
{
|
|
Bigs = new List<string>();
|
|
MapsToBigs = new Dictionary<string, string>();
|
|
}
|
|
}
|
|
|
|
//private Cache _cache;
|
|
private volatile IReadOnlyDictionary<string, string> _mapsToBigs = null;
|
|
|
|
public BigMinimapCache(Cache cache, string ra3Directory)
|
|
{
|
|
//_cache = cache;
|
|
|
|
Task.Run(() =>
|
|
{
|
|
try
|
|
{
|
|
if (!Directory.Exists(ra3Directory))
|
|
{
|
|
Debug.Instance.DebugMessage += $"Will not initialize BigMinimapCache because RA3Directory {ra3Directory} does not exist.\r\n";
|
|
return;
|
|
}
|
|
|
|
var bigSet = ParseSkudefs(Directory.EnumerateFiles(ra3Directory, "*.SkuDef"));
|
|
|
|
//var cached = _cache.GetOrDefault("bigsCache", new CacheAdapter());
|
|
var mapsToBigs = new Dictionary<string, string>();
|
|
|
|
foreach (var bigPath in bigSet/*.Where(x => !cached.Bigs.Contains(x))*/)
|
|
{
|
|
if (!File.Exists(bigPath))
|
|
{
|
|
Debug.Instance.DebugMessage += $"Big {bigPath} does not exist.\r\n";
|
|
continue;
|
|
}
|
|
|
|
Debug.Instance.DebugMessage += $"Trying to add Big {bigPath} to big minimap cache...\r\n";
|
|
try
|
|
{
|
|
using (var big = new BigArchive(bigPath))
|
|
{
|
|
foreach (var entry in big.Entries)
|
|
{
|
|
if (entry.FullName.EndsWith("_art.tga", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
mapsToBigs[entry.FullName] = bigPath;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
catch(Exception exception)
|
|
{
|
|
Debug.Instance.DebugMessage += $"Exception when reading big:\r\n {exception}\r\n";
|
|
}
|
|
}
|
|
//cached.Bigs = bigSet.ToList();
|
|
|
|
//_cache.Set("bigsCache", cached);
|
|
_mapsToBigs = mapsToBigs; //cached.MapsToBigs;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.Instance.DebugMessage += $"Exception during initialization of BigMinimapCache: \r\n{exception}\r\n";
|
|
}
|
|
});
|
|
}
|
|
|
|
public static HashSet<string> ParseSkudefs(IEnumerable<string> skudefs)
|
|
{
|
|
var skudefSet = new HashSet<string>(skudefs.Select(x => x.ToLowerInvariant()));
|
|
var unreadSkudefs = new HashSet<string>();
|
|
var bigSet = new HashSet<string>();
|
|
|
|
void ReadSkudefLine(string baseDirectory, string line, string expectedCommand, Action<string> action)
|
|
{
|
|
try
|
|
{
|
|
char[] separators = { ' ', '\t' };
|
|
line = line.ToLowerInvariant();
|
|
var splitted = line.Split(separators, 2, StringSplitOptions.RemoveEmptyEntries);
|
|
if (splitted[0].Equals(expectedCommand))
|
|
{
|
|
var path = splitted[1];
|
|
if (!Path.IsPathRooted(path))
|
|
{
|
|
path = Path.Combine(baseDirectory, path);
|
|
}
|
|
action(path);
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.Instance.DebugMessage += $"Exception when parsing skudef line:\r\n {exception}\r\n";
|
|
}
|
|
}
|
|
|
|
void ReadSkudef(string fileName, Action<string, string> onBaseDirectoryAndLine)
|
|
{
|
|
try
|
|
{
|
|
var baseDirectory = Path.GetDirectoryName(fileName).ToLowerInvariant();
|
|
foreach (var line in File.ReadAllLines(fileName))
|
|
{
|
|
onBaseDirectoryAndLine(baseDirectory, line);
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.Instance.DebugMessage += $"Exception when parsing skudef file:\r\n {exception}\r\n";
|
|
}
|
|
}
|
|
|
|
foreach (var skudef in skudefSet)
|
|
{
|
|
ReadSkudef(skudef, (baseDirectory, line) =>
|
|
{
|
|
ReadSkudefLine(baseDirectory, line, "add-config", x =>
|
|
{
|
|
if (!skudefSet.Contains(x))
|
|
{
|
|
unreadSkudefs.Add(x);
|
|
}
|
|
});
|
|
|
|
ReadSkudefLine(baseDirectory, line, "add-big", x => bigSet.Add(x));
|
|
});
|
|
}
|
|
|
|
foreach (var skudef in unreadSkudefs)
|
|
{
|
|
ReadSkudef(skudef, (baseDirectory, line) =>
|
|
{
|
|
ReadSkudefLine(baseDirectory, line, "add-big", x => bigSet.Add(x));
|
|
});
|
|
}
|
|
|
|
return bigSet;
|
|
}
|
|
|
|
public bool TryGetBigByEntryPath(string path, out BigArchive big)
|
|
{
|
|
big = null;
|
|
|
|
if (_mapsToBigs == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!_mapsToBigs.ContainsKey(path))
|
|
{
|
|
Debug.Instance.DebugMessage += $"Cannot find big entry [{path}].\r\n";
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
var bigPath = _mapsToBigs[path];
|
|
big = new BigArchive(bigPath);
|
|
if(big.GetEntry(path) == null)
|
|
{
|
|
//_cache.Remove("bigsCache");
|
|
big.Dispose();
|
|
big = null;
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.Instance.DebugMessage += $"Exception during query (entryStream) of BigMinimapCache: \r\n{exception}\r\n";
|
|
big = null;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public byte[] TryReadBytesFromBig(string path)
|
|
{
|
|
if(_mapsToBigs == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if(!_mapsToBigs.ContainsKey(path))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
var bigPath = _mapsToBigs[path];
|
|
using (var big = new BigArchive(path))
|
|
{
|
|
var entry = big.GetEntry(path);
|
|
using (var stream = entry.Open())
|
|
using (var reader = new BinaryReader(stream))
|
|
{
|
|
return reader.ReadBytes((int)entry.Length);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Debug.Instance.DebugMessage += $"Exception during query (bytes) of BigMinimapCache: \r\n{exception}\r\n";
|
|
//_cache.Remove("bigsCache");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
}
|