generated from pancake-llc/package
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
250 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using Pancake.OdinSerializer; | ||
using UnityEngine; | ||
|
||
namespace Pancake | ||
{ | ||
/// <summary> | ||
/// | ||
/// </summary> | ||
public static class Data | ||
{ | ||
[Serializable] | ||
private sealed class DataSegment | ||
{ | ||
public byte[] value; | ||
} | ||
|
||
private static bool isInitialized; | ||
private static string path = string.Empty; | ||
private static int profile; | ||
private static Dictionary<string, DataSegment> datas; | ||
private const int INIT_SIZE = 64; | ||
private const DataFormat FORMAT = DataFormat.Binary; | ||
|
||
public static event Action OnSaveEvent; | ||
|
||
#region Internal Stuff | ||
|
||
internal static void Init() | ||
{ | ||
if (isInitialized) return; | ||
isInitialized = true; | ||
|
||
GeneratePath(); | ||
Load(); | ||
RuntimeHelper.AddFocusCallback(OnApplicationFocus); | ||
} | ||
|
||
private static byte[] Serialize<T>(T data) | ||
{ | ||
byte[] bytes = SerializationUtility.SerializeValue(data, FORMAT); | ||
return bytes; | ||
} | ||
|
||
private static T Deserialize<T>(byte[] bytes) | ||
{ | ||
var data = SerializationUtility.DeserializeValue<T>(bytes, FORMAT); | ||
return data; | ||
} | ||
|
||
private static void GeneratePath() { path = Path.Combine(Application.persistentDataPath, $"masterdata_{profile}.data"); } | ||
|
||
private static void OnApplicationFocus(bool focus) | ||
{ | ||
if (!focus) | ||
{ | ||
Save(); | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
#region Public API | ||
|
||
public static void ChangeProfile(int value) | ||
{ | ||
if (profile == value) return; | ||
|
||
Save(); | ||
profile = value; | ||
GeneratePath(); | ||
Load(); | ||
} | ||
|
||
public static void Save() | ||
{ | ||
OnSaveEvent?.Invoke(); | ||
|
||
byte[] bytes = Serialize(datas); | ||
File.WriteAllBytes(path, bytes); | ||
} | ||
|
||
public static void Load() | ||
{ | ||
if (!path.FileExists()) | ||
{ | ||
var stream = File.Create(path); | ||
stream?.Close(); | ||
} | ||
|
||
byte[] bytes = File.ReadAllBytes(path); | ||
datas = Deserialize<Dictionary<string, DataSegment>>(bytes) ?? new Dictionary<string, DataSegment>(INIT_SIZE); | ||
} | ||
|
||
public static T Load<T>(string key) | ||
{ | ||
datas.TryGetValue(key, out var value); | ||
if (value == null) throw Error.NotFound(key); | ||
return Deserialize<T>(value.value); | ||
} | ||
|
||
public static bool TryLoad<T>(string key, out T data) | ||
{ | ||
bool hasKey; | ||
if (datas.TryGetValue(key, out var value)) | ||
{ | ||
data = Deserialize<T>(value.value); | ||
hasKey = true; | ||
} | ||
else | ||
{ | ||
data = default; | ||
hasKey = false; | ||
} | ||
|
||
return hasKey; | ||
} | ||
|
||
public static void Save<T>(string key, T data) | ||
{ | ||
if (datas.TryGetValue(key, out var value)) | ||
{ | ||
value.value = Serialize<T>(data); | ||
} | ||
else | ||
{ | ||
var dataSegment = new DataSegment {value = Serialize<T>(data)}; | ||
datas.Add(key, dataSegment); | ||
} | ||
} | ||
|
||
public static bool HasKey(string key) => datas.ContainsKey(key); | ||
|
||
public static void DeleteKey(string key) => datas.Remove(key); | ||
|
||
public static void DeleteAll() => datas.Clear(); | ||
|
||
#endregion | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using System; | ||
using System.Globalization; | ||
using System.IO; | ||
using System.Text; | ||
using UnityEngine; | ||
|
||
namespace Pancake | ||
{ | ||
public static class DeviceLogTracking | ||
{ | ||
private static bool isInitialized; | ||
public static StringBuilder sessionLogError; | ||
|
||
internal static void Init() | ||
{ | ||
if (isInitialized) return; | ||
isInitialized = true; | ||
// tracking log | ||
sessionLogError = new StringBuilder(); | ||
Application.logMessageReceived -= OnHandleLogReceived; | ||
Application.logMessageReceived += OnHandleLogReceived; | ||
RuntimeHelper.AddQuitCallback(OnApplicationQuit); | ||
} | ||
|
||
/// <summary> | ||
/// handle when receive log | ||
/// </summary> | ||
/// <param name="log"></param> | ||
/// <param name="stacktrace"></param> | ||
/// <param name="type"></param> | ||
private static void OnHandleLogReceived(string log, string stacktrace, LogType type) | ||
{ | ||
if (type == LogType.Exception || type == LogType.Error) | ||
{ | ||
sessionLogError.AppendLine(log); | ||
sessionLogError.AppendLine(stacktrace); | ||
} | ||
} | ||
|
||
private static void OnApplicationQuit() | ||
{ | ||
// remove old log outdate | ||
RemoveOldLogDirectory(3); | ||
|
||
// write current log | ||
WriteLocalLog(); | ||
} | ||
|
||
/// <summary> | ||
/// write log to local file | ||
/// </summary> | ||
/// <returns></returns> | ||
private static string WriteLocalLog() | ||
{ | ||
var log = sessionLogError.ToString(); | ||
if (!string.IsNullOrEmpty(log)) | ||
{ | ||
// create the directory | ||
var feedbackDirectory = $"{Application.persistentDataPath}/userlogs/{DateTime.Now:ddMMyyyy}/{DateTime.Now:HHmmss}"; | ||
if (!feedbackDirectory.DirectoryExists()) feedbackDirectory.CreateDirectory(); | ||
|
||
// save the log | ||
File.WriteAllText(feedbackDirectory + "/logs.txt", log); | ||
|
||
return feedbackDirectory; | ||
} | ||
|
||
return ""; | ||
} | ||
|
||
/// <summary> | ||
/// Removes stale logs that exceed the number of days specified by <paramref name="day"/> | ||
/// </summary> | ||
/// <param name="day"></param> | ||
private static void RemoveOldLogDirectory(int day) | ||
{ | ||
var path = $"{Application.persistentDataPath}/userlogs"; | ||
if (path.DirectoryExists()) | ||
{ | ||
DirectoryInfo info = new DirectoryInfo(path); | ||
foreach (var directoryInfo in info.GetDirectories()) | ||
{ | ||
string folderName = directoryInfo.Name; | ||
DateTime.TryParseExact(folderName, | ||
"ddMMyyyy", | ||
CultureInfo.InvariantCulture, | ||
DateTimeStyles.None, | ||
out var dateTime); | ||
|
||
if ((DateTime.Now - dateTime).TotalDays >= day) $"{path}/{folderName}".DeleteDirectory(); | ||
} | ||
} | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters