diff --git a/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs b/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs index 670cfed..c578f5e 100644 --- a/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs +++ b/MareSynchronos/PlayerData/Factories/PlayerDataFactory.cs @@ -183,8 +183,6 @@ public class PlayerDataFactory if (string.IsNullOrEmpty(texPath)) continue; - _logger.LogTrace("Checking File Replacement for Texture {file}", texPath); - AddReplacementsFromTexture(texPath, forwardResolve, reverseResolve); } @@ -234,7 +232,7 @@ public class PlayerDataFactory { if (string.IsNullOrEmpty(texPath)) return; - _logger.LogTrace("Checking file Replacement for texture {path}", texPath); + _logger.LogTrace("Checking File Replacement for Texture {path}", texPath); if (doNotReverseResolve) forwardResolve.Add(texPath); diff --git a/MareSynchronos/PlayerData/Handlers/PairHandler.cs b/MareSynchronos/PlayerData/Handlers/PairHandler.cs index c08836c..b879aa5 100644 --- a/MareSynchronos/PlayerData/Handlers/PairHandler.cs +++ b/MareSynchronos/PlayerData/Handlers/PairHandler.cs @@ -59,6 +59,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase Mediator.Subscribe(this, (_) => FrameworkUpdate()); Mediator.Subscribe(this, (_) => { + MediatorUnsubscribeFromCharacterChanged(); _charaHandler?.Invalidate(); IsVisible = false; }); @@ -89,7 +90,9 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase { Logger.LogDebug("[BASE-{appBase}] Received data but player was in invalid state, charaHandlerIsNull: {charaIsNull}, playerPointerIsNull: {ptrIsNull}", applicationBase, _charaHandler == null, PlayerCharacter == IntPtr.Zero); - _forceApplyMods = _forceApplyMods || (PlayerCharacter == IntPtr.Zero && _cachedData == null); + var hasDiffMods = characterData.CheckUpdatedData(applicationBase, _cachedData, Logger, + this, forceApplyCustomization, false).Any(p => p.Value.Contains(PlayerChanges.ModManip) || p.Value.Contains(PlayerChanges.ModFiles)); + _forceApplyMods = hasDiffMods || _forceApplyMods || (PlayerCharacter == IntPtr.Zero && _cachedData == null); _cachedData = characterData; Logger.LogDebug("[BASE-{appBase}] Setting data: {hash}, forceApplyMods: {force}", applicationBase, _cachedData.DataHash.Value, _forceApplyMods); return; @@ -100,14 +103,11 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase Logger.LogDebug("[BASE-{appbase}] Applying data for {player}, forceApplyCustomization: {forced}, forceApplyMods: {forceMods}", applicationBase, this, forceApplyCustomization, _forceApplyMods); Logger.LogDebug("[BASE-{appbase}] Hash for data is {newHash}, current cache hash is {oldHash}", applicationBase, characterData.DataHash.Value, _cachedData?.DataHash.Value ?? "NODATA"); - if (!_ipcManager.CheckPenumbraApi()) return; - if (!_ipcManager.CheckGlamourerApi()) return; - if (string.Equals(characterData.DataHash.Value, _cachedData?.DataHash.Value ?? string.Empty, StringComparison.Ordinal) && !forceApplyCustomization) return; - if (_dalamudUtil.IsInCutscene || _dalamudUtil.IsInGpose) + if (_dalamudUtil.IsInCutscene || _dalamudUtil.IsInGpose || !_ipcManager.CheckPenumbraApi() || !_ipcManager.CheckGlamourerApi()) { - Logger.LogInformation("[BASE-{appbase}] Application of data for {player} while in cutscene/gpose, returning", applicationBase, this); + Logger.LogInformation("[BASE-{appbase}] Application of data for {player} while in cutscene/gpose or Penumbra/Glamourer unavailable, returning", applicationBase, this); return; } @@ -396,12 +396,12 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase if (_charaHandler?.Address != nint.Zero && !IsVisible) { + Guid appData = Guid.NewGuid(); IsVisible = true; Mediator.Publish(new PairHandlerVisibleMessage(this)); if (_cachedData != null) { - Guid appData = Guid.NewGuid(); - Logger.LogTrace("{this} visibility changed, now: {visi}, cached data exists => application {app}", this, IsVisible, appData); + Logger.LogTrace("[BASE-{appBase}] {this} visibility changed, now: {visi}, cached data exists", appData, this, IsVisible); Task.Run(async () => { @@ -413,11 +413,14 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase { Logger.LogTrace("{this} visibility changed, now: {visi}, no cached data exists", this, IsVisible); } + + MediatorSubscribeToCharacterChanged(); } else if (_charaHandler?.Address == nint.Zero && IsVisible) { IsVisible = false; _charaHandler?.Invalidate(); + MediatorUnsubscribeFromCharacterChanged(); Logger.LogTrace("{this} visibility changed, now: {visi}", this, IsVisible); } } @@ -430,18 +433,6 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult(); _lastGlamourerData = _originalGlamourerData; Mediator.Subscribe(this, IpcManagerOnPenumbraRedrawEvent); - Mediator.Subscribe(this, async (msg) => - { - if (msg.GameObjectHandler == _charaHandler && (_applicationTask?.IsCompleted ?? true)) - { - Logger.LogTrace("Saving new Glamourer Data for {this}", this); - _lastGlamourerData = await _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false); - if (_cachedData != null) - { - ApplyCharacterData(Guid.NewGuid(), _cachedData!, true); - } - } - }); Mediator.Subscribe(this, async (_) => { if (string.IsNullOrEmpty(_cachedData?.HonorificData)) return; @@ -476,6 +467,33 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase }, token); } + private void MediatorSubscribeToCharacterChanged() + { + Mediator.Subscribe(this, (msg) => + { + if (msg.GameObjectHandler == _charaHandler && (_applicationTask?.IsCompleted ?? true)) + { + Guid appBase = Guid.NewGuid(); + var newGlamData = _ipcManager.GlamourerGetCharacterCustomizationAsync(PlayerCharacter).ConfigureAwait(false).GetAwaiter().GetResult(); + if (!string.Equals(_lastGlamourerData, newGlamData, StringComparison.OrdinalIgnoreCase)) + { + Logger.LogTrace("[BASE-{appBase}] Saving new Glamourer Data for {this}", appBase, this); + + _lastGlamourerData = newGlamData; + if (_cachedData != null) + { + ApplyCharacterData(appBase, _cachedData!, true); + } + } + } + }); + } + + private void MediatorUnsubscribeFromCharacterChanged() + { + Mediator.Unsubscribe(this); + } + private async Task RevertCustomizationDataAsync(ObjectKind objectKind, string name, Guid applicationId) { nint address = _dalamudUtil.GetPlayerCharacterFromCachedTableByIdent(OnlineUser.Ident); diff --git a/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs b/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs index d7bd52f..d3adbc8 100644 --- a/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs +++ b/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs @@ -23,6 +23,7 @@ public class ServerConfigurationManager _serverTagConfig = serverTagConfig; _notesConfig = notesConfig; _dalamudUtil = dalamudUtil; + EnsureMainExists(); } public string CurrentApiUrl => CurrentServer.ServerUri; @@ -96,11 +97,7 @@ public class ServerConfigurationManager catch { _configService.Current.CurrentServer = 0; - if (!string.Equals(_configService.Current.ServerStorage[0].ServerUri, ApiController.MainServer, StringComparison.OrdinalIgnoreCase)) - { - _configService.Current.ServerStorage.Insert(0, new ServerStorage() { ServerUri = ApiController.MainServiceUri, ServerName = ApiController.MainServer }); - } - Save(); + EnsureMainExists(); return CurrentServer!; } } @@ -341,6 +338,15 @@ public class ServerConfigurationManager return _serverTagConfig.Current.ServerTagStorage[CurrentApiUrl]; } + private void EnsureMainExists() + { + if (_configService.Current.ServerStorage.Count == 0 || !string.Equals(_configService.Current.ServerStorage[0].ServerUri, ApiController.MainServiceUri, StringComparison.OrdinalIgnoreCase)) + { + _configService.Current.ServerStorage.Insert(0, new ServerStorage() { ServerUri = ApiController.MainServiceUri, ServerName = ApiController.MainServer }); + } + Save(); + } + private void TryCreateCurrentNotesStorage() { if (!_notesConfig.Current.ServerNotes.ContainsKey(CurrentApiUrl))