2025-07-09 17:23:17 +08:00

1035 lines
38 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 System.IO;
using Logic;
using Logic.Action;
using Logic.AI;
using UnityEngine;
namespace RuntimeData
{
public enum GameMode
{
PERFECT,
DOMINATION,
CREATIVE
}
// 一场游戏的设置数据
[Serializable]
public class MapConfig
{
public uint Width;
public uint Height;
public uint PlayerCount;
public AIDifficult AIDiff;
public GameMode GameMode;
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 void GetCityDataListByPlayerId(uint pid, HashSet<CityData> cityDataList=null)
{
if (cityDataList == null) cityDataList = new HashSet<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 找 领土Set
public HashSet<GridData> GetGridDataSetByPlayerId(uint pid)
{
var citySet = GetCityDataSetByPlayerId(pid);
var gridSet = new HashSet<GridData>();
foreach (var city in citySet)
{
var cityGridSet = new HashSet<uint>();
city.Territory.GetAllTerritoryArea(cityGridSet);
foreach (var gid in cityGridSet)
{
GridMap.GetGridDataByGid(gid, out var grid);
gridSet.Add(grid);
}
}
return gridSet;
}
//通过玩家ID 找 领土ID Set
public HashSet<uint> GetGridIdSetByPlayerId(uint pid)
{
var citySet = GetCityDataSetByPlayerId(pid);
var gridSet = new HashSet<uint>();
foreach (var city in citySet)
{
var cityGridSet = new HashSet<uint>();
city.Territory.GetAllTerritoryArea(cityGridSet);
gridSet.UnionWith(cityGridSet);
}
return gridSet;
}
// 通过玩家 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;
}
//判断playerA和playerB是否同一个联盟
//TODO 加入外交系统后要更新这个函数
public bool SameUnion(uint pidA, uint pidB)
{
return pidA == pidB;
}
//-------------- 查询格子方法 -------------------//
// 通过小兵 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;
}
public bool CheckIfNearByGridSameCity(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))
{
GetCityDataByTerritoryGid(gridData.Id,out var c1);
GetCityDataByTerritoryGid(gridData2.Id,out var c2);
return c1 == c2;
}
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;
}
//判断grid的dir方向是不是道路或者海路联通的。注意要区分 陆地港口桥梁 和 港口海域 两种情况,港口是两种情况都出现的
public bool CheckIfNearByGridRoadCanConnenct(GridData gridData, int 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 return
if (gridData.Feature != TerrainFeature.Road || gridData2.Feature != TerrainFeature.Road) return false;
//判断主权情况 均有主权且不是一个同盟要return false
if (GetPlayerDataByTerritoryGridId(gridData.Id, out var playerData1) &&
GetPlayerDataByTerritoryGridId(gridData2.Id, out var playerData2) &&
!SameUnion(playerData1.Id, playerData2.Id))
return false;
//排除一个是非港口海域,一个是陆地的情况
if (gridData.Terrain != TerrainType.Land && gridData.Resource != ResourceType.Port &&
gridData2.Terrain == TerrainType.Land)
{
//bridge的情况特判
if (gridData.Resource == ResourceType.Bridge) return true;
return false;
}
if (gridData2.Terrain != TerrainType.Land && gridData2.Resource != ResourceType.Port &&
gridData.Terrain == TerrainType.Land)
{
//bridge的情况特判
if (gridData2.Resource == ResourceType.Bridge) return true;
return false;
}
//剩下情况都是true
return true;
}
//返回在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;
int cityRk = Table.Instance.cityNameLibraryHat[civId]++;
Table.Instance.CivDataAssets.GetCivInfo(civId, out var civData);
CityLibrary nameEnum = civData.CityInfoList[cityRk].CityNameEnum;
CityData cityData = CityMap.AddCityData(GetNearby1RadiusFreelandGidList(gid), nameEnum, _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 OnUnitDamaged(SettlementInfo info)
{
foreach (var idBase in GetAllIdentifierBase())
{
foreach (var skill in idBase.Skills) skill.OnUnitDamaged(idBase, this, info);
}
}
// 当场上有小兵移动时
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;
}
//-------------- 判断数据间关系的快捷方法 -------------------//
public bool CheckCityIdBelongPlayerId(uint cid,uint pid)
{
return GetPlayerIdByCityId(cid, out var pid1) && pid1 == pid;
}
public bool CheckUnitIdBelongPlayerId(uint uid,uint pid)
{
return GetPlayerIdByUnitId(uid, out var pid1) && pid1 == pid;
}
//判断一个unit是否属于pid及其盟友
public bool CheckUnitIdBelongPlayerIdUnion(uint uid,uint pid)
{
//TODO #外交系统更新
return GetPlayerIdByUnitId(uid, out var pid1) && pid1 == pid;
}
//判断一个grid是否属于pid及其盟友
public bool CheckGridIdBelongPlayerIdUnion(uint gid,uint pid)
{
//TODO #外交系统更新
return GetPlayerDataByTerritoryGridId(gid, out var player) && player.Id == pid;
}
public bool CheckUnitIdBelongCityId(uint uid,uint cid)
{
return GetCityIdByUnitId(uid, out var cid1) && cid1 == cid;
}
public bool CheckCityIdBelongSelfPlayer(uint cid)
{
return GetPlayerIdByCityId(cid, out var pid1) && pid1 == PlayerMap.SelfPlayerData.Id;
}
public bool CheckUnitIdBelongSelfPlayer(uint uid)
{
return GetPlayerIdByUnitId(uid, out var pid1) && pid1 == PlayerMap.SelfPlayerData.Id;
}
}
// 地图 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;
}
}
}