@@ -122,12 +122,6 @@ namespace SeamlessClientPlugin
|
|||||||
|
|
||||||
public void Init(object gameInstance)
|
public void Init(object gameInstance)
|
||||||
{
|
{
|
||||||
Utilities.UpdateChecker Checker = new Utilities.UpdateChecker(false);
|
|
||||||
Task UpdateChecker = new Task(() => Checker.PingUpdateServer());
|
|
||||||
UpdateChecker.Start();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Patches.GetPatches();
|
Patches.GetPatches();
|
||||||
TryShow("Running Seamless Client Plugin v[" + Version + "]");
|
TryShow("Running Seamless Client Plugin v[" + Version + "]");
|
||||||
PingTimer.Elapsed += PingTimer_Elapsed;
|
PingTimer.Elapsed += PingTimer_Elapsed;
|
||||||
@@ -145,6 +139,9 @@ namespace SeamlessClientPlugin
|
|||||||
TryShow("Initilizing Communications!");
|
TryShow("Initilizing Communications!");
|
||||||
RunInitilizations();
|
RunInitilizations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//OnNewPlayerRequest
|
//OnNewPlayerRequest
|
||||||
//throw new NotImplementedException();
|
//throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@@ -158,6 +155,8 @@ namespace SeamlessClientPlugin
|
|||||||
// Terrible way to make sure server knows we are running seamless client
|
// Terrible way to make sure server knows we are running seamless client
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
ClientMessage PingServer = new ClientMessage(ClientMessageType.FirstJoin);
|
ClientMessage PingServer = new ClientMessage(ClientMessageType.FirstJoin);
|
||||||
MyAPIGateway.Multiplayer?.SendMessageToServer(SeamlessClientNetID, Utilities.Utility.Serialize(PingServer));
|
MyAPIGateway.Multiplayer?.SendMessageToServer(SeamlessClientNetID, Utilities.Utility.Serialize(PingServer));
|
||||||
}
|
}
|
||||||
|
@@ -167,7 +167,6 @@
|
|||||||
<Compile Include="Messages\Transfer.cs" />
|
<Compile Include="Messages\Transfer.cs" />
|
||||||
<Compile Include="Utilities\Patches.cs" />
|
<Compile Include="Utilities\Patches.cs" />
|
||||||
<Compile Include="SeamlessTransfer\SwitchServers.cs" />
|
<Compile Include="SeamlessTransfer\SwitchServers.cs" />
|
||||||
<Compile Include="Utilities\UpdateChecker.cs" />
|
|
||||||
<Compile Include="Utilities\Utility.cs" />
|
<Compile Include="Utilities\Utility.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -6,6 +6,7 @@ using Sandbox.Game.Entities;
|
|||||||
using Sandbox.Game.Gui;
|
using Sandbox.Game.Gui;
|
||||||
using Sandbox.Game.GUI;
|
using Sandbox.Game.GUI;
|
||||||
using Sandbox.Game.Multiplayer;
|
using Sandbox.Game.Multiplayer;
|
||||||
|
using Sandbox.Game.SessionComponents;
|
||||||
using Sandbox.Game.World;
|
using Sandbox.Game.World;
|
||||||
using Sandbox.Game.World.Generator;
|
using Sandbox.Game.World.Generator;
|
||||||
using Sandbox.ModAPI;
|
using Sandbox.ModAPI;
|
||||||
@@ -34,6 +35,8 @@ namespace SeamlessClientPlugin.SeamlessTransfer
|
|||||||
public MyGameServerItem TargetServer { get; }
|
public MyGameServerItem TargetServer { get; }
|
||||||
public MyObjectBuilder_World TargetWorld { get; }
|
public MyObjectBuilder_World TargetWorld { get; }
|
||||||
|
|
||||||
|
private string OldArmorSkin { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
public SwitchServers(MyGameServerItem TargetServer, MyObjectBuilder_World TargetWorld)
|
public SwitchServers(MyGameServerItem TargetServer, MyObjectBuilder_World TargetWorld)
|
||||||
{
|
{
|
||||||
@@ -44,6 +47,8 @@ namespace SeamlessClientPlugin.SeamlessTransfer
|
|||||||
|
|
||||||
public void BeginSwitch()
|
public void BeginSwitch()
|
||||||
{
|
{
|
||||||
|
OldArmorSkin = MySession.Static.LocalHumanPlayer.BuildArmorSkin;
|
||||||
|
|
||||||
MySandboxGame.Static.Invoke(delegate
|
MySandboxGame.Static.Invoke(delegate
|
||||||
{
|
{
|
||||||
//Set camera controller to fixed spectator
|
//Set camera controller to fixed spectator
|
||||||
@@ -74,6 +79,8 @@ namespace SeamlessClientPlugin.SeamlessTransfer
|
|||||||
MyMultiplayer.Static = Utility.CastToReflected(instance, Patches.ClientType);
|
MyMultiplayer.Static = Utility.CastToReflected(instance, Patches.ClientType);
|
||||||
MyMultiplayer.Static.ExperimentalMode = true;
|
MyMultiplayer.Static.ExperimentalMode = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Set the new SyncLayer to the MySession.Static.SyncLayer
|
// Set the new SyncLayer to the MySession.Static.SyncLayer
|
||||||
Patches.MySessionLayer.SetValue(MySession.Static, MyMultiplayer.Static.SyncLayer);
|
Patches.MySessionLayer.SetValue(MySession.Static, MyMultiplayer.Static.SyncLayer);
|
||||||
|
|
||||||
@@ -122,6 +129,10 @@ namespace SeamlessClientPlugin.SeamlessTransfer
|
|||||||
MyModAPIHelper.Initialize();
|
MyModAPIHelper.Initialize();
|
||||||
// Allow the game to start proccessing incoming messages in the buffer
|
// Allow the game to start proccessing incoming messages in the buffer
|
||||||
MyMultiplayer.Static.StartProcessingClientMessages();
|
MyMultiplayer.Static.StartProcessingClientMessages();
|
||||||
|
|
||||||
|
//Recreate all controls... Will fix weird gui/paint/crap
|
||||||
|
MyGuiScreenHudSpace.Static.RecreateControls(true);
|
||||||
|
//MySession.Static.LocalHumanPlayer.BuildArmorSkin = OldArmorSkin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -277,7 +288,7 @@ namespace SeamlessClientPlugin.SeamlessTransfer
|
|||||||
|
|
||||||
private void LoadConnectedClients()
|
private void LoadConnectedClients()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
Patches.LoadMembersFromWorld.Invoke(MySession.Static, new object[] { TargetWorld, MyMultiplayer.Static });
|
Patches.LoadMembersFromWorld.Invoke(MySession.Static, new object[] { TargetWorld, MyMultiplayer.Static });
|
||||||
|
|
||||||
@@ -320,10 +331,6 @@ namespace SeamlessClientPlugin.SeamlessTransfer
|
|||||||
|
|
||||||
SeamlessClient.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count);
|
SeamlessClient.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count);
|
||||||
SeamlessClient.TryShow("Loading Complete!");
|
SeamlessClient.TryShow("Loading Complete!");
|
||||||
|
|
||||||
|
|
||||||
//Recreate all controls... Will fix weird gui/paint/crap
|
|
||||||
MyGuiScreenHudSpace.Static.RecreateControls(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MyMultiplayer_PendingReplicablesDone()
|
private void MyMultiplayer_PendingReplicablesDone()
|
||||||
@@ -378,6 +385,9 @@ namespace SeamlessClientPlugin.SeamlessTransfer
|
|||||||
if (MyMultiplayer.Static == null)
|
if (MyMultiplayer.Static == null)
|
||||||
throw new Exception("MyMultiplayer.Static is null on unloading? dafuq?");
|
throw new Exception("MyMultiplayer.Static is null on unloading? dafuq?");
|
||||||
|
|
||||||
|
//Try and close the quest log
|
||||||
|
MySessionComponentIngameHelp component = MySession.Static.GetComponent<MySessionComponentIngameHelp>();
|
||||||
|
component?.TryCancelObjective();
|
||||||
|
|
||||||
//Clear all old players and clients.
|
//Clear all old players and clients.
|
||||||
Sync.Clients.Clear();
|
Sync.Clients.Clear();
|
||||||
|
@@ -1,341 +0,0 @@
|
|||||||
using ProtoBuf;
|
|
||||||
using Sandbox.Graphics.GUI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
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 const 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RestartClientAfterUpdate()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SeamlessClient.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];
|
|
||||||
}
|
|
||||||
|
|
||||||
SeamlessClient.TryShow(NewCommandLine);
|
|
||||||
Process.Start(exe, NewCommandLine);
|
|
||||||
currentProcess.Kill();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
SeamlessClient.TryShow("Restarting Client error!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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!");
|
|
||||||
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; }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user