using Cryville.Common.Network; using Cryville.Common.Unity; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using UnityEngine; using Logger = Cryville.Common.Logging.Logger; using ThreadPriority = System.Threading.ThreadPriority; namespace Cryville.Crtr.Network { public class UpdateChecker : MonoBehaviour { string _currentVersion; void Start() { _currentVersion = Application.version; new Thread(CheckVersion) { IsBackground = true, Priority = ThreadPriority.BelowNormal }.Start(); } static readonly Uri BaseUri = new Uri("https://www.cryville.world/api/crtr/index"); List _versions; public void CheckVersion() { try { var client = new HttpsClient(BaseUri); client.Connect(); var response = client.Request("GET", new Uri(BaseUri, "versions")); var data = Encoding.UTF8.GetString(response.MessageBody.ReadToEnd()); _versions = JsonConvert.DeserializeObject>(data, Game.GlobalJsonSerializerSettings); } catch (Exception ex) { Logger.Log("main", 4, "Network", "An error occurred while checking for update: {0}", ex); Dialog.Show(null, "Failed to check for update."); return; } var availableVersions = _versions.Where(v => v.platforms.ContainsKey(PlatformConfig.Name)).ToArray(); var versionIndex = new Dictionary(availableVersions.Length); for (int i = 0; i < availableVersions.Length; i++) versionIndex.Add(availableVersions[i].name, i); var currentVersion = availableVersions.Where(v => v.name == _currentVersion).SingleOrDefault(); var latestVersion = availableVersions.Last(); if (currentVersion == null) { Dialog.Show(null, string.Format("You are playing an unknown version of Cosmo Resona: {0}\nThe latest version is: {1}", _currentVersion, latestVersion.name)); return; } if (latestVersion.name != _currentVersion) { var latestResources = latestVersion.platforms[PlatformConfig.Name].resources; VersionResourceInfo fullPackage = null; if (latestResources != null) { fullPackage = (from r in latestResources where r.upstream == null select r).SingleOrDefault(); } if (fullPackage == null) { Dialog.Show(null, string.Format("A new version is present: {0}\nUpdate is not available.", latestVersion.name)); return; } long totalDiffSize = 0; int searchIndex = versionIndex[latestVersion.name], targetIndex = versionIndex[currentVersion.name]; while (searchIndex != targetIndex) { var searchVersion = availableVersions[searchIndex]; VersionResourceInfo matchedUpstream = null; var resources = searchVersion.platforms[PlatformConfig.Name].resources; if (resources == null) { totalDiffSize = 0; break; } foreach (var r in resources) { if (r.upstream == null) continue; var upstreamIndex = versionIndex[r.upstream]; if (upstreamIndex >= targetIndex && upstreamIndex < searchIndex) { matchedUpstream = r; searchIndex = upstreamIndex; } } if (matchedUpstream != null) { if (matchedUpstream.external) { totalDiffSize = 0; Dialog.ShowAndWait("An error occurred while checking for update.\nPlease report this to the developers."); Logger.Log("main", 4, "Network", "Diff package is external, which is not expected"); break; } totalDiffSize += matchedUpstream.size; if (totalDiffSize >= fullPackage.size) { totalDiffSize = 0; break; } } else { totalDiffSize = 0; break; } } if (totalDiffSize == 0 || totalDiffSize >= fullPackage.size) { // TODO Check if external if (Dialog.ShowAndWait(string.Format("A new version is available: {0}\nYou have to download the full package.\nOpen the download link now?", latestVersion.name), "Yes", "No") == 0) { UrlOpener.Open(fullPackage.url); } } else { Dialog.ShowAndWait(string.Format("A new version is available: {0}\nDo you want to update?", latestVersion.name), "Yes", "No"); } } Logger.Log("main", 0, "Network", "Update checker exited"); } class VersionInfo { [JsonRequired] public string name; public string type; public Dictionary platforms; } class PlatformVersionInfo { public List resources; } class VersionResourceInfo { public bool external; public string upstream; [JsonRequired] public string url; [JsonRequired] public long size; } } }