NLDClient-yudde/ProjectNLD/Assets/Editor/LevelValidator/LevelValidator.cs

440 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using cfg;
using System.IO;
using Framework;
using System.Linq;
using UnityEditor;
using UnityEngine;
using cfg.LevelCfg;
using PhxhSDK.Phxh;
using Gameplay.Level;
using UnityEditor.SceneManagement;
public abstract class LevelValidatorBase
{
/// <summary>
/// 错误数据
/// </summary>
public bool ErrorData;
/// <summary>
/// 错误场景
/// </summary>
protected bool ErrorScene;
/// <summary>
/// 错误信息
/// </summary>
public string ErrorMessage;
/// <summary>
/// 警告信息
/// </summary>
public string WarningMessage;
protected LevelData LevelData;
protected MapData MapData;
protected readonly string LevelDataPath;
protected readonly string MapDataPath;
private readonly DataLevel levelCfg;
protected LevelValidatorBase(string levelDataPath, string mapDataPath)
{
LevelDataPath = levelDataPath;
MapDataPath = mapDataPath;
CheckWellResourced();
}
protected LevelValidatorBase(DataLevel levelCfg)
{
this.levelCfg = levelCfg;
LevelDataPath = levelCfg.LevelData;
MapDataPath = levelCfg.MapData;
CheckWellResourced();
CheckMapScene();
}
private void CheckMapScene()
{
if (levelCfg == null || string.IsNullOrEmpty(levelCfg.LevelScene) || !File.Exists(levelCfg.LevelScene))
{
ErrorScene = true;
AppendWithNewLine(ref ErrorMessage, "场景路径不存在,请检查资源");
return;
}
if (!File.Exists(GetPostScenePath()))
{
ErrorScene = true;
AppendWithNewLine(ref ErrorMessage, $"后处理场景不存在,请先后处理{levelCfg.LevelScene}");
}
}
private void CheckWellResourced()
{
if (string.IsNullOrEmpty(LevelDataPath) || string.IsNullOrEmpty(MapDataPath))
{
AppendWithNewLine(ref ErrorMessage, "地图或关卡数据为空,请检查配置表");
ErrorData = true;
return;
}
var levelPath = string.Format(Constants.LEVEL_CONFIG_FORMAT_PATH, LevelDataPath);
var mapPath = string.Format(Constants.MAP_CONFIG_FORMAT_PATH, MapDataPath);
var levelAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(levelPath);
var mapAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(mapPath);
if (levelAsset == null || mapAsset == null)
{
AppendWithNewLine(ref ErrorMessage, $"【地图数据路径:{MapDataPath} / 关卡数据路径:{LevelDataPath} 】加载失败,请检查本地是否有对应数据文件");
ErrorData = true;
return;
}
LevelData = JsonToData<LevelData>(levelAsset);
MapData = JsonToData<MapData>(mapAsset);
if (LevelData == null || MapData == null)
{
AppendWithNewLine(ref ErrorMessage, "无法正确转换关卡和地图数据");
ErrorData = true;
}
}
public abstract bool CheckData();
private T JsonToData<T>(TextAsset jsonText) where T : new()
{
if (jsonText != null)
{
var jsonStr = jsonText.text;
if (string.IsNullOrEmpty(jsonStr))
{
return new T();
}
else
{
var path = AssetDatabase.GetAssetPath(jsonText);
return JsonHelper.LoadJson<T>(path);
}
}
return default;
}
protected bool RegionIsLegal(int regionID)
{
return MapData.regions.Count > regionID;
}
/// <summary>
/// 后处理场景路径
/// </summary>
private string _postScenePath;
protected string GetPostScenePath()
{
if (ErrorScene) return null;
if (!string.IsNullOrEmpty(_postScenePath)) return _postScenePath;
var scenePath = levelCfg.LevelScene;
var postSceneDirectory = Path.GetFileNameWithoutExtension(scenePath.Replace("/", "_"));
var postScene = Path.GetFileNameWithoutExtension(scenePath) + "_PostProcess.unity";
_postScenePath = $"Assets/Art/AutoGen/PostProcessScenes/{postSceneDirectory}/{postScene}";
return _postScenePath;
}
protected void AppendWithNewLine(ref string original, string newString)
{
if (!string.IsNullOrEmpty(original))
{
original += "\n";
}
original += newString;
}
}
/// <summary>
/// 检查占领点是否合法
/// </summary>
public class CheckCaptureData : LevelValidatorBase
{
public CheckCaptureData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath)
{
}
public override bool CheckData()
{
if (ErrorData) return false;
if (MapData.capturePoints.Count > 0)
{
if (LevelData.captureProgress <= 0)
{
ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】有占领点,但无占领进度信息!";
return false;
}
}
return true;
}
}
/// <summary>
/// 检查扛旗点
/// </summary>
public class CheckFlagData : LevelValidatorBase
{
public CheckFlagData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath)
{
}
public override bool CheckData()
{
if (ErrorData) return false;
if (MapData.flagStartPoints.Count > 0)
{
DebugUtil.Log("有扛旗起点");
if (LevelData.flagTargetRegionId == 0 && RegionIsLegal(0))
{
WarningMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】有扛旗起点,扛旗终点区域为默认 0 ";
}
if (!RegionIsLegal(LevelData.flagTargetRegionId))
{
ErrorMessage =
$"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】有扛旗起点,扛旗终点区域【{LevelData.flagTargetRegionId}】不存在 ";
return false;
}
}
return true;
}
}
/// <summary>
/// 检查关卡区域设置
/// </summary>
public class CheckLevelRegionData : LevelValidatorBase
{
public CheckLevelRegionData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath)
{
}
public override bool CheckData()
{
if (ErrorData) return false;
if (!RegionIsLegal(LevelData.preparingRegionId))
{
ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】出战区【{LevelData.preparingRegionId}】错误,不存在 ";
return false;
}
if (!RegionIsLegal(LevelData.fallbackRegionId))
{
ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】撤退区【{LevelData.fallbackRegionId}】错误,不存在 ";
return false;
}
if (!RegionIsLegal(LevelData.enemyFallbackRegionId))
{
ErrorMessage =
$"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】敌方撤退区【{LevelData.enemyFallbackRegionId}】错误,不存在 ";
return false;
}
if (!RegionIsLegal(LevelData.pvpDefendRegionId))
{
ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】PVP防守区【{LevelData.pvpDefendRegionId}】错误,不存在 ";
return false;
}
if (LevelData.fallbackRegionId == LevelData.enemyFallbackRegionId)
{
WarningMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】敌人撤退区域和我方撤退区域相同 ";
}
return true;
}
}
/// <summary>
/// 检查护送相关设置
/// </summary>
public class CheckProtectData : LevelValidatorBase
{
public CheckProtectData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath)
{
}
public override bool CheckData()
{
if (ErrorData) return false;
string errorUnitIds = "";
if (LevelData.protectUnitInfos.Count > 0)
{
foreach (var protectUnit in LevelData.protectUnitInfos)
{
if (protectUnit.protectStartPoint == protectUnit.protectTargetPoint)
{
errorUnitIds = errorUnitIds + protectUnit.id + " ";
}
}
}
if (!string.IsNullOrEmpty(errorUnitIds))
{
ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】护送对象【{errorUnitIds}】的终点和起点相同";
}
return true;
}
}
/// <summary>
/// 检查是否存在后处理场景 及场景中是否有未删除的人物或载具模型
/// </summary>
public class CheckScenePostProcess : LevelValidatorBase
{
public CheckScenePostProcess(DataLevel levelCfg) : base(levelCfg)
{
}
public override bool CheckData()
{
if (ErrorData || ErrorScene) return false;
var postScenePath = GetPostScenePath();
var scene = EditorSceneManager.OpenScene(postScenePath, OpenSceneMode.Additive);
var rootObjects = scene.GetRootGameObjects();
if (rootObjects.Any(obj => obj.name.StartsWith("P_")))
{
EditorSceneManager.CloseScene(scene, true);
AppendWithNewLine(ref ErrorMessage, $"【地图: {postScenePath} 】后处理场景中有未删除的人物或载具模型");
return false;
}
EditorSceneManager.CloseScene(scene, true);
return true;
}
}
/// <summary>
/// 检查胜利胜败阶段条件
/// </summary>
public class CheckLevelCondition : LevelValidatorBase
{
public CheckLevelCondition(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath)
{
}
public override bool CheckData()
{
if (ErrorData) return false;
var stages = LevelData.stages;
if (stages is { Count: <= 0 })
{
AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中没有设置阶段信息");
return false;
}
foreach (var stage in stages)
{
if (stage.successCondition.conditionType == ConditionType.None)
{
AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中获胜目标为None");
return false;
}
if (stage.failConditions is { Count: <= 0 })
{
AppendWithNewLine(ref ErrorMessage, $"【【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中没有设置失败阶段");
return false;
}
if (stage.failConditions.Any(failCondition => failCondition.conditionType == ConditionType.None))
{
AppendWithNewLine(ref ErrorMessage, $"【【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中失败阶段目标为None");
return false;
}
}
return true;
}
}
/// <summary>
/// 检查若为星级关卡 参数是否正确
/// </summary>
public class CheckLevelStarTarget : LevelValidatorBase
{
public CheckLevelStarTarget(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath)
{
}
public override bool CheckData()
{
if (ErrorData) return false;
if (LevelData.scoreLevel) return true;
var starTargets = LevelData.starTarget;
if (starTargets is { Count: <= 0 })
{
AppendWithNewLine(ref ErrorMessage, $"【【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】为星级关卡,但未设置星级目标");
return false;
}
if (starTargets.Any(startTarget => startTarget.conditionType == ConditionType.None))
{
AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中有星级目标条件为None");
return false;
}
return true;
}
}
/// <summary>
/// 检查若为评分关卡 参数是否正确
/// </summary>
public class CheckLevelScoreTarget : LevelValidatorBase
{
public CheckLevelScoreTarget(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath)
{
}
public override bool CheckData()
{
if (ErrorData) return false;
if (!LevelData.scoreLevel) return true;
var scoreTargets = LevelData.scoreTarget;
if (scoreTargets is { Count: <= 0 })
{
AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】为评分关卡,但未设置评分目标");
return false;
}
foreach (var scoreTarget in scoreTargets)
{
if (scoreTarget.conditionType == ConditionType.None)
{
AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中有评分目标条件为None");
return false;
}
if (scoreTarget.score <= 0)
{
AppendWithNewLine(ref ErrorMessage,
$"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中评分目标【{scoreTarget.conditionType}】的分数为 0");
return false;
}
}
return true;
}
}