forked from OpenRA/OpenRA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGameInformation.cs
198 lines (157 loc) · 5.56 KB
/
GameInformation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#region Copyright & License Information
/*
* Copyright (c) The OpenRA Developers and Contributors
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Network;
using OpenRA.Primitives;
namespace OpenRA
{
public class GameInformation
{
public string Mod;
public string Version;
public string MapUid;
public string MapTitle;
public int FinalGameTick;
/// <summary>Game start timestamp (when the recoding started).</summary>
public DateTime StartTimeUtc;
/// <summary>Game end timestamp (when the recoding stopped).</summary>
public DateTime EndTimeUtc;
/// <summary>Gets the game's duration, from the time the game started until the replay recording stopped.</summary>
public TimeSpan Duration => EndTimeUtc > StartTimeUtc ? EndTimeUtc - StartTimeUtc : TimeSpan.Zero;
public IList<Player> Players { get; }
public HashSet<int> DisabledSpawnPoints = new();
public MapPreview MapPreview => Game.ModData.MapCache[MapUid];
public IEnumerable<Player> HumanPlayers { get { return Players.Where(p => p.IsHuman); } }
public bool IsSinglePlayer => HumanPlayers.Count() == 1;
readonly Dictionary<OpenRA.Player, Player> playersByRuntime;
public GameInformation()
{
Players = new List<Player>();
playersByRuntime = new Dictionary<OpenRA.Player, Player>();
}
public static GameInformation Deserialize(string data)
{
try
{
var info = new GameInformation();
var nodes = MiniYaml.FromString(data);
foreach (var node in nodes)
{
var keyParts = node.Key.Split('@');
switch (keyParts[0])
{
case "Root":
FieldLoader.Load(info, node.Value);
break;
case "Player":
info.Players.Add(FieldLoader.Load<Player>(node.Value));
break;
}
}
return info;
}
catch (YamlException)
{
Log.Write("debug", $"GameInformation deserialized invalid MiniYaml:\n{data}");
throw;
}
}
public string Serialize()
{
var nodes = new List<MiniYamlNode>
{
new MiniYamlNode("Root", FieldSaver.Save(this))
};
for (var i = 0; i < Players.Count; i++)
nodes.Add(new MiniYamlNode($"Player@{i}", FieldSaver.Save(Players[i])));
return nodes.WriteToString();
}
/// <summary>Adds the player information at start-up.</summary>
public void AddPlayer(OpenRA.Player runtimePlayer, Session lobbyInfo)
{
if (runtimePlayer == null)
throw new ArgumentNullException(nameof(runtimePlayer));
if (lobbyInfo == null)
throw new ArgumentNullException(nameof(lobbyInfo));
// We don't care about spectators and map players
if (runtimePlayer.NonCombatant || !runtimePlayer.Playable)
return;
// Find the lobby client that created the runtime player
var client = lobbyInfo.ClientWithIndex(runtimePlayer.ClientIndex);
if (client == null)
return;
var player = new Player
{
ClientIndex = runtimePlayer.ClientIndex,
Name = runtimePlayer.PlayerName,
IsHuman = !runtimePlayer.IsBot,
IsBot = runtimePlayer.IsBot,
FactionName = runtimePlayer.Faction.Name,
FactionId = runtimePlayer.Faction.InternalName,
DisplayFactionName = runtimePlayer.DisplayFaction.Name,
DisplayFactionId = runtimePlayer.DisplayFaction.InternalName,
Color = runtimePlayer.Color,
Team = client.Team,
Handicap = client.Handicap,
SpawnPoint = runtimePlayer.SpawnPoint,
IsRandomFaction = runtimePlayer.Faction.InternalName != client.Faction,
IsRandomSpawnPoint = runtimePlayer.DisplaySpawnPoint == 0,
Fingerprint = client.Fingerprint
};
playersByRuntime.Add(runtimePlayer, player);
Players.Add(player);
}
/// <summary>Gets the player information for the specified runtime player instance.</summary>
public Player GetPlayer(OpenRA.Player runtimePlayer)
{
playersByRuntime.TryGetValue(runtimePlayer, out var player);
return player;
}
public class Player
{
#region Start-up information
public int ClientIndex;
/// <summary>The player name, not guaranteed to be unique.</summary>
public string Name;
public bool IsHuman;
public bool IsBot;
/// <summary>The faction's display name.</summary>
public string FactionName;
/// <summary>The faction ID, a.k.a. the faction's internal name.</summary>
public string FactionId;
public Color Color;
/// <summary>The faction (including Random, etc.) that was selected in the lobby.</summary>
public string DisplayFactionName;
public string DisplayFactionId;
/// <summary>The team ID on start-up, or 0 if the player is not part of a team.</summary>
public int Team;
public int SpawnPoint;
public int Handicap;
/// <summary>True if the faction was chosen at random; otherwise, false.</summary>
public bool IsRandomFaction;
/// <summary>True if the spawn point was chosen at random; otherwise, false.</summary>
public bool IsRandomSpawnPoint;
/// <summary>Player authentication fingerprint for the OpenRA forum.</summary>
public string Fingerprint;
#endregion
#region
/// <summary>The game outcome for this player.</summary>
public WinState Outcome;
/// <summary>The time when this player won or lost the game.</summary>
public DateTime OutcomeTimestampUtc;
/// <summary>The frame at which this player disconnected.</summary>
public int DisconnectFrame;
#endregion
}
}
}