fuck vfx
This commit is contained in:
@@ -150,6 +150,32 @@ public sealed class FileCacheManager : IDisposable
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, FileCacheEntity?> GetFileCachesByPaths(string[] paths)
|
||||||
|
{
|
||||||
|
var cleanedPaths = paths.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(p => p,
|
||||||
|
p => p.Replace("/", "\\", StringComparison.OrdinalIgnoreCase).Replace(_ipcManager.PenumbraModDirectory!, PenumbraPrefix, StringComparison.OrdinalIgnoreCase),
|
||||||
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
Dictionary<string, FileCacheEntity?> result = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var dict = _fileCaches.SelectMany(f => f.Value).Where(f => f.PrefixedFilePath.StartsWith(PenumbraPrefix, StringComparison.Ordinal))
|
||||||
|
.ToDictionary(d => d.PrefixedFilePath, d => d, StringComparer.Ordinal);
|
||||||
|
|
||||||
|
foreach (var entry in cleanedPaths)
|
||||||
|
{
|
||||||
|
if (dict.TryGetValue(entry.Value, out var entity))
|
||||||
|
{
|
||||||
|
result.Add(entry.Key, entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Add(entry.Key, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public FileCacheEntity? GetFileCacheByPath(string path)
|
public FileCacheEntity? GetFileCacheByPath(string path)
|
||||||
{
|
{
|
||||||
var cleanedPath = path.Replace("/", "\\", StringComparison.OrdinalIgnoreCase).ToLowerInvariant().Replace(_ipcManager.PenumbraModDirectory!.ToLowerInvariant(), "", StringComparison.OrdinalIgnoreCase);
|
var cleanedPath = path.Replace("/", "\\", StringComparison.OrdinalIgnoreCase).ToLowerInvariant().Replace(_ipcManager.PenumbraModDirectory!.ToLowerInvariant(), "", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|||||||
@@ -13,14 +13,15 @@ public class CharacterData
|
|||||||
|
|
||||||
public string HeelsData { get; set; } = string.Empty;
|
public string HeelsData { get; set; } = string.Empty;
|
||||||
public string HonorificData { get; set; } = string.Empty;
|
public string HonorificData { get; set; } = string.Empty;
|
||||||
public bool IsReady => FileReplacements.SelectMany(k => k.Value).All(f => f.Computed);
|
|
||||||
|
|
||||||
public string ManipulationString { get; set; } = string.Empty;
|
public string ManipulationString { get; set; } = string.Empty;
|
||||||
public string PalettePlusPalette { get; set; } = string.Empty;
|
public string PalettePlusPalette { get; set; } = string.Empty;
|
||||||
|
|
||||||
public API.Data.CharacterData ToAPI()
|
public API.Data.CharacterData ToAPI()
|
||||||
{
|
{
|
||||||
var fileReplacements = FileReplacements.ToDictionary(k => k.Key, k => k.Value.Where(f => f.HasFileReplacement && !f.IsFileSwap).GroupBy(f => f.Hash, StringComparer.OrdinalIgnoreCase).Select(g =>
|
Dictionary<ObjectKind, List<FileReplacementData>> fileReplacements =
|
||||||
|
FileReplacements.ToDictionary(k => k.Key, k => k.Value.Where(f => f.HasFileReplacement && !f.IsFileSwap)
|
||||||
|
.GroupBy(f => f.Hash, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.Select(g =>
|
||||||
{
|
{
|
||||||
return new FileReplacementData()
|
return new FileReplacementData()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,27 +1,21 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using MareSynchronos.FileCache;
|
|
||||||
using MareSynchronos.API.Data;
|
using MareSynchronos.API.Data;
|
||||||
|
|
||||||
namespace MareSynchronos.PlayerData.Data;
|
namespace MareSynchronos.PlayerData.Data;
|
||||||
|
|
||||||
public partial class FileReplacement
|
public partial class FileReplacement
|
||||||
{
|
{
|
||||||
private readonly Lazy<string> _hashLazy;
|
public FileReplacement(string[] gamePaths, string filePath)
|
||||||
|
|
||||||
public FileReplacement(string[] gamePaths, string filePath, FileCacheManager fileDbManager)
|
|
||||||
{
|
{
|
||||||
GamePaths = gamePaths.Select(g => g.Replace('\\', '/').ToLowerInvariant()).ToHashSet(StringComparer.Ordinal);
|
GamePaths = gamePaths.Select(g => g.Replace('\\', '/').ToLowerInvariant()).ToHashSet(StringComparer.Ordinal);
|
||||||
ResolvedPath = filePath.Replace('\\', '/');
|
ResolvedPath = filePath.Replace('\\', '/');
|
||||||
_hashLazy = new(() => !IsFileSwap ? fileDbManager.GetFileCacheByPath(ResolvedPath)?.Hash ?? string.Empty : string.Empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Computed => IsFileSwap || !HasFileReplacement || !string.IsNullOrEmpty(Hash);
|
|
||||||
|
|
||||||
public HashSet<string> GamePaths { get; init; }
|
public HashSet<string> GamePaths { get; init; }
|
||||||
|
|
||||||
public bool HasFileReplacement => GamePaths.Count >= 1 && GamePaths.Any(p => !string.Equals(p, ResolvedPath, StringComparison.Ordinal));
|
public bool HasFileReplacement => GamePaths.Count >= 1 && GamePaths.Any(p => !string.Equals(p, ResolvedPath, StringComparison.Ordinal));
|
||||||
|
|
||||||
public string Hash => _hashLazy.Value;
|
public string Hash { get; set; } = string.Empty;
|
||||||
public bool IsFileSwap => !LocalPathRegex().IsMatch(ResolvedPath) && GamePaths.All(p => !LocalPathRegex().IsMatch(p));
|
public bool IsFileSwap => !LocalPathRegex().IsMatch(ResolvedPath) && GamePaths.All(p => !LocalPathRegex().IsMatch(p));
|
||||||
public string ResolvedPath { get; init; }
|
public string ResolvedPath { get; init; }
|
||||||
|
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ public class PlayerDataFactory
|
|||||||
var (forwardResolve, reverseResolve) = await _dalamudUtil.RunOnFrameworkThread(() => BuildDataFromModel(objectKind, charaPointer, token)).ConfigureAwait(false);
|
var (forwardResolve, reverseResolve) = await _dalamudUtil.RunOnFrameworkThread(() => BuildDataFromModel(objectKind, charaPointer, token)).ConfigureAwait(false);
|
||||||
Dictionary<string, List<string>> resolvedPaths = await GetFileReplacementsFromPaths(forwardResolve, reverseResolve).ConfigureAwait(false);
|
Dictionary<string, List<string>> resolvedPaths = await GetFileReplacementsFromPaths(forwardResolve, reverseResolve).ConfigureAwait(false);
|
||||||
previousData.FileReplacements[objectKind] =
|
previousData.FileReplacements[objectKind] =
|
||||||
new HashSet<FileReplacement>(resolvedPaths.Select(c => new FileReplacement(c.Value.ToArray(), c.Key, _fileCacheManager)), FileReplacementComparer.Instance)
|
new HashSet<FileReplacement>(resolvedPaths.Select(c => new FileReplacement(c.Value.ToArray(), c.Key)), FileReplacementComparer.Instance)
|
||||||
.Where(p => p.HasFileReplacement).ToHashSet();
|
.Where(p => p.HasFileReplacement).ToHashSet();
|
||||||
previousData.FileReplacements[objectKind].RemoveWhere(c => c.GamePaths.Any(g => !AllowedExtensionsForGamePaths.Any(e => g.EndsWith(e, StringComparison.OrdinalIgnoreCase))));
|
previousData.FileReplacements[objectKind].RemoveWhere(c => c.GamePaths.Any(g => !AllowedExtensionsForGamePaths.Any(e => g.EndsWith(e, StringComparison.OrdinalIgnoreCase))));
|
||||||
|
|
||||||
@@ -371,7 +371,7 @@ public class PlayerDataFactory
|
|||||||
var resolvedTransientPaths = await GetFileReplacementsFromPaths(transientPaths, new HashSet<string>(StringComparer.Ordinal)).ConfigureAwait(false);
|
var resolvedTransientPaths = await GetFileReplacementsFromPaths(transientPaths, new HashSet<string>(StringComparer.Ordinal)).ConfigureAwait(false);
|
||||||
|
|
||||||
_logger.LogDebug("== Transient Replacements ==");
|
_logger.LogDebug("== Transient Replacements ==");
|
||||||
foreach (var replacement in resolvedTransientPaths.Select(c => new FileReplacement(c.Value.ToArray(), c.Key, _fileCacheManager)).OrderBy(f => f.ResolvedPath, StringComparer.Ordinal))
|
foreach (var replacement in resolvedTransientPaths.Select(c => new FileReplacement(c.Value.ToArray(), c.Key)).OrderBy(f => f.ResolvedPath, StringComparer.Ordinal))
|
||||||
{
|
{
|
||||||
_logger.LogDebug("=> {repl}", replacement);
|
_logger.LogDebug("=> {repl}", replacement);
|
||||||
previousData.FileReplacements[objectKind].Add(replacement);
|
previousData.FileReplacements[objectKind].Add(replacement);
|
||||||
@@ -407,6 +407,22 @@ public class PlayerDataFactory
|
|||||||
previousData.HeelsData = await getHeelsOffset.ConfigureAwait(false);
|
previousData.HeelsData = await getHeelsOffset.ConfigureAwait(false);
|
||||||
_logger.LogDebug("Heels is now: {heels}", previousData.HeelsData);
|
_logger.LogDebug("Heels is now: {heels}", previousData.HeelsData);
|
||||||
|
|
||||||
|
if (previousData.FileReplacements.ContainsKey(objectKind))
|
||||||
|
{
|
||||||
|
var toCompute = previousData.FileReplacements[objectKind].Where(f => !f.IsFileSwap).ToArray();
|
||||||
|
_logger.LogDebug("Getting Hashes for {amount} Files", toCompute.Length);
|
||||||
|
var computedPaths = _fileCacheManager.GetFileCachesByPaths(toCompute.Select(c => c.ResolvedPath).ToArray());
|
||||||
|
foreach (var file in toCompute)
|
||||||
|
{
|
||||||
|
file.Hash = computedPaths[file.ResolvedPath]?.Hash ?? string.Empty;
|
||||||
|
}
|
||||||
|
var removed = previousData.FileReplacements[objectKind].RemoveWhere(f => !f.IsFileSwap && string.IsNullOrEmpty(f.Hash));
|
||||||
|
if (removed > 0)
|
||||||
|
{
|
||||||
|
_logger.LogDebug("Removed {amount} of invalid files", removed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
st.Stop();
|
st.Stop();
|
||||||
_logger.LogInformation("Building character data for {obj} took {time}ms", objectKind, TimeSpan.FromTicks(st.ElapsedTicks).TotalMilliseconds);
|
_logger.LogInformation("Building character data for {obj} took {time}ms", objectKind, TimeSpan.FromTicks(st.ElapsedTicks).TotalMilliseconds);
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class OnlinePlayerManager : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
if (visiblePlayers.Any() && _lastSentData != null)
|
if (visiblePlayers.Any() && _lastSentData != null)
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var dataToSend = await _fileTransferManager.UploadFiles(_lastSentData.DeepClone(), visiblePlayers).ConfigureAwait(false);
|
var dataToSend = await _fileTransferManager.UploadFiles(_lastSentData.DeepClone(), visiblePlayers).ConfigureAwait(false);
|
||||||
await _apiController.PushCharacterData(dataToSend, visiblePlayers).ConfigureAwait(false);
|
await _apiController.PushCharacterData(dataToSend, visiblePlayers).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -165,14 +165,6 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
|
|||||||
await _characterDataFactory.BuildCharacterData(_playerData, obj.Value, _cts.Token).ConfigureAwait(false);
|
await _characterDataFactory.BuildCharacterData(_playerData, obj.Value, _cts.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxWaitingTime = 10000;
|
|
||||||
while (!_playerData.IsReady && maxWaitingTime > 0)
|
|
||||||
{
|
|
||||||
await Task.Delay(100).ConfigureAwait(false);
|
|
||||||
maxWaitingTime -= 100;
|
|
||||||
Logger.LogTrace("Waiting for Cache to be ready");
|
|
||||||
}
|
|
||||||
|
|
||||||
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
|
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
Reference in New Issue
Block a user