存档完善和修复
This commit is contained in:
@@ -71,7 +71,12 @@ namespace BaseGames.Core
|
||||
_onQuestStateChanged? .Subscribe(OnQuestStateChanged) .AddTo(_subs);
|
||||
}
|
||||
|
||||
private void OnDisable() => _subs.Clear();
|
||||
private void OnDisable()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
_onCooldown = false;
|
||||
_subs.Clear();
|
||||
}
|
||||
|
||||
// ── 触发处理 ───────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -66,7 +66,10 @@ namespace BaseGames.Core
|
||||
Debug.LogWarning("[GameServiceRegistrar] ⚠ _eventChannelRegistry 未绑定,IEventChannelRegistry 未注册。", this);
|
||||
|
||||
if (_saveManager)
|
||||
{
|
||||
_saveManager.Initialize(new BaseGames.Core.Save.LocalFileStorage());
|
||||
ServiceLocator.Register<ISaveService>(new SaveServiceAdapter(_saveManager));
|
||||
}
|
||||
else
|
||||
Debug.LogWarning("[GameServiceRegistrar] ⚠ _saveManager 未绑定,ISaveService 未注册。", this);
|
||||
|
||||
@@ -228,5 +231,6 @@ namespace BaseGames.Core
|
||||
public void SetFlag(string flagId, bool value) => _save.SetFlag(flagId, value);
|
||||
public System.Collections.Generic.IEnumerable<string> GetCompletedChains() => _save.GetCompletedChains();
|
||||
public void SetChainCompleted(string chainId) => _save.SetChainCompleted(chainId);
|
||||
public void MarkBossDefeated(string bossId) => _save.MarkBossDefeated(bossId);
|
||||
}
|
||||
}
|
||||
|
||||
12
Assets/_Game/Scripts/Core/ILingZhuProvider.cs
Normal file
12
Assets/_Game/Scripts/Core/ILingZhuProvider.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace BaseGames.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 提供当前玩家灵珠数量的只读接口。
|
||||
/// 置于 BaseGames.Core 程序集,使 World 程序集中的组件(如 DeathShadeManager)
|
||||
/// 无需直接引用 BaseGames.Player 程序集即可读取灵珠值。
|
||||
/// </summary>
|
||||
public interface ILingZhuProvider
|
||||
{
|
||||
int CurrentLingZhu { get; }
|
||||
}
|
||||
}
|
||||
@@ -73,5 +73,8 @@ namespace BaseGames.Core
|
||||
|
||||
/// <summary>标记某条事件链已完成。</summary>
|
||||
void SetChainCompleted(string chainId);
|
||||
|
||||
/// <summary>标记某个 Boss 已被击败,立即写入当前 SaveData(无需等待下次存档)。</summary>
|
||||
void MarkBossDefeated(string bossId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace BaseGames.Core.Save
|
||||
private void Update()
|
||||
{
|
||||
if (!_gameplayActive || _saveManager == null) return;
|
||||
_timer += Time.deltaTime;
|
||||
_timer += Time.unscaledDeltaTime;
|
||||
if (_timer >= _intervalSeconds)
|
||||
{
|
||||
_timer = 0f;
|
||||
|
||||
@@ -39,8 +39,15 @@ namespace BaseGames.Core.Save
|
||||
if (_instance != null) { Destroy(gameObject); return; }
|
||||
_instance = this;
|
||||
ServiceLocator.Register<ISaveableRegistry>(this);
|
||||
}
|
||||
|
||||
_storage = new LocalFileStorage();
|
||||
/// <summary>
|
||||
/// 注入存储后端。由 GameServiceRegistrar.Awake 在注册服务后立即调用。
|
||||
/// 允许在测试环境替换为 InMemoryStorage 等替代实现。
|
||||
/// </summary>
|
||||
public void Initialize(ISaveStorage storage)
|
||||
{
|
||||
_storage = storage;
|
||||
}
|
||||
|
||||
// ── ISaveable 注册 ────────────────────────────────────────────────────
|
||||
@@ -105,8 +112,12 @@ namespace BaseGames.Core.Save
|
||||
|
||||
if (!ValidateChecksum(loaded, json))
|
||||
{
|
||||
if (loaded.Meta.IsSteelSoul)
|
||||
{
|
||||
Debug.LogError("[SaveManager] 钢铁之魂存档 checksum 校验失败,拒绝加载以防止作弊。");
|
||||
return false;
|
||||
}
|
||||
Debug.LogWarning("[SaveManager] 存档 checksum 校验失败。");
|
||||
// 非 SteelSoul 模式仍允许加载(只是警告)
|
||||
}
|
||||
|
||||
loaded = SaveMigrator.Migrate(loaded);
|
||||
@@ -179,6 +190,13 @@ namespace BaseGames.Core.Save
|
||||
public bool IsBossDefeated(string bossId)
|
||||
=> _current?.World.DefeatedBossIds.Contains(bossId) == true;
|
||||
|
||||
public void MarkBossDefeated(string bossId)
|
||||
{
|
||||
_current ??= new SaveData();
|
||||
if (!_current.World.DefeatedBossIds.Contains(bossId))
|
||||
_current.World.DefeatedBossIds.Add(bossId);
|
||||
}
|
||||
|
||||
// ── 存档槽摘要 ────────────────────────────────────────────────────────
|
||||
public async Task<SlotSummary> GetSlotSummaryAsync(int slotIndex)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace BaseGames.Core.Save
|
||||
[Serializable]
|
||||
public class PlayerSaveData
|
||||
{
|
||||
public float PosX, PosY;
|
||||
public string Scene;
|
||||
public int CurrentHP, MaxHP;
|
||||
public int CurrentLingZhu, LifetimeLingZhu;
|
||||
@@ -97,7 +96,6 @@ namespace BaseGames.Core.Save
|
||||
public List<string> DefeatedBossIds = new();
|
||||
public List<string> CollectedIds = new();
|
||||
public List<string> DestroyedObjectIds = new();
|
||||
public Dictionary<string, bool> Switches = new();
|
||||
public Dictionary<string, int> NpcRelations = new();
|
||||
public HashSet<string> ChallengeFirstClears = new();
|
||||
}
|
||||
@@ -106,9 +104,9 @@ namespace BaseGames.Core.Save
|
||||
[Serializable]
|
||||
public class MapSaveData
|
||||
{
|
||||
public List<string> ExploredRooms = new(); // 踏入过的房间 ID
|
||||
public List<string> MappedRooms = new(); // 完整地图信息(购买/存档点揭示)
|
||||
public List<MapPin> Pins = new(); // 玩家自定义地图标记
|
||||
public HashSet<string> ExploredRooms = new(); // 踏入过的房间 ID
|
||||
public HashSet<string> MappedRooms = new(); // 完整地图信息(购买/存档点揭示)
|
||||
public List<MapPin> Pins = new(); // 玩家自定义地图标记
|
||||
}
|
||||
|
||||
/// <summary>玩家在地图上放置的自定义标记(架构 15_MapShopModule §1.5)。</summary>
|
||||
@@ -171,7 +169,6 @@ namespace BaseGames.Core.Save
|
||||
public int LingZhuEarned, LingZhuLost;
|
||||
public float DistanceTraveled;
|
||||
public float SpeedrunTime;
|
||||
public int SaveCount;
|
||||
public Dictionary<string, int> SkillUseCounts = new();
|
||||
public Dictionary<string, int> DeathsByBoss = new();
|
||||
}
|
||||
|
||||
@@ -26,10 +26,6 @@ namespace BaseGames.Core.Save
|
||||
data.ChallengeRooms ??= new ChallengeRoomsSaveData();
|
||||
data.NGPlus = null; // 非 NG+ 模式
|
||||
|
||||
// Player 子字段兼容(旧版本可能未记录 DeathShade)
|
||||
if (data.Player != null)
|
||||
data.Player.DeathShade ??= new DeathShadeSaveData();
|
||||
|
||||
Debug.Log($"[SaveMigrator] 从 '{v}' 迁移至 '2.0'。");
|
||||
v = "2.0";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user