440 lines
14 KiB
C#
440 lines
14 KiB
C#
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;
|
||
}
|
||
} |