mirror of
https://github.com/OxyZin/LegacyConsoleLauncher.git
synced 2026-07-16 03:00:47 +00:00
add automatic game installer and updater
- download and install LCEWindows64.zip automatically - update Minecraft.Client.exe from nightly releases - detect installed version using commit hash - add progress window for downloads - store version in releaseinfo.txt
This commit is contained in:
14
Form1.Designer.cs
generated
14
Form1.Designer.cs
generated
@@ -36,6 +36,7 @@
|
|||||||
this.openFolderButton = new System.Windows.Forms.Button();
|
this.openFolderButton = new System.Windows.Forms.Button();
|
||||||
this.resetLink = new System.Windows.Forms.LinkLabel();
|
this.resetLink = new System.Windows.Forms.LinkLabel();
|
||||||
this.playtimeLabel = new System.Windows.Forms.Label();
|
this.playtimeLabel = new System.Windows.Forms.Label();
|
||||||
|
this.checkforLink = new System.Windows.Forms.LinkLabel();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
@@ -147,11 +148,23 @@
|
|||||||
this.playtimeLabel.TabIndex = 11;
|
this.playtimeLabel.TabIndex = 11;
|
||||||
this.playtimeLabel.Text = "Playtime: 0h 0m";
|
this.playtimeLabel.Text = "Playtime: 0h 0m";
|
||||||
//
|
//
|
||||||
|
// checkforLink
|
||||||
|
//
|
||||||
|
this.checkforLink.AutoSize = true;
|
||||||
|
this.checkforLink.Location = new System.Drawing.Point(143, 280);
|
||||||
|
this.checkforLink.Name = "checkforLink";
|
||||||
|
this.checkforLink.Size = new System.Drawing.Size(94, 13);
|
||||||
|
this.checkforLink.TabIndex = 12;
|
||||||
|
this.checkforLink.TabStop = true;
|
||||||
|
this.checkforLink.Text = "Check for updates";
|
||||||
|
this.checkforLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.checkforLink_LinkClicked);
|
||||||
|
//
|
||||||
// Form1
|
// Form1
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(364, 302);
|
this.ClientSize = new System.Drawing.Size(364, 302);
|
||||||
|
this.Controls.Add(this.checkforLink);
|
||||||
this.Controls.Add(this.resetLink);
|
this.Controls.Add(this.resetLink);
|
||||||
this.Controls.Add(this.openFolderButton);
|
this.Controls.Add(this.openFolderButton);
|
||||||
this.Controls.Add(this.gamePathTextBox);
|
this.Controls.Add(this.gamePathTextBox);
|
||||||
@@ -187,5 +200,6 @@
|
|||||||
private System.Windows.Forms.Button openFolderButton;
|
private System.Windows.Forms.Button openFolderButton;
|
||||||
private System.Windows.Forms.LinkLabel resetLink;
|
private System.Windows.Forms.LinkLabel resetLink;
|
||||||
private System.Windows.Forms.Label playtimeLabel;
|
private System.Windows.Forms.Label playtimeLabel;
|
||||||
|
private System.Windows.Forms.LinkLabel checkforLink;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
402
Form1.cs
402
Form1.cs
@@ -2,26 +2,38 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace LegacyConsoleLauncher
|
namespace LegacyConsoleLauncher
|
||||||
{
|
{
|
||||||
public partial class Form1 : Form
|
public partial class Form1 : Form
|
||||||
{
|
{
|
||||||
private string accountsFile = Path.Combine(Application.StartupPath, "accounts.txt");
|
private readonly string accountsFile = Path.Combine(Application.StartupPath, "accounts.txt");
|
||||||
private string gamePathFile = Path.Combine(Application.StartupPath, "gamepath.txt");
|
private readonly string gamePathFile = Path.Combine(Application.StartupPath, "gamepath.txt");
|
||||||
|
private readonly string releaseInfoFile = Path.Combine(Application.StartupPath, "releaseinfo.txt");
|
||||||
|
private readonly string gameInstallDir = Path.Combine(Application.StartupPath, "Game");
|
||||||
|
|
||||||
private string exePath = Path.Combine(Application.StartupPath, "Minecraft.Client.exe");
|
private string exePath = Path.Combine(Application.StartupPath, "Minecraft.Client.exe");
|
||||||
|
|
||||||
private Dictionary<string, int> playtimeData = new Dictionary<string, int>();
|
private readonly string nightlyReleaseUrl = "https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly";
|
||||||
|
private readonly string nightlyZipUrl = "https://github.com/smartcmd/MinecraftConsoles/releases/download/nightly/LCEWindows64.zip";
|
||||||
|
private readonly string nightlyExeUrl = "https://github.com/smartcmd/MinecraftConsoles/releases/download/nightly/Minecraft.Client.exe";
|
||||||
|
|
||||||
|
private readonly Dictionary<string, int> playtimeData = new Dictionary<string, int>();
|
||||||
private DateTime sessionStart;
|
private DateTime sessionStart;
|
||||||
private Process gameProcess;
|
private Process gameProcess;
|
||||||
|
private Form2 progressForm;
|
||||||
|
|
||||||
public Form1()
|
public Form1()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Form1_Load(object sender, EventArgs e)
|
private async void Form1_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
openFolderButton.Text = "Open Folder";
|
openFolderButton.Text = "Open Folder";
|
||||||
launchButton.Text = "Launch Game";
|
launchButton.Text = "Launch Game";
|
||||||
@@ -32,28 +44,36 @@ namespace LegacyConsoleLauncher
|
|||||||
gamePathLabel.Text = "Game path:";
|
gamePathLabel.Text = "Game path:";
|
||||||
|
|
||||||
gamePathTextBox.ReadOnly = true;
|
gamePathTextBox.ReadOnly = true;
|
||||||
this.AcceptButton = launchButton;
|
AcceptButton = launchButton;
|
||||||
|
checkforLink.Visible = false;
|
||||||
|
|
||||||
LoadAccounts();
|
LoadAccounts();
|
||||||
|
LoadSavedGamePath();
|
||||||
if (File.Exists(gamePathFile))
|
|
||||||
{
|
|
||||||
string savedPath = File.ReadAllText(gamePathFile).Trim();
|
|
||||||
|
|
||||||
if (File.Exists(savedPath))
|
|
||||||
{
|
|
||||||
exePath = savedPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoDetectGame();
|
AutoDetectGame();
|
||||||
UpdateGamePathDisplay();
|
UpdateGamePathDisplay();
|
||||||
LoadFullscreenSetting();
|
LoadFullscreenSetting();
|
||||||
UpdatePlaytimeLabel();
|
UpdatePlaytimeLabel();
|
||||||
|
|
||||||
this.AllowDrop = true;
|
AllowDrop = true;
|
||||||
this.DragEnter += Form1_DragEnter;
|
DragEnter += Form1_DragEnter;
|
||||||
this.DragDrop += Form1_DragDrop;
|
DragDrop += Form1_DragDrop;
|
||||||
|
|
||||||
|
await CheckForUpdatesOnStartupAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadSavedGamePath()
|
||||||
|
{
|
||||||
|
if (!File.Exists(gamePathFile))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string savedPath = File.ReadAllText(gamePathFile).Trim();
|
||||||
|
|
||||||
|
if (File.Exists(savedPath))
|
||||||
|
{
|
||||||
|
exePath = savedPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadAccounts()
|
private void LoadAccounts()
|
||||||
@@ -144,7 +164,8 @@ namespace LegacyConsoleLauncher
|
|||||||
Path.Combine(Application.StartupPath, "Minecraft.Client.exe"),
|
Path.Combine(Application.StartupPath, "Minecraft.Client.exe"),
|
||||||
Path.Combine(Application.StartupPath, "build", "Minecraft.Client.exe"),
|
Path.Combine(Application.StartupPath, "build", "Minecraft.Client.exe"),
|
||||||
Path.Combine(Application.StartupPath, "bin", "Minecraft.Client.exe"),
|
Path.Combine(Application.StartupPath, "bin", "Minecraft.Client.exe"),
|
||||||
Path.Combine(Application.StartupPath, "game", "Minecraft.Client.exe")
|
Path.Combine(Application.StartupPath, "game", "Minecraft.Client.exe"),
|
||||||
|
Path.Combine(gameInstallDir, "Minecraft.Client.exe")
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (string path in possiblePaths)
|
foreach (string path in possiblePaths)
|
||||||
@@ -170,7 +191,6 @@ namespace LegacyConsoleLauncher
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool gameFound = File.Exists(exePath);
|
bool gameFound = File.Exists(exePath);
|
||||||
|
|
||||||
openFolderButton.Enabled = gameFound;
|
openFolderButton.Enabled = gameFound;
|
||||||
launchButton.Enabled = gameFound;
|
launchButton.Enabled = gameFound;
|
||||||
}
|
}
|
||||||
@@ -186,7 +206,7 @@ namespace LegacyConsoleLauncher
|
|||||||
private string FormatPlaytime(int totalSeconds)
|
private string FormatPlaytime(int totalSeconds)
|
||||||
{
|
{
|
||||||
TimeSpan time = TimeSpan.FromSeconds(totalSeconds);
|
TimeSpan time = TimeSpan.FromSeconds(totalSeconds);
|
||||||
return ((int)time.TotalHours).ToString() + "h " + time.Minutes.ToString() + "m";
|
return ((int)time.TotalHours) + "h " + time.Minutes + "m";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePlaytimeLabel()
|
private void UpdatePlaytimeLabel()
|
||||||
@@ -273,6 +293,290 @@ namespace LegacyConsoleLauncher
|
|||||||
File.WriteAllLines(optionsPath, lines);
|
File.WriteAllLines(optionsPath, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string FindGameExe(string rootFolder)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(rootFolder))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] files = Directory.GetFiles(rootFolder, "Minecraft.Client.exe", SearchOption.AllDirectories);
|
||||||
|
return files.Length > 0 ? files[0] : string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> DownloadStringWithUserAgentAsync(string url)
|
||||||
|
{
|
||||||
|
using (WebClient client = new WebClient())
|
||||||
|
{
|
||||||
|
client.Headers.Add("User-Agent", "LegacyConsoleLauncher");
|
||||||
|
return await client.DownloadStringTaskAsync(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownloadFileWithProgressAsync(string url, string outputPath, string statusText)
|
||||||
|
{
|
||||||
|
ShowProgressForm(statusText);
|
||||||
|
|
||||||
|
using (WebClient client = new WebClient())
|
||||||
|
{
|
||||||
|
client.Headers.Add("User-Agent", "LegacyConsoleLauncher");
|
||||||
|
|
||||||
|
client.DownloadProgressChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (progressForm != null && !progressForm.IsDisposed)
|
||||||
|
{
|
||||||
|
progressForm.SetStatus(statusText + " " + e.ProgressPercentage + "%");
|
||||||
|
progressForm.SetProgress(e.ProgressPercentage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await client.DownloadFileTaskAsync(new Uri(url), outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progressForm != null && !progressForm.IsDisposed)
|
||||||
|
{
|
||||||
|
progressForm.SetProgress(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowProgressForm(string status)
|
||||||
|
{
|
||||||
|
if (progressForm == null || progressForm.IsDisposed)
|
||||||
|
{
|
||||||
|
progressForm = new Form2();
|
||||||
|
}
|
||||||
|
|
||||||
|
progressForm.Show();
|
||||||
|
progressForm.BringToFront();
|
||||||
|
progressForm.SetStatus(status);
|
||||||
|
progressForm.SetProgress(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseProgressForm()
|
||||||
|
{
|
||||||
|
if (progressForm != null && !progressForm.IsDisposed)
|
||||||
|
{
|
||||||
|
progressForm.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetNightlyCommitAsync()
|
||||||
|
{
|
||||||
|
string html = await DownloadStringWithUserAgentAsync(nightlyReleaseUrl);
|
||||||
|
|
||||||
|
Match match = Regex.Match(
|
||||||
|
html,
|
||||||
|
@"\b[0-9a-f]{7,40}\b",
|
||||||
|
RegexOptions.IgnoreCase
|
||||||
|
);
|
||||||
|
|
||||||
|
return match.Success ? match.Value : string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetInstalledCommit()
|
||||||
|
{
|
||||||
|
if (!File.Exists(releaseInfoFile))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string line in File.ReadAllLines(releaseInfoFile))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("commit="))
|
||||||
|
{
|
||||||
|
return line.Substring("commit=".Length).Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveInstalledCommit(string commit)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(commit))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(releaseInfoFile, "commit=" + commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InstallGameAsync()
|
||||||
|
{
|
||||||
|
string zipPath = Path.Combine(Application.StartupPath, "LCEWindows64.zip");
|
||||||
|
string tempExtractDir = Path.Combine(Application.StartupPath, "Game_Temp");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await DownloadFileWithProgressAsync(nightlyZipUrl, zipPath, "Installing...");
|
||||||
|
ShowProgressForm("Extracting...");
|
||||||
|
|
||||||
|
if (Directory.Exists(tempExtractDir))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempExtractDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(tempExtractDir);
|
||||||
|
ZipFile.ExtractToDirectory(zipPath, tempExtractDir);
|
||||||
|
|
||||||
|
if (File.Exists(zipPath))
|
||||||
|
{
|
||||||
|
File.Delete(zipPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Directory.Exists(gameInstallDir))
|
||||||
|
{
|
||||||
|
Directory.Delete(gameInstallDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.Move(tempExtractDir, gameInstallDir);
|
||||||
|
|
||||||
|
string detectedExe = FindGameExe(gameInstallDir);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(detectedExe) || !File.Exists(detectedExe))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Minecraft.Client.exe could not be found after installation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SetGamePath(detectedExe);
|
||||||
|
|
||||||
|
string latestCommit = await GetNightlyCommitAsync();
|
||||||
|
SaveInstalledCommit(latestCommit);
|
||||||
|
|
||||||
|
CloseProgressForm();
|
||||||
|
|
||||||
|
MessageBox.Show(
|
||||||
|
"Game installed successfully.",
|
||||||
|
"Install Complete",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Information
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
CloseProgressForm();
|
||||||
|
|
||||||
|
if (Directory.Exists(tempExtractDir))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempExtractDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(zipPath))
|
||||||
|
{
|
||||||
|
File.Delete(zipPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateGameExeAsync()
|
||||||
|
{
|
||||||
|
if (!File.Exists(exePath))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Game executable was not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string tempExePath = Path.Combine(Application.StartupPath, "Minecraft.Client.new.exe");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await DownloadFileWithProgressAsync(nightlyExeUrl, tempExePath, "Updating...");
|
||||||
|
File.Copy(tempExePath, exePath, true);
|
||||||
|
|
||||||
|
if (File.Exists(tempExePath))
|
||||||
|
{
|
||||||
|
File.Delete(tempExePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string latestCommit = await GetNightlyCommitAsync();
|
||||||
|
SaveInstalledCommit(latestCommit);
|
||||||
|
|
||||||
|
CloseProgressForm();
|
||||||
|
|
||||||
|
MessageBox.Show(
|
||||||
|
"Game updated successfully.",
|
||||||
|
"Update Complete",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Information
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
CloseProgressForm();
|
||||||
|
|
||||||
|
if (File.Exists(tempExePath))
|
||||||
|
{
|
||||||
|
File.Delete(tempExePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckForUpdatesOnStartupAsync()
|
||||||
|
{
|
||||||
|
checkforLink.Visible = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string latestCommit = await GetNightlyCommitAsync();
|
||||||
|
string installedCommit = GetInstalledCommit();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(latestCommit))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(exePath))
|
||||||
|
{
|
||||||
|
DialogResult installResult = MessageBox.Show(
|
||||||
|
"Game not installed.\n\nDo you want to download and install it now?",
|
||||||
|
"Install Game",
|
||||||
|
MessageBoxButtons.YesNo,
|
||||||
|
MessageBoxIcon.Question
|
||||||
|
);
|
||||||
|
|
||||||
|
if (installResult == DialogResult.Yes)
|
||||||
|
{
|
||||||
|
await InstallGameAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
checkforLink.Visible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(latestCommit, installedCommit, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
checkforLink.Visible = true;
|
||||||
|
|
||||||
|
DialogResult updateResult = MessageBox.Show(
|
||||||
|
"A new nightly build is available.\n\nDo you want to update now?",
|
||||||
|
"Update Available",
|
||||||
|
MessageBoxButtons.YesNo,
|
||||||
|
MessageBoxIcon.Information
|
||||||
|
);
|
||||||
|
|
||||||
|
if (updateResult == DialogResult.Yes)
|
||||||
|
{
|
||||||
|
await UpdateGameExeAsync();
|
||||||
|
checkforLink.Visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
checkforLink.Visible = true;
|
||||||
|
|
||||||
|
MessageBox.Show(
|
||||||
|
"Failed to check for updates.\n\n" + ex.Message,
|
||||||
|
"Update Check Error",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Warning
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void openFolderButton_Click(object sender, EventArgs e)
|
private void openFolderButton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (!File.Exists(exePath))
|
if (!File.Exists(exePath))
|
||||||
@@ -309,7 +613,7 @@ namespace LegacyConsoleLauncher
|
|||||||
File.WriteAllText(gamePathFile, exePath);
|
File.WriteAllText(gamePathFile, exePath);
|
||||||
SaveFullscreenSetting();
|
SaveFullscreenSetting();
|
||||||
|
|
||||||
string args = "";
|
string args = string.Empty;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(username))
|
if (!string.IsNullOrWhiteSpace(username))
|
||||||
{
|
{
|
||||||
@@ -336,18 +640,17 @@ namespace LegacyConsoleLauncher
|
|||||||
}
|
}
|
||||||
|
|
||||||
sessionStart = DateTime.Now;
|
sessionStart = DateTime.Now;
|
||||||
|
|
||||||
gameProcess.EnableRaisingEvents = true;
|
gameProcess.EnableRaisingEvents = true;
|
||||||
gameProcess.Exited += GameProcess_Exited;
|
gameProcess.Exited += GameProcess_Exited;
|
||||||
|
|
||||||
this.Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GameProcess_Exited(object sender, EventArgs e)
|
private void GameProcess_Exited(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
int sessionSeconds = (int)(DateTime.Now - sessionStart).TotalSeconds;
|
int sessionSeconds = (int)(DateTime.Now - sessionStart).TotalSeconds;
|
||||||
|
|
||||||
this.Invoke((MethodInvoker)delegate
|
Invoke((MethodInvoker)delegate
|
||||||
{
|
{
|
||||||
string username = usernameComboBox.Text.Trim();
|
string username = usernameComboBox.Text.Trim();
|
||||||
|
|
||||||
@@ -519,8 +822,13 @@ namespace LegacyConsoleLauncher
|
|||||||
File.Delete(gamePathFile);
|
File.Delete(gamePathFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (File.Exists(releaseInfoFile))
|
||||||
|
{
|
||||||
|
File.Delete(releaseInfoFile);
|
||||||
|
}
|
||||||
|
|
||||||
usernameComboBox.Items.Clear();
|
usernameComboBox.Items.Clear();
|
||||||
usernameComboBox.Text = "";
|
usernameComboBox.Text = string.Empty;
|
||||||
playtimeData.Clear();
|
playtimeData.Clear();
|
||||||
|
|
||||||
exePath = Path.Combine(Application.StartupPath, "Minecraft.Client.exe");
|
exePath = Path.Combine(Application.StartupPath, "Minecraft.Client.exe");
|
||||||
@@ -558,5 +866,45 @@ namespace LegacyConsoleLauncher
|
|||||||
private void gamePathLabel_Click(object sender, EventArgs e)
|
private void gamePathLabel_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void checkforLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string latestCommit = await GetNightlyCommitAsync();
|
||||||
|
string installedCommit = GetInstalledCommit();
|
||||||
|
|
||||||
|
if (!File.Exists(exePath))
|
||||||
|
{
|
||||||
|
await InstallGameAsync();
|
||||||
|
checkforLink.Visible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(latestCommit, installedCommit, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
await UpdateGameExeAsync();
|
||||||
|
checkforLink.Visible = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
"You are already using the latest nightly build.",
|
||||||
|
"No Updates",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Information
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
"Failed to check for updates.\n\n" + ex.Message,
|
||||||
|
"Error",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Warning
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
70
Form2.Designer.cs
generated
Normal file
70
Form2.Designer.cs
generated
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
namespace LegacyConsoleLauncher
|
||||||
|
{
|
||||||
|
partial class Form2
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.progressBar1 = new System.Windows.Forms.ProgressBar();
|
||||||
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// progressBar1
|
||||||
|
//
|
||||||
|
this.progressBar1.Location = new System.Drawing.Point(12, 41);
|
||||||
|
this.progressBar1.Name = "progressBar1";
|
||||||
|
this.progressBar1.Size = new System.Drawing.Size(527, 23);
|
||||||
|
this.progressBar1.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
this.label1.AutoSize = true;
|
||||||
|
this.label1.Location = new System.Drawing.Point(12, 13);
|
||||||
|
this.label1.Name = "label1";
|
||||||
|
this.label1.Size = new System.Drawing.Size(48, 13);
|
||||||
|
this.label1.TabIndex = 1;
|
||||||
|
this.label1.Text = "Installing";
|
||||||
|
//
|
||||||
|
// Form2
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(551, 76);
|
||||||
|
this.Controls.Add(this.label1);
|
||||||
|
this.Controls.Add(this.progressBar1);
|
||||||
|
this.Name = "Form2";
|
||||||
|
this.Text = "Installing...";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ProgressBar progressBar1;
|
||||||
|
private System.Windows.Forms.Label label1;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
Form2.cs
Normal file
28
Form2.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace LegacyConsoleLauncher
|
||||||
|
{
|
||||||
|
public partial class Form2 : Form
|
||||||
|
{
|
||||||
|
public Form2()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetStatus(string text)
|
||||||
|
{
|
||||||
|
label1.Text = text;
|
||||||
|
label1.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetProgress(int value)
|
||||||
|
{
|
||||||
|
if (value < 0) value = 0;
|
||||||
|
if (value > 100) value = 100;
|
||||||
|
|
||||||
|
progressBar1.Value = value;
|
||||||
|
progressBar1.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Form2.resx
Normal file
120
Form2.resx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
@@ -40,6 +40,8 @@
|
|||||||
<HintPath>..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.dll</HintPath>
|
<HintPath>..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.IO.Compression" />
|
||||||
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
@@ -57,11 +59,20 @@
|
|||||||
<Compile Include="Form1.Designer.cs">
|
<Compile Include="Form1.Designer.cs">
|
||||||
<DependentUpon>Form1.cs</DependentUpon>
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Form2.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Form2.Designer.cs">
|
||||||
|
<DependentUpon>Form2.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<EmbeddedResource Include="Form1.resx">
|
<EmbeddedResource Include="Form1.resx">
|
||||||
<DependentUpon>Form1.cs</DependentUpon>
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Form2.resx">
|
||||||
|
<DependentUpon>Form2.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
|||||||
Reference in New Issue
Block a user