diff --git a/TranslationUpdater.cs b/TranslationUpdater.cs index 32a1d23..5d76e92 100644 --- a/TranslationUpdater.cs +++ b/TranslationUpdater.cs @@ -1,7 +1,5 @@ using BepInEx; -using HarmonyLib; -using System.Reflection; -using UnityEngine; +using System; namespace TranslationUpdater { @@ -10,11 +8,12 @@ namespace TranslationUpdater { public const string pluginGuid = "katboi01.TranslationUpdater"; public const string pluginName = "KF3 Translation Updater"; - public const string pluginVersion = "1.0.0"; + public const string pluginVersion = "1.1.0"; public void Awake() { - new GameObject(pluginName).AddComponent(); + Console.WriteLine("Loading Updater"); + UpdateHandler.Create(); } } } diff --git a/TranslationUpdater.csproj b/TranslationUpdater.csproj index da6018d..efae0c3 100644 --- a/TranslationUpdater.csproj +++ b/TranslationUpdater.csproj @@ -50,9 +50,15 @@ + + ..\Libs\Unity.TextMeshPro.dll + ..\Libs\UnityEngine.dll + + ..\Libs\UnityEngine.AssetBundleModule.dll + ..\Libs\UnityEngine.CoreModule.dll @@ -65,6 +71,10 @@ ..\Libs\UnityEngine.TextRenderingModule.dll + + False + ..\Libs\UnityEngine.UI.dll + ..\Libs\UnityEngine.UIModule.dll @@ -77,5 +87,8 @@ + + + \ No newline at end of file diff --git a/UpdateHandler.asset b/UpdateHandler.asset new file mode 100644 index 0000000..7d8f44d Binary files /dev/null and b/UpdateHandler.asset differ diff --git a/UpdateHandler.cs b/UpdateHandler.cs index c28bb62..f0d4bd4 100644 --- a/UpdateHandler.cs +++ b/UpdateHandler.cs @@ -1,64 +1,115 @@ -using System.Collections; -using System.Collections.Generic; -using System.IO.Compression; +using System.IO.Compression; using System.IO; -using UnityEngine; +using System; using UnityEngine.Networking; +using UnityEngine.UI; +using UnityEngine; +using System.Collections; +using System.Reflection; public class UpdateHandler : MonoBehaviour { - private string _message = ""; private string _serverVersion = ""; private float _messageTime = 0; - private bool _updating = false; - private bool _updateSuccess = false; - private const string translationVersion = "lastVersion"; - private const string repositoryUrl = "https://git.japari.cafe/api/v1/repos/Vorked/VorkedTranslationPack"; + private bool _readyForDeletion = false; + + private const string PluginVersion = "1.1.0"; + private const string defaultRepositoryUrl = "https://git.japari.cafe/api/v1/repos/Vorked/VorkedTranslationPack"; + + //playerprefs keys + private const string translationVersionKey = "lastVersion"; + private const string repositoryUrlKey = "customRepositoryUrl"; + private const string customRepositoryKey = "customRepository"; + + public static void Create() + { +#if UNITY_EDITOR + var prefab = AssetBundle.LoadFromFile(@"R:\Unity\KF3Modder2\Assets\AssetBundles\UpdateHandler"); +#else + var prefab = AssetBundle.LoadFromMemory(LoadResource("UpdateHandler.asset")); +#endif + Instantiate(prefab.LoadAsset("UpdateHandler")); + prefab.Unload(false); + } + + public static byte[] LoadResource(string fileName) + { + Assembly asm = Assembly.GetExecutingAssembly(); + fileName = asm.GetName().Name + "." + fileName; + + var bytes = new byte[0]; + using (Stream resFilestream = asm.GetManifestResourceStream(fileName)) + { + if (resFilestream == null) return null; + byte[] byteArray = new byte[resFilestream.Length]; + resFilestream.Read(byteArray, 0, byteArray.Length); + bytes = byteArray; + } + Console.WriteLine(bytes.Length); + + return bytes; + } public IEnumerator Start() { - string currentVersion = PlayerPrefs.GetString(translationVersion, "0"); + yield return 0; + transform.SetAsLastSibling(); + PanelUpdateChecker.SetActive(true); + + string repositoryUrl = PlayerPrefs.GetInt(customRepositoryKey, 0) == 0 ? defaultRepositoryUrl : PlayerPrefs.GetString(repositoryUrlKey, defaultRepositoryUrl); + string currentVersion = PlayerPrefs.GetString(translationVersionKey, "undefined"); string newVersion = currentVersion; + string downloadError = ""; + bool updateSuccess = false; yield return DownloadText(repositoryUrl, (json) => { - var newData = JsonUtility.FromJson(json); - newVersion = newData.updated_at; + try + { + if (string.IsNullOrEmpty(json)) + { + throw new System.Exception("No response from " + repositoryUrl); + } + var newData = JsonUtility.FromJson(json); + newVersion = newData.updated_at; + updateSuccess = true; + } + catch (System.Exception e) + { + downloadError = e.Message; + updateSuccess = false; + } } ); + if (!updateSuccess) + { + PanelUpdateChecker.SetActive(false); + yield return SetAwaitableMessage("Failed to check for update!\nError: " + downloadError, 5); + OpenSettings(); + _readyForDeletion = true; + yield break; + } + Debug.Log("local version: " + currentVersion); Debug.Log("server version: " + newVersion); if (newVersion != currentVersion) { + OpenUpdateAvailable(); _serverVersion = newVersion; + PanelUpdateChecker.SetActive(false); } else { - Destroy(this.gameObject); - } - } - - public void OnGUI() - { - if (_updating || _messageTime > 0) - { - var style = GUI.skin.GetStyle("Label"); - style.normal.textColor = Color.black; - style.normal.background = Texture2D.whiteTexture; - style.alignment = TextAnchor.MiddleCenter; - GUI.Label(new Rect(Screen.width / 2 - 10, Screen.height / 2 - 25, 200, 100), _message, style); - } - else - { - var style = GUI.skin.GetStyle("Button"); - style.alignment = TextAnchor.UpperCenter; - if (GUI.Button(new Rect(Screen.width / 2 - 100, 0, 200, 50), "Translation Update Available", style)) + float time = 0; + while (time < 3 || PanelSettings.activeInHierarchy) { - StartCoroutine(UpdateTranslation()); + time += Time.deltaTime; + yield return 0; } + Destroy(this.gameObject); } } @@ -67,8 +118,13 @@ public class UpdateHandler : MonoBehaviour if (_messageTime > 0) { _messageTime -= Time.deltaTime; + + if (_messageTime <= 0) + { + PanelMessage.SetActive(false); + } } - else if (_updateSuccess) + else if (_readyForDeletion && !PanelSettings.activeInHierarchy) { Destroy(this.gameObject); } @@ -76,56 +132,192 @@ public class UpdateHandler : MonoBehaviour public IEnumerator UpdateTranslation() { - _updating = true; + PanelUpdateProgress.SetActive(true); + SlUpdateProgress.value = 0; byte[] bytes = null; + string repositoryUrl = PlayerPrefs.GetInt(customRepositoryKey, 0) == 0 ? defaultRepositoryUrl : PlayerPrefs.GetString(repositoryUrlKey, defaultRepositoryUrl); yield return DownloadBytes(repositoryUrl + "/archive/master.zip", (newBytes) => { bytes = newBytes; }, - (progress) => - { - SetMessage($"Downloading {progress * 100}%"); - } + SetUpdateProgress ); if (bytes.Length <= 0) { - SetMessage("Error. Download failed"); - _updateSuccess = false; + PanelUpdateProgress.SetActive(false); + yield return SetAwaitableMessage("Failed to download the update!\nCheck your settings.", 5); + OpenSettings(); + _readyForDeletion = true; yield break; } - using (var compressedFileStream = new MemoryStream(bytes)) + try { - using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Read, false)) + using (var compressedFileStream = new MemoryStream(bytes)) { - foreach (var file in zipArchive.Entries) + using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Read, false)) { - if (file.Name != "") + foreach (var file in zipArchive.Entries) { - //remove repo name from file path - var outFilePath = file.FullName.Split(new[] { '/' }, 2)[1]; - Directory.CreateDirectory(Path.GetDirectoryName(outFilePath)); - file.ExtractToFile(outFilePath, true); + if (file.Name != "") + { + //remove repo name from file path + var outFilePath = file.FullName.Split(new[] { '/' }, 2)[1]; + Directory.CreateDirectory(Path.GetDirectoryName(outFilePath)); + file.ExtractToFile(outFilePath, true); + } } } } } + catch (System.Exception e) + { + SetMessage("Failed to install the update!\nError:" + e.Message, 5); + _readyForDeletion = true; + yield break; + } - PlayerPrefs.SetString(translationVersion, _serverVersion); + PlayerPrefs.SetString(translationVersionKey, _serverVersion); + PlayerPrefs.Save(); + PanelUpdateProgress.SetActive(false); SetMessage("Update completed! Please restart the game to apply it.", 5); - _updateSuccess = true; - _updating = false; + _readyForDeletion = true; } + #region Message + [Header("Message")] + public GameObject PanelMessage; + public Text TextMessage; + private void SetMessage(string message, float time = 2) { - _message = message; + PanelMessage.SetActive(true); + TextMessage.text = message; _messageTime = time; } + private IEnumerator SetAwaitableMessage(string message, float time) + { + SetMessage(message, time); + do + { + yield return 0; + } + while (PanelMessage.activeInHierarchy); + } + #endregion + + #region UpdateChecker + [Header("UpdateChecker")] + public GameObject PanelUpdateChecker; + #endregion + + #region UpdateProgress + [Header("UpdateProgress")] + public GameObject PanelUpdateProgress; + public Slider SlUpdateProgress; + public Text TextUpdateProgress; + + public void SetUpdateProgress(float value) + { + SlUpdateProgress.value = value; + TextUpdateProgress.text = $"{Mathf.Round(value * 10000) / 100}%"; + } + #endregion + + #region UpdateAvailable + [Header("UpdateAvailable")] + public GameObject PanelUpdateAvailable; + + public void OpenUpdateAvailable() + { + PanelUpdateAvailable.SetActive(true); + } + + public void OnIgnore() + { + Destroy(this.gameObject); + } + + public void OnDownload() + { + PanelUpdateAvailable.SetActive(false); + StartCoroutine(UpdateTranslation()); + } + #endregion + + #region Settings + private bool _settingsChanged = false; + [Header("Settings")] + public GameObject PanelSettings; + public Dropdown DdRepository; + public InputField InRepositoryUrl; + public Text TextUpdaterVersion; + public Text TextTranslationVersion; + + public void OpenSettings() + { + PanelSettings.gameObject.SetActive(true); + int mode = PlayerPrefs.GetInt(customRepositoryKey, 0); + OnSourceDropdown(mode); + DdRepository.SetValueWithoutNotify(mode); + TextUpdaterVersion.text = "Updater Version: " + PluginVersion; + TextTranslationVersion.text = "Translation Version: " + PlayerPrefs.GetString(translationVersionKey, "undefined"); + _settingsChanged = false; + } + + public void OnSourceDropdown(int choice) + { + switch (choice) + { + case 0: + PlayerPrefs.SetInt(customRepositoryKey, 0); + InRepositoryUrl.text = defaultRepositoryUrl; + InRepositoryUrl.interactable = false; + break; + case 1: + PlayerPrefs.SetInt(customRepositoryKey, 1); + InRepositoryUrl.text = PlayerPrefs.GetString(repositoryUrlKey, defaultRepositoryUrl); + InRepositoryUrl.interactable = true; + break; + } + PlayerPrefs.Save(); + _settingsChanged = true; + } + + public void OnSourceEditFinished(string text) + { + PlayerPrefs.SetString(repositoryUrlKey, text); + PlayerPrefs.Save(); + _settingsChanged = true; + } + + public void OnClearButton() + { + PlayerPrefs.SetString(translationVersionKey, "undefined"); + PlayerPrefs.Save(); + OpenSettings(); + _settingsChanged = true; + } + + public void OnSettingsClose() + { + if (_settingsChanged) + { + Destroy(this.gameObject); + Create(); + } + else + { + PanelSettings.SetActive(false); + } + } + + #endregion + public static IEnumerator DownloadBytes(string url, System.Action callback, System.Action onProgressChanged = null) { UnityWebRequest www = UnityWebRequest.Get(url);