From f69effb8a3a9451c35bdf96a68a10144df2c43fa Mon Sep 17 00:00:00 2001 From: azyges Date: Sun, 28 Dec 2025 10:48:40 +0900 Subject: [PATCH] fix syncing.. --- .../FileCache/TransientResourceManager.cs | 13 +++- .../Interop/Ipc/IpcCallerPenumbra.cs | 6 ++ .../Interop/Ipc/Penumbra/PenumbraResource.cs | 16 ++++- .../PlayerData/Factories/PlayerDataFactory.cs | 66 ++++++++++++++++++- 4 files changed, 95 insertions(+), 6 deletions(-) diff --git a/LightlessSync/FileCache/TransientResourceManager.cs b/LightlessSync/FileCache/TransientResourceManager.cs index 3518018..c2531db 100644 --- a/LightlessSync/FileCache/TransientResourceManager.cs +++ b/LightlessSync/FileCache/TransientResourceManager.cs @@ -352,6 +352,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase private void RefreshPlayerRelatedAddressMap() { _playerRelatedByAddress.Clear(); + var updatedFrameAddresses = new ConcurrentDictionary(); lock (_playerRelatedLock) { foreach (var handler in _playerRelatedPointers) @@ -360,9 +361,12 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase if (address != nint.Zero) { _playerRelatedByAddress[address] = handler; + updatedFrameAddresses[address] = handler.ObjectKind; } } } + + _cachedFrameAddresses = updatedFrameAddresses; } private void HandleActorTracked(ActorObjectService.ActorDescriptor descriptor) @@ -498,7 +502,14 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase var gameObjectAddress = msg.GameObject; if (!_cachedFrameAddresses.TryGetValue(gameObjectAddress, out var objectKind)) { - return; + if (_actorObjectService.TryGetOwnedKind(gameObjectAddress, out var ownedKind)) + { + objectKind = ownedKind; + } + else + { + return; + } } var gamePath = NormalizeGamePath(msg.GamePath); diff --git a/LightlessSync/Interop/Ipc/IpcCallerPenumbra.cs b/LightlessSync/Interop/Ipc/IpcCallerPenumbra.cs index a30d05b..e077eab 100644 --- a/LightlessSync/Interop/Ipc/IpcCallerPenumbra.cs +++ b/LightlessSync/Interop/Ipc/IpcCallerPenumbra.cs @@ -95,6 +95,12 @@ public sealed class IpcCallerPenumbra : IpcServiceBase public Task<(string[] forward, string[][] reverse)> ResolvePathsAsync(string[] forward, string[] reverse) => _resources.ResolvePathsAsync(forward, reverse); + public string ResolveGameObjectPath(string gamePath, int objectIndex) + => _resources.ResolveGameObjectPath(gamePath, objectIndex); + + public string[] ReverseResolveGameObjectPath(string moddedPath, int objectIndex) + => _resources.ReverseResolveGameObjectPath(moddedPath, objectIndex); + public Task RedrawAsync(ILogger logger, GameObjectHandler handler, Guid applicationId, CancellationToken token) => _redraw.RedrawAsync(logger, handler, applicationId, token); diff --git a/LightlessSync/Interop/Ipc/Penumbra/PenumbraResource.cs b/LightlessSync/Interop/Ipc/Penumbra/PenumbraResource.cs index 2dd5676..73da7cc 100644 --- a/LightlessSync/Interop/Ipc/Penumbra/PenumbraResource.cs +++ b/LightlessSync/Interop/Ipc/Penumbra/PenumbraResource.cs @@ -14,6 +14,8 @@ public sealed class PenumbraResource : PenumbraBase { private readonly ActorObjectService _actorObjectService; private readonly GetGameObjectResourcePaths _gameObjectResourcePaths; + private readonly ResolveGameObjectPath _resolveGameObjectPath; + private readonly ReverseResolveGameObjectPath _reverseResolveGameObjectPath; private readonly ResolvePlayerPathsAsync _resolvePlayerPaths; private readonly GetPlayerMetaManipulations _getPlayerMetaManipulations; private readonly EventSubscriber _gameObjectResourcePathResolved; @@ -27,6 +29,8 @@ public sealed class PenumbraResource : PenumbraBase { _actorObjectService = actorObjectService; _gameObjectResourcePaths = new GetGameObjectResourcePaths(pluginInterface); + _resolveGameObjectPath = new ResolveGameObjectPath(pluginInterface); + _reverseResolveGameObjectPath = new ReverseResolveGameObjectPath(pluginInterface); _resolvePlayerPaths = new ResolvePlayerPathsAsync(pluginInterface); _getPlayerMetaManipulations = new GetPlayerMetaManipulations(pluginInterface); _gameObjectResourcePathResolved = GameObjectResourcePathResolved.Subscriber(pluginInterface, HandleResourceLoaded); @@ -67,7 +71,13 @@ public sealed class PenumbraResource : PenumbraBase return await _resolvePlayerPaths.Invoke(forwardPaths, reversePaths).ConfigureAwait(false); } - private void HandleResourceLoaded(nint ptr, string resolvedPath, string gamePath) + public string ResolveGameObjectPath(string gamePath, int gameObjectIndex) + => IsAvailable ? _resolveGameObjectPath.Invoke(gamePath, gameObjectIndex) : gamePath; + + public string[] ReverseResolveGameObjectPath(string moddedPath, int gameObjectIndex) + => IsAvailable ? _reverseResolveGameObjectPath.Invoke(moddedPath, gameObjectIndex) : Array.Empty(); + + private void HandleResourceLoaded(nint ptr, string gamePath, string resolvedPath) { if (ptr == nint.Zero) { @@ -79,12 +89,12 @@ public sealed class PenumbraResource : PenumbraBase return; } - if (string.Compare(resolvedPath, gamePath, StringComparison.OrdinalIgnoreCase) == 0) + if (string.Compare(gamePath, resolvedPath, StringComparison.OrdinalIgnoreCase) == 0) { return; } - Mediator.Publish(new PenumbraResourceLoadMessage(ptr, resolvedPath, gamePath)); + Mediator.Publish(new PenumbraResourceLoadMessage(ptr, gamePath, resolvedPath)); } protected override void HandleStateChange(IpcConnectionState previous, IpcConnectionState current) diff --git a/LightlessSync/PlayerData/Factories/PlayerDataFactory.cs b/LightlessSync/PlayerData/Factories/PlayerDataFactory.cs index 39aa6c8..9ecfcc3 100644 --- a/LightlessSync/PlayerData/Factories/PlayerDataFactory.cs +++ b/LightlessSync/PlayerData/Factories/PlayerDataFactory.cs @@ -194,7 +194,7 @@ public class PlayerDataFactory // get all remaining paths and resolve them var transientPaths = ManageSemiTransientData(objectKind); - var resolvedTransientPaths = await GetFileReplacementsFromPaths(transientPaths, new HashSet(StringComparer.Ordinal)).ConfigureAwait(false); + var resolvedTransientPaths = await GetFileReplacementsFromPaths(playerRelatedObject, transientPaths, new HashSet(StringComparer.Ordinal)).ConfigureAwait(false); if (logDebug) { @@ -373,11 +373,73 @@ public class PlayerDataFactory } } - private async Task> GetFileReplacementsFromPaths(HashSet forwardResolve, HashSet reverseResolve) + private async Task> GetFileReplacementsFromPaths(GameObjectHandler handler, HashSet forwardResolve, HashSet reverseResolve) { var forwardPaths = forwardResolve.ToArray(); var reversePaths = reverseResolve.ToArray(); Dictionary> resolvedPaths = new(StringComparer.Ordinal); + if (handler.ObjectKind != ObjectKind.Player) + { + var (objectIndex, forwardResolved, reverseResolved) = await _dalamudUtil.RunOnFrameworkThread(() => + { + var idx = handler.GetGameObject()?.ObjectIndex; + if (!idx.HasValue) + { + return ((int?)null, Array.Empty(), Array.Empty()); + } + + var resolvedForward = new string[forwardPaths.Length]; + for (int i = 0; i < forwardPaths.Length; i++) + { + resolvedForward[i] = _ipcManager.Penumbra.ResolveGameObjectPath(forwardPaths[i], idx.Value); + } + + var resolvedReverse = new string[reversePaths.Length][]; + for (int i = 0; i < reversePaths.Length; i++) + { + resolvedReverse[i] = _ipcManager.Penumbra.ReverseResolveGameObjectPath(reversePaths[i], idx.Value); + } + + return (idx, resolvedForward, resolvedReverse); + }).ConfigureAwait(false); + + if (objectIndex.HasValue) + { + for (int i = 0; i < forwardPaths.Length; i++) + { + var filePath = forwardResolved[i]?.ToLowerInvariant(); + if (string.IsNullOrEmpty(filePath)) + { + continue; + } + + if (resolvedPaths.TryGetValue(filePath, out var list)) + { + list.Add(forwardPaths[i].ToLowerInvariant()); + } + else + { + resolvedPaths[filePath] = [forwardPaths[i].ToLowerInvariant()]; + } + } + + for (int i = 0; i < reversePaths.Length; i++) + { + var filePath = reversePaths[i].ToLowerInvariant(); + if (resolvedPaths.TryGetValue(filePath, out var list)) + { + list.AddRange(reverseResolved[i].Select(c => c.ToLowerInvariant())); + } + else + { + resolvedPaths[filePath] = new List(reverseResolved[i].Select(c => c.ToLowerInvariant()).ToList()); + } + } + + return resolvedPaths.ToDictionary(k => k.Key, k => k.Value.ToArray(), StringComparer.OrdinalIgnoreCase).AsReadOnly(); + } + } + var (forward, reverse) = await _ipcManager.Penumbra.ResolvePathsAsync(forwardPaths, reversePaths).ConfigureAwait(false); for (int i = 0; i < forwardPaths.Length; i++) {