adjust collection handling

This commit is contained in:
rootdarkarchon
2023-05-07 00:14:07 +02:00
parent f512552fe7
commit bfb83772ef
4 changed files with 102 additions and 48 deletions

View File

@@ -433,15 +433,12 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
} }
} }
public async Task PenumbraRemoveTemporaryCollectionAsync(ILogger logger, Guid applicationId, string characterName) public async Task PenumbraRemoveTemporaryCollectionAsync(ILogger logger, Guid applicationId, string collName)
{ {
if (!CheckPenumbraApi()) return; if (!CheckPenumbraApi()) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
var collName = "Mare_" + characterName;
logger.LogTrace("[{applicationId}] Removing temp collection for {collName}", applicationId, collName); logger.LogTrace("[{applicationId}] Removing temp collection for {collName}", applicationId, collName);
var ret = _penumbraRemoveTemporaryMod.Invoke("MareChara", collName, 0);
logger.LogTrace("[{applicationId}] RemoveTemporaryMod: {ret}", applicationId, ret);
var ret2 = _penumbraRemoveTemporaryCollection.Invoke(collName); var ret2 = _penumbraRemoveTemporaryCollection.Invoke(collName);
logger.LogTrace("[{applicationId}] RemoveTemporaryCollection: {ret2}", applicationId, ret2); logger.LogTrace("[{applicationId}] RemoveTemporaryCollection: {ret2}", applicationId, ret2);
}).ConfigureAwait(false); }).ConfigureAwait(false);
@@ -452,25 +449,61 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
return await _dalamudUtil.RunOnFrameworkThread(() => _penumbraResolvePaths.Invoke(forward, reverse)).ConfigureAwait(false); return await _dalamudUtil.RunOnFrameworkThread(() => _penumbraResolvePaths.Invoke(forward, reverse)).ConfigureAwait(false);
} }
public async Task PenumbraSetTemporaryModsAsync(ILogger logger, Guid applicationId, string characterName, int? idx, Dictionary<string, string> modPaths, string manipulationData) public async Task PenumbraSetTemporaryModsAsync(ILogger logger, Guid applicationId, string collName, Dictionary<string, string> modPaths)
{ {
if (!CheckPenumbraApi() || idx == null) return; if (!CheckPenumbraApi()) return;
await _dalamudUtil.RunOnFrameworkThread(() => await _dalamudUtil.RunOnFrameworkThread(() =>
{ {
var collName = "Mare_" + characterName;
var ret = _penumbraCreateNamedTemporaryCollection.Invoke(collName);
logger.LogTrace("[{applicationId}] Creating Temp Collection {collName}, Success: {ret}", applicationId, collName, ret);
var retAssign = _penumbraAssignTemporaryCollection.Invoke(collName, idx.Value, c: true);
logger.LogTrace("[{applicationId}] Assigning Temp Collection {collName} to index {idx}, Success: {ret}", applicationId, collName, idx, retAssign);
foreach (var mod in modPaths) foreach (var mod in modPaths)
{ {
logger.LogTrace("[{applicationId}] Change: {from} => {to}", applicationId, mod.Key, mod.Value); logger.LogTrace("[{applicationId}] Change: {from} => {to}", applicationId, mod.Key, mod.Value);
} }
var retRemove = _penumbraRemoveTemporaryMod.Invoke("MareChara_Files", collName, 0);
logger.LogTrace("[{applicationId}] Removing prev mod files mod for {collName}, Success: {ret}", applicationId, collName, retRemove);
var retAdd = _penumbraAddTemporaryMod.Invoke("MareChara_Files", collName, modPaths, string.Empty, 0);
logger.LogTrace("[{applicationId}] Setting temp files mod for {collName}, Success: {ret}", applicationId, collName, retAdd);
}).ConfigureAwait(false);
}
public async Task PenumbraSetManipulationDataAsync(ILogger logger, Guid applicationId, string collName, string manipulationData)
{
if (!CheckPenumbraApi()) return;
await _dalamudUtil.RunOnFrameworkThread(() =>
{
logger.LogTrace("[{applicationId}] Manip: {data}", applicationId, manipulationData); logger.LogTrace("[{applicationId}] Manip: {data}", applicationId, manipulationData);
var ret2 = _penumbraAddTemporaryMod.Invoke("MareChara", collName, modPaths, manipulationData, 0); var retRemove = _penumbraRemoveTemporaryMod.Invoke("MareChara_Meta", collName, 0);
logger.LogTrace("[{applicationId}] Setting temp mods for {collName}, Success: {ret2}", applicationId, collName, ret2); logger.LogTrace("[{applicationId}] Removing prev meta mod for {collName}, Success: {ret}", applicationId, collName, retRemove);
var retAdd = _penumbraAddTemporaryMod.Invoke("MareChara_Meta", collName, new Dictionary<string, string>(), manipulationData, 0);
logger.LogTrace("[{applicationId}] Setting temp meta mod for {collName}, Success: {ret}", applicationId, collName, retAdd);
}).ConfigureAwait(false);
}
public async Task<string> PenumbraCreateTemporaryCollection(ILogger logger, string uid)
{
if (!CheckPenumbraApi()) return string.Empty;
return await _dalamudUtil.RunOnFrameworkThread(() =>
{
var collName = "Mare_" + uid;
var retRemove = _penumbraRemoveTemporaryCollection.Invoke(collName);
logger.LogTrace("Removing Temp Collection {collName}, Success: {ret}", collName, retRemove);
var retCreate = _penumbraCreateNamedTemporaryCollection.Invoke(collName);
logger.LogTrace("Creating Temp Collection {collName}, Success: {ret}", collName, retCreate);
return collName;
}).ConfigureAwait(false);
}
public async Task PenumbraAssignTemporaryCollection(ILogger logger, string collName, int idx)
{
if (!CheckPenumbraApi()) return;
await _dalamudUtil.RunOnFrameworkThread(() =>
{
var retAssign = _penumbraAssignTemporaryCollection.Invoke(collName, idx, c: true);
logger.LogTrace("Assigning Temp Collection {collName} to index {idx}, Success: {ret}", collName, idx, retAssign);
return collName;
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
@@ -687,6 +720,8 @@ public sealed class IpcManager : DisposableMediatorSubscriberBase
private void PenumbraInit() private void PenumbraInit()
{ {
_penumbraAvailable = true;
PenumbraModDirectory = _penumbraResolveModDir.Invoke();
Mediator.Publish(new PenumbraInitializedMessage()); Mediator.Publish(new PenumbraInitializedMessage());
_penumbraRedraw!.Invoke("self", RedrawType.Redraw); _penumbraRedraw!.Invoke("self", RedrawType.Redraw);
} }

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Authors></Authors> <Authors></Authors>
<Company></Company> <Company></Company>
<Version>0.8.35</Version> <Version>0.8.36</Version>
<Description></Description> <Description></Description>
<Copyright></Copyright> <Copyright></Copyright>
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl> <PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>

View File

@@ -10,6 +10,7 @@ using MareSynchronos.Interop;
using MareSynchronos.Services; using MareSynchronos.Services;
using MareSynchronos.Utils; using MareSynchronos.Utils;
using MareSynchronos.PlayerData.Factories; using MareSynchronos.PlayerData.Factories;
using Lumina.Excel.GeneratedSheets;
namespace MareSynchronos.PlayerData.Export; namespace MareSynchronos.PlayerData.Export;
@@ -66,9 +67,10 @@ public class MareCharaFileManager
var applicationId = Guid.NewGuid(); var applicationId = Guid.NewGuid();
_ipcManager.ToggleGposeQueueMode(on: true); _ipcManager.ToggleGposeQueueMode(on: true);
await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false); await _ipcManager.PenumbraRemoveTemporaryCollectionAsync(_logger, applicationId, charaTarget.Name.TextValue).ConfigureAwait(false);
await _ipcManager.PenumbraSetTemporaryModsAsync(_logger, applicationId, charaTarget.Name.TextValue, charaTarget.ObjectTableIndex(), var coll = await _ipcManager.PenumbraCreateTemporaryCollection(_logger, charaTarget.Name.TextValue).ConfigureAwait(false);
extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal), await _ipcManager.PenumbraAssignTemporaryCollection(_logger, coll, charaTarget.ObjectTableIndex()!.Value).ConfigureAwait(false);
LoadedCharaFile.CharaFileData.ManipulationData).ConfigureAwait(false); await _ipcManager.PenumbraSetTemporaryModsAsync(_logger, applicationId, coll, extractedFiles.Union(fileSwaps).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal)).ConfigureAwait(false);
await _ipcManager.PenumbraSetManipulationDataAsync(_logger, applicationId, coll, LoadedCharaFile.CharaFileData.ManipulationData).ConfigureAwait(false);
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => charaTarget.Address, false).ConfigureAwait(false); using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => charaTarget.Address, false).ConfigureAwait(false);
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);

View File

@@ -39,6 +39,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
private string _lastGlamourerData = string.Empty; private string _lastGlamourerData = string.Empty;
private string _originalGlamourerData = string.Empty; private string _originalGlamourerData = string.Empty;
private CancellationTokenSource _redrawCts = new(); private CancellationTokenSource _redrawCts = new();
private string _penumbraCollection;
public CachedPlayer(ILogger<CachedPlayer> logger, OnlineUserIdentDto onlineUser, public CachedPlayer(ILogger<CachedPlayer> logger, OnlineUserIdentDto onlineUser,
GameObjectHandlerFactory gameObjectHandlerFactory, GameObjectHandlerFactory gameObjectHandlerFactory,
@@ -57,8 +58,17 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
{ {
_charaHandler?.Invalidate(); _charaHandler?.Invalidate();
IsVisible = false; IsVisible = false;
} });
); Mediator.Subscribe<PenumbraInitializedMessage>(this, (_) =>
{
_penumbraCollection = _ipcManager.PenumbraCreateTemporaryCollection(logger, OnlineUser.User.UID).ConfigureAwait(false).GetAwaiter().GetResult();
if (!IsVisible && _charaHandler != null)
{
PlayerName = string.Empty;
_charaHandler.Dispose();
_charaHandler = null;
}
});
_pluginWarnings ??= new() _pluginWarnings ??= new()
{ {
ShownCustomizePlusWarning = mareConfigService.Current.DisableOptionalPluginWarnings, ShownCustomizePlusWarning = mareConfigService.Current.DisableOptionalPluginWarnings,
@@ -66,6 +76,10 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
ShownPalettePlusWarning = mareConfigService.Current.DisableOptionalPluginWarnings, ShownPalettePlusWarning = mareConfigService.Current.DisableOptionalPluginWarnings,
ShownHonorificWarning = mareConfigService.Current.DisableOptionalPluginWarnings, ShownHonorificWarning = mareConfigService.Current.DisableOptionalPluginWarnings,
}; };
Task.Run(async () =>
{
_penumbraCollection = await _ipcManager.PenumbraCreateTemporaryCollection(logger, OnlineUser.User.UID).ConfigureAwait(false);
});
} }
private enum PlayerChanges private enum PlayerChanges
@@ -74,7 +88,9 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
Customize = 2, Customize = 2,
Palette = 3, Palette = 3,
Honorific = 4, Honorific = 4,
Mods = 5, ModFiles = 5,
ModManip = 6,
Glamourer = 7
} }
public bool IsVisible { get; private set; } public bool IsVisible { get; private set; }
@@ -167,7 +183,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (_dalamudUtil is { IsZoning: false, IsInCutscene: false }) if (_dalamudUtil is { IsZoning: false, IsInCutscene: false })
{ {
Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser); Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser);
_ipcManager.PenumbraRemoveTemporaryCollectionAsync(Logger, applicationId, name).GetAwaiter().GetResult(); _ipcManager.PenumbraRemoveTemporaryCollectionAsync(Logger, applicationId, _penumbraCollection).GetAwaiter().GetResult();
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData?.FileReplacements ?? new()) foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData?.FileReplacements ?? new())
{ {
@@ -252,12 +268,15 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
await _ipcManager.HonorificSetTitleAsync(handler.Address, charaData.HonorificData).ConfigureAwait(false); await _ipcManager.HonorificSetTitleAsync(handler.Address, charaData.HonorificData).ConfigureAwait(false);
break; break;
case PlayerChanges.Mods: case PlayerChanges.Glamourer:
if (charaData.GlamourerData.TryGetValue(changes.Key, out var glamourerData)) if (charaData.GlamourerData.TryGetValue(changes.Key, out var glamourerData))
{ {
await _ipcManager.GlamourerApplyAllAsync(Logger, handler, glamourerData, applicationId, token).ConfigureAwait(false); await _ipcManager.GlamourerApplyAllAsync(Logger, handler, glamourerData, applicationId, token).ConfigureAwait(false);
} }
else break;
case PlayerChanges.ModFiles:
case PlayerChanges.ModManip:
if (!changes.Value.Contains(PlayerChanges.Glamourer))
{ {
await _ipcManager.PenumbraRedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false); await _ipcManager.PenumbraRedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false);
} }
@@ -295,19 +314,20 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (hasNewButNotOldFileReplacements || hasOldButNotNewFileReplacements || hasNewButNotOldGlamourerData || hasOldButNotNewGlamourerData) if (hasNewButNotOldFileReplacements || hasOldButNotNewFileReplacements || hasNewButNotOldGlamourerData || hasOldButNotNewGlamourerData)
{ {
Logger.LogDebug("Updating {object}/{kind} (Some new data arrived: NewButNotOldFiles:{hasNewButNotOldFileReplacements}," + Logger.LogDebug("Updating {object}/{kind} (Some new data arrived: NewButNotOldFiles:{hasNewButNotOldFileReplacements}," +
" OldButNotNewFiles:{hasOldButNotNewFileReplacements}, NewButNotOldGlam:{hasNewButNotOldGlamourerData}, OldButNotNewGlam:{hasOldButNotNewGlamourerData}) => {change}", " OldButNotNewFiles:{hasOldButNotNewFileReplacements}, NewButNotOldGlam:{hasNewButNotOldGlamourerData}, OldButNotNewGlam:{hasOldButNotNewGlamourerData}) => {change}, {change2}",
this, objectKind, hasNewButNotOldFileReplacements, hasOldButNotNewFileReplacements, hasNewButNotOldGlamourerData, hasOldButNotNewGlamourerData, PlayerChanges.Mods); this, objectKind, hasNewButNotOldFileReplacements, hasOldButNotNewFileReplacements, hasNewButNotOldGlamourerData, hasOldButNotNewGlamourerData, PlayerChanges.ModFiles, PlayerChanges.Glamourer);
charaDataToUpdate[objectKind].Add(PlayerChanges.Mods); charaDataToUpdate[objectKind].Add(PlayerChanges.ModFiles);
charaDataToUpdate[objectKind].Add(PlayerChanges.Glamourer);
} }
else else
{ {
if (hasNewAndOldFileReplacements) if (hasNewAndOldFileReplacements)
{ {
bool listsAreEqual = oldData.FileReplacements[objectKind].SequenceEqual(newData.FileReplacements[objectKind], Data.FileReplacementDataComparer.Instance); bool listsAreEqual = oldData.FileReplacements[objectKind].SequenceEqual(newData.FileReplacements[objectKind], Data.FileReplacementDataComparer.Instance);
if (!listsAreEqual || forced) if (!listsAreEqual)
{ {
Logger.LogDebug("Updating {object}/{kind} (FileReplacements not equal) => {change}", this, objectKind, PlayerChanges.Mods); Logger.LogDebug("Updating {object}/{kind} (FileReplacements not equal) => {change}", this, objectKind, PlayerChanges.ModFiles);
charaDataToUpdate[objectKind].Add(PlayerChanges.Mods); charaDataToUpdate[objectKind].Add(PlayerChanges.ModFiles);
} }
} }
@@ -316,8 +336,8 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
bool glamourerDataDifferent = !string.Equals(oldData.GlamourerData[objectKind], newData.GlamourerData[objectKind], StringComparison.Ordinal); bool glamourerDataDifferent = !string.Equals(oldData.GlamourerData[objectKind], newData.GlamourerData[objectKind], StringComparison.Ordinal);
if (glamourerDataDifferent || forced) if (glamourerDataDifferent || forced)
{ {
Logger.LogDebug("Updating {object}/{kind} (Glamourer different) => {change}", this, objectKind, PlayerChanges.Mods); Logger.LogDebug("Updating {object}/{kind} (Glamourer different) => {change}", this, objectKind, PlayerChanges.Glamourer);
charaDataToUpdate[objectKind].Add(PlayerChanges.Mods); charaDataToUpdate[objectKind].Add(PlayerChanges.Glamourer);
} }
} }
} }
@@ -325,10 +345,10 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
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);
if (manipDataDifferent || forced) if (manipDataDifferent)
{ {
Logger.LogDebug("Updating {object}/{kind} (Diff manip data) => {change}", this, objectKind, PlayerChanges.Mods); Logger.LogDebug("Updating {object}/{kind} (Diff manip data) => {change}", this, objectKind, PlayerChanges.ModManip);
charaDataToUpdate[objectKind].Add(PlayerChanges.Mods); charaDataToUpdate[objectKind].Add(PlayerChanges.ModManip);
} }
bool heelsOffsetDifferent = oldData.HeelsOffset != newData.HeelsOffset; bool heelsOffsetDifferent = oldData.HeelsOffset != newData.HeelsOffset;
@@ -377,7 +397,8 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
return; return;
} }
var updateModdedPaths = updatedData.Values.Any(v => v.Any(p => p == PlayerChanges.Mods)); var updateModdedPaths = updatedData.Values.Any(v => v.Any(p => p == PlayerChanges.ModFiles));
var updateManip = updatedData.Values.Any(v => v.Any(p => p == PlayerChanges.ModManip));
_downloadCancellationTokenSource = _downloadCancellationTokenSource?.CancelRecreate() ?? new CancellationTokenSource(); _downloadCancellationTokenSource = _downloadCancellationTokenSource?.CancelRecreate() ?? new CancellationTokenSource();
var downloadToken = _downloadCancellationTokenSource.Token; var downloadToken = _downloadCancellationTokenSource.Token;
@@ -447,20 +468,14 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
if (updateModdedPaths && (moddedPaths.Any() || !string.IsNullOrEmpty(charaData.ManipulationData))) if (updateModdedPaths)
{ {
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync((_) => _ipcManager await _ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, _penumbraCollection, moddedPaths).ConfigureAwait(false);
.PenumbraRemoveTemporaryCollectionAsync(Logger, _applicationId, PlayerName!) }
.ConfigureAwait(true).GetAwaiter().GetResult(), token).ConfigureAwait(false);
token.ThrowIfCancellationRequested();
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync((chara) => if (updateManip)
{ {
var objTableIndex = chara.ObjectTableIndex(); await _ipcManager.PenumbraSetManipulationDataAsync(Logger, _applicationId, _penumbraCollection, charaData.ManipulationData).ConfigureAwait(false);
_ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, PlayerName!, objTableIndex, moddedPaths, charaData.ManipulationData)
.ConfigureAwait(true).GetAwaiter().GetResult();
}, token).ConfigureAwait(false);
token.ThrowIfCancellationRequested();
} }
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
@@ -542,6 +557,8 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
await _ipcManager.HonorificSetTitleAsync(PlayerCharacter, _cachedData.HonorificData).ConfigureAwait(false); await _ipcManager.HonorificSetTitleAsync(PlayerCharacter, _cachedData.HonorificData).ConfigureAwait(false);
}); });
_ipcManager.PenumbraAssignTemporaryCollection(Logger, _penumbraCollection, _charaHandler.GetGameObject()!.ObjectIndex).GetAwaiter().GetResult();
_downloadManager.Initialize(); _downloadManager.Initialize();
} }
@@ -561,7 +578,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (_cachedData != null) if (_cachedData != null)
{ {
await ApplyCustomizationDataAsync(applicationId, new(ObjectKind.Player, await ApplyCustomizationDataAsync(applicationId, new(ObjectKind.Player,
new HashSet<PlayerChanges>(new[] { PlayerChanges.Palette, PlayerChanges.Customize, PlayerChanges.Heels, PlayerChanges.Mods })), new HashSet<PlayerChanges>(new[] { PlayerChanges.Palette, PlayerChanges.Customize, PlayerChanges.Heels, PlayerChanges.Glamourer })),
_cachedData, token).ConfigureAwait(false); _cachedData, token).ConfigureAwait(false);
} }
}, token); }, token);