mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
parent
570fc318e7
commit
8429911c25
@ -87,6 +87,7 @@
|
||||
"export_preparing": "Preparing for Export...\nThis might take a minute.",
|
||||
"export_primary_content": "Export Primary Content",
|
||||
"export_unity_project": "Export Unity Project",
|
||||
"failed_files": "Failed Files",
|
||||
"format": "Format",
|
||||
"frequency": "Frequency",
|
||||
"game_object": "GameObject",
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using AssetRipper.Assets.Collections;
|
||||
using AssetRipper.Assets.IO;
|
||||
using AssetRipper.IO.Files;
|
||||
using AssetRipper.IO.Files.ResourceFiles;
|
||||
using AssetRipper.IO.Files.SerializedFiles;
|
||||
using AssetRipper.IO.Files.SerializedFiles.Parser;
|
||||
@ -16,21 +17,31 @@ public abstract class Bundle : IDisposable
|
||||
/// The parent <see cref="Bundle"/> of this Bundle.
|
||||
/// </summary>
|
||||
public Bundle? Parent { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of <see cref="ResourceFile"/>s in this Bundle.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ResourceFile> Resources => resources;
|
||||
private readonly List<ResourceFile> resources = new();
|
||||
private readonly List<ResourceFile> resources = [];
|
||||
|
||||
/// <summary>
|
||||
/// The list of <see cref="AssetCollection"/>s in this Bundle.
|
||||
/// </summary>
|
||||
public IReadOnlyList<AssetCollection> Collections => collections;
|
||||
private readonly List<AssetCollection> collections = new();
|
||||
private readonly List<AssetCollection> collections = [];
|
||||
|
||||
/// <summary>
|
||||
/// The list of child <see cref="Bundle"/>s in this Bundle.
|
||||
/// </summary>
|
||||
public IReadOnlyList<Bundle> Bundles => bundles;
|
||||
private readonly List<Bundle> bundles = new();
|
||||
private readonly List<Bundle> bundles = [];
|
||||
|
||||
/// <summary>
|
||||
/// The list of <see cref="FailedFile"/>s in this Bundle.
|
||||
/// </summary>
|
||||
public IReadOnlyList<FailedFile> FailedFiles => failedFiles;
|
||||
private readonly List<FailedFile> failedFiles = [];
|
||||
|
||||
private bool disposedValue;
|
||||
|
||||
/// <summary>
|
||||
@ -281,6 +292,11 @@ public abstract class Bundle : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFailed(FailedFile file)
|
||||
{
|
||||
failedFiles.Add(file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the specified <see cref="AssetCollection"/> is compatible with this Bundle.
|
||||
/// </summary>
|
||||
|
||||
@ -49,6 +49,9 @@ partial class GameBundle
|
||||
case ResourceFile resourceFile:
|
||||
AddResource(resourceFile);
|
||||
break;
|
||||
case FailedFile failedFile:
|
||||
AddFailed(failedFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,13 +70,26 @@ partial class GameBundle
|
||||
HashSet<string> serializedFileNames = new();//Includes missing dependencies
|
||||
foreach (string path in paths)
|
||||
{
|
||||
FileBase? file = SchemeReader.LoadFile(path);
|
||||
file?.ReadContentsRecursively();
|
||||
FileBase? file;
|
||||
try
|
||||
{
|
||||
file = SchemeReader.LoadFile(path);
|
||||
file.ReadContentsRecursively();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
file = new FailedFile()
|
||||
{
|
||||
Name = Path.GetFileName(path),
|
||||
FilePath = path,
|
||||
StackTrace = ex.ToString(),
|
||||
};
|
||||
}
|
||||
while (file is CompressedFile compressedFile)
|
||||
{
|
||||
file = compressedFile.UncompressedFile;
|
||||
}
|
||||
if (file is ResourceFile resourceFile)
|
||||
if (file is ResourceFile or FailedFile)
|
||||
{
|
||||
files.Add(file);
|
||||
}
|
||||
|
||||
@ -32,6 +32,10 @@ public sealed class SerializedBundle : Bundle
|
||||
SerializedBundle childBundle = FromFileContainer(childContainer, factory, defaultVersion);
|
||||
bundle.AddBundle(childBundle);
|
||||
}
|
||||
foreach (FailedFile failedFile in container.FailedFiles)
|
||||
{
|
||||
bundle.AddFailed(failedFile);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
||||
@ -449,6 +449,11 @@ partial class Localization
|
||||
/// </summary>
|
||||
public static string ExportUnityProject => Get("export_unity_project");
|
||||
|
||||
/// <summary>
|
||||
/// Failed Files
|
||||
/// </summary>
|
||||
public static string FailedFiles => Get("failed_files");
|
||||
|
||||
/// <summary>
|
||||
/// Format
|
||||
/// </summary>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using AssetRipper.Assets.Bundles;
|
||||
using AssetRipper.Assets.Collections;
|
||||
using AssetRipper.GUI.Web.Paths;
|
||||
using AssetRipper.IO.Files;
|
||||
|
||||
namespace AssetRipper.GUI.Web.Pages.Bundles;
|
||||
|
||||
@ -69,5 +70,18 @@ public sealed class ViewPage : DefaultPage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Bundle.FailedFiles.Count > 0)
|
||||
{
|
||||
new H2(writer).Close(Localization.FailedFiles);
|
||||
using (new Ul(writer).End())
|
||||
{
|
||||
foreach (FailedFile failedFile in Bundle.FailedFiles)
|
||||
{
|
||||
// Todo: page for failed files
|
||||
new Li(writer).Close(failedFile.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,10 +28,7 @@ namespace AssetRipper.IO.Files.BundleFiles.FileStream
|
||||
|
||||
public SmartStream ReadEntry(FileStreamNode entry)
|
||||
{
|
||||
if (m_isDisposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(BundleFileBlockReader));
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(m_isDisposed, typeof(BundleFileBlockReader));
|
||||
|
||||
// find block offsets
|
||||
int blockIndex;
|
||||
|
||||
@ -142,8 +142,20 @@ namespace AssetRipper.IO.Files.BundleFiles.FileStream
|
||||
using BundleFileBlockReader blockReader = new BundleFileBlockReader(stream, BlocksInfo);
|
||||
foreach (FileStreamNode entry in DirectoryInfo.Nodes)
|
||||
{
|
||||
SmartStream entryStream = blockReader.ReadEntry(entry);
|
||||
AddResourceFile(new ResourceFile(entryStream, FilePath, entry.Path));
|
||||
try
|
||||
{
|
||||
SmartStream entryStream = blockReader.ReadEntry(entry);
|
||||
AddResourceFile(new ResourceFile(entryStream, FilePath, entry.Path));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddFailedFile(new FailedFile()
|
||||
{
|
||||
Name = entry.Path,
|
||||
FilePath = FilePath,
|
||||
StackTrace = ex.ToString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
using AssetRipper.IO.Endian;
|
||||
using AssetRipper.IO.Files.BundleFiles.RawWeb.Raw;
|
||||
using AssetRipper.IO.Files.BundleFiles.RawWeb.Web;
|
||||
using AssetRipper.IO.Files.Extensions;
|
||||
using AssetRipper.IO.Files.ResourceFiles;
|
||||
using AssetRipper.IO.Files.Streams.Smart;
|
||||
|
||||
|
||||
@ -10,8 +10,20 @@ namespace AssetRipper.IO.Files.CompressedFiles.Brotli
|
||||
|
||||
public override void Read(SmartStream stream)
|
||||
{
|
||||
byte[] buffer = ReadBrotli(stream);
|
||||
UncompressedFile = new ResourceFile(buffer, FilePath, Name);
|
||||
try
|
||||
{
|
||||
byte[] buffer = ReadBrotli(stream);
|
||||
UncompressedFile = new ResourceFile(buffer, FilePath, Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UncompressedFile = new FailedFile()
|
||||
{
|
||||
Name = Name,
|
||||
FilePath = FilePath,
|
||||
StackTrace = ex.ToString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsBrotliFile(Stream stream)
|
||||
|
||||
@ -11,13 +11,25 @@ namespace AssetRipper.IO.Files.CompressedFiles.GZip
|
||||
|
||||
public override void Read(SmartStream stream)
|
||||
{
|
||||
using SmartStream memoryStream = SmartStream.CreateMemory();
|
||||
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, true))
|
||||
try
|
||||
{
|
||||
gzipStream.CopyTo(memoryStream);
|
||||
using SmartStream memoryStream = SmartStream.CreateMemory();
|
||||
using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, true))
|
||||
{
|
||||
gzipStream.CopyTo(memoryStream);
|
||||
}
|
||||
memoryStream.Position = 0;
|
||||
UncompressedFile = new ResourceFile(memoryStream, FilePath, Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UncompressedFile = new FailedFile()
|
||||
{
|
||||
Name = Name,
|
||||
FilePath = FilePath,
|
||||
StackTrace = ex.ToString(),
|
||||
};
|
||||
}
|
||||
memoryStream.Position = 0;
|
||||
UncompressedFile = new ResourceFile(memoryStream, FilePath, Name);
|
||||
}
|
||||
|
||||
public override void Write(Stream stream)
|
||||
|
||||
17
Source/AssetRipper.IO.Files/FailedFile.cs
Normal file
17
Source/AssetRipper.IO.Files/FailedFile.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using AssetRipper.IO.Files.Streams.Smart;
|
||||
|
||||
namespace AssetRipper.IO.Files;
|
||||
|
||||
public class FailedFile : FileBase
|
||||
{
|
||||
public string StackTrace { get; set; } = "";
|
||||
|
||||
public override void Read(SmartStream stream)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Write(Stream stream)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
@ -33,6 +33,9 @@ namespace AssetRipper.IO.Files
|
||||
case FileContainer fileList:
|
||||
AddFileContainer(fileList);
|
||||
return;
|
||||
case FailedFile failedFile:
|
||||
AddFailedFile(failedFile);
|
||||
return;
|
||||
default:
|
||||
throw new NotSupportedException(file.GetType().ToString());
|
||||
}
|
||||
@ -40,22 +43,55 @@ namespace AssetRipper.IO.Files
|
||||
|
||||
public void AddSerializedFile(SerializedFile file)
|
||||
{
|
||||
m_serializedFiles.Add(file);
|
||||
if (m_serializedFiles is null)
|
||||
{
|
||||
m_serializedFiles = [file];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_serializedFiles.Add(file);
|
||||
}
|
||||
OnSerializedFileAdded(file);
|
||||
}
|
||||
|
||||
public void AddFileContainer(FileContainer container)
|
||||
{
|
||||
m_fileLists.Add(container);
|
||||
if (m_fileLists is null)
|
||||
{
|
||||
m_fileLists = [container];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fileLists.Add(container);
|
||||
}
|
||||
OnFileContainerAdded(container);
|
||||
}
|
||||
|
||||
public void AddResourceFile(ResourceFile resource)
|
||||
{
|
||||
m_resourceFiles.Add(resource);
|
||||
if (m_resourceFiles is null)
|
||||
{
|
||||
m_resourceFiles = [resource];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_resourceFiles.Add(resource);
|
||||
}
|
||||
OnResourceFileAdded(resource);
|
||||
}
|
||||
|
||||
public void AddFailedFile(FailedFile file)
|
||||
{
|
||||
if (m_failedFiles is null)
|
||||
{
|
||||
m_failedFiles = [file];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_failedFiles.Add(file);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnSerializedFileAdded(SerializedFile file) { }
|
||||
|
||||
protected virtual void OnFileContainerAdded(FileContainer container) { }
|
||||
@ -64,7 +100,7 @@ namespace AssetRipper.IO.Files
|
||||
|
||||
public override void ReadContents()
|
||||
{
|
||||
if (m_resourceFiles.Count > 0)
|
||||
if (m_resourceFiles is { Count: > 0 })
|
||||
{
|
||||
ResourceFile[] resourceFiles = m_resourceFiles.ToArray();
|
||||
m_resourceFiles.Clear();
|
||||
@ -84,9 +120,10 @@ namespace AssetRipper.IO.Files
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<SerializedFile> SerializedFiles => m_serializedFiles;
|
||||
public IReadOnlyList<FileContainer> FileLists => m_fileLists;
|
||||
public IReadOnlyList<ResourceFile> ResourceFiles => m_resourceFiles;
|
||||
public IReadOnlyList<SerializedFile> SerializedFiles => m_serializedFiles ?? [];
|
||||
public IReadOnlyList<FileContainer> FileLists => m_fileLists ?? [];
|
||||
public IReadOnlyList<ResourceFile> ResourceFiles => m_resourceFiles ?? [];
|
||||
public IReadOnlyList<FailedFile> FailedFiles => m_failedFiles ?? [];
|
||||
|
||||
public IEnumerable<FileBase> AllFiles
|
||||
{
|
||||
@ -104,11 +141,16 @@ namespace AssetRipper.IO.Files
|
||||
{
|
||||
yield return container;
|
||||
}
|
||||
foreach (FailedFile file in FailedFiles)
|
||||
{
|
||||
yield return file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<SerializedFile> m_serializedFiles = new List<SerializedFile>(0);
|
||||
private readonly List<FileContainer> m_fileLists = new List<FileContainer>(0);
|
||||
private readonly List<ResourceFile> m_resourceFiles = new List<ResourceFile>(0);
|
||||
private List<SerializedFile>? m_serializedFiles;
|
||||
private List<FileContainer>? m_fileLists;
|
||||
private List<ResourceFile>? m_resourceFiles;
|
||||
private List<FailedFile>? m_failedFiles;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user