mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-01-03 06:13:45 +01:00
Add shape meta manipulations and rework attribute hook.
This commit is contained in:
parent
0adec35848
commit
6ad0b4299a
23 changed files with 900 additions and 298 deletions
|
|
@ -245,6 +245,8 @@ public sealed class CollectionCache : IDisposable
|
|||
AddManipulation(mod, identifier, entry);
|
||||
foreach (var (identifier, entry) in files.Manipulations.Atch)
|
||||
AddManipulation(mod, identifier, entry);
|
||||
foreach (var (identifier, entry) in files.Manipulations.Shp)
|
||||
AddManipulation(mod, identifier, entry);
|
||||
foreach (var identifier in files.Manipulations.GlobalEqp)
|
||||
AddManipulation(mod, identifier, null!);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
|||
public readonly RspCache Rsp = new(manager, collection);
|
||||
public readonly ImcCache Imc = new(manager, collection);
|
||||
public readonly AtchCache Atch = new(manager, collection);
|
||||
public readonly ShpCache Shp = new(manager, collection);
|
||||
public readonly GlobalEqpCache GlobalEqp = new();
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
public int Count
|
||||
=> Eqp.Count + Eqdp.Count + Est.Count + Gmp.Count + Rsp.Count + Imc.Count + Atch.Count + GlobalEqp.Count;
|
||||
=> Eqp.Count + Eqdp.Count + Est.Count + Gmp.Count + Rsp.Count + Imc.Count + Atch.Count + Shp.Count + GlobalEqp.Count;
|
||||
|
||||
public IEnumerable<(IMetaIdentifier, IMod)> IdentifierSources
|
||||
=> Eqp.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value.Source))
|
||||
|
|
@ -30,6 +31,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
|||
.Concat(Rsp.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value.Source)))
|
||||
.Concat(Imc.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value.Source)))
|
||||
.Concat(Atch.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value.Source)))
|
||||
.Concat(Shp.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value.Source)))
|
||||
.Concat(GlobalEqp.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value)));
|
||||
|
||||
public void Reset()
|
||||
|
|
@ -41,6 +43,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
|||
Rsp.Reset();
|
||||
Imc.Reset();
|
||||
Atch.Reset();
|
||||
Shp.Reset();
|
||||
GlobalEqp.Clear();
|
||||
}
|
||||
|
||||
|
|
@ -57,6 +60,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
|||
Rsp.Dispose();
|
||||
Imc.Dispose();
|
||||
Atch.Dispose();
|
||||
Shp.Dispose();
|
||||
}
|
||||
|
||||
public bool TryGetMod(IMetaIdentifier identifier, [NotNullWhen(true)] out IMod? mod)
|
||||
|
|
@ -71,6 +75,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
|||
ImcIdentifier i => Imc.TryGetValue(i, out var p) && Convert(p, out mod),
|
||||
RspIdentifier i => Rsp.TryGetValue(i, out var p) && Convert(p, out mod),
|
||||
AtchIdentifier i => Atch.TryGetValue(i, out var p) && Convert(p, out mod),
|
||||
ShpIdentifier i => Shp.TryGetValue(i, out var p) && Convert(p, out mod),
|
||||
GlobalEqpManipulation i => GlobalEqp.TryGetValue(i, out mod),
|
||||
_ => false,
|
||||
};
|
||||
|
|
@ -92,6 +97,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
|||
ImcIdentifier i => Imc.RevertMod(i, out mod),
|
||||
RspIdentifier i => Rsp.RevertMod(i, out mod),
|
||||
AtchIdentifier i => Atch.RevertMod(i, out mod),
|
||||
ShpIdentifier i => Shp.RevertMod(i, out mod),
|
||||
GlobalEqpManipulation i => GlobalEqp.RevertMod(i, out mod),
|
||||
_ => (mod = null) != null,
|
||||
};
|
||||
|
|
@ -108,6 +114,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
|||
ImcIdentifier i when entry is ImcEntry e => Imc.ApplyMod(mod, i, e),
|
||||
RspIdentifier i when entry is RspEntry e => Rsp.ApplyMod(mod, i, e),
|
||||
AtchIdentifier i when entry is AtchEntry e => Atch.ApplyMod(mod, i, e),
|
||||
ShpIdentifier i when entry is ShpEntry e => Shp.ApplyMod(mod, i, e),
|
||||
GlobalEqpManipulation i => GlobalEqp.ApplyMod(mod, i),
|
||||
_ => false,
|
||||
};
|
||||
|
|
|
|||
109
Penumbra/Collections/Cache/ShpCache.cs
Normal file
109
Penumbra/Collections/Cache/ShpCache.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Meta;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
|
||||
namespace Penumbra.Collections.Cache;
|
||||
|
||||
public sealed class ShpCache(MetaFileManager manager, ModCollection collection) : MetaCacheBase<ShpIdentifier, ShpEntry>(manager, collection)
|
||||
{
|
||||
public bool ShouldBeEnabled(in ShapeString shape, HumanSlot slot, PrimaryId id)
|
||||
=> _shpData.TryGetValue(shape, out var value) && value.Contains(slot, id);
|
||||
|
||||
internal IReadOnlyDictionary<ShapeString, ShpHashSet> State
|
||||
=> _shpData;
|
||||
|
||||
internal sealed class ShpHashSet : HashSet<(HumanSlot Slot, PrimaryId Id)>
|
||||
{
|
||||
private readonly BitArray _allIds = new(ShapeManager.ModelSlotSize);
|
||||
|
||||
public bool All
|
||||
{
|
||||
get => _allIds[^1];
|
||||
set => _allIds[^1] = value;
|
||||
}
|
||||
|
||||
public bool this[HumanSlot slot]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (slot is HumanSlot.Unknown)
|
||||
return All;
|
||||
|
||||
return _allIds[(int)slot];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (slot is HumanSlot.Unknown)
|
||||
_allIds[^1] = value;
|
||||
else
|
||||
_allIds[(int)slot] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(HumanSlot slot, PrimaryId id)
|
||||
=> All || this[slot] || Contains((slot, id));
|
||||
|
||||
public bool TrySet(HumanSlot slot, PrimaryId? id, ShpEntry value)
|
||||
{
|
||||
if (slot is HumanSlot.Unknown)
|
||||
{
|
||||
var old = All;
|
||||
All = value.Value;
|
||||
return old != value.Value;
|
||||
}
|
||||
|
||||
if (!id.HasValue)
|
||||
{
|
||||
var old = this[slot];
|
||||
this[slot] = value.Value;
|
||||
return old != value.Value;
|
||||
}
|
||||
|
||||
if (value.Value)
|
||||
return Add((slot, id.Value));
|
||||
|
||||
return Remove((slot, id.Value));
|
||||
}
|
||||
|
||||
public new void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
_allIds.SetAll(false);
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
=> !_allIds.HasAnySet() && Count is 0;
|
||||
}
|
||||
|
||||
private readonly Dictionary<ShapeString, ShpHashSet> _shpData = [];
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Clear();
|
||||
_shpData.Clear();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool _)
|
||||
=> Clear();
|
||||
|
||||
protected override void ApplyModInternal(ShpIdentifier identifier, ShpEntry entry)
|
||||
{
|
||||
if (!_shpData.TryGetValue(identifier.Shape, out var value))
|
||||
{
|
||||
value = [];
|
||||
_shpData.Add(identifier.Shape, value);
|
||||
}
|
||||
|
||||
value.TrySet(identifier.Slot, identifier.Id, entry);
|
||||
}
|
||||
|
||||
protected override void RevertModInternal(ShpIdentifier identifier)
|
||||
{
|
||||
if (!_shpData.TryGetValue(identifier.Shape, out var value))
|
||||
return;
|
||||
|
||||
if (value.TrySet(identifier.Slot, identifier.Id, ShpEntry.False) && value.IsEmpty)
|
||||
_shpData.Remove(identifier.Shape);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue