gameconfig中玩家信息修改

This commit is contained in:
wuwenbo 2026-05-09 15:18:56 +08:00
parent ec04df6514
commit d51777bdbe
7 changed files with 246 additions and 64 deletions

View File

@ -61,7 +61,9 @@ namespace RuntimeData
public MatchSettlementType MatchSettlement;
public List<PlayerSettlementInfo> PlayerSettlements;
// 单机用
// 单机用:真人玩家选择的 PlayerInfos 索引
public uint SelfPlayerInfoIndex;
// 兼容旧数据(已弃用)
public uint selfCivId;
public uint selfForceId;
@ -103,11 +105,18 @@ namespace RuntimeData
Height = height;
PlayerCount = playerCount;
AIDiff = aiDiff;
SelfPlayerInfoIndex = 0;
selfCivId = civId;
selfForceId = forceId;
MultiCivs = new List<MemberCiv>();
_memberCivs = new Dictionary<ulong, MemberCiv>();
PlayerInfos = new List<PlayerInfo>();
EnsurePlayerInfosCount();
if (GetPlayerInfoByIndex(SelfPlayerInfoIndex, out var selfInfo))
{
selfInfo.CivId = civId;
selfInfo.ForceId = forceId;
}
}
// MemoryPack 反序列化之后的后处理
@ -118,22 +127,136 @@ namespace RuntimeData
// 旧存档兼容WaterType 字段不存在时默认为 Pangea
if (!System.Enum.IsDefined(typeof(Logic.MapWaterType), WaterType))
WaterType = Logic.MapWaterType.Pangea;
MultiCivs ??= new List<MemberCiv>();
PlayerInfos ??= new List<PlayerInfo>();
_memberCivs ??= new Dictionary<ulong, MemberCiv>();
RefreshMultiCivsDict();
EnsurePlayerInfosCount();
NormalizeMemberPlayerInfoIndexes();
}
public void EnsurePlayerInfosCount()
{
PlayerInfos ??= new List<PlayerInfo>();
if (PlayerCount == 0)
{
PlayerInfos.Clear();
SelfPlayerInfoIndex = 0;
return;
}
for (int i = 0; i < PlayerCount; i++)
{
if (i >= PlayerInfos.Count)
{
PlayerInfos.Add(new PlayerInfo { Index = (uint)i, CivId = (uint)i, ForceId = (uint)i });
}
else
{
PlayerInfos[i] ??= new PlayerInfo();
PlayerInfos[i].Index = (uint)i;
}
}
if (PlayerInfos.Count > PlayerCount)
{
PlayerInfos.RemoveRange((int)PlayerCount, PlayerInfos.Count - (int)PlayerCount);
}
if (SelfPlayerInfoIndex >= PlayerCount) SelfPlayerInfoIndex = 0;
// 旧数据迁移:若旧字段有效,补到 SelfPlayerInfoIndex 对应的 PlayerInfo
if (GetPlayerInfoByIndex(SelfPlayerInfoIndex, out var selfInfo))
{
if (selfCivId != 0 || selfForceId != 0)
{
selfInfo.CivId = selfCivId;
selfInfo.ForceId = selfForceId;
}
}
// 旧联机数据迁移MemberCiv 可能还带着 Civ/Force迁移到其索引对应 PlayerInfo
if (MultiCivs == null) return;
foreach (var member in MultiCivs)
{
if (member == null) continue;
if (member.PlayerInfoIndex >= PlayerCount) continue;
if (member.CivId == 0 && member.ForceId == 0) continue;
if (!GetPlayerInfoByIndex(member.PlayerInfoIndex, out var info)) continue;
info.CivId = member.CivId;
info.ForceId = member.ForceId;
}
}
public bool GetPlayerInfoByIndex(uint index, out PlayerInfo info)
{
info = null;
EnsurePlayerInfosCount();
if (index >= PlayerInfos.Count) return false;
info = PlayerInfos[(int)index];
info ??= new PlayerInfo { Index = index, CivId = index, ForceId = index };
PlayerInfos[(int)index] = info;
return true;
}
private void NormalizeMemberPlayerInfoIndexes()
{
if (MultiCivs == null || MultiCivs.Count == 0) return;
EnsurePlayerInfosCount();
if (PlayerCount == 0) return;
var used = new HashSet<uint>();
for (int i = 0; i < MultiCivs.Count; i++)
{
var member = MultiCivs[i];
if (member == null) continue;
if (member.PlayerInfoIndex < PlayerCount && !used.Contains(member.PlayerInfoIndex))
{
used.Add(member.PlayerInfoIndex);
continue;
}
member.PlayerInfoIndex = uint.MaxValue;
}
for (int i = 0; i < MultiCivs.Count; i++)
{
var member = MultiCivs[i];
if (member == null || member.PlayerInfoIndex != uint.MaxValue) continue;
uint fallback = 0;
while (fallback < PlayerCount && used.Contains(fallback)) fallback++;
if (fallback >= PlayerCount)
{
member.PlayerInfoIndex = 0;
continue;
}
member.PlayerInfoIndex = fallback;
used.Add(fallback);
}
}
// 根据房间成员信息更新 mapconfig 信息
public void UpdateLobbyMember(Dictionary<ulong, MemberInfo> memberInfos)
{
EnsurePlayerInfosCount();
RefreshMultiCivsDict();
for (int i = MultiCivs.Count - 1; i >= 0; i--)
{
if (memberInfos.ContainsKey(MultiCivs[i].MemberId)) continue;
_memberCivs.Remove(MultiCivs[i].MemberId);
MultiCivs.RemoveAt(i);
}
RefreshMultiCivsDict();
foreach (var kv in memberInfos)
{
if (_memberCivs.ContainsKey(kv.Key)) continue;
var civ = new MemberCiv();
civ.MemberId = kv.Key;
civ.CivId = 0;
civ.ForceId = 0;
civ.PlayerInfoIndex = uint.MaxValue;
MultiCivs.Add(civ);
}
RefreshMultiCivsDict();
NormalizeMemberPlayerInfoIndexes();
}
// 内部刷新
@ -163,14 +286,31 @@ namespace RuntimeData
return;
}
EnsurePlayerInfosCount();
uint newIndex = civ.PlayerInfoIndex;
if (newIndex >= PlayerCount)
{
// 兼容旧消息:按 Civ/Force 找索引
for (uint i = 0; i < PlayerCount; i++)
{
if (!GetPlayerInfoByIndex(i, out var info)) continue;
if (info.CivId != civ.CivId || info.ForceId != civ.ForceId) continue;
newIndex = i;
break;
}
if (newIndex >= PlayerCount) newIndex = 0;
}
foreach (var memberCiv in MultiCivs)
{
if (memberCiv.MemberId != civ.MemberId) continue;
memberCiv.CivId = civ.CivId;
memberCiv.ForceId = civ.ForceId;
memberCiv.PlayerInfoIndex = newIndex;
NormalizeMemberPlayerInfoIndexes();
return;
}
civ.PlayerInfoIndex = newIndex;
MultiCivs.Add(civ);
NormalizeMemberPlayerInfoIndexes();
}
// 主从端一致的本地数据检测
@ -192,18 +332,17 @@ namespace RuntimeData
// 从 MapData 中重绑定 MemberCiv 的 Player 信息
public bool ReBindPlayerInfoFromMapData(MapData mapData)
{
EnsurePlayerInfosCount();
RefreshMultiCivsDict();
NormalizeMemberPlayerInfoIndexes();
if (mapData.Net.Mode == NetMode.Single)
{
foreach (var player in mapData.PlayerMap.PlayerDataList)
{
if (player.PlayerCivId != selfCivId || player.PlayerForceId != selfForceId) continue;
mapData.PlayerMap.SelfPlayerId = player.Id;
}
if (mapData.PlayerMap.SelfPlayerId == 0)
if (SelfPlayerInfoIndex < mapData.PlayerMap.PlayerDataList.Count)
mapData.PlayerMap.SelfPlayerId = mapData.PlayerMap.PlayerDataList[(int)SelfPlayerInfoIndex].Id;
else
{
LogSystem.LogError($"单机模式指定地图中找不到指定的阵营信息, 启动游戏失败, " +
$"地图 ID : {Id} 文明 ID : {selfCivId} 势力 ID : {selfForceId}");
$"地图 ID : {Id} 玩家索引 : {SelfPlayerInfoIndex}");
return false;
}
}
@ -212,16 +351,13 @@ namespace RuntimeData
{
foreach (var member in MultiCivs)
{
foreach (var player in mapData.PlayerMap.PlayerDataList)
{
if (player.PlayerCivId != member.CivId || player.PlayerForceId != member.ForceId) continue;
member.PlayerId = player.PlayerCivId;
}
if (member.PlayerInfoIndex >= mapData.PlayerMap.PlayerDataList.Count) member.PlayerId = 0;
else member.PlayerId = mapData.PlayerMap.PlayerDataList[(int)member.PlayerInfoIndex].Id;
if (member.PlayerId == 0)
{
LogSystem.LogError($"联机模式指定地图中找不到指定的阵营信息, 启动游戏失败, " +
$"地图 ID : {Id} 文明 ID : {member.CivId} 势力 ID : {member.ForceId}");
$"地图 ID : {Id} 玩家索引 : {member.PlayerInfoIndex}");
return false;
}
}
@ -275,6 +411,8 @@ namespace RuntimeData
{
public ulong MemberId;
public uint PlayerId;
public uint PlayerInfoIndex;
// 兼容旧数据(已弃用,真实值来自 PlayerInfos[PlayerInfoIndex]
public uint CivId;
public uint ForceId;
}

View File

@ -151,6 +151,7 @@ namespace RuntimeData
public int RandomSeed;
private System.Random _random;
private static readonly ArrayBufferWriter<byte> _bufferWriter = new ArrayBufferWriter<byte>(64 * 1024);
private List<ulong> _tmpMemberIdListBuffer;
// 玩家开始时间记录
[MemoryPackIgnore]
@ -205,16 +206,35 @@ namespace RuntimeData
if (Mode != NetMode.Multi) return;
if (LobbyManager.Instance.Lobby.IsLobbyOwner())
{
// 创建 Player 的时候会分配一次 PlayerId这里直接使用
mapData.MapConfig.EnsurePlayerInfosCount();
var memberIds = LobbyManager.Instance.Lobby.GetAllMemberIds();
// 移除不在当前房间的映射
_tmpMemberIdListBuffer ??= new List<ulong>();
_tmpMemberIdListBuffer.Clear();
foreach (var kv in Players)
{
if (memberIds.Contains(kv.Key)) continue;
_tmpMemberIdListBuffer.Add(kv.Key);
}
foreach (var memberId in _tmpMemberIdListBuffer) Players.Remove(memberId);
// 创建 Player 的时候会分配一次 PlayerId这里直接使用 index -> PlayerId
foreach (var memberCiv in mapData.MapConfig.MultiCivs)
{
if (memberCiv.PlayerInfoIndex >= mapData.PlayerMap.PlayerDataList.Count)
{
memberCiv.PlayerId = 0;
continue;
}
memberCiv.PlayerId = mapData.PlayerMap.PlayerDataList[(int)memberCiv.PlayerInfoIndex].Id;
if (memberCiv.PlayerId == 0) continue;
if (Players.ContainsKey(memberCiv.MemberId)) continue;
if (!memberIds.Contains(memberCiv.MemberId)) continue;
Players[memberCiv.MemberId] = memberCiv.PlayerId;
}
// 添加其他人
foreach (var memberId in LobbyManager.Instance.Lobby.GetAllMemberIds())
foreach (var memberId in memberIds)
{
if (Players.ContainsKey(memberId)) continue;
foreach (var player in mapData.PlayerMap.PlayerDataList)

View File

@ -118,47 +118,53 @@ namespace RuntimeData
if (netMode == NetMode.Single)
{
map.MapConfig.EnsurePlayerInfosCount();
for (int i = 0; i < map.MapConfig.PlayerCount; i++)
{
PlayerData player;
//处理player到底是谁的问题。目前临时使用的方案今后要改。目前civ一定=force,所以可以这么做
if (i == 0)
player = new PlayerData(map.MapConfig.selfCivId,map.MapConfig.selfForceId,idGenerator);
else if (map.MapConfig.selfCivId == i)
player = new PlayerData((uint)0,(uint)0,idGenerator);
else
player = new PlayerData((uint)i,(uint)i,idGenerator);
uint civId = (uint)i;
uint forceId = (uint)i;
if (map.MapConfig.GetPlayerInfoByIndex((uint)i, out var playerInfo))
{
civId = playerInfo.CivId;
forceId = playerInfo.ForceId;
}
PlayerData player = new PlayerData(civId, forceId, idGenerator);
PlayerDataList.Add(player);
_playerDataDict[player.Id] = player;
}
}
if (netMode == NetMode.Multi)
{
// 这里 civList 要包含所有 civId (civId = civEnum - 1目前 17 个 civ → 0..16)
var civList = new List<uint>();
for (int i = 0; i < 17; i++) civList.Add((uint)i);
map.MapConfig.EnsurePlayerInfosCount();
for (int i = 0; i < map.MapConfig.PlayerCount; i++)
{
uint civId = (uint)i;
uint forceId = (uint)i;
if (map.MapConfig.GetPlayerInfoByIndex((uint)i, out var playerInfo))
{
civId = playerInfo.CivId;
forceId = playerInfo.ForceId;
}
var player = new PlayerData(civId, forceId, idGenerator);
PlayerDataList.Add(player);
_playerDataDict[player.Id] = player;
}
foreach (var multiCiv in map.MapConfig.MultiCivs)
{
var player = new PlayerData(multiCiv.CivId, multiCiv.CivId, idGenerator);
PlayerDataList.Add(player);
_playerDataDict[player.Id] = player;
civList.Remove(multiCiv.CivId);
multiCiv.PlayerId = player.Id;
}
for (int i = map.MapConfig.MultiCivs.Count; i < map.MapConfig.PlayerCount; i++)
{
int idx = UnityEngine.Random.Range(0, civList.Count);//map.Net.GetRandom().Next
var civId = civList[idx];
var player = new PlayerData(civId, civId, idGenerator);
PlayerDataList.Add(player);
_playerDataDict[player.Id] = player;
civList.RemoveAt(idx);
if (multiCiv.PlayerInfoIndex >= PlayerDataList.Count)
{
multiCiv.PlayerId = 0;
continue;
}
multiCiv.PlayerId = PlayerDataList[(int)multiCiv.PlayerInfoIndex].Id;
}
}
SelfPlayerId = PlayerDataList[0].Id;
if (netMode == NetMode.Single && map.MapConfig.SelfPlayerInfoIndex < PlayerDataList.Count)
SelfPlayerId = PlayerDataList[(int)map.MapConfig.SelfPlayerInfoIndex].Id;
else
SelfPlayerId = PlayerDataList[0].Id;
foreach (var self in PlayerDataList)
{
foreach (var target in PlayerDataList)

View File

@ -107,6 +107,7 @@ namespace Logic.Editor
private void OnGUIMapConfig(MapConfig mapConfig)
{
EditorGUILayout.BeginVertical();
mapConfig.EnsurePlayerInfosCount();
// 基础配置
if (InspectorUtils.InspectorButtonWithTextWidth("删除关卡"))
@ -135,7 +136,9 @@ namespace Logic.Editor
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich("玩家数量:");
var oldPlayerCount = mapConfig.PlayerCount;
mapConfig.PlayerCount = (uint)EditorGUILayout.IntField((int)mapConfig.PlayerCount, GUILayout.Width(200));
if (oldPlayerCount != mapConfig.PlayerCount) mapConfig.EnsurePlayerInfosCount();
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
@ -159,13 +162,19 @@ namespace Logic.Editor
// 单机配置
InspectorUtils.InspectorTextWidthRich("<b>单机配置</b>");
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich("文明ID:");
mapConfig.selfCivId = (uint)EditorGUILayout.IntField((int)mapConfig.selfCivId, GUILayout.Width(200));
InspectorUtils.InspectorTextWidthRich("单机玩家索引:");
mapConfig.SelfPlayerInfoIndex = (uint)EditorGUILayout.IntField((int)mapConfig.SelfPlayerInfoIndex, GUILayout.Width(200));
if (mapConfig.PlayerCount > 0 && mapConfig.SelfPlayerInfoIndex >= mapConfig.PlayerCount)
mapConfig.SelfPlayerInfoIndex = mapConfig.PlayerCount - 1;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich("势力ID:");
mapConfig.selfForceId = (uint)EditorGUILayout.IntField((int)mapConfig.selfForceId, GUILayout.Width(200));
InspectorUtils.InspectorTextWidthRich("单机玩家阵营(Civ/Force):");
if (mapConfig.GetPlayerInfoByIndex(mapConfig.SelfPlayerInfoIndex, out var selfInfo))
{
selfInfo.CivId = (uint)EditorGUILayout.IntField((int)selfInfo.CivId, GUILayout.Width(95));
selfInfo.ForceId = (uint)EditorGUILayout.IntField((int)selfInfo.ForceId, GUILayout.Width(95));
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
@ -387,4 +396,4 @@ namespace Logic.Editor
return 0;
}
}
}
}

View File

@ -146,11 +146,13 @@ namespace Logic.Editor
var civ = Main.Instance.MapConfig.GetMemberCiv(selfMemberId);
if (civ != null)
{
Main.Instance.MapConfig.GetPlayerInfoByIndex(civ.PlayerInfoIndex, out var info);
EditorGUILayout.BeginHorizontal();
if (InspectorUtils.InspectorButtonWithTextWidth("改1")) civ.CivId = 1;
if (InspectorUtils.InspectorButtonWithTextWidth("改2")) civ.CivId = 2;
if (InspectorUtils.InspectorButtonWithTextWidth("改3")) civ.CivId = 3;
if (InspectorUtils.InspectorButtonWithTextWidth("改4")) civ.CivId = 4;
InspectorUtils.InspectorTextWidthRich($"Idx:{civ.PlayerInfoIndex} Civ:{info?.CivId ?? 0} Force:{info?.ForceId ?? 0}");
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx0")) { civ.PlayerInfoIndex = 0; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx1")) { civ.PlayerInfoIndex = 1; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx2")) { civ.PlayerInfoIndex = 2; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
if (InspectorUtils.InspectorButtonWithTextWidth("改Idx3")) { civ.PlayerInfoIndex = 3; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();

View File

@ -161,7 +161,12 @@ namespace TH1_Logic.Steam
}
var data = new ChangeCivMessage();
data.Civ = memberCiv;
data.Civ = new MemberCiv
{
MemberId = memberCiv.MemberId,
PlayerInfoIndex = memberCiv.PlayerInfoIndex,
PlayerId = memberCiv.PlayerId
};
SendMessage(data);
}
@ -263,4 +268,4 @@ namespace TH1_Logic.Steam
BroadcastMessage(data);
}
}
}
}

View File

@ -121,11 +121,13 @@ namespace TH1_Logic.Steam
var civ = Main.Instance.MapConfig.GetMemberCiv(selfMemberId);
if (civ != null)
{
Main.Instance.MapConfig.GetPlayerInfoByIndex(civ.PlayerInfoIndex, out var info);
GUILayout.BeginHorizontal();
if (GUILayout.Button("改1")) civ.CivId = 1;
if (GUILayout.Button("改2")) civ.CivId = 2;
if (GUILayout.Button("改3")) civ.CivId = 3;
if (GUILayout.Button("改4")) civ.CivId = 4;
GUILayout.Label($"Idx:{civ.PlayerInfoIndex} Civ:{info?.CivId ?? 0} Force:{info?.ForceId ?? 0}");
if (GUILayout.Button("改Idx0")) { civ.PlayerInfoIndex = 0; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
if (GUILayout.Button("改Idx1")) { civ.PlayerInfoIndex = 1; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
if (GUILayout.Button("改Idx2")) { civ.PlayerInfoIndex = 2; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
if (GUILayout.Button("改Idx3")) { civ.PlayerInfoIndex = 3; Main.Instance.MapConfig.UpdateMemberCiv(civ); }
GUILayout.EndHorizontal();
}
}
@ -138,4 +140,4 @@ namespace TH1_Logic.Steam
#endif
}
}
}