diff --git a/Source/AssetRipper.Export.UnityProjects/Project/YamlStreamedAssetExportCollection.cs b/Source/AssetRipper.Export.UnityProjects/Project/YamlStreamedAssetExportCollection.cs index 5e16d4104..e990764bf 100644 --- a/Source/AssetRipper.Export.UnityProjects/Project/YamlStreamedAssetExportCollection.cs +++ b/Source/AssetRipper.Export.UnityProjects/Project/YamlStreamedAssetExportCollection.cs @@ -23,64 +23,62 @@ namespace AssetRipper.Export.UnityProjects.Project private bool ExportMesh(IExportContainer container, string filePath, string dirPath, IMesh mesh, FileSystem fileSystem) { - bool result; - if (mesh.Has_StreamData()) + if (!mesh.Has_StreamData()) { - ulong offset = mesh.StreamData.GetOffset(); - Utf8String path = mesh.StreamData.Path; - uint size = mesh.StreamData.Size; - if (mesh.VertexData is not null && mesh.VertexData.Data.Length == 0 && mesh.StreamData.IsSet()) - { - mesh.VertexData.Data = mesh.StreamData.GetContent(mesh.Collection); - mesh.StreamData.ClearValues(); - result = base.ExportInner(container, filePath, dirPath, fileSystem); - mesh.VertexData.Data = Array.Empty(); - } - else - { - mesh.StreamData.ClearValues(); - result = base.ExportInner(container, filePath, dirPath, fileSystem); - } - mesh.StreamData.SetOffset(offset); - mesh.StreamData.Path = path; - mesh.StreamData.Size = size; + return base.ExportInner(container, filePath, dirPath, fileSystem); + } + + bool result; + mesh.StreamData.GetValues(out Utf8String path, out ulong offset, out uint size); + if (mesh.VertexData.Data.Length != 0) + { + mesh.StreamData.ClearValues(); + result = base.ExportInner(container, filePath, dirPath, fileSystem); } else { + byte[]? data = mesh.StreamData.GetContent(mesh.Collection); + if (data.IsNullOrEmpty()) + { + return false; + } + mesh.VertexData.Data = data; + mesh.StreamData.ClearValues(); result = base.ExportInner(container, filePath, dirPath, fileSystem); + mesh.VertexData.Data = []; } + mesh.StreamData.SetValues(path, offset, size); return result; } private bool ExportTexture(IExportContainer container, string filePath, string dirPath, IImageTexture texture, FileSystem fileSystem) { - bool result; - if (texture.Has_StreamData_C189()) + if (!texture.Has_StreamData_C189()) { - ulong offset = texture.StreamData_C189.GetOffset(); - Utf8String path = texture.StreamData_C189.Path; - uint size = texture.StreamData_C189.Size; - if (texture.ImageData_C189.Length == 0 && texture.StreamData_C189.IsSet()) - { - texture.ImageData_C189 = texture.StreamData_C189.GetContent(texture.Collection); - texture.StreamData_C189.ClearValues(); - result = base.ExportInner(container, filePath, dirPath, fileSystem); - texture.ImageData_C189 = Array.Empty(); - } - else - { - texture.StreamData_C189.ClearValues(); - result = base.ExportInner(container, filePath, dirPath, fileSystem); - } - texture.StreamData_C189.SetOffset(offset); - texture.StreamData_C189.Path = path; - texture.StreamData_C189.Size = size; + return base.ExportInner(container, filePath, dirPath, fileSystem); + } + + bool result; + texture.StreamData_C189.GetValues(out Utf8String path, out ulong offset, out uint size); + if (texture.ImageData_C189.Length != 0) + { + texture.StreamData_C189.ClearValues(); + result = base.ExportInner(container, filePath, dirPath, fileSystem); } else { + byte[]? data = texture.StreamData_C189.GetContent(texture.Collection); + if (data.IsNullOrEmpty()) + { + return false; + } + texture.ImageData_C189 = data; + texture.StreamData_C189.ClearValues(); result = base.ExportInner(container, filePath, dirPath, fileSystem); + texture.ImageData_C189 = []; } + texture.StreamData_C189.SetValues(path, offset, size); return result; } diff --git a/Source/AssetRipper.SourceGenerated.Extensions/CubemapArrayExtensions.cs b/Source/AssetRipper.SourceGenerated.Extensions/CubemapArrayExtensions.cs index 5520cfba7..cd49077af 100644 --- a/Source/AssetRipper.SourceGenerated.Extensions/CubemapArrayExtensions.cs +++ b/Source/AssetRipper.SourceGenerated.Extensions/CubemapArrayExtensions.cs @@ -26,7 +26,7 @@ public static class CubemapArrayExtensions } else { - return Array.Empty(); + return []; } } diff --git a/Source/AssetRipper.SourceGenerated.Extensions/MeshExtensions.cs b/Source/AssetRipper.SourceGenerated.Extensions/MeshExtensions.cs index 2703453e0..484225dc2 100644 --- a/Source/AssetRipper.SourceGenerated.Extensions/MeshExtensions.cs +++ b/Source/AssetRipper.SourceGenerated.Extensions/MeshExtensions.cs @@ -131,7 +131,7 @@ namespace AssetRipper.SourceGenerated.Extensions } else { - return mesh.VertexData?.Data ?? Array.Empty(); + return mesh.VertexData?.Data ?? []; } } diff --git a/Source/AssetRipper.SourceGenerated.Extensions/StreamedResourceExtensions.cs b/Source/AssetRipper.SourceGenerated.Extensions/StreamedResourceExtensions.cs index f06385a63..cfc3b1e2e 100644 --- a/Source/AssetRipper.SourceGenerated.Extensions/StreamedResourceExtensions.cs +++ b/Source/AssetRipper.SourceGenerated.Extensions/StreamedResourceExtensions.cs @@ -6,37 +6,71 @@ namespace AssetRipper.SourceGenerated.Extensions { public static class StreamedResourceExtensions { - public static bool CheckIntegrity(this IStreamedResource streamedResource, AssetCollection file) + internal static bool CheckIntegrity(Utf8String? path, ulong offset, ulong size, AssetCollection collection) { - if (!streamedResource.IsSet()) + if (Utf8String.IsNullOrEmpty(path)) { return true; } - if (streamedResource.Size == 0) + + if (offset > long.MaxValue || size > long.MaxValue || offset + size > long.MaxValue) { - // I think they read data by its type for this verison, so I can't even export raw data :/ return false; } - return file.Bundle.ResolveResource(streamedResource.Source.String) != null; + if (size == 0) + { + // Data might be read by its type for this verison, so we can't even export raw data. + return false; + } + + ResourceFile? file = collection.Bundle.ResolveResource(path.String); + if (file == null) + { + return false; + } + + return file.Stream.Length <= unchecked((long)(offset + size)); + } + + internal static byte[]? GetContent(Utf8String? path, ulong offset, ulong size, AssetCollection collection) + { + if (Utf8String.IsNullOrEmpty(path)) + { + return null; + } + + if (offset > long.MaxValue || size > long.MaxValue || offset + size > long.MaxValue) + { + return null; + } + + if (size == 0) + { + // Data might be read by its type for this verison, so we can't even export raw data. + return null; + } + + ResourceFile? file = collection.Bundle.ResolveResource(path.String); + if (file == null) + { + return null; + } + + byte[] data = new byte[size]; + file.Stream.Position = (long)offset; + file.Stream.ReadExactly(data); + return data; + } + + public static bool CheckIntegrity(this IStreamedResource streamedResource, AssetCollection collection) + { + return CheckIntegrity(streamedResource.Source, streamedResource.Offset, streamedResource.Size, collection); } public static byte[]? GetContent(this IStreamedResource streamedResource, AssetCollection file) { - ResourceFile? res = file.Bundle.ResolveResource(streamedResource.Source.String); - if (res == null) - { - return null; - } - if (streamedResource.Size <= 0 || streamedResource.Offset > long.MaxValue) - { - return null; - } - - byte[] data = new byte[streamedResource.Size]; - res.Stream.Position = (long)streamedResource.Offset; - res.Stream.ReadExactly(data); - return data; + return GetContent(streamedResource.Source, streamedResource.Offset, streamedResource.Size, file); } public static bool TryGetContent(this IStreamedResource streamedResource, AssetCollection file, [NotNullWhen(true)] out byte[]? data) @@ -45,6 +79,6 @@ namespace AssetRipper.SourceGenerated.Extensions return !data.IsNullOrEmpty(); } - public static bool IsSet(this IStreamedResource streamedResource) => !string.IsNullOrEmpty(streamedResource.Source?.String); + public static bool IsSet(this IStreamedResource streamedResource) => !Utf8String.IsNullOrEmpty(streamedResource.Source); } } diff --git a/Source/AssetRipper.SourceGenerated.Extensions/StreamingInfoExtensions.cs b/Source/AssetRipper.SourceGenerated.Extensions/StreamingInfoExtensions.cs index 7113f6f9e..4221bd96f 100644 --- a/Source/AssetRipper.SourceGenerated.Extensions/StreamingInfoExtensions.cs +++ b/Source/AssetRipper.SourceGenerated.Extensions/StreamingInfoExtensions.cs @@ -1,6 +1,4 @@ using AssetRipper.Assets.Collections; -using AssetRipper.IO.Files.ResourceFiles; -using AssetRipper.Primitives; using AssetRipper.SourceGenerated.Subclasses.StreamingInfo; namespace AssetRipper.SourceGenerated.Extensions @@ -11,25 +9,12 @@ namespace AssetRipper.SourceGenerated.Extensions public static bool CheckIntegrity(this IStreamingInfo streamingInfo, AssetCollection file) { - if (!streamingInfo.IsSet()) - { - return true; - } - return file.Bundle.ResolveResource(streamingInfo.Path.String) != null; + return StreamedResourceExtensions.CheckIntegrity(streamingInfo.Path, streamingInfo.GetOffset(), streamingInfo.Size, file); } public static byte[] GetContent(this IStreamingInfo streamingInfo, AssetCollection file) { - ResourceFile? res = file.Bundle.ResolveResource(streamingInfo.Path.String); - if (res == null) - { - return Array.Empty(); - } - - byte[] data = new byte[streamingInfo.Size]; - res.Stream.Position = (long)streamingInfo.GetOffset(); - res.Stream.ReadExactly(data); - return data; + return StreamedResourceExtensions.GetContent(streamingInfo.Path, streamingInfo.GetOffset(), streamingInfo.Size, file) ?? []; } public static ulong GetOffset(this IStreamingInfo streamingInfo) @@ -63,5 +48,19 @@ namespace AssetRipper.SourceGenerated.Extensions streamingInfo.Path = Utf8String.Empty; streamingInfo.Size = default; } + + public static void GetValues(this IStreamingInfo streamingInfo, out Utf8String path, out ulong offset, out uint size) + { + path = streamingInfo.Path; + offset = streamingInfo.GetOffset(); + size = streamingInfo.Size; + } + + public static void SetValues(this IStreamingInfo streamingInfo, Utf8String path, ulong offset, uint size) + { + streamingInfo.Path = path; + streamingInfo.SetOffset(offset); + streamingInfo.Size = size; + } } }