mirror of
https://gitlab.com/2009scape/Saradomin-Launcher.git
synced 2026-08-01 14:19:14 -06:00
UX
This commit is contained in:
parent
babd1d3058
commit
6745b5f35a
7 changed files with 163 additions and 139 deletions
|
|
@ -60,10 +60,6 @@ namespace Saradomin.Infrastructure.Services
|
|||
string tempDir = Path.Combine(CrossPlatform.LocateDefault2009scapeHome(), "singleplayer_temp");
|
||||
if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true);
|
||||
await Task.Run(() => ZipFile.ExtractToDirectory(downloadPath, tempDir));
|
||||
foreach (string directory in Directory.GetDirectories(tempDir))
|
||||
{
|
||||
Console.WriteLine("Found directory " + directory + " in " + tempDir);
|
||||
}
|
||||
Directory.Move(Directory.GetDirectories(tempDir)[0], CrossPlatform.LocateSingleplayerHome());
|
||||
Directory.Delete(tempDir, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,4 +23,9 @@
|
|||
<Setter Property="Background" Value="{StaticResource AccentBrush}" />
|
||||
<Setter Property="TextBlock.Foreground" Value="{StaticResource DarkForegroundBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Button.OutsideNavigator:disabled">
|
||||
<Setter Property="Background" Value="{StaticResource DarkMediumBackgroundBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource SemiDarkForegroundBrush}" />
|
||||
</Style>
|
||||
</Styles>
|
||||
|
|
@ -247,6 +247,7 @@ namespace Saradomin.Utilities
|
|||
return Path.Combine(LocateSingleplayerHome(), "launch.sh");
|
||||
}
|
||||
|
||||
// TODO - MacOS
|
||||
throw new InvalidOperationException("Unsupported OS for singleplayer: " +
|
||||
RuntimeInformation.OSArchitecture);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ public static class SingleplayerManagement
|
|||
private static readonly string[] DirsToBackup =
|
||||
{
|
||||
"game/data/players",
|
||||
"game/data/serverstore"
|
||||
"game/data/serverstore",
|
||||
"game/worldprops"
|
||||
};
|
||||
private static readonly string[] FilesToBackup =
|
||||
{
|
||||
|
|
@ -18,7 +19,7 @@ public static class SingleplayerManagement
|
|||
"game/data/eco/grandexchange.db"
|
||||
};
|
||||
|
||||
public static void MakeBackup()
|
||||
public static void MakeBackup(Action<string> log)
|
||||
{
|
||||
if (!Directory.Exists(CrossPlatform.LocateSingleplayerBackupsHome()))
|
||||
Directory.CreateDirectory(CrossPlatform.LocateSingleplayerBackupsHome());
|
||||
|
|
@ -33,6 +34,11 @@ public static class SingleplayerManagement
|
|||
foreach (string dir in DirsToBackup)
|
||||
{
|
||||
string sourcePath = Path.Combine(CrossPlatform.LocateSingleplayerHome(), dir);
|
||||
if (!Directory.Exists(sourcePath))
|
||||
{
|
||||
log($" Skipping backup of {dir} because it doesn't exist (Full path attempted: {sourcePath}");
|
||||
continue;
|
||||
}
|
||||
string destPath = Path.Combine(newBackupDir, dir);
|
||||
CopyDirectory(sourcePath, destPath);
|
||||
}
|
||||
|
|
@ -40,6 +46,11 @@ public static class SingleplayerManagement
|
|||
foreach (string file in FilesToBackup)
|
||||
{
|
||||
string sourceFilePath = Path.Combine(CrossPlatform.LocateSingleplayerHome(), file);
|
||||
if (!File.Exists(sourceFilePath))
|
||||
{
|
||||
log($" Skipping backup of {file} because it doesn't exist (Full path attempted: {sourceFilePath}");
|
||||
continue;
|
||||
}
|
||||
string destFilePath = Path.Combine(newBackupDir, file);
|
||||
string directoryForFile = Path.GetDirectoryName(destFilePath);
|
||||
if (!Directory.Exists(directoryForFile))
|
||||
|
|
@ -74,7 +85,7 @@ public static class SingleplayerManagement
|
|||
return directories.Select(Path.GetFileName).MaxBy(name => name);
|
||||
}
|
||||
|
||||
public static void ApplyLatestBackup()
|
||||
public static void ApplyLatestBackup(Action<string> log)
|
||||
{
|
||||
var backupHome = CrossPlatform.LocateSingleplayerBackupsHome();
|
||||
var singleplayerHome = CrossPlatform.LocateSingleplayerHome();
|
||||
|
|
@ -82,17 +93,15 @@ public static class SingleplayerManagement
|
|||
// Get all backup directories
|
||||
var backupDirectories = Directory.GetDirectories(backupHome);
|
||||
|
||||
// Find the most recent backup directory by parsing the directory names as dates
|
||||
string mostRecentBackupDirName = FindMostRecentBackupDirectory(backupDirectories);
|
||||
|
||||
if (mostRecentBackupDirName == null)
|
||||
{
|
||||
Console.WriteLine("No backups found.");
|
||||
log(" No backups found.");
|
||||
return;
|
||||
}
|
||||
|
||||
string mostRecentBackupFullPath = Path.Combine(backupHome, mostRecentBackupDirName);
|
||||
Console.WriteLine($"Most recent backup found: {mostRecentBackupFullPath}");
|
||||
|
||||
// Get the list of files in the most recent backup
|
||||
var filesInBackup = Directory.GetFiles(
|
||||
|
|
@ -119,6 +128,6 @@ public static class SingleplayerManagement
|
|||
File.Copy(file, destFilePath, true);
|
||||
}
|
||||
|
||||
Console.WriteLine("Backup has been successfully applied.");
|
||||
log($" Backup from {mostRecentBackupDirName} has been successfully applied.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,61 +32,61 @@
|
|||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="Singleplayer is provided by the 2009scape team" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,8"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="for advanced users only." />
|
||||
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="2009scape official servers have free membership," />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="multiple exp rates, and are hosted 24/7." />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="In addition, your player save file" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="is always exportable from the multiplayer server" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="if you ever choose" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="to switch to singleplayer - However," />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="we will not import your singleplayer save" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,8"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="file into the multiplayer world." />
|
||||
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="It is our strong recommendation" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="to play the multiplayer server instead." />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="If you have any questions," />
|
||||
<TextBlock
|
||||
Margin="0,0,4,8"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Foreground="Black"
|
||||
Text="feel free to ask on our Discord or Forums." />
|
||||
|
||||
</StackPanel>
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
<HeaderedContentControl Margin="2,2,0,0"
|
||||
Classes="GroupBox"
|
||||
DockPanel.Dock="Top"
|
||||
Header="singleplayer config">
|
||||
Header="singleplayer config (edit config manually for now)">
|
||||
<HeaderedContentControl.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
|
|
@ -225,27 +225,37 @@
|
|||
<StackPanel>
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Foreground="{StaticResource DarkForegroundBrush}"
|
||||
Text="Not configurable via launcher for now. Edit config file manually." />
|
||||
/>
|
||||
|
||||
<CheckBox Content="Place 'X' button on the left"
|
||||
<CheckBox Content="Cheats"
|
||||
IsEnabled="False"
|
||||
IsChecked="{Binding Launcher.PlaceCloseButtonOnLeft, Mode=TwoWay}" />
|
||||
/>
|
||||
|
||||
<CheckBox Content="Close the launcher after executing the client"
|
||||
<CheckBox Content="Fake Players"
|
||||
IsChecked="True"
|
||||
IsEnabled="False"
|
||||
IsChecked="{Binding Launcher.ExitAfterLaunchingClient, Mode=TwoWay}" />
|
||||
/>
|
||||
|
||||
<CheckBox Content="Check for client updates on launch"
|
||||
<CheckBox Content="GE Autostock"
|
||||
IsEnabled="False"
|
||||
IsChecked="{Binding Launcher.CheckForClientUpdatesOnLaunch, Mode=TwoWay}" />
|
||||
/>
|
||||
|
||||
<CheckBox Content="Check for updated server profiles on launch"
|
||||
<CheckBox Content="Debug"
|
||||
IsEnabled="False"
|
||||
IsChecked="{Binding Launcher.CheckForServerProfilesOnLaunch, Mode=TwoWay}" />
|
||||
/>
|
||||
|
||||
<CheckBox Content="Allow multiple client instances to run"
|
||||
IsEnabled="False"
|
||||
IsChecked="{Binding Launcher.AllowMultiboxing, Mode=TwoWay}" />
|
||||
<Button
|
||||
Margin="0,0,0,0"
|
||||
Width="140"
|
||||
Height="25"
|
||||
BorderBrush="{StaticResource DarkBorderBrush}"
|
||||
BorderThickness="1"
|
||||
Classes="OutsideNavigator"
|
||||
Opacity="1"
|
||||
FontSize="11"
|
||||
Content="Reset Config"
|
||||
IsEnabled="False"
|
||||
ZIndex="9999"/>
|
||||
</StackPanel>
|
||||
</HeaderedContentControl>
|
||||
</DockPanel>
|
||||
|
|
|
|||
|
|
@ -12,121 +12,123 @@ using Saradomin.Infrastructure.Services;
|
|||
using Saradomin.Model.Settings.Launcher;
|
||||
using Saradomin.Utilities;
|
||||
|
||||
namespace Saradomin.ViewModel.Controls
|
||||
namespace Saradomin.ViewModel.Controls;
|
||||
|
||||
public class SingleplayerViewModel : ViewModelBase
|
||||
{
|
||||
public class SingleplayerViewModel : ViewModelBase
|
||||
private readonly ISingleplayerUpdateService _singleplayerUpdateService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
|
||||
public string SingleplayerDownloadText { get; private set; } =
|
||||
Directory.Exists(CrossPlatform.LocateSingleplayerHome()) ? "Update Singleplayer" : "Download Singleplayer";
|
||||
|
||||
public bool CanDownload { get; private set; } = true;
|
||||
public bool CanLaunch { get; private set; } = File.Exists(CrossPlatform.LocateSingleplayerExecutable());
|
||||
public TextBox SingleplayerLogsTextBox { get; }
|
||||
public bool ShowLogPanel { get; private set; }
|
||||
public LauncherSettings Launcher => _settingsService.Launcher;
|
||||
|
||||
public SingleplayerViewModel(ISettingsService settingsService,
|
||||
ISingleplayerUpdateService iSingleplayerUpdateService)
|
||||
{
|
||||
private readonly ISingleplayerUpdateService _singleplayerUpdateService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
_settingsService = settingsService;
|
||||
Message.Subscribe<MainViewLoadedMessage>(this, OnMainViewLoaded); // todo test delete
|
||||
_singleplayerUpdateService = iSingleplayerUpdateService;
|
||||
_singleplayerUpdateService.SingleplayerDownloadProgressChanged += OnSingleplayerDownloadProgressChanged;
|
||||
|
||||
public string SingleplayerDownloadText { get; private set; } = "Download Singleplayer";
|
||||
public bool CanDownload { get; private set; } = true;
|
||||
public bool CanLaunch => File.Exists(CrossPlatform.LocateSingleplayerExecutable()) && !_isRunning;
|
||||
public TextBox SingleplayerLogsTextBox { get; private set; }
|
||||
public bool ShowLogPanel {get; private set; }
|
||||
public LauncherSettings Launcher => _settingsService.Launcher;
|
||||
SingleplayerLogsTextBox = new TextBox
|
||||
{
|
||||
Foreground = new SolidColorBrush(Colors.Black),
|
||||
FontSize = 12,
|
||||
Margin = new Thickness(8, 0, 0, 0),
|
||||
IsReadOnly = true,
|
||||
BorderThickness = new Thickness(0),
|
||||
Background = Brushes.Transparent,
|
||||
AcceptsReturn = true,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
};
|
||||
}
|
||||
|
||||
private bool _isRunning;
|
||||
public SingleplayerViewModel(ISettingsService settingsService, ISingleplayerUpdateService iSingleplayerUpdateService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
Message.Subscribe<MainViewLoadedMessage>(this, OnMainViewLoaded); // todo test delete
|
||||
_singleplayerUpdateService = iSingleplayerUpdateService;
|
||||
_singleplayerUpdateService.SingleplayerDownloadProgressChanged += OnSingleplayerDownloadProgressChanged;
|
||||
|
||||
SingleplayerLogsTextBox = new TextBox
|
||||
{
|
||||
Foreground = new SolidColorBrush(Colors.Black),
|
||||
FontSize = 12,
|
||||
Margin = new Thickness(8, 0, 0, 0),
|
||||
IsReadOnly = true,
|
||||
BorderThickness = new Thickness(0),
|
||||
Background = Brushes.Transparent,
|
||||
AcceptsReturn = true,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
};
|
||||
private void OnSingleplayerDownloadProgressChanged(object sender, Tuple<float, bool> e)
|
||||
{
|
||||
float progress = e.Item1;
|
||||
bool finished = e.Item2;
|
||||
if (finished)
|
||||
{
|
||||
SingleplayerDownloadText = "Update Singleplayer";
|
||||
PrintLog($"Singleplayer Download complete");
|
||||
SingleplayerManagement.ApplyLatestBackup(PrintLog);
|
||||
PrintLog($"");
|
||||
return;
|
||||
}
|
||||
|
||||
private void OnSingleplayerDownloadProgressChanged(object sender, Tuple<float, bool> e)
|
||||
if (progress >= 1f)
|
||||
{
|
||||
float progress = e.Item1;
|
||||
bool finished = e.Item2;
|
||||
CanDownload = finished;
|
||||
if (finished)
|
||||
{
|
||||
SingleplayerDownloadText = "Download Singleplayer";
|
||||
PrintLog($"Singleplayer Download/Update complete");
|
||||
SingleplayerManagement.ApplyLatestBackup();
|
||||
PrintLog($"Restored progress from last made backup");
|
||||
return;
|
||||
}
|
||||
|
||||
if (progress >= 1f)
|
||||
{
|
||||
SingleplayerDownloadText = "Extracting...";
|
||||
return;
|
||||
}
|
||||
SingleplayerDownloadText = $"Downloading... {progress * 100:F2}%";
|
||||
SingleplayerDownloadText = "Extracting...";
|
||||
return;
|
||||
}
|
||||
|
||||
private void OnMainViewLoaded(MainViewLoadedMessage _)
|
||||
{
|
||||
Message.Subscribe<SettingsModifiedMessage>(this, OnSettingsModified);
|
||||
}
|
||||
SingleplayerDownloadText = $"Downloading... {progress * 100:F2}%";
|
||||
}
|
||||
|
||||
private void OnSettingsModified(SettingsModifiedMessage _)
|
||||
{
|
||||
Console.WriteLine("Saving settings");
|
||||
_settingsService.SaveAll();
|
||||
}
|
||||
|
||||
public void DownloadSingleplayer()
|
||||
{
|
||||
MakeBackup();
|
||||
PrintLog($"Starting singleplayer download/update...");
|
||||
_singleplayerUpdateService.DownloadSingleplayer();
|
||||
}
|
||||
private void OnMainViewLoaded(MainViewLoadedMessage _)
|
||||
{
|
||||
Message.Subscribe<SettingsModifiedMessage>(this, OnSettingsModified);
|
||||
}
|
||||
|
||||
public void MakeBackup()
|
||||
{
|
||||
PrintLog("Starting backup of player saves and economy files..");
|
||||
SingleplayerManagement.MakeBackup();
|
||||
}
|
||||
private void OnSettingsModified(SettingsModifiedMessage _)
|
||||
{
|
||||
Console.WriteLine("Saving settings");
|
||||
_settingsService.SaveAll();
|
||||
}
|
||||
|
||||
public void OpenBackupFolder()
|
||||
{
|
||||
if (!Directory.Exists(CrossPlatform.LocateSingleplayerBackupsHome()))
|
||||
Directory.CreateDirectory(CrossPlatform.LocateSingleplayerBackupsHome());
|
||||
CrossPlatform.OpenFolder(CrossPlatform.LocateSingleplayerBackupsHome());
|
||||
}
|
||||
public void DownloadSingleplayer()
|
||||
{
|
||||
MakeBackup();
|
||||
PrintLog($"Starting singleplayer download...");
|
||||
_singleplayerUpdateService.DownloadSingleplayer();
|
||||
}
|
||||
|
||||
private void PrintLog(string message)
|
||||
{
|
||||
ShowLogPanel = true;
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
SingleplayerLogsTextBox.Text += message + Environment.NewLine;
|
||||
}, DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
public void LaunchSingleplayer()
|
||||
{
|
||||
_isRunning = true;
|
||||
new Task(() =>
|
||||
CrossPlatform.RunCommandAndGetOutput($"{CrossPlatform.LocateSingleplayerExecutable()} {Launcher.JavaExecutableLocation}",
|
||||
PrintLog,
|
||||
PrintLog)
|
||||
).Start();
|
||||
}
|
||||
private void MakeBackup()
|
||||
{
|
||||
PrintLog("Starting backup of player saves and economy files..");
|
||||
SingleplayerManagement.MakeBackup(PrintLog);
|
||||
PrintLog($"Done backing up player saves and economy files");
|
||||
PrintLog($"");
|
||||
}
|
||||
|
||||
private void LaunchFaq()
|
||||
{
|
||||
CrossPlatform.LaunchURL("https://2009scape.org/site/game_guide/singleplayer.html");
|
||||
}
|
||||
public void OpenBackupFolder()
|
||||
{
|
||||
if (!Directory.Exists(CrossPlatform.LocateSingleplayerBackupsHome()))
|
||||
Directory.CreateDirectory(CrossPlatform.LocateSingleplayerBackupsHome());
|
||||
CrossPlatform.OpenFolder(CrossPlatform.LocateSingleplayerBackupsHome());
|
||||
}
|
||||
|
||||
private void LaunchForums()
|
||||
{
|
||||
CrossPlatform.LaunchURL("https://forum.2009scape.org/viewforum.php?f=8-support");
|
||||
}
|
||||
private void PrintLog(string message)
|
||||
{
|
||||
ShowLogPanel = true;
|
||||
Dispatcher.UIThread.Post(() => { SingleplayerLogsTextBox.Text += message + Environment.NewLine; },
|
||||
DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
public void LaunchSingleplayer()
|
||||
{
|
||||
CanLaunch = false;
|
||||
new Task(() =>
|
||||
CrossPlatform.RunCommandAndGetOutput(
|
||||
$"{CrossPlatform.LocateSingleplayerExecutable()} {Launcher.JavaExecutableLocation}",
|
||||
PrintLog,
|
||||
PrintLog)
|
||||
).Start();
|
||||
}
|
||||
|
||||
private void LaunchFaq()
|
||||
{
|
||||
CrossPlatform.LaunchURL("https://2009scape.org/site/game_guide/singleplayer.html");
|
||||
}
|
||||
|
||||
private void LaunchForums()
|
||||
{
|
||||
CrossPlatform.LaunchURL("https://forum.2009scape.org/viewforum.php?f=8-support");
|
||||
}
|
||||
}
|
||||
|
|
@ -280,6 +280,7 @@ public class BackupManagerTests
|
|||
public void WithNoDirectories_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
// ReSharper disable once CollectionNeverUpdated.Local
|
||||
var directories = new List<string>();
|
||||
|
||||
// Act
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue