Skip to content

Commit

Permalink
Setup CLI (tModLoader#4353)
Browse files Browse the repository at this point in the history
* Implement setup CLI

* Remove obsolete call

* Keep block-scoped namespaces for existing files for easier diffing

* Use tabs in Setup.GUI.Designer.csproj

* Update Setup.GUI.Designer.csproj

* Remove obsolete code

* Cleanup diffs a bit

* Disable nullability in HookGenerator

* Add SupportedOSPlatform to steam registry key queries

* Use dotnet run for faster and cleaner CLI launching

* Fix command existence checks in setup-cli.sh

* Add a marker file to skip unnecessary slow git submodule restore

* Remove unnecessary pause on error in setup-cli.bat

* More diff reductions

* More diff reductions

* Remov usage of this

* Only save if settings changed

* Change async-await in MainForm

* Update UpdateLocalizationFilesTask

* Fix warning

* Simplify diff sub commands

* Re-add newline to .gitignore

* Update SetupOperation

* Make UpdateLocalizationFilesTask cross-platform compatible

Process.Start will throw an error if python is not found

* Make OK the default option

* Make LogsDir static

* Make Ref class obsolete

* Rename PathUtils.SetCrossPlatformDirectorySeparators; add UnixJoin method

* Remove obsolete setting of default parameter

* Use progress in RoslynTask

* Make results in PatchTask local

* Use null-forgiving operator for logFile; won't be null

* Break look in CompositeTask if a task failed

* Use singleton instead of transient

* Reset MainForm.resx

* Remove need for CSharpSelectionPrompt

* Fix live table renderer bug when status has not been updated yet

* Simplify LiveConsoleProgress

* Refactor LiveConsoleProgress variable names

* Get the localization update task to work with the live progress

* Fix inverted time test in setup-cli.sh

* Fix Setup.GUI launchSettings

* Fix warning

* Add new linux Terraria install search path

* Revert most of the formatting changes in DecompileTask for better diffs

* Simplify Terraria selection prompt, and SetupOperation.ConfigurationPrompt using OperationCancelledExceptions

* Remove unnecessary call and clarify comment

* Cleanup diffs in Formatting folder

* Cleanup HookGenerator diffs

* Use sync method for better readability

* Cleanup some more diffs

* Cleanup

* Only show informative error prompt if Terraria directory cannot be found

* Make commands fail if task failed; make setup-auto command also fail on warnings

* Use setup-cli.bat in build.yml; remove "auto" option from setup.bat

* Fix variable and method names

* Make field readonly

* Return exit code instead of calling `Environment.Exit`

* Fix live progress overflow

* Cleanup

* Remove diff in Setup.GUI.Designer.csproj

* Add missing EnableModelessKeyboardInterop call for PatchReviewer

* Fix 'obj\project.assets.json’ doesn’t have a target error when building GUI projects

* Cleanup async task running code in MainForm

* Set ConfigureAwait(false) to be the default for Setup.Core

* Use timer for main form progress updates to avoid bottlenecking or overwhelming on Invoke/BeginInvoke

* Add newline to task completion message. Required for unix consoles

* Cleanup warnings in DecompileTask

* Reference the setup gui build in the output directory

* Fix gui progress bar not animating fast enough

* Minor diff minimisations

* Use non async work items for a couple of simple file writes

* Correctly configure var/explicit type diagnostics.

* Remove progress messages from PlainConsoleProgress as they're not helpful

* Move encrypted Terraria.exe into the setup program so it can be used for Mac and Linux decomp

Note that the provided Terraria_v1.4.4.9_win.exe.enc has been edited with dnSpy to include SteelSeriesEngineWrapper.dll as an embedded resource for the CI. This will not be required in 1.4.5

* Refactor exception handling

* Cleanup

* Refactor updating of .targets files; add CLI options to set paths

* Also update Git info on every run in GUI project

* Implement Terraria executable retrieval flow for decompilation

* Remove obsolete field from PatchTask

* Refactor AggregateException throwing

* Update docs

* Update comment

* Add strict command line option

* Fix warning

* Remove padding from derived keys

* Remove BaseCommandSettings inheritance for secret commands; base properties are not used

* Add new CLI options to DecompileCommand; update build script

* Remove --no-validate flag from DecompileCommand

* Refactor progress to reduce output for --plain-progress option

* Use other lock object in MainForm

* Use lists to keep WorkItemProgresses to reduce visual noise by items moving around

* Remove SetupAutoCommand

* Move Indent method in PlainConsoleProgress

* Remove unnecessary exit code checks in build.yml

* Remove unnecessary method parameter

* Add a TaskProgressBase class; use it for GUI and live console progress

* Move WorkItemProgress class into TaskProgressBase

* Fix secret commands auto retrieval of Terraria exe path

* Fix bash script not passing quoted arguments correctly

* Remove embedded SteelSeriesEngineWrapper.dll from Terraria secret. It's now just the regular windows copy

* Fix valid culture identification on other platforms

* Supply XNA framework dlls and .NET reference assemblies to perfect decompilation on osx/linux

* Remove --max-parallelism 1 from github decompile

* Extract zips directly without using temp files

* Cleanup

* Fix merge

* Fix SteamLibraryFoldersRegex for new steam format

* Fix merge derp

* Make setup-cli.sh executable in git

* Update LiveConsoleProgress

* Add UpdateWorkspaceInfoCommand; fix build.yml; fix file/folder path inputs in CLI

* Inline method

* Fix DecompileCommand description

* Fix docs

* Add constants for paths

* Refactor PathUtils.GetCrossPlatformFullPath

* Also migrate settings on CLI startup

* Fix PathUtils.GetCrossPlatformFullPath

* Better cross platform path detection of reference assemblies for HookGen

* Improve HookGen progress reporting

* Escape markup in status text in LiveConsoleProgress

* Cleanup dead code path

* Simplify name of TerrariaNetCore patch stage

* Use Markup.Escape

---------

Co-authored-by: Chicken-Bones <mehvids@gmail.com>
  • Loading branch information
alueck and Chicken-Bones authored Sep 13, 2024
1 parent adecdfa commit 3f60c70
Show file tree
Hide file tree
Showing 110 changed files with 3,634 additions and 1,609 deletions.
9 changes: 6 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,12 @@ dotnet_diagnostic.CA2211.severity = none
#### C# Coding Conventions ####

# var preferences
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_var_when_type_is_apparent = true:none
csharp_style_var_elsewhere = false
csharp_style_var_for_built_in_types = false
csharp_style_var_when_type_is_apparent = true

dotnet_diagnostic.IDE0007.severity = suggestion # Use var instead of explicit type
dotnet_diagnostic.IDE0008.severity = none # Use explicit type instead of var

# Expression-bodied members
csharp_style_expression_bodied_lambdas = true:silent
Expand Down
25 changes: 15 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,21 @@ jobs:
# Extra file needed for client decomp which isn't embedded in the Terraria.exe, will be embedded in 1.4.5
cp patches/TerrariaNetCore/Terraria/Libraries/Common/SteelSeriesEngineWrapper.dll ./$TERRARIA_VERSION/Windows/SteelSeriesEngineWrapper.dll
echo Extracting Setup Secret Assets
gpg --quiet --batch --yes --decrypt --passphrase="$SETUP_ASSETS_PASSPHRASE" --output ./$TERRARIA_VERSION/Windows/Terraria.exe ./setup/SecretAssets/SetupAsset1.gpg
echo Installing XNA
curl -s -L https://github.com/JavidPack/tModLoaderPublishIntegration/raw/master/xnafx40_redist.msi -O
msiexec //i xnafx40_redist.msi //quiet
echo XNA Installed
echo ::group::Running setup.bat
./setup.bat auto ./$TERRARIA_VERSION/Windows
echo ::group::Running setup-cli.bat
if [ ${{github.ref}} = 'refs/heads/${{env.StableBranch}}' ] ; then
tmlVersionDefine=TML_$(cut -d '.' -f1 <<< $TMLVERSION)_$(cut -d '.' -f2 <<< $TMLVERSION)
echo "TMLVERSIONDefine: $tmlVersionDefine"
sed -i "s#<\!-- TML stable version define placeholder -->#<DefineConstants>\$(DefineConstants);$tmlVersionDefine</DefineConstants>#g" ./patches/tModLoader/Terraria/release_extras/tMLMod.targets
fi
if [ ! -d "./src/decompiled" ]; then
./setup-cli.bat decompile --key $TERRARIA_OWNERSHIP_KEY --terraria-steam-dir ./$TERRARIA_VERSION/Windows --tml-dev-steam-dir steam_build --plain-progress -f --strict
else
echo "src/decompiled found. Skipping decompilation..."
./setup-cli.bat update-workspace-info ./$TERRARIA_VERSION/Windows steam_build --no-validate
fi
./setup-cli.bat regen-source --plain-progress -f --strict
echo ::endgroup::
echo ::group::WorkspaceInfo.targets
Expand Down
4 changes: 2 additions & 2 deletions patches/Terraria/removed_files.list
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ReLogic\Microsoft\Xna\Framework.RuntimeProfile
Terraria\Microsoft\Xna\Framework.RuntimeProfile
ReLogic/Microsoft/Xna/Framework.RuntimeProfile
Terraria/Microsoft/Xna/Framework.RuntimeProfile
26 changes: 13 additions & 13 deletions patches/TerrariaNetCore/removed_files.list
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Terraria\Libraries\NVorbis.System.ValueTuple.dll
ReLogic\Localization\IME\WindowsIme.cs
Terraria\Libraries\CsvHelper\CsvHelper.dll
Terraria\Libraries\DotNetZip\Ionic.Zip.CF.dll
Terraria\Libraries\JSON.NET\Newtonsoft.Json.dll
Terraria\Libraries\MP3Sharp\MP3Sharp.dll
Terraria\Libraries\NVorbis\NVorbis.dll
Terraria\Libraries\RailSDK.Windows\RailSDK.Net.dll
Terraria\Libraries\Steamworks.NET.Windows\Steamworks.NET.dll
Terraria\Social\WeGame\AsyncTaskHelper.cs
Terraria\Social\WeGame\CurrentThreadRunner.cs
ReLogic\Localization\IME\Windows\Imm.cs
ReLogic\Localization\IME\Windows\NativeMethods.cs
ReLogic/Localization/IME/Windows/Imm.cs
ReLogic/Localization/IME/Windows/NativeMethods.cs
ReLogic/Localization/IME/WindowsIme.cs
Terraria/Libraries/CsvHelper/CsvHelper.dll
Terraria/Libraries/DotNetZip/Ionic.Zip.CF.dll
Terraria/Libraries/JSON.NET/Newtonsoft.Json.dll
Terraria/Libraries/MP3Sharp/MP3Sharp.dll
Terraria/Libraries/NVorbis.System.ValueTuple.dll
Terraria/Libraries/NVorbis/NVorbis.dll
Terraria/Libraries/RailSDK.Windows/RailSDK.Net.dll
Terraria/Libraries/Steamworks.NET.Windows/Steamworks.NET.dll
Terraria/Social/WeGame/AsyncTaskHelper.cs
Terraria/Social/WeGame/CurrentThreadRunner.cs
28 changes: 14 additions & 14 deletions patches/tModLoader/removed_files.list
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
ReLogic\Content\AssetLoader.cs
ReLogic\Content\AsyncAssetLoader.cs
ReLogic\Content\ContentRejectionFromFailedLoad_ByAssetExtensionType.cs
ReLogic\Content\IAsyncAssetLoader.cs
Terraria\DataStructures\AEntitySource_OnHit.cs
Terraria\DataStructures\EntitySource_ByItemSourceId.cs
Terraria\DataStructures\EntitySource_ByProjectileSourceId.cs
Terraria\DataStructures\EntitySource_OnHit_ByItemSourceID.cs
Terraria\DataStructures\EntitySource_OnHit_ByProjectileSourceID.cs
ReLogic\Content\Sources\XnaContentSource.cs
Terraria\Libraries\Common\Ionic.Zip.CF.dll
Terraria\Libraries\FNA\FNA.dll
Terraria\Libraries\Mono\Steamworks.NET.dll
Terraria\Libraries\Mono\System.Windows.Forms.dll
ReLogic/Content/AssetLoader.cs
ReLogic/Content/AsyncAssetLoader.cs
ReLogic/Content/ContentRejectionFromFailedLoad_ByAssetExtensionType.cs
ReLogic/Content/IAsyncAssetLoader.cs
ReLogic/Content/Sources/XnaContentSource.cs
Terraria/DataStructures/AEntitySource_OnHit.cs
Terraria/DataStructures/EntitySource_ByItemSourceId.cs
Terraria/DataStructures/EntitySource_ByProjectileSourceId.cs
Terraria/DataStructures/EntitySource_OnHit_ByItemSourceID.cs
Terraria/DataStructures/EntitySource_OnHit_ByProjectileSourceID.cs
Terraria/Libraries/Common/Ionic.Zip.CF.dll
Terraria/Libraries/FNA/FNA.dll
Terraria/Libraries/Mono/Steamworks.NET.dll
Terraria/Libraries/Mono/System.Windows.Forms.dll
30 changes: 30 additions & 0 deletions setup-cli.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@echo off
setlocal enabledelayedexpansion

where git >NUL
if !errorlevel! neq 0 (
echo git not found on PATH
exit /b %errorlevel%
)

set busybox=patches\tModLoader\Terraria\release_extras\LaunchUtils\busybox64.exe
set submoduleupdatemarker=.git\tml-setup-module-init.touch
%busybox% [ .git\index -ot %submoduleupdatemarker% ]
rem a 0 exit code means true, a 1 exit code indicates false, or missing file
if !errorlevel! neq 0 (
echo Restoring git submodules
git submodule update --init --recursive
if !errorlevel! neq 0 (
exit /b %errorlevel%
)
%busybox% touch %submoduleupdatemarker%
)

where dotnet >NUL
if !errorlevel! neq 0 (
echo dotnet not found on PATH. Install .NET Core!
exit /b %errorlevel%
)

endlocal
dotnet run --project setup/CLI/Setup.CLI.csproj -c Release -p:WarningLevel=0 -v q -- %*
28 changes: 28 additions & 0 deletions setup-cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/sh

if ! command -v git > /dev/null;
then
echo "git not found in PATH"
exit 1
fi

submoduleupdatemarker=".git/tml-setup-module-init.touch"
if ! [ ".git/index" -ot "$submoduleupdatemarker" ]
then
echo "Restoring git submodules"
git submodule update --init --recursive
if [ $? -ne 0 ]
then
exit $?
fi
touch "$submoduleupdatemarker"
fi

if ! command -v dotnet > /dev/null
then
echo "dotnet not found in PATH"
exit 1
fi

dotnet run --project setup/CLI/Setup.CLI.csproj -c Release -p:WarningLevel=0 -v q -- "$@"

48 changes: 23 additions & 25 deletions setup.bat
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
@echo off
setlocal enabledelayedexpansion

where git >NUL
if NOT ["%errorlevel%"]==["0"] (
if !errorlevel! neq 0 (
echo git not found on PATH
pause
exit /b %errorlevel%
)

echo Restoring git submodules
git submodule update --init --recursive
if NOT ["%errorlevel%"]==["0"] (
pause
exit /b %errorlevel%
set busybox=patches\tModLoader\Terraria\release_extras\LaunchUtils\busybox64.exe
set submoduleupdatemarker=.git\tml-setup-module-init.touch
%busybox% [ .git\index -ot %submoduleupdatemarker% ]
rem a 0 exit code means true, a 1 exit code indicates false, or missing file
if !errorlevel! neq 0 (
echo Restoring git submodules
git submodule update --init --recursive
if !errorlevel! neq 0 (
pause
exit /b %errorlevel%
)
%busybox% touch %submoduleupdatemarker%
)

where dotnet >NUL
if NOT ["%errorlevel%"]==["0"] (
if !errorlevel! neq 0 (
echo dotnet not found on PATH. Install .NET Core!
pause
exit /b %errorlevel%
)

If "%1"=="auto" (
echo building setupAuto.csproj
dotnet build setup/GUI/Setup.Auto.csproj --output "setup/bin/Debug/net6.0-windows"
endlocal

if NOT ["%errorlevel%"]==["0"] (
pause
exit /b %errorlevel%
)
echo building Setup.GUI.csproj
dotnet build setup/GUI/Setup.GUI.csproj -c Release -p:WarningLevel=0 -v q

"setup/bin/Debug/net6.0-windows/setup-auto.exe" %2
) Else (
echo building setup.csproj
dotnet build setup/GUI/Setup.GUI.csproj --output "setup/bin/Debug/net6.0-windows"

if NOT ["%errorlevel%"]==["0"] (
pause
exit /b %errorlevel%
)
if NOT ["%errorlevel%"]==["0"] (
pause
exit /b %errorlevel%
)

start "" "setup/bin/Debug/net6.0-windows/setup-gui.exe" %*
)
start "" "setup/GUI/bin/Release/net8.0-windows/setup-gui.exe" %*
2 changes: 2 additions & 0 deletions setup/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
user.settings
.NETFramework
14 changes: 14 additions & 0 deletions setup/CLI/CancellableAsyncCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Spectre.Console.Cli;

namespace Terraria.ModLoader.Setup.CLI;

public abstract class CancellableAsyncCommand<TSettings> : AsyncCommand<TSettings>
where TSettings : CommandSettings
{
private readonly ConsoleAppCancellationTokenSource cancellationTokenSource = new();

public sealed override async Task<int> ExecuteAsync(CommandContext context, TSettings settings)
=> await ExecuteAsync(context, settings, cancellationTokenSource.Token);

protected abstract Task<int> ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken);
}
14 changes: 14 additions & 0 deletions setup/CLI/Commands/BaseCommandSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.ComponentModel;
using Spectre.Console.Cli;

namespace Terraria.ModLoader.Setup.CLI.Commands;

public class BaseCommandSettings : CommandSettings
{
[CommandOption("--plain-progress")]
public bool PlainProgress { get; init; }

[CommandOption("--strict")]
[Description("Exit with non-success instead of success exit code on warnings.")]
public bool Strict { get; init; }
}
72 changes: 72 additions & 0 deletions setup/CLI/Commands/DecompileCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.ComponentModel;
using Spectre.Console.Cli;
using Terraria.ModLoader.Setup.Core;
using Terraria.ModLoader.Setup.Core.Utilities;

namespace Terraria.ModLoader.Setup.CLI.Commands;

public sealed class DecompileCommandSettings : BaseCommandSettings
{
private readonly string? terrariaSteamDir;
private readonly string? tmlDevSteamDir;

[CommandOption("--server-only")]
[Description("Decompile only server code.")]
public bool ServerOnly { get; init; }

[CommandOption("-f|--no-prompts")]
[Description("Execute command without prompting for confirmation or any missing information.")]
public bool NoPrompts { get; init; }

[CommandOption("--terraria-steam-dir")]
[Description("Path to the Terraria steam directory. This is usually auto-detected. The value is persisted to src/WorkspaceInfo.targets")]
public string? TerrariaSteamDir {
get => terrariaSteamDir;
init => terrariaSteamDir = value != null ? PathUtils.GetCrossPlatformFullPath(value) : null;
}

[CommandOption("--tml-dev-steam-dir")]
[Description("Path to the TML dev steam directory. This is derived from the Terraria steam directory if no value is supplied. The value is persisted to src/WorkspaceInfo.targets")]
public string? TMLDevSteamDir {
get => tmlDevSteamDir;
init => tmlDevSteamDir = value != null ? PathUtils.GetCrossPlatformFullPath(value) : null;
}

[CommandOption("--max-parallelism")]
[Description("Maximum parallel decompile tasks. Default is CPU count.")]
public int? MaxParallelism { get; init; }

[CommandOption("-k|--key")]
[Description("Terraria ownership key in hexadecimal format. This is used to decrypt the Windows Terraria executable on non-windows platforms. The key is usally derived from the installed Terraria.exe")]
public string? Key { get; init; }
}

public sealed class DecompileCommand : CancellableAsyncCommand<DecompileCommandSettings>
{
private readonly TaskRunner taskRunner;
private readonly IServiceProvider serviceProvider;

public DecompileCommand(
TaskRunner taskRunner,
IServiceProvider serviceProvider)
{
this.taskRunner = taskRunner;
this.serviceProvider = serviceProvider;
}

protected override async Task<int> ExecuteAsync(CommandContext context, DecompileCommandSettings settings, CancellationToken cancellationToken)
{
DecompileTaskParameters decompileTaskParameters = DecompileTaskParameters.CreateDefault(
settings.TerrariaSteamDir,
settings.TMLDevSteamDir,
settings.ServerOnly,
settings.MaxParallelism,
string.IsNullOrWhiteSpace(settings.Key) ? null : Convert.FromHexString(settings.Key));

return await taskRunner.Run(
new DecompileTask(decompileTaskParameters, serviceProvider),
settings,
settings.NoPrompts,
cancellationToken: cancellationToken);
}
}
Loading

0 comments on commit 3f60c70

Please sign in to comment.