Rewrite resolve dependencies.
This commit is contained in:
@@ -16,23 +16,17 @@ namespace AssetStudio
|
|||||||
public const string CABMapName = "Maps";
|
public const string CABMapName = "Maps";
|
||||||
|
|
||||||
public static CancellationTokenSource tokenSource = new CancellationTokenSource();
|
public static CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||||
public static AssetsManager assetsManager = new AssetsManager() { Silent = true, SkipProcess = true, ResolveDependencies = false };
|
|
||||||
|
|
||||||
public static string BaseFolder = "";
|
private static string BaseFolder = "";
|
||||||
public static Dictionary<string, Entry> CABMap = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase);
|
private static Dictionary<string, Entry> CABMap = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase);
|
||||||
public static Dictionary<string, HashSet<long>> Offsets = new Dictionary<string, HashSet<long>>();
|
private static Dictionary<string, HashSet<long>> Offsets = new Dictionary<string, HashSet<long>>();
|
||||||
|
private static AssetsManager assetsManager = new AssetsManager() { Silent = true, SkipProcess = true, ResolveDependencies = false };
|
||||||
|
|
||||||
public static void Clear()
|
public record Entry
|
||||||
{
|
{
|
||||||
CABMap.Clear();
|
public string Path { get; set; }
|
||||||
Offsets.Clear();
|
public long Offset { get; set; }
|
||||||
BaseFolder = "";
|
public string[] Dependencies { get; set; }
|
||||||
|
|
||||||
tokenSource.Dispose();
|
|
||||||
tokenSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
GC.WaitForPendingFinalizers();
|
|
||||||
GC.Collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] GetMaps()
|
public static string[] GetMaps()
|
||||||
@@ -42,12 +36,57 @@ namespace AssetStudio
|
|||||||
return files.Select(x => Path.GetFileNameWithoutExtension(x)).ToArray();
|
return files.Select(x => Path.GetFileNameWithoutExtension(x)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Clear()
|
||||||
|
{
|
||||||
|
CABMap.Clear();
|
||||||
|
Offsets.Clear();
|
||||||
|
BaseFolder = string.Empty;
|
||||||
|
|
||||||
|
tokenSource.Dispose();
|
||||||
|
tokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
GC.WaitForPendingFinalizers();
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClearOffsets() => Offsets.Clear();
|
||||||
|
|
||||||
|
public static void Remove(string path) => Offsets.Remove(path);
|
||||||
|
|
||||||
|
public static bool TryAdd(string name, out string path)
|
||||||
|
{
|
||||||
|
if (CABMap.TryGetValue(name, out var entry))
|
||||||
|
{
|
||||||
|
path = Path.Combine(BaseFolder, entry.Path);
|
||||||
|
if (!Offsets.ContainsKey(path))
|
||||||
|
{
|
||||||
|
Offsets.Add(path, new HashSet<long>());
|
||||||
|
}
|
||||||
|
Offsets[path].Add(entry.Offset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
path = string.Empty;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGet(string path, out long[] offsets)
|
||||||
|
{
|
||||||
|
if (Offsets.TryGetValue(path, out var list))
|
||||||
|
{
|
||||||
|
offsets = list.ToArray();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
offsets = Array.Empty<long>();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static void BuildCABMap(string[] files, string mapName, string baseFolder, Game game)
|
public static void BuildCABMap(string[] files, string mapName, string baseFolder, Game game)
|
||||||
{
|
{
|
||||||
Logger.Info($"Processing...");
|
Logger.Info($"Processing...");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CABMap.Clear();
|
CABMap.Clear();
|
||||||
|
var collision = 0;
|
||||||
BaseFolder = baseFolder;
|
BaseFolder = baseFolder;
|
||||||
assetsManager.Game = game;
|
assetsManager.Game = game;
|
||||||
for (int i = 0; i < files.Length; i++)
|
for (int i = 0; i < files.Length; i++)
|
||||||
@@ -72,8 +111,11 @@ namespace AssetStudio
|
|||||||
Dependencies = dependencies
|
Dependencies = dependencies
|
||||||
};
|
};
|
||||||
|
|
||||||
CABMap.TryAdd(assetsFile.fileName, new());
|
if (CABMap.ContainsKey(assetsFile.fileName))
|
||||||
CABMap[assetsFile.fileName] = entry;
|
{
|
||||||
|
collision++;
|
||||||
|
}
|
||||||
|
CABMap.Add(assetsFile.fileName, entry);
|
||||||
}
|
}
|
||||||
Logger.Info($"Processed {Path.GetFileName(file)}");
|
Logger.Info($"Processed {Path.GetFileName(file)}");
|
||||||
}
|
}
|
||||||
@@ -81,11 +123,11 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
|
|
||||||
CABMap = CABMap.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);
|
CABMap = CABMap.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);
|
||||||
var outputFile = new FileInfo(Path.Combine(CABMapName, $"{mapName}.bin"));
|
var outputFile = Path.Combine(CABMapName, $"{mapName}.bin");
|
||||||
|
|
||||||
outputFile.Directory.Create();
|
Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
|
||||||
|
|
||||||
using (var binaryFile = outputFile.Create())
|
using (var binaryFile = File.OpenWrite(outputFile))
|
||||||
using (var writer = new BinaryWriter(binaryFile))
|
using (var writer = new BinaryWriter(binaryFile))
|
||||||
{
|
{
|
||||||
writer.Write(BaseFolder);
|
writer.Write(BaseFolder);
|
||||||
@@ -103,11 +145,11 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info($"CABMap build successfully !!");
|
Logger.Info($"CABMap build successfully !! {collision} collisions found");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warning($"CABMap was not build, {e.Message}{e.StackTrace}");
|
Logger.Warning($"CABMap was not build, {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +189,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warning($"{mapName} was not loaded, {e.Message}");
|
Logger.Warning($"{mapName} was not loaded, {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,80 +399,5 @@ namespace AssetStudio
|
|||||||
Logger.Info($"AssetMap build successfully !!");
|
Logger.Info($"AssetMap build successfully !!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddCABOffsets(string[] path, List<string> cabs)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < cabs.Count; i++)
|
|
||||||
{
|
|
||||||
var cab = cabs[i];
|
|
||||||
if (CABMap.TryGetValue(cab, out var entry))
|
|
||||||
{
|
|
||||||
if (!path.Contains(entry.Path))
|
|
||||||
{
|
|
||||||
var fullPath = Path.Combine(BaseFolder, entry.Path);
|
|
||||||
if (!Offsets.ContainsKey(fullPath))
|
|
||||||
{
|
|
||||||
Offsets.Add(fullPath, new HashSet<long>());
|
|
||||||
}
|
|
||||||
Offsets[fullPath].Add(entry.Offset);
|
|
||||||
}
|
|
||||||
foreach (var dep in entry.Dependencies)
|
|
||||||
{
|
|
||||||
if (!cabs.Contains(dep))
|
|
||||||
cabs.Add(dep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool FindCAB(string path, out List<string> cabs)
|
|
||||||
{
|
|
||||||
cabs = new List<string>();
|
|
||||||
var relativePath = Path.GetRelativePath(BaseFolder, path);
|
|
||||||
foreach (var kv in CABMap)
|
|
||||||
{
|
|
||||||
if (kv.Value.Path.Equals(relativePath))
|
|
||||||
{
|
|
||||||
cabs.Add(kv.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cabs.Count != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] ProcessFiles(string[] files)
|
|
||||||
{
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
if (!Offsets.ContainsKey(file))
|
|
||||||
{
|
|
||||||
Offsets.Add(file, new HashSet<long>());
|
|
||||||
}
|
|
||||||
if (FindCAB(file, out var cabs))
|
|
||||||
{
|
|
||||||
AddCABOffsets(files, cabs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Offsets.Keys.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string[] ProcessDependencies(string[] files)
|
|
||||||
{
|
|
||||||
if (CABMap.Count == 0)
|
|
||||||
{
|
|
||||||
Logger.Warning("CABMap is not build, skip resolving dependencies...");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Info("Resolving Dependencies...");
|
|
||||||
files = ProcessFiles(files);
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
public record Entry
|
|
||||||
{
|
|
||||||
public string Path { get; set; }
|
|
||||||
public long Offset { get; set; }
|
|
||||||
public string[] Dependencies { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ namespace AssetStudio
|
|||||||
var path = Path.GetDirectoryName(Path.GetFullPath(files[0]));
|
var path = Path.GetDirectoryName(Path.GetFullPath(files[0]));
|
||||||
MergeSplitAssets(path);
|
MergeSplitAssets(path);
|
||||||
var toReadFile = ProcessingSplitFiles(files.ToList());
|
var toReadFile = ProcessingSplitFiles(files.ToList());
|
||||||
if (ResolveDependencies)
|
|
||||||
toReadFile = AssetsHelper.ProcessDependencies(toReadFile);
|
|
||||||
Load(toReadFile);
|
Load(toReadFile);
|
||||||
|
|
||||||
if (Silent)
|
if (Silent)
|
||||||
@@ -95,6 +93,7 @@ namespace AssetStudio
|
|||||||
importFilesHash.Clear();
|
importFilesHash.Clear();
|
||||||
noexistFiles.Clear();
|
noexistFiles.Clear();
|
||||||
assetsFileListHash.Clear();
|
assetsFileListHash.Clear();
|
||||||
|
AssetsHelper.ClearOffsets();
|
||||||
|
|
||||||
if (!SkipProcess && !tokenSource.IsCancellationRequested)
|
if (!SkipProcess && !tokenSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -138,9 +137,6 @@ namespace AssetStudio
|
|||||||
case FileType.BlkFile:
|
case FileType.BlkFile:
|
||||||
LoadBlkFile(reader);
|
LoadBlkFile(reader);
|
||||||
break;
|
break;
|
||||||
case FileType.Mhy0File:
|
|
||||||
LoadMhy0File(reader);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +214,38 @@ namespace AssetStudio
|
|||||||
CheckStrippedVersion(assetsFile);
|
CheckStrippedVersion(assetsFile);
|
||||||
assetsFileList.Add(assetsFile);
|
assetsFileList.Add(assetsFile);
|
||||||
assetsFileListHash.Add(assetsFile.fileName);
|
assetsFileListHash.Add(assetsFile.fileName);
|
||||||
|
|
||||||
|
if (ResolveDependencies)
|
||||||
|
{
|
||||||
|
foreach (var sharedFile in assetsFile.m_Externals)
|
||||||
|
{
|
||||||
|
var sharedFileName = sharedFile.fileName;
|
||||||
|
|
||||||
|
if (!importFilesHash.Contains(sharedFileName))
|
||||||
|
{
|
||||||
|
var sharedFilePath = Path.Combine(Path.GetDirectoryName(originalPath), sharedFileName);
|
||||||
|
if (!noexistFiles.Contains(sharedFilePath))
|
||||||
|
{
|
||||||
|
if (AssetsHelper.TryAdd(sharedFileName, out var path))
|
||||||
|
{
|
||||||
|
sharedFilePath = path;
|
||||||
|
}
|
||||||
|
if (File.Exists(sharedFilePath))
|
||||||
|
{
|
||||||
|
if (!importFiles.Contains(sharedFilePath))
|
||||||
|
{
|
||||||
|
importFiles.Add(sharedFilePath);
|
||||||
|
}
|
||||||
|
importFilesHash.Add(sharedFileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
noexistFiles.Add(sharedFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -409,9 +437,8 @@ namespace AssetStudio
|
|||||||
Logger.Info("Loading " + reader.FullPath);
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var offsets = AssetsHelper.Offsets.TryGetValue(reader.FullPath, out var list) ? list.ToArray() : Array.Empty<long>();
|
|
||||||
using var stream = new BlockStream(reader.BaseStream, 0);
|
using var stream = new BlockStream(reader.BaseStream, 0);
|
||||||
if (!offsets.IsNullOrEmpty())
|
if (AssetsHelper.TryGet(reader.FullPath, out var offsets))
|
||||||
{
|
{
|
||||||
foreach (var offset in offsets)
|
foreach (var offset in offsets)
|
||||||
{
|
{
|
||||||
@@ -420,6 +447,7 @@ namespace AssetStudio
|
|||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
LoadBundleFile(subReader, reader.FullPath, offset);
|
LoadBundleFile(subReader, reader.FullPath, offset);
|
||||||
}
|
}
|
||||||
|
AssetsHelper.Remove(reader.FullPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -446,9 +474,8 @@ namespace AssetStudio
|
|||||||
Logger.Info("Loading " + reader.FullPath);
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var offsets = AssetsHelper.Offsets.TryGetValue(reader.FullPath, out var list) ? list.ToArray() : Array.Empty<long>();
|
|
||||||
using var stream = BlkUtils.Decrypt(reader, (Blk)Game);
|
using var stream = BlkUtils.Decrypt(reader, (Blk)Game);
|
||||||
if (!offsets.IsNullOrEmpty())
|
if (AssetsHelper.TryGet(reader.FullPath, out var offsets))
|
||||||
{
|
{
|
||||||
foreach (var offset in offsets)
|
foreach (var offset in offsets)
|
||||||
{
|
{
|
||||||
@@ -465,6 +492,7 @@ namespace AssetStudio
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AssetsHelper.Remove(reader.FullPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ namespace AssetStudioGUI
|
|||||||
ResetForm();
|
ResetForm();
|
||||||
openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
|
openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
|
||||||
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||||
|
assetsManager.Game = Studio.Game;
|
||||||
await Task.Run(() => assetsManager.LoadFiles(openFileDialog1.FileNames));
|
await Task.Run(() => assetsManager.LoadFiles(openFileDialog1.FileNames));
|
||||||
BuildAssetStructures();
|
BuildAssetStructures();
|
||||||
}
|
}
|
||||||
@@ -1933,6 +1934,8 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
ResetForm();
|
ResetForm();
|
||||||
AssetsHelper.Clear();
|
AssetsHelper.Clear();
|
||||||
|
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||||
|
assetsManager.Game = Studio.Game;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableConsole_CheckedChanged(object sender, EventArgs e)
|
private void enableConsole_CheckedChanged(object sender, EventArgs e)
|
||||||
|
|||||||
Reference in New Issue
Block a user