Add metadata block to replays

The replay files are just streams all network communication so to
get any info out of them it is necessary to play back the stream
until the wanted information is reached.

This introduces a new metadata block placed at the end of the
replay files and logic to read the new block, or fall back to
playing back the stream for older files.

The replay browser is also updated to use the metadata information
instead of reading the replay stream directly.
This commit is contained in:
Pavlos Touboulidis
2014-04-28 00:44:04 +03:00
parent 4454c0c2f8
commit 98a05b61b3
8 changed files with 353 additions and 86 deletions

View File

@@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Network;
using OpenRA.Widgets;
@@ -51,11 +52,22 @@ namespace OpenRA.Mods.RA.Widgets.Logic
rl.RemoveChildren();
if (Directory.Exists(dir))
{
var files = Directory.GetFiles(dir, "*.rep").Reverse();
foreach (var replayFile in files)
AddReplay(rl, replayFile, template);
List<ReplayMetadata> replays;
SelectReplay(files.FirstOrDefault());
using (new Support.PerfTimer("Load replays"))
{
replays = Directory
.GetFiles(dir, "*.rep")
.Select((filename) => ReplayMetadata.Read(filename))
.Where((r) => r != null)
.OrderByDescending((r) => Path.GetFileName(r.FilePath))
.ToList();
}
foreach (var replay in replays)
AddReplay(rl, replay, template);
SelectReplay(replays.FirstOrDefault());
}
var watch = panel.Get<ButtonWidget>("WATCH_BUTTON");
@@ -79,63 +91,62 @@ namespace OpenRA.Mods.RA.Widgets.Logic
panel.Get<LabelWidget>("DURATION").GetText = () => selectedDuration;
}
void SelectReplay(string filename)
void SelectReplay(ReplayMetadata replay)
{
if (filename == null)
if (replay == null)
return;
try
{
using (var conn = new ReplayConnection(filename))
var lobby = replay.Session.Value;
selectedFilename = replay.FilePath;
selectedMap = Game.modData.MapCache[lobby.GlobalSettings.Map];
selectedSpawns = LobbyUtils.GetSpawnClients(lobby, selectedMap);
selectedDuration = WidgetUtils.FormatTimeSeconds((int)replay.Duration.TotalSeconds);
selectedValid = true;
var clients = lobby.Clients.Where(c => c.Slot != null)
.GroupBy(c => c.Team)
.OrderBy(g => g.Key);
var teams = new Dictionary<string, IEnumerable<Session.Client>>();
var noTeams = clients.Count() == 1;
foreach (var c in clients)
{
selectedFilename = filename;
selectedMap = Game.modData.MapCache[conn.LobbyInfo.GlobalSettings.Map];
selectedSpawns = LobbyUtils.GetSpawnClients(conn.LobbyInfo, selectedMap);
selectedDuration = WidgetUtils.FormatTime(conn.TickCount * Game.NetTickScale);
selectedValid = conn.TickCount > 0;
var label = noTeams ? "Players" : c.Key == 0 ? "No Team" : "Team {0}".F(c.Key);
teams.Add(label, c);
}
var clients = conn.LobbyInfo.Clients.Where(c => c.Slot != null)
.GroupBy(c => c.Team)
.OrderBy(g => g.Key);
playerList.RemoveChildren();
var teams = new Dictionary<string, IEnumerable<Session.Client>>();
var noTeams = clients.Count() == 1;
foreach (var c in clients)
foreach (var kv in teams)
{
var group = kv.Key;
if (group.Length > 0)
{
var label = noTeams ? "Players" : c.Key == 0 ? "No Team" : "Team {0}".F(c.Key);
teams.Add(label, c);
var header = ScrollItemWidget.Setup(playerHeader, () => true, () => {});
header.Get<LabelWidget>("LABEL").GetText = () => group;
playerList.AddChild(header);
}
playerList.RemoveChildren();
foreach (var kv in teams)
foreach (var option in kv.Value)
{
var group = kv.Key;
if (group.Length > 0)
{
var header = ScrollItemWidget.Setup(playerHeader, () => true, () => {});
header.Get<LabelWidget>("LABEL").GetText = () => group;
playerList.AddChild(header);
}
var o = option;
foreach (var option in kv.Value)
{
var o = option;
var color = o.Color.RGB;
var color = o.Color.RGB;
var item = ScrollItemWidget.Setup(playerTemplate, () => false, () => { });
var item = ScrollItemWidget.Setup(playerTemplate, () => false, () => { });
var label = item.Get<LabelWidget>("LABEL");
label.GetText = () => o.Name;
label.GetColor = () => color;
var label = item.Get<LabelWidget>("LABEL");
label.GetText = () => o.Name;
label.GetColor = () => color;
var flag = item.Get<ImageWidget>("FLAG");
flag.GetImageCollection = () => "flags";
flag.GetImageName = () => o.Country;
var flag = item.Get<ImageWidget>("FLAG");
flag.GetImageCollection = () => "flags";
flag.GetImageName = () => o.Country;
playerList.AddChild(item);
}
playerList.AddChild(item);
}
}
}
@@ -157,13 +168,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
}
}
void AddReplay(ScrollPanelWidget list, string filename, ScrollItemWidget template)
void AddReplay(ScrollPanelWidget list, ReplayMetadata replay, ScrollItemWidget template)
{
var item = ScrollItemWidget.Setup(template,
() => selectedFilename == filename,
() => SelectReplay(filename),
() => selectedFilename == replay.FilePath,
() => SelectReplay(replay),
() => WatchReplay());
var f = Path.GetFileName(filename);
var f = Path.GetFileName(replay.FilePath);
item.Get<LabelWidget>("TITLE").GetText = () => f;
list.AddChild(item);
}