diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..3af8e6e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,28 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/SeamlessClient.cs b/SeamlessClient.cs
index 569df3b..c650e20 100644
--- a/SeamlessClient.cs
+++ b/SeamlessClient.cs
@@ -122,6 +122,12 @@ namespace SeamlessClientPlugin
public void Init(object gameInstance)
{
+ Utilities.UpdateChecker Checker = new Utilities.UpdateChecker(false);
+ Task UpdateChecker = new Task(() => Checker.PingUpdateServer());
+ UpdateChecker.Start();
+
+
+
Patches.GetPatches();
TryShow("Running Seamless Client Plugin v[" + Version + "]");
PingTimer.Elapsed += PingTimer_Elapsed;
@@ -208,6 +214,31 @@ namespace SeamlessClientPlugin
}
+ public static void RestartClientAfterUpdate()
+ {
+ try
+ {
+ TryShow("Restarting Client!");
+ string exe = Assembly.GetEntryAssembly().Location;
+ Process currentProcess = Process.GetCurrentProcess();
+
+ string[] CommandArgs = Environment.GetCommandLineArgs();
+ string NewCommandLine = "";
+ for (int i = 1; i < CommandArgs.Length; i++)
+ {
+ NewCommandLine += " " + CommandArgs[i];
+ }
+
+ TryShow(NewCommandLine);
+ Process.Start(exe, NewCommandLine);
+ currentProcess.Kill();
+ }
+ catch (Exception ex)
+ {
+ TryShow("Restarting Client error!");
+ }
+ }
+
public static void TryShow(string message)
{
if (MySession.Static?.LocalHumanPlayer != null && Debug)
diff --git a/SeamlessClientPlugin.csproj b/SeamlessClientPlugin.csproj
index 0f70936..1a3d93f 100644
--- a/SeamlessClientPlugin.csproj
+++ b/SeamlessClientPlugin.csproj
@@ -166,6 +166,7 @@
+
diff --git a/SeamlessTransfer/SwitchServers.cs b/SeamlessTransfer/SwitchServers.cs
index e7e40ca..7c96e3e 100644
--- a/SeamlessTransfer/SwitchServers.cs
+++ b/SeamlessTransfer/SwitchServers.cs
@@ -194,7 +194,6 @@ namespace SeamlessClientPlugin.SeamlessTransfer
MySession.Static.InGameTime = MyObjectBuilder_Checkpoint.DEFAULT_DATE;
MySession.Static.ElapsedGameTime = new TimeSpan(TargetWorld.Checkpoint.ElapsedGameTime);
MySession.Static.Settings.EnableSpectator = false;
-
MySession.Static.Password = TargetWorld.Checkpoint.Password;
MySession.Static.PreviousEnvironmentHostility = TargetWorld.Checkpoint.PreviousEnvironmentHostility;
@@ -333,7 +332,7 @@ namespace SeamlessClientPlugin.SeamlessTransfer
//Clear all old players and clients.
Sync.Clients.Clear();
Sync.Players.ClearPlayers();
-
+
MyHud.Chat.UnregisterChat(MyMultiplayer.Static);
MySession.Static.Gpss.RemovePlayerGpss(MySession.Static.LocalPlayerId);
diff --git a/Utilities/UpdateChecker.cs b/Utilities/UpdateChecker.cs
new file mode 100644
index 0000000..7cdc29f
--- /dev/null
+++ b/Utilities/UpdateChecker.cs
@@ -0,0 +1,315 @@
+using ProtoBuf;
+using Sandbox.Graphics.GUI;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Json;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml.Serialization;
+namespace SeamlessClientPlugin.Utilities
+{
+ public class UpdateChecker
+ {
+ public string PluginFolder;
+ public string CurrentVersion;
+ public bool DownloadUpdate;
+ private string GitHubAPILink = "https://api.github.com/repos/Casimir255/SeamlessClientPlugin/releases/latest";
+
+ private WebClient Client;
+
+
+
+
+ public UpdateChecker(bool AutoUpdate)
+ {
+ PluginFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ Client = new WebClient();
+ DeleteOLDFiles();
+ }
+
+
+
+
+ public void PingUpdateServer()
+ {
+ try
+ {
+ //Create new webclient and insert a user-agent
+ Client.Headers["User-Agent"] = "SeamlessClientUpdater";
+
+ //Grap API data for latest seamless client release
+ string data = Client.DownloadString(GitHubAPILink);
+
+ //SeamlessClient.TryShow(data);
+
+
+ DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(GithubRelease));
+
+ GithubRelease Release;
+ using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
+ {
+ Release = (GithubRelease)s.ReadObject(stream);
+ }
+
+
+ if (Release == null || !TryGetMainRelease(Release.Content, out GitZipFile MainReleaseFile))
+ return;
+
+
+ //Check if the client needs an update based off of github latest release version
+
+ if (!NeedsUpdate(SeamlessClient.Version, Release.LatestVersion))
+ return;
+
+
+ //Ask client if they want to update!
+ ShowDialog(Release, MainReleaseFile);
+ }
+ catch (Exception Ex)
+ {
+ SeamlessClient.TryShow(Ex.ToString());
+ }
+ }
+
+
+ private bool TryGetMainRelease(GitZipFile[] Files, out GitZipFile Release)
+ {
+ Release = null;
+
+ //Sanity saftey checks
+ if (Files == null || Files.Length <= 0)
+ return false;
+
+ foreach (GitZipFile File in Files)
+ {
+ if (File.Name == "SeamlessClientPlugin.zip")
+ {
+ Release = File;
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+
+ private void ShowDialog(GithubRelease Release, GitZipFile MainReleaseFile)
+ {
+ StringBuilder Response = new StringBuilder();
+ Response.AppendLine($"Current version: {SeamlessClient.Version} Latest: {Release.LatestVersion}");
+ Response.AppendLine($"Update: {Release.Name}");
+ Response.AppendLine($"Description: {Release.Description}");
+ Response.AppendLine($"Size: {MainReleaseFile.Size / 1000}kb");
+ Response.AppendLine();
+ Response.AppendLine("Warning: If you have a version less than latest seamless will be disabled to prevent crashes!");
+ Response.AppendLine("(Clicking yes should restart your game)");
+
+ DialogResult Result = MessageBox.Show(Response.ToString(), $"Download Seamless Client Plugin Update v{ Release.LatestVersion}?", MessageBoxButtons.YesNo, MessageBoxIcon.None, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
+ SeamlessClient.TryShow(Response.ToString());
+
+ if (Result == DialogResult.Yes)
+ {
+ SeamlessClient.TryShow("Client wants to update!");
+ string DownloadPath = Path.Combine(PluginFolder, MainReleaseFile.Name);
+ Client.DownloadFile(new Uri(MainReleaseFile.ZipURL), DownloadPath);
+
+ if (!File.Exists(DownloadPath))
+ {
+ SeamlessClient.TryShow("Failed to download zip!");
+ return;
+ }
+
+ if (ExtractAndReplace(DownloadPath))
+ {
+ StringBuilder ErrorResponse = new StringBuilder();
+ ErrorResponse.AppendLine("There was an error during the extraction proccess! Check your logs for more information!");
+ ErrorResponse.AppendLine();
+ ErrorResponse.AppendLine("You can download manually here:");
+ ErrorResponse.AppendLine(Release.GitHubPage);
+ SeamlessClient.TryShow(ErrorResponse.ToString());
+ MessageBox.Show(ErrorResponse.ToString(), $"Failed to update plugin to v{ Release.LatestVersion}!", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
+ return;
+ }
+
+ }
+ else
+ {
+ SeamlessClient.TryShow("Client skipped Update!");
+ return;
+ }
+
+
+
+
+ }
+
+
+
+
+
+ private void DeleteOLDFiles()
+ {
+ foreach (var OLDFile in Directory.GetFiles(PluginFolder, "*.old"))
+ {
+ File.Delete(OLDFile);
+ }
+
+ SeamlessClient.TryShow("Deleted all OLD update files");
+
+ }
+
+
+ private bool ExtractAndReplace(string ZipPath)
+ {
+ try
+ {
+
+ //Start extractor
+ using (ZipArchive archive = ZipFile.OpenRead(ZipPath))
+ {
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ {
+ string ExsistingFilePath = Path.Combine(PluginFolder, entry.Name);
+ string OldFilePath = Path.Combine(PluginFolder, entry.Name + ".old");
+
+ //No need to extract to files that dont exsist
+ if (!File.Exists(ExsistingFilePath))
+ continue;
+
+ SeamlessClient.TryShow(ExsistingFilePath + "=>" + OldFilePath);
+
+ if (File.Exists(OldFilePath))
+ File.Delete(OldFilePath);
+
+ File.Move(ExsistingFilePath, OldFilePath);
+ entry.ExtractToFile(ExsistingFilePath, false);
+ //File.Delete(OldFilePath);
+ }
+ }
+
+ //Delete latest zip
+ File.Delete(ZipPath);
+
+ //Restart client
+ SeamlessClient.TryShow("UpdateComplete!");
+ SeamlessClient.RestartClientAfterUpdate();
+ return true;
+
+ }
+ catch (Exception ex)
+ {
+ SeamlessClient.TryShow(ex.ToString());
+ return false;
+ }
+ }
+
+ private bool NeedsUpdate(string ClientVersion, string ServerVersion)
+ {
+
+
+ Version Client = new Version(ClientVersion);
+ Version Latest = new Version(ServerVersion);
+
+ var result = Client.CompareTo(Latest);
+ if (result > 0)
+ {
+ //Console.WriteLine("Client is greater");
+ SeamlessClient.TryShow("Client version is greater than latest! Wow!");
+ return false;
+ }
+ else if (result < 0)
+ {
+ //Console.WriteLine("Latest is greater");
+ SeamlessClient.TryShow("Client version is out-of-date!");
+ return true;
+ }
+ else
+ {
+ //Console.WriteLine("versions are equal");
+ SeamlessClient.TryShow("Client is up-to-date!");
+ return false;
+ }
+ }
+
+ }
+
+
+ [ProtoContract]
+ public class UpdateMessage
+ {
+ [ProtoMember(10)]
+ public string ClientVersion = "";
+
+ [ProtoMember(20)]
+ public bool UpToDate = false;
+
+ [ProtoMember(30)]
+ public bool DownloadNewUpdate = false;
+
+ [ProtoMember(40)]
+ public string ServerVersion = "";
+
+ [ProtoMember(50)]
+ public string UpdateNotes = "";
+
+
+
+ /* Misc Stuff incase I need it */
+ [ProtoMember(60)]
+ public byte[] XmlCharactersAsBytes;
+
+
+ public UpdateMessage() { }
+
+
+ }
+
+
+ [DataContract]
+ public class GithubRelease
+ {
+
+ [DataMember(Name = "url")]
+ public string GitHubPage { get; set; }
+
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+
+
+ [DataMember(Name = "tag_name")]
+ public string LatestVersion { get; set; }
+
+ [DataMember(Name = "prerelease")]
+ public bool Beta { get; set; }
+
+ [DataMember(Name = "body")]
+ public string Description { get; set; }
+
+ [DataMember(Name = "assets")]
+ public GitZipFile[] Content { get; set; }
+
+ }
+
+ [DataContract]
+ public class GitZipFile
+ {
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+
+ [DataMember(Name = "browser_download_url")]
+ public string ZipURL { get; set; }
+
+ [DataMember(Name = "size")]
+ public int Size { get; set; }
+
+ }
+}