/// <summary>Unpack all assets in the content folder and store them in the output folder.</summary> public void Run() { // get game info Platform platform = EnvironmentUtility.DetectPlatform(); string gamePath = new ModToolkit().GetGameFolders().FirstOrDefault()?.FullName; if (gamePath == null) { this.PrintColor("Can't find Stardew Valley folder.", ConsoleColor.Red); return; } Console.WriteLine($"Found game folder: {gamePath}."); Console.WriteLine(); // get import/export paths string contentPath = Path.Combine(gamePath, "Content"); string exportPath = Path.Combine(gamePath, "Content (unpacked)"); // symlink files on Linux/Mac if (platform == Platform.Linux || platform == Platform.Mac) { Process.Start("ln", $"-sf \"{Path.Combine(gamePath, "Content")}\""); Process.Start("ln", $"-sf \"{Path.Combine(gamePath, "lib")}\""); Process.Start("ln", $"-sf \"{Path.Combine(gamePath, "lib64")}\""); } // load game ConsoleProgressBar progressBar; Console.WriteLine("Loading game instance..."); Console.ForegroundColor = ConsoleColor.DarkGray; using (Game1 game = this.GetGameInstance(platform, contentPath)) { Console.ResetColor(); Console.WriteLine(); Console.WriteLine("Unpacking files..."); // collect files DirectoryInfo contentDir = new DirectoryInfo(contentPath); FileInfo[] files = contentDir.EnumerateFiles("*.xnb", SearchOption.AllDirectories).ToArray(); progressBar = new ConsoleProgressBar(files.Length); // write assets foreach (FileInfo file in files) { // prepare paths string assetName = file.FullName.Substring(contentPath.Length + 1, file.FullName.Length - contentPath.Length - 5); // remove root path + .xnb extension string fileExportPath = Path.Combine(exportPath, assetName); Directory.CreateDirectory(Path.GetDirectoryName(fileExportPath)); // show progress bar progressBar.Increment(); progressBar.Print(assetName); // read asset object asset = null; try { asset = game.Content.Load <object>(assetName); } catch (Exception ex) { progressBar.Erase(); this.PrintColor($"{assetName} => read error: {ex.Message}", ConsoleColor.Red); continue; } // write asset try { // get writer IAssetWriter writer = this.AssetWriters.FirstOrDefault(p => p.CanWrite(asset)); // write file if (writer == null) { progressBar.Erase(); this.PrintColor($"{assetName}.xnb ({asset.GetType().Name}) isn't a supported asset type.", ConsoleColor.DarkYellow); File.Copy(file.FullName, $"{fileExportPath}.xnb", overwrite: true); } else if (!writer.TryWriteFile(asset, fileExportPath, assetName, platform, out string writeError)) { progressBar.Erase(); this.PrintColor($"{assetName}.xnb ({asset.GetType().Name}) could not be saved: {writeError}.", ConsoleColor.DarkYellow); File.Copy(file.FullName, $"{fileExportPath}.xnb", overwrite: true); } } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"{assetName} => export error: {ex.Message}"); Console.ResetColor(); } finally { game.Content.Unload(); } } } progressBar.Erase(); Console.WriteLine($"Done! Unpacked files to {exportPath}."); }