add moodles integration (temporary)

This commit is contained in:
rootdarkarchon
2024-02-29 13:04:12 +01:00
parent 8bfbf4b582
commit e94a2a7565
13 changed files with 183 additions and 26 deletions

View File

@@ -0,0 +1,104 @@
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using MareSynchronos.Services;
using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging;
namespace MareSynchronos.Interop.Ipc;
public sealed class IpcCallerMoodles : IIpcCaller
{
private readonly ICallGateSubscriber<int> _moodlesApiVersion;
private readonly ICallGateSubscriber<PlayerCharacter, object> _moodlesOnChange;
private readonly ICallGateSubscriber<nint, string> _moodlesGetStatus;
private readonly ICallGateSubscriber<nint, string, object> _moodlesSetStatus;
private readonly ICallGateSubscriber<nint, object> _moodlesRevertStatus;
private readonly ILogger<IpcCallerMoodles> _logger;
private readonly DalamudUtilService _dalamudUtil;
private readonly MareMediator _mareMediator;
public IpcCallerMoodles(ILogger<IpcCallerMoodles> logger, DalamudPluginInterface pi, DalamudUtilService dalamudUtil,
MareMediator mareMediator)
{
_logger = logger;
_dalamudUtil = dalamudUtil;
_mareMediator = mareMediator;
_moodlesApiVersion = pi.GetIpcSubscriber<int>("Moodles.Version");
_moodlesOnChange = pi.GetIpcSubscriber<PlayerCharacter, object>("Moodles.StatusManagerModified");
_moodlesGetStatus = pi.GetIpcSubscriber<nint, string>("Moodles.GetStatusManagerByPtr");
_moodlesSetStatus = pi.GetIpcSubscriber<nint, string, object>("Moodles.SetStatusManagerByPtr");
_moodlesRevertStatus = pi.GetIpcSubscriber<nint, object>("Moodles.ClearStatusManagerByPtr");
_moodlesOnChange.Subscribe(OnMoodlesChange);
CheckAPI();
}
private void OnMoodlesChange(PlayerCharacter character)
{
_mareMediator.Publish(new MoodlesMessage(character.Address));
}
public bool APIAvailable { get; private set; } = false;
public void CheckAPI()
{
try
{
APIAvailable = _moodlesApiVersion.InvokeFunc() == 1;
}
catch
{
APIAvailable = false;
}
}
public void Dispose()
{
_moodlesOnChange.Unsubscribe(OnMoodlesChange);
}
public async Task<string?> GetStatusAsync(nint address)
{
if (!APIAvailable) return null;
try
{
return await _dalamudUtil.RunOnFrameworkThread(() => _moodlesGetStatus.InvokeFunc(address)).ConfigureAwait(false);
}
catch (Exception e)
{
_logger.LogWarning(e, "Could not Get Moodles Status");
return null;
}
}
public async Task SetStatusAsync(nint pointer, string status)
{
if (!APIAvailable) return;
try
{
await _dalamudUtil.RunOnFrameworkThread(() => _moodlesSetStatus.InvokeAction(pointer, status)).ConfigureAwait(false);
}
catch (Exception e)
{
_logger.LogWarning(e, "Could not Set Moodles Status");
}
}
public async Task RevertStatusAsync(nint pointer)
{
if (!APIAvailable) return;
try
{
await _dalamudUtil.RunOnFrameworkThread(() => _moodlesRevertStatus.InvokeAction(pointer)).ConfigureAwait(false);
}
catch (Exception e)
{
_logger.LogWarning(e, "Could not Set Moodles Status");
}
}
}

View File

@@ -7,13 +7,14 @@ public sealed partial class IpcManager : DisposableMediatorSubscriberBase
{ {
public IpcManager(ILogger<IpcManager> logger, MareMediator mediator, public IpcManager(ILogger<IpcManager> logger, MareMediator mediator,
IpcCallerPenumbra penumbraIpc, IpcCallerGlamourer glamourerIpc, IpcCallerCustomize customizeIpc, IpcCallerHeels heelsIpc, IpcCallerPenumbra penumbraIpc, IpcCallerGlamourer glamourerIpc, IpcCallerCustomize customizeIpc, IpcCallerHeels heelsIpc,
IpcCallerHonorific honorificIpc) : base(logger, mediator) IpcCallerHonorific honorificIpc, IpcCallerMoodles moodlesIpc) : base(logger, mediator)
{ {
CustomizePlus = customizeIpc; CustomizePlus = customizeIpc;
Heels = heelsIpc; Heels = heelsIpc;
Glamourer = glamourerIpc; Glamourer = glamourerIpc;
Penumbra = penumbraIpc; Penumbra = penumbraIpc;
Honorific = honorificIpc; Honorific = honorificIpc;
Moodles = moodlesIpc;
if (Initialized) if (Initialized)
{ {
@@ -39,6 +40,7 @@ public sealed partial class IpcManager : DisposableMediatorSubscriberBase
public IpcCallerHeels Heels { get; init; } public IpcCallerHeels Heels { get; init; }
public IpcCallerGlamourer Glamourer { get; } public IpcCallerGlamourer Glamourer { get; }
public IpcCallerPenumbra Penumbra { get; } public IpcCallerPenumbra Penumbra { get; }
public IpcCallerMoodles Moodles { get; }
private void PeriodicApiStateCheck() private void PeriodicApiStateCheck()
{ {
@@ -48,5 +50,6 @@ public sealed partial class IpcManager : DisposableMediatorSubscriberBase
Heels.CheckAPI(); Heels.CheckAPI();
CustomizePlus.CheckAPI(); CustomizePlus.CheckAPI();
Honorific.CheckAPI(); Honorific.CheckAPI();
Moodles.CheckAPI();
} }
} }

View File

@@ -2,8 +2,6 @@
using MareSynchronos.API.Data.Enum; using MareSynchronos.API.Data.Enum;
using System.Text;
namespace MareSynchronos.PlayerData.Data; namespace MareSynchronos.PlayerData.Data;
public class CharacterData public class CharacterData
@@ -16,6 +14,7 @@ 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 string ManipulationString { get; set; } = string.Empty; public string ManipulationString { get; set; } = string.Empty;
public string MoodlesData { get; set; } = string.Empty;
public API.Data.CharacterData ToAPI() public API.Data.CharacterData ToAPI()
{ {
@@ -44,17 +43,8 @@ public class CharacterData
ManipulationData = ManipulationString, ManipulationData = ManipulationString,
HeelsData = HeelsData, HeelsData = HeelsData,
CustomizePlusData = CustomizePlusScale.ToDictionary(d => d.Key, d => d.Value), CustomizePlusData = CustomizePlusScale.ToDictionary(d => d.Key, d => d.Value),
HonorificData = HonorificData HonorificData = HonorificData,
PalettePlusData = MoodlesData
}; };
} }
public override string ToString()
{
StringBuilder stringBuilder = new();
foreach (var fileReplacement in FileReplacements.SelectMany(k => k.Value).OrderBy(a => a.GamePaths.First(), StringComparer.Ordinal))
{
stringBuilder.Append(fileReplacement).AppendLine();
}
return stringBuilder.ToString();
}
} }

View File

@@ -8,5 +8,6 @@ public enum PlayerChanges
Customize = 4, Customize = 4,
Heels = 5, Heels = 5,
Honorific = 7, Honorific = 7,
ForcedRedraw = 8, Moodles = 8,
ForcedRedraw = 9,
} }

View File

@@ -207,6 +207,10 @@ public class PlayerDataFactory
_logger.LogDebug("Honorific is now: {data}", previousData.HonorificData); _logger.LogDebug("Honorific is now: {data}", previousData.HonorificData);
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 (objectKind == ObjectKind.Player)
{
previousData.MoodlesData = await _ipcManager.Moodles.GetStatusAsync(playerRelatedObject.Address).ConfigureAwait(false) ?? string.Empty;
}
if (previousData.FileReplacements.TryGetValue(objectKind, out HashSet<FileReplacement>? fileReplacements)) if (previousData.FileReplacements.TryGetValue(objectKind, out HashSet<FileReplacement>? fileReplacements))
{ {

View File

@@ -334,6 +334,10 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
} }
break; break;
case PlayerChanges.Moodles:
await _ipcManager.Moodles.SetStatusAsync(handler.Address, charaData.PalettePlusData).ConfigureAwait(false);
break;
case PlayerChanges.ForcedRedraw: case PlayerChanges.ForcedRedraw:
await _ipcManager.Penumbra.RedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false); await _ipcManager.Penumbra.RedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false);
break; break;
@@ -555,6 +559,8 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
tempHandler.CompareNameAndThrow(name); tempHandler.CompareNameAndThrow(name);
Logger.LogDebug("[{applicationId}] Restoring Honorific for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name); Logger.LogDebug("[{applicationId}] Restoring Honorific for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name);
await _ipcManager.Honorific.ClearTitleAsync(address).ConfigureAwait(false); await _ipcManager.Honorific.ClearTitleAsync(address).ConfigureAwait(false);
Logger.LogDebug("[{applicationId}] Restoring Moodles for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name);
await _ipcManager.Moodles.RevertStatusAsync(address).ConfigureAwait(false);
} }
else if (objectKind == ObjectKind.MinionOrMount) else if (objectKind == ObjectKind.MinionOrMount)
{ {

View File

@@ -5,4 +5,5 @@ public record OptionalPluginWarning
public bool ShownHeelsWarning { get; set; } = false; public bool ShownHeelsWarning { get; set; } = false;
public bool ShownCustomizePlusWarning { get; set; } = false; public bool ShownCustomizePlusWarning { get; set; } = false;
public bool ShownHonorificWarning { get; set; } = false; public bool ShownHonorificWarning { get; set; } = false;
public bool ShownMoodlesWarning { get; set; } = false;
} }

View File

@@ -20,6 +20,7 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
private readonly Dictionary<ObjectKind, GameObjectHandler> _playerRelatedObjects = []; private readonly Dictionary<ObjectKind, GameObjectHandler> _playerRelatedObjects = [];
private Task? _cacheCreationTask; private Task? _cacheCreationTask;
private CancellationTokenSource _honorificCts = new(); private CancellationTokenSource _honorificCts = new();
private CancellationTokenSource _moodlesCts = new();
private bool _isZoning = false; private bool _isZoning = false;
private readonly Dictionary<ObjectKind, CancellationTokenSource> _glamourerCts = new(); private readonly Dictionary<ObjectKind, CancellationTokenSource> _glamourerCts = new();
@@ -108,6 +109,16 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
HonorificChanged(); HonorificChanged();
} }
}); });
Mediator.Subscribe<MoodlesMessage>(this, (msg) =>
{
if (_isZoning) return;
var changedType = _playerRelatedObjects.FirstOrDefault(f => f.Value.Address == msg.Address);
if (!default(KeyValuePair<ObjectKind, GameObjectHandler>).Equals(changedType) && changedType.Key == ObjectKind.Player)
{
Logger.LogDebug("Received Moodles change, updating player");
MoodlesChanged();
}
});
Mediator.Subscribe<PenumbraModSettingChangedMessage>(this, async (msg) => Mediator.Subscribe<PenumbraModSettingChangedMessage>(this, async (msg) =>
{ {
Logger.LogDebug("Received Penumbra Mod settings change, updating player"); Logger.LogDebug("Received Penumbra Mod settings change, updating player");
@@ -162,6 +173,21 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
await AddPlayerCacheToCreate().ConfigureAwait(false); await AddPlayerCacheToCreate().ConfigureAwait(false);
}, token); }, token);
} }
private void MoodlesChanged()
{
_moodlesCts?.Cancel();
_moodlesCts?.Dispose();
_moodlesCts = new();
var token = _moodlesCts.Token;
_ = Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(2), token).ConfigureAwait(false);
await AddPlayerCacheToCreate().ConfigureAwait(false);
}, token);
}
private void ProcessCacheCreation() private void ProcessCacheCreation()
{ {
if (_isZoning) return; if (_isZoning) return;

View File

@@ -101,9 +101,12 @@ public sealed class Plugin : IDalamudPlugin
s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<MareMediator>())); s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<MareMediator>()));
collection.AddSingleton((s) => new IpcCallerHonorific(s.GetRequiredService<ILogger<IpcCallerHonorific>>(), pluginInterface, collection.AddSingleton((s) => new IpcCallerHonorific(s.GetRequiredService<ILogger<IpcCallerHonorific>>(), pluginInterface,
s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<MareMediator>())); s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<MareMediator>()));
collection.AddSingleton((s) => new IpcCallerMoodles(s.GetRequiredService<ILogger<IpcCallerMoodles>>(), pluginInterface,
s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<MareMediator>()));
collection.AddSingleton((s) => new IpcManager(s.GetRequiredService<ILogger<IpcManager>>(), collection.AddSingleton((s) => new IpcManager(s.GetRequiredService<ILogger<IpcManager>>(),
s.GetRequiredService<MareMediator>(), s.GetRequiredService<IpcCallerPenumbra>(), s.GetRequiredService<IpcCallerGlamourer>(), s.GetRequiredService<MareMediator>(), s.GetRequiredService<IpcCallerPenumbra>(), s.GetRequiredService<IpcCallerGlamourer>(),
s.GetRequiredService<IpcCallerCustomize>(), s.GetRequiredService<IpcCallerHeels>(), s.GetRequiredService<IpcCallerHonorific>())); s.GetRequiredService<IpcCallerCustomize>(), s.GetRequiredService<IpcCallerHeels>(), s.GetRequiredService<IpcCallerHonorific>(),
s.GetRequiredService<IpcCallerMoodles>()));
collection.AddSingleton((s) => new MareConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new MareConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new ServerConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new ServerConfigService(pluginInterface.ConfigDirectory.FullName));

View File

@@ -40,6 +40,7 @@ public record HeelsOffsetMessage : MessageBase;
public record PenumbraResourceLoadMessage(IntPtr GameObject, string GamePath, string FilePath) : SameThreadMessage; public record PenumbraResourceLoadMessage(IntPtr GameObject, string GamePath, string FilePath) : SameThreadMessage;
public record CustomizePlusMessage(string ProfileName) : MessageBase; public record CustomizePlusMessage(string ProfileName) : MessageBase;
public record HonorificMessage(string NewHonorificTitle) : MessageBase; public record HonorificMessage(string NewHonorificTitle) : MessageBase;
public record MoodlesMessage(IntPtr Address) : MessageBase;
public record HonorificReadyMessage : MessageBase; public record HonorificReadyMessage : MessageBase;
public record PlayerChangedMessage(CharacterData Data) : MessageBase; public record PlayerChangedMessage(CharacterData Data) : MessageBase;
public record CharacterChangedMessage(GameObjectHandler GameObjectHandler) : MessageBase; public record CharacterChangedMessage(GameObjectHandler GameObjectHandler) : MessageBase;

View File

@@ -52,6 +52,12 @@ public class PluginWarningNotificationService
warning.ShownHonorificWarning = true; warning.ShownHonorificWarning = true;
} }
if (changes.Contains(PlayerChanges.Moodles) && !warning.ShownMoodlesWarning && !_ipcManager.Moodles.APIAvailable)
{
missingPluginsForData.Add("Moodles");
warning.ShownMoodlesWarning = true;
}
if (missingPluginsForData.Any()) if (missingPluginsForData.Any())
{ {
_mediator.Publish(new NotificationMessage("Missing plugins for " + playerName, _mediator.Publish(new NotificationMessage("Missing plugins for " + playerName,

View File

@@ -65,6 +65,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
private bool _heelsExists = false; private bool _heelsExists = false;
private bool _honorificExists = false; private bool _honorificExists = false;
private bool _moodlesExists = false;
private bool _isDirectoryWritable = false; private bool _isDirectoryWritable = false;
private bool _isPenumbraDirectory = false; private bool _isPenumbraDirectory = false;
@@ -103,6 +104,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
_customizePlusExists = _ipcManager.CustomizePlus.APIAvailable; _customizePlusExists = _ipcManager.CustomizePlus.APIAvailable;
_heelsExists = _ipcManager.Heels.APIAvailable; _heelsExists = _ipcManager.Heels.APIAvailable;
_honorificExists = _ipcManager.Honorific.APIAvailable; _honorificExists = _ipcManager.Honorific.APIAvailable;
_moodlesExists = _ipcManager.Moodles.APIAvailable;
}); });
} }
@@ -712,11 +714,6 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public bool DrawOtherPluginState() public bool DrawOtherPluginState()
{ {
var penumbraColor = _penumbraExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var glamourerColor = _glamourerExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var heelsColor = _heelsExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var customizeColor = _customizePlusExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var honorificColor = _honorificExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var check = FontAwesomeIcon.Check.ToIconString(); var check = FontAwesomeIcon.Check.ToIconString();
var cross = FontAwesomeIcon.SquareXmark.ToIconString(); var cross = FontAwesomeIcon.SquareXmark.ToIconString();
ImGui.TextUnformatted("Mandatory Plugins:"); ImGui.TextUnformatted("Mandatory Plugins:");
@@ -724,7 +721,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextUnformatted("Penumbra"); ImGui.TextUnformatted("Penumbra");
ImGui.SameLine(); ImGui.SameLine();
FontText(_penumbraExists ? check : cross, UiBuilder.IconFont, penumbraColor); FontText(_penumbraExists ? check : cross, UiBuilder.IconFont, GetBoolColor(_penumbraExists));
ImGui.SameLine(); ImGui.SameLine();
AttachToolTip($"Penumbra is " + (_penumbraExists ? "available and up to date." : "unavailable or not up to date.")); AttachToolTip($"Penumbra is " + (_penumbraExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.Spacing(); ImGui.Spacing();
@@ -732,7 +729,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextUnformatted("Glamourer"); ImGui.TextUnformatted("Glamourer");
ImGui.SameLine(); ImGui.SameLine();
FontText(_glamourerExists ? check : cross, UiBuilder.IconFont, glamourerColor); FontText(_glamourerExists ? check : cross, UiBuilder.IconFont, GetBoolColor(_glamourerExists));
ImGui.SameLine(); ImGui.SameLine();
AttachToolTip($"Glamourer is " + (_glamourerExists ? "available and up to date." : "unavailable or not up to date.")); AttachToolTip($"Glamourer is " + (_glamourerExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.Spacing(); ImGui.Spacing();
@@ -741,7 +738,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextUnformatted("SimpleHeels"); ImGui.TextUnformatted("SimpleHeels");
ImGui.SameLine(); ImGui.SameLine();
FontText(_heelsExists ? check : cross, UiBuilder.IconFont, heelsColor); FontText(_heelsExists ? check : cross, UiBuilder.IconFont, GetBoolColor(_heelsExists));
ImGui.SameLine(); ImGui.SameLine();
AttachToolTip($"SimpleHeels is " + (_heelsExists ? "available and up to date." : "unavailable or not up to date.")); AttachToolTip($"SimpleHeels is " + (_heelsExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.Spacing(); ImGui.Spacing();
@@ -749,7 +746,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextUnformatted("Customize+"); ImGui.TextUnformatted("Customize+");
ImGui.SameLine(); ImGui.SameLine();
FontText(_customizePlusExists ? check : cross, UiBuilder.IconFont, customizeColor); FontText(_customizePlusExists ? check : cross, UiBuilder.IconFont, GetBoolColor(_customizePlusExists));
ImGui.SameLine(); ImGui.SameLine();
AttachToolTip($"Customize+ is " + (_customizePlusExists ? "available and up to date." : "unavailable or not up to date.")); AttachToolTip($"Customize+ is " + (_customizePlusExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.Spacing(); ImGui.Spacing();
@@ -757,11 +754,19 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextUnformatted("Honorific"); ImGui.TextUnformatted("Honorific");
ImGui.SameLine(); ImGui.SameLine();
FontText(_honorificExists ? check : cross, UiBuilder.IconFont, honorificColor); FontText(_honorificExists ? check : cross, UiBuilder.IconFont, GetBoolColor(_honorificExists));
ImGui.SameLine(); ImGui.SameLine();
AttachToolTip($"Honorific is " + (_honorificExists ? "available and up to date." : "unavailable or not up to date.")); AttachToolTip($"Honorific is " + (_honorificExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.Spacing(); ImGui.Spacing();
ImGui.SameLine();
ImGui.TextUnformatted("Moodles");
ImGui.SameLine();
FontText(_moodlesExists ? check : cross, UiBuilder.IconFont, GetBoolColor(_moodlesExists));
ImGui.SameLine();
AttachToolTip($"Moodles is " + (_moodlesExists ? "available and up to date." : "unavailable or not up to date."));
ImGui.Spacing();
if (!_penumbraExists || !_glamourerExists) if (!_penumbraExists || !_glamourerExists)
{ {
ImGui.TextColored(ImGuiColors.DalamudRed, "You need to install both Penumbra and Glamourer and keep them up to date to use Mare Synchronos."); ImGui.TextColored(ImGuiColors.DalamudRed, "You need to install both Penumbra and Glamourer and keep them up to date to use Mare Synchronos.");

View File

@@ -180,6 +180,13 @@ public static class VariousExtensions
logger.LogDebug("[BASE-{appBase}] Updating {object}/{kind} (Diff honorific data) => {change}", applicationBase, cachedPlayer, objectKind, PlayerChanges.Honorific); logger.LogDebug("[BASE-{appBase}] Updating {object}/{kind} (Diff honorific data) => {change}", applicationBase, cachedPlayer, objectKind, PlayerChanges.Honorific);
charaDataToUpdate[objectKind].Add(PlayerChanges.Honorific); charaDataToUpdate[objectKind].Add(PlayerChanges.Honorific);
} }
bool moodlesDataDifferent = !string.Equals(oldData.PalettePlusData, newData.PalettePlusData, StringComparison.Ordinal);
if (moodlesDataDifferent || (forceApplyCustomization && !string.IsNullOrEmpty(newData.PalettePlusData)))
{
logger.LogDebug("[BASE-{appBase}] Updating {object}/{kind} (Diff moodles data) => {change}", applicationBase, cachedPlayer, objectKind, PlayerChanges.Moodles);
charaDataToUpdate[objectKind].Add(PlayerChanges.Moodles);
}
} }
foreach (KeyValuePair<ObjectKind, HashSet<PlayerChanges>> data in charaDataToUpdate.ToList()) foreach (KeyValuePair<ObjectKind, HashSet<PlayerChanges>> data in charaDataToUpdate.ToList())