客户端rsa,冗余清理,bug修复,安卓build问题
This commit is contained in:
@@ -0,0 +1,396 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
public static class FirstRunFactoryResetService
|
||||
{
|
||||
private const string StoreStateLegacyPath = "storeSystem_state.json";
|
||||
// 明文"已初始化"标记:不依赖 deviceUniqueIdentifier / 加密,仅表示本机曾成功初始化过。
|
||||
// 用途见 TryPerformFactoryResetFallback:区分"真首启"与"存档存在但暂时读不出"。
|
||||
private const string InitializedMarkerFileName = ".bansonic_initialized";
|
||||
private static readonly int[] DefaultTeamHeroIds = { 30201, 30202, 30203, 30204, 30205 };
|
||||
private static bool executed;
|
||||
|
||||
private static string InitializedMarkerPath =>
|
||||
Path.Combine(Application.persistentDataPath, InitializedMarkerFileName);
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void Bootstrap()
|
||||
{
|
||||
TryPerformFactoryResetFallback();
|
||||
}
|
||||
|
||||
private static void TryPerformFactoryResetFallback()
|
||||
{
|
||||
if (executed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
executed = true;
|
||||
|
||||
if (HasAnyRecoverableLocalState())
|
||||
{
|
||||
// 有可恢复存档:补写标记(覆盖历史版本升级上来、尚无标记的老用户),不重置。
|
||||
EnsureInitializedMarker();
|
||||
return;
|
||||
}
|
||||
|
||||
// 走到这里说明"当前读不到任何可恢复存档"。必须区分两种情况:
|
||||
// A) 真正首次运行:应用出厂默认(全 0)并写标记 —— 安全。
|
||||
// B) 曾经玩过、但存档暂时读不出(典型:deviceUniqueIdentifier 变化致解密/验签失败):
|
||||
// 此时清零 = 数据丢失灾难。宁可保留现状等待其它恢复路径,也绝不主动抹除。
|
||||
if (HasInitializedMarker())
|
||||
{
|
||||
Debug.LogWarning("[FactoryReset] 检测到已初始化标记,但当前读不到任何存档。" +
|
||||
"为避免误删既有(暂不可读)玩家数据,跳过出厂重置。");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.LogWarning("[FactoryReset] 首次运行且无可恢复存档,应用出厂默认设置。");
|
||||
ApplyFactoryReset();
|
||||
EnsureInitializedMarker();
|
||||
}
|
||||
|
||||
private static bool HasInitializedMarker()
|
||||
{
|
||||
try
|
||||
{
|
||||
return File.Exists(InitializedMarkerPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning("[FactoryReset] 读取初始化标记失败: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureInitializedMarker()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(InitializedMarkerPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
File.WriteAllText(InitializedMarkerPath, DateTime.UtcNow.ToString("o"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning("[FactoryReset] 写入初始化标记失败: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasAnyRecoverableLocalState()
|
||||
{
|
||||
if (PlayerEconomyStorage.HasAnyRecoverableState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SecureSaveVault.HasAnyRecoverableState("player_experience", "runtime", Path.Combine(Application.persistentDataPath, "player_experience.json")))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (AllyHeroDeployLedgerStorage.HasAnyRecoverableState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ExpBottleLedgerStorage.HasAnyRecoverableState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DushMaterialLedgerStorage.HasAnyRecoverableState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (EquipmentConsumableLedgerStorage.HasAnyRecoverableState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (StoreOwnershipStorage.HasAnyRecoverableState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SecureSaveVault.HasAnyRecoverableState("player_rks", "overall"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SecureSaveVault.HasAnyRecoverableState("player_skills", "runtime"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SecureSaveVault.HasAnyRecoverableState("recent_play_history", "runs_v1"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SecureSaveVault.HasAnyRecoverableState("runtime_equipment", "generated_list"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DailyTaskSaveService.HasAnyRecoverableState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SecureSaveVault.HasAnyRecoverableState("store_state", "runtime", Path.Combine(Application.persistentDataPath, StoreStateLegacyPath)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (PlayerProgressBackupService.HasExistingBackupFile())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SongData[] songs = RuntimeResourcesCache.LoadAllSongs();
|
||||
if (songs != null)
|
||||
{
|
||||
for (int i = 0; i < songs.Length; i++)
|
||||
{
|
||||
SongData song = songs[i];
|
||||
if (song == null || song.songID <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string legacySongPath = Path.Combine(Application.persistentDataPath, $"SongData_{song.songID}.json");
|
||||
if (SecureSaveVault.HasAnyRecoverableState("song_runtime", song.songID.ToString(), legacySongPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ApplyFactoryReset()
|
||||
{
|
||||
ResetPlayerEconomyAndExperience();
|
||||
ResetHeroGrowthAndLoadout();
|
||||
ResetPlayerSkillAndRks();
|
||||
ResetSongProgressAndRecentHistory();
|
||||
ResetDailyTasks();
|
||||
ResetStoreState();
|
||||
ResetGeneratedEquipment();
|
||||
ResetTeamSelection();
|
||||
ResetSettingsAndUserPrefs();
|
||||
ResetPlayerMirrorSo();
|
||||
ResetDlcOwnershipFlags();
|
||||
|
||||
RuntimeResourcesCache.InvalidateAll();
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
private static void ResetPlayerEconomyAndExperience()
|
||||
{
|
||||
Player_SO player = RuntimeResourcesCache.LoadDefaultPlayerSo();
|
||||
|
||||
PlayerEconomyLedger economyLedger = PlayerEconomyLedger.EnsureInstance();
|
||||
economyLedger.SetCoins(0);
|
||||
economyLedger.SetMaterial(0);
|
||||
|
||||
PlayerExperienceLedger experienceLedger = PlayerExperienceLedger.EnsureInstance();
|
||||
experienceLedger.SetExperience(0);
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
player.player_currentEXP = 0;
|
||||
player.SetCoins(0);
|
||||
player.SetMaterial(0);
|
||||
player.SetURankingScore(0f);
|
||||
player.SetLegacyExpBottleCount("commonExpBottle78001", 0);
|
||||
player.SetLegacyExpBottleCount("mediumExpBottle78002", 0);
|
||||
player.SetLegacyExpBottleCount("superiorExpBottle78003", 0);
|
||||
player.SetLegacyExpBottleCount("supremeExpBottle78004", 0);
|
||||
player.SetLegacyExpBottleCount("extraordinaryExpBottle78005", 0);
|
||||
player.SetLegacyExpBottleCount("celestialExpBottle78006", 0);
|
||||
player.SetLegacyDushMaterialCount("dushMaterial78021", 0);
|
||||
player.SetLegacyDushMaterialCount("dushMaterial78022", 0);
|
||||
player.SetLegacyDushMaterialCount("dushMaterial78023", 0);
|
||||
player.SetLegacyDushMaterialCount("dushMaterial78024", 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResetHeroGrowthAndLoadout()
|
||||
{
|
||||
AllyHeroDeployLedger.EnsureInstance().ResetGrowthProgressOnly();
|
||||
ExpBottleLedger.EnsureInstance().ResetAllToZero();
|
||||
DushMaterialLedger.EnsureInstance().ResetAllToZero();
|
||||
EquipmentConsumableLedger.EnsureInstance().ResetAllToZero();
|
||||
AllyHero_SO.ClearAllEquippedSkills();
|
||||
|
||||
AllyHero_SO[] heroes = RuntimeResourcesCache.LoadAllAllyHeroes();
|
||||
if (heroes == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < heroes.Length; i++)
|
||||
{
|
||||
AllyHero_SO hero = heroes[i];
|
||||
if (hero == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hero.ClearEquippedEquipment();
|
||||
hero.ClearSelectedSkin();
|
||||
hero.ally_currentEXP = 0;
|
||||
hero.ally_growthUnlockedTierIndex = 0;
|
||||
hero.level_lock = false;
|
||||
hero.ally_autoBreakthroughEnabled = false;
|
||||
hero.ally_battleDeployCount = 0;
|
||||
hero.ally_finishCount = 0;
|
||||
hero.ally_mvpCount = 0;
|
||||
hero.ally_joinDateUtcTicks = 0L;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResetPlayerSkillAndRks()
|
||||
{
|
||||
PlayerRksService.ClearPersistentState();
|
||||
PlayerSkillService.ResetToDefaultLevelOneSkill();
|
||||
}
|
||||
|
||||
private static void ResetSongProgressAndRecentHistory()
|
||||
{
|
||||
SongData[] songs = RuntimeResourcesCache.LoadAllSongs();
|
||||
if (songs != null)
|
||||
{
|
||||
for (int i = 0; i < songs.Length; i++)
|
||||
{
|
||||
if (songs[i] != null)
|
||||
{
|
||||
songs[i].ClearSaveDataAndReload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RecentPlayHistoryStore.Clear();
|
||||
}
|
||||
|
||||
private static void ResetDailyTasks()
|
||||
{
|
||||
DailyTaskService.EnsureInstance().ClearPersistentState();
|
||||
}
|
||||
|
||||
private static void ResetStoreState()
|
||||
{
|
||||
SecureSaveVault.Delete("store_state", "runtime", Path.Combine(Application.persistentDataPath, StoreStateLegacyPath));
|
||||
StoreOwnershipLedger.EnsureInstance().ClearPersistentState();
|
||||
PlayerProgressBackupService.ClearStoreOwnershipBackup();
|
||||
|
||||
storeItemSO[] storeItems = RuntimeResourcesCache.LoadAllStoreItems();
|
||||
if (storeItems == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < storeItems.Length; i++)
|
||||
{
|
||||
storeItemSO item = storeItems[i];
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
item.purchasedCount = 0;
|
||||
item.user_has_read = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResetGeneratedEquipment()
|
||||
{
|
||||
equipSmelt.ClearPersistentState();
|
||||
Bansonic.equipmentGenerator.ClearRuntimeGeneratedPersistence();
|
||||
PlayerPrefs.DeleteKey("bansonic_equipment_next_id_v1");
|
||||
}
|
||||
|
||||
private static void ResetTeamSelection()
|
||||
{
|
||||
for (int i = 0; i < DefaultTeamHeroIds.Length; i++)
|
||||
{
|
||||
int slot = i + 1;
|
||||
PlayerPrefs.SetInt($"selected_heroSlot0{slot}_heroID", DefaultTeamHeroIds[i]);
|
||||
PlayerPrefs.DeleteKey($"selected_heroSlot0{slot}_exp");
|
||||
}
|
||||
|
||||
PlayerPrefs.SetInt("SelectedMainHeroID", DefaultTeamHeroIds[0]);
|
||||
}
|
||||
|
||||
private static void ResetSettingsAndUserPrefs()
|
||||
{
|
||||
string[] keysToDelete =
|
||||
{
|
||||
"noteSpeedMultiplier",
|
||||
"UserGlobalDelaySeconds",
|
||||
"screenMode",
|
||||
"resolutionIndex",
|
||||
"customResW",
|
||||
"customResH",
|
||||
"frameRateIndex",
|
||||
"SuperResolution",
|
||||
"EnableGlobalMute",
|
||||
"Volume_Main",
|
||||
"Volume_NoteHit",
|
||||
"Volume_MusicInGame",
|
||||
"Volume_MusicOutGame",
|
||||
"Volume_UI",
|
||||
"EnableSyncNotePrefab",
|
||||
"bansonic_language_code",
|
||||
"global_chat_last_private_partner_id",
|
||||
"notebook.selected_category",
|
||||
"notebook.selected_father_id",
|
||||
"notebook.selected_son_id",
|
||||
"bansonic_online_enabled",
|
||||
"before_everything_agree_ranking",
|
||||
"before_everything_first_launch_completed",
|
||||
"before_everything_light_warning_accepted",
|
||||
"before_everything_user_info_accepted",
|
||||
"selected_song_last_entered_id",
|
||||
"song_select_skip_quick_enter_prompt"
|
||||
};
|
||||
|
||||
for (int i = 0; i < keysToDelete.Length; i++)
|
||||
{
|
||||
PlayerPrefs.DeleteKey(keysToDelete[i]);
|
||||
}
|
||||
|
||||
string[] keyBindingPrefixes = { "red", "green", "yellow", "purple", "blue" };
|
||||
for (int i = 0; i < keyBindingPrefixes.Length; i++)
|
||||
{
|
||||
PlayerPrefs.DeleteKey($"KeyBinding_{keyBindingPrefixes[i]}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResetPlayerMirrorSo()
|
||||
{
|
||||
Player_SO player = RuntimeResourcesCache.LoadDefaultPlayerSo();
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player.SetCurrentLevel(0);
|
||||
player.player_currentEXP = 0;
|
||||
}
|
||||
|
||||
private static void ResetDlcOwnershipFlags()
|
||||
{
|
||||
DlcOwnershipService.ClearLocalPersistence();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user