Heels and C+ updates (#54)

* add heels and customize plus multi data

* adjust customize plus api calls

* adjustments to ipc for customize

---------

Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
This commit is contained in:
rootdarkarchon
2023-07-17 08:57:56 +02:00
committed by GitHub
parent 5543c7c7ad
commit 08a35c9152
11 changed files with 116 additions and 125 deletions

Submodule MareAPI updated: 51645cbc79...a422dc8798

View File

@@ -2,7 +2,6 @@
using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc;
using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Action = System.Action;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Text; using System.Text;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
@@ -12,15 +11,16 @@ using Microsoft.Extensions.Logging;
using MareSynchronos.PlayerData.Handlers; using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using MareSynchronos.Services; using MareSynchronos.Services;
using Dalamud.Utility;
namespace MareSynchronos.Interop; namespace MareSynchronos.Interop;
public sealed class IpcManager : DisposableMediatorSubscriberBase public sealed class IpcManager : DisposableMediatorSubscriberBase
{ {
private readonly ICallGateSubscriber<string> _customizePlusApiVersion; private readonly ICallGateSubscriber<(int, int)> _customizePlusApiVersion;
private readonly ICallGateSubscriber<string, string> _customizePlusGetBodyScale; private readonly ICallGateSubscriber<Character?, string?> _customizePlusGetBodyScale;
private readonly ICallGateSubscriber<string?, object> _customizePlusOnScaleUpdate; private readonly ICallGateSubscriber<string?, string?, object> _customizePlusOnScaleUpdate;
private readonly ICallGateSubscriber<Character?, object> _customizePlusRevert; private readonly ICallGateSubscriber<Character?, object> _customizePlusRevertCharacter;
private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter; private readonly ICallGateSubscriber<string, Character?, object> _customizePlusSetBodyScaleToCharacter;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly ICallGateSubscriber<int> _glamourerApiVersion; private readonly ICallGateSubscriber<int> _glamourerApiVersion;
@@ -28,11 +28,10 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyCustomization; private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyCustomization;
private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyEquipment; private readonly ICallGateSubscriber<string, GameObject?, object>? _glamourerApplyOnlyEquipment;
private readonly ICallGateSubscriber<GameObject?, string>? _glamourerGetAllCustomization; private readonly ICallGateSubscriber<GameObject?, string>? _glamourerGetAllCustomization;
private readonly ConcurrentQueue<Action> _gposeActionQueue = new(); private readonly ICallGateSubscriber<(int, int)> _heelsGetApiVersion;
private readonly ICallGateSubscriber<string> _heelsGetApiVersion; private readonly ICallGateSubscriber<string> _heelsGetOffset;
private readonly ICallGateSubscriber<float> _heelsGetOffset; private readonly ICallGateSubscriber<string, object?> _heelsOffsetUpdate;
private readonly ICallGateSubscriber<float, object?> _heelsOffsetUpdate; private readonly ICallGateSubscriber<GameObject, string, object?> _heelsRegisterPlayer;
private readonly ICallGateSubscriber<GameObject, float, object?> _heelsRegisterPlayer;
private readonly ICallGateSubscriber<GameObject, object?> _heelsUnregisterPlayer; private readonly ICallGateSubscriber<GameObject, object?> _heelsUnregisterPlayer;
private readonly ICallGateSubscriber<(uint major, uint minor)> _honorificApiVersion; private readonly ICallGateSubscriber<(uint major, uint minor)> _honorificApiVersion;
private readonly ICallGateSubscriber<Character, object> _honorificClearCharacterTitle; private readonly ICallGateSubscriber<Character, object> _honorificClearCharacterTitle;
@@ -41,7 +40,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private readonly ICallGateSubscriber<string, object> _honorificLocalCharacterTitleChanged; private readonly ICallGateSubscriber<string, object> _honorificLocalCharacterTitleChanged;
private readonly ICallGateSubscriber<object> _honorificReady; private readonly ICallGateSubscriber<object> _honorificReady;
private readonly ICallGateSubscriber<Character, string, object> _honorificSetCharacterTitle; private readonly ICallGateSubscriber<Character, string, object> _honorificSetCharacterTitle;
private readonly ConcurrentQueue<Action> _normalQueue = new();
private readonly ICallGateSubscriber<string> _palettePlusApiVersion; private readonly ICallGateSubscriber<string> _palettePlusApiVersion;
private readonly ICallGateSubscriber<Character, string> _palettePlusBuildCharaPalette; private readonly ICallGateSubscriber<Character, string> _palettePlusBuildCharaPalette;
private readonly ICallGateSubscriber<Character, string, object> _palettePlusPaletteChanged; private readonly ICallGateSubscriber<Character, string, object> _palettePlusPaletteChanged;
@@ -71,7 +69,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private bool _glamourerAvailable = false; private bool _glamourerAvailable = false;
private bool _heelsAvailable = false; private bool _heelsAvailable = false;
private bool _honorificAvailable = false; private bool _honorificAvailable = false;
private bool _inGposeQueueMode = false;
private bool _palettePlusAvailable = false; private bool _palettePlusAvailable = false;
private bool _penumbraAvailable = false; private bool _penumbraAvailable = false;
private bool _shownGlamourerUnavailable = false; private bool _shownGlamourerUnavailable = false;
@@ -110,19 +107,19 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
_glamourerApplyOnlyCustomization = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyCustomizationToCharacter"); _glamourerApplyOnlyCustomization = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyCustomizationToCharacter");
_glamourerApplyOnlyEquipment = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyEquipmentToCharacter"); _glamourerApplyOnlyEquipment = pi.GetIpcSubscriber<string, GameObject?, object>("Glamourer.ApplyOnlyEquipmentToCharacter");
_heelsGetApiVersion = pi.GetIpcSubscriber<string>("HeelsPlugin.ApiVersion"); _heelsGetApiVersion = pi.GetIpcSubscriber<(int, int)>("SimpleHeels.ApiVersion");
_heelsGetOffset = pi.GetIpcSubscriber<float>("HeelsPlugin.GetOffset"); _heelsGetOffset = pi.GetIpcSubscriber<string>("SimpleHeels.GetLocalPlayer");
_heelsRegisterPlayer = pi.GetIpcSubscriber<GameObject, float, object?>("HeelsPlugin.RegisterPlayer"); _heelsRegisterPlayer = pi.GetIpcSubscriber<GameObject, string, object?>("SimpleHeels.RegisterPlayer");
_heelsUnregisterPlayer = pi.GetIpcSubscriber<GameObject, object?>("HeelsPlugin.UnregisterPlayer"); _heelsUnregisterPlayer = pi.GetIpcSubscriber<GameObject, object?>("SimpleHeels.UnregisterPlayer");
_heelsOffsetUpdate = pi.GetIpcSubscriber<float, object?>("HeelsPlugin.OffsetChanged"); _heelsOffsetUpdate = pi.GetIpcSubscriber<string, object?>("SimpleHeels.LocalChanged");
_heelsOffsetUpdate.Subscribe(HeelsOffsetChange); _heelsOffsetUpdate.Subscribe(HeelsOffsetChange);
_customizePlusApiVersion = pi.GetIpcSubscriber<string>("CustomizePlus.GetApiVersion"); _customizePlusApiVersion = pi.GetIpcSubscriber<(int, int)>("CustomizePlus.GetApiVersion");
_customizePlusGetBodyScale = pi.GetIpcSubscriber<string, string>("CustomizePlus.GetBodyScale"); _customizePlusGetBodyScale = pi.GetIpcSubscriber<Character?, string?>("CustomizePlus.GetProfileFromCharacter");
_customizePlusRevert = pi.GetIpcSubscriber<Character?, object>("CustomizePlus.RevertCharacter"); _customizePlusRevertCharacter = pi.GetIpcSubscriber<Character?, object>("CustomizePlus.RevertCharacter");
_customizePlusSetBodyScaleToCharacter = pi.GetIpcSubscriber<string, Character?, object>("CustomizePlus.SetBodyScaleToCharacter"); _customizePlusSetBodyScaleToCharacter = pi.GetIpcSubscriber<string, Character?, object>("CustomizePlus.SetProfileToCharacter");
_customizePlusOnScaleUpdate = pi.GetIpcSubscriber<string?, object>("CustomizePlus.OnScaleUpdate"); _customizePlusOnScaleUpdate = pi.GetIpcSubscriber<string?, string?, object>("CustomizePlus.OnProfileUpdate");
_customizePlusOnScaleUpdate.Subscribe(OnCustomizePlusScaleChange); _customizePlusOnScaleUpdate.Subscribe(OnCustomizePlusScaleChange);
@@ -151,9 +148,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
Mediator.Publish(new PenumbraInitializedMessage()); Mediator.Publish(new PenumbraInitializedMessage());
} }
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => HandleActionQueue());
Mediator.Subscribe<CutsceneFrameworkUpdateMessage>(this, (_) => HandleGposeActionQueue());
Mediator.Subscribe<ZoneSwitchEndMessage>(this, (_) => ClearActionQueue());
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => PeriodicApiStateCheck()); Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => PeriodicApiStateCheck());
PeriodicApiStateCheck(); PeriodicApiStateCheck();
@@ -161,7 +155,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
public bool Initialized => CheckPenumbraApiInternal() && CheckGlamourerApiInternal(); public bool Initialized => CheckPenumbraApiInternal() && CheckGlamourerApiInternal();
public string? PenumbraModDirectory { get; private set; } public string? PenumbraModDirectory { get; private set; }
private ConcurrentQueue<Action> ActionQueue => _inGposeQueueMode ? _gposeActionQueue : _normalQueue;
public bool CheckCustomizePlusApi() => _customizePlusAvailable; public bool CheckCustomizePlusApi() => _customizePlusAvailable;
@@ -184,14 +177,14 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
if (gameObj is Character c) if (gameObj is Character c)
{ {
Logger.LogTrace("CustomizePlus reverting for {chara}", c.Address.ToString("X")); Logger.LogTrace("CustomizePlus reverting for {chara}", c.Address.ToString("X"));
_customizePlusRevert!.InvokeAction(c); _customizePlusRevertCharacter!.InvokeAction(c);
} }
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task CustomizePlusSetBodyScaleAsync(IntPtr character, string scale) public async Task CustomizePlusSetBodyScaleAsync(IntPtr character, string scale)
{ {
if (!CheckCustomizePlusApi() || string.IsNullOrEmpty(scale)) return; if (!CheckCustomizePlusApi()) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
var gameObj = _dalamudUtil.CreateGameObject(character); var gameObj = _dalamudUtil.CreateGameObject(character);
@@ -199,22 +192,38 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
{ {
string decodedScale = Encoding.UTF8.GetString(Convert.FromBase64String(scale)); string decodedScale = Encoding.UTF8.GetString(Convert.FromBase64String(scale));
Logger.LogTrace("CustomizePlus applying for {chara}", c.Address.ToString("X")); Logger.LogTrace("CustomizePlus applying for {chara}", c.Address.ToString("X"));
_customizePlusSetBodyScaleToCharacter!.InvokeAction(decodedScale, c); if (scale.IsNullOrEmpty())
{
_customizePlusRevertCharacter!.InvokeAction(c);
}
else
{
_customizePlusSetBodyScaleToCharacter!.InvokeAction(decodedScale, c);
}
} }
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task<string> GetCustomizePlusScaleAsync() public async Task<string> GetCustomizePlusScaleAsync(IntPtr character)
{ {
if (!CheckCustomizePlusApi()) return string.Empty; if (!CheckCustomizePlusApi()) return string.Empty;
var scale = await _dalamudUtil.RunOnFrameworkThread(() => _customizePlusGetBodyScale.InvokeFunc(_dalamudUtil.GetPlayerName())).ConfigureAwait(false); var scale = await _dalamudUtil.RunOnFrameworkThread(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj is Character c)
{
return _customizePlusGetBodyScale.InvokeFunc(c);
}
return string.Empty;
}).ConfigureAwait(false);
if (string.IsNullOrEmpty(scale)) return string.Empty; if (string.IsNullOrEmpty(scale)) return string.Empty;
return Convert.ToBase64String(Encoding.UTF8.GetBytes(scale)); return Convert.ToBase64String(Encoding.UTF8.GetBytes(scale));
} }
public async Task<float> GetHeelsOffsetAsync() public async Task<string> GetHeelsOffsetAsync()
{ {
if (!CheckHeelsApi()) return 0.0f; if (!CheckHeelsApi()) return string.Empty;
return await _dalamudUtil.RunOnFrameworkThread(_heelsGetOffset.InvokeFunc).ConfigureAwait(false); return await _dalamudUtil.RunOnFrameworkThread(_heelsGetOffset.InvokeFunc).ConfigureAwait(false);
} }
@@ -300,7 +309,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public async Task HeelsSetOffsetForPlayerAsync(IntPtr character, float offset) public async Task HeelsSetOffsetForPlayerAsync(IntPtr character, string data)
{ {
if (!CheckHeelsApi()) return; if (!CheckHeelsApi()) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
@@ -309,7 +318,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
if (gameObj != null) if (gameObj != null)
{ {
Logger.LogTrace("Applying Heels data to {chara}", character.ToString("X")); Logger.LogTrace("Applying Heels data to {chara}", character.ToString("X"));
_heelsRegisterPlayer.InvokeAction(gameObj, offset); _heelsRegisterPlayer.InvokeAction(gameObj, data);
} }
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
@@ -503,37 +512,12 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public void ToggleGposeQueueMode(bool on)
{
_inGposeQueueMode = on;
}
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
base.Dispose(disposing); base.Dispose(disposing);
_disposalCts.Cancel(); _disposalCts.Cancel();
int totalSleepTime = 0;
while (!ActionQueue.IsEmpty && totalSleepTime < 2000)
{
Logger.LogTrace("Waiting for actionqueue to clear...");
PeriodicApiStateCheck();
if (CheckPenumbraApi())
{
HandleActionQueue();
}
Thread.Sleep(16);
totalSleepTime += 16;
}
if (totalSleepTime >= 2000)
{
Logger.LogTrace("Action queue clear or not, disposing");
}
ActionQueue.Clear();
_penumbraModSettingChanged.Dispose(); _penumbraModSettingChanged.Dispose();
_penumbraGameObjectResourcePathResolved.Dispose(); _penumbraGameObjectResourcePathResolved.Dispose();
_penumbraDispose.Dispose(); _penumbraDispose.Dispose();
@@ -551,7 +535,9 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
{ {
try try
{ {
return string.Equals(_customizePlusApiVersion.InvokeFunc(), "2.0", StringComparison.Ordinal); var version = _customizePlusApiVersion.InvokeFunc();
if (version.Item1 == 3 && version.Item2 >= 0) return true;
return false;
} }
catch catch
{ {
@@ -586,7 +572,7 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
{ {
try try
{ {
return string.Equals(_heelsGetApiVersion.InvokeFunc(), "1.0.1", StringComparison.Ordinal); return _heelsGetApiVersion.InvokeFunc() is { Item1: 1, Item2: >= 0 };
} }
catch catch
{ {
@@ -641,46 +627,20 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
} }
} }
private void ClearActionQueue()
{
ActionQueue.Clear();
_gposeActionQueue.Clear();
}
private string? GetPenumbraModDirectoryInternal() private string? GetPenumbraModDirectoryInternal()
{ {
if (!CheckPenumbraApi()) return null; if (!CheckPenumbraApi()) return null;
return _penumbraResolveModDir!.Invoke().ToLowerInvariant(); return _penumbraResolveModDir!.Invoke().ToLowerInvariant();
} }
private void HandleActionQueue() private void HeelsOffsetChange(string offset)
{
if (ActionQueue.TryDequeue(out var action))
{
if (action == null) return;
Logger.LogDebug("Execution action in queue: {method}", action.Method);
action();
}
}
private void HandleGposeActionQueue()
{
if (_gposeActionQueue.TryDequeue(out var action))
{
if (action == null) return;
Logger.LogDebug("Execution action in gpose queue: {method}", action.Method);
action();
}
}
private void HeelsOffsetChange(float offset)
{ {
Mediator.Publish(new HeelsOffsetMessage()); Mediator.Publish(new HeelsOffsetMessage());
} }
private void OnCustomizePlusScaleChange(string? scale) private void OnCustomizePlusScaleChange(string? profileName, string? scale)
{ {
Mediator.Publish(new CustomizePlusMessage()); Mediator.Publish(new CustomizePlusMessage(profileName ?? string.Empty));
} }
private void OnHonorificDisposing() private void OnHonorificDisposing()
@@ -710,7 +670,6 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
_disposalCts.Cancel(); _disposalCts.Cancel();
_disposalCts.Dispose(); _disposalCts.Dispose();
Mediator.Publish(new PenumbraDisposedMessage()); Mediator.Publish(new PenumbraDisposedMessage());
ActionQueue.Clear();
_disposalCts = new(); _disposalCts = new();
} }

View File

@@ -6,17 +6,17 @@ namespace MareSynchronos.PlayerData.Data;
public class CharacterData public class CharacterData
{ {
public string CustomizePlusScale { get; set; } = string.Empty; public Dictionary<ObjectKind, string> CustomizePlusScale { get; set; } = new();
public Dictionary<ObjectKind, HashSet<FileReplacement>> FileReplacements { get; set; } = new(); public Dictionary<ObjectKind, HashSet<FileReplacement>> FileReplacements { get; set; } = new();
public Dictionary<ObjectKind, string> GlamourerString { get; set; } = new(); public Dictionary<ObjectKind, string> GlamourerString { get; set; } = new();
public float HeelsOffset { get; set; } = 0f; public string HeelsData { get; set; } = string.Empty;
public string HonorificData { get; set; } = string.Empty;
public bool IsReady => FileReplacements.SelectMany(k => k.Value).All(f => f.Computed); public bool IsReady => FileReplacements.SelectMany(k => k.Value).All(f => f.Computed);
public string ManipulationString { get; set; } = string.Empty; public string ManipulationString { get; set; } = string.Empty;
public string PalettePlusPalette { get; set; } = string.Empty; public string PalettePlusPalette { get; set; } = string.Empty;
public string HonorificData { get; set; } = string.Empty;
public API.Data.CharacterData ToAPI() public API.Data.CharacterData ToAPI()
{ {
@@ -40,8 +40,8 @@ public class CharacterData
FileReplacements = fileReplacements, FileReplacements = fileReplacements,
GlamourerData = GlamourerString.ToDictionary(d => d.Key, d => d.Value), GlamourerData = GlamourerString.ToDictionary(d => d.Key, d => d.Value),
ManipulationData = ManipulationString, ManipulationData = ManipulationString,
HeelsOffset = HeelsOffset, HeelsData = HeelsData,
CustomizePlusData = CustomizePlusScale, CustomizePlusData = CustomizePlusScale.ToDictionary(d => d.Key, d => d.Value),
PalettePlusData = PalettePlusPalette, PalettePlusData = PalettePlusPalette,
HonorificData = HonorificData HonorificData = HonorificData
}; };

View File

@@ -26,7 +26,8 @@ public record MareCharaFileData
GlamourerData = glamourerData; GlamourerData = glamourerData;
} }
CustomizePlusData = dto.CustomizePlusData; dto.CustomizePlusData.TryGetValue(ObjectKind.Player, out var customizePlusData);
CustomizePlusData = customizePlusData ?? string.Empty;
PalettePlusData = dto.PalettePlusData; PalettePlusData = dto.PalettePlusData;
ManipulationData = dto.ManipulationData; ManipulationData = dto.ManipulationData;

View File

@@ -64,7 +64,6 @@ public class MareCharaFileManager
} }
} }
var applicationId = Guid.NewGuid(); var applicationId = Guid.NewGuid();
_ipcManager.ToggleGposeQueueMode(on: true);
await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false); await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
var coll = await _ipcManager.PenumbraCreateTemporaryCollectionAsync(_logger, charaTarget.Name.TextValue).ConfigureAwait(false); var coll = await _ipcManager.PenumbraCreateTemporaryCollectionAsync(_logger, charaTarget.Name.TextValue).ConfigureAwait(false);
await _ipcManager.PenumbraAssignTemporaryCollectionAsync(_logger, coll, charaTarget.ObjectTableIndex()!.Value).ConfigureAwait(false); await _ipcManager.PenumbraAssignTemporaryCollectionAsync(_logger, coll, charaTarget.ObjectTableIndex()!.Value).ConfigureAwait(false);
@@ -74,7 +73,22 @@ public class MareCharaFileManager
await _ipcManager.GlamourerApplyAllAsync(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false); await _ipcManager.GlamourerApplyAllAsync(_logger, tempHandler, LoadedCharaFile.CharaFileData.GlamourerData, applicationId, disposeCts.Token).ConfigureAwait(false);
_dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000); _dalamudUtil.WaitWhileGposeCharacterIsDrawing(charaTarget.Address, 30000);
await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, coll).ConfigureAwait(false); await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, coll).ConfigureAwait(false);
_ipcManager.ToggleGposeQueueMode(on: false); if (!string.IsNullOrEmpty(LoadedCharaFile.CharaFileData.CustomizePlusData))
{
await _ipcManager.CustomizePlusSetBodyScaleAsync(tempHandler.Address, LoadedCharaFile.CharaFileData.CustomizePlusData).ConfigureAwait(false);
}
else
{
await _ipcManager.CustomizePlusRevertAsync(tempHandler.Address).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(LoadedCharaFile.CharaFileData.PalettePlusData))
{
await _ipcManager.PalettePlusSetPaletteAsync(tempHandler.Address, LoadedCharaFile.CharaFileData.PalettePlusData).ConfigureAwait(false);
}
else
{
await _ipcManager.PalettePlusRemovePaletteAsync(tempHandler.Address).ConfigureAwait(false);
}
} }
} }
finally finally

View File

@@ -73,6 +73,7 @@ public class PlayerDataFactory
_logger.LogTrace("Pointer was zero for {objectKind}", playerRelatedObject.ObjectKind); _logger.LogTrace("Pointer was zero for {objectKind}", playerRelatedObject.ObjectKind);
previousData.FileReplacements.Remove(playerRelatedObject.ObjectKind); previousData.FileReplacements.Remove(playerRelatedObject.ObjectKind);
previousData.GlamourerString.Remove(playerRelatedObject.ObjectKind); previousData.GlamourerString.Remove(playerRelatedObject.ObjectKind);
previousData.CustomizePlusScale.Remove(playerRelatedObject.ObjectKind);
return; return;
} }
@@ -373,20 +374,20 @@ public class PlayerDataFactory
// gather up data from ipc // gather up data from ipc
previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations(); previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations();
Task<float> getHeelsOffset = _ipcManager.GetHeelsOffsetAsync(); Task<string> getHeelsOffset = _ipcManager.GetHeelsOffsetAsync();
Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(playerRelatedObject.Address); Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(playerRelatedObject.Address);
Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScaleAsync(); Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScaleAsync(playerRelatedObject.Address);
Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPaletteAsync(); Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPaletteAsync();
previousData.GlamourerString[playerRelatedObject.ObjectKind] = await getGlamourerData.ConfigureAwait(false); previousData.GlamourerString[playerRelatedObject.ObjectKind] = await getGlamourerData.ConfigureAwait(false);
_logger.LogDebug("Glamourer is now: {data}", previousData.GlamourerString[playerRelatedObject.ObjectKind]); _logger.LogDebug("Glamourer is now: {data}", previousData.GlamourerString[playerRelatedObject.ObjectKind]);
previousData.CustomizePlusScale = await getCustomizeData.ConfigureAwait(false); previousData.CustomizePlusScale[playerRelatedObject.ObjectKind] = await getCustomizeData.ConfigureAwait(false);
_logger.LogDebug("Customize is now: {data}", previousData.CustomizePlusScale); _logger.LogDebug("Customize is now: {data}", previousData.CustomizePlusScale[playerRelatedObject.ObjectKind]);
previousData.PalettePlusPalette = await getPalettePlusData.ConfigureAwait(false); previousData.PalettePlusPalette = await getPalettePlusData.ConfigureAwait(false);
_logger.LogDebug("Palette is now: {data}", previousData.PalettePlusPalette); _logger.LogDebug("Palette is now: {data}", previousData.PalettePlusPalette);
previousData.HonorificData = _ipcManager.HonorificGetTitle(); previousData.HonorificData = _ipcManager.HonorificGetTitle();
_logger.LogDebug("Honorific is now: {data}", previousData.HonorificData); _logger.LogDebug("Honorific is now: {data}", previousData.HonorificData);
previousData.HeelsOffset = await getHeelsOffset.ConfigureAwait(false); previousData.HeelsData = await getHeelsOffset.ConfigureAwait(false);
_logger.LogDebug("Heels is now: {heels}", previousData.HeelsOffset); _logger.LogDebug("Heels is now: {heels}", previousData.HeelsData);
st.Stop(); st.Stop();
_logger.LogInformation("Building character data for {obj} took {time}ms", objectKind, TimeSpan.FromTicks(st.ElapsedTicks).TotalMilliseconds); _logger.LogInformation("Building character data for {obj} took {time}ms", objectKind, TimeSpan.FromTicks(st.ElapsedTicks).TotalMilliseconds);

View File

@@ -229,11 +229,14 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
break; break;
case PlayerChanges.Customize: case PlayerChanges.Customize:
await _ipcManager.CustomizePlusSetBodyScaleAsync(handler.Address, charaData.CustomizePlusData).ConfigureAwait(false); if (charaData.CustomizePlusData.TryGetValue(changes.Key, out var customizePlusData))
{
await _ipcManager.CustomizePlusSetBodyScaleAsync(handler.Address, customizePlusData).ConfigureAwait(false);
}
break; break;
case PlayerChanges.Heels: case PlayerChanges.Heels:
await _ipcManager.HeelsSetOffsetForPlayerAsync(handler.Address, charaData.HeelsOffset).ConfigureAwait(false); await _ipcManager.HeelsSetOffsetForPlayerAsync(handler.Address, charaData.HeelsData).ConfigureAwait(false);
break; break;
case PlayerChanges.Honorific: case PlayerChanges.Honorific:

View File

@@ -5,6 +5,7 @@ using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.Services; using MareSynchronos.Services;
using MareSynchronos.Services.Mediator; using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Linq;
namespace MareSynchronos.PlayerData.Services; namespace MareSynchronos.PlayerData.Services;
@@ -53,15 +54,20 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
Logger.LogTrace("Clearing cache for {obj}", msg.ObjectToCreateFor); Logger.LogTrace("Clearing cache for {obj}", msg.ObjectToCreateFor);
_playerData.FileReplacements.Remove(msg.ObjectToCreateFor.ObjectKind); _playerData.FileReplacements.Remove(msg.ObjectToCreateFor.ObjectKind);
_playerData.GlamourerString.Remove(msg.ObjectToCreateFor.ObjectKind); _playerData.GlamourerString.Remove(msg.ObjectToCreateFor.ObjectKind);
_playerData.CustomizePlusScale.Remove(msg.ObjectToCreateFor.ObjectKind);
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI())); Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
}); });
}); });
Mediator.Subscribe<CustomizePlusMessage>(this, async (_) => Mediator.Subscribe<CustomizePlusMessage>(this, async (msg) =>
{ {
if (_isZoning) return; if (_isZoning) return;
Logger.LogDebug("Received CustomizePlus change, updating player"); foreach (var item in _playerRelatedObjects
await AddPlayerCacheToCreate().ConfigureAwait(false); .Where(item => string.Equals(item.Value.Name, msg.ProfileName, StringComparison.Ordinal)).Select(k => k.Key))
{
Logger.LogDebug("Received CustomizePlus change, updating {obj}", item);
await AddPlayerCacheToCreate(item).ConfigureAwait(false);
}
}); });
Mediator.Subscribe<HeelsOffsetMessage>(this, async (_) => Mediator.Subscribe<HeelsOffsetMessage>(this, async (_) =>
{ {
@@ -104,10 +110,10 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
_cts.Dispose(); _cts.Dispose();
} }
private async Task AddPlayerCacheToCreate() private async Task AddPlayerCacheToCreate(ObjectKind kind = ObjectKind.Player)
{ {
await _cacheCreateLock.WaitAsync().ConfigureAwait(false); await _cacheCreateLock.WaitAsync().ConfigureAwait(false);
_cachesToCreate[ObjectKind.Player] = _playerRelatedObjects[ObjectKind.Player]; _cachesToCreate[kind] = _playerRelatedObjects[kind];
_cacheCreateLock.Release(); _cacheCreateLock.Release();
} }

View File

@@ -34,7 +34,7 @@ public record PenumbraDisposedMessage : MessageBase;
public record PenumbraRedrawMessage(IntPtr Address, int ObjTblIdx, bool WasRequested) : SameThreadMessage; public record PenumbraRedrawMessage(IntPtr Address, int ObjTblIdx, bool WasRequested) : SameThreadMessage;
public record HeelsOffsetMessage : MessageBase; 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 : MessageBase; public record CustomizePlusMessage(string ProfileName) : MessageBase;
public record PalettePlusMessage(Character Character) : MessageBase; public record PalettePlusMessage(Character Character) : MessageBase;
public record HonorificMessage(string NewHonorificTitle) : MessageBase; public record HonorificMessage(string NewHonorificTitle) : MessageBase;
public record HonorificReadyMessage : MessageBase; public record HonorificReadyMessage : MessageBase;

View File

@@ -52,7 +52,10 @@ public sealed class DtrEntry : IDisposable, IHostedService
{ {
await _runTask!.ConfigureAwait(false); await _runTask!.ConfigureAwait(false);
} }
catch (OperationCanceledException) { } catch (OperationCanceledException)
{
// ignore cancelled
}
finally finally
{ {
_cancellationTokenSource.Dispose(); _cancellationTokenSource.Dispose();

View File

@@ -1,4 +1,5 @@
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Utility;
using MareSynchronos.API.Data; using MareSynchronos.API.Data;
using MareSynchronos.API.Data.Enum; using MareSynchronos.API.Data.Enum;
using MareSynchronos.PlayerData.Handlers; using MareSynchronos.PlayerData.Handlers;
@@ -83,6 +84,16 @@ public static class VariousExtensions
} }
} }
oldData.CustomizePlusData.TryGetValue(objectKind, out var oldCustomizePlusData);
newData.CustomizePlusData.TryGetValue(objectKind, out var newCustomizePlusData);
bool customizeDataDifferent = !string.Equals(oldCustomizePlusData, newCustomizePlusData, StringComparison.Ordinal);
if (customizeDataDifferent || (forceApplyCustomization && !string.IsNullOrEmpty(newCustomizePlusData)))
{
logger.LogDebug("[BASE-{appBase}] Updating {object}/{kind} (Diff customize data) => {change}", applicationBase, cachedPlayer, objectKind, PlayerChanges.Customize);
charaDataToUpdate[objectKind].Add(PlayerChanges.Customize);
}
if (objectKind != ObjectKind.Player) continue; if (objectKind != ObjectKind.Player) continue;
bool manipDataDifferent = !string.Equals(oldData.ManipulationData, newData.ManipulationData, StringComparison.Ordinal); bool manipDataDifferent = !string.Equals(oldData.ManipulationData, newData.ManipulationData, StringComparison.Ordinal);
@@ -92,20 +103,13 @@ public static class VariousExtensions
charaDataToUpdate[objectKind].Add(PlayerChanges.ModManip); charaDataToUpdate[objectKind].Add(PlayerChanges.ModManip);
} }
bool heelsOffsetDifferent = oldData.HeelsOffset != newData.HeelsOffset; bool heelsOffsetDifferent = !string.Equals(oldData.HeelsData, newData.HeelsData, StringComparison.Ordinal);
if (heelsOffsetDifferent || (forceApplyCustomization && newData.HeelsOffset != 0)) if (heelsOffsetDifferent || (forceApplyCustomization && !string.IsNullOrEmpty(newData.HeelsData)))
{ {
logger.LogDebug("[BASE-{appBase}] Updating {object}/{kind} (Diff heels data) => {change}", applicationBase, cachedPlayer, objectKind, PlayerChanges.Heels); logger.LogDebug("[BASE-{appBase}] Updating {object}/{kind} (Diff heels data) => {change}", applicationBase, cachedPlayer, objectKind, PlayerChanges.Heels);
charaDataToUpdate[objectKind].Add(PlayerChanges.Heels); charaDataToUpdate[objectKind].Add(PlayerChanges.Heels);
} }
bool customizeDataDifferent = !string.Equals(oldData.CustomizePlusData, newData.CustomizePlusData, StringComparison.Ordinal);
if (customizeDataDifferent || (forceApplyCustomization && !string.IsNullOrEmpty(newData.CustomizePlusData)))
{
logger.LogDebug("[BASE-{appBase}] Updating {object}/{kind} (Diff customize data) => {change}", applicationBase, cachedPlayer, objectKind, PlayerChanges.Customize);
charaDataToUpdate[objectKind].Add(PlayerChanges.Customize);
}
bool palettePlusDataDifferent = !string.Equals(oldData.PalettePlusData, newData.PalettePlusData, StringComparison.Ordinal); bool palettePlusDataDifferent = !string.Equals(oldData.PalettePlusData, newData.PalettePlusData, StringComparison.Ordinal);
if (palettePlusDataDifferent || (forceApplyCustomization && !string.IsNullOrEmpty(newData.PalettePlusData))) if (palettePlusDataDifferent || (forceApplyCustomization && !string.IsNullOrEmpty(newData.PalettePlusData)))
{ {