From ce28799db388796ff50a0b55da26eaafab5fd260 Mon Sep 17 00:00:00 2001 From: defnotken Date: Mon, 5 Jan 2026 20:46:14 -0600 Subject: [PATCH] More checks for animations and bones. --- LightlessSync/Services/XivDataAnalyzer.cs | 51 ++++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/LightlessSync/Services/XivDataAnalyzer.cs b/LightlessSync/Services/XivDataAnalyzer.cs index cd3b20c..65d9346 100644 --- a/LightlessSync/Services/XivDataAnalyzer.cs +++ b/LightlessSync/Services/XivDataAnalyzer.cs @@ -202,7 +202,7 @@ public sealed partial class XivDataAnalyzer var tempSets = new Dictionary>(StringComparer.OrdinalIgnoreCase); - var tempFileName = $"lightless_pap_{Guid.NewGuid():N}_{hash.Substring(0, Math.Min(8, hash.Length))}.hkx"; + var tempFileName = $"lightless_pap_{Guid.NewGuid():N}_{hash[..Math.Min(8, hash.Length)]}.hkx"; var tempHavokDataPath = Path.Combine(Path.GetTempPath(), tempFileName); IntPtr tempHavokDataPathAnsi = IntPtr.Zero; @@ -215,7 +215,16 @@ public sealed partial class XivDataAnalyzer return null; } - File.WriteAllBytes(tempHavokDataPath, havokData); + // Write the file with explicit error handling + try + { + File.WriteAllBytes(tempHavokDataPath, havokData); + } + catch (Exception writeEx) + { + _logger.LogError(writeEx, "Failed to write temporary Havok file to {path}", tempHavokDataPath); + return null; + } if (!File.Exists(tempHavokDataPath)) { @@ -228,7 +237,26 @@ public sealed partial class XivDataAnalyzer { _logger.LogWarning("Written temp file size mismatch: expected {expected}, got {actual}", havokData.Length, writtenFileInfo.Length); - File.Delete(tempHavokDataPath); + try { File.Delete(tempHavokDataPath); } catch { } + return null; + } + + Thread.Sleep(10); // stabilize file system + + try + { + using var testStream = File.OpenRead(tempHavokDataPath); + if (testStream.Length != havokData.Length) + { + _logger.LogWarning("File verification failed: length mismatch after write"); + try { File.Delete(tempHavokDataPath); } catch { } + return null; + } + } + catch (Exception readEx) + { + _logger.LogError(readEx, "Cannot read back temporary file at {path}", tempHavokDataPath); + try { File.Delete(tempHavokDataPath); } catch { } return null; } @@ -245,18 +273,31 @@ public sealed partial class XivDataAnalyzer hkResource* resource = null; try { + if (tempHavokDataPathAnsi == IntPtr.Zero) + { + _logger.LogError("Failed to allocate ANSI string for path"); + return null; + } + resource = hkSerializeUtil.LoadFromFile((byte*)tempHavokDataPathAnsi, null, loadoptions); } catch (SEHException ex) { - _logger.LogError(ex, "SEH exception loading Havok file from {path} (hash={hash}). Native error code: 0x{code:X}", + _logger.LogError(ex, "SEH exception loading Havok file from {path} (hash={hash}). Native error code: 0x{code:X}. This may indicate a corrupted PAP file or incompatible Havok format.", tempHavokDataPath, hash, ex.ErrorCode); return null; } + catch (Exception ex) + { + _logger.LogError(ex, "Unexpected exception loading Havok file from {path} (hash={hash})", + tempHavokDataPath, hash); + return null; + } if (resource == null) { - _logger.LogDebug("Havok resource was null after loading from {path} (hash={hash})", tempHavokDataPath, hash); + _logger.LogDebug("Havok resource was null after loading from {path} (hash={hash}). File may be corrupted or in an unsupported format.", + tempHavokDataPath, hash); return null; }