改了一亿个东西,修了一亿个 BUG

This commit is contained in:
2021-10-19 17:42:18 +02:00
parent 5b907309e0
commit 888ddce4ef
40 changed files with 1870 additions and 1715 deletions

View File

@@ -1,172 +1,35 @@
using System;
using System.Collections.Generic;
using AnotherReplayReader.Utils;
using Microsoft.Win32;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Win32;
using OpenSage.FileFormats.Big;
using TechnologyAssembler.Core.IO;
namespace AnotherReplayReader
{
internal sealed class BigMinimapCache
{
private sealed class CacheAdapter
{
public List<string> Bigs { get; set; }
public Dictionary<string, string> MapsToBigs { get; set; }
private readonly object _lock = new();
private SkuDefFileSystemProvider? _skudefFileSystem = null;
public CacheAdapter()
{
Bigs = new List<string>();
MapsToBigs = new Dictionary<string, string>();
}
public BigMinimapCache(string? ra3Directory)
{
Task.Run(() => Initialize(ra3Directory));
}
//private Cache _cache;
private volatile IReadOnlyDictionary<string, string> _mapsToBigs = null;
public BigMinimapCache(Cache cache, string ra3Directory)
public bool TryGetEntry(string path, out Stream? bigEntry)
{
//_cache = cache;
bigEntry = null;
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)
using var locker = new Lock(_lock);
if (_skudefFileSystem is not { } fs)
{
return false;
}
if (!_mapsToBigs.ContainsKey(path))
if (!fs.FileExists(path))
{
Debug.Instance.DebugMessage += $"Cannot find big entry [{path}].\r\n";
return false;
@@ -174,58 +37,75 @@ namespace AnotherReplayReader
try
{
var bigPath = _mapsToBigs[path];
big = new BigArchive(bigPath);
if(big.GetEntry(path) == null)
{
//_cache.Remove("bigsCache");
big.Dispose();
big = null;
return false;
}
bigEntry = fs.OpenStream(path, VirtualFileModeType.Open);
return true;
}
catch (Exception exception)
{
Debug.Instance.DebugMessage += $"Exception during query (entryStream) of BigMinimapCache: \r\n{exception}\r\n";
big = null;
return false;
}
return true;
return false;
}
public byte[] TryReadBytesFromBig(string path)
private void Initialize(string? ra3Directory)
{
if(_mapsToBigs == null)
{
return null;
}
if(!_mapsToBigs.ContainsKey(path))
{
return null;
}
try
{
var bigPath = _mapsToBigs[path];
using (var big = new BigArchive(path))
if (ra3Directory is null || !Directory.Exists(ra3Directory))
{
var entry = big.GetEntry(path);
using (var stream = entry.Open())
using (var reader = new BinaryReader(stream))
{
return reader.ReadBytes((int)entry.Length);
}
Debug.Instance.DebugMessage += $"Will not initialize BigMinimapCache because RA3Directory {ra3Directory} does not exist.\r\n";
return;
}
var currentLanguage = RegistryUtils.RetrieveInRa3(RegistryHive.CurrentUser, "Language");
var currentLanguage_ = $"{currentLanguage}_";
double SkudefVersionSelector(string fullPath)
{
var value = -1.0;
try
{
const string skudefPrefix = "RA3";
const int prefix = 1;
const int language = 2;
const int majorVersion = 3;
const int minorVersion = 4;
const int majorVersionMultiplier = 10000;
const int correctLanguageBonus = 1000_0000;
value = 0;
var stem = Path.GetFileNameWithoutExtension(fullPath);
var match = Regex.Match(stem, @"([^_]*)_([^0-9]*)([0-9]*)\.([0-9]*)");
if (!match.Success || match.Groups.Cast<Group>().Any(g => !g.Success))
{
return value;
}
value += match.Groups[prefix].Value == skudefPrefix ? 0.1 : 0;
value += match.Groups[language].Value == currentLanguage_ ? correctLanguageBonus : 0;
value += int.Parse(match.Groups[majorVersion].Value) * majorVersionMultiplier;
value += int.Parse(match.Groups[minorVersion].Value);
return value;
}
catch (Exception e)
{
Debug.Instance.DebugMessage += $"Failed to retrieve skudef: {e}\r\n";
}
return value;
}
var highestSkudef = (from p in Directory.EnumerateFiles(ra3Directory, "*.SkuDef")
orderby SkudefVersionSelector(p) descending
select p).First();
Debug.Instance.DebugMessage += $"Retrieved highest skudef: {highestSkudef}\r\n";
using var locker = new Lock(_lock);
DronePlatform.BuildTechnologyAssembler();
_skudefFileSystem = new SkuDefFileSystemProvider("config", highestSkudef);
}
catch (Exception exception)
{
Debug.Instance.DebugMessage += $"Exception during query (bytes) of BigMinimapCache: \r\n{exception}\r\n";
//_cache.Remove("bigsCache");
Debug.Instance.DebugMessage += $"Exception during initialization of BigMinimapCache: \r\n{exception}\r\n";
}
return null;
}
}
}