807 lines
31 KiB
C#
807 lines
31 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Threading.Tasks;
|
||
|
using UnityEngine;
|
||
|
using static BulletHellTemplate.FirebaseManager;
|
||
|
|
||
|
namespace BulletHellTemplate
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Handles saving and retrieving player local data such as name, icon, frame, and character upgrades using PlayerPrefs.
|
||
|
/// </summary>
|
||
|
public class PlayerSave : MonoBehaviour
|
||
|
{
|
||
|
//Account
|
||
|
private const string PlayerNamePrefix = "PLAYERNAME_";
|
||
|
private const string PlayerIconPrefix = "PLAYERICON_";
|
||
|
private const string PlayerFramePrefix = "PLAYERFRAME_";
|
||
|
private const string PlayerAccountLevelPrefix = "PLAYERACCOUNTLEVEL_";
|
||
|
private const string PlayerAccountCurrentExpPrefix = "PLAYERACCOUNTCURRENTEXP_";
|
||
|
private const string TutorialIsDonePrefix = "TUTORIALISDONE_";
|
||
|
|
||
|
//Character
|
||
|
private const string PlayerSelectedCharacterPrefix = "PLAYERSELECTEDCHARACTER_";
|
||
|
private const string PlayerFavouriteCharacterPrefix = "PLAYERFAVOURITECHARACTER_";
|
||
|
private const string CharacterMasteryLevelPrefix = "CHARACTERMASTERYLEVEL_";
|
||
|
private const string CharacterMasteryCurrentExpPrefix = "CHARACTERMASTERYCURRENTEXP_";
|
||
|
private const string CharacterLevelPrefix = "CHARACTERLEVEL_";
|
||
|
private const string CharacterCurrentExpPrefix = "CHARACTERCURRENTEXP_";
|
||
|
private const string CharacterSlotPrefix = "ITEMSLOT_";
|
||
|
private const string ItemLevelPrefix = "ITEMLEVEL_";
|
||
|
private const string CharacterUpgradeLevelPrefix = "CHARACTERUPGRADELEVEL_";
|
||
|
private const string CharacterSkinPrefix = "CHARACTERSKIN_";
|
||
|
private const string CharacterUnlockedSkinsPrefix = "CHARACTERUNLOCKEDSKINS_";
|
||
|
|
||
|
//Progress
|
||
|
private const string UnlockedMapsKey = "UNLOCKED_MAPS";
|
||
|
private const string QuestProgressPrefix = "QUEST_PROGRESS_";
|
||
|
private const string QuestCompletionPrefix = "QUEST_COMPLETED_";
|
||
|
private const string UsedCouponsKey = "USED_COUPONS_";
|
||
|
|
||
|
private const string DailyRewardsKey = "LOCAL_DAILYREWARDS_DATA";
|
||
|
private const string NewPlayerRewardsKey = "LOCAL_NEWPLAYERREWARDS_DATA";
|
||
|
private const string NextDailyResetKey = "NEXTDAILYRESETTIME";
|
||
|
|
||
|
private static bool isLoading = false;
|
||
|
public static void SetLoadingState(bool state)
|
||
|
{
|
||
|
isLoading = state;
|
||
|
}
|
||
|
|
||
|
#region Account Functions
|
||
|
/// <summary>
|
||
|
/// Sets the player's name in PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <param name="playerName">The name of the player.</param>
|
||
|
public static void SetPlayerName(string playerName)
|
||
|
{
|
||
|
PlayerPrefs.SetString(PlayerNamePrefix, playerName);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the player's name from PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <returns>The name of the player.</returns>
|
||
|
public static string GetPlayerName()
|
||
|
{
|
||
|
return PlayerPrefs.GetString(PlayerNamePrefix);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the player's icon in PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <param name="playerIcon">The icon of the player.</param>
|
||
|
public static void SetPlayerIcon(string playerIcon)
|
||
|
{
|
||
|
PlayerPrefs.SetString(PlayerIconPrefix, playerIcon);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the player's icon from PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <returns>The icon of the player.</returns>
|
||
|
public static string GetPlayerIcon()
|
||
|
{
|
||
|
return PlayerPrefs.GetString(PlayerIconPrefix);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the player's frame in PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <param name="playerFrame">The frame of the player.</param>
|
||
|
public static void SetPlayerFrame(string playerFrame)
|
||
|
{
|
||
|
PlayerPrefs.SetString(PlayerFramePrefix, playerFrame);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the player's frame from PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <returns>The frame of the player.</returns>
|
||
|
public static string GetPlayerFrame()
|
||
|
{
|
||
|
return PlayerPrefs.GetString(PlayerFramePrefix);
|
||
|
}
|
||
|
|
||
|
|
||
|
public static void SetAccountLevel(int level)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(PlayerAccountLevelPrefix, level);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
public static int GetAccountLevel()
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(PlayerAccountLevelPrefix, 1);
|
||
|
}
|
||
|
|
||
|
public static void SetAccountCurrentExp(int currentExp)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(PlayerAccountCurrentExpPrefix, currentExp);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
public static int GetAccountCurrentExp()
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(PlayerAccountCurrentExpPrefix, 0);
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region Characters Functions
|
||
|
/// <summary>
|
||
|
/// Sets the selected character's ID in PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The ID of the selected character.</param>
|
||
|
public static void SetSelectedCharacter(int characterId)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(PlayerSelectedCharacterPrefix, characterId);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the selected character's ID from PlayerPrefs.
|
||
|
/// If no character is selected, returns the first unlocked character's ID.
|
||
|
/// </summary>
|
||
|
/// <returns>The ID of the selected or first unlocked character.</returns>
|
||
|
public static int GetSelectedCharacter()
|
||
|
{
|
||
|
if (PlayerPrefs.HasKey(PlayerSelectedCharacterPrefix))
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(PlayerSelectedCharacterPrefix);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (GameInstance.Singleton != null && GameInstance.Singleton.characterData != null)
|
||
|
{
|
||
|
foreach (CharacterData character in GameInstance.Singleton.characterData)
|
||
|
{
|
||
|
if (character.CheckUnlocked)
|
||
|
{
|
||
|
return character.characterId;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Debug.LogError("No unlocked characters available to select.");
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the favourite character's ID in PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The ID of the favourite character.</param>
|
||
|
public static void SetFavouriteCharacter(int characterId)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(PlayerFavouriteCharacterPrefix, characterId);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the favourite character's ID from PlayerPrefs.
|
||
|
/// If no favourite character is set, returns 0.
|
||
|
/// </summary>
|
||
|
/// <returns>The ID of the favourite character or 0 if not set.</returns>
|
||
|
public static int GetFavouriteCharacter()
|
||
|
{
|
||
|
if (PlayerPrefs.HasKey(PlayerFavouriteCharacterPrefix))
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(PlayerFavouriteCharacterPrefix);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the level for the specified character.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <param name="level">The level to set.</param>
|
||
|
public static void SetCharacterLevel(int characterId, int level)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(CharacterLevelPrefix + characterId, level);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the level of the specified character.
|
||
|
/// Returns 1 if the key does not exist.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <returns>The character level.</returns>
|
||
|
public static int GetCharacterLevel(int characterId)
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(CharacterLevelPrefix + characterId, 1);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the current experience for the specified character.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <param name="currentExp">The current experience to set.</param>
|
||
|
public static void SetCharacterCurrentExp(int characterId, int currentExp)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(CharacterCurrentExpPrefix + characterId, currentExp);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the current experience of the specified character.
|
||
|
/// Returns 0 if the key does not exist.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <returns>The current experience.</returns>
|
||
|
public static int GetCharacterCurrentExp(int characterId)
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(CharacterCurrentExpPrefix + characterId, 0);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the mastery level for the specified character.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <param name="masteryLevel">The mastery level to set.</param>
|
||
|
public static void SetCharacterMasteryLevel(int characterId, int masteryLevel)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(CharacterMasteryLevelPrefix + characterId, masteryLevel);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the mastery level of the specified character.
|
||
|
/// Returns 0 if the key does not exist.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <returns>The mastery level.</returns>
|
||
|
public static int GetCharacterMasteryLevel(int characterId)
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(CharacterMasteryLevelPrefix + characterId, 0);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the current mastery experience for the specified character.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <param name="masteryCurrentExp">The current mastery experience to set.</param>
|
||
|
public static void SetCharacterCurrentMasteryExp(int characterId, int masteryCurrentExp)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(CharacterMasteryCurrentExpPrefix + characterId, masteryCurrentExp);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the current mastery experience of the specified character.
|
||
|
/// Returns 0 if the key does not exist.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <returns>The current mastery experience.</returns>
|
||
|
public static int GetCharacterCurrentMasteryExp(int characterId)
|
||
|
{
|
||
|
return PlayerPrefs.GetInt(CharacterMasteryCurrentExpPrefix + characterId, 0);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the unique GUID of the item equipped in a specific slot of a given character.
|
||
|
/// Example key: "CharSlot_{characterId}_{slotName}"
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The ID of the character.</param>
|
||
|
/// <param name="slotName">The slot name (e.g. "WeaponSlot").</param>
|
||
|
/// <param name="uniqueItemGuid">The unique ID of the item, or empty to unequip.</param>
|
||
|
public static void SetCharacterSlotItem(int characterId, string slotName, string uniqueItemGuid)
|
||
|
{
|
||
|
string key = $"{CharacterSlotPrefix}{characterId}_{slotName}";
|
||
|
PlayerPrefs.SetString(key, uniqueItemGuid);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns the unique GUID of the item equipped in the specified slot for the given character.
|
||
|
/// Returns an empty string if none is equipped.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The ID of the character.</param>
|
||
|
/// <param name="slotName">The slot name.</param>
|
||
|
/// <returns>The unique item GUID, or empty if none.</returns>
|
||
|
public static string GetCharacterSlotItem(int characterId, string slotName)
|
||
|
{
|
||
|
string key = $"{CharacterSlotPrefix}{characterId}_{slotName}";
|
||
|
return PlayerPrefs.GetString(key, string.Empty);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the upgrade level for a purchased item identified by its unique GUID.
|
||
|
/// Example key: "ItemLevel_{uniqueItemGuid}"
|
||
|
/// </summary>
|
||
|
/// <param name="uniqueItemGuid">Unique identifier of the purchased item.</param>
|
||
|
/// <param name="level">Current upgrade level.</param>
|
||
|
public static void SetItemUpgradeLevel(string uniqueItemGuid, int level)
|
||
|
{
|
||
|
string key = $"{ItemLevelPrefix}{uniqueItemGuid}";
|
||
|
PlayerPrefs.SetInt(key, level);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Retrieves the upgrade level for a purchased item identified by its unique GUID.
|
||
|
/// Returns 0 if not found.
|
||
|
/// </summary>
|
||
|
/// <param name="uniqueItemGuid">Unique identifier of the purchased item.</param>
|
||
|
/// <returns>Upgrade level if present, otherwise 0.</returns>
|
||
|
public static int GetItemUpgradeLevel(string uniqueItemGuid)
|
||
|
{
|
||
|
string key = $"{ItemLevelPrefix}{uniqueItemGuid}";
|
||
|
return PlayerPrefs.GetInt(key, 0);
|
||
|
}
|
||
|
public static void SetCharacterSkin(int characterId, int skinIndex)
|
||
|
{
|
||
|
PlayerPrefs.SetInt(CharacterSkinPrefix + characterId, skinIndex);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
public static int GetCharacterSkin(int characterId)
|
||
|
{
|
||
|
string key = CharacterSkinPrefix + characterId;
|
||
|
return PlayerPrefs.HasKey(key) ? PlayerPrefs.GetInt(key) : -1;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the unlocked skins for a character locally.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">Unique identifier for the character.</param>
|
||
|
/// <param name="unlockedSkins">List of unlocked skin indices.</param>
|
||
|
public static void SaveCharacterUnlockedSkins(int characterId, List<int> unlockedSkins)
|
||
|
{
|
||
|
UnlockedSkinsData data = new UnlockedSkinsData { unlockedSkins = unlockedSkins };
|
||
|
string json = JsonUtility.ToJson(data);
|
||
|
PlayerPrefs.SetString(CharacterUnlockedSkinsPrefix + characterId, json);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Loads the unlocked skins for a character from local storage.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">Unique identifier for the character.</param>
|
||
|
/// <returns>List of unlocked skin indices. Returns an empty list if no data is found.</returns>
|
||
|
public static List<int> LoadCharacterUnlockedSkins(int characterId)
|
||
|
{
|
||
|
string key = CharacterUnlockedSkinsPrefix + characterId;
|
||
|
if (PlayerPrefs.HasKey(key))
|
||
|
{
|
||
|
string json = PlayerPrefs.GetString(key);
|
||
|
UnlockedSkinsData data = JsonUtility.FromJson<UnlockedSkinsData>(json);
|
||
|
if (data != null && data.unlockedSkins != null)
|
||
|
{
|
||
|
return data.unlockedSkins;
|
||
|
}
|
||
|
}
|
||
|
return new List<int>();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the initial upgrade level (0) for the specified character's stat type.
|
||
|
/// </summary>
|
||
|
/// <param name="characterId">The character identifier.</param>
|
||
|
/// <param name="statType">The stat type.</param>
|
||
|
public static void SaveInitialCharacterUpgradeLevel(int characterId, StatType statType)
|
||
|
{
|
||
|
string key = $"{CharacterUpgradeLevelPrefix}{characterId}_{statType}";
|
||
|
PlayerPrefs.SetInt(key, 0);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
public static void SaveCharacterUpgradeLevel(int characterId, StatType statType, int level)
|
||
|
{
|
||
|
string key = $"{CharacterUpgradeLevelPrefix}{characterId}_{statType}";
|
||
|
PlayerPrefs.SetInt(key, level);
|
||
|
PlayerPrefs.Save();
|
||
|
|
||
|
if (!isLoading && BackendManager.Singleton.CheckInitialized())
|
||
|
{
|
||
|
BackendManager.Singleton.StartCoroutine(SaveCharacterUpgradesAsyncCoroutine(characterId));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerator SaveCharacterUpgradesAsyncCoroutine(int characterId)
|
||
|
{
|
||
|
var upgrades = LoadAllCharacterUpgradeLevels(characterId);
|
||
|
var task = BackendManager.Singleton.SaveCharacterUpgradesAsync(characterId.ToString(), upgrades);
|
||
|
yield return new WaitUntil(() => task.IsCompleted);
|
||
|
|
||
|
if (task.Exception != null)
|
||
|
{
|
||
|
Debug.LogError($"Failed to save character upgrades for {characterId}: {task.Exception}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static int LoadCharacterUpgradeLevel(int characterId, StatType statType)
|
||
|
{
|
||
|
string key = $"{CharacterUpgradeLevelPrefix}{characterId}_{statType}";
|
||
|
return PlayerPrefs.GetInt(key, 0);
|
||
|
}
|
||
|
|
||
|
public static Dictionary<StatType, int> LoadAllCharacterUpgradeLevels(int characterId)
|
||
|
{
|
||
|
Dictionary<StatType, int> upgradeLevels = new Dictionary<StatType, int>();
|
||
|
|
||
|
foreach (StatType statType in System.Enum.GetValues(typeof(StatType)))
|
||
|
{
|
||
|
upgradeLevels[statType] = LoadCharacterUpgradeLevel(characterId, statType);
|
||
|
}
|
||
|
|
||
|
return upgradeLevels;
|
||
|
}
|
||
|
|
||
|
public static void ResetCharacterUpgrades(int characterId)
|
||
|
{
|
||
|
foreach (StatType statType in System.Enum.GetValues(typeof(StatType)))
|
||
|
{
|
||
|
string key = $"{CharacterUpgradeLevelPrefix}{characterId}_{statType}";
|
||
|
if (PlayerPrefs.HasKey(key))
|
||
|
{
|
||
|
PlayerPrefs.DeleteKey(key);
|
||
|
}
|
||
|
}
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
/// <summary>
|
||
|
/// Clears the unlocked maps in PlayerPrefs.
|
||
|
/// </summary>
|
||
|
public static void ClearUnlockedMaps()
|
||
|
{
|
||
|
PlayerPrefs.DeleteKey(UnlockedMapsKey);
|
||
|
PlayerPrefs.Save();
|
||
|
Debug.Log("Local unlocked maps have been cleared.");
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets the unlocked maps in PlayerPrefs and optionally saves them to the database if initialized.
|
||
|
/// </summary>
|
||
|
/// <param name="unlockedMapIds">A list of map IDs that are unlocked.</param>
|
||
|
public static void SetUnlockedMaps(List<int> unlockedMapIds)
|
||
|
{
|
||
|
string mapIdsString = string.Join(",", unlockedMapIds);
|
||
|
PlayerPrefs.SetString(UnlockedMapsKey, mapIdsString);
|
||
|
PlayerPrefs.Save();
|
||
|
|
||
|
if (BackendManager.Singleton.CheckInitialized())
|
||
|
{
|
||
|
BackendManager.Singleton.SaveUnlockedMapsAsync().ContinueWith(task =>
|
||
|
{
|
||
|
if (task.IsFaulted)
|
||
|
{
|
||
|
Debug.LogError("Failed to save unlocked maps to backend: " + task.Exception);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the unlocked maps from PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <returns>A list of map IDs that are unlocked.</returns>
|
||
|
public static List<int> GetUnlockedMaps()
|
||
|
{
|
||
|
string mapIdsString = PlayerPrefs.GetString(UnlockedMapsKey, "");
|
||
|
if (string.IsNullOrEmpty(mapIdsString))
|
||
|
{
|
||
|
return new List<int>();
|
||
|
}
|
||
|
string[] mapIdsArray = mapIdsString.Split(',');
|
||
|
List<int> unlockedMapIds = new List<int>();
|
||
|
foreach (string id in mapIdsArray)
|
||
|
{
|
||
|
if (int.TryParse(id, out int mapId))
|
||
|
{
|
||
|
unlockedMapIds.Add(mapId);
|
||
|
}
|
||
|
}
|
||
|
return unlockedMapIds;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the progress of a quest both locally and in backend if initialized.
|
||
|
/// </summary>
|
||
|
/// <param name="questId">The ID of the quest.</param>
|
||
|
/// <param name="progress">The progress value to save.</param>
|
||
|
public static void SaveQuestProgress(int questId, int progress)
|
||
|
{
|
||
|
// Save the quest progress locally
|
||
|
PlayerPrefs.SetInt($"{QuestProgressPrefix}{questId}", progress);
|
||
|
PlayerPrefs.Save();
|
||
|
|
||
|
if (BackendManager.Singleton.CheckInitialized())
|
||
|
{
|
||
|
BackendManager.Singleton.StartCoroutine(SaveQuestProgressToBackendCoroutine(questId, progress));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Coroutine to save quest progress to Backend.
|
||
|
/// </summary>
|
||
|
/// <param name="questId">The ID of the quest.</param>
|
||
|
/// <param name="progress">The progress value to save.</param>
|
||
|
/// <returns>IEnumerator for coroutine execution.</returns>
|
||
|
private static IEnumerator SaveQuestProgressToBackendCoroutine(int questId, int progress)
|
||
|
{
|
||
|
var task = BackendManager.Singleton.SaveQuestProgressAsync(questId, progress);
|
||
|
yield return new WaitUntil(() => task.IsCompleted);
|
||
|
|
||
|
if (task.Exception != null)
|
||
|
{
|
||
|
Debug.LogError($"Failed to save quest progress for {questId}: {task.Exception}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Loads the progress of a quest.
|
||
|
/// </summary>
|
||
|
/// <param name="questId">The ID of the quest.</param>
|
||
|
/// <returns>The saved progress value.</returns>
|
||
|
public static int LoadQuestProgress(int questId)
|
||
|
{
|
||
|
return PlayerPrefs.GetInt($"{QuestProgressPrefix}{questId}", 0); // Default to 0 if not set
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the completion status of a quest both locally and in Backend if initialized.
|
||
|
/// </summary>
|
||
|
/// <param name="questId">The ID of the quest.</param>
|
||
|
public static void SaveQuestCompletion(int questId)
|
||
|
{
|
||
|
// Save the quest completion status locally
|
||
|
PlayerPrefs.SetInt($"{QuestCompletionPrefix}{questId}", 1);
|
||
|
PlayerPrefs.Save();
|
||
|
|
||
|
if (BackendManager.Singleton.CheckInitialized())
|
||
|
{
|
||
|
BackendManager.Singleton.StartCoroutine(SaveQuestCompletionToBackendCoroutine(questId));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Coroutine to save quest completion to Backend.
|
||
|
/// </summary>
|
||
|
/// <param name="questId">The ID of the quest.</param>
|
||
|
/// <returns>IEnumerator for coroutine execution.</returns>
|
||
|
private static IEnumerator SaveQuestCompletionToBackendCoroutine(int questId)
|
||
|
{
|
||
|
var task = BackendManager.Singleton.SaveQuestCompletionAsync(questId);
|
||
|
yield return new WaitUntil(() => task.IsCompleted);
|
||
|
|
||
|
if (task.Exception != null)
|
||
|
{
|
||
|
Debug.LogError($"Failed to save quest completion for {questId}: {task.Exception}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Checks if a quest is completed.
|
||
|
/// </summary>
|
||
|
/// <param name="questId">The ID of the quest.</param>
|
||
|
/// <returns>True if the quest is completed, false otherwise.</returns>
|
||
|
public static bool IsQuestCompleted(int questId)
|
||
|
{
|
||
|
return PlayerPrefs.GetInt($"{QuestCompletionPrefix}{questId}", 0) == 1;
|
||
|
}
|
||
|
/// <summary>
|
||
|
/// Clears the local progress and completion status of daily quests stored in PlayerPrefs.
|
||
|
/// </summary>
|
||
|
public static void ClearLocalDayleQuestProgress()
|
||
|
{
|
||
|
QuestItem[] quests = GameInstance.Singleton.questData;
|
||
|
foreach (var quest in quests)
|
||
|
{
|
||
|
if (quest.questType == QuestType.Daily)
|
||
|
{
|
||
|
// Clear progress for the daily quest
|
||
|
PlayerPrefs.DeleteKey($"{QuestProgressPrefix}{quest.questId}");
|
||
|
|
||
|
// Clear completion status for the daily quest
|
||
|
PlayerPrefs.DeleteKey($"{QuestCompletionPrefix}{quest.questId}");
|
||
|
}
|
||
|
}
|
||
|
PlayerPrefs.Save();
|
||
|
Debug.Log("Local daily quest progress and completion status cleared.");
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the completion time of a quest locally in PlayerPrefs using a provided server time.
|
||
|
/// </summary>
|
||
|
/// <param name="questId">The ID of the quest.</param>
|
||
|
/// <param name="completionTime">The completion time of the quest, provided by the server.</param>
|
||
|
public static void SaveQuestCompletionTime(int questId, DateTime completionTime)
|
||
|
{
|
||
|
string key = $"QUEST_COMPLETION_TIME_{questId}";
|
||
|
|
||
|
// Save the provided completion time as a string in the format "yyyy-MM-dd HH:mm:ss"
|
||
|
string formattedTime = completionTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||
|
|
||
|
PlayerPrefs.SetString(key, formattedTime);
|
||
|
PlayerPrefs.Save();
|
||
|
|
||
|
Debug.Log($"Quest {questId} completion time saved locally: {formattedTime}");
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Marks a coupon as used by saving its ID in PlayerPrefs and in the backend if initialized.
|
||
|
/// </summary>
|
||
|
/// <param name="couponId">The unique ID of the coupon.</param>
|
||
|
public static void MarkCouponAsUsed(string couponId)
|
||
|
{
|
||
|
List<string> usedCoupons = GetUsedCoupons();
|
||
|
if (!usedCoupons.Contains(couponId))
|
||
|
{
|
||
|
usedCoupons.Add(couponId);
|
||
|
SaveUsedCoupons(usedCoupons);
|
||
|
if (BackendManager.Singleton.CheckInitialized())
|
||
|
{
|
||
|
BackendManager.Singleton.StartCoroutine(SaveUsedCouponCoroutine(couponId));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Coroutine to save the used coupon via the BackendManager.
|
||
|
/// </summary>
|
||
|
/// <param name="couponId">The unique ID of the coupon.</param>
|
||
|
/// <returns>IEnumerator for coroutine execution.</returns>
|
||
|
private static IEnumerator SaveUsedCouponCoroutine(string couponId)
|
||
|
{
|
||
|
Task saveTask = BackendManager.Singleton.SaveUsedCouponAsync(couponId);
|
||
|
yield return new WaitUntil(() => saveTask.IsCompleted);
|
||
|
|
||
|
if (saveTask.Exception != null)
|
||
|
{
|
||
|
Debug.LogError($"Failed to save used coupon {couponId} via BackendManager: {saveTask.Exception}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Debug.Log($"Coupon {couponId} marked as used and saved via BackendManager successfully.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Checks if a coupon has already been used.
|
||
|
/// </summary>
|
||
|
/// <param name="couponId">The unique ID of the coupon.</param>
|
||
|
/// <returns>True if the coupon has been used, false otherwise.</returns>
|
||
|
public static bool IsCouponUsed(string couponId)
|
||
|
{
|
||
|
List<string> usedCoupons = GetUsedCoupons();
|
||
|
return usedCoupons.Contains(couponId);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the list of used coupons locally using PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <param name="usedCoupons">A list of used coupon IDs.</param>
|
||
|
public static void SaveUsedCoupons(List<string> usedCoupons)
|
||
|
{
|
||
|
string couponsString = string.Join(",", usedCoupons);
|
||
|
PlayerPrefs.SetString(UsedCouponsKey, couponsString);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Retrieves the list of used coupons from PlayerPrefs.
|
||
|
/// </summary>
|
||
|
/// <returns>A list of used coupon IDs.</returns>
|
||
|
public static List<string> GetUsedCoupons()
|
||
|
{
|
||
|
string couponsString = PlayerPrefs.GetString(UsedCouponsKey, string.Empty);
|
||
|
return new List<string>(couponsString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves daily rewards data locally in JSON form.
|
||
|
/// </summary>
|
||
|
public static void SetDailyRewardsLocal(DailyRewardsData data)
|
||
|
{
|
||
|
string json = JsonUtility.ToJson(data);
|
||
|
PlayerPrefs.SetString(DailyRewardsKey, json);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Retrieves the locally saved daily rewards data. Returns defaults if not found.
|
||
|
/// </summary>
|
||
|
public static DailyRewardsData GetDailyRewardsLocal()
|
||
|
{
|
||
|
if (!PlayerPrefs.HasKey(DailyRewardsKey))
|
||
|
{
|
||
|
return new DailyRewardsData();
|
||
|
}
|
||
|
string json = PlayerPrefs.GetString(DailyRewardsKey);
|
||
|
DailyRewardsData data = JsonUtility.FromJson<DailyRewardsData>(json);
|
||
|
return data ?? new DailyRewardsData();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves new player rewards data locally in JSON form.
|
||
|
/// </summary>
|
||
|
public static void SetNewPlayerRewardsLocal(NewPlayerRewardsData data)
|
||
|
{
|
||
|
string json = JsonUtility.ToJson(data);
|
||
|
PlayerPrefs.SetString(NewPlayerRewardsKey, json);
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Retrieves the locally saved new player rewards data. Returns defaults if not found.
|
||
|
/// </summary>
|
||
|
public static NewPlayerRewardsData GetNewPlayerRewardsLocal()
|
||
|
{
|
||
|
if (!PlayerPrefs.HasKey(NewPlayerRewardsKey))
|
||
|
{
|
||
|
return new NewPlayerRewardsData();
|
||
|
}
|
||
|
string json = PlayerPrefs.GetString(NewPlayerRewardsKey);
|
||
|
NewPlayerRewardsData data = JsonUtility.FromJson<NewPlayerRewardsData>(json);
|
||
|
return data ?? new NewPlayerRewardsData();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Saves the next daily reset DateTime as a string.
|
||
|
/// </summary>
|
||
|
public static void SetNextDailyReset(DateTime nextReset)
|
||
|
{
|
||
|
// Convert to ticks or string
|
||
|
long ticks = nextReset.Ticks;
|
||
|
PlayerPrefs.SetString(NextDailyResetKey, ticks.ToString());
|
||
|
PlayerPrefs.Save();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Retrieves the next daily reset DateTime.
|
||
|
/// </summary>
|
||
|
public static DateTime GetNextDailyReset()
|
||
|
{
|
||
|
if (!PlayerPrefs.HasKey(NextDailyResetKey))
|
||
|
return DateTime.MinValue;
|
||
|
|
||
|
string ticksString = PlayerPrefs.GetString(NextDailyResetKey);
|
||
|
if (long.TryParse(ticksString, out long ticks))
|
||
|
{
|
||
|
return new DateTime(ticks);
|
||
|
}
|
||
|
return DateTime.MinValue;
|
||
|
}
|
||
|
/// <summary>
|
||
|
/// Simple data structure to hold daily rewards info for local save.
|
||
|
/// </summary>
|
||
|
[Serializable]
|
||
|
public class DailyRewardsData
|
||
|
{
|
||
|
public DateTime firstClaimDate;
|
||
|
public List<int> claimedRewards = new List<int>();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Simple data structure to hold new player rewards info for local save.
|
||
|
/// </summary>
|
||
|
[Serializable]
|
||
|
public class NewPlayerRewardsData
|
||
|
{
|
||
|
public DateTime accountCreationDate;
|
||
|
public List<int> claimedRewards = new List<int>();
|
||
|
}
|
||
|
|
||
|
|
||
|
[Serializable]
|
||
|
private class UnlockedSkinsData
|
||
|
{
|
||
|
public List<int> unlockedSkins;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|