Make icon cache save to disk

This commit is contained in:
2026-01-24 20:08:42 -07:00
parent 44b594a7f2
commit 8b69294674
6 changed files with 182 additions and 67 deletions

View File

@@ -1,5 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Numerics; using System.Numerics;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using UnityEngine; using UnityEngine;
@@ -9,7 +13,7 @@ public class BazookaManager : MonoBehaviour
private bool firstLoadDone = false; private bool firstLoadDone = false;
public JObject saveFile = new() public JObject saveFile = new()
{ {
["version"] = "0" ["version"] = "1"
}; };
public List<MarketplaceIcon> iconCache = new(); public List<MarketplaceIcon> iconCache = new();
@@ -22,7 +26,42 @@ public class BazookaManager : MonoBehaviour
if (!firstLoadDone) if (!firstLoadDone)
{ {
firstLoadDone = true; 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<List<MarketplaceIcon>>() ?? new List<MarketplaceIcon>();
foreach (var icon in tempIconCache)
{
iconCache.Add(new MarketplaceIcon
{
Data = icon.Data.Substring(0, icon.Data.Length - 128),
ID = icon.ID
});
}
}
} }
} }
else else
@@ -33,65 +72,106 @@ public class BazookaManager : MonoBehaviour
void OnApplicationQuit() 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) void OnApplicationPause(bool pause)
{ {
if (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, saveName + ".json");
string path = Path.Join(Application.persistentDataPath, SensitiveInfo.BAZOOKA_MANAGER_FILE_KEY + ".dat");
if (!File.Exists(path)) if (!File.Exists(path))
{ {
File.Create(path).Dispose(); return null;
} }
else else
{ {
try try
{ {
var tempSaveFile = JObject.Parse(SensitiveInfo.DecryptRaw(File.ReadAllBytes(path), SensitiveInfo.BAZOOKA_MANAGER_KEY)); var tempSaveFile = JObject.Parse(File.ReadAllText(path));
if (tempSaveFile != null) saveFile = tempSaveFile; 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") return null;
{
saveFile["version"] = "0";
}
} }
public void Save() public JArray LoadArray(string saveName)
{ {
#if UNITY_EDITOR string path = Path.Join(Application.persistentDataPath, saveName + ".json");
return; if (!File.Exists(path))
#else {
if (SensitiveInfo.BAZOOKA_MANAGER_KEY.Trim().Length == 0 || SensitiveInfo.BAZOOKA_MANAGER_FILE_KEY.Trim().Length == 0) return; return null;
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); 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; if (encoded == null) return;
using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
fileStream.Write(encoded, 0, encoded.Length); fileStream.Write(encoded, 0, encoded.Length);
fileStream.Flush(true); fileStream.Flush(true);
#endif
} }
public void ResetSave() public void ResetSave()
{ {
saveFile = new JObject saveFile = new JObject
{ {
["version"] = "0" ["version"] = "1"
}; };
Save(); Save("savefile", saveFile);
} }
//Random stuff //Random stuff
@@ -135,7 +215,6 @@ public class BazookaManager : MonoBehaviour
saveFile["bird"]["overlay"] = value; saveFile["bird"]["overlay"] = value;
} }
public void UnsetBirdOverlay() public void UnsetBirdOverlay()
{ {
if (saveFile["bird"] == null) return; if (saveFile["bird"] == null) return;

View File

@@ -41,12 +41,8 @@ public class CustomIconLoader : MonoBehaviour
var cachedIcon = BazookaManager.Instance.iconCache.FirstOrDefault(icon => icon.ID == obj.ID); var cachedIcon = BazookaManager.Instance.iconCache.FirstOrDefault(icon => icon.ID == obj.ID);
if (cachedIcon != null) if (cachedIcon != null)
{ {
var (d, h) = Tools.FixIconData(cachedIcon.Data); try { Tools.RenderFromBase64(cachedIcon.Data, obj.GetComponent<Image>()); }
if (d != null && h != null && Tools.Sha512Sum(Convert.FromBase64String(d)) == h) catch { Tools.RenderFromBase64(cachedIcon.Data, obj.GetComponent<SpriteRenderer>()); }
{
try { Tools.RenderFromBase64(d, obj.GetComponent<Image>()); }
catch { Tools.RenderFromBase64(d, obj.GetComponent<SpriteRenderer>()); }
}
} }
Destroy(obj); Destroy(obj);
} }

View File

@@ -166,8 +166,7 @@ public class IconMarketplaceDownloadIcon : MonoBehaviour
{ {
GameObject newIcon = Instantiate(sample, content.transform); GameObject newIcon = Instantiate(sample, content.transform);
newIcon.name = "IconEntry"; newIcon.name = "IconEntry";
var (d, h) = Tools.FixIconData(entry.Data); Tools.RenderFromBase64(entry.Data, newIcon.transform.GetChild(0).GetChild(0).GetComponent<Image>());
if (d != null && h != null && Tools.Sha512Sum(Convert.FromBase64String(d)) == h) Tools.RenderFromBase64(d, newIcon.transform.GetChild(0).GetChild(0).GetComponent<Image>());
newIcon.transform.GetChild(1).GetComponent<TMP_Text>().text = "Bird Name: " + entry.Name; newIcon.transform.GetChild(1).GetComponent<TMP_Text>().text = "Bird Name: " + entry.Name;
newIcon.transform.GetChild(2).GetComponent<TMP_Text>().text = "Price " + Tools.FormatWithCommas(entry.Price) + " coins"; newIcon.transform.GetChild(2).GetComponent<TMP_Text>().text = "Price " + Tools.FormatWithCommas(entry.Price) + " coins";
newIcon.transform.GetChild(3).GetComponent<TMP_Text>().text = "Designer Name: " + entry.CreatorUsername; newIcon.transform.GetChild(3).GetComponent<TMP_Text>().text = "Designer Name: " + entry.CreatorUsername;

View File

@@ -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;
}
}
}

View File

@@ -66,38 +66,6 @@ public static class Tools
if (root.TryGetComponent<RectTransform>(out var rect)) LayoutRebuilder.ForceRebuildLayoutImmediate(rect); if (root.TryGetComponent<RectTransform>(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) public static string Sha512Sum(byte[] data)
{ {
using var sha512 = SHA512.Create(); using var sha512 = SHA512.Create();