diff --git a/src/Lumina/Models/Materials/Material.cs b/src/Lumina/Models/Materials/Material.cs
index 880053e2..f55ee4c1 100644
--- a/src/Lumina/Models/Materials/Material.cs
+++ b/src/Lumina/Models/Materials/Material.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using Lumina.Data;
using Lumina.Data.Files;
@@ -137,6 +138,12 @@ public Material Update( GameData data )
return this;
}
+ ///
+ /// This overload is present to maintain compatibility with already compiled binaries and will eventually be removed.
+ [OverloadResolutionPriority( 0 )]
+ public static string? ResolveRelativeMaterialPath( string relativePath, int variantId )
+ => ResolveRelativeMaterialPath( relativePath, variantId, true );
+
///
/// Resolves a relative material path in the form /mt_c0101e0001_top_a.mtrl
/// into its full path, chara/equipment/e0001/material/v{variantId}/mt_c0101e0001_top_a.mtrl.
@@ -145,20 +152,22 @@ public Material Update( GameData data )
///
/// The relative path of the provided material.
/// The variant to use in material resolution.
+ /// Whether to strictly validate suffixes. If dealing with mods, you may want to turn this off.
/// The resolved, absolute path to the requested material, or null if unsuccessful.
- public static string? ResolveRelativeMaterialPath( string relativePath, int variantId )
+ [OverloadResolutionPriority( 1 )]
+ public static string? ResolveRelativeMaterialPath( string relativePath, int variantId, bool strictSuffixValidation = true )
{
- Regex rx = MatNameRegex();
+ Regex rx = strictSuffixValidation ? MatNameRegexStrictSuffix() : MatNameRegexLaxSuffix();
var result = rx.Match( relativePath );
if( !result.Success )
return null;
- var id1 = result.Groups["id1"].Value[0];
- var val1 = result.Groups["val1"].Value;
- var id2 = result.Groups["id2"].Value[0];
- var val2 = result.Groups["val2"].Value;
+ var id1 = result.Groups[ "id1" ].Value[ 0 ];
+ var val1 = result.Groups[ "val1" ].Value;
+ var id2 = result.Groups[ "id2" ].Value[ 0 ];
+ var val2 = result.Groups[ "val2" ].Value;
- return (id1, id2) switch
+ return ( id1, id2 ) switch
{
('c', 'a') => $"chara/accessory/a{val2}/material/v{variantId:D4}{relativePath}",
('c', 'b') => $"chara/human/c{val1}/obj/body/b{val2}/material/v{variantId:D4}{relativePath}",
@@ -173,11 +182,14 @@ public Material Update( GameData data )
(_, _) => null
};
}
-
- [GeneratedRegex(@"/mt_(?'id1'[cdmw])(?'val1'\d{4})(?'id2'[abefhtze])(?'val2'\d{4})_(?:\w{3}(?:_\w)|(?:\w))\.mtrl")]
- private static partial Regex MatNameRegex();
-
-
+
+ [GeneratedRegex( @"/mt_(?'id1'[cdmw])(?'val1'\d{4})(?'id2'[abefhtze])(?'val2'\d{4})_(?:\w{3}_\w|\w)\.mtrl$" )]
+ private static partial Regex MatNameRegexStrictSuffix();
+
+ [GeneratedRegex( @"/mt_(?'id1'[cdmw])(?'val1'\d{4})(?'id2'[abefhtze])(?'val2'\d{4})_\w+\.mtrl$" )]
+ private static partial Regex MatNameRegexLaxSuffix();
+
+
///
/// Parse the variant ID out of an existing absolute path to a .mtrl file.
///
@@ -242,4 +254,4 @@ private void ReadStrings()
br.Dispose();
}
}
-}
\ No newline at end of file
+}