diff --git a/Enums/AssetTypes.cs b/Enums/AssetTypes.cs new file mode 100644 index 0000000..7eba011 --- /dev/null +++ b/Enums/AssetTypes.cs @@ -0,0 +1,8 @@ +namespace USSR.Enums +{ + public enum AssetTypes + { + Asset, + Bundle + } +} diff --git a/Enums/WebCompressionTypes.cs b/Enums/WebCompressionTypes.cs new file mode 100644 index 0000000..33c95f1 --- /dev/null +++ b/Enums/WebCompressionTypes.cs @@ -0,0 +1,9 @@ +namespace USSR.Enums +{ + public enum WebCompressionTypes + { + None, + Brotli, + GZip + } +} diff --git a/USSR.cs b/USSR.cs index e009b3e..dbe7320 100644 --- a/USSR.cs +++ b/USSR.cs @@ -4,84 +4,39 @@ using Kiraio.UnityWebTools; using NativeFileDialogSharp; using Spectre.Console; +using Spectre.Console.Cli; +using USSR.Enums; using USSR.Utilities; namespace USSR.Core { public class USSR { - const string VERSION = "1.1.7"; + static readonly string? appVersion = Utility.GetVersion(); const string ASSET_CLASS_DB = "classdata.tpk"; - enum AssetTypes - { - Asset, - Bundle - } - - enum WebGLCompressionType - { - None, - Brotli, - GZip - } - - static AssetTypes assetType; - static WebGLCompressionType webGLCompressionType; - static void Main(string[] args) { AnsiConsole.Background = Color.Grey11; PrintHelp(); Console.WriteLine(); - string? ussrExec = Path.GetDirectoryName(AppContext.BaseDirectory); - ChooseAction: - string[] actionList = { "Remove Unity Splash Screen", "Remove Watermark", "Exit" }; - string actionPrompt = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("What would you like to do? (Press ENTER go, UP/DOWN to select)") - .AddChoices(actionList) - ); - int choiceIndex = Array.FindIndex(actionList, item => item == actionPrompt); - - string? selectedFile = string.Empty, - webDataFile = string.Empty, - unpackedWebDataDirectory = string.Empty; - bool isWebGL = false; + string? ussrExec = Path.GetDirectoryName(AppContext.BaseDirectory); + int choiceIndex = GetChoice(); + string? selectedFile = string.Empty; switch (choiceIndex) { case 0: case 1: - AnsiConsole.MarkupLine("Opening File Picker..."); - // Unfortunately, this File Picker library currently only support one filter :( - // So we pass all file types and manually checking them if it's a valid file that we want. - DialogResult filePicker = Dialog.FileOpen( - null, - Path.GetDirectoryName(Utility.GetLastOpenedFile()) - ); - - if (filePicker.IsCancelled) - { - AnsiConsole.MarkupLine("Cancelled. Oh, it\'s okay ^_^"); - Console.WriteLine(); - goto ChooseAction; - } - else if (filePicker.IsError) - { - AnsiConsole.MarkupLine( - "[red]( RAWR )[/] Unable to open File Picker! Try using a different Terminal?" - ); - Console.WriteLine(); + selectedFile = OpenFilePicker(); + if (selectedFile == null) goto ChooseAction; - } - - selectedFile = filePicker.Path; AnsiConsole.MarkupLineInterpolated( $"( INFO ) Selected file: [green]{selectedFile}[/]" ); + Utility.SaveLastOpenedFile(selectedFile); break; case 2: @@ -90,10 +45,15 @@ static void Main(string[] args) return; } - webDataFile = Path.Combine( + string webDataFile = Path.Combine( Path.GetDirectoryName(selectedFile) ?? string.Empty, Path.GetFileNameWithoutExtension(selectedFile) // Without .br / .gz extension ); + string? unpackedWebDataDirectory = string.Empty; + bool isWebGL = false; + + AssetTypes assetType = AssetTypes.Asset; + WebCompressionTypes webCompressionType = WebCompressionTypes.None; string selectedFileName = Path.GetFileName(selectedFile); if (selectedFileName.Contains("globalgamemanagers")) @@ -104,70 +64,38 @@ static void Main(string[] args) { isWebGL = true; webDataFile = selectedFile; - webGLCompressionType = WebGLCompressionType.None; + webCompressionType = WebCompressionTypes.None; } else if (selectedFileName.EndsWith("data.unityweb")) { - string[] compressionList = { "Brotli", "GZip" }; - string compressionListPrompt = AnsiConsole.Prompt( - new SelectionPrompt() - .Title("What compression type did you use?") - .AddChoices(compressionList) - ); - int compressionChoiceIndex = Array.FindIndex( - compressionList, - item => item == compressionListPrompt - ); isWebGL = true; - - switch (compressionChoiceIndex) - { - case 0: - webGLCompressionType = WebGLCompressionType.Brotli; - if ( - DecompressCompressedWebData( - webGLCompressionType, - selectedFile, - webDataFile - ) == 1 - ) - goto ChooseAction; - break; - case 1: - webGLCompressionType = WebGLCompressionType.GZip; - if ( - DecompressCompressedWebData( - webGLCompressionType, - selectedFile, - webDataFile - ) == 1 - ) - goto ChooseAction; - break; - } + webCompressionType = GetCompression(); + if (!DecompressWebData(webCompressionType, selectedFile, webDataFile)) + goto ChooseAction; } else if (selectedFileName.EndsWith("data.br")) { isWebGL = true; - webGLCompressionType = WebGLCompressionType.Brotli; - DecompressCompressedWebData(webGLCompressionType, selectedFile, webDataFile); + webCompressionType = WebCompressionTypes.Brotli; + DecompressWebData(webCompressionType, selectedFile, webDataFile); } else if (selectedFileName.EndsWith("data.gz")) { isWebGL = true; - webGLCompressionType = WebGLCompressionType.GZip; - DecompressCompressedWebData(webGLCompressionType, selectedFile, webDataFile); + webCompressionType = WebCompressionTypes.GZip; + DecompressWebData(webCompressionType, selectedFile, webDataFile); } else { - AnsiConsole.MarkupLine("[red]( RAWR )[/] Unknown/Unsupported file type!"); + AnsiConsole.MarkupLine("[red]( ERRO )[/] Unknown/Unsupported file type!"); Console.WriteLine(); goto ChooseAction; } AssetsManager assetsManager = new(); string? tpkFile = Path.Combine(ussrExec ??= string.Empty, ASSET_CLASS_DB); - LoadClassPackage(assetsManager, tpkFile); + if (!LoadClassPackage(assetsManager, tpkFile)) + goto ChooseAction; // List of files to be deleted later List temporaryFiles = new(); @@ -226,7 +154,7 @@ static void Main(string[] args) catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when loading asset class types database! {ex.Message}" + $"[red]( ERRO )[/] Error when loading asset class types database! {ex.Message}" ); goto Cleanup; } @@ -234,7 +162,7 @@ static void Main(string[] args) if (assetFileInstance != null) { AnsiConsole.MarkupLineInterpolated( - $"( INFO ) [bold]Unity Version[/]: [green]{assetFileInstance?.file.Metadata.UnityVersion.ToString()}[/]" + $"( INFO ) Unity Version: [bold green]{assetFileInstance?.file.Metadata.UnityVersion.ToString()}[/]" ); switch (choiceIndex) @@ -253,6 +181,7 @@ static void Main(string[] args) // Write changes to the asset file WriteChanges( inspectedFile, + assetType, assetFileInstance, bundleFileInstance, assetsReplacer @@ -274,9 +203,9 @@ static void Main(string[] args) AnsiConsole.MarkupLineInterpolated( $"( INFO ) Packing [green]{unpackedWebDataDirectory}[/]..." ); - switch (webGLCompressionType) + switch (webCompressionType) { - case WebGLCompressionType.Brotli: + case WebCompressionTypes.Brotli: UnityWebTool.Pack(unpackedWebDataDirectory, webDataFile); AnsiConsole.MarkupLineInterpolated( @@ -284,7 +213,7 @@ static void Main(string[] args) ); BrotliUtils.CompressFile(webDataFile, selectedFile); break; - case WebGLCompressionType.GZip: + case WebCompressionTypes.GZip: UnityWebTool.Pack(unpackedWebDataDirectory, webDataFile); AnsiConsole.MarkupLineInterpolated( @@ -292,7 +221,7 @@ static void Main(string[] args) ); GZipUtils.CompressFile(webDataFile, selectedFile); break; - case WebGLCompressionType.None: + case WebCompressionTypes.None: default: UnityWebTool.Pack(unpackedWebDataDirectory, selectedFile); break; @@ -302,7 +231,7 @@ static void Main(string[] args) catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when compressing Unity Web Data! {ex.Message}" + $"[red]( ERRO )[/] Error when compressing Unity Web Data! {ex.Message}" ); } finally @@ -314,7 +243,7 @@ static void Main(string[] args) if (Directory.Exists(unpackedWebDataDirectory)) Directory.Delete(unpackedWebDataDirectory, true); if ( - !webGLCompressionType.Equals(WebGLCompressionType.None) + !webCompressionType.Equals(WebCompressionTypes.None) && File.Exists(webDataFile) ) File.Delete(webDataFile); @@ -330,31 +259,81 @@ static void Main(string[] args) static void PrintHelp() { AnsiConsole.MarkupLineInterpolated( - $"[bold red]Unity Splash Screen Remover v{VERSION}[/]" + $"[bold red]Unity Splash Screen Remover v{appVersion}[/]" ); Console.WriteLine(); - AnsiConsole.MarkupLine( - "USSR is a CLI tool to easily remove Unity splash screen logo (Made with Unity) from your game and keep your logo displayed. USSR didn't directly \"hack\" Unity Editor, but the generated build." - ); + AnsiConsole.MarkupLine("USSR is a tool to easily remove Unity splash screen."); Console.WriteLine(); AnsiConsole.MarkupLine( - "Before using USSR, make sure you have set the splash screen [bold green]\"Draw Mode\"[/] in [bold green]Player Settings[/] to [bold green]\"All Sequential\"[/] and don't forget to backup your game files!" + "USSR didn't directly \"hack\" Unity Editor, but the generated build.\nBefore using USSR, make sure you have set the splash screen [bold green]Draw Mode[/] in [bold green]Player Settings[/] to [bold green]All Sequential[/] and backup the target file!" ); Console.WriteLine(); AnsiConsole.MarkupLine( "For more information, visit USSR GitHub repo: [link]https://github.com/kiraio-moe/USSR[/]" ); Console.WriteLine(); - AnsiConsole.MarkupLine("[bold green]How to Use[/]:"); + AnsiConsole.MarkupLine("[bold green]How to Use?[/]"); AnsiConsole.MarkupLine( - "Select the Action, find and choose one of these files in you game data:" + "Select the action, find and choose one of these files in you game data:" ); AnsiConsole.MarkupLine( - "[green]globalgamemanagers[/] | [green]data.unity3d[/] | [green].data[/] | [green].data.br[/] | [green].data.gz[/] | [green].data.unityweb[/]" + "[green]globalgamemanagers[/] | [green]data.unity3d[/] | [green]*.data[/] | [green]*.data.br[/] | [green]*.data.gz[/] | [green]*.data.unityweb[/]" + ); + } + + static int GetChoice() + { + string[] menuList = { "Remove Unity Splash Screen", "Remove Watermark", "Exit" }; + string actionPrompt = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("What would you like to do? (Press ENTER to go, UP/DOWN to select)") + .AddChoices(menuList) ); + return Array.FindIndex(menuList, item => item == actionPrompt); } - static void LoadClassPackage(AssetsManager assetsManager, string tpkFile) + static WebCompressionTypes GetCompression() + { + string[] compressionList = { "Brotli", "GZip" }; + string compressionListPrompt = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("What compression did you use?") + .AddChoices(compressionList) + ); + int choiceIndex = Array.FindIndex( + compressionList, + item => item == compressionListPrompt + ); + + return choiceIndex switch + { + 0 => WebCompressionTypes.Brotli, + 1 => WebCompressionTypes.GZip, + _ => WebCompressionTypes.None, + }; + } + + static string OpenFilePicker() + { + AnsiConsole.MarkupLine("Opening File Picker..."); + + DialogResult filePicker = Dialog.FileOpen( + null, + Path.GetDirectoryName(Utility.GetLastOpenedFile()) + ); + + if (filePicker.IsCancelled) + AnsiConsole.MarkupLine("( INFO ) Cancelled."); + else if (filePicker.IsError) + { + AnsiConsole.MarkupLine( + "[red]( ERRO )[/] Unable to open File Picker! Try using a different Terminal?" + ); + } + + return filePicker.Path; + } + static bool LoadClassPackage(AssetsManager assetsManager, string tpkFile) { if (File.Exists(tpkFile)) { @@ -364,18 +343,21 @@ static void LoadClassPackage(AssetsManager assetsManager, string tpkFile) $"( INFO ) Loading class types package: [green]{tpkFile}[/]..." ); assetsManager.LoadClassPackage(path: tpkFile); + return true; } catch (Exception ex) { AnsiConsole.MarkupLine( - $"[red]( RAWR )[/] Error when loading class types package! {ex.Message}" + $"[red]( ERRO )[/] Error when loading class types package! {ex.Message}" ); } } else AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] TPK file not found: [red]{tpkFile}[/]..." + $"[red]( ERRO )[/] TPK file not found: [red]{tpkFile}[/]..." ); + + return false; } /// @@ -402,14 +384,14 @@ AssetsManager assetsManager catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when loading asset file! {ex.Message}" + $"[red]( ERRO )[/] Error when loading asset file! {ex.Message}" ); } } else { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Asset file not found: [red]{assetFile}[/]" + $"[red]( ERRO )[/] Asset file not found: [red]{assetFile}[/]" ); } @@ -447,14 +429,14 @@ AssetsManager assetsManager catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when loading asset file! {ex.Message}" + $"[red]( ERRO )[/] Error when loading asset file! {ex.Message}" ); } } else { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Asset file not found: [red]{assetFile}[/]" + $"[red]( ERRO )[/] Asset file not found: [red]{assetFile}[/]" ); } @@ -487,14 +469,14 @@ AssetsManager assetsManager catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when loading bundle file! {ex.Message}" + $"[red]( ERRO )[/] Error when loading bundle file! {ex.Message}" ); } } else { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Bundle file not found: [red]{bundleFile}[/]" + $"[red]( ERRO )[/] Bundle file not found: [red]{bundleFile}[/]" ); } @@ -523,21 +505,21 @@ AssetsManager assetsManager List? playerSettingsInfo = assetFile?.GetAssetsOfType( AssetClassID.PlayerSettings ); - AssetTypeValueField? playerSettingsBase = assetsManager.GetBaseField( - assetFileInstance, - playerSettingsInfo?[0] - ); - - if (playerSettingsBase == null) + AssetTypeValueField? playerSettingsBase = null; + try { - AnsiConsole.MarkupLine( - "[red]( RAWR )[/] Can\'t get Player Settings fields! It\'s possible that this current version of Unity are currently not supported yet." + playerSettingsBase = assetsManager.GetBaseField( + assetFileInstance, + playerSettingsInfo?[0] ); - AnsiConsole.MarkupLine( - "Try updating USSR [bold green]classdata.tpk[/] manually from there: [link green]https://nightly.link/AssetRipper/Tpk/workflows/type_tree_tpk/master/uncompressed_file.zip[/] and try again." + } + catch (Exception ex) + { + AnsiConsole.MarkupLineInterpolated( + $"[red]( ERRO )[/] Can\'t get Player Settings fields! {ex.Message} It\'s possible that the current Unity version aren\'t supported yet." ); AnsiConsole.MarkupLine( - "If the issue still persist, try switching to another Unity version." + "( INFO ) Try updating the [bold green]classdata.tpk[/] manually from there: [link green]https://nightly.link/AssetRipper/Tpk/workflows/type_tree_tpk/master/uncompressed_file.zip[/] and try again. If the issue still persist, try use another Unity version." ); return null; } @@ -550,7 +532,7 @@ AssetsManager assetsManager if (hasProVersion && !showUnityLogo) { AnsiConsole.MarkupLine( - "[yellow]( WARN ) Unity splash screen already removed![/]" + "[yellow]( WARN ) [bold]Unity splash screen already removed![/][/]" ); return null; } @@ -565,21 +547,20 @@ AssetsManager assetsManager $"( INFO ) There's [green]{totalSplashScreen}[/] splash screen detected." ); - switch (totalSplashScreen) + if (totalSplashScreen <= 0) { - case 0: - AnsiConsole.MarkupLine( - "[yellow]( WARN ) Nothing to do. Finally, taking a rest :)[/]" - ); - return null; - case 1: - AnsiConsole.MarkupLine("( INFO ) Auto remove the splash screen..."); - goto RemoveSplashScreen; // auto remove the splash screen + AnsiConsole.MarkupLine("[yellow]( WARN ) Nothing to do.[/]"); + return null; } - AnsiConsole.MarkupLine( - "What order are Unity splash screen logo in your Player Settings? (Start from 0 [upmost])" - ); + for (int i = 0; i < totalSplashScreen; i++) + { + AnsiConsole.MarkupLineInterpolated( + $"[green]{i}[/] => [green]{splashScreenLogos.Children[i].FieldName}[/]" + ); + } + + AnsiConsole.MarkupLine("What order are Unity logo in your Player Settings?"); InputLogoIndex: int.TryParse( @@ -592,12 +573,12 @@ out splashScreenIndex if (splashScreenIndex < 0 && splashScreenIndex >= totalSplashScreen) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] There's no splash screen at index [red]{splashScreenIndex}[/]! Try again." + $"[red]( ERRO )[/] There's no splash screen at index [red]{splashScreenIndex}[/]! Try again." ); goto InputLogoIndex; } - RemoveSplashScreen: + // RemoveSplashScreen: AnsiConsole.MarkupLineInterpolated( $"( INFO ) Set [green]hasProVersion[/] = [green]{!hasProVersion}[/] | [green]m_ShowUnitySplashLogo[/] = [green]{!showUnityLogo}[/]" ); @@ -629,7 +610,7 @@ out splashScreenIndex catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when removing the splash screen! {ex.Message}" + $"[red]( ERRO )[/] Error when removing the splash screen! {ex.Message}" ); return null; } @@ -681,7 +662,7 @@ out splashScreenIndex catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when removing the watermark! {ex.Message}" + $"[red]( ERRO )[/] Error when removing the watermark! {ex.Message}" ); return null; } @@ -689,6 +670,7 @@ out splashScreenIndex static void WriteChanges( string modifiedFile, + AssetTypes assetType, AssetsFileInstance? assetFileInstance, BundleFileInstance? bundleFileInstance, List assetsReplacer @@ -753,7 +735,7 @@ List assetsReplacer catch (Exception ex) { AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR )[/] Error when writing changes! {ex.Message}" + $"[red]( ERRO )[/] Error when writing changes! {ex.Message}" ); } finally @@ -763,55 +745,42 @@ List assetsReplacer } } - static int DecompressCompressedWebData( - WebGLCompressionType compressionType, + static bool DecompressWebData( + WebCompressionTypes compressionType, string inputPath, string outputPath ) { - switch (compressionType) + AnsiConsole.MarkupLineInterpolated( + $"( INFO ) Decompressing data as {compressionType.ToString()} compression: [green]{inputPath}[/]..." + ); + + try { - case WebGLCompressionType.Brotli: - try - { - AnsiConsole.MarkupLineInterpolated( - $"( INFO ) Decompressing Brotli [green]{inputPath}[/]..." - ); + switch (compressionType) + { + case WebCompressionTypes.Brotli: BrotliUtils.DecompressFile(inputPath, outputPath); - return 0; - } - catch (Exception ex) - { - AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR ) Failed to decompress {inputPath}![/] {ex.Message} Try choose different compression type." - ); - Console.WriteLine(); - if (File.Exists(outputPath)) - File.Delete(outputPath); - return 1; - } - case WebGLCompressionType.GZip: - try - { - AnsiConsole.MarkupLineInterpolated( - $"( INFO ) Decompressing GZip [green]{inputPath}[/]..." - ); + return true; + case WebCompressionTypes.GZip: GZipUtils.DecompressFile(inputPath, outputPath); - return 0; - } - catch (Exception ex) - { - AnsiConsole.MarkupLineInterpolated( - $"[red]( RAWR ) Failed to decompress {inputPath}![/] {ex.Message} Try choose different compression type." - ); - Console.WriteLine(); - if (File.Exists(outputPath)) - File.Delete(outputPath); - return 1; - } - case WebGLCompressionType.None: - default: - return 1; + return true; + case WebCompressionTypes.None: + default: + return false; + } + } + catch (Exception ex) + { + if (File.Exists(outputPath)) + File.Delete(outputPath); + + AnsiConsole.MarkupLineInterpolated( + $"[red]( ERRO ) Failed to decompress: {inputPath}![/] {ex.Message} Try different compression type." + ); + Console.WriteLine(); + + return false; } } } diff --git a/USSR.csproj b/USSR.csproj index 66c06bc..10c8f49 100644 --- a/USSR.csproj +++ b/USSR.csproj @@ -13,7 +13,8 @@ - + + diff --git a/Utils/Utility.cs b/Utils/Utility.cs index cc478cd..94186c4 100644 --- a/Utils/Utility.cs +++ b/Utils/Utility.cs @@ -5,6 +5,7 @@ namespace USSR.Utilities internal class Utility { const string LAST_OPEN_FILE = "last_open.txt"; + const string VERSION_FILE = "version.txt"; /// /// Check the file signature if it's a valid file. @@ -169,5 +170,14 @@ internal static string GetLastOpenedFile() return lastOpenedDirectory; } + + internal static string? GetVersion() + { + if (!File.Exists(VERSION_FILE)) + return "UNKNOWN"; + + using StreamReader reader = new(VERSION_FILE); + return reader.ReadLine(); + } } } diff --git a/build.sh b/build.sh index 6572b8f..ca51183 100644 --- a/build.sh +++ b/build.sh @@ -1,8 +1,8 @@ #!/bin/bash -VERSION="1.1.7" +VERSION=$(