2023-10-13 21:14:59 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
2025-02-03 02:44:00 +08:00
|
|
|
using System.IO;
|
|
|
|
using System.IO.Compression;
|
2023-10-13 21:14:59 +08:00
|
|
|
using System.Reflection;
|
2025-02-03 02:44:00 +08:00
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.Networking;
|
2023-10-14 00:48:58 +08:00
|
|
|
using Newtonsoft.Json.Linq;
|
2023-10-11 08:33:27 +08:00
|
|
|
|
|
|
|
public class UpdateHandler : MonoBehaviour
|
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
/// <summary> Set by harmony/bepinex </summary>
|
|
|
|
public static string PluginVersion = "1.0.0";
|
2023-10-13 21:14:59 +08:00
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
[Header("Message")]
|
|
|
|
public PopupMessage PanelMessage;
|
|
|
|
|
|
|
|
[Header("UpdateChecker")]
|
|
|
|
public UpdateChecker UpdateChecker;
|
|
|
|
|
|
|
|
[Header("UpdateProgress")]
|
|
|
|
public ProgressSlider UpdateProgress;
|
|
|
|
|
|
|
|
[Header("UpdateAvailable")]
|
|
|
|
public UpdateAvailable UpdatePanel;
|
|
|
|
|
|
|
|
[Header("Settings")]
|
|
|
|
public SettingsPanel PanelSettings;
|
|
|
|
|
|
|
|
public const string REPO_DEFAULT = "https://git.japari.cafe/api/v1/repos/Vorked/VorkedTranslationPack";
|
2023-10-13 21:14:59 +08:00
|
|
|
|
|
|
|
//playerprefs keys
|
2025-02-03 02:44:00 +08:00
|
|
|
public const string TRANSLATION_VER = "translationVersion";
|
|
|
|
public const string TRANSLATOR_VER = "KF3TLVersion";
|
|
|
|
public const string REPO_CUSTOM_URL = "customRepositoryUrl";
|
|
|
|
public const string REPO_CUSTOM_NAME = "customRepository";
|
|
|
|
|
|
|
|
private int _idleFrames = 0;
|
2023-10-13 21:14:59 +08:00
|
|
|
|
|
|
|
public static void Create()
|
|
|
|
{
|
|
|
|
#if UNITY_EDITOR
|
2025-02-03 02:44:00 +08:00
|
|
|
//var prefab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/UpdateHandler");
|
|
|
|
var prefab = Resources.Load("UpdateHandler");
|
|
|
|
Instantiate(prefab);
|
2023-10-13 21:14:59 +08:00
|
|
|
#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;
|
|
|
|
}
|
2023-10-11 08:33:27 +08:00
|
|
|
|
|
|
|
public IEnumerator Start()
|
|
|
|
{
|
2023-10-13 21:14:59 +08:00
|
|
|
yield return 0;
|
|
|
|
transform.SetAsLastSibling();
|
2025-02-03 02:44:00 +08:00
|
|
|
UpdateChecker.SetActive(true);
|
2023-10-13 21:14:59 +08:00
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
yield return CheckKF3TLUpdate();
|
|
|
|
yield return CheckTranslationUpdate();
|
2023-10-11 08:33:27 +08:00
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
yield return new WaitForSeconds(5);
|
|
|
|
UpdateChecker.SetActive(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < transform.childCount; i++)
|
|
|
|
{
|
|
|
|
if (transform.GetChild(i).gameObject.activeSelf)
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
_idleFrames = 0;
|
|
|
|
return;
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
2025-02-03 02:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_idleFrames >= 5)
|
|
|
|
{
|
|
|
|
Destroy(this.gameObject);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_idleFrames++;
|
|
|
|
}
|
|
|
|
}
|
2023-10-11 08:33:27 +08:00
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
public IEnumerator CheckKF3TLUpdate()
|
|
|
|
{
|
|
|
|
Debug.Log("Checking KF3TL Update");
|
|
|
|
|
|
|
|
string currentVersion = PlayerPrefs.GetString(TRANSLATOR_VER, "undefined");
|
|
|
|
var firstRun = currentVersion == "undefined";
|
|
|
|
BranchCheckResult result = null;
|
|
|
|
|
|
|
|
yield return GetRepoVersion("https://api.github.com/repos/Vorked/KF3TL/branches/main", data =>
|
2023-10-13 21:14:59 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
result = data;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (result == null || !result.Success)
|
|
|
|
{
|
|
|
|
UpdateChecker.SetActive(false);
|
|
|
|
if (result == null)
|
|
|
|
{
|
|
|
|
yield return SetAwaitableMessage("Failed to get response from server", 5);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
yield return SetAwaitableMessage("Failed to check for update!\nError: " + result.Error, 5);
|
|
|
|
}
|
2023-10-13 21:14:59 +08:00
|
|
|
yield break;
|
|
|
|
}
|
|
|
|
|
2023-10-11 08:33:27 +08:00
|
|
|
Debug.Log("local version: " + currentVersion);
|
2025-02-03 02:44:00 +08:00
|
|
|
Debug.Log("server version: " + result.Version);
|
2023-10-11 08:33:27 +08:00
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
if (firstRun)
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
yield return SetAwaitableMessage("First run detected. Press Ignore on next prompt if you have the newest version of KF3TL", 150);
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
2025-02-03 02:44:00 +08:00
|
|
|
|
|
|
|
if (result.Version != currentVersion)
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
var panel = Instantiate(UpdatePanel, transform);
|
|
|
|
panel.Init("KF3TL Plugin Update", currentVersion, result.Version);
|
|
|
|
panel.OnDownloadAction = () =>
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
StartCoroutine(UpdateKF3TL(result.Version, () => Destroy(panel.gameObject)));
|
|
|
|
panel.gameObject.SetActive(false);
|
|
|
|
};
|
|
|
|
panel.OnIgnoreAction = () =>
|
|
|
|
{
|
|
|
|
Destroy(panel.gameObject);
|
|
|
|
};
|
|
|
|
if (firstRun)
|
|
|
|
{
|
|
|
|
panel.OnIgnorePersistentAction = () =>
|
|
|
|
{
|
|
|
|
PlayerPrefs.SetString(TRANSLATOR_VER, result.Version);
|
|
|
|
PlayerPrefs.Save();
|
|
|
|
Destroy(panel.gameObject);
|
|
|
|
};
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
2025-02-03 02:44:00 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
panel.IgnorePersistentButton.gameObject.SetActive(false);
|
|
|
|
}
|
|
|
|
while (panel != null) yield return 0;
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
public IEnumerator UpdateKF3TL(string version, System.Action onComplete)
|
|
|
|
{
|
|
|
|
byte[] bytes = null;
|
|
|
|
yield return DownloadBytes("https://api.github.com/repos/Vorked/KF3TL/zipball/main",
|
|
|
|
(newBytes) =>
|
|
|
|
{
|
|
|
|
bytes = newBytes;
|
|
|
|
},
|
|
|
|
UpdateProgress.SetUpdateProgress
|
|
|
|
);
|
|
|
|
|
|
|
|
UpdateProgress.SetUpdateProgress(1);
|
|
|
|
|
|
|
|
if (bytes.Length <= 0)
|
|
|
|
{
|
|
|
|
yield return SetAwaitableMessage("Failed to download the update!\nDownload new version from https://github.com/Vorked/KF3TL", 15);
|
|
|
|
yield break;
|
|
|
|
}
|
|
|
|
|
|
|
|
var path = Application.dataPath + "/../" + "KF3TL.zip";
|
|
|
|
File.WriteAllBytes(path, bytes);
|
|
|
|
|
|
|
|
PlayerPrefs.SetString(TRANSLATOR_VER, version);
|
|
|
|
PlayerPrefs.Save();
|
|
|
|
UpdateProgress.SetActive(false);
|
|
|
|
var message = Instantiate(PanelMessage, transform).Init($"New version downloaded as KF3TL.zip. Please close the game and install it.", 150);
|
|
|
|
message.OnFinishedAction = () =>
|
|
|
|
{
|
|
|
|
System.Diagnostics.Process.Start("explorer.exe", "/select," + path.Replace("/", "\\"));
|
|
|
|
onComplete?.Invoke();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
public IEnumerator CheckTranslationUpdate()
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
Debug.Log("Checking Translation Update");
|
|
|
|
|
|
|
|
string repositoryUrl = PlayerPrefs.GetInt(REPO_CUSTOM_NAME, 0) == 0 ? REPO_DEFAULT : PlayerPrefs.GetString(REPO_CUSTOM_URL, REPO_DEFAULT);
|
|
|
|
string currentVersion = PlayerPrefs.GetString(TRANSLATION_VER, "undefined");
|
|
|
|
BranchCheckResult result = null;
|
|
|
|
|
|
|
|
yield return GetRepoVersion(repositoryUrl + "/branches/master", data =>
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
result = data;
|
|
|
|
});
|
2023-10-13 21:14:59 +08:00
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
if (result == null || !result.Success)
|
|
|
|
{
|
|
|
|
UpdateChecker.SetActive(false);
|
|
|
|
if (result == null)
|
|
|
|
{
|
|
|
|
yield return SetAwaitableMessage("Failed to get response from server", 5);
|
|
|
|
}
|
|
|
|
else
|
2023-10-13 21:14:59 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
yield return SetAwaitableMessage("Failed to check for update!\nError: " + result.Error, 5);
|
2023-10-13 21:14:59 +08:00
|
|
|
}
|
2025-02-03 02:44:00 +08:00
|
|
|
yield break;
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
2025-02-03 02:44:00 +08:00
|
|
|
|
|
|
|
Debug.Log("local version: " + currentVersion);
|
|
|
|
Debug.Log("server version: " + result.Version);
|
|
|
|
|
|
|
|
if (result.Version != currentVersion)
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
var panel = Instantiate(UpdatePanel, transform);
|
|
|
|
panel.Init("Translation pack", currentVersion, result.Version);
|
|
|
|
panel.OnDownloadAction = () =>
|
|
|
|
{
|
|
|
|
StartCoroutine(UpdateTranslation(result.Version, () => Destroy(panel.gameObject)));
|
|
|
|
panel.gameObject.SetActive(false);
|
|
|
|
};
|
|
|
|
panel.OnIgnoreAction = () =>
|
|
|
|
{
|
|
|
|
Destroy(panel.gameObject);
|
|
|
|
};
|
|
|
|
panel.OnIgnorePersistentAction = () =>
|
|
|
|
{
|
|
|
|
PlayerPrefs.SetString(TRANSLATION_VER, result.Version);
|
|
|
|
PlayerPrefs.Save();
|
|
|
|
Destroy(panel.gameObject);
|
|
|
|
};
|
|
|
|
do yield return 0; while (panel != null);
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
public IEnumerator UpdateTranslation(string version, System.Action onComplete)
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
|
|
|
byte[] bytes = null;
|
2025-02-03 02:44:00 +08:00
|
|
|
string repositoryUrl = PlayerPrefs.GetInt(REPO_CUSTOM_NAME, 0) == 0 ? REPO_DEFAULT : PlayerPrefs.GetString(REPO_CUSTOM_URL, REPO_DEFAULT);
|
2023-10-11 08:33:27 +08:00
|
|
|
yield return DownloadBytes(repositoryUrl + "/archive/master.zip",
|
|
|
|
(newBytes) =>
|
|
|
|
{
|
|
|
|
bytes = newBytes;
|
|
|
|
},
|
2025-02-03 02:44:00 +08:00
|
|
|
UpdateProgress.SetUpdateProgress
|
2023-10-11 08:33:27 +08:00
|
|
|
);
|
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
UpdateProgress.SetUpdateProgress(1);
|
|
|
|
|
2023-10-11 08:33:27 +08:00
|
|
|
if (bytes.Length <= 0)
|
|
|
|
{
|
2023-10-13 21:14:59 +08:00
|
|
|
yield return SetAwaitableMessage("Failed to download the update!\nCheck your settings.", 5);
|
2023-10-11 08:33:27 +08:00
|
|
|
yield break;
|
|
|
|
}
|
|
|
|
|
2023-10-13 21:14:59 +08:00
|
|
|
try
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2023-10-13 21:14:59 +08:00
|
|
|
using (var compressedFileStream = new MemoryStream(bytes))
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2023-10-13 21:14:59 +08:00
|
|
|
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Read, false))
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2023-10-13 21:14:59 +08:00
|
|
|
foreach (var file in zipArchive.Entries)
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2023-10-13 21:14:59 +08:00
|
|
|
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);
|
|
|
|
}
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-13 21:14:59 +08:00
|
|
|
catch (System.Exception e)
|
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
Instantiate(PanelMessage, transform).Init("Failed to install the update!\nError:" + e.Message, 5);
|
2023-10-13 21:14:59 +08:00
|
|
|
yield break;
|
|
|
|
}
|
2023-10-11 08:33:27 +08:00
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
PlayerPrefs.SetString(TRANSLATION_VER, version);
|
2023-10-13 21:14:59 +08:00
|
|
|
PlayerPrefs.Save();
|
2025-02-03 02:44:00 +08:00
|
|
|
UpdateProgress.SetActive(false);
|
|
|
|
var message = Instantiate(PanelMessage, transform).Init("Update completed! Please restart the game to apply it.", 5);
|
|
|
|
message.OnFinishedAction = onComplete;
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
private IEnumerator GetRepoVersion(string url, System.Action<BranchCheckResult> callback)
|
2023-10-11 08:33:27 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
BranchCheckResult result = null;
|
|
|
|
yield return DownloadText(url,
|
|
|
|
(json) =>
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(json))
|
|
|
|
{
|
|
|
|
throw new System.Exception("No response from " + url);
|
|
|
|
}
|
|
|
|
result = new BranchCheckResult();
|
|
|
|
var newData = JObject.Parse(json).ToObject<BranchInfo>();
|
|
|
|
result.Version = newData.commit.timestamp /* gitea */ ?? newData.commit.commit.author.date; //github
|
|
|
|
result.Success = true;
|
|
|
|
}
|
|
|
|
catch (System.Exception e)
|
|
|
|
{
|
|
|
|
result.Error = e.Message;
|
|
|
|
result.Success = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
callback(result);
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|
|
|
|
|
2023-10-13 21:14:59 +08:00
|
|
|
private IEnumerator SetAwaitableMessage(string message, float time)
|
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
var msg = Instantiate(PanelMessage, transform).Init(message, time);
|
|
|
|
do yield return 0; while (msg != null);
|
2023-10-13 21:14:59 +08:00
|
|
|
}
|
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
public void OpenSettingsDetached()
|
2023-10-13 21:14:59 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
if (PanelSettings.gameObject.activeSelf) return;
|
|
|
|
StartCoroutine(OpenSettings());
|
2023-10-13 21:14:59 +08:00
|
|
|
}
|
|
|
|
|
2025-02-03 02:44:00 +08:00
|
|
|
private IEnumerator OpenSettings()
|
2023-10-13 21:14:59 +08:00
|
|
|
{
|
2025-02-03 02:44:00 +08:00
|
|
|
PanelSettings.Init(PluginVersion);
|
|
|
|
do yield return 0; while (PanelSettings.gameObject.activeSelf);
|
2023-10-13 21:14:59 +08:00
|
|
|
}
|
|
|
|
|
2023-10-11 08:33:27 +08:00
|
|
|
public static IEnumerator DownloadBytes(string url, System.Action<byte[]> callback, System.Action<float> onProgressChanged = null)
|
|
|
|
{
|
|
|
|
UnityWebRequest www = UnityWebRequest.Get(url);
|
|
|
|
|
|
|
|
var request = www.SendWebRequest();
|
|
|
|
while (!request.isDone)
|
|
|
|
{
|
|
|
|
onProgressChanged?.Invoke(request.progress);
|
|
|
|
yield return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (www.result != UnityWebRequest.Result.Success)
|
|
|
|
{
|
|
|
|
Debug.Log(url);
|
|
|
|
Debug.Log(www.error);
|
|
|
|
callback(null);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
callback(www.downloadHandler.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static IEnumerator DownloadText(string url, System.Action<string> callback)
|
|
|
|
{
|
|
|
|
UnityWebRequest www = UnityWebRequest.Get(url);
|
|
|
|
|
|
|
|
yield return www.SendWebRequest();
|
|
|
|
|
|
|
|
if (www.result != UnityWebRequest.Result.Success)
|
|
|
|
{
|
|
|
|
Debug.Log(url);
|
|
|
|
Debug.Log(www.error);
|
|
|
|
callback(null);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
callback(www.downloadHandler.text);
|
|
|
|
}
|
|
|
|
}
|
2025-02-03 02:44:00 +08:00
|
|
|
|
|
|
|
[System.Serializable]
|
|
|
|
public class BranchInfo
|
|
|
|
{
|
|
|
|
public CommitInfo commit;
|
|
|
|
|
|
|
|
[System.Serializable]
|
|
|
|
public class CommitInfo
|
|
|
|
{
|
|
|
|
public string id;
|
|
|
|
public string sha;
|
|
|
|
public string timestamp;
|
|
|
|
public CommitInfo2 commit;
|
|
|
|
|
|
|
|
[System.Serializable]
|
|
|
|
public class CommitInfo2
|
|
|
|
{
|
|
|
|
public AuthorInfo author;
|
|
|
|
|
|
|
|
[System.Serializable]
|
|
|
|
public class AuthorInfo
|
|
|
|
{
|
|
|
|
public string date;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class BranchCheckResult
|
|
|
|
{
|
|
|
|
public bool Success;
|
|
|
|
public string Version;
|
|
|
|
public string Error;
|
|
|
|
}
|
2023-10-11 08:33:27 +08:00
|
|
|
}
|