This commit is contained in:
dginovker 2023-11-05 20:58:32 +09:00
parent babd1d3058
commit 6745b5f35a
7 changed files with 163 additions and 139 deletions

View file

@ -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);

View file

@ -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>

View file

@ -247,6 +247,7 @@ namespace Saradomin.Utilities
return Path.Combine(LocateSingleplayerHome(), "launch.sh");
}
// TODO - MacOS
throw new InvalidOperationException("Unsupported OS for singleplayer: " +
RuntimeInformation.OSArchitecture);
}

View file

@ -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.");
}
}

View file

@ -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>

View file

@ -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");
}
}

View file

@ -280,6 +280,7 @@ public class BackupManagerTests
public void WithNoDirectories_ReturnsNull()
{
// Arrange
// ReSharper disable once CollectionNeverUpdated.Local
var directories = new List<string>();
// Act