Add support for Palette+ (#40)

This commit is contained in:
Cara
2023-01-30 19:13:57 +10:30
committed by GitHub
parent 2eb9c0992b
commit d218d06230
9 changed files with 128 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ public record MareCharaFileData
public string Description { get; set; } = string.Empty; public string Description { get; set; } = string.Empty;
public string GlamourerData { get; set; } = string.Empty; public string GlamourerData { get; set; } = string.Empty;
public string CustomizePlusData { get; set; } = string.Empty; public string CustomizePlusData { get; set; } = string.Empty;
public string PalettePlusData { get; set; } = string.Empty;
public string ManipulationData { get; set; } = string.Empty; public string ManipulationData { get; set; } = string.Empty;
public List<FileData> Files { get; set; } = new(); public List<FileData> Files { get; set; } = new();
public List<FileSwap> FileSwaps { get; set; } = new(); public List<FileSwap> FileSwaps { get; set; } = new();
@@ -26,6 +27,7 @@ public record MareCharaFileData
} }
CustomizePlusData = dto.CustomizePlusData; CustomizePlusData = dto.CustomizePlusData;
PalettePlusData = dto.PalettePlusData;
ManipulationData = dto.ManipulationData; ManipulationData = dto.ManipulationData;
if (dto.FileReplacements.TryGetValue(ObjectKind.Player, out var fileReplacements)) if (dto.FileReplacements.TryGetValue(ObjectKind.Player, out var fileReplacements))

View File

@@ -326,6 +326,7 @@ public class CharacterDataFactory
previousData.GlamourerString[objectKind] = _ipcManager.GlamourerGetCharacterCustomization(charaPointer); previousData.GlamourerString[objectKind] = _ipcManager.GlamourerGetCharacterCustomization(charaPointer);
previousData.HeelsOffset = _ipcManager.GetHeelsOffset(); previousData.HeelsOffset = _ipcManager.GetHeelsOffset();
previousData.CustomizePlusScale = _ipcManager.GetCustomizePlusScale(); previousData.CustomizePlusScale = _ipcManager.GetCustomizePlusScale();
previousData.PalettePlusPalette = _ipcManager.PalettePlusGetPalette();
Logger.Debug("Handling transient update for " + objectKind); Logger.Debug("Handling transient update for " + objectKind);
ManageSemiTransientData(previousData, objectKind, charaPointer); ManageSemiTransientData(previousData, objectKind, charaPointer);

View File

@@ -129,6 +129,14 @@ public class CachedPlayer : IDisposable
charaDataToUpdate.Add(objectKind); charaDataToUpdate.Add(objectKind);
continue; continue;
} }
bool palettePlusDataDifferent = !string.Equals(_cachedData.PalettePlusData, characterData.PalettePlusData, StringComparison.Ordinal);
if (palettePlusDataDifferent)
{
Logger.Debug("Updating " + objectKind);
charaDataToUpdate.Add(objectKind);
continue;
}
} }
} }
@@ -149,6 +157,15 @@ public class CachedPlayer : IDisposable
} }
} }
if (!string.IsNullOrEmpty(characterData.PalettePlusData))
{
if (!warning.ShownPalettePlusWarning && !_ipcManager.CheckPalettePlusApi())
{
_dalamudUtil.PrintWarnChat("Received Palette+ data for player " + PlayerName + ", but Palette+ is not installed. Install Palette+ to experience their character fully.");
warning.ShownPalettePlusWarning = true;
}
}
_cachedData = characterData; _cachedData = characterData;
DownloadAndApplyCharacter(charaDataToUpdate, updateModdedPaths); DownloadAndApplyCharacter(charaDataToUpdate, updateModdedPaths);
@@ -244,6 +261,7 @@ public class CachedPlayer : IDisposable
ct.ThrowIfCancellationRequested(); ct.ThrowIfCancellationRequested();
_ipcManager.HeelsSetOffsetForPlayer(_cachedData.HeelsOffset, PlayerCharacter); _ipcManager.HeelsSetOffsetForPlayer(_cachedData.HeelsOffset, PlayerCharacter);
_ipcManager.CustomizePlusSetBodyScale(PlayerCharacter, _cachedData.CustomizePlusData); _ipcManager.CustomizePlusSetBodyScale(PlayerCharacter, _cachedData.CustomizePlusData);
_ipcManager.PalettePlusSetPalette(PlayerCharacter, _cachedData.PalettePlusData);
RequestedPenumbraRedraw = true; RequestedPenumbraRedraw = true;
Logger.Debug( Logger.Debug(
$"Request Redraw for {PlayerName}"); $"Request Redraw for {PlayerName}");
@@ -449,6 +467,7 @@ public class CachedPlayer : IDisposable
_ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerCharacter); _ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerCharacter);
_ipcManager.HeelsRestoreOffsetForPlayer(PlayerCharacter); _ipcManager.HeelsRestoreOffsetForPlayer(PlayerCharacter);
_ipcManager.CustomizePlusRevert(PlayerCharacter); _ipcManager.CustomizePlusRevert(PlayerCharacter);
_ipcManager.PalettePlusRemovePalette(PlayerCharacter);
} }
else else
{ {

View File

@@ -51,6 +51,12 @@ public class IpcManager : IDisposable
private readonly ICallGateSubscriber<Character?, object> _customizePlusRevert; private readonly ICallGateSubscriber<Character?, object> _customizePlusRevert;
private readonly ICallGateSubscriber<string?, object> _customizePlusOnScaleUpdate; private readonly ICallGateSubscriber<string?, object> _customizePlusOnScaleUpdate;
private readonly ICallGateSubscriber<string> _palettePlusApiVersion;
private readonly ICallGateSubscriber<Character, string> _palettePlusGetCharaPalette;
private readonly ICallGateSubscriber<Character, string, object> _palettePlusSetCharaPalette;
private readonly ICallGateSubscriber<Character, object> _palettePlusRemoveCharaPalette;
private readonly ICallGateSubscriber<Character, string, object> _palettePlusPaletteChanged;
private readonly DalamudUtil _dalamudUtil; private readonly DalamudUtil _dalamudUtil;
private bool _inGposeQueueMode = false; private bool _inGposeQueueMode = false;
private ConcurrentQueue<Action> ActionQueue => _inGposeQueueMode ? _gposeActionQueue : _normalQueue; private ConcurrentQueue<Action> ActionQueue => _inGposeQueueMode ? _gposeActionQueue : _normalQueue;
@@ -103,6 +109,14 @@ public class IpcManager : IDisposable
_customizePlusOnScaleUpdate.Subscribe(OnCustomizePlusScaleChange); _customizePlusOnScaleUpdate.Subscribe(OnCustomizePlusScaleChange);
_palettePlusApiVersion = pi.GetIpcSubscriber<string>("PalettePlus.ApiVersion");
_palettePlusGetCharaPalette = pi.GetIpcSubscriber<Character, string>("PalettePlus.GetCharaPalette");
_palettePlusSetCharaPalette = pi.GetIpcSubscriber<Character, string, object>("PalettePlus.SetCharaPalette");
_palettePlusRemoveCharaPalette = pi.GetIpcSubscriber<Character, object>("PalettePlus.RemoveCharaPalette");
_palettePlusPaletteChanged = pi.GetIpcSubscriber<Character, string, object>("PalettePlus.PaletteChanged");
_palettePlusPaletteChanged.Subscribe(OnPalettePlusPaletteChange);
if (Initialized) if (Initialized)
{ {
PenumbraInitialized?.Invoke(); PenumbraInitialized?.Invoke();
@@ -168,6 +182,7 @@ public class IpcManager : IDisposable
public event FloatDelegate? HeelsOffsetChangeEvent; public event FloatDelegate? HeelsOffsetChangeEvent;
public event PenumbraFileResourceDelegate? PenumbraResourceLoadEvent; public event PenumbraFileResourceDelegate? PenumbraResourceLoadEvent;
public event StringDelegate? CustomizePlusScaleChange; public event StringDelegate? CustomizePlusScaleChange;
public event StringDelegate? PalettePlusPaletteChange;
public bool Initialized => CheckPenumbraApi(); public bool Initialized => CheckPenumbraApi();
public bool CheckGlamourerApi() public bool CheckGlamourerApi()
@@ -218,6 +233,18 @@ public class IpcManager : IDisposable
} }
} }
public bool CheckPalettePlusApi()
{
try
{
return string.Equals(_palettePlusApiVersion.InvokeFunc(), "1.0.0", StringComparison.Ordinal);
}
catch
{
return false;
}
}
public void Dispose() public void Dispose()
{ {
Logger.Verbose("Disposing " + nameof(IpcManager)); Logger.Verbose("Disposing " + nameof(IpcManager));
@@ -503,6 +530,59 @@ public class IpcManager : IDisposable
CustomizePlusScaleChange?.Invoke(scale); CustomizePlusScaleChange?.Invoke(scale);
} }
private void OnPalettePlusPaletteChange(Character character, string palette)
{
if (character.Address == 0 || character.Address != _dalamudUtil.PlayerPointer) return;
if (palette != null) palette = Convert.ToBase64String(Encoding.UTF8.GetBytes(palette));
PalettePlusPaletteChange?.Invoke(palette);
}
public void PalettePlusSetPalette(IntPtr character, string palette)
{
if (!CheckPalettePlusApi()) return;
ActionQueue.Enqueue(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj is Character c)
{
string decodedPalette = Encoding.UTF8.GetString(Convert.FromBase64String(palette));
if (string.IsNullOrEmpty(decodedPalette))
{
Logger.Verbose("PalettePlus removing for " + c.Address.ToString("X"));
_palettePlusRemoveCharaPalette!.InvokeAction(c);
}
else
{
Logger.Verbose("PalettePlus applying for " + c.Address.ToString("X"));
_palettePlusSetCharaPalette!.InvokeAction(c, decodedPalette);
}
}
});
}
public string PalettePlusGetPalette()
{
if (!CheckPalettePlusApi()) return string.Empty;
var palette = _palettePlusGetCharaPalette.InvokeFunc(_dalamudUtil.PlayerCharacter);
if (string.IsNullOrEmpty(palette)) return string.Empty;
return Convert.ToBase64String(Encoding.UTF8.GetBytes(palette));
}
public void PalettePlusRemovePalette(IntPtr character)
{
if (!CheckPalettePlusApi()) return;
ActionQueue.Enqueue(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj is Character c)
{
Logger.Verbose("PalettePlus removing for " + c.Address.ToString("X"));
_palettePlusRemoveCharaPalette!.InvokeAction(c);
}
});
}
private void PenumbraDispose() private void PenumbraDispose()
{ {
PenumbraDisposed?.Invoke(); PenumbraDisposed?.Invoke();

View File

@@ -51,6 +51,7 @@ public class PlayerManager : IDisposable
_dalamudUtil.DelayedFrameworkUpdate += DalamudUtilOnDelayedFrameworkUpdate; _dalamudUtil.DelayedFrameworkUpdate += DalamudUtilOnDelayedFrameworkUpdate;
_ipcManager.HeelsOffsetChangeEvent += HeelsOffsetChanged; _ipcManager.HeelsOffsetChangeEvent += HeelsOffsetChanged;
_ipcManager.CustomizePlusScaleChange += CustomizePlusChanged; _ipcManager.CustomizePlusScaleChange += CustomizePlusChanged;
_ipcManager.PalettePlusPaletteChange += PalettePlusChanged;
_dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate; _dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate;
@@ -118,6 +119,17 @@ public class PlayerManager : IDisposable
} }
} }
private void PalettePlusChanged(string? change)
{
change ??= string.Empty;
var player = _playerRelatedObjects.First(f => f.ObjectKind == ObjectKind.Player);
if (LastCreatedCharacterData != null && !string.Equals(LastCreatedCharacterData.PalettePlusData, change, StringComparison.Ordinal) && !player.IsProcessing)
{
Logger.Debug("PalettePlus data changed to " + change);
player.HasTransientsUpdate = true;
}
}
public void Dispose() public void Dispose()
{ {
Logger.Verbose("Disposing " + nameof(PlayerManager)); Logger.Verbose("Disposing " + nameof(PlayerManager));
@@ -134,6 +146,7 @@ public class PlayerManager : IDisposable
_playerChangedCts?.Cancel(); _playerChangedCts?.Cancel();
_ipcManager.HeelsOffsetChangeEvent -= HeelsOffsetChanged; _ipcManager.HeelsOffsetChangeEvent -= HeelsOffsetChanged;
_ipcManager.CustomizePlusScaleChange -= CustomizePlusChanged; _ipcManager.CustomizePlusScaleChange -= CustomizePlusChanged;
_ipcManager.PalettePlusPaletteChange -= PalettePlusChanged;
} }
private unsafe void DalamudUtilOnDelayedFrameworkUpdate() private unsafe void DalamudUtilOnDelayedFrameworkUpdate()

View File

@@ -26,6 +26,9 @@ public class CharacterData
[JsonProperty] [JsonProperty]
public string CustomizePlusScale { get; set; } = string.Empty; public string CustomizePlusScale { get; set; } = string.Empty;
[JsonProperty]
public string PalettePlusPalette { get; set; } = string.Empty;
public void AddFileReplacement(ObjectKind objectKind, FileReplacement fileReplacement) public void AddFileReplacement(ObjectKind objectKind, FileReplacement fileReplacement)
{ {
if (!fileReplacement.HasFileReplacement) return; if (!fileReplacement.HasFileReplacement) return;
@@ -74,6 +77,7 @@ public class CharacterData
ManipulationData = ManipulationString, ManipulationData = ManipulationString,
HeelsOffset = HeelsOffset, HeelsOffset = HeelsOffset,
CustomizePlusData = CustomizePlusScale, CustomizePlusData = CustomizePlusScale,
PalettePlusData = PalettePlusPalette,
}; };
} }

View File

@@ -4,4 +4,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 ShownPalettePlusWarning { get; set; } = false;
} }

View File

@@ -64,6 +64,7 @@ public class Pair
{ {
ShownCustomizePlusWarning = _configService.Current.DisableOptionalPluginWarnings, ShownCustomizePlusWarning = _configService.Current.DisableOptionalPluginWarnings,
ShownHeelsWarning = _configService.Current.DisableOptionalPluginWarnings, ShownHeelsWarning = _configService.Current.DisableOptionalPluginWarnings,
ShownPalettePlusWarning = _configService.Current.DisableOptionalPluginWarnings,
}; };
CachedPlayer.Initialize(address, name); CachedPlayer.Initialize(address, name);
@@ -91,6 +92,7 @@ public class Pair
{ {
ShownCustomizePlusWarning = _configService.Current.DisableOptionalPluginWarnings, ShownCustomizePlusWarning = _configService.Current.DisableOptionalPluginWarnings,
ShownHeelsWarning = _configService.Current.DisableOptionalPluginWarnings, ShownHeelsWarning = _configService.Current.DisableOptionalPluginWarnings,
ShownPalettePlusWarning = _configService.Current.DisableOptionalPluginWarnings,
}; };
CachedPlayer.ApplyCharacterData(RemoveNotSyncedFiles(LastReceivedCharacterData.DeepClone())!, _pluginWarnings); CachedPlayer.ApplyCharacterData(RemoveNotSyncedFiles(LastReceivedCharacterData.DeepClone())!, _pluginWarnings);

View File

@@ -181,11 +181,13 @@ public partial class UiShared : IDisposable
var glamourerExists = _ipcManager.CheckGlamourerApi(); var glamourerExists = _ipcManager.CheckGlamourerApi();
var heelsExists = _ipcManager.CheckHeelsApi(); var heelsExists = _ipcManager.CheckHeelsApi();
var customizeExists = _ipcManager.CheckCustomizePlusApi(); var customizeExists = _ipcManager.CheckCustomizePlusApi();
var paletteExists = _ipcManager.CheckPalettePlusApi();
var penumbraColor = penumbraExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed; var penumbraColor = penumbraExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var glamourerColor = glamourerExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed; var glamourerColor = glamourerExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var heelsColor = heelsExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed; var heelsColor = heelsExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var customizeColor = customizeExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed; var customizeColor = customizeExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
var paletteColor = paletteExists ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
ImGui.Text("Penumbra:"); ImGui.Text("Penumbra:");
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextColored(penumbraColor, penumbraExists ? "Available" : "Unavailable"); ImGui.TextColored(penumbraColor, penumbraExists ? "Available" : "Unavailable");
@@ -202,6 +204,10 @@ public partial class UiShared : IDisposable
ImGui.Text("Customize+:"); ImGui.Text("Customize+:");
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextColored(customizeColor, customizeExists ? "Available" : "Unavailable"); ImGui.TextColored(customizeColor, customizeExists ? "Available" : "Unavailable");
ImGui.SameLine();
ImGui.Text("PalettePlus+:");
ImGui.SameLine();
ImGui.TextColored(paletteColor, paletteExists ? "Available" : "Unavailable");
if (!penumbraExists || !glamourerExists) if (!penumbraExists || !glamourerExists)
{ {