Added auto-update capability to launcher

This commit is contained in:
Ace73 2025-02-18 16:32:03 -08:00
parent bc882af2e5
commit 09f57041e0
26 changed files with 400 additions and 10 deletions

View file

@ -0,0 +1,9 @@
<Application x:Class="Bobocraft_2_Launcher_Update_Assistant.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Bobocraft_2_Launcher_Update_Assistant"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace Bobocraft_2_Launcher_Update_Assistant
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View file

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View file

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Bobocraft_2_Launcher_Update_Assistant</RootNamespace>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Compile Remove="images\**" />
<EmbeddedResource Remove="images\**" />
<None Remove="images\**" />
<Page Remove="images\**" />
</ItemGroup>
<ItemGroup>
<None Remove="bobocraft 2 logo vector.png" />
<None Remove="LauncherBackground.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="bobocraft 2 logo vector.png" />
<Resource Include="LauncherBackground.png" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,18 @@
<Window x:Class="Bobocraft_2_Launcher_Update_Assistant.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Bobocraft_2_Launcher_Update_Assistant"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
ContentRendered="Window_ContentRendered"
Title="Bobocraft 2 Launcher" Height="576" Width="1080" ResizeMode="NoResize">
<Grid>
<Image Source="/LauncherBackground.png" Stretch="UniformToFill"/>
<TextBlock Name="VersionText" VerticalAlignment="Bottom" HorizontalAlignment="Right" FontSize="20" Foreground="White" Margin="0, 0, 5, 0"/>
<TextBlock Name="LauncherVersionText" VerticalAlignment="Bottom" HorizontalAlignment="Left" FontSize="20" Foreground="White" Margin="0, 0, 5, 0"/>
<Image Margin="792,503,10,0" Source="/bobocraft 2 logo vector.png" Stretch="Fill"/>
<Button Name="PlayButton" Content="Updating Launcher" Click="PlayButton_Click" Height="60" FontSize="28" FontWeight="Bold" Foreground="#DDFFFFFF" Margin="0, 0, 0, 15" VerticalAlignment="Bottom" HorizontalAlignment="Center" MinWidth="150" Background="#FFFF9700" Padding="10,1,10,1"/>
</Grid>
</Window>

View file

@ -0,0 +1,224 @@
using Bobocraft_2_Launcher_Update_Assistant;
using System;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace Bobocraft_2_Launcher_Update_Assistant
{
enum LauncherStatus
{
ready,
failed,
downloadingGame,
downloadingUpdate,
awaitingInput
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string rootPath;
private string versionFile;
private string launcherVersionFile;
private string tempZip;
private string modZip;
private string launcherExe;
private string launcherPath;
private string configFile;
private bool isNewInstall;
private string chosenUserName;
private LauncherStatus _status;
internal LauncherStatus Status
{
get => _status;
set
{
_status = value;
switch (_status)
{
case LauncherStatus.ready:
PlayButton.Content = "Play Bobocraft 2";
break;
case LauncherStatus.failed:
PlayButton.Content = "Install/Update Failed - Retry";
break;
case LauncherStatus.downloadingGame:
PlayButton.Content = "Installing Mod";
break;
case LauncherStatus.downloadingUpdate:
PlayButton.Content = "Updating";
break;
case LauncherStatus.awaitingInput:
PlayButton.Content = "Done";
break;
default:
break;
}
}
}
public MainWindow()
{
InitializeComponent();
launcherPath = Directory.GetCurrentDirectory();
rootPath = launcherPath;
launcherExe = Path.Combine(rootPath, "Bobocraft 2 Launcher.exe");
versionFile = Path.Combine(rootPath, "version.txt");
launcherVersionFile = Path.Combine(rootPath, "launcherversion.txt");
tempZip = Path.Combine(rootPath, "temp");
}
private void CheckForLauncherUpdates()
{
if (File.Exists(launcherVersionFile))
{
Version localLauncherVersion = new Version(File.ReadAllText(launcherVersionFile));
LauncherVersionText.Text = localLauncherVersion.ToString();
try
{
WebClient webClient = new WebClient();
Version onlineLauncherVersion = new Version(webClient.DownloadString("https://drive.google.com/uc?export=download&id=16YSzW2p-mWDyS4249HdsNivMHvPU6uOu"));
if (onlineLauncherVersion.IsDifferentThan(localLauncherVersion))
{
UpdateLauncher(onlineLauncherVersion);
}
else
{
ProcessStartInfo process = new ProcessStartInfo(@launcherExe);
Process.Start(process);
this.Close();
}
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error checking for launcher updates: {ex}");
}
}
else
{
UpdateLauncher(Version.zero);
}
}
private void UpdateLauncher(Version _onlinelauncherVersion)
{
try
{
WebClient webClient = new WebClient();
Status = LauncherStatus.downloadingUpdate;
_onlinelauncherVersion = new Version(webClient.DownloadString("https://drive.google.com/uc?export=download&id=16YSzW2p-mWDyS4249HdsNivMHvPU6uOu"));
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadLauncherCompletedCallback);
webClient.DownloadFileAsync(new Uri("https://cloud.norbipeti.eu/s/YWYN2mQL4p7ptWn/download/asd.zip"), tempZip, _onlinelauncherVersion);
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error downloading launcher update: {ex}");
}
}
private void DownloadLauncherCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
try
{
string onlineLauncherVersion = ((Version)e.UserState).ToString();
ZipFile.ExtractToDirectory(tempZip, rootPath, true);
ProcessStartInfo process = new ProcessStartInfo(@launcherExe);
File.WriteAllText(launcherVersionFile, onlineLauncherVersion);
File.Delete(tempZip);
Process.Start(process);
this.Close();
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error updating launcher: {ex}");
}
}
private void PlayButton_Click(object sender, RoutedEventArgs e)
{
}
private void Window_ContentRendered(object sender, EventArgs e)
{
CheckForLauncherUpdates();
}
}
struct Version
{
internal static Version zero = new Version(0, 0, 0);
private short major;
private short minor;
private short subMinor;
internal Version(short _major, short _minor, short _subMinor)
{
major = _major;
minor = _minor;
subMinor = _subMinor;
}
internal Version(string _version)
{
string[] versionStrings = _version.Split('.');
if (versionStrings.Length != 3)
{
major = 0;
minor = 0;
subMinor = 0;
return;
}
major = short.Parse(versionStrings[0]);
minor = short.Parse(versionStrings[1]);
subMinor = short.Parse(versionStrings[2]);
}
internal bool IsDifferentThan(Version _otherVersion)
{
if (major != _otherVersion.major)
{
return true;
}
else
{
if (minor != _otherVersion.minor)
{
return true;
}
else
{
if (subMinor != _otherVersion.subMinor)
{
return true;
}
}
}
return false;
}
public override string ToString()
{
return $"{major}.{minor}.{subMinor}";
}
}
}

View file

@ -5,6 +5,8 @@ VisualStudioVersion = 17.11.35222.181
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bobocraft 2 Launcher", "GameLauncher\Bobocraft 2 Launcher.csproj", "{7FA3FB14-7943-4E38-820E-77E2BA28283E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bobocraft 2 Launcher Update Assistant", "Bobocraft 2 Launcher Update Assistant\Bobocraft 2 Launcher Update Assistant.csproj", "{6B20984F-DCE0-4198-B77C-CCFD55DA208B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,6 +17,10 @@ Global
{7FA3FB14-7943-4E38-820E-77E2BA28283E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FA3FB14-7943-4E38-820E-77E2BA28283E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FA3FB14-7943-4E38-820E-77E2BA28283E}.Release|Any CPU.Build.0 = Release|Any CPU
{6B20984F-DCE0-4198-B77C-CCFD55DA208B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B20984F-DCE0-4198-B77C-CCFD55DA208B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B20984F-DCE0-4198-B77C-CCFD55DA208B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B20984F-DCE0-4198-B77C-CCFD55DA208B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -11,6 +11,7 @@
<Grid>
<Image Stretch="UniformToFill" Source="images/LauncherBackground.png"/>
<TextBlock Name="VersionText" VerticalAlignment="Bottom" HorizontalAlignment="Right" FontSize="20" Foreground="White" Margin="0, 0, 5, 0"/>
<TextBlock Name="LauncherVersionText" VerticalAlignment="Bottom" HorizontalAlignment="Left" FontSize="20" Foreground="White" Margin="0, 0, 5, 0"/>
<Button Name="PlayButton" Content="Checking For Updates" Click="PlayButton_Click" Height="60" FontSize="28" FontWeight="Bold" Foreground="#DDFFFFFF" Margin="0, 0, 0, 15" VerticalAlignment="Bottom" HorizontalAlignment="Center" MinWidth="150" Background="#FFFF9700" Padding="10,1,10,1"/>
<TextBox x:Name ="mainWindowBox" Margin="300,200,300,256" FontSize="36" FontFamily="Bahnschrift SemiBold" Text="Enter Username" TextAlignment="Center" Background="White" VerticalAlignment="Center" Visibility="Hidden"/>
<Image Margin="792,503,10,0" Source="/bobocraft 2 logo vector.png"/>

View file

@ -29,13 +29,16 @@ namespace GameLauncher
{
private string rootPath;
private string versionFile;
private string launcherVersionFile;
private string tempZip;
private string modZip;
private string gameExe;
private string launcherAssistantExe;
private string launcherPath;
private string configFile;
private bool isNewInstall;
private string chosenUserName;
private string assistantPath;
private LauncherStatus _status;
internal LauncherStatus Status
@ -71,6 +74,7 @@ namespace GameLauncher
{
InitializeComponent();
launcherPath = Directory.GetCurrentDirectory();
assistantPath = launcherPath;
gameExe = Path.Combine(launcherPath, "Robocraft 2.exe");
if (File.Exists(gameExe))
{
@ -85,13 +89,87 @@ namespace GameLauncher
MessageBox.Show("Unable to find Robocraft 2 installation. Please make sure this file is placed inside the main /Robocraft 2 folder.");
}
}
launcherAssistantExe = Path.Combine(assistantPath, "Bobocraft 2 Launcher Update Assistant.exe");
versionFile = Path.Combine(rootPath, "version.txt");
launcherVersionFile = Path.Combine(assistantPath, "launcherversion.txt");
tempZip = Path.Combine(rootPath, "temp");
modZip = Path.Combine(rootPath, "BepInEx", "plugins");
configFile = Path.Combine(rootPath, "BepInEx", "config", "RC2MPWE.cfg");
}
private void CheckForLauncherUpdates()
{
if (File.Exists(launcherVersionFile))
{
Version localLauncherVersion = new Version(File.ReadAllText(launcherVersionFile));
LauncherVersionText.Text = localLauncherVersion.ToString();
try
{
WebClient webClient = new WebClient();
Version onlineLauncherVersion = new Version(webClient.DownloadString("https://drive.google.com/uc?export=download&id=16YSzW2p-mWDyS4249HdsNivMHvPU6uOu"));
if (onlineLauncherVersion.IsDifferentThan(localLauncherVersion))
{
UpdateLauncherAssistant(onlineLauncherVersion);
}
else
{
if (File.Exists(launcherAssistantExe))
{
File.Delete(launcherAssistantExe);
}
CheckForUpdates();
}
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error checking for launcher updates: {ex}");
}
}
else
{
UpdateLauncherAssistant(Version.zero);
}
}
private void UpdateLauncherAssistant(Version _onlinelauncherVersion)
{
try
{
WebClient webClient = new WebClient();
Status = LauncherStatus.downloadingUpdate;
_onlinelauncherVersion = new Version(webClient.DownloadString("https://drive.google.com/uc?export=download&id=16YSzW2p-mWDyS4249HdsNivMHvPU6uOu"));
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadLauncherAssistantCompletedCallback);
webClient.DownloadFileAsync(new Uri("https://cloud.norbipeti.eu/s/ZwRmsKb3gLNKKNH/download/assist.zip"), tempZip, _onlinelauncherVersion);
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error downloading launcher update: {ex}");
}
}
private void DownloadLauncherAssistantCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
try
{
string onlineLauncherVersion = ((Version)e.UserState).ToString();
ZipFile.ExtractToDirectory(tempZip, assistantPath, true);
ProcessStartInfo process = new ProcessStartInfo(@launcherAssistantExe);
File.Delete(tempZip);
Process.Start(process);
this.Close();
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error updating launcher assistant: {ex}");
}
}
private void CheckForUpdates()
{
if (File.Exists(versionFile))
@ -106,7 +184,7 @@ namespace GameLauncher
if (onlineVersion.IsDifferentThan(localVersion))
{
InstallGameFiles(true, onlineVersion);
InstallModFiles(true, onlineVersion);
}
else
{
@ -121,11 +199,11 @@ namespace GameLauncher
}
else
{
InstallGameFiles(false, Version.zero);
InstallModFiles(false, Version.zero);
}
}
private void InstallGameFiles(bool _isUpdate, Version _onlineVersion)
private void InstallModFiles(bool _isUpdate, Version _onlineVersion)
{
try
{
@ -134,7 +212,7 @@ namespace GameLauncher
{
isNewInstall = false;
Status = LauncherStatus.downloadingUpdate;
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadGameCompletedCallback);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadModCompletedCallback);
webClient.DownloadFileAsync(new Uri("https://cloud.norbipeti.eu/s/yyk3LBaZsXa4GpR/download/RC2MPWE.zip"), tempZip, _onlineVersion);
}
else
@ -142,18 +220,18 @@ namespace GameLauncher
isNewInstall = true;
Status = LauncherStatus.downloadingGame;
_onlineVersion = new Version(webClient.DownloadString("https://cloud.norbipeti.eu/s/j6TFGJbbS5z9Dp4/download/version.txt"));
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadGameCompletedCallback);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadModCompletedCallback);
webClient.DownloadFileAsync(new Uri("https://cloud.norbipeti.eu/s/kZSSjFc2jqa22Hw/download/sus.zip"), tempZip, _onlineVersion);
}
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error installing mod files: {ex}");
MessageBox.Show($"Error downloading mod files: {ex}");
}
}
private void DownloadGameCompletedCallback(object sender, AsyncCompletedEventArgs e)
private void DownloadModCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
try
{
@ -179,13 +257,13 @@ namespace GameLauncher
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error finishing download: {ex}");
MessageBox.Show($"Error installing/updating mod: {ex}");
}
}
private void Window_ContentRendered(object sender, EventArgs e)
{
CheckForUpdates();
CheckForLauncherUpdates();
}
private void PlayButton_Click(object sender, RoutedEventArgs e)

Binary file not shown.

After

(image error) Size: 33 KiB

Binary file not shown.

After

(image error) Size: 1.6 MiB