Save map generation args in replays/saves instead of full map.
This commit is contained in:
committed by
Gustas Kažukauskas
parent
0d479e7c18
commit
fdb4ce4e0f
@@ -158,16 +158,6 @@ namespace OpenRA.FileSystem
|
||||
pkg.CommitUpdate();
|
||||
Commit();
|
||||
}
|
||||
|
||||
public static ReadWriteZipFile FromBase64String(string data)
|
||||
{
|
||||
return new ReadWriteZipFile(Convert.FromBase64String(data));
|
||||
}
|
||||
|
||||
public string ToBase64String()
|
||||
{
|
||||
return Convert.ToBase64String(pkgStream.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ZipFolder : IReadOnlyPackage
|
||||
|
||||
@@ -13,7 +13,6 @@ using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
@@ -29,7 +28,6 @@ namespace OpenRA
|
||||
|
||||
public string MapUid;
|
||||
public string MapTitle;
|
||||
public string MapData;
|
||||
public int FinalGameTick;
|
||||
|
||||
/// <summary>Game start timestamp (when the recoding started).</summary>
|
||||
@@ -44,24 +42,12 @@ namespace OpenRA
|
||||
public IList<Player> Players { get; }
|
||||
public FrozenSet<int> DisabledSpawnPoints = FrozenSet<int>.Empty;
|
||||
|
||||
public MapPreview MapPreview
|
||||
{
|
||||
get
|
||||
{
|
||||
var preview = Game.ModData.MapCache[MapUid];
|
||||
if (preview.Status != MapStatus.Available && MapData != null)
|
||||
{
|
||||
var package = ZipFileLoader.ReadWriteZipFile.FromBase64String(MapData);
|
||||
preview.UpdateFromMap(package, MapClassification.Generated);
|
||||
}
|
||||
|
||||
return preview;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Player> HumanPlayers { get { return Players.Where(p => p.IsHuman); } }
|
||||
public bool IsSinglePlayer => HumanPlayers.Count() == 1;
|
||||
|
||||
[FieldLoader.Ignore]
|
||||
public MapGenerationArgs MapGenerationArgs;
|
||||
|
||||
readonly Dictionary<OpenRA.Player, Player> playersByRuntime;
|
||||
|
||||
public GameInformation()
|
||||
@@ -70,6 +56,15 @@ namespace OpenRA
|
||||
playersByRuntime = [];
|
||||
}
|
||||
|
||||
public MapPreview GetMapPreview(ModData modData)
|
||||
{
|
||||
var preview = modData.MapCache[MapUid];
|
||||
if (preview.Status != MapStatus.Available && MapGenerationArgs != null)
|
||||
modData.MapCache.GenerateMap(modData, MapGenerationArgs);
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
public static GameInformation Deserialize(string data, string path)
|
||||
{
|
||||
try
|
||||
@@ -90,6 +85,10 @@ namespace OpenRA
|
||||
case "Player":
|
||||
info.Players.Add(FieldLoader.Load<Player>(node.Value));
|
||||
break;
|
||||
|
||||
case "MapGenerationArgs":
|
||||
info.MapGenerationArgs = FieldLoader.Load<MapGenerationArgs>(node.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +111,9 @@ namespace OpenRA
|
||||
for (var i = 0; i < Players.Count; i++)
|
||||
nodes.Add(new MiniYamlNode($"Player@{i}", FieldSaver.Save(Players[i])));
|
||||
|
||||
if (MapGenerationArgs != null)
|
||||
nodes.Add(new MiniYamlNode("MapGenerationArgs", new MiniYaml("", MiniYaml.FromString(MapGenerationArgs.Serialize(), "MapGenerationArgs"))));
|
||||
|
||||
return nodes.WriteToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace OpenRA
|
||||
public MapClassification Class;
|
||||
public MapVisibility Visibility;
|
||||
public DateTime ModifiedDate;
|
||||
public MapGenerationArgs GenerationArgs;
|
||||
|
||||
public MiniYaml RuleDefinitions;
|
||||
public MiniYaml WeaponDefinitions;
|
||||
@@ -219,19 +220,6 @@ namespace OpenRA
|
||||
return new Map(modData, package);
|
||||
}
|
||||
|
||||
public string ToBase64String()
|
||||
{
|
||||
LoadPackage();
|
||||
if (package is not ZipFileLoader.ReadWriteZipFile p)
|
||||
{
|
||||
var map = new Map(modData, package);
|
||||
p = new ZipFileLoader.ReadWriteZipFile();
|
||||
map.Save(p);
|
||||
}
|
||||
|
||||
return p.ToBase64String();
|
||||
}
|
||||
|
||||
IReadOnlyPackage parentPackage;
|
||||
|
||||
volatile InnerData innerData;
|
||||
@@ -259,6 +247,8 @@ namespace OpenRA
|
||||
public ActorInfo PlayerActorInfo => innerData.PlayerActorInfo;
|
||||
public DateTime ModifiedDate => innerData.ModifiedDate;
|
||||
|
||||
public MapGenerationArgs GenerationArgs => innerData.GenerationArgs;
|
||||
|
||||
public long DownloadBytes { get; private set; }
|
||||
public int DownloadPercentage { get; private set; }
|
||||
|
||||
@@ -482,6 +472,7 @@ namespace OpenRA
|
||||
newData.Status = MapStatus.Generating;
|
||||
newData.Title = args.Title;
|
||||
newData.Author = args.Author;
|
||||
newData.GenerationArgs = args;
|
||||
}
|
||||
else
|
||||
newData.Status = MapStatus.Unavailable;
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace OpenRA.Network
|
||||
public Dictionary<string, Session.Slot> Slots { get; private set; }
|
||||
public Dictionary<string, SlotClient> SlotClients { get; private set; }
|
||||
public Dictionary<int, MiniYaml> TraitData = [];
|
||||
public string MapData;
|
||||
public MapGenerationArgs MapGenerationArgs;
|
||||
|
||||
// Set on game start
|
||||
int[] clientsBySlotIndex = [];
|
||||
@@ -142,7 +142,9 @@ namespace OpenRA.Network
|
||||
SlotClients.Add(slotClient.Slot, slotClient);
|
||||
}
|
||||
|
||||
MapData = rs.ReadLengthPrefixedString(Encoding.UTF8, Connection.MaxOrderLength);
|
||||
var mapGenerationArgs = rs.ReadLengthPrefixedString(Encoding.UTF8, Connection.MaxOrderLength);
|
||||
if (!string.IsNullOrEmpty(mapGenerationArgs))
|
||||
MapGenerationArgs = FieldLoader.Load<MapGenerationArgs>(new MiniYaml("", MiniYaml.FromString(mapGenerationArgs, $"{filepath}:mapGenerationArgs")));
|
||||
|
||||
if (rs.Position != traitDataOffset || rs.ReadInt32() != TraitDataMarker)
|
||||
throw new InvalidDataException("Invalid orasav file");
|
||||
@@ -159,7 +161,7 @@ namespace OpenRA.Network
|
||||
public void StartGame(Session lobbyInfo, MapPreview map)
|
||||
{
|
||||
if (map.Class == MapClassification.Generated)
|
||||
MapData = map.ToBase64String();
|
||||
MapGenerationArgs = map.GenerationArgs;
|
||||
|
||||
// Game orders are mapped from a client index to the slot that they occupy
|
||||
// Orders from spectators are ignored, which is not a problem in practice
|
||||
@@ -312,7 +314,7 @@ namespace OpenRA.Network
|
||||
.ToList();
|
||||
file.WriteLengthPrefixedString(Encoding.UTF8, slotClientNodes.WriteToString());
|
||||
|
||||
file.WriteLengthPrefixedString(Encoding.UTF8, MapData);
|
||||
file.WriteLengthPrefixedString(Encoding.UTF8, MapGenerationArgs?.Serialize() ?? string.Empty);
|
||||
|
||||
var traitDataOffset = file.Length;
|
||||
file.Write(TraitDataMarker);
|
||||
|
||||
@@ -1356,7 +1356,7 @@ namespace OpenRA.Server
|
||||
};
|
||||
|
||||
if (Map.Class == MapClassification.Generated)
|
||||
gameInfo.MapData = Map.ToBase64String();
|
||||
gameInfo.MapGenerationArgs = Map.GenerationArgs;
|
||||
|
||||
// Replay metadata should only include the playable players
|
||||
foreach (var p in worldPlayers)
|
||||
|
||||
@@ -228,7 +228,7 @@ namespace OpenRA
|
||||
|
||||
var preview = modData.MapCache[Map.Uid];
|
||||
if (preview.Class == MapClassification.Generated)
|
||||
gameInfo.MapData = preview.ToBase64String();
|
||||
gameInfo.MapGenerationArgs = preview.GenerationArgs;
|
||||
|
||||
RulesContainTemporaryBlocker = Map.Rules.Actors.Any(a => a.Value.HasTraitInfo<ITemporaryBlockerInfo>());
|
||||
gameSettings = GetSettings<GameSettings>();
|
||||
|
||||
Reference in New Issue
Block a user