elevate penumbra resolving to default resolving method
This commit is contained in:
		| @@ -1,7 +1,4 @@ | ||||
| using FFXIVClientStructs.FFXIV.Client.Game.Character; | ||||
| using FFXIVClientStructs.FFXIV.Client.Graphics.Render; | ||||
| using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; | ||||
| using FFXIVClientStructs.FFXIV.Client.System.Resource; | ||||
| using MareSynchronos.API.Data.Enum; | ||||
| using MareSynchronos.FileCache; | ||||
| using MareSynchronos.Interop; | ||||
| @@ -11,10 +8,7 @@ using MareSynchronos.PlayerData.Handlers; | ||||
| using MareSynchronos.Services; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System.Diagnostics; | ||||
| using System.Globalization; | ||||
| using CharacterData = MareSynchronos.PlayerData.Data.CharacterData; | ||||
| using Object = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.Object; | ||||
| using Weapon = MareSynchronos.Interop.Weapon; | ||||
|  | ||||
| namespace MareSynchronos.PlayerData.Factories; | ||||
|  | ||||
| @@ -26,12 +20,11 @@ public class PlayerDataFactory | ||||
|     private readonly IpcManager _ipcManager; | ||||
|     private readonly ILogger<PlayerDataFactory> _logger; | ||||
|     private readonly PerformanceCollectorService _performanceCollector; | ||||
|     private readonly MareConfigService _mareConfigService; | ||||
|     private readonly TransientResourceManager _transientResourceManager; | ||||
|  | ||||
|     public PlayerDataFactory(ILogger<PlayerDataFactory> logger, DalamudUtilService dalamudUtil, IpcManager ipcManager, | ||||
|         TransientResourceManager transientResourceManager, FileCacheManager fileReplacementFactory, | ||||
|         PerformanceCollectorService performanceCollector, MareConfigService mareConfigService) | ||||
|         PerformanceCollectorService performanceCollector) | ||||
|     { | ||||
|         _logger = logger; | ||||
|         _dalamudUtil = dalamudUtil; | ||||
| @@ -39,7 +32,6 @@ public class PlayerDataFactory | ||||
|         _transientResourceManager = transientResourceManager; | ||||
|         _fileCacheManager = fileReplacementFactory; | ||||
|         _performanceCollector = performanceCollector; | ||||
|         _mareConfigService = mareConfigService; | ||||
|         _logger.LogTrace("Creating " + nameof(PlayerDataFactory)); | ||||
|     } | ||||
|  | ||||
| @@ -107,190 +99,6 @@ public class PlayerDataFactory | ||||
|         previousData.CustomizePlusScale = previousCustomize; | ||||
|     } | ||||
|  | ||||
|     private unsafe void AddPlayerSpecificReplacements(Human* human, HashSet<string> forwardResolve, HashSet<string> reverseResolve) | ||||
|     { | ||||
|         var weaponObject = (Weapon*)((Object*)human)->ChildObject; | ||||
|  | ||||
|         if ((IntPtr)weaponObject != IntPtr.Zero) | ||||
|         { | ||||
|             var mainHandWeapon = weaponObject->WeaponRenderModel->RenderModel; | ||||
|  | ||||
|             AddReplacementsFromRenderModel((Model*)mainHandWeapon, forwardResolve, reverseResolve); | ||||
|  | ||||
|             foreach (var item in _transientResourceManager.GetTransientResources((IntPtr)weaponObject)) | ||||
|             { | ||||
|                 _logger.LogTrace("Found transient weapon resource: {item}", item); | ||||
|                 forwardResolve.Add(item); | ||||
|             } | ||||
|  | ||||
|             if (weaponObject->NextSibling != (IntPtr)weaponObject) | ||||
|             { | ||||
|                 var offHandWeapon = ((Weapon*)weaponObject->NextSibling)->WeaponRenderModel->RenderModel; | ||||
|  | ||||
|                 AddReplacementsFromRenderModel((Model*)offHandWeapon, forwardResolve, reverseResolve); | ||||
|  | ||||
|                 foreach (var item in _transientResourceManager.GetTransientResources((IntPtr)offHandWeapon)) | ||||
|                 { | ||||
|                     _logger.LogTrace("Found transient offhand weapon resource: {item}", item); | ||||
|                     forwardResolve.Add(item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         AddReplacementSkeleton((human)->RaceSexId, forwardResolve); | ||||
|         try | ||||
|         { | ||||
|             AddReplacementsFromTexture((human)->Decal->ResourceHandle.FileName.ToString(), forwardResolve, reverseResolve, doNotReverseResolve: false); | ||||
|         } | ||||
|         catch | ||||
|         { | ||||
|             _logger.LogWarning("Could not get Decal data"); | ||||
|         } | ||||
|         try | ||||
|         { | ||||
|             AddReplacementsFromTexture((human)->LegacyBodyDecal->ResourceHandle.FileName.ToString(), forwardResolve, reverseResolve, doNotReverseResolve: false); | ||||
|         } | ||||
|         catch | ||||
|         { | ||||
|             _logger.LogWarning("Could not get Legacy Body Decal Data"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private unsafe void AddReplacementsFromMaterial(Material* mtrl, HashSet<string> forwardResolve, HashSet<string> reverseResolve) | ||||
|     { | ||||
|         string fileName; | ||||
|         try | ||||
|         { | ||||
|             fileName = mtrl->MaterialResourceHandle->ResourceHandle.FileName.ToString(); | ||||
|         } | ||||
|         catch | ||||
|         { | ||||
|             _logger.LogWarning("Could not get material data"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         _logger.LogTrace("Checking File Replacement for Material {file}", fileName); | ||||
|         var mtrlPath = fileName.Split("|")[2]; | ||||
|  | ||||
|         reverseResolve.Add(mtrlPath); | ||||
|  | ||||
|         var mtrlResourceHandle = mtrl->MaterialResourceHandle; | ||||
|         for (var resIdx = 0; resIdx < mtrlResourceHandle->TextureCount; resIdx++) | ||||
|         { | ||||
|             string? texPath = null; | ||||
|             try | ||||
|             { | ||||
|                 texPath = mtrlResourceHandle->TexturePathString(resIdx); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 _logger.LogWarning(e, "Could not get Texture data for Material {file}", fileName); | ||||
|             } | ||||
|  | ||||
|             if (string.IsNullOrEmpty(texPath)) continue; | ||||
|  | ||||
|             AddReplacementsFromTexture(texPath, forwardResolve, reverseResolve); | ||||
|         } | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             var shpkPath = "shader/sm5/shpk/" + mtrlResourceHandle->ShpkNameString; | ||||
|             _logger.LogTrace("Checking File Replacement for Shader {path}", shpkPath); | ||||
|             forwardResolve.Add(shpkPath); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             _logger.LogWarning(ex, "Could not find shpk for Material {path}", fileName); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private unsafe void AddReplacementsFromRenderModel(Model* mdl, HashSet<string> forwardResolve, HashSet<string> reverseResolve) | ||||
|     { | ||||
|         if (mdl == null || mdl->ModelResourceHandle == null || (ResourceCategory)mdl->ModelResourceHandle->ResourceHandle.Type.Value != ResourceCategory.Chara) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         string mdlPath; | ||||
|         try | ||||
|         { | ||||
|             mdlPath = mdl->ModelResourceHandle->ResourceHandle.FileName.ToString(); | ||||
|         } | ||||
|         catch | ||||
|         { | ||||
|             _logger.LogWarning("Could not get model data"); | ||||
|             return; | ||||
|         } | ||||
|         _logger.LogTrace("Checking File Replacement for Model {path}", mdlPath); | ||||
|  | ||||
|         reverseResolve.Add(mdlPath); | ||||
|  | ||||
|         for (var mtrlIdx = 0; mtrlIdx < mdl->MaterialCount; mtrlIdx++) | ||||
|         { | ||||
|             var mtrl = mdl->Materials[mtrlIdx]; | ||||
|             if (mtrl == null) continue; | ||||
|  | ||||
|             AddReplacementsFromMaterial(mtrl, forwardResolve, reverseResolve); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void AddReplacementsFromTexture(string texPath, HashSet<string> forwardResolve, HashSet<string> reverseResolve, bool doNotReverseResolve = true) | ||||
|     { | ||||
|         if (string.IsNullOrEmpty(texPath)) return; | ||||
|  | ||||
|         _logger.LogTrace("Checking File Replacement for Texture {path}", texPath); | ||||
|  | ||||
|         if (doNotReverseResolve) | ||||
|             forwardResolve.Add(texPath); | ||||
|         else | ||||
|             reverseResolve.Add(texPath); | ||||
|  | ||||
|         if (texPath.Contains("/--", StringComparison.Ordinal)) return; | ||||
|  | ||||
|         var dx11Path = texPath.Insert(texPath.LastIndexOf('/') + 1, "--"); | ||||
|         if (doNotReverseResolve) | ||||
|             forwardResolve.Add(dx11Path); | ||||
|         else | ||||
|             reverseResolve.Add(dx11Path); | ||||
|     } | ||||
|  | ||||
|     private void AddReplacementSkeleton(ushort raceSexId, HashSet<string> forwardResolve) | ||||
|     { | ||||
|         string raceSexIdString = raceSexId.ToString("0000", CultureInfo.InvariantCulture); | ||||
|  | ||||
|         string skeletonPath = $"chara/human/c{raceSexIdString}/skeleton/base/b0001/skl_c{raceSexIdString}b0001.sklb"; | ||||
|  | ||||
|         _logger.LogTrace("Checking skeleton {path}", skeletonPath); | ||||
|  | ||||
|         forwardResolve.Add(skeletonPath); | ||||
|     } | ||||
|  | ||||
|     private unsafe (HashSet<string> forwardResolve, HashSet<string> reverseResolve) BuildDataFromModel(ObjectKind objectKind, nint charaPointer, CancellationToken token) | ||||
|     { | ||||
|         HashSet<string> forwardResolve = new(StringComparer.Ordinal); | ||||
|         HashSet<string> reverseResolve = new(StringComparer.Ordinal); | ||||
|         var human = (Human*)((Character*)charaPointer)->GameObject.GetDrawObject(); | ||||
|         for (var mdlIdx = 0; mdlIdx < human->CharacterBase.SlotCount; ++mdlIdx) | ||||
|         { | ||||
|             var mdl = human->CharacterBase.Models[mdlIdx]; | ||||
|             if (mdl == null || mdl->ModelResourceHandle == null || (ResourceCategory)mdl->ModelResourceHandle->ResourceHandle.Type.Value != ResourceCategory.Chara) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             token.ThrowIfCancellationRequested(); | ||||
|  | ||||
|             AddReplacementsFromRenderModel(mdl, forwardResolve, reverseResolve); | ||||
|         } | ||||
|  | ||||
|         if (objectKind == ObjectKind.Player && human->CharacterBase.GetModelType() == CharacterBase.ModelType.Human) | ||||
|         { | ||||
|             AddPlayerSpecificReplacements(human, forwardResolve, reverseResolve); | ||||
|         } | ||||
|  | ||||
|         return (forwardResolve, reverseResolve); | ||||
|     } | ||||
|  | ||||
|     private async Task<bool> CheckForNullDrawObject(IntPtr playerPointer) | ||||
|     { | ||||
|         return await _dalamudUtil.RunOnFrameworkThread(() => CheckForNullDrawObjectUnsafe(playerPointer)).ConfigureAwait(false); | ||||
| @@ -333,17 +141,10 @@ public class PlayerDataFactory | ||||
|  | ||||
|         // penumbra call, it's currently broken | ||||
|         IReadOnlyDictionary<string, string[]>? resolvedPaths; | ||||
|         if (_mareConfigService.Current.ExperimentalUsePenumbraResourceTree) | ||||
|         { | ||||
|             resolvedPaths = (await _ipcManager.PenumbraGetCharacterData(_logger, playerRelatedObject).ConfigureAwait(false))![0]; | ||||
|             if (resolvedPaths == null) throw new InvalidOperationException("Penumbra returned null data"); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // gather static replacements from render model | ||||
|             var (forwardResolve, reverseResolve) = await _dalamudUtil.RunOnFrameworkThread(() => BuildDataFromModel(objectKind, charaPointer, token)).ConfigureAwait(false); | ||||
|             resolvedPaths = await GetFileReplacementsFromPaths(forwardResolve, reverseResolve).ConfigureAwait(false); | ||||
|         } | ||||
|  | ||||
|         resolvedPaths = (await _ipcManager.PenumbraGetCharacterData(_logger, playerRelatedObject).ConfigureAwait(false))![0]; | ||||
|         if (resolvedPaths == null) throw new InvalidOperationException("Penumbra returned null data"); | ||||
|  | ||||
|         previousData.FileReplacements[objectKind] = | ||||
|                 new HashSet<FileReplacement>(resolvedPaths.Select(c => new FileReplacement([.. c.Value], c.Key)), FileReplacementComparer.Instance) | ||||
|                 .Where(p => p.HasFileReplacement).ToHashSet(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 rootdarkarchon
					rootdarkarchon