Project_WL/Assets/WL/Island/WLIslandSave.cs

113 lines
6.6 KiB
C#

// ─────────────────────────────────────────────────────────────────────────────
// WLIslandSave.cs — 섬 세이브 파일 이름을 **경로와 무관하게 하나로** 고정한다.
//
// ■ 왜 필요한가 (Lead 실측 · 2026-09-13 · 816f 가 발견)
// `IslandManager.cs:119` 가 `saveFileName = SceneManager.GetActiveScene().name` 이라
// 같은 섬인데도 **들어온 경로에 따라 세이브가 갈린다**:
// · 섬 씬만 단독 Play → `Level01.dat`
// · 게임 정식 경로(로그인 → Load_Map → 섬이 Additive) → **`InGame.dat`**
// → 섬을 키워 놔도 다른 경로로 들어가면 초기 상태가 나온다.
//
// ■ PD 결정(2026-09-13): 「세이브가 경로마다 갈리면 안돼. 그냥 기존 세이브를
// 초기화하고 단일 경로로 맞춰」 → 이름을 하나로 고정한다.
//
// ■ 원본 수정은 `IslandManager.cs` **1줄**(그 대입문)뿐이다 — WL 하우스 규칙의
// 「1줄 훅 + 새 파일」 그대로. `enabled_ = 0` 이면 원래 동작(씬 이름)으로 돌아간다.
// ─────────────────────────────────────────────────────────────────────────────
using UnityEngine;
namespace WL.Island
{
// 🔴 `WLIslandSaveSettings`(ScriptableObject)는 **`WLIslandSaveSettings.cs` 로 분리**했다.
// 유니티는 SO 를 클래스 이름과 같은 이름의 .cs 파일에서만 MonoScript 로 인식한다 —
// 여기 있던 동안 `.asset` 의 `m_Script` 가 비어 세이브 단일화가 동작하지 않았다(816g 실측).
public static class WLIslandSave
{
/// <summary>
/// `IslandManager.Awake` 의 **기존 1줄 훅**이 부른다. 끄면 받은 값을 그대로 돌려준다.
///
/// 🔴 WL-816g — 이 호출은 `IslandManager.Awake` 안에서 `LoadGameData()` **바로 앞**에 있다
/// (`IslandManager.cs:119` vs `:120`). 그래서 「새 게임 시작 골드」와 「세이브 1회 초기화」를
/// 걸 수 있는 **유일한 시점**이다 — 덕분에 FI 원본에 새 줄을 한 줄도 넣지 않았다.
/// </summary>
public static string ResolveSaveName(string sceneName)
{
var cfg = WLIslandSaveSettings.Get();
string resolved = sceneName;
if (cfg != null && cfg.enabled_ != 0 && !string.IsNullOrEmpty(cfg.saveName))
{
resolved = cfg.saveName;
if (cfg.verboseLog != 0)
Debug.Log("[WL-816] 섬 세이브 이름 '" + sceneName + "' → '" + resolved + "' (경로 무관 고정)");
}
WLIslandStart.Prepare(resolved);
return resolved;
}
}
/// <summary>
/// 새 게임의 시작 상태(WL-816g §3) — **시작 골드 10** + 필요하면 세이브 1회 초기화.
/// FI 기본 시작 골드는 500 이다(`IslandManager.cs:30` `startingMoney`).
/// </summary>
public static class WLIslandStart
{
public static int LastStartCoin = -1;
public static bool DidReset;
public static string LastLog = "";
const string kTokenKey = "WL_Island_SaveToken";
static System.Reflection.FieldInfo s_startingMoney;
static bool s_resetDoneThisRun; // 2026-09-15 PD — 실행(Play) 1회당 1번만 초기화
/// <summary>`IslandManager.Awake` 안(= `LoadGameData()` 직전)에서 단 한 번 불린다.</summary>
public static void Prepare(string saveName)
{
var cfg = WLIslandSettings.Instance;
if (cfg == null || cfg.enabled_ == 0 || cfg.gateFlowEnabled == 0) return;
// ① 세이브 초기화 — 토큰이 바뀌었을 때(1회) · 또는 `resetSaveEveryStart` 면 **게임 시작마다**(실행 1회당 1번 ·
// 던전에서 섬으로 돌아올 때는 아님 · 2026-09-15 PD 「내가 얘기하기 전까지 매번 초기화 상태에서 시작」)
bool everyStart = cfg.resetSaveEveryStart != 0 && !s_resetDoneThisRun;
if (everyStart ||
(!string.IsNullOrEmpty(cfg.saveResetToken) &&
PlayerPrefs.GetString(kTokenKey, "") != cfg.saveResetToken))
{
s_resetDoneThisRun = true;
try
{
string path = Application.persistentDataPath + "/" + saveName + ".dat";
if (System.IO.File.Exists(path)) { System.IO.File.Delete(path); DidReset = true; }
}
catch (System.Exception ex) { Debug.LogWarning("[WL-816g] 세이브 초기화 실패 — " + ex.Message); }
PlayerPrefs.SetString(kTokenKey, cfg.saveResetToken);
PlayerPrefs.SetInt(cfg.dungeonUnlockPrefsKey, 0); // 해금한 던전도 0 개로
// WL-816zc — 초기 플로우 단계·확장 개방도 같이 0 으로(시작마다 초기화 대상)
if (!string.IsNullOrEmpty(cfg.flowStepPrefsKey)) PlayerPrefs.SetInt(cfg.flowStepPrefsKey, 0);
if (!string.IsNullOrEmpty(cfg.expansionUnlockPrefsKey)) PlayerPrefs.SetInt(cfg.expansionUnlockPrefsKey, 0);
WLIslandExpansionGate.ClearSpotMemory(); // 2026-09-17 — 확장 가격판 자리 기억도 세이브와 함께 초기화
PlayerPrefs.Save();
WLIslandBridge.ClearPending(); // 보류 보상도 비운다(정적 값까지)
}
// ② 시작 골드 — `startingMoney` 는 `data == null`(세이브 없음)일 때만 쓰인다(IslandManager.cs:397)
if (cfg.applyStartCoin == 0) return;
var mgr = CryingSnow.FarmingIsland.IslandManager.Instance;
if (mgr == null) return;
if (s_startingMoney == null)
s_startingMoney = typeof(CryingSnow.FarmingIsland.IslandManager).GetField("startingMoney",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (s_startingMoney == null) return;
s_startingMoney.SetValue(mgr, cfg.startCoin);
LastStartCoin = cfg.startCoin;
LastLog = "시작 골드 500 → " + cfg.startCoin + (DidReset ? " · 세이브 초기화함" : " · 기존 세이브 유지");
if (cfg.verboseLog != 0) Debug.Log("[WL-816g] " + LastLog);
}
}
}