Skip to content

Commit

Permalink
Added Linux launch instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
slxdy committed Nov 19, 2024
1 parent 8a7b19e commit 14523e9
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 59 deletions.
3 changes: 3 additions & 0 deletions MelonLoader.Installer/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
<Style Selector="ComboBox">
<Setter Property="BorderThickness" Value="0" />
</Style>
<Style Selector="TextBox">
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</Application.Styles>
</Application>
37 changes: 14 additions & 23 deletions MelonLoader.Installer/MLManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,11 @@ private static async Task<bool> GetVersionsAsync(List<MLVersion> versions)
return true;
}

public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(false)] out string? errorMessage)
public static string? Uninstall(string gameDir, bool removeUserFiles)
{
if (!Directory.Exists(gameDir))
{
errorMessage = "The provided directory does not exist.";
return false;
return "The provided directory does not exist.";
}

foreach (var proxy in proxyNames)
Expand All @@ -194,8 +193,7 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = "Failed to uninstall MelonLoader. Ensure that the game is fully closed before trying again.";
return false;
return "Failed to uninstall MelonLoader. Ensure that the game is fully closed before trying again.";
}
}

Expand All @@ -208,8 +206,7 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = "Failed to uninstall MelonLoader. Ensure that the game is fully closed before trying again.";
return false;
return "Failed to uninstall MelonLoader. Ensure that the game is fully closed before trying again.";
}
}

Expand All @@ -222,8 +219,7 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = $"Failed to fully uninstall MelonLoader: Failed to remove dobby.";
return false;
return "Failed to fully uninstall MelonLoader: Failed to remove dobby.";
}
}

Expand All @@ -236,8 +232,7 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = $"Failed to fully uninstall MelonLoader: Failed to remove 'NOTICE.txt'.";
return false;
return "Failed to fully uninstall MelonLoader: Failed to remove 'NOTICE.txt'.";
}
}

Expand All @@ -252,8 +247,7 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = $"Failed to fully uninstall MelonLoader: Failed to remove the Mods folder.";
return false;
return "Failed to fully uninstall MelonLoader: Failed to remove the Mods folder.";
}
}

Expand All @@ -266,8 +260,7 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = $"Failed to fully uninstall MelonLoader: Failed to remove the Plugins folder.";
return false;
return "Failed to fully uninstall MelonLoader: Failed to remove the Plugins folder.";
}
}

Expand All @@ -280,8 +273,7 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = $"Failed to fully uninstall MelonLoader: Failed to remove the UserData folder.";
return false;
return "Failed to fully uninstall MelonLoader: Failed to remove the UserData folder.";
}
}

Expand All @@ -294,14 +286,12 @@ public static bool Uninstall(string gameDir, bool removeUserFiles, [NotNullWhen(
}
catch
{
errorMessage = $"Failed to fully uninstall MelonLoader: Failed to remove the UserLibs folder.";
return false;
return "Failed to fully uninstall MelonLoader: Failed to remove the UserLibs folder.";
}
}
}

errorMessage = null;
return true;
return null;
}

public static void SetLocalZip(string zipPath, InstallProgressEventHandler? onProgress, InstallFinishedEventHandler? onFinished)
Expand Down Expand Up @@ -372,9 +362,10 @@ public static async Task InstallAsync(string gameDir, bool removeUserFiles, MLVe

onProgress?.Invoke(0, "Uninstalling previous versions");

if (!Uninstall(gameDir, removeUserFiles, out var error))
var unErr = Uninstall(gameDir, removeUserFiles);
if (unErr != null)
{
onFinished?.Invoke(error);
onFinished?.Invoke(unErr);
return;
}

Expand Down
25 changes: 8 additions & 17 deletions MelonLoader.Installer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ internal static class Program
[STAThread]
private static void Main(string[] args)
{
SetupCrashLogging();

if (!Directory.Exists(Config.CacheDir))
Directory.CreateDirectory(Config.CacheDir);

Expand Down Expand Up @@ -53,28 +51,21 @@ private static void Main(string[] args)

Updater.UpdateIfPossible();

BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
try
{
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
catch (Exception ex)
{
LogCrashException(ex);
}

Exiting?.Invoke();

processLock.Dispose();
File.Delete(processLockPath);
}

private static void SetupCrashLogging()
{
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
}

private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (!e.IsTerminating)
return;

if (e.ExceptionObject is Exception ex and not TaskCanceledException)
LogCrashException(ex);
}

public static void LogCrashException(Exception ex)
{
try
Expand Down
11 changes: 11 additions & 0 deletions MelonLoader.Installer/ViewModels/DetailsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public class DetailsViewModel(GameModel game) : ViewModelBase
{
private bool _installing;
private bool _offline;
private bool _linuxInstructions;

public GameModel Game => game;

Expand All @@ -29,5 +30,15 @@ public bool Offline
}
}

public bool LinuxInstructions
{
get => _linuxInstructions;
set
{
_linuxInstructions = value;
OnPropertyChanged();
}
}

public bool EnableSettings => !Offline && !Installing;
}
3 changes: 2 additions & 1 deletion MelonLoader.Installer/ViewModels/GameModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class GameModel(string path, string name, bool is32Bit, bool isLinux, Gam
public string MLStatusText => mlVersion == null ? "Not Installed" : "Installed " + MLVersionText;
public bool MLInstalled => mlVersion != null;
public bool IsProtected => isProtected;
public string Dir { get; } = System.IO.Path.GetDirectoryName(path)!;

public SemVersion? MLVersion
{
Expand Down Expand Up @@ -46,7 +47,7 @@ public bool ValidateGame()
return false;
}

var newMlVersion = Installer.MLVersion.GetMelonLoaderVersion(System.IO.Path.GetDirectoryName(path)!, out var ml86, out var mlLinux);
var newMlVersion = Installer.MLVersion.GetMelonLoaderVersion(Dir, out var ml86, out var mlLinux);
if (newMlVersion != null && (ml86 != Is32Bit || mlLinux != IsLinux))
newMlVersion = null;

Expand Down
31 changes: 27 additions & 4 deletions MelonLoader.Installer/Views/DetailsView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="650"
x:Class="MelonLoader.Installer.Views.DetailsView"
x:DataType="vm:DetailsViewModel">
<Grid RowDefinitions="auto, *, 80, 60, auto, *, 80, auto, 2*, auto, auto, 30, 70, auto, *">
<Grid RowDefinitions="Auto, *">
<Button Grid.Row="0" IsEnabled="{Binding !Installing}" Click="BackClickHandler"
FontSize="20" Background="Transparent" Content="" FontWeight="Bold" Foreground="Gray"
HorizontalContentAlignment="Center" />
FontSize="20" Background="Transparent" Content="" FontWeight="Bold" Foreground="Gray"
HorizontalContentAlignment="Center" />

<Grid Grid.Row="1" RowDefinitions="auto, *, 80, 60, auto, *, 80, auto, 2*, auto, auto, 30, 70, auto, auto, *" IsVisible="{Binding !LinuxInstructions}">
<Border Grid.Row="2" ClipToBounds="True" CornerRadius="20" HorizontalAlignment="Center">
<Image Source="{Binding Game.Icon}" />
</Border>
<TextBlock Grid.Row="3" HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="22" Text="{Binding Game.Name}" />
<Grid Grid.Row="4" ColumnDefinitions="*, auto">
<TextBox Grid.Column="0" Foreground="Gray" Text="{Binding Game.Path}" IsReadOnly="True"
<TextBox Grid.Column="0" Foreground="Gray" Text="{Binding Game.Dir}" IsReadOnly="True"
Focusable="False" SelectionBrush="#222" Background="Transparent" BorderThickness="0" />
<Button Click="OpenDirHandler" Grid.Column="1" Margin="3">📂</Button>
</Grid>
Expand Down Expand Up @@ -56,5 +58,26 @@
VerticalAlignment="Center" Opacity="0.7" FontSize="14" />
</Grid>
</Grid>

<TextBlock Name="ShowLinuxInstructions" Grid.Row="14" Tapped="ShowLinuxInstructionsHandler" HorizontalAlignment="Center" Foreground="Gray" TextDecorations="Underline" FontSize="13" Cursor="Hand">
How do I start MelonLoader?
</TextBlock>
</Grid>
<Grid Grid.Row="1" Margin="30" RowDefinitions="auto, *" IsVisible="{Binding LinuxInstructions}">
<TextBlock Grid.Row="0" FontSize="25" Margin="0 0 0 20">Linux Launch Instructions</TextBlock>
<StackPanel Orientation="Vertical" IsVisible="{Binding !Game.IsLinux}" Grid.Row="1">
<TextBlock TextWrapping="Wrap">In order to start MelonLoader under Wine, you'll need to export the following variable:</TextBlock>
<TextBox Margin="0 4 0 10" BorderBrush="Transparent" IsReadOnly="True">WINEDLLOVERRIDES="version=n,b"</TextBox>
<TextBlock TextWrapping="Wrap">On Steam, you can set the launch options to:</TextBlock>
<TextBox Margin="0 4 0 10" BorderBrush="Transparent" IsReadOnly="True">WINEDLLOVERRIDES="version=n,b" %command%"</TextBox>
</StackPanel>
<StackPanel Orientation="Vertical" IsVisible="{Binding Game.IsLinux}" Grid.Row="1">
<TextBlock TextWrapping="Wrap">In order to start MelonLoader, you'll need to export the following variables:</TextBlock>
<TextBox Name="LdLibPathVar" Margin="0 4 0 0" BorderBrush="Transparent" IsReadOnly="True"/>
<TextBox Name="LdPreloadVar" Margin="0 4 0 10" BorderBrush="Transparent" IsReadOnly="True">LD_PRELOAD="libversion.so"</TextBox>
<TextBlock TextWrapping="Wrap">On Steam, you can set the launch options to:</TextBlock>
<TextBox Name="SteamLaunchOptions" Margin="0 4 0 10" BorderBrush="Transparent" IsReadOnly="True"/>
</StackPanel>
</Grid>
</Grid>
</UserControl>
53 changes: 39 additions & 14 deletions MelonLoader.Installer/Views/DetailsView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ protected override void OnDataContextChanged(EventArgs e)

if (Model == null)
return;

#if LINUX
if (Model.Game.IsLinux)
{
LdLibPathVar.Text = $"LD_LIBRARY_PATH=\"{Model.Game.Dir}:$LD_LIBRARY_PATH\"";
SteamLaunchOptions.Text = $"{LdLibPathVar.Text} {LdPreloadVar.Text} %command%";
}

ShowLinuxInstructions.IsVisible = Model.Game.MLInstalled;
#endif

Model.Game.PropertyChanged += PropertyChangedHandler;

Expand Down Expand Up @@ -73,7 +83,16 @@ public void UpdateVersionList()

private void BackClickHandler(object sender, RoutedEventArgs args)
{
if (Model is { Installing: true })
if (Model == null)
return;

if (Model.LinuxInstructions)
{
Model.LinuxInstructions = false;
return;
}

if (Model.Installing)
return;

MainWindow.Instance.ShowMainView();
Expand Down Expand Up @@ -116,6 +135,7 @@ private void InstallHandler(object sender, RoutedEventArgs args)
}

Model.Installing = true;
ShowLinuxInstructions.IsVisible = false;

_ = MLManager.InstallAsync(Path.GetDirectoryName(Model.Game.Path)!, Model.Game.MLInstalled && !KeepFilesCheck.IsChecked!.Value,
(MLVersion)VersionCombobox.SelectedItem!, Model.Game.IsLinux, Model.Game.Is32Bit,
Expand All @@ -139,26 +159,28 @@ private void OnInstallFinished(string? errorMessage)

var wasReinstall = Model.Game.MLInstalled;
Model.Game.ValidateGame();

#if LINUX
ShowLinuxInstructions.IsVisible = Model.Game.MLInstalled;
#endif

Model.Installing = false;
NightlyCheck.IsEnabled = true;
VersionCombobox.IsEnabled = true;

if (errorMessage != null)
{
DialogBox.ShowError(errorMessage);
return;
}

DialogBox.ShowNotice("Success!", $"{(wasReinstall ? "Reinstall" : "Install")} was Successful!");
DialogBox.ShowNotice("Success!", $"Successfully {(Model.Game.MLInstalled ? (wasReinstall ? "reinstalled" : "installed") : "uninstalled")} MelonLoader!");
}

private void OpenDirHandler(object sender, RoutedEventArgs args)
{
if (Model == null)
return;

TopLevel.GetTopLevel(this)!.Launcher.LaunchDirectoryInfoAsync(new(Path.GetDirectoryName(Model.Game.Path)!));
TopLevel.GetTopLevel(this)!.Launcher.LaunchDirectoryInfoAsync(new(Model.Game.Dir));
}

private void UninstallHandler(object sender, RoutedEventArgs args)
Expand All @@ -172,15 +194,9 @@ private void UninstallHandler(object sender, RoutedEventArgs args)
if (!Model.Game.MLInstalled)
return;

if (!MLManager.Uninstall(Path.GetDirectoryName(Model.Game.Path)!, !KeepFilesCheck.IsChecked!.Value, out var error))
{
DialogBox.ShowError(error);
Model.Game.ValidateGame();
return;
}

Model.Game.ValidateGame();
DialogBox.ShowNotice("Success!", "Uninstall was Successful!");
var error = MLManager.Uninstall(Model.Game.Dir, !KeepFilesCheck.IsChecked!.Value);

OnInstallFinished(error);
}

private async void SelectZipHandler(object sender, TappedEventArgs args)
Expand Down Expand Up @@ -208,6 +224,7 @@ private async void SelectZipHandler(object sender, TappedEventArgs args)
var path = files[0].Path.LocalPath;

Model.Installing = true;
ShowLinuxInstructions.IsVisible = false;

_ = Task.Run(() => MLManager.SetLocalZip(path,
(progress, newStatus) => Dispatcher.UIThread.Post(() => OnInstallProgress(progress, newStatus)),
Expand All @@ -226,4 +243,12 @@ private async void SelectZipHandler(object sender, TappedEventArgs args)
UpdateVersionList();
})));
}

private void ShowLinuxInstructionsHandler(object sender, TappedEventArgs args)
{
if (Model == null)
return;

Model.LinuxInstructions = true;
}
}
2 changes: 2 additions & 0 deletions MelonLoader.Installer/Views/MainView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ protected override void OnDataContextChanged(EventArgs e)
if (Model == null)
return;

Model.Ready = false;

Task.Run(InitServicesAsync);
}

Expand Down

0 comments on commit 14523e9

Please sign in to comment.