2025-06-13 14:59:58 -04:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
2025-07-26 04:20:25 -04:00
|
|
|
|
using Ichni.Menu;
|
2025-06-13 14:59:58 -04:00
|
|
|
|
using Ichni.RhythmGame;
|
|
|
|
|
|
using Ichni.Story;
|
|
|
|
|
|
using Sirenix.OdinInspector;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Ichni
|
|
|
|
|
|
{
|
|
|
|
|
|
public class GameSaveManager : SerializedMonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
public static GameSaveManager instance;
|
|
|
|
|
|
|
|
|
|
|
|
public SongSaveModule SongSaveModule;
|
|
|
|
|
|
public StorySaveModule StorySaveModule;
|
|
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (instance == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
instance = this;
|
|
|
|
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Destroy(gameObject);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-26 04:20:25 -04:00
|
|
|
|
|
|
|
|
|
|
private void Start()
|
|
|
|
|
|
{
|
|
|
|
|
|
SongSaveModule = new SongSaveModule();
|
|
|
|
|
|
SongSaveModule.LoadSongStatuses();
|
2025-08-11 14:04:06 -04:00
|
|
|
|
SongSaveModule.LoadStoryUnlockKeys();
|
2025-07-26 04:20:25 -04:00
|
|
|
|
|
|
|
|
|
|
StorySaveModule = new StorySaveModule();
|
2026-07-05 16:08:23 -04:00
|
|
|
|
StorySaveModule.LoadVariables();
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
2025-06-13 14:59:58 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public partial class SongSaveModule
|
|
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
public HashSet<string> storyUnlockKeys;
|
|
|
|
|
|
public HashSet<string> paymentUnlockKeys;
|
2025-06-13 14:59:58 -04:00
|
|
|
|
public Dictionary<string, SongStatusSave> songStatusSaves;
|
2025-08-11 14:04:06 -04:00
|
|
|
|
private string songSavePath => Application.persistentDataPath + "/GameSaves/SongSaves.json";
|
|
|
|
|
|
private string storyUnlockKeysPath => Application.persistentDataPath + "/GameSaves/UnlockKeys.json";
|
|
|
|
|
|
private string paymentUnlockKeysPath => Application.persistentDataPath + "/GameSaves/PaymentUnlockKeys.json";
|
2025-06-13 14:59:58 -04:00
|
|
|
|
public SongSaveModule()
|
|
|
|
|
|
{
|
|
|
|
|
|
songStatusSaves = new Dictionary<string, SongStatusSave>();
|
2025-08-11 14:04:06 -04:00
|
|
|
|
storyUnlockKeys = new HashSet<string>();
|
|
|
|
|
|
paymentUnlockKeys = new HashSet<string>();
|
|
|
|
|
|
//Debug.Log("Song save path: " + songSavePath);
|
2025-06-13 14:59:58 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public partial class SongSaveModule
|
|
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
public void SaveStoryUnlockKeys()
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
ES3.Save("UnlockKeys", storyUnlockKeys, storyUnlockKeysPath);
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-11 14:04:06 -04:00
|
|
|
|
public void LoadStoryUnlockKeys()
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
if (ES3.FileExists(storyUnlockKeysPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
storyUnlockKeys = ES3.Load<HashSet<string>>("UnlockKeys", storyUnlockKeysPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
storyUnlockKeys = new HashSet<string>();
|
|
|
|
|
|
SaveStoryUnlockKeys();
|
|
|
|
|
|
}
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-11 14:04:06 -04:00
|
|
|
|
public bool CheckStoryKey(string key)
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
return key == string.Empty || storyUnlockKeys.Contains(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void ClearStoryKeys()
|
|
|
|
|
|
{
|
|
|
|
|
|
storyUnlockKeys.Clear();
|
|
|
|
|
|
SaveStoryUnlockKeys();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public partial class SongSaveModule
|
|
|
|
|
|
{
|
|
|
|
|
|
public void SavePaymentUnlockKeys()
|
|
|
|
|
|
{
|
|
|
|
|
|
ES3.Save("UnlockKeys", paymentUnlockKeys, paymentUnlockKeysPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void LoadPaymentUnlockKeys()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ES3.FileExists(paymentUnlockKeysPath))
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
paymentUnlockKeys = ES3.Load<HashSet<string>>("UnlockKeys", paymentUnlockKeysPath);
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
paymentUnlockKeys = new HashSet<string>();
|
|
|
|
|
|
SavePaymentUnlockKeys();
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-11 14:04:06 -04:00
|
|
|
|
public bool CheckPaymentKey(string key)
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
return key == string.Empty || paymentUnlockKeys.Contains(key);
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-11 14:04:06 -04:00
|
|
|
|
public void ClearPaymentKeys()
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
paymentUnlockKeys.Clear();
|
|
|
|
|
|
SavePaymentUnlockKeys();
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public partial class SongSaveModule
|
|
|
|
|
|
{
|
|
|
|
|
|
private void InitializeSongStatuses()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (ChapterSelectionUnit chapter in ChapterSelectionManager.instance.chapters)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (SongItemData song in chapter.songs)
|
|
|
|
|
|
{
|
|
|
|
|
|
SongStatusSave songStatus = new SongStatusSave(false, string.Empty, new List<BeatmapSave>());
|
|
|
|
|
|
foreach (DifficultyData difficulty in song.difficultyDataList)
|
|
|
|
|
|
{
|
|
|
|
|
|
songStatus.beatmapSaves.Add(new BeatmapSave(0f,false, false));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
songStatusSaves.Add(song.songName, songStatus);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SaveSongStatuses();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void CheckSongStatuses()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (ChapterSelectionUnit chapter in ChapterSelectionManager.instance.chapters)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (SongItemData song in chapter.songs)
|
|
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
if (songStatusSaves.TryGetValue(song.songName, out SongStatusSave songStatus))
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
int difficultiesCount = song.difficultyDataList.Count;
|
|
|
|
|
|
if (songStatus.beatmapSaves.Count < difficultiesCount)
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
for (int i = songStatus.beatmapSaves.Count; i < difficultiesCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
songStatus.beatmapSaves.Add(new BeatmapSave(0f, false, false));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (songStatus.beatmapSaves.Count > difficultiesCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
songStatus.beatmapSaves.RemoveRange(difficultiesCount, songStatus.beatmapSaves.Count - difficultiesCount);
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-11 14:04:06 -04:00
|
|
|
|
else
|
2025-07-26 04:20:25 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
songStatus = new SongStatusSave(false, string.Empty, new List<BeatmapSave>());
|
|
|
|
|
|
foreach (DifficultyData difficulty in song.difficultyDataList)
|
|
|
|
|
|
{
|
|
|
|
|
|
songStatus.beatmapSaves.Add(new BeatmapSave(0f, false, false));
|
|
|
|
|
|
}
|
|
|
|
|
|
songStatusSaves.Add(song.songName, songStatus);
|
2025-07-26 04:20:25 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SaveSongStatuses();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-13 14:59:58 -04:00
|
|
|
|
[Button]
|
|
|
|
|
|
public void SaveSongStatuses()
|
|
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
ES3.Save("SongSaves", songStatusSaves, songSavePath);
|
2025-06-13 14:59:58 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void LoadSongStatuses()
|
|
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
if (ES3.FileExists(songSavePath))
|
2025-06-13 14:59:58 -04:00
|
|
|
|
{
|
2025-08-11 14:04:06 -04:00
|
|
|
|
songStatusSaves = ES3.Load<Dictionary<string, SongStatusSave>>("SongSaves", songSavePath);
|
2025-07-26 04:20:25 -04:00
|
|
|
|
CheckSongStatuses();
|
2025-06-13 14:59:58 -04:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-07-26 04:20:25 -04:00
|
|
|
|
InitializeSongStatuses();
|
2025-06-13 14:59:58 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Button]
|
|
|
|
|
|
public void ClearBeatmapRecords()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var songStatus in songStatusSaves.Values)
|
|
|
|
|
|
{
|
2025-07-26 04:20:25 -04:00
|
|
|
|
foreach (var beatmapSave in songStatus.beatmapSaves)
|
2025-06-13 14:59:58 -04:00
|
|
|
|
{
|
|
|
|
|
|
beatmapSave.accuracy = 0.0f;
|
|
|
|
|
|
beatmapSave.isFullCombo = false;
|
|
|
|
|
|
beatmapSave.isAllPerfect = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SaveSongStatuses();
|
|
|
|
|
|
}
|
2025-07-26 04:20:25 -04:00
|
|
|
|
|
|
|
|
|
|
public SongStatusSave GetSongStatusSave(string songName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (songStatusSaves.TryGetValue(songName, out SongStatusSave save))
|
|
|
|
|
|
{
|
|
|
|
|
|
return save;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Debug.LogWarning("Song status save for " + songName + " does not exist.");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2025-06-13 14:59:58 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-05 16:08:23 -04:00
|
|
|
|
// StorySaveModule 已迁移至 NewStorySystem/Save/StorySaveModule.cs(按章节存树/选项,全局存变量)
|
2025-06-13 14:59:58 -04:00
|
|
|
|
}
|