From 8843add1550e7c0e40fc1ba70c5d1736ddfad140 Mon Sep 17 00:00:00 2001 From: Loporrit <141286461+loporrit@users.noreply.github.com> Date: Mon, 30 Jun 2025 20:13:30 +0000 Subject: [PATCH] Experimental option for non-async player applications --- .../Interop/Ipc/IpcCallerGlamourer.cs | 15 ++++++- .../Configurations/MareConfig.cs | 1 + .../PlayerData/Handlers/PairHandler.cs | 39 +++++++++++++------ MareSynchronos/UI/SettingsUi.cs | 8 ++++ 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/MareSynchronos/Interop/Ipc/IpcCallerGlamourer.cs b/MareSynchronos/Interop/Ipc/IpcCallerGlamourer.cs index 283a029..73b086e 100644 --- a/MareSynchronos/Interop/Ipc/IpcCallerGlamourer.cs +++ b/MareSynchronos/Interop/Ipc/IpcCallerGlamourer.cs @@ -115,15 +115,26 @@ public sealed class IpcCallerGlamourer : DisposableMediatorSubscriberBase, IIpcC } } - public async Task ApplyAllAsync(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool fireAndForget = false) + public async Task ApplyAllAsync(ILogger logger, GameObjectHandler handler, string? customization, Guid applicationId, CancellationToken token, bool allowImmediate = false) { if (!APIAvailable || string.IsNullOrEmpty(customization) || _dalamudUtil.IsZoning) return; + // Call immediately if possible + if (allowImmediate && _dalamudUtil.IsOnFrameworkThread && !await handler.IsBeingDrawnRunOnFrameworkAsync().ConfigureAwait(false)) + { + var gameObj = await _dalamudUtil.CreateGameObjectAsync(handler.Address).ConfigureAwait(false); + if (gameObj is ICharacter chara) + { + logger.LogDebug("[{appid}] Calling on IPC: GlamourerApplyAll", applicationId); + _glamourerApplyAll!.Invoke(customization, chara.ObjectIndex, LockCode); + return; + } + } + await _redrawManager.RedrawSemaphore.WaitAsync(token).ConfigureAwait(false); try { - await _redrawManager.PenumbraRedrawInternalAsync(logger, handler, applicationId, (chara) => { try diff --git a/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs b/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs index 435b8ef..8c03281 100644 --- a/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs +++ b/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs @@ -48,6 +48,7 @@ public class MareConfig : IMareConfiguration public bool ShowOfflineUsersSeparately { get; set; } = true; public bool ShowSyncshellOfflineUsersSeparately { get; set; } = true; public bool GroupUpSyncshells { get; set; } = true; + public bool SerialApplication { get; set; } = false; public bool ShowOnlineNotifications { get; set; } = false; public bool ShowOnlineNotificationsOnlyForIndividualPairs { get; set; } = true; public bool ShowOnlineNotificationsOnlyForNamedPairs { get; set; } = false; diff --git a/MareSynchronos/PlayerData/Handlers/PairHandler.cs b/MareSynchronos/PlayerData/Handlers/PairHandler.cs index 371e4ee..5213db8 100644 --- a/MareSynchronos/PlayerData/Handlers/PairHandler.cs +++ b/MareSynchronos/PlayerData/Handlers/PairHandler.cs @@ -388,19 +388,11 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase _ => throw new NotSupportedException("ObjectKind not supported: " + changes.Key) }; - try + async Task processApplication(IEnumerable changeList) { - if (handler.Address == nint.Zero) + foreach (var change in changeList) { - return; - } - - Logger.LogDebug("[{applicationId}] Applying Customization Data for {handler}", applicationId, handler); - await _dalamudUtil.WaitWhileCharacterIsDrawing(Logger, handler, applicationId, 30000, token).ConfigureAwait(false); - token.ThrowIfCancellationRequested(); - foreach (var change in changes.Value.OrderBy(p => (int)p)) - { - Logger.LogDebug("[{applicationId}] Processing {change} for {handler}", applicationId, change, handler); + Logger.LogDebug("[{applicationId}{ft}] Processing {change} for {handler}", applicationId, _dalamudUtil.IsOnFrameworkThread ? "*" : "", change, handler); switch (change) { case PlayerChanges.Customize: @@ -426,7 +418,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase case PlayerChanges.Glamourer: if (charaData.GlamourerData.TryGetValue(changes.Key, out var glamourerData)) { - await _ipcManager.Glamourer.ApplyAllAsync(Logger, handler, glamourerData, applicationId, token).ConfigureAwait(false); + await _ipcManager.Glamourer.ApplyAllAsync(Logger, handler, glamourerData, applicationId, token, allowImmediate: true).ConfigureAwait(false); } break; @@ -448,6 +440,29 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase token.ThrowIfCancellationRequested(); } } + + try + { + if (handler.Address == nint.Zero) + { + return; + } + + Logger.LogDebug("[{applicationId}] Applying Customization Data for {handler}", applicationId, handler); + await _dalamudUtil.WaitWhileCharacterIsDrawing(Logger, handler, applicationId, 30000, token).ConfigureAwait(false); + token.ThrowIfCancellationRequested(); + if (_configService.Current.SerialApplication) + { + var serialChangeList = changes.Value.Where(p => p <= PlayerChanges.ForcedRedraw).OrderBy(p => (int)p); + var asyncChangeList = changes.Value.Where(p => p > PlayerChanges.ForcedRedraw).OrderBy(p => (int)p); + await _dalamudUtil.RunOnFrameworkThread(async () => await processApplication(serialChangeList).ConfigureAwait(false)).ConfigureAwait(false); + await Task.Run(async () => await processApplication(asyncChangeList).ConfigureAwait(false), CancellationToken.None).ConfigureAwait(false); + } + else + { + _ = processApplication(changes.Value.OrderBy(p => (int)p)); + } + } finally { if (handler != _charaHandler) handler.Dispose(); diff --git a/MareSynchronos/UI/SettingsUi.cs b/MareSynchronos/UI/SettingsUi.cs index 6d405b7..2722046 100644 --- a/MareSynchronos/UI/SettingsUi.cs +++ b/MareSynchronos/UI/SettingsUi.cs @@ -635,6 +635,14 @@ public class SettingsUi : WindowMediatorSubscriberBase _configService.Save(); } + bool serializedApplications = _configService.Current.SerialApplication; + if (ImGui.Checkbox("Serialized player applications", ref serializedApplications)) + { + _configService.Current.SerialApplication = serializedApplications; + _configService.Save(); + } + _uiShared.DrawHelpText("Experimental - May reduce issues in crowded areas"); + ImGui.Separator(); _uiShared.BigText("Debug"); #if DEBUG