Files
bansonic_beta_main/Assets/Editor/PackagingBuildGuard.cs
T

161 lines
5.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Text;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
/// <summary>
/// 构建前防线:若随包发布的玩家进度数据(Player_SO / AllyHero_SO / SongData
/// 仍带有非零测试值,直接中断构建。
///
/// 目的:杜绝"忘记跑一键初始化 → 测试存档随安装包发布 → 玩家首启被灌入 999988
/// 金币等测试数据"的事故(这是历史上多次出现的存档污染根因)。
///
/// 只做只读校验,不改动任何资产;发现问题时抛出 BuildFailedException 并给出
/// 明确指引(跑 Tools/Packaging/一键初始化打包设置)。
/// </summary>
public sealed class PackagingBuildGuard : IPreprocessBuildWithReport
{
public int callbackOrder => 0;
public void OnPreprocessBuild(BuildReport report)
{
var problems = new List<string>();
CheckPlayers(problems);
CheckHeroes(problems);
CheckSongs(problems);
if (problems.Count == 0)
{
return;
}
var sb = new StringBuilder();
sb.AppendLine("检测到随包发布的玩家进度数据仍带测试值,已中断构建。");
sb.AppendLine("请先执行菜单:Tools/Packaging/一键初始化打包设置(恢复默认),再重新打包。");
sb.AppendLine();
sb.AppendLine("问题明细:");
int shown = 0;
foreach (var p in problems)
{
sb.AppendLine(" - " + p);
if (++shown >= 40)
{
sb.AppendLine(" - ...(其余 " + (problems.Count - shown) + " 项省略)");
break;
}
}
Debug.LogError("[PackagingBuildGuard]\n" + sb);
throw new BuildFailedException(sb.ToString());
}
private static void CheckPlayers(List<string> problems)
{
string[] intFields =
{
"player_coins", "player_material", "player_currentEXP", "player_currentLevel",
"commonExpBottle78001", "mediumExpBottle78002", "superiorExpBottle78003",
"supremeExpBottle78004", "extraordinaryExpBottle78005", "celestialExpBottle78006",
"dushMaterial78021", "dushMaterial78022", "dushMaterial78023", "dushMaterial78024",
};
foreach (var guid in AssetDatabase.FindAssets("t:Player_SO"))
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var so = AssetDatabase.LoadAssetAtPath<Player_SO>(path);
if (so == null) continue;
var s = new SerializedObject(so);
foreach (var f in intFields)
{
var prop = s.FindProperty(f);
if (prop != null && prop.intValue != 0)
{
problems.Add(path + " :: " + f + " = " + prop.intValue);
}
}
var rank = s.FindProperty("uRankingScore");
if (rank != null && Mathf.Abs(rank.floatValue) > 0.0001f)
{
problems.Add(path + " :: uRankingScore = " + rank.floatValue);
}
}
}
private static void CheckHeroes(List<string> problems)
{
string[] intFields =
{
"ally_currentEXP", "ally_growthUnlockedTierIndex",
"ally_battleDeployCount", "ally_finishCount", "ally_mvpCount",
};
foreach (var guid in AssetDatabase.FindAssets("t:AllyHero_SO"))
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var so = AssetDatabase.LoadAssetAtPath<AllyHero_SO>(path);
if (so == null) continue;
var s = new SerializedObject(so);
foreach (var f in intFields)
{
var prop = s.FindProperty(f);
if (prop != null && prop.intValue != 0)
{
problems.Add(path + " :: " + f + " = " + prop.intValue);
}
}
var join = s.FindProperty("ally_joinDateUtcTicks");
if (join != null && join.longValue != 0L)
{
problems.Add(path + " :: ally_joinDateUtcTicks = " + join.longValue);
}
}
}
private static void CheckSongs(List<string> problems)
{
string[] recordFields =
{
"lastScoreForThisDifficulty", "chartPersonalRecordForThisDifficulty",
"idolPersonalRecordForThisDifficulty", "totalPersonalRecordForThisDifficulty",
};
foreach (var guid in AssetDatabase.FindAssets("t:SongData"))
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var so = AssetDatabase.LoadAssetAtPath<SongData>(path);
if (so == null) continue;
var s = new SerializedObject(so);
var enter = s.FindProperty("game_enterTimes");
if (enter != null && enter.intValue != 0)
{
problems.Add(path + " :: game_enterTimes = " + enter.intValue);
}
var chartFiles = s.FindProperty("chartFiles");
if (chartFiles != null && chartFiles.isArray)
{
for (int i = 0; i < chartFiles.arraySize; i++)
{
var entry = chartFiles.GetArrayElementAtIndex(i);
foreach (var f in recordFields)
{
var prop = entry.FindPropertyRelative(f);
if (prop != null && prop.intValue != 0)
{
problems.Add(path + " :: chartFiles[" + i + "]." + f + " = " + prop.intValue);
}
}
}
}
}
}
}
#endif