446 lines
14 KiB
C#
446 lines
14 KiB
C#
/*
|
||
* @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;
|
||
}
|
||
}
|
||
|
||
} |