List of changes: * Better and more filters with new layout, for both mods. * Rename/Delete/Detele all functionality. * Simplified ReplayMetadata class considerably by introducing a new GameInformation data object. The new GameInformation class contains more information than previously available so the new solution is not compatible with old replays, meaning it can't read old replays. * Better and cleaner game information gathering in order to be written at the end of the replay file. * Revert changes to ReplayConnection, no longer necessary. * Better exception message on missing sprites and fonts. * New "SpawnOccupant" class that holds all the information needed by the MapPreviewWidget to visualize a spawn point. It was using Session.Client before and it was necessary to separate it to be able to show information not available at lobby time. * Fix keyboard focus UI bug when closing a window would not remove focus.
137 lines
3.2 KiB
C#
137 lines
3.2 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
|
* 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. For more information,
|
|
* see COPYING.
|
|
*/
|
|
#endregion
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using OpenRA.Network;
|
|
|
|
namespace OpenRA.FileFormats
|
|
{
|
|
public class ReplayMetadata
|
|
{
|
|
// Must be an invalid replay 'client' value
|
|
public const int MetaStartMarker = -1;
|
|
public const int MetaEndMarker = -2;
|
|
public const int MetaVersion = 0x00000001;
|
|
|
|
public readonly GameInformation GameInfo;
|
|
public string FilePath { get; private set; }
|
|
|
|
public ReplayMetadata(GameInformation info)
|
|
{
|
|
if (info == null)
|
|
throw new ArgumentNullException("info");
|
|
|
|
GameInfo = info;
|
|
}
|
|
|
|
ReplayMetadata(BinaryReader reader, string path)
|
|
{
|
|
FilePath = path;
|
|
|
|
// Read start marker
|
|
if (reader.ReadInt32() != MetaStartMarker)
|
|
throw new InvalidOperationException("Expected MetaStartMarker but found an invalid value.");
|
|
|
|
// Read version
|
|
var version = reader.ReadInt32();
|
|
if (version != MetaVersion)
|
|
throw new NotSupportedException("Metadata version {0} is not supported".F(version));
|
|
|
|
// Read game info
|
|
string data = ReadUtf8String(reader);
|
|
GameInfo = GameInformation.Deserialize(data);
|
|
}
|
|
|
|
public void Write(BinaryWriter writer)
|
|
{
|
|
// Write start marker & version
|
|
writer.Write(MetaStartMarker);
|
|
writer.Write(MetaVersion);
|
|
|
|
// Write data
|
|
int dataLength = 0;
|
|
{
|
|
// Write lobby info data
|
|
dataLength += WriteUtf8String(writer, GameInfo.Serialize());
|
|
}
|
|
|
|
// Write total length & end marker
|
|
writer.Write(dataLength);
|
|
writer.Write(MetaEndMarker);
|
|
}
|
|
|
|
public void RenameFile(string newFilenameWithoutExtension)
|
|
{
|
|
var newPath = Path.Combine(Path.GetDirectoryName(FilePath), newFilenameWithoutExtension) + ".rep";
|
|
File.Move(FilePath, newPath);
|
|
FilePath = newPath;
|
|
}
|
|
|
|
public static ReplayMetadata Read(string path)
|
|
{
|
|
using (var fs = new FileStream(path, FileMode.Open))
|
|
return Read(fs, path);
|
|
}
|
|
|
|
static ReplayMetadata Read(FileStream fs, string path)
|
|
{
|
|
if (!fs.CanSeek)
|
|
return null;
|
|
|
|
fs.Seek(-(4 + 4), SeekOrigin.End);
|
|
using (var reader = new BinaryReader(fs))
|
|
{
|
|
var dataLength = reader.ReadInt32();
|
|
if (reader.ReadInt32() == MetaEndMarker)
|
|
{
|
|
// go back end marker + length storage + data + version + start marker
|
|
fs.Seek(-(4 + 4 + dataLength + 4 + 4), SeekOrigin.Current);
|
|
try
|
|
{
|
|
return new ReplayMetadata(reader, path);
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
Log.Write("debug", ex.ToString());
|
|
}
|
|
catch (NotSupportedException ex)
|
|
{
|
|
Log.Write("debug", ex.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static int WriteUtf8String(BinaryWriter writer, string text)
|
|
{
|
|
byte[] bytes;
|
|
|
|
if (!string.IsNullOrEmpty(text))
|
|
bytes = Encoding.UTF8.GetBytes(text);
|
|
else
|
|
bytes = new byte[0];
|
|
|
|
writer.Write(bytes.Length);
|
|
writer.Write(bytes);
|
|
|
|
return 4 + bytes.Length;
|
|
}
|
|
|
|
static string ReadUtf8String(BinaryReader reader)
|
|
{
|
|
return Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadInt32()));
|
|
}
|
|
}
|
|
}
|