From 8b692946749eae7c6d7737e9f7002f5b787e55ba Mon Sep 17 00:00:00 2001 From: Lncvrt Date: Sat, 24 Jan 2026 20:08:42 -0700 Subject: [PATCH] Make icon cache save to disk --- Assets/Scripts/BazookaManager.cs | 133 ++++++++++++++---- Assets/Scripts/CustomIconLoader.cs | 8 +- .../IconMarketplaceDownloadIcon.cs | 3 +- Assets/Scripts/OldSavefileEncryption.cs | 73 ++++++++++ ....cs.meta => OldSavefileEncryption.cs.meta} | 0 Assets/Scripts/Tools.cs | 32 ----- 6 files changed, 182 insertions(+), 67 deletions(-) create mode 100644 Assets/Scripts/OldSavefileEncryption.cs rename Assets/Scripts/{SensitiveInfo.cs.meta => OldSavefileEncryption.cs.meta} (100%) diff --git a/Assets/Scripts/BazookaManager.cs b/Assets/Scripts/BazookaManager.cs index d95aa04..f4caf55 100644 --- a/Assets/Scripts/BazookaManager.cs +++ b/Assets/Scripts/BazookaManager.cs @@ -1,5 +1,9 @@ +using System; +using System.Collections.Generic; using System.IO; using System.Numerics; +using System.Text; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; @@ -9,7 +13,7 @@ public class BazookaManager : MonoBehaviour private bool firstLoadDone = false; public JObject saveFile = new() { - ["version"] = "0" + ["version"] = "1" }; public List iconCache = new(); @@ -22,7 +26,42 @@ public class BazookaManager : MonoBehaviour if (!firstLoadDone) { firstLoadDone = true; - Load(); + var save = LoadObject("savefile"); + var cache = LoadArray("cache"); + if (save != null) + { + saveFile = save; + if (saveFile["version"] == null) + { + saveFile["version"] = "0"; + } + if (saveFile["version"].ToString() == "0") + { + if (saveFile["bird"]["customIcon"]["data"] != null) + { + var data = saveFile["bird"]["customIcon"]["data"]; + var customData = GetCustomBirdIconData(); + saveFile["bird"]["customIcon"]["data"].Parent.Remove(); + foreach (var icon in data) + if (icon["uuid"].ToString() != null) customData.Purchased.Add(icon["uuid"].ToString()); + SetCustomBirdIconData(customData); + } + saveFile["version"] = "1"; + Save("savefile", saveFile); + } + } + if (cache != null) + { + var tempIconCache = cache.ToObject>() ?? new List(); + foreach (var icon in tempIconCache) + { + iconCache.Add(new MarketplaceIcon + { + Data = icon.Data.Substring(0, icon.Data.Length - 128), + ID = icon.ID + }); + } + } } } else @@ -33,65 +72,106 @@ public class BazookaManager : MonoBehaviour void OnApplicationQuit() { - Save(); + Save("savefile", saveFile); + + var cacheIcons = new JArray(); + foreach (var icon in iconCache) + cacheIcons.Add(new JObject + { + ["data"] = icon.Data + Tools.Sha512Sum(Convert.FromBase64String(icon.Data)), + ["id"] = icon.ID + }); + Save("cache", cacheIcons); } void OnApplicationPause(bool pause) { if (pause) { - Save(); + Save("savefile", saveFile); + + var cacheIcons = new JArray(); + foreach (var icon in iconCache) + cacheIcons.Add(new JObject + { + ["data"] = icon.Data + Tools.Sha512Sum(Convert.FromBase64String(icon.Data)), + ["id"] = icon.ID + }); + Save("cache", cacheIcons); } } - public void Load() + public JObject LoadObject(string saveName) { - if (SensitiveInfo.BAZOOKA_MANAGER_KEY.Trim().Length == 0 || SensitiveInfo.BAZOOKA_MANAGER_FILE_KEY.Trim().Length == 0) return; - string path = Path.Join(Application.persistentDataPath, SensitiveInfo.BAZOOKA_MANAGER_FILE_KEY + ".dat"); + string path = Path.Join(Application.persistentDataPath, saveName + ".json"); if (!File.Exists(path)) { - File.Create(path).Dispose(); + return null; } else { try { - var tempSaveFile = JObject.Parse(SensitiveInfo.DecryptRaw(File.ReadAllBytes(path), SensitiveInfo.BAZOOKA_MANAGER_KEY)); - if (tempSaveFile != null) saveFile = tempSaveFile; + var tempSaveFile = JObject.Parse(File.ReadAllText(path)); + if (tempSaveFile != null) return tempSaveFile; } - catch + catch (Exception e) { - Debug.LogWarning("Failed to load save file"); + Debug.LogWarning("Failed to load save file: " + e); } } - if (saveFile["version"] == null || saveFile["version"].ToString() != "0") - { - saveFile["version"] = "0"; - } + return null; } - public void Save() + public JArray LoadArray(string saveName) { -#if UNITY_EDITOR - return; -#else - if (SensitiveInfo.BAZOOKA_MANAGER_KEY.Trim().Length == 0 || SensitiveInfo.BAZOOKA_MANAGER_FILE_KEY.Trim().Length == 0) return; - string path = Path.Join(Application.persistentDataPath, SensitiveInfo.BAZOOKA_MANAGER_FILE_KEY + ".dat"); - var encoded = SensitiveInfo.EncryptRaw(saveFile.ToString(Newtonsoft.Json.Formatting.None), SensitiveInfo.BAZOOKA_MANAGER_KEY); + string path = Path.Join(Application.persistentDataPath, saveName + ".json"); + if (!File.Exists(path)) + { + return null; + } + else + { + try + { + var tempSaveFile = JArray.Parse(File.ReadAllText(path)); + if (tempSaveFile != null) return tempSaveFile; + } + catch (Exception e) + { + Debug.LogWarning("Failed to load save file: " + e); + } + } + return null; + } + + public void Save(string saveName, JObject save) + { + string path = Path.Join(Application.persistentDataPath, saveName + ".json"); + var encoded = Encoding.UTF8.GetBytes(save.ToString(Formatting.Indented)); + if (encoded == null) return; + using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); + fileStream.Write(encoded, 0, encoded.Length); + fileStream.Flush(true); + } + + public void Save(string saveName, JArray save) + { + string path = Path.Join(Application.persistentDataPath, saveName + ".json"); + var encoded = Encoding.UTF8.GetBytes(save.ToString(Formatting.Indented)); if (encoded == null) return; using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); fileStream.Write(encoded, 0, encoded.Length); fileStream.Flush(true); -#endif } public void ResetSave() { saveFile = new JObject { - ["version"] = "0" + ["version"] = "1" }; - Save(); + Save("savefile", saveFile); } //Random stuff @@ -135,7 +215,6 @@ public class BazookaManager : MonoBehaviour saveFile["bird"]["overlay"] = value; } - public void UnsetBirdOverlay() { if (saveFile["bird"] == null) return; diff --git a/Assets/Scripts/CustomIconLoader.cs b/Assets/Scripts/CustomIconLoader.cs index 46d2e69..53f978e 100644 --- a/Assets/Scripts/CustomIconLoader.cs +++ b/Assets/Scripts/CustomIconLoader.cs @@ -41,12 +41,8 @@ public class CustomIconLoader : MonoBehaviour var cachedIcon = BazookaManager.Instance.iconCache.FirstOrDefault(icon => icon.ID == obj.ID); if (cachedIcon != null) { - var (d, h) = Tools.FixIconData(cachedIcon.Data); - if (d != null && h != null && Tools.Sha512Sum(Convert.FromBase64String(d)) == h) - { - try { Tools.RenderFromBase64(d, obj.GetComponent()); } - catch { Tools.RenderFromBase64(d, obj.GetComponent()); } - } + try { Tools.RenderFromBase64(cachedIcon.Data, obj.GetComponent()); } + catch { Tools.RenderFromBase64(cachedIcon.Data, obj.GetComponent()); } } Destroy(obj); } diff --git a/Assets/Scripts/IconMarketplace/IconMarketplaceDownloadIcon.cs b/Assets/Scripts/IconMarketplace/IconMarketplaceDownloadIcon.cs index 2923efe..fb4a7b6 100644 --- a/Assets/Scripts/IconMarketplace/IconMarketplaceDownloadIcon.cs +++ b/Assets/Scripts/IconMarketplace/IconMarketplaceDownloadIcon.cs @@ -166,8 +166,7 @@ public class IconMarketplaceDownloadIcon : MonoBehaviour { GameObject newIcon = Instantiate(sample, content.transform); newIcon.name = "IconEntry"; - var (d, h) = Tools.FixIconData(entry.Data); - if (d != null && h != null && Tools.Sha512Sum(Convert.FromBase64String(d)) == h) Tools.RenderFromBase64(d, newIcon.transform.GetChild(0).GetChild(0).GetComponent()); + Tools.RenderFromBase64(entry.Data, newIcon.transform.GetChild(0).GetChild(0).GetComponent()); newIcon.transform.GetChild(1).GetComponent().text = "Bird Name: " + entry.Name; newIcon.transform.GetChild(2).GetComponent().text = "Price " + Tools.FormatWithCommas(entry.Price) + " coins"; newIcon.transform.GetChild(3).GetComponent().text = "Designer Name: " + entry.CreatorUsername; diff --git a/Assets/Scripts/OldSavefileEncryption.cs b/Assets/Scripts/OldSavefileEncryption.cs new file mode 100644 index 0000000..3d872b8 --- /dev/null +++ b/Assets/Scripts/OldSavefileEncryption.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using UnityEngine; + +public class OldSavefileEncryption +{ + public static readonly string BAZOOKA_MANAGER_KEY = "5de0d5798d4eb751e13b668c1fc5297d"; + public static readonly string BAZOOKA_MANAGER_FILE_KEY = "e74af7ba21b8b4edd0e3f1d572d63c67"; + + public static byte[] EncryptRaw(string text, string key) + { + if (BAZOOKA_MANAGER_KEY.Trim() == string.Empty) + { + Debug.LogError("Failed to encrypt: Encryption/Decryption keys not present"); + return null; + } + try + { + using Aes aes = Aes.Create(); + aes.Key = Encoding.UTF8.GetBytes(key); + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + aes.GenerateIV(); + + using MemoryStream ms = new(); + ms.Write(aes.IV, 0, aes.IV.Length); + + using (var cryptoStream = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) + using (var writer = new StreamWriter(cryptoStream)) + { + writer.Write(text); + } + + return ms.ToArray(); + } + catch + { + return null; + } + } + + public static string DecryptRaw(byte[] data, string key) + { + if (BAZOOKA_MANAGER_KEY.Trim() == string.Empty) + { + Debug.LogError("Failed to decrypt: Encryption/Decryption keys not present"); + return null; + } + try + { + using Aes aes = Aes.Create(); + aes.Key = Encoding.UTF8.GetBytes(key); + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + + byte[] iv = new byte[16]; + Array.Copy(data, 0, iv, 0, iv.Length); + aes.IV = iv; + + using MemoryStream ms = new(data, iv.Length, data.Length - iv.Length); + using var cryptoStream = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read); + using StreamReader reader = new(cryptoStream); + + return reader.ReadToEnd(); + } + catch + { + return null; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/SensitiveInfo.cs.meta b/Assets/Scripts/OldSavefileEncryption.cs.meta similarity index 100% rename from Assets/Scripts/SensitiveInfo.cs.meta rename to Assets/Scripts/OldSavefileEncryption.cs.meta diff --git a/Assets/Scripts/Tools.cs b/Assets/Scripts/Tools.cs index 39b1eba..4e96972 100644 --- a/Assets/Scripts/Tools.cs +++ b/Assets/Scripts/Tools.cs @@ -66,38 +66,6 @@ public static class Tools if (root.TryGetComponent(out var rect)) LayoutRebuilder.ForceRebuildLayoutImmediate(rect); } - public static (string, string) FixIconData(string i) - { - try - { - int t = i.Length; - int h = 128; - int d = t - h; - int a = d / 4; - int b = h / 4; - - string D = string.Concat( - i.Substring(0, a), - i.Substring(a + b, a), - i.Substring(a * 2 + b * 2, a), - i.Substring(a * 3 + b * 3, d - a * 3) - ); - - string H = string.Concat( - i.Substring(a, b), - i.Substring(a * 2 + b, b), - i.Substring(a * 3 + b * 2, b), - i.Substring(a * 4 + b * 3, b) - ); - - return (D, H); - } - catch - { - return (null, null); - } - } - public static string Sha512Sum(byte[] data) { using var sha512 = SHA512.Create();