Add changed item adapters.

This commit is contained in:
Ottermandias 2025-02-12 16:44:22 +01:00
parent 60b9facea3
commit 0af9667789
6 changed files with 113 additions and 3 deletions

@ -1 +1 @@
Subproject commit c67809057fac73a0fd407e3ad567f0aa6bc0bc37 Subproject commit 7ae46f0d09f40b36a5b2d10382db46fbfb729117

View file

@ -145,4 +145,10 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable
=> _modManager.TryGetMod(modDirectory, modName, out var mod) => _modManager.TryGetMod(modDirectory, modName, out var mod)
? mod.ChangedItems.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToInternalObject()) ? mod.ChangedItems.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToInternalObject())
: []; : [];
public IReadOnlyDictionary<string, IReadOnlyDictionary<string, object?>> GetChangedItemAdapterDictionary()
=> new ModChangedItemAdapter(new WeakReference<ModStorage>(_modManager));
public IReadOnlyList<(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)> GetChangedItemAdapterList()
=> new ModChangedItemAdapter(new WeakReference<ModStorage>(_modManager));
} }

View file

@ -22,7 +22,7 @@ public class PenumbraApi(
} }
public (int Breaking, int Feature) ApiVersion public (int Breaking, int Feature) ApiVersion
=> (5, 6); => (5, 7);
public bool Valid { get; private set; } = true; public bool Valid { get; private set; } = true;
public IPenumbraApiCollection Collection { get; } = collection; public IPenumbraApiCollection Collection { get; } = collection;

View file

@ -54,6 +54,8 @@ public sealed class IpcProviders : IDisposable, IApiService
IpcSubscribers.GetModPath.Provider(pi, api.Mods), IpcSubscribers.GetModPath.Provider(pi, api.Mods),
IpcSubscribers.SetModPath.Provider(pi, api.Mods), IpcSubscribers.SetModPath.Provider(pi, api.Mods),
IpcSubscribers.GetChangedItems.Provider(pi, api.Mods), IpcSubscribers.GetChangedItems.Provider(pi, api.Mods),
IpcSubscribers.GetChangedItemAdapterDictionary.Provider(pi, api.Mods),
IpcSubscribers.GetChangedItemAdapterList.Provider(pi, api.Mods),
IpcSubscribers.GetAvailableModSettings.Provider(pi, api.ModSettings), IpcSubscribers.GetAvailableModSettings.Provider(pi, api.ModSettings),
IpcSubscribers.GetCurrentModSettings.Provider(pi, api.ModSettings), IpcSubscribers.GetCurrentModSettings.Provider(pi, api.ModSettings),

View file

@ -15,7 +15,7 @@ public class ModCacheManager : IDisposable, IService
private readonly CommunicatorService _communicator; private readonly CommunicatorService _communicator;
private readonly ObjectIdentification _identifier; private readonly ObjectIdentification _identifier;
private readonly ModStorage _modManager; private readonly ModStorage _modManager;
private bool _updatingItems = false; private bool _updatingItems;
public ModCacheManager(CommunicatorService communicator, ObjectIdentification identifier, ModStorage modStorage, Configuration config) public ModCacheManager(CommunicatorService communicator, ObjectIdentification identifier, ModStorage modStorage, Configuration config)
{ {

View file

@ -0,0 +1,102 @@
using Penumbra.GameData.Data;
namespace Penumbra.Mods.Manager;
public sealed class ModChangedItemAdapter(WeakReference<ModStorage> storage)
: IReadOnlyDictionary<string, IReadOnlyDictionary<string, object?>>,
IReadOnlyList<(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)>
{
IEnumerator<(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)>
IEnumerable<(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)>.GetEnumerator()
=> Storage.Select(m => (m.Identifier, (IReadOnlyDictionary<string, object?>)new ChangedItemDictionaryAdapter(m.ChangedItems)))
.GetEnumerator();
public IEnumerator<KeyValuePair<string, IReadOnlyDictionary<string, object?>>> GetEnumerator()
=> Storage.Select(m => new KeyValuePair<string, IReadOnlyDictionary<string, object?>>(m.Identifier,
new ChangedItemDictionaryAdapter(m.ChangedItems)))
.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
public int Count
=> Storage.Count;
public bool ContainsKey(string key)
=> Storage.TryGetMod(key, string.Empty, out _);
public bool TryGetValue(string key, [NotNullWhen(true)] out IReadOnlyDictionary<string, object?>? value)
{
if (Storage.TryGetMod(key, string.Empty, out var mod))
{
value = new ChangedItemDictionaryAdapter(mod.ChangedItems);
return true;
}
value = null;
return false;
}
public IReadOnlyDictionary<string, object?> this[string key]
=> TryGetValue(key, out var v) ? v : throw new KeyNotFoundException();
(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)
IReadOnlyList<(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)>.this[int index]
{
get
{
var m = Storage[index];
return (m.Identifier, new ChangedItemDictionaryAdapter(m.ChangedItems));
}
}
public IEnumerable<string> Keys
=> Storage.Select(m => m.Identifier);
public IEnumerable<IReadOnlyDictionary<string, object?>> Values
=> Storage.Select(m => new ChangedItemDictionaryAdapter(m.ChangedItems));
private ModStorage Storage
{
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
get => storage.TryGetTarget(out var t)
? t
: throw new ObjectDisposedException("The underlying mod storage of this IPC container was disposed.");
}
private sealed class ChangedItemDictionaryAdapter(SortedList<string, IIdentifiedObjectData?> data) : IReadOnlyDictionary<string, object?>
{
public IEnumerator<KeyValuePair<string, object?>> GetEnumerator()
=> data.Select(d => new KeyValuePair<string, object?>(d.Key, d.Value?.ToInternalObject())).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
public int Count
=> data.Count;
public bool ContainsKey(string key)
=> data.ContainsKey(key);
public bool TryGetValue(string key, out object? value)
{
if (data.TryGetValue(key, out var v))
{
value = v?.ToInternalObject();
return true;
}
value = null;
return false;
}
public object? this[string key]
=> data[key]?.ToInternalObject();
public IEnumerable<string> Keys
=> data.Keys;
public IEnumerable<object?> Values
=> data.Values.Select(v => v?.ToInternalObject());
}
}