mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Fix issue with IPC adding mods before character utility is ready in rare cases.
This commit is contained in:
parent
dcab443b2f
commit
40168d7daf
5 changed files with 60 additions and 15 deletions
|
|
@ -2,6 +2,8 @@ using Dalamud.Plugin;
|
|||
using OtterGui.Services;
|
||||
using Penumbra.Api.Api;
|
||||
using Penumbra.Api.Helpers;
|
||||
using Penumbra.Communication;
|
||||
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
|
||||
|
||||
namespace Penumbra.Api;
|
||||
|
||||
|
|
@ -9,11 +11,13 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
{
|
||||
private readonly List<IDisposable> _providers;
|
||||
|
||||
private readonly EventProvider _disposedProvider;
|
||||
private readonly EventProvider _initializedProvider;
|
||||
private readonly EventProvider _disposedProvider;
|
||||
private readonly EventProvider _initializedProvider;
|
||||
private readonly CharacterUtility _characterUtility;
|
||||
|
||||
public IpcProviders(IDalamudPluginInterface pi, IPenumbraApi api)
|
||||
public IpcProviders(IDalamudPluginInterface pi, IPenumbraApi api, CharacterUtility characterUtility)
|
||||
{
|
||||
_characterUtility = characterUtility;
|
||||
_disposedProvider = IpcSubscribers.Disposed.Provider(pi);
|
||||
_initializedProvider = IpcSubscribers.Initialized.Provider(pi);
|
||||
_providers =
|
||||
|
|
@ -115,11 +119,21 @@ public sealed class IpcProviders : IDisposable, IApiService
|
|||
IpcSubscribers.OpenMainWindow.Provider(pi, api.Ui),
|
||||
IpcSubscribers.CloseMainWindow.Provider(pi, api.Ui),
|
||||
];
|
||||
if (_characterUtility.Ready)
|
||||
_initializedProvider.Invoke();
|
||||
else
|
||||
_characterUtility.LoadingFinished.Subscribe(OnCharacterUtilityReady, CharacterUtilityFinished.Priority.IpcProvider);
|
||||
}
|
||||
|
||||
private void OnCharacterUtilityReady()
|
||||
{
|
||||
_initializedProvider.Invoke();
|
||||
_characterUtility.LoadingFinished.Unsubscribe(OnCharacterUtilityReady);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_characterUtility.LoadingFinished.Unsubscribe(OnCharacterUtilityReady);
|
||||
foreach (var provider in _providers)
|
||||
provider.Dispose();
|
||||
_providers.Clear();
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public class CollectionCacheManager : IDisposable, IService
|
|||
_communicator.ModDiscoveryFinished.Subscribe(OnModDiscoveryFinished, ModDiscoveryFinished.Priority.CollectionCacheManager);
|
||||
|
||||
if (!MetaFileManager.CharacterUtility.Ready)
|
||||
MetaFileManager.CharacterUtility.LoadingFinished += IncrementCounters;
|
||||
MetaFileManager.CharacterUtility.LoadingFinished.Subscribe(IncrementCounters, CharacterUtilityFinished.Priority.CollectionCacheManager);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -83,7 +83,7 @@ public class CollectionCacheManager : IDisposable, IService
|
|||
_communicator.ModOptionChanged.Unsubscribe(OnModOptionChange);
|
||||
_communicator.ModSettingChanged.Unsubscribe(OnModSettingChange);
|
||||
_communicator.CollectionInheritanceChanged.Unsubscribe(OnCollectionInheritanceChange);
|
||||
MetaFileManager.CharacterUtility.LoadingFinished -= IncrementCounters;
|
||||
MetaFileManager.CharacterUtility.LoadingFinished.Unsubscribe(IncrementCounters);
|
||||
|
||||
foreach (var collection in _storage)
|
||||
{
|
||||
|
|
@ -298,7 +298,7 @@ public class CollectionCacheManager : IDisposable, IService
|
|||
{
|
||||
foreach (var collection in _storage.Where(c => c.HasCache))
|
||||
collection.Counters.IncrementChange();
|
||||
MetaFileManager.CharacterUtility.LoadingFinished -= IncrementCounters;
|
||||
MetaFileManager.CharacterUtility.LoadingFinished.Unsubscribe(IncrementCounters);
|
||||
}
|
||||
|
||||
private void OnModSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx, bool _)
|
||||
|
|
|
|||
23
Penumbra/Communication/CharacterUtilityFinished.cs
Normal file
23
Penumbra/Communication/CharacterUtilityFinished.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using OtterGui.Classes;
|
||||
using Penumbra.Api;
|
||||
using Penumbra.Interop.Services;
|
||||
|
||||
namespace Penumbra.Communication;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the Character Utility becomes ready.
|
||||
/// </summary>
|
||||
public sealed class CharacterUtilityFinished() : EventWrapper<CharacterUtilityFinished.Priority>(nameof(CharacterUtilityFinished))
|
||||
{
|
||||
public enum Priority
|
||||
{
|
||||
/// <seealso cref="CharacterUtility"/>
|
||||
OnFinishedLoading = int.MaxValue,
|
||||
|
||||
/// <seealso cref="IpcProviders.OnCharacterUtilityReady"/>
|
||||
IpcProvider = int.MinValue,
|
||||
|
||||
/// <seealso cref="Collections.Cache.CollectionCacheManager"/>
|
||||
CollectionCacheManager = 0,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Communication;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.Interop.Structs;
|
||||
|
||||
|
|
@ -26,14 +27,16 @@ public unsafe class CharacterUtility : IDisposable, IRequiredService
|
|||
public CharacterUtilityData* Address
|
||||
=> *_characterUtilityAddress;
|
||||
|
||||
public bool Ready { get; private set; }
|
||||
public event Action LoadingFinished;
|
||||
public nint DefaultHumanPbdResource { get; private set; }
|
||||
public nint DefaultTransparentResource { get; private set; }
|
||||
public nint DefaultDecalResource { get; private set; }
|
||||
public nint DefaultSkinShpkResource { get; private set; }
|
||||
public nint DefaultCharacterStockingsShpkResource { get; private set; }
|
||||
public nint DefaultCharacterLegacyShpkResource { get; private set; }
|
||||
public bool Ready { get; private set; }
|
||||
|
||||
public readonly CharacterUtilityFinished LoadingFinished = new();
|
||||
|
||||
public nint DefaultHumanPbdResource { get; private set; }
|
||||
public nint DefaultTransparentResource { get; private set; }
|
||||
public nint DefaultDecalResource { get; private set; }
|
||||
public nint DefaultSkinShpkResource { get; private set; }
|
||||
public nint DefaultCharacterStockingsShpkResource { get; private set; }
|
||||
public nint DefaultCharacterLegacyShpkResource { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The relevant indices depend on which meta manipulations we allow for.
|
||||
|
|
@ -61,7 +64,7 @@ public unsafe class CharacterUtility : IDisposable, IRequiredService
|
|||
.Select(idx => new MetaList(new InternalIndex(idx)))
|
||||
.ToArray();
|
||||
_framework = framework;
|
||||
LoadingFinished += () => Penumbra.Log.Debug("Loading of CharacterUtility finished.");
|
||||
LoadingFinished.Subscribe(() => Penumbra.Log.Debug("Loading of CharacterUtility finished."), CharacterUtilityFinished.Priority.OnFinishedLoading);
|
||||
LoadDefaultResources(null!);
|
||||
if (!Ready)
|
||||
_framework.Update += LoadDefaultResources;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,11 @@ public class ModMetaEditor(
|
|||
|
||||
public static bool DeleteDefaultValues(MetaFileManager metaFileManager, MetaDictionary dict)
|
||||
{
|
||||
if (!metaFileManager.CharacterUtility.Ready)
|
||||
{
|
||||
Penumbra.Log.Warning("Trying to delete default meta values before CharacterUtility was ready, skipped.");
|
||||
return false;
|
||||
}
|
||||
var clone = dict.Clone();
|
||||
dict.ClearForDefault();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue