Atch stuff.

This commit is contained in:
Ottermandias 2024-11-22 12:19:14 +01:00
parent 65538868c3
commit b1be868a6a
32 changed files with 802 additions and 43 deletions

View file

@ -0,0 +1,122 @@
using Penumbra.GameData.Enums;
using Penumbra.GameData.Files;
using Penumbra.GameData.Files.AtchStructs;
using Penumbra.Meta;
using Penumbra.Meta.Files;
using Penumbra.Meta.Manipulations;
namespace Penumbra.Collections.Cache;
public sealed class AtchCache(MetaFileManager manager, ModCollection collection) : MetaCacheBase<AtchIdentifier, AtchEntry>(manager, collection)
{
private readonly Dictionary<GenderRace, (AtchFile, HashSet<AtchIdentifier>)> _atchFiles = [];
public bool HasFile(GenderRace gr)
=> _atchFiles.ContainsKey(gr);
public bool GetFile(GenderRace gr, [NotNullWhen(true)] out AtchFile? file)
{
if (!_atchFiles.TryGetValue(gr, out var p))
{
file = null;
return false;
}
file = p.Item1;
return true;
}
public void Reset()
{
foreach (var (_, (_, set)) in _atchFiles)
set.Clear();
_atchFiles.Clear();
Clear();
}
protected override void ApplyModInternal(AtchIdentifier identifier, AtchEntry entry)
{
++Collection.AtchChangeCounter;
ApplyFile(identifier, entry);
}
private void ApplyFile(AtchIdentifier identifier, AtchEntry entry)
{
try
{
if (!_atchFiles.TryGetValue(identifier.GenderRace, out var pair))
{
if (!Manager.AtchManager.AtchFileBase.TryGetValue(identifier.GenderRace, out var baseFile))
throw new Exception($"Invalid Atch File for {identifier.GenderRace.ToName()} requested.");
pair = (baseFile.Clone(), []);
}
if (!Apply(pair.Item1, identifier, entry))
return;
pair.Item2.Add(identifier);
_atchFiles[identifier.GenderRace] = pair;
}
catch (Exception e)
{
Penumbra.Log.Error($"Could not apply ATCH Manipulation {identifier}:\n{e}");
}
}
protected override void RevertModInternal(AtchIdentifier identifier)
{
++Collection.AtchChangeCounter;
if (!_atchFiles.TryGetValue(identifier.GenderRace, out var pair))
return;
if (!pair.Item2.Remove(identifier))
return;
if (pair.Item2.Count == 0)
{
_atchFiles.Remove(identifier.GenderRace);
return;
}
var def = GetDefault(Manager, identifier);
if (def == null)
throw new Exception($"Reverting an .atch mod had no default value for the identifier to revert to.");
Apply(pair.Item1, identifier, def.Value);
}
public static AtchEntry? GetDefault(MetaFileManager manager, AtchIdentifier identifier)
{
if (!manager.AtchManager.AtchFileBase.TryGetValue(identifier.GenderRace, out var baseFile))
return null;
if (baseFile.Points.FirstOrDefault(p => p.Type == identifier.Type) is not { } point)
return null;
if (point.Entries.Length <= identifier.EntryIndex)
return null;
return point.Entries[identifier.EntryIndex];
}
public static bool Apply(AtchFile file, AtchIdentifier identifier, in AtchEntry entry)
{
if (file.Points.FirstOrDefault(p => p.Type == identifier.Type) is not { } point)
return false;
if (point.Entries.Length <= identifier.EntryIndex)
return false;
point.Entries[identifier.EntryIndex] = entry;
return true;
}
protected override void Dispose(bool _)
{
Clear();
_atchFiles.Clear();
}
}

View file

@ -228,20 +228,25 @@ public sealed class CollectionCache : IDisposable
foreach (var (path, file) in files.FileRedirections)
AddFile(path, file, mod);
foreach (var (identifier, entry) in files.Manipulations.Eqp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Eqdp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Est)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Gmp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Rsp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Imc)
AddManipulation(mod, identifier, entry);
foreach (var identifier in files.Manipulations.GlobalEqp)
AddManipulation(mod, identifier, null!);
if (files.Manipulations.Count > 0)
{
foreach (var (identifier, entry) in files.Manipulations.Eqp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Eqdp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Est)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Gmp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Rsp)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Imc)
AddManipulation(mod, identifier, entry);
foreach (var (identifier, entry) in files.Manipulations.Atch)
AddManipulation(mod, identifier, entry);
foreach (var identifier in files.Manipulations.GlobalEqp)
AddManipulation(mod, identifier, null!);
}
if (addMetaChanges)
{

View file

@ -1,4 +1,5 @@
using Penumbra.GameData.Enums;
using Penumbra.GameData.Files.AtchStructs;
using Penumbra.GameData.Structs;
using Penumbra.Meta;
using Penumbra.Meta.Manipulations;
@ -14,11 +15,12 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
public readonly GmpCache Gmp = new(manager, collection);
public readonly RspCache Rsp = new(manager, collection);
public readonly ImcCache Imc = new(manager, collection);
public readonly AtchCache Atch = 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 + GlobalEqp.Count;
=> Eqp.Count + Eqdp.Count + Est.Count + Gmp.Count + Rsp.Count + Imc.Count + Atch.Count + GlobalEqp.Count;
public IEnumerable<(IMetaIdentifier, IMod)> IdentifierSources
=> Eqp.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value.Source))
@ -27,6 +29,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
.Concat(Gmp.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value.Source)))
.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(GlobalEqp.Select(kvp => ((IMetaIdentifier)kvp.Key, kvp.Value)));
public void Reset()
@ -37,6 +40,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
Gmp.Reset();
Rsp.Reset();
Imc.Reset();
Atch.Reset();
GlobalEqp.Clear();
}
@ -52,6 +56,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
Gmp.Dispose();
Rsp.Dispose();
Imc.Dispose();
Atch.Dispose();
}
public bool TryGetMod(IMetaIdentifier identifier, [NotNullWhen(true)] out IMod? mod)
@ -65,6 +70,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
GmpIdentifier i => Gmp.TryGetValue(i, out var p) && Convert(p, out mod),
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),
GlobalEqpManipulation i => GlobalEqp.TryGetValue(i, out mod),
_ => false,
};
@ -85,6 +91,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
GmpIdentifier i => Gmp.RevertMod(i, out mod),
ImcIdentifier i => Imc.RevertMod(i, out mod),
RspIdentifier i => Rsp.RevertMod(i, out mod),
AtchIdentifier i => Atch.RevertMod(i, out mod),
GlobalEqpManipulation i => GlobalEqp.RevertMod(i, out mod),
_ => (mod = null) != null,
};
@ -100,6 +107,7 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
GmpIdentifier i when entry is GmpEntry e => Gmp.ApplyMod(mod, i, e),
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),
GlobalEqpManipulation i => GlobalEqp.ApplyMod(mod, i),
_ => false,
};