experimental first iteration of persistent transient resources on startup
This commit is contained in:
@@ -8,7 +8,6 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronos.FileCache;
|
||||
using MareSynchronos.Interop;
|
||||
using MareSynchronos.Managers;
|
||||
using MareSynchronos.Models;
|
||||
@@ -24,16 +23,16 @@ public class CharacterDataFactory
|
||||
{
|
||||
private readonly DalamudUtil _dalamudUtil;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly TransientResourceManager transientResourceManager;
|
||||
private readonly FileCacheManager fileDbManager;
|
||||
private readonly TransientResourceManager _transientResourceManager;
|
||||
private readonly FileReplacementFactory _fileReplacementFactory;
|
||||
|
||||
public CharacterDataFactory(DalamudUtil dalamudUtil, IpcManager ipcManager, TransientResourceManager transientResourceManager, FileCacheManager fileDbManager)
|
||||
public CharacterDataFactory(DalamudUtil dalamudUtil, IpcManager ipcManager, TransientResourceManager transientResourceManager, FileReplacementFactory fileReplacementFactory)
|
||||
{
|
||||
Logger.Verbose("Creating " + nameof(CharacterDataFactory));
|
||||
this.fileDbManager = fileDbManager;
|
||||
_dalamudUtil = dalamudUtil;
|
||||
_ipcManager = ipcManager;
|
||||
this.transientResourceManager = transientResourceManager;
|
||||
_transientResourceManager = transientResourceManager;
|
||||
_fileReplacementFactory = fileReplacementFactory;
|
||||
}
|
||||
|
||||
private unsafe bool CheckForPointer(IntPtr playerPointer)
|
||||
@@ -281,7 +280,7 @@ public class CharacterDataFactory
|
||||
|
||||
foreach (var item in previousData.FileReplacements[objectKind])
|
||||
{
|
||||
transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
_transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
}
|
||||
|
||||
if (objectKind == ObjectKind.Player)
|
||||
@@ -293,7 +292,7 @@ public class CharacterDataFactory
|
||||
{
|
||||
foreach (var item in previousData.FileReplacements[objectKind])
|
||||
{
|
||||
transientResourceManager.AddSemiTransientResource(objectKind, item);
|
||||
_transientResourceManager.AddSemiTransientResource(objectKind, item);
|
||||
}
|
||||
|
||||
previousData.FileReplacements[objectKind].Clear();
|
||||
@@ -315,9 +314,9 @@ public class CharacterDataFactory
|
||||
|
||||
private unsafe void ManageSemiTransientData(CharacterData previousData, ObjectKind objectKind, IntPtr charaPointer)
|
||||
{
|
||||
transientResourceManager.PersistTransientResources(charaPointer, objectKind, CreateFileReplacement);
|
||||
_transientResourceManager.PersistTransientResources(charaPointer, objectKind, CreateFileReplacement);
|
||||
|
||||
foreach (var item in transientResourceManager.GetSemiTransientResources(objectKind))
|
||||
foreach (var item in _transientResourceManager.GetSemiTransientResources(objectKind))
|
||||
{
|
||||
if (!previousData.FileReplacements.ContainsKey(objectKind))
|
||||
{
|
||||
@@ -331,7 +330,7 @@ public class CharacterDataFactory
|
||||
if (string.Equals(penumResolve, gamePath, StringComparison.Ordinal))
|
||||
{
|
||||
Logger.Verbose("PenumResolve was same as GamePath, not adding " + item);
|
||||
transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
_transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -354,10 +353,10 @@ public class CharacterDataFactory
|
||||
|
||||
foreach (var item in previousData.FileReplacements[objectKind])
|
||||
{
|
||||
transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
_transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
}
|
||||
|
||||
foreach (var item in transientResourceManager.GetTransientResources((IntPtr)weaponObject))
|
||||
foreach (var item in _transientResourceManager.GetTransientResources((IntPtr)weaponObject))
|
||||
{
|
||||
Logger.Verbose("Found transient weapon resource: " + item);
|
||||
AddReplacement(item, objectKind, previousData, 1, true);
|
||||
@@ -371,10 +370,10 @@ public class CharacterDataFactory
|
||||
|
||||
foreach (var item in previousData.FileReplacements[objectKind])
|
||||
{
|
||||
transientResourceManager.RemoveTransientResource((IntPtr)offHandWeapon, item);
|
||||
_transientResourceManager.RemoveTransientResource((IntPtr)offHandWeapon, item);
|
||||
}
|
||||
|
||||
foreach (var item in transientResourceManager.GetTransientResources((IntPtr)offHandWeapon))
|
||||
foreach (var item in _transientResourceManager.GetTransientResources((IntPtr)offHandWeapon))
|
||||
{
|
||||
Logger.Verbose("Found transient offhand weapon resource: " + item);
|
||||
AddReplacement(item, objectKind, previousData, 1, true);
|
||||
@@ -402,7 +401,7 @@ public class CharacterDataFactory
|
||||
|
||||
foreach (var item in previousData.FileReplacements[objectKind])
|
||||
{
|
||||
transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
_transientResourceManager.RemoveTransientResource(charaPointer, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,17 +419,14 @@ public class CharacterDataFactory
|
||||
|
||||
private FileReplacement CreateFileReplacement(string path, bool doNotReverseResolve = false)
|
||||
{
|
||||
var fileReplacement = new FileReplacement(fileDbManager);
|
||||
var fileReplacement = _fileReplacementFactory.Create();
|
||||
if (!doNotReverseResolve)
|
||||
{
|
||||
fileReplacement.GamePaths =
|
||||
_ipcManager.PenumbraReverseResolvePlayer(path).ToList();
|
||||
fileReplacement.SetResolvedPath(path);
|
||||
fileReplacement.ReverseResolvePath(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileReplacement.GamePaths = new List<string> { path };
|
||||
fileReplacement.SetResolvedPath(_ipcManager.PenumbraResolvePath(path)!);
|
||||
fileReplacement.ResolvePath(path);
|
||||
}
|
||||
|
||||
return fileReplacement;
|
||||
|
||||
22
MareSynchronos/Factories/FileReplacementFactory.cs
Normal file
22
MareSynchronos/Factories/FileReplacementFactory.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using MareSynchronos.FileCache;
|
||||
using MareSynchronos.Managers;
|
||||
using MareSynchronos.Models;
|
||||
|
||||
namespace MareSynchronos.Factories;
|
||||
|
||||
public class FileReplacementFactory
|
||||
{
|
||||
private readonly FileCacheManager fileCacheManager;
|
||||
private readonly IpcManager ipcManager;
|
||||
|
||||
public FileReplacementFactory(FileCacheManager fileCacheManager, IpcManager ipcManager)
|
||||
{
|
||||
this.fileCacheManager = fileCacheManager;
|
||||
this.ipcManager = ipcManager;
|
||||
}
|
||||
|
||||
public FileReplacement Create()
|
||||
{
|
||||
return new FileReplacement(fileCacheManager, ipcManager);
|
||||
}
|
||||
}
|
||||
@@ -10,14 +10,6 @@ using System.Text;
|
||||
|
||||
namespace MareSynchronos.FileCache;
|
||||
|
||||
|
||||
public enum FileState
|
||||
{
|
||||
Valid,
|
||||
RequireUpdate,
|
||||
RequireDeletion
|
||||
}
|
||||
|
||||
public class FileCacheManager : IDisposable
|
||||
{
|
||||
private const string PenumbraPrefix = "{penumbra}";
|
||||
@@ -227,6 +219,11 @@ public class FileCacheManager : IDisposable
|
||||
return fileCache;
|
||||
}
|
||||
|
||||
public string ResolveFileReplacement(string gamePath)
|
||||
{
|
||||
return _ipcManager.PenumbraResolvePath(gamePath);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
WriteOutFullCsv();
|
||||
11
MareSynchronos/FileCache/FileState.cs
Normal file
11
MareSynchronos/FileCache/FileState.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using MareSynchronos.Models;
|
||||
|
||||
namespace MareSynchronos.FileCache;
|
||||
|
||||
|
||||
public enum FileState
|
||||
{
|
||||
Valid,
|
||||
RequireUpdate,
|
||||
RequireDeletion
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronos.Factories;
|
||||
using MareSynchronos.Models;
|
||||
using MareSynchronos.Utils;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MareSynchronos.Managers;
|
||||
|
||||
@@ -16,20 +16,39 @@ public class TransientResourceManager : IDisposable
|
||||
{
|
||||
private readonly IpcManager manager;
|
||||
private readonly DalamudUtil dalamudUtil;
|
||||
private readonly FileReplacementFactory fileReplacementFactory;
|
||||
private readonly string configurationDirectory;
|
||||
|
||||
public event TransientResourceLoadedEvent? TransientResourceLoaded;
|
||||
public IntPtr[] PlayerRelatedPointers = Array.Empty<IntPtr>();
|
||||
private readonly string[] FileTypesToHandle = new[] { "tmb", "pap", "avfx", "atex", "sklb", "eid", "phyb", "scd", "skp" };
|
||||
private string PersistentDataCache => Path.Combine(configurationDirectory, "PersistentTransientData.lst");
|
||||
|
||||
private ConcurrentDictionary<IntPtr, HashSet<string>> TransientResources { get; } = new();
|
||||
private ConcurrentDictionary<ObjectKind, HashSet<FileReplacement>> SemiTransientResources { get; } = new();
|
||||
public TransientResourceManager(IpcManager manager, DalamudUtil dalamudUtil)
|
||||
public TransientResourceManager(IpcManager manager, DalamudUtil dalamudUtil, FileReplacementFactory fileReplacementFactory, string configurationDirectory)
|
||||
{
|
||||
manager.PenumbraResourceLoadEvent += Manager_PenumbraResourceLoadEvent;
|
||||
this.manager = manager;
|
||||
this.dalamudUtil = dalamudUtil;
|
||||
this.fileReplacementFactory = fileReplacementFactory;
|
||||
this.configurationDirectory = configurationDirectory;
|
||||
dalamudUtil.FrameworkUpdate += DalamudUtil_FrameworkUpdate;
|
||||
dalamudUtil.ClassJobChanged += DalamudUtil_ClassJobChanged;
|
||||
if (File.Exists(PersistentDataCache))
|
||||
{
|
||||
var persistentEntities = File.ReadAllLines(PersistentDataCache);
|
||||
SemiTransientResources.TryAdd(ObjectKind.Player, new HashSet<FileReplacement>());
|
||||
foreach (var line in persistentEntities)
|
||||
{
|
||||
var fileReplacement = fileReplacementFactory.Create();
|
||||
fileReplacement.ResolvePath(line);
|
||||
if (fileReplacement.HasFileReplacement)
|
||||
{
|
||||
SemiTransientResources[ObjectKind.Player].Add(fileReplacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DalamudUtil_ClassJobChanged()
|
||||
@@ -180,6 +199,10 @@ public class TransientResourceManager : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
if (objectKind == ObjectKind.Player && SemiTransientResources.TryGetValue(ObjectKind.Player, out var fileReplacements))
|
||||
{
|
||||
File.WriteAllLines(PersistentDataCache, fileReplacements.SelectMany(p => p.GamePaths).Distinct(StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
TransientResources[gameObject].Clear();
|
||||
}
|
||||
|
||||
@@ -189,6 +212,11 @@ public class TransientResourceManager : IDisposable
|
||||
manager.PenumbraResourceLoadEvent -= Manager_PenumbraResourceLoadEvent;
|
||||
dalamudUtil.ClassJobChanged -= DalamudUtil_ClassJobChanged;
|
||||
TransientResources.Clear();
|
||||
SemiTransientResources.Clear();
|
||||
if (SemiTransientResources.ContainsKey(ObjectKind.Player))
|
||||
{
|
||||
File.WriteAllLines(PersistentDataCache, SemiTransientResources[ObjectKind.Player].SelectMany(p => p.GamePaths).Distinct(StringComparer.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddSemiTransientResource(ObjectKind objectKind, FileReplacement item)
|
||||
|
||||
@@ -5,16 +5,20 @@ using System.Threading.Tasks;
|
||||
using MareSynchronos.API;
|
||||
using System.Text.RegularExpressions;
|
||||
using MareSynchronos.FileCache;
|
||||
using MareSynchronos.Managers;
|
||||
using System;
|
||||
|
||||
namespace MareSynchronos.Models;
|
||||
|
||||
public class FileReplacement
|
||||
{
|
||||
private readonly FileCacheManager fileDbManager;
|
||||
private readonly IpcManager ipcManager;
|
||||
|
||||
public FileReplacement(FileCacheManager fileDbManager)
|
||||
public FileReplacement(FileCacheManager fileDbManager, IpcManager ipcManager)
|
||||
{
|
||||
this.fileDbManager = fileDbManager;
|
||||
this.ipcManager = ipcManager;
|
||||
}
|
||||
|
||||
public bool Computed => IsFileSwap || !HasFileReplacement || !string.IsNullOrEmpty(Hash);
|
||||
@@ -29,7 +33,7 @@ public class FileReplacement
|
||||
|
||||
public string ResolvedPath { get; set; } = string.Empty;
|
||||
|
||||
public void SetResolvedPath(string path)
|
||||
private void SetResolvedPath(string path)
|
||||
{
|
||||
ResolvedPath = path.ToLowerInvariant().Replace('\\', '/');
|
||||
if (!HasFileReplacement || IsFileSwap) return;
|
||||
@@ -43,10 +47,18 @@ public class FileReplacement
|
||||
|
||||
public bool Verify()
|
||||
{
|
||||
var cache = fileDbManager.GetFileCacheByPath(ResolvedPath);
|
||||
if (cache == null) return false;
|
||||
Hash = cache.Hash;
|
||||
return true;
|
||||
if (!IsFileSwap)
|
||||
{
|
||||
var cache = fileDbManager.GetFileCacheByPath(ResolvedPath);
|
||||
if (cache == null) return false;
|
||||
Hash = cache.Hash;
|
||||
return true;
|
||||
}
|
||||
|
||||
var resolvedPath = fileDbManager.ResolveFileReplacement(GamePaths.First());
|
||||
ResolvedPath = resolvedPath.ToLowerInvariant();
|
||||
|
||||
return IsFileSwap;
|
||||
}
|
||||
|
||||
public FileReplacementDto ToFileReplacementDto()
|
||||
@@ -58,10 +70,23 @@ public class FileReplacement
|
||||
FileSwapPath = IsFileSwap ? ResolvedPath : string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder builder = new();
|
||||
builder.AppendLine($"Modded: {HasFileReplacement} - {string.Join(",", GamePaths)} => {ResolvedPath}");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
internal void ReverseResolvePath(string path)
|
||||
{
|
||||
GamePaths = ipcManager.PenumbraReverseResolvePlayer(path).ToList();
|
||||
SetResolvedPath(path);
|
||||
}
|
||||
|
||||
internal void ResolvePath(string path)
|
||||
{
|
||||
GamePaths = new List<string> { path };
|
||||
SetResolvedPath(ipcManager.PenumbraResolvePath(path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,11 @@ public sealed class Plugin : IDalamudPlugin
|
||||
private OnlinePlayerManager? _characterCacheManager;
|
||||
private readonly DownloadUi _downloadUi;
|
||||
private readonly FileDialogManager _fileDialogManager;
|
||||
private readonly FileCacheManager _fileDbManager;
|
||||
private readonly FileCacheManager _fileCacheManager;
|
||||
private readonly CompactUi _compactUi;
|
||||
private readonly UiShared _uiSharedComponent;
|
||||
private readonly Dalamud.Localization _localization;
|
||||
private readonly FileReplacementFactory _fileReplacementFactory;
|
||||
|
||||
|
||||
public Plugin(DalamudPluginInterface pluginInterface, CommandManager commandManager,
|
||||
@@ -62,9 +63,10 @@ public sealed class Plugin : IDalamudPlugin
|
||||
|
||||
_ipcManager = new IpcManager(_pluginInterface, _dalamudUtil);
|
||||
_fileDialogManager = new FileDialogManager();
|
||||
_fileDbManager = new FileCacheManager(_ipcManager, _configuration, _pluginInterface.ConfigDirectory.FullName);
|
||||
_apiController = new ApiController(_configuration, _dalamudUtil, _fileDbManager);
|
||||
_periodicFileScanner = new PeriodicFileScanner(_ipcManager, _configuration, _fileDbManager, _apiController, _dalamudUtil);
|
||||
_fileCacheManager = new FileCacheManager(_ipcManager, _configuration, _pluginInterface.ConfigDirectory.FullName);
|
||||
_apiController = new ApiController(_configuration, _dalamudUtil, _fileCacheManager);
|
||||
_periodicFileScanner = new PeriodicFileScanner(_ipcManager, _configuration, _fileCacheManager, _apiController, _dalamudUtil);
|
||||
_fileReplacementFactory = new FileReplacementFactory(_fileCacheManager, _ipcManager);
|
||||
|
||||
_uiSharedComponent =
|
||||
new UiShared(_ipcManager, _apiController, _periodicFileScanner, _fileDialogManager, _configuration, _dalamudUtil, _pluginInterface, _localization);
|
||||
@@ -118,7 +120,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
_compactUi?.Dispose();
|
||||
|
||||
_periodicFileScanner?.Dispose();
|
||||
_fileDbManager?.Dispose();
|
||||
_fileCacheManager?.Dispose();
|
||||
_playerManager?.Dispose();
|
||||
_characterCacheManager?.Dispose();
|
||||
_ipcManager?.Dispose();
|
||||
@@ -180,13 +182,13 @@ public sealed class Plugin : IDalamudPlugin
|
||||
|
||||
try
|
||||
{
|
||||
_transientResourceManager = new TransientResourceManager(_ipcManager, _dalamudUtil);
|
||||
_transientResourceManager = new TransientResourceManager(_ipcManager, _dalamudUtil, _fileReplacementFactory, _pluginInterface.ConfigDirectory.FullName);
|
||||
var characterCacheFactory =
|
||||
new CharacterDataFactory(_dalamudUtil, _ipcManager, _transientResourceManager, _fileDbManager);
|
||||
new CharacterDataFactory(_dalamudUtil, _ipcManager, _transientResourceManager, _fileReplacementFactory);
|
||||
_playerManager = new PlayerManager(_apiController, _ipcManager,
|
||||
characterCacheFactory, _dalamudUtil, _transientResourceManager, _periodicFileScanner);
|
||||
_characterCacheManager = new OnlinePlayerManager(_apiController,
|
||||
_dalamudUtil, _ipcManager, _playerManager, _fileDbManager);
|
||||
_dalamudUtil, _ipcManager, _playerManager, _fileCacheManager);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user