Add some functionality to allow an IMC group to add apply to all variants.

This commit is contained in:
Ottermandias 2024-06-02 12:08:49 +02:00
parent 137b752196
commit 05d010a281
10 changed files with 117 additions and 46 deletions

View file

@ -9,20 +9,20 @@ namespace Penumbra.Meta.Files;
public class ImcException : Exception
{
public readonly ImcManipulation Manipulation;
public readonly string GamePath;
public readonly ImcIdentifier Identifier;
public readonly string GamePath;
public ImcException(ImcManipulation manip, Utf8GamePath path)
public ImcException(ImcIdentifier identifier, Utf8GamePath path)
{
Manipulation = manip;
GamePath = path.ToString();
Identifier = identifier;
GamePath = path.ToString();
}
public override string Message
=> "Could not obtain default Imc File.\n"
+ " Either the default file does not exist (possibly for offhand files from TexTools) or the installation is corrupted.\n"
+ $" Game Path: {GamePath}\n"
+ $" Manipulation: {Manipulation}";
+ $" Manipulation: {Identifier}";
}
public unsafe class ImcFile : MetaBaseFile
@ -142,13 +142,14 @@ public unsafe class ImcFile : MetaBaseFile
}
}
public ImcFile(MetaFileManager manager, ImcManipulation manip)
public ImcFile(MetaFileManager manager, ImcIdentifier identifier)
: base(manager, 0)
{
Path = manip.GamePath();
var file = manager.GameData.GetFile(Path.ToString());
var path = identifier.GamePathString();
Path = Utf8GamePath.FromString(path, out var p) ? p : Utf8GamePath.Empty;
var file = manager.GameData.GetFile(path);
if (file == null)
throw new ImcException(manip, Path);
throw new ImcException(identifier, Path);
fixed (byte* ptr = file.Data)
{

View file

@ -4,11 +4,32 @@ using Penumbra.Meta.Manipulations;
namespace Penumbra.Meta;
public class ImcChecker(MetaFileManager metaFileManager)
public class ImcChecker
{
private static readonly Dictionary<ImcIdentifier, int> VariantCounts = [];
private static MetaFileManager? _dataManager;
public static int GetVariantCount(ImcIdentifier identifier)
{
if (VariantCounts.TryGetValue(identifier, out var count))
return count;
count = GetFile(identifier)?.Count ?? 0;
VariantCounts[identifier] = count;
return count;
}
public readonly record struct CachedEntry(ImcEntry Entry, bool FileExists, bool VariantExists);
private readonly Dictionary<ImcIdentifier, CachedEntry> _cachedDefaultEntries = new();
private readonly MetaFileManager _metaFileManager;
public ImcChecker(MetaFileManager metaFileManager)
{
_metaFileManager = metaFileManager;
_dataManager = metaFileManager;
}
public CachedEntry GetDefaultEntry(ImcIdentifier identifier, bool storeCache)
{
@ -17,7 +38,7 @@ public class ImcChecker(MetaFileManager metaFileManager)
try
{
var e = ImcFile.GetDefault(metaFileManager, identifier.GamePath(), identifier.EquipSlot, identifier.Variant, out var entryExists);
var e = ImcFile.GetDefault(_metaFileManager, identifier.GamePath(), identifier.EquipSlot, identifier.Variant, out var entryExists);
entry = new CachedEntry(e, true, entryExists);
}
catch (Exception)
@ -33,4 +54,19 @@ public class ImcChecker(MetaFileManager metaFileManager)
public CachedEntry GetDefaultEntry(ImcManipulation imcManip, bool storeCache)
=> GetDefaultEntry(new ImcIdentifier(imcManip.PrimaryId, imcManip.Variant, imcManip.ObjectType, imcManip.SecondaryId.Id,
imcManip.EquipSlot, imcManip.BodySlot), storeCache);
private static ImcFile? GetFile(ImcIdentifier identifier)
{
if (_dataManager == null)
return null;
try
{
return new ImcFile(_dataManager, identifier);
}
catch
{
return null;
}
}
}

View file

@ -31,12 +31,16 @@ public readonly record struct ImcIdentifier(
=> new(ObjectType, BodySlot, PrimaryId, SecondaryId.Id, Variant.Id, EquipSlot, entry);
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems)
=> AddChangedItems(identifier, changedItems, false);
public void AddChangedItems(ObjectIdentification identifier, IDictionary<string, object?> changedItems, bool allVariants)
{
var path = ObjectType switch
{
ObjectType.Equipment or ObjectType.Accessory => GamePaths.Equipment.Mtrl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot,
Variant,
"a"),
ObjectType.Equipment when allVariants => GamePaths.Equipment.Mdl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot),
ObjectType.Equipment => GamePaths.Equipment.Mtrl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot, Variant, "a"),
ObjectType.Accessory when allVariants => GamePaths.Accessory.Mdl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot),
ObjectType.Accessory => GamePaths.Accessory.Mtrl.Path(PrimaryId, GenderRace.MidlanderMale, EquipSlot, Variant, "a"),
ObjectType.Weapon => GamePaths.Weapon.Mtrl.Path(PrimaryId, SecondaryId.Id, Variant, "a"),
ObjectType.DemiHuman => GamePaths.DemiHuman.Mtrl.Path(PrimaryId, SecondaryId.Id, EquipSlot, Variant,
"a"),
@ -49,24 +53,19 @@ public readonly record struct ImcIdentifier(
identifier.Identify(changedItems, path);
}
public Utf8GamePath GamePath()
{
return ObjectType switch
public string GamePathString()
=> ObjectType switch
{
ObjectType.Accessory => Utf8GamePath.FromString(GamePaths.Accessory.Imc.Path(PrimaryId), out var p) ? p : Utf8GamePath.Empty,
ObjectType.Equipment => Utf8GamePath.FromString(GamePaths.Equipment.Imc.Path(PrimaryId), out var p) ? p : Utf8GamePath.Empty,
ObjectType.DemiHuman => Utf8GamePath.FromString(GamePaths.DemiHuman.Imc.Path(PrimaryId, SecondaryId.Id), out var p)
? p
: Utf8GamePath.Empty,
ObjectType.Monster => Utf8GamePath.FromString(GamePaths.Monster.Imc.Path(PrimaryId, SecondaryId.Id), out var p)
? p
: Utf8GamePath.Empty,
ObjectType.Weapon => Utf8GamePath.FromString(GamePaths.Weapon.Imc.Path(PrimaryId, SecondaryId.Id), out var p)
? p
: Utf8GamePath.Empty,
_ => throw new NotImplementedException(),
ObjectType.Accessory => GamePaths.Accessory.Imc.Path(PrimaryId),
ObjectType.Equipment => GamePaths.Equipment.Imc.Path(PrimaryId),
ObjectType.DemiHuman => GamePaths.DemiHuman.Imc.Path(PrimaryId, SecondaryId.Id),
ObjectType.Monster => GamePaths.Monster.Imc.Path(PrimaryId, SecondaryId.Id),
ObjectType.Weapon => GamePaths.Weapon.Imc.Path(PrimaryId, SecondaryId.Id),
_ => string.Empty,
};
}
public Utf8GamePath GamePath()
=> Utf8GamePath.FromString(GamePathString(), out var p) ? p : Utf8GamePath.Empty;
public MetaIndex FileIndex()
=> (MetaIndex)(-1);