改了一亿个东西,修了一亿个 BUG
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user