902 lines
34 KiB
C#
902 lines
34 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description:
|
||
* @Date: 2025年04月03日 星期四 11:04:31
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using Logic.Action;
|
||
using Logic.AI;
|
||
using UnityEngine;
|
||
|
||
namespace RuntimeData
|
||
{
|
||
// 一场游戏的设置数据
|
||
[Serializable]
|
||
public class MapConfig
|
||
{
|
||
public uint Width;
|
||
public uint Height;
|
||
public uint PlayerCount;
|
||
public AIDifficult AIDiff;
|
||
|
||
public uint selfCivId;
|
||
public uint selfForceId;
|
||
public MapConfig(uint width, uint height, uint playerCount,uint civId, uint forceId, AIDifficult aiDiff = AIDifficult.Normal)
|
||
{
|
||
Width = width;
|
||
Height = height;
|
||
PlayerCount = playerCount;
|
||
AIDiff = aiDiff;
|
||
selfCivId = civId;
|
||
selfForceId = forceId;
|
||
}
|
||
}
|
||
|
||
|
||
// 一场游戏的地图数据
|
||
[Serializable]
|
||
public class MapData : ISerializationCallbackReceiver
|
||
{
|
||
//--------------- 基础核心数据 ---------------//
|
||
// 地图 ID
|
||
public uint MapID;
|
||
// 地图配置数据
|
||
public MapConfig MapConfig;
|
||
// 地块数据
|
||
public GridMapData GridMap;
|
||
// 玩家数据
|
||
public PlayerMapData PlayerMap;
|
||
// 城市数据
|
||
public CityMapData CityMap;
|
||
// 小兵数据
|
||
public UnitMapData UnitMap;
|
||
// 城市 -> 玩家, 将引用关系转化为ID关系
|
||
public Dictionary<uint, uint> CityToPlayerDict;
|
||
// 小兵 -> 城市, 将引用关系转化为ID关系
|
||
public Dictionary<uint, uint> UnitToCityDict;
|
||
// 小兵 -> 格子, 将引用关系转化为ID关系
|
||
public Dictionary<uint, uint> UnitToGridDict;
|
||
// 城市 -> 格子, 将引用关系转化为ID关系
|
||
public Dictionary<uint, uint> CityToGridDict;
|
||
|
||
//--------------- 核心数据派生的数据 ---------------//
|
||
// 格子 -> 小兵, 缓存数据
|
||
private Dictionary<uint, uint> _gridToUnitDict;
|
||
// 格子 -> 城市, 缓存数据
|
||
private Dictionary<uint, uint> _gridToCityDict;
|
||
|
||
//--------------- 其他数据 ---------------//
|
||
// 地图 ID 生成器
|
||
[SerializeField]
|
||
private MapIdGenerator _idGenerator;
|
||
public MapIdGenerator IdGenerator => _idGenerator;
|
||
|
||
//--------------- 序列化临时数据 ---------------//
|
||
public List<uint> CityToPlayerDictKey;
|
||
public List<uint> CityToPlayerDictValue;
|
||
public List<uint> UnitToCityDictKey;
|
||
public List<uint> UnitToCityDictValue;
|
||
public List<uint> UnitToGridDictKey;
|
||
public List<uint> UnitToGridDictValue;
|
||
public List<uint> CityToGridDictKey;
|
||
public List<uint> CityToGridDictValue;
|
||
|
||
|
||
//-------------- 读写城市方法 -------------------//
|
||
// 通过格子 gid 找城市 cid
|
||
public bool GetCityIdByGridId(uint gid, out uint cid)
|
||
{
|
||
return _gridToCityDict.TryGetValue(gid, out cid);
|
||
}
|
||
|
||
// 通过格子 gid 找城市数据 cityData
|
||
public bool GetCityDataByGid(uint gid, out CityData cityData)
|
||
{
|
||
if (_gridToCityDict.TryGetValue(gid, out var cid))
|
||
{
|
||
return CityMap.GetCityById(_gridToCityDict[gid], out cityData);
|
||
}
|
||
|
||
cityData = null;
|
||
return false;
|
||
}
|
||
|
||
// 通过小兵 ID 找城市 cid
|
||
public bool GetCityIdByUnitId(uint uid, out uint cid)
|
||
{
|
||
return UnitToCityDict.TryGetValue(uid, out cid);
|
||
}
|
||
|
||
// 通过小兵 ID 找城市 data
|
||
public bool GetCityDataByUnitId(uint uid, out CityData cityData)
|
||
{
|
||
if (UnitToCityDict.TryGetValue(uid, out var cid))
|
||
{
|
||
return CityMap.GetCityById(cid, out cityData);
|
||
}
|
||
|
||
cityData = null;
|
||
return false;
|
||
}
|
||
|
||
// 通过领土格子 gid 找城市数据 cityData
|
||
public bool GetCityDataByTerritoryGid(uint gid, out CityData cityData)
|
||
{
|
||
return CityMap.GetCityDataByTerritoryGridId(gid, out cityData);
|
||
}
|
||
|
||
// 通过玩家 ID 找城市列表
|
||
public void GetCityDataListByPlayerId(uint pid, List<CityData> cityDataList=null)
|
||
{
|
||
if (cityDataList == null) cityDataList = new List<CityData>();
|
||
foreach (var kv in CityToPlayerDict)
|
||
{
|
||
if (kv.Value != pid) continue;
|
||
if (!CityMap.GetCityById(kv.Key, out var cityData)) continue;
|
||
cityDataList.Add(cityData);
|
||
}
|
||
}
|
||
|
||
// 通过玩家 ID 找城市 Set
|
||
public HashSet<CityData> GetCityDataSetByPlayerId(uint pid)
|
||
{
|
||
var citySet = new HashSet<CityData>();
|
||
foreach (var kv in CityToPlayerDict)
|
||
{
|
||
if (kv.Value != pid) continue;
|
||
if (!CityMap.GetCityById(kv.Key, out var cityData)) continue;
|
||
citySet.Add(cityData);
|
||
}
|
||
|
||
return citySet;
|
||
}
|
||
|
||
// 通过玩家 ID 查找首都城市 cityData
|
||
public bool GetCapitalCityDataByPlayerId(uint pid, out CityData cityData)
|
||
{
|
||
var cityList = new List<CityData>();
|
||
GetCityDataListByPlayerId(pid, cityList);
|
||
foreach (var city in cityList)
|
||
{
|
||
if (!city.IsCapital) continue;
|
||
cityData = city;
|
||
return true;
|
||
}
|
||
|
||
cityData = null;
|
||
return false;
|
||
}
|
||
|
||
// 改变城市所属关系
|
||
public bool SetCityIdToPlayerId(uint cid, uint pid)
|
||
{
|
||
if (!GetPlayerDataByCityId(cid, out var oldPlayerData))
|
||
return false;
|
||
if (!GetCapitalCityDataByPlayerId(oldPlayerData.Id, out var oldPlayerCapitalCityData))
|
||
return false;
|
||
//playerData.RenderMark = true;
|
||
//如果cid的老东家没有别的城市了,判负
|
||
if (GetCityCount(oldPlayerData.Id) == 1)
|
||
{
|
||
oldPlayerData.Alive = false;
|
||
oldPlayerData.DieMark = true;
|
||
//所有unit都销毁
|
||
var unitDataList = new List<UnitData>();
|
||
GetUnitDataListByCityId(cid,unitDataList);
|
||
foreach (var unitData in unitDataList)
|
||
SetUnitDataDie(unitData);
|
||
}
|
||
//否则要将所有unit转移到老东家的capital下面去
|
||
else
|
||
{
|
||
//如果cid的老东家的首都就是cid,那么老东家首先要更换首都
|
||
if (oldPlayerCapitalCityData.Id == cid)
|
||
{
|
||
foreach (var tmpCityData in CityMap.CityList)
|
||
{
|
||
if (tmpCityData.Id == cid)
|
||
continue;
|
||
if (GetPlayerIdByCityId(tmpCityData.Id, out var tmpPlayerId) && tmpPlayerId == oldPlayerData.Id)
|
||
{
|
||
tmpCityData.IsCapital = true;
|
||
oldPlayerCapitalCityData.IsCapital = false;
|
||
oldPlayerCapitalCityData = tmpCityData;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
//开始将所有cid的小兵都转移到oldPlayerCapitalCityData下去
|
||
var tmpUnitDataList = new List<UnitData>();
|
||
GetUnitDataListByCityId(cid, tmpUnitDataList);
|
||
foreach(var tmpUnitData in tmpUnitDataList)
|
||
SetUnitIdToCityId(tmpUnitData.Id,oldPlayerData.Id);
|
||
oldPlayerCapitalCityData.RenderMark = true;
|
||
|
||
}
|
||
|
||
//正式更换城市归属
|
||
CityToPlayerDict[cid] = pid;
|
||
if (CityMap.GetCityById(cid, out var cityData))
|
||
{
|
||
cityData.RenderMark = true;
|
||
if (GetGridDataByCityId(cid, out var gridData))
|
||
gridData.CityBuildingRenderMark = true;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
//改变小兵的位置
|
||
public void SetUnitIdToGridId(uint uid, uint gid)
|
||
{
|
||
if (UnitToGridDict.TryGetValue(uid, out var oldGid))
|
||
{
|
||
_gridToUnitDict.Remove(oldGid);
|
||
}
|
||
|
||
UnitToGridDict[uid] = gid;
|
||
_gridToUnitDict[gid] = uid;
|
||
if (UnitMap.GetUnitDataByUnitId(uid, out var unitData))
|
||
unitData.RenderMark = true;
|
||
}
|
||
|
||
public void SetUnitDataDie(UnitData unitData)
|
||
{
|
||
unitData.Alive = false;
|
||
|
||
// 标记原city的rendermark
|
||
if (GetCityDataByUnitId(unitData.Id, out var cityData))
|
||
cityData.CityInfoRenderMark = true;
|
||
|
||
// 清除数据层绑定
|
||
RemoveUnitData(unitData.Id);
|
||
if (GetGridIdByUnitId(unitData.Id, out var gridId))
|
||
_gridToUnitDict.Remove(gridId);
|
||
|
||
|
||
UnitMap.UnitMapRenderMark = true;
|
||
|
||
}
|
||
|
||
//改变小兵到城市的所属关系
|
||
public void SetUnitIdToCityId(uint uid, uint cid)
|
||
{
|
||
UnitToCityDict[uid] = cid;
|
||
//if (CityMap.GetCityById(cid, out var cityData)) cityData.RenderMark = true;
|
||
//if (PlayerMap.GetPlayerDataByPlayerID(pid, out var playerData)) playerData.RenderMark = true;
|
||
}
|
||
|
||
|
||
//获得一个玩家有多少个城市
|
||
public int GetCityCount(uint pid)
|
||
{
|
||
int ret = 0;
|
||
foreach (var cityData in CityMap.CityList)
|
||
if (CityToPlayerDict.ContainsKey(cityData.Id) && CityToPlayerDict[cityData.Id] == pid)
|
||
ret++;
|
||
|
||
return ret;
|
||
}
|
||
|
||
//获得一共城市有多少单位
|
||
public int GetUnitCount(uint cid)
|
||
{
|
||
int ret = 0;
|
||
foreach (var cityData in UnitMap.UnitList)
|
||
if (UnitToCityDict.ContainsKey(cityData.Id) && UnitToCityDict[cityData.Id] == cid)
|
||
ret++;
|
||
return ret;
|
||
}
|
||
|
||
//-------------- 读写小兵方法 -------------------//
|
||
// 通过格子 gid 找小兵 uid
|
||
public bool GetUnitIdByGid(uint gid, out uint uid)
|
||
{
|
||
return _gridToUnitDict.TryGetValue(gid, out uid);
|
||
}
|
||
|
||
// 通过格子 gid 找小兵 data
|
||
public bool GetUnitDataByGid(uint gid, out UnitData unitData)
|
||
{
|
||
unitData = null;
|
||
|
||
/*foreach(var tt in UnitMap.UnitList)
|
||
if (GetGridDataByUnitId(tt.Id,out var gridData))
|
||
if (gridData.Id == gid)
|
||
{
|
||
unitData = tt;
|
||
return true;
|
||
}
|
||
|
||
return false;*/
|
||
//TODO _gridToUnitDict这个缓存有错,和unitToGrid没有对上。 暂时用了上面的办法,之后需要修改这里的缓存
|
||
if (_gridToUnitDict.TryGetValue(gid, out var uid))
|
||
{
|
||
return UnitMap.GetUnitDataByUnitId(uid, out unitData);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// 通过城市 ID 找小兵列表
|
||
public void GetUnitDataListByCityId(uint cid, List<UnitData> unitDataList=null)
|
||
{
|
||
if (unitDataList == null) unitDataList = new List<UnitData>();
|
||
foreach (var kv in UnitToCityDict)
|
||
{
|
||
if (kv.Value != cid) continue;
|
||
if (!UnitMap.GetUnitDataByUnitId(kv.Key, out var unitData)) continue;
|
||
unitDataList.Add(unitData);
|
||
}
|
||
}
|
||
|
||
// 通过玩家 ID 找小兵列表
|
||
public void GetUnitDataListByPlayerId(uint pid, List<UnitData> unitDataList=null)
|
||
{
|
||
if (unitDataList == null) unitDataList = new List<UnitData>();
|
||
foreach (var kv in CityToPlayerDict)
|
||
{
|
||
if (kv.Value != pid) continue;
|
||
GetUnitDataListByCityId(kv.Key, unitDataList);
|
||
}
|
||
}
|
||
|
||
// 通过城市 ID 找小兵 Set
|
||
public void GetUnitDataListByCityId(uint cid, HashSet<UnitData> unitDataList=null)
|
||
{
|
||
if (unitDataList == null) unitDataList = new HashSet<UnitData>();
|
||
foreach (var kv in UnitToCityDict)
|
||
{
|
||
if (kv.Value != cid) continue;
|
||
if (!UnitMap.GetUnitDataByUnitId(kv.Key, out var unitData)) continue;
|
||
unitDataList.Add(unitData);
|
||
}
|
||
}
|
||
|
||
// 通过玩家 ID 找小兵 Set
|
||
public void GetUnitDataListByPlayerId(uint pid, HashSet<UnitData> unitDataList=null)
|
||
{
|
||
if (unitDataList == null) unitDataList = new HashSet<UnitData>();
|
||
foreach (var kv in CityToPlayerDict)
|
||
{
|
||
if (kv.Value != pid) continue;
|
||
GetUnitDataListByCityId(kv.Key, unitDataList);
|
||
}
|
||
}
|
||
|
||
// 通过玩家 ID 找敌方小兵列表
|
||
public void GetOtherUnitDataListByPlayerId(uint pid, List<UnitData> unitDataList=null)
|
||
{
|
||
if (unitDataList == null) unitDataList = new List<UnitData>();
|
||
foreach (var kv in CityToPlayerDict)
|
||
{
|
||
if (kv.Value == pid) continue;
|
||
GetUnitDataListByCityId(kv.Key, unitDataList);
|
||
}
|
||
}
|
||
|
||
|
||
//-------------- 读写玩家方法 -------------------//
|
||
// 通过城市找玩家 pid
|
||
public bool GetPlayerIdByCityId(uint cityId, out uint playerId)
|
||
{
|
||
return CityToPlayerDict.TryGetValue(cityId, out playerId);
|
||
}
|
||
|
||
// 通过城市找玩家 data
|
||
public bool GetPlayerDataByCityId(uint cityId, out PlayerData playerData)
|
||
{
|
||
playerData = null;
|
||
|
||
if (CityToPlayerDict.TryGetValue(cityId, out var playerId))
|
||
{
|
||
playerData = PlayerMap.GetPlayerData(playerId);
|
||
}
|
||
return playerData != null;
|
||
}
|
||
|
||
// 通过小兵 uid 找城市 pid
|
||
public bool GetPlayerIdByUnitId(uint uid, out uint pid)
|
||
{
|
||
if (UnitToCityDict.TryGetValue(uid, out var cid))
|
||
{
|
||
return CityToPlayerDict.TryGetValue(cid, out pid);
|
||
}
|
||
|
||
pid = 0;
|
||
return false;
|
||
}
|
||
|
||
// 通过小兵 uid 找城市数据 playerData
|
||
public bool GetPlayerDataByUnitId(uint uid, out PlayerData playerData)
|
||
{
|
||
playerData = null;
|
||
if (UnitToCityDict.TryGetValue(uid, out var cid))
|
||
{
|
||
if (CityToPlayerDict.TryGetValue(cid, out var pid))
|
||
{
|
||
playerData = PlayerMap.GetPlayerData(pid);
|
||
}
|
||
}
|
||
|
||
return playerData != null;
|
||
}
|
||
|
||
// 通过领土位置找玩家
|
||
public bool GetPlayerDataByTerritoryGridId(uint gid, out PlayerData playerData)
|
||
{
|
||
if (CityMap.GetCityDataByTerritoryGridId(gid, out var cityData))
|
||
{
|
||
return GetPlayerDataByCityId(cityData.Id, out playerData);
|
||
}
|
||
|
||
playerData = null;
|
||
return false;
|
||
}
|
||
|
||
|
||
//-------------- 查询格子方法 -------------------//
|
||
// 通过小兵 uid 找格子 gid
|
||
public bool GetGridIdByUnitId(uint uid, out uint gid)
|
||
{
|
||
return UnitToGridDict.TryGetValue(uid, out gid);
|
||
}
|
||
|
||
// 通过小兵 uid 找格子数据 data
|
||
public bool GetGridDataByUnitId(uint uid, out GridData data)
|
||
{
|
||
if (UnitToGridDict.TryGetValue(uid, out var gid))
|
||
{
|
||
return GridMap.GetGridDataByGid(gid, out data);
|
||
}
|
||
|
||
data = null;
|
||
return false;
|
||
}
|
||
|
||
// 通过城市 cid 找格子 gid
|
||
public bool GetGridIdByCityId(uint cid, out uint gid)
|
||
{
|
||
return CityToGridDict.TryGetValue(cid, out gid);
|
||
}
|
||
|
||
// 通过城市 cid 找格子数据 data
|
||
public bool GetGridDataByCityId(uint cid, out GridData data)
|
||
{
|
||
if (CityToGridDict.TryGetValue(cid, out var gid))
|
||
{
|
||
return GridMap.GetGridDataByGid(gid, out data);
|
||
}
|
||
|
||
data = null;
|
||
return false;
|
||
}
|
||
|
||
|
||
//------------- 计算地图信息方法 -----------------//
|
||
public bool CheckIfNearByGridSamePlayer(GridData gridData, int dir)
|
||
{
|
||
dir--;
|
||
int x = gridData.Pos.X + dir % 3 - 1, y = gridData.Pos.Y + dir / 3 - 1;
|
||
if(x < 0 || x >= MapConfig.Width || y < 0 || y >= MapConfig.Height)
|
||
return false;
|
||
if (GridMap.GetGridDataByPos(x, y, out GridData gridData2))
|
||
{
|
||
GetPlayerDataByTerritoryGridId(gridData.Id,out var p1);
|
||
GetPlayerDataByTerritoryGridId(gridData2.Id,out var p2);
|
||
return p1 == p2;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//返回在gid周围1格内,dir方向的那格是否是freeland
|
||
public bool CheckIfNearByGridFreeland(GridData gridData, int dir,out GridData gridData2)
|
||
{
|
||
gridData2 = null;
|
||
dir--;
|
||
int x = (int)gridData.Pos.X + dir % 3 - 1, y = (int)gridData.Pos.Y + dir / 3 - 1;
|
||
if(x < 0 || x >= MapConfig.Width || y < 0 || y >= MapConfig.Height)
|
||
return false;
|
||
if(GridMap.GetGridDataByPos(x, y, out gridData2))
|
||
return !GetPlayerDataByTerritoryGridId(gridData2.Id,out var playerData);
|
||
return false;
|
||
}
|
||
|
||
public bool CheckIfNearByGridRoadCanConnenct(GridData gridData, int dir)
|
||
{
|
||
dir--;
|
||
int x = gridData.Pos.X + dir % 3 - 1, y = gridData.Pos.Y + dir / 3 - 1;
|
||
if(x < 0 || x >= MapConfig.Width || y < 0 || y >= MapConfig.Height)
|
||
return false;
|
||
if (!GridMap.GetGridDataByPos(x, y, out var gridData2))
|
||
return false;
|
||
//如果本身就是无主领土,直接判断目标有没有road
|
||
if (!GetPlayerDataByTerritoryGridId(gridData.Id, out var playerData1))
|
||
return gridData2.Feature == TerrainFeature.Road;
|
||
//否则就判断对目标有没有road,且必须是无主或者和playerdata1一样
|
||
if (!GetPlayerDataByTerritoryGridId(gridData2.Id, out var playerData2) || playerData1 == playerData2)
|
||
return gridData2.Feature == TerrainFeature.Road;
|
||
return false;
|
||
}
|
||
|
||
//返回在gid周围1个内,dir方向的那格是不是land
|
||
public bool CheckIfNearByGridIsLand(GridData gridData, int dir,out GridData gridData2)
|
||
{
|
||
gridData2 = null;
|
||
dir--;
|
||
int x = (int)gridData.Pos.X + dir % 3 - 1, y = (int)gridData.Pos.Y + dir / 3 - 1;
|
||
if(x < 0 || x >= MapConfig.Width || y < 0 || y >= MapConfig.Height)
|
||
return false;
|
||
GridMap.GetGridDataByPos(x, y, out gridData2);
|
||
return gridData2.Terrain == TerrainType.Land;
|
||
}
|
||
|
||
public List<uint> GetNearby1RadiusFreelandGidList(uint gid)
|
||
{
|
||
var ret = new List<uint>();
|
||
GridMap.GetGridDataByGid(gid,out GridData gridData);
|
||
//遍历周围一圈方向,将所有freeland加入列表
|
||
for (int dir = 1; dir <= 9; dir++)
|
||
if(CheckIfNearByGridFreeland(gridData, dir, out var gridData2))
|
||
ret.Add(gridData2.Id);
|
||
return ret;
|
||
}
|
||
|
||
//返回在gridData上是否存在建设桥梁的基础地理条件
|
||
public bool HasBridgeSideLand(GridData gridData,out bool isMirror)
|
||
{
|
||
isMirror = false;
|
||
if (gridData.Terrain == TerrainType.Land)
|
||
return false;
|
||
GridData t;
|
||
if (CheckIfNearByGridIsLand(gridData, 2, out t) && CheckIfNearByGridIsLand(gridData, 8, out t))
|
||
return true;
|
||
isMirror = true;
|
||
if (CheckIfNearByGridIsLand(gridData, 4, out t) && CheckIfNearByGridIsLand(gridData, 6, out t))
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
// 获取玩家的所有领土格子 ID
|
||
public HashSet<uint> GetPlayerTerritoryGridIdSet(uint pid)
|
||
{
|
||
var gridSet = new HashSet<uint>();
|
||
var cityList = new List<CityData>();
|
||
GetCityDataListByPlayerId(pid, cityList);
|
||
foreach (var cityData in cityList)
|
||
{
|
||
cityData.Territory.GetAllTerritoryArea(gridSet);
|
||
}
|
||
return gridSet;
|
||
}
|
||
|
||
public bool CheckIfCityFullPopulation(CityData cityData)
|
||
{
|
||
return GetUnitCount(cityData.Id) >= cityData.Level;
|
||
}
|
||
|
||
public uint GetMapSize()
|
||
{
|
||
return MapConfig.Width * MapConfig.Height;
|
||
}
|
||
|
||
|
||
//-------------- 新建数据的方法 -------------------//
|
||
// 新建城市数据
|
||
public CityData AddCityData(uint gid, uint pid)
|
||
{
|
||
uint civId = PlayerMap.GetPlayerData(pid).PlayerCivId;
|
||
string name = Table.Instance.cityNameLibrary[civId,Table.Instance.cityNameLibraryHat[civId]++];
|
||
CityData cityData = CityMap.AddCityData(GetNearby1RadiusFreelandGidList(gid), name, _idGenerator);
|
||
CityToPlayerDict[cityData.Id] = pid;
|
||
CityToGridDict[cityData.Id] = gid;
|
||
_gridToCityDict[gid] = cityData.Id;
|
||
//建立city会在改格子上自动建立road
|
||
if (GridMap.GetGridDataByGid(gid, out var gridData))
|
||
gridData.Feature = TerrainFeature.Road;
|
||
|
||
//处理rendermark
|
||
var gridIdSet = GetPlayerTerritoryGridIdSet(pid);
|
||
foreach(var gridId in gridIdSet)
|
||
if (GridMap.GetGridDataByGid(gridId, out var gridDataTerr))
|
||
gridDataTerr.RenderMark = true;
|
||
CityMap.CityMapRenderMark = true;
|
||
cityData.RenderMark = true;
|
||
cityData.CityInfoRenderMark = true;
|
||
return cityData;
|
||
}
|
||
|
||
// 新建小兵数据
|
||
public UnitData AddUnitData(uint gid, uint cid, UnitType unitType,GiantType giantType = GiantType.None)
|
||
{
|
||
UnitData unitData = UnitMap.AddUnitData(unitType,giantType, _idGenerator);
|
||
UnitToCityDict[unitData.Id] = cid;
|
||
UnitToGridDict[unitData.Id] = gid;
|
||
_gridToUnitDict[gid] = unitData.Id;
|
||
UnitMap.UnitMapRenderMark = true;
|
||
unitData.RenderMark = true;
|
||
//给角色新增skill
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitType, giantType, out var unitInfo))
|
||
return unitData;
|
||
foreach (var skill in unitInfo.Skills)
|
||
unitData.AddSkill(skill);
|
||
if (!GetPlayerDataByUnitId(unitData.Id, out var playerData))
|
||
return unitData;
|
||
|
||
var dict = ActionLogicFactory.GetActionLogicDict();
|
||
foreach (var action in dict.Keys)
|
||
if(action.ActionType == CommonActionType.UnitSkill
|
||
&& playerData.TechTree.CheckActionCan(action))
|
||
unitData.AddSkill(action.SkillType);
|
||
|
||
return unitData;
|
||
}
|
||
|
||
// 移除小兵数据
|
||
public void RemoveUnitData(uint uid)
|
||
{
|
||
UnitMap.RemoveUnitData(uid);
|
||
if (UnitToGridDict.Remove(uid, out var gid))
|
||
{
|
||
_gridToUnitDict.Remove(gid);
|
||
}
|
||
UnitToGridDict.Remove(uid);
|
||
UnitToCityDict.Remove(uid);
|
||
}
|
||
|
||
// 获取所有 ID 单位
|
||
public List<IdentifierBase> GetAllIdentifierBase()
|
||
{
|
||
var list = new List<IdentifierBase>();
|
||
foreach (var idBase in PlayerMap.PlayerDataList) list.Add(idBase);
|
||
foreach (var idBase in CityMap.CityList) list.Add(idBase);
|
||
foreach (var idBase in UnitMap.UnitList) list.Add(idBase);
|
||
foreach (var idBase in GridMap.GridList) list.Add(idBase);
|
||
return list;
|
||
}
|
||
|
||
//-------------- 生命周期方法 -------------------//
|
||
// 从地图配置初始化
|
||
public MapData(MapConfig mapCfg)
|
||
{
|
||
MapID = 0;
|
||
MapConfig = mapCfg;
|
||
_idGenerator = new MapIdGenerator();
|
||
|
||
GridMap = new GridMapData(mapCfg, _idGenerator);
|
||
PlayerMap = new PlayerMapData(mapCfg, _idGenerator);
|
||
CityMap = new CityMapData();
|
||
UnitMap = new UnitMapData();
|
||
|
||
CityToPlayerDict = new Dictionary<uint, uint>();
|
||
UnitToCityDict = new Dictionary<uint, uint>();
|
||
UnitToGridDict = new Dictionary<uint, uint>();
|
||
CityToGridDict = new Dictionary<uint, uint>();
|
||
_gridToCityDict = new Dictionary<uint, uint>();
|
||
_gridToUnitDict = new Dictionary<uint, uint>();
|
||
}
|
||
|
||
public MapData(MapData copyMap)
|
||
{
|
||
MapConfig = copyMap.MapConfig;
|
||
_idGenerator = copyMap._idGenerator.DeepCopy();
|
||
GridMap = new GridMapData(copyMap.GridMap);
|
||
PlayerMap = new PlayerMapData(copyMap.PlayerMap);
|
||
CityMap = new CityMapData(copyMap.CityMap);
|
||
UnitMap = new UnitMapData(copyMap.UnitMap);
|
||
|
||
CityToPlayerDict = new Dictionary<uint, uint>();
|
||
UnitToCityDict = new Dictionary<uint, uint>();
|
||
UnitToGridDict = new Dictionary<uint, uint>();
|
||
CityToGridDict = new Dictionary<uint, uint>();
|
||
_gridToCityDict = new Dictionary<uint, uint>();
|
||
_gridToUnitDict = new Dictionary<uint, uint>();
|
||
foreach (var kv in copyMap.CityToPlayerDict) CityToPlayerDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap.UnitToCityDict) UnitToCityDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap.UnitToGridDict) UnitToGridDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap.CityToGridDict) CityToGridDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap._gridToCityDict) _gridToCityDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap._gridToUnitDict) _gridToUnitDict[kv.Key] = kv.Value;
|
||
}
|
||
|
||
// 获取深拷贝的一份新的地图数据
|
||
public MapData GetDeepCopyMapData()
|
||
{
|
||
return new MapData(this);
|
||
}
|
||
|
||
// 深度拷贝另一封 map 数据
|
||
public void DeepCopy(MapData copyMap)
|
||
{
|
||
MapConfig = copyMap.MapConfig;
|
||
_idGenerator.DeepCopy(copyMap._idGenerator);
|
||
GridMap.DeepCopy(copyMap.GridMap);
|
||
PlayerMap.DeepCopy(copyMap.PlayerMap);
|
||
CityMap.DeepCopy(copyMap.CityMap);
|
||
UnitMap.DeepCopy(copyMap.UnitMap);
|
||
|
||
CityToPlayerDict.Clear();
|
||
UnitToCityDict.Clear();
|
||
UnitToGridDict.Clear();
|
||
CityToGridDict.Clear();
|
||
_gridToCityDict.Clear();
|
||
_gridToUnitDict.Clear();
|
||
foreach (var kv in copyMap.CityToPlayerDict) CityToPlayerDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap.UnitToCityDict) UnitToCityDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap.UnitToGridDict) UnitToGridDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap.CityToGridDict) CityToGridDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap._gridToCityDict) _gridToCityDict[kv.Key] = kv.Value;
|
||
foreach (var kv in copyMap._gridToUnitDict) _gridToUnitDict[kv.Key] = kv.Value;
|
||
}
|
||
|
||
// 序列化方法
|
||
public void OnBeforeSerialize()
|
||
{
|
||
CityToPlayerDictKey ??= new List<uint>();
|
||
CityToPlayerDictValue ??= new List<uint>();
|
||
UnitToCityDictKey ??= new List<uint>();
|
||
UnitToCityDictValue ??= new List<uint>();
|
||
UnitToGridDictKey ??= new List<uint>();
|
||
UnitToGridDictValue ??= new List<uint>();
|
||
CityToGridDictKey ??= new List<uint>();
|
||
CityToGridDictValue ??= new List<uint>();
|
||
CityToPlayerDictKey.Clear();
|
||
CityToPlayerDictValue.Clear();
|
||
UnitToCityDictKey.Clear();
|
||
UnitToCityDictValue.Clear();
|
||
UnitToGridDictKey.Clear();
|
||
UnitToGridDictValue.Clear();
|
||
CityToGridDictKey.Clear();
|
||
CityToGridDictValue.Clear();
|
||
|
||
foreach (var kv in CityToPlayerDict)
|
||
{
|
||
CityToPlayerDictKey.Add(kv.Key);
|
||
CityToPlayerDictValue.Add(kv.Value);
|
||
}
|
||
foreach (var kv in UnitToCityDict)
|
||
{
|
||
UnitToCityDictKey.Add(kv.Key);
|
||
UnitToCityDictValue.Add(kv.Value);
|
||
}
|
||
foreach (var kv in UnitToGridDict)
|
||
{
|
||
UnitToGridDictKey.Add(kv.Key);
|
||
UnitToGridDictValue.Add(kv.Value);
|
||
}
|
||
foreach (var kv in CityToGridDict)
|
||
{
|
||
CityToGridDictKey.Add(kv.Key);
|
||
CityToGridDictValue.Add(kv.Value);
|
||
}
|
||
}
|
||
|
||
// 反序列化方法
|
||
public void OnAfterDeserialize()
|
||
{
|
||
CityToPlayerDict??= new Dictionary<uint, uint>();
|
||
UnitToCityDict??= new Dictionary<uint, uint>();
|
||
UnitToGridDict??= new Dictionary<uint, uint>();
|
||
CityToGridDict??= new Dictionary<uint, uint>();
|
||
_gridToCityDict??= new Dictionary<uint, uint>();
|
||
_gridToUnitDict??= new Dictionary<uint, uint>();
|
||
|
||
CityToPlayerDict.Clear();
|
||
UnitToCityDict.Clear();
|
||
UnitToGridDict.Clear();
|
||
CityToGridDict.Clear();
|
||
_gridToCityDict.Clear();
|
||
_gridToUnitDict.Clear();
|
||
|
||
for (int i = 0; i < CityToPlayerDictKey.Count; i++)
|
||
CityToPlayerDict[CityToPlayerDictKey[i]] = CityToPlayerDictValue[i];
|
||
for (int i = 0; i < UnitToCityDictKey.Count; i++)
|
||
UnitToCityDict[UnitToCityDictKey[i]] = UnitToCityDictValue[i];
|
||
for (int i = 0; i < UnitToGridDictKey.Count; i++)
|
||
{
|
||
UnitToGridDict[UnitToGridDictKey[i]] = UnitToGridDictValue[i];
|
||
_gridToUnitDict[UnitToGridDictValue[i]] = UnitToGridDictKey[i];
|
||
}
|
||
for (int i = 0; i < CityToGridDictKey.Count; i++)
|
||
{
|
||
CityToGridDict[CityToGridDictKey[i]] = CityToGridDictValue[i];
|
||
_gridToCityDict[CityToGridDictValue[i]] = CityToGridDictKey[i];
|
||
}
|
||
}
|
||
|
||
// 当场上有小兵攻击时
|
||
public void OnUnitAttack(UnitData origin, UnitData target)
|
||
{
|
||
foreach (var idBase in GetAllIdentifierBase())
|
||
{
|
||
foreach (var skill in idBase.Skills) skill.OnUnitAttack(idBase, origin, target, this);
|
||
}
|
||
}
|
||
|
||
// 当场上有小兵受伤时
|
||
public void OnUnitDamage(UnitData origin, UnitData target)
|
||
{
|
||
foreach (var idBase in GetAllIdentifierBase())
|
||
{
|
||
foreach (var skill in idBase.Skills) skill.OnUnitDamage(idBase, origin, target, this);
|
||
}
|
||
}
|
||
|
||
// 当场上有小兵移动时
|
||
public void OnUnitMove(UnitData moveUnit, GridData target)
|
||
{
|
||
foreach (var idBase in GetAllIdentifierBase())
|
||
{
|
||
foreach (var skill in idBase.Skills) skill.OnUnitMove(idBase, moveUnit, target, this);
|
||
}
|
||
}
|
||
|
||
public static void SaveMapData(MapData map)
|
||
{
|
||
string json = JsonUtility.ToJson(map);
|
||
File.WriteAllText(Application.persistentDataPath + "/map_archive.json", json);
|
||
}
|
||
|
||
public static MapData GetMapData()
|
||
{
|
||
string path = Application.persistentDataPath + "/map_archive.json";
|
||
if (!File.Exists(path)) return null;
|
||
|
||
string json = File.ReadAllText(path);
|
||
MapData map = JsonUtility.FromJson<MapData>(json);
|
||
return map;
|
||
}
|
||
|
||
public GameRecord ExportGameRecord()
|
||
{
|
||
var gameRecord = new GameRecord();
|
||
gameRecord.Score = PlayerMap.SelfPlayerData.PlayerScore;
|
||
DateTime now = DateTime.Now;
|
||
gameRecord.Time = now.ToString("yyyy-MM-dd HH-mm-ss");
|
||
var cityList = new List<CityData>();
|
||
GetCityDataListByPlayerId(PlayerMap.SelfPlayerId, cityList);
|
||
gameRecord.CityCount = (uint)cityList.Count;
|
||
gameRecord.MapWidth = MapConfig.Width;
|
||
gameRecord.MapHeight = MapConfig.Height;
|
||
gameRecord.PlayerCount = MapConfig.PlayerCount - 1;
|
||
gameRecord.AIDiff = MapConfig.AIDiff;
|
||
return gameRecord;
|
||
}
|
||
}
|
||
|
||
|
||
// 地图 ID 生成器
|
||
[Serializable]
|
||
public class MapIdGenerator
|
||
{
|
||
[SerializeField]
|
||
private uint _idGenerator;
|
||
|
||
|
||
public MapIdGenerator()
|
||
{
|
||
_idGenerator = 0;
|
||
}
|
||
|
||
public uint GeneratorId()
|
||
{
|
||
return ++_idGenerator;
|
||
}
|
||
|
||
public MapIdGenerator DeepCopy()
|
||
{
|
||
var copy = new MapIdGenerator();
|
||
copy._idGenerator = _idGenerator;
|
||
return copy;
|
||
}
|
||
|
||
public void DeepCopy(MapIdGenerator copy)
|
||
{
|
||
_idGenerator = copy._idGenerator;
|
||
}
|
||
}
|
||
} |