using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using Dalamud.Utility; using MareSynchronos.Services; using MareSynchronos.Services.Mediator; using Microsoft.Extensions.Logging; using System.Text; namespace MareSynchronos.Interop.Ipc; public sealed class IpcCallerCustomize : IIpcCaller { private readonly ICallGateSubscriber<(int, int)> _customizePlusApiVersion; private readonly ICallGateSubscriber _customizePlusGetBodyScale; private readonly ICallGateSubscriber _customizePlusOnScaleUpdate; private readonly ICallGateSubscriber _customizePlusRevertCharacter; private readonly ICallGateSubscriber _customizePlusSetBodyScaleToCharacter; private readonly ILogger _logger; private readonly DalamudUtilService _dalamudUtil; private readonly MareMediator _mareMediator; public IpcCallerCustomize(ILogger logger, DalamudPluginInterface dalamudPluginInterface, DalamudUtilService dalamudUtil, MareMediator mareMediator) { _customizePlusApiVersion = dalamudPluginInterface.GetIpcSubscriber<(int, int)>("CustomizePlus.GetApiVersion"); _customizePlusGetBodyScale = dalamudPluginInterface.GetIpcSubscriber("CustomizePlus.GetProfileFromCharacter"); _customizePlusRevertCharacter = dalamudPluginInterface.GetIpcSubscriber("CustomizePlus.RevertCharacter"); _customizePlusSetBodyScaleToCharacter = dalamudPluginInterface.GetIpcSubscriber("CustomizePlus.SetProfileToCharacter"); _customizePlusOnScaleUpdate = dalamudPluginInterface.GetIpcSubscriber("CustomizePlus.OnProfileUpdate"); _customizePlusOnScaleUpdate.Subscribe(OnCustomizePlusScaleChange); _logger = logger; _dalamudUtil = dalamudUtil; _mareMediator = mareMediator; CheckAPI(); } public bool APIAvailable { get; private set; } = false; public async Task RevertAsync(nint character) { if (!APIAvailable) return; await _dalamudUtil.RunOnFrameworkThread(() => { var gameObj = _dalamudUtil.CreateGameObject(character); if (gameObj is Character c) { _logger.LogTrace("CustomizePlus reverting for {chara}", c.Address.ToString("X")); _customizePlusRevertCharacter!.InvokeAction(c); } }).ConfigureAwait(false); } public async Task SetBodyScaleAsync(nint character, string scale) { if (!APIAvailable) return; await _dalamudUtil.RunOnFrameworkThread(() => { var gameObj = _dalamudUtil.CreateGameObject(character); if (gameObj is Character c) { string decodedScale = Encoding.UTF8.GetString(Convert.FromBase64String(scale)); _logger.LogTrace("CustomizePlus applying for {chara}", c.Address.ToString("X")); if (scale.IsNullOrEmpty()) { _customizePlusRevertCharacter!.InvokeAction(c); } else { _customizePlusSetBodyScaleToCharacter!.InvokeAction(decodedScale, c); } } }).ConfigureAwait(false); } public async Task GetScaleAsync(nint character) { if (!APIAvailable) return null; 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; return Convert.ToBase64String(Encoding.UTF8.GetBytes(scale)); } public void CheckAPI() { try { var version = _customizePlusApiVersion.InvokeFunc(); APIAvailable = (version.Item1 == 3 && version.Item2 >= 0); } catch { APIAvailable = false; } } private void OnCustomizePlusScaleChange(string? profileName, string? scale) { _mareMediator.Publish(new CustomizePlusMessage(profileName ?? string.Empty)); } public void Dispose() { _customizePlusOnScaleUpdate.Unsubscribe(OnCustomizePlusScaleChange); } }