2025-06-26 20:11:17 +08:00

446 lines
14 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.

/*
* @Author: 白哉
* @Description:
* @Date: 2025年04月03日 星期四 11:04:31
* @Modify:
*/
using System;
using System.Collections.Generic;
using TH1Renderer;
using UnityEngine;
namespace RuntimeData
{
[Serializable]
public class GridMapData : ISerializationCallbackReceiver
{
public List<GridData> GridList;
private Dictionary<uint, GridData> _posToGridDict;
private Dictionary<uint, GridData> _gridIdToGridDict;
private MapConfig _mapCfg;
public GridMapData()
{
GridList = new List<GridData>();
_posToGridDict = new Dictionary<uint, GridData>();
_gridIdToGridDict = new Dictionary<uint, GridData>();
}
public GridMapData(MapConfig mapCfg, MapIdGenerator idGenerator)
{
_mapCfg = mapCfg;
GridList = new List<GridData>();
_posToGridDict = new Dictionary<uint, GridData>();
_gridIdToGridDict = new Dictionary<uint, GridData>();
for (int x = 0; x < mapCfg.Width; x++)
{
for (int y = 0; y < mapCfg.Height; y++)
{
var gridData = new GridData(x, y, idGenerator);
GridList.Add(gridData);
_gridIdToGridDict[gridData.Id] = gridData;
_posToGridDict[gridData.Pos.PosId] = gridData;
}
}
}
public GridMapData(GridMapData copyData)
{
_mapCfg = copyData._mapCfg;
GridList = new List<GridData>();
_posToGridDict = new Dictionary<uint, GridData>();
_gridIdToGridDict = new Dictionary<uint, GridData>();
foreach (var grid in copyData.GridList)
{
var gridData = new GridData(grid);
GridList.Add(gridData);
_gridIdToGridDict[gridData.Id] = gridData;
_posToGridDict[gridData.Pos.PosId] = gridData;
}
}
public void DeepCopy(GridMapData copyData)
{
_mapCfg = copyData._mapCfg;
_posToGridDict.Clear();
_gridIdToGridDict.Clear();
for (int i = 0; i < copyData.GridList.Count; i++)
{
var copyGrid = copyData.GridList[i];
if (i >= GridList.Count)
{
var gridData = new GridData(copyGrid);
GridList.Add(gridData);
_gridIdToGridDict[gridData.Id] = gridData;
_posToGridDict[gridData.Pos.PosId] = gridData;
}
else
{
GridList[i].DeepCopy(copyGrid);
_gridIdToGridDict[GridList[i].Id] = GridList[i];
_posToGridDict[GridList[i].Pos.PosId] = GridList[i];
}
}
for (int i = GridList.Count - 1; i >= copyData.GridList.Count; i--)
{
_gridIdToGridDict.Remove(GridList[i].Id);
_posToGridDict.Remove(GridList[i].Pos.PosId);
GridList.RemoveAt(i);
}
}
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
_posToGridDict ??= new Dictionary<uint, GridData>();
_gridIdToGridDict ??= new Dictionary<uint, GridData>();
_posToGridDict.Clear();
_gridIdToGridDict.Clear();
foreach (var grid in GridList)
{
_gridIdToGridDict[grid.Id] = grid;
_posToGridDict[grid.Pos.PosId] = grid;
}
}
public void BindMapConfig(MapConfig cfg)
{
_mapCfg = cfg;
}
public void OnTurnStart(MapData map)
{
foreach (var grid in GridList) grid.OnTurnStart(map);
}
public void OnTurnEnd(MapData map)
{
foreach (var grid in GridList) grid.OnTurnEnd(map);
}
// 通过 gid 获取格子数据
public bool GetGridDataByGid(uint gid, out GridData data)
{
return _gridIdToGridDict.TryGetValue(gid, out data);
}
// 通过坐标获取格子数据
public bool GetGridDataByPos(int x, int y, out GridData gridData)
{
return _posToGridDict.TryGetValue(MapPosition.CalculatePosId(x, y), out gridData);
}
public bool GetGridDataByVector3Pos(Vector3 pos, out GridData gridData)
{
var p = Table.Instance.WorldToGrid(pos);
return _posToGridDict.TryGetValue(MapPosition.CalculatePosId(p.x, p.y), out gridData);
}
// 获取目标周围的所有格子
public List<GridData> GetAroundGridData(int xOffset, int yOffset, GridData gridData)
{
List<GridData> gridDataList = new List<GridData>();
for (int x = gridData.Pos.X - xOffset; x <= gridData.Pos.X + xOffset; x++)
{
for (int y = gridData.Pos.Y - yOffset; y <= gridData.Pos.Y + yOffset; y++)
{
if (!GetGridDataByPos(x, y, out var aroundGridData)) continue;
gridDataList.Add(aroundGridData);
}
}
return gridDataList;
}
// 获取目标周围的所有格子
public HashSet<GridData> GetAroundGridDataSet(int xOffset, int yOffset, GridData gridData)
{
HashSet<GridData> gridDataSet = new HashSet<GridData>();
for (int x = gridData.Pos.X - xOffset; x <= gridData.Pos.X + xOffset; x++)
{
for (int y = gridData.Pos.Y - yOffset; y <= gridData.Pos.Y + yOffset; y++)
{
if (!GetGridDataByPos(x, y, out var aroundGridData)) continue;
if (x == gridData.Pos.X && y == gridData.Pos.Y) continue;
gridDataSet.Add(aroundGridData);
}
}
return gridDataSet;
}
public List<uint> GetAroundGridIdList(int radius, GridData gridData, bool remainCenter = false)
{
List<uint> gridIdList = new List<uint>();
for (int x = gridData.Pos.X - radius; x <= gridData.Pos.X + radius; x++)
{
for (int y = gridData.Pos.Y - radius; y <= gridData.Pos.Y + radius; y++)
{
if (!GetGridDataByPos(x, y, out var aroundGridData)) continue;
if (!remainCenter && x == gridData.Pos.X && y == gridData.Pos.Y) continue;
gridIdList.Add(aroundGridData.Id);
}
}
return gridIdList;
}
// 获取周围某个格子
public bool GetUpGridData(GridData gridData, int xOffset, int yOffset, out GridData upGridData)
{
return GetGridDataByPos(gridData.Pos.X + xOffset, gridData.Pos.Y + yOffset, out upGridData);
}
// 判断是否在左右边界
public bool IsInLeftOrRightBorder(GridData gridData)
{
return gridData.Pos.X == 0 || gridData.Pos.X == _mapCfg.Width - 1;
}
// 判断是否在上下边界
public bool IsInUpOrDownBorder(GridData gridData)
{
return gridData.Pos.Y == 0 || gridData.Pos.Y == _mapCfg.Height - 1;
}
//-------- 计算类方法 --------//
public int CalcDistance(GridData gridDataA, GridData gridDataB)
{
return Mathf.Max(Mathf.Abs(gridDataA.Pos.X - gridDataB.Pos.X),Mathf.Abs(gridDataA.Pos.Y - gridDataB.Pos.Y));
}
public void RefreshConnectInfo()
{
}
}
public class GridVFXRenderMark
{
//1play 0stop
public GridVFXType Type;
public bool PlayOrStop;
public bool RenderMark;
public uint CivId;
public int Damage;
public GridVFXRenderMark(GridVFXType gridVFXType,bool renderMark = true, bool playOrStop = true)
{
Type = gridVFXType;
RenderMark = renderMark;
PlayOrStop = playOrStop;
}
public void CopyFrom(GridVFXRenderMark other)
{
if (other == null) return;
Type = other.Type;
PlayOrStop = other.PlayOrStop;
RenderMark = other.RenderMark;
CivId = other.CivId;
Damage = other.Damage;
}
}
// 每个格子包含5个层次的信息
[Serializable]
public class GridData : IdentifierBase
{
//-------- BaseData ---------//
// 位置信息
public MapPosition Pos;
public bool CityBuildingRenderMark = false;
// 海陆层
public TerrainType Terrain;
// 地形层
public TerrainFeature Feature;
// 植被层
public Vegetation Vegetation;
// 资源层+建筑层
public ResourceType Resource;
public WonderLibrary Wonder;
public ResourceType ResourceUnderBuilding;
// 文明层
public uint CivId;
//奇观Id
//建筑level-只对部分建筑生效
public int buildingLevel;
//-------- RenderData ---------//
//gridVFX相关的RenderMark
public bool VFXRenderMarkHurt = false;
public bool VFXRenderMarkDie = false;
public bool VFXRenderMarkDieHintStart = false;
public int VFXRenderMarkDieHintStartParam = 0;
public bool VFXRenderMarkDieHintEnd = false;
public bool VFXRenderMarkTreasure = false;
public bool VFXRenderMarkHeal = false;
public bool VFXRenderMarkFlag = false;
public uint VFXRenderMarkFlagCivId = 0;
public bool VFXRenderMarkFog = false;
public bool VFXRenderMark = false;
public Dictionary<GridVFXType, GridVFXRenderMark> RenderMarkVFXDict;
//cityborder相关的RenderMark
public bool CityBorderRenderMark = false;
//用来设置vfxRenderMark, 单独做成一个方法是为了避免dict值为空的情况
public void SetGridVFXRenderMark(GridVFXRenderMark tmp)
{
if (RenderMarkVFXDict == null || !RenderMarkVFXDict.TryGetValue(tmp.Type, out var target))
{
InitRenderMark();
if (!RenderMarkVFXDict.TryGetValue(tmp.Type, out target))
return;
}
target.CopyFrom(tmp);
}
public void InitRenderMark()
{
RenderMarkVFXDict = new Dictionary<GridVFXType,GridVFXRenderMark>();
foreach(GridVFXType type in Enum.GetValues(typeof(GridVFXType)))
RenderMarkVFXDict[type] = new GridVFXRenderMark(type,false);
}
public GridData(int x, int y,MapIdGenerator mapIdGenerator)
{
Pos = new MapPosition(x,y);
Id = mapIdGenerator.GeneratorId();
}
//仅用于AI计算data不需要render的部分
public GridData(GridData copyData)
{
Pos = new MapPosition(copyData.Pos.X, copyData.Pos.Y);
Id = copyData.Id;
Terrain = copyData.Terrain;
Feature = copyData.Feature;
Vegetation = copyData.Vegetation;
Resource = copyData.Resource;
ResourceUnderBuilding = copyData.ResourceUnderBuilding;
CivId = copyData.CivId;
Wonder = copyData.Wonder;
buildingLevel = copyData.buildingLevel;
foreach (var skill in copyData.Skills) Skills.Add(skill.GetCopySkill());
}
public void DeepCopy(GridData copyData)
{
Pos.X = copyData.Pos.X;
Pos.Y = copyData.Pos.Y;
Id = copyData.Id;
Terrain = copyData.Terrain;
Feature = copyData.Feature;
Vegetation = copyData.Vegetation;
Resource = copyData.Resource;
ResourceUnderBuilding = copyData.ResourceUnderBuilding;
CivId = copyData.CivId;
Wonder = copyData.Wonder;
buildingLevel = copyData.buildingLevel;
foreach (var skill in copyData.Skills)
{
AddSkill(skill.GetSkillType());
if (!GetSkill(skill.GetSkillType(), out var selfSkill)) continue;
selfSkill.DeepCopy(skill);
}
for (int i = Skills.Count - 1; i >= 0; i--)
{
if (copyData.GetSkill(Skills[i].GetSkillType(), out _)) continue;
Skills.RemoveAt(i);
}
}
public void SetGridData(TerrainType ter,TerrainFeature fea,Vegetation veg, ResourceType res,uint civ)
{
Terrain = ter;
Feature = fea;
Vegetation = veg;
Resource = res;
ResourceUnderBuilding = ResourceType.None;
CivId = civ;
}
public bool IsRoadBridgePort()
{
return Feature == TerrainFeature.Road || Resource == ResourceType.Port || Resource == ResourceType.Bridge;
}
// 全局通知调用
public void OnTurnStart(MapData map)
{
for (int i = Skills.Count - 1; i >= 0; i--)
{
var skill = Skills[i];
if (skill.IsFinished())
{
Skills.RemoveAt(i);
continue;
}
skill.OnTurnStart(this, map);
}
}
public void OnTurnEnd(MapData map)
{
foreach (var skill in Skills) skill.OnTurnEnd(this, map);
}
}
// 位置基类
[Serializable]
public class MapPosition
{
public int X;
public int Y;
public uint PosId => CalculatePosId(X, Y);
public static uint CalculatePosId(int x, int y)
{
return (uint)(x * 1000 + y);
}
public MapPosition()
{
X = 0;
Y = 0;
}
public MapPosition(int x,int y)
{
X = x;
Y = y;
}
public void SetPosition(MapPosition pos)
{
X = pos.X;
Y = pos.Y;
}
}
}