Load MapPreview data without initialising a full Map.

This commit is contained in:
Paul Chote
2016-02-06 12:37:19 +00:00
parent ab25e26312
commit 02ab54c9bc
3 changed files with 98 additions and 21 deletions

View File

@@ -44,20 +44,27 @@ namespace OpenRA
public void LoadMaps() public void LoadMaps()
{ {
// Utility mod that does not support maps
if (!modData.Manifest.Contains<MapGrid>())
return;
// Expand the dictionary (dir path, dir type) to a dictionary of (map path, dir type) // Expand the dictionary (dir path, dir type) to a dictionary of (map path, dir type)
var mapPaths = modData.Manifest.MapFolders.SelectMany(kv => var mapPaths = modData.Manifest.MapFolders.SelectMany(kv =>
FindMapsIn(modData.ModFiles, kv.Key).ToDictionary(p => p, p => string.IsNullOrEmpty(kv.Value) FindMapsIn(modData.ModFiles, kv.Key).ToDictionary(p => p, p => string.IsNullOrEmpty(kv.Value)
? MapClassification.Unknown : Enum<MapClassification>.Parse(kv.Value))); ? MapClassification.Unknown : Enum<MapClassification>.Parse(kv.Value)));
var mapGrid = modData.Manifest.Get<MapGrid>();
foreach (var path in mapPaths) foreach (var path in mapPaths)
{ {
try try
{ {
using (new Support.PerfTimer(path.Key)) using (new Support.PerfTimer(path.Key))
{ {
var map = new Map(path.Key); using (var package = modData.ModFiles.OpenPackage(path.Key))
if (modData.Manifest.MapCompatibility.Contains(map.RequiresMod)) {
previews[map.Uid].UpdateFromMap(map, path.Value); var uid = Map.ComputeUID(package);
previews[uid].UpdateFromMap(package, path.Value, modData.Manifest.MapCompatibility, mapGrid.Type);
}
} }
} }
catch (Exception e) catch (Exception e)

View File

@@ -17,6 +17,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using OpenRA.FileSystem;
using OpenRA.Graphics; using OpenRA.Graphics;
namespace OpenRA namespace OpenRA
@@ -92,7 +93,7 @@ namespace OpenRA
return null; return null;
} }
public void SetMinimap(Sprite minimap) internal void SetMinimap(Sprite minimap)
{ {
this.minimap = minimap; this.minimap = minimap;
generatingMinimap = false; generatingMinimap = false;
@@ -114,26 +115,90 @@ namespace OpenRA
Visibility = MapVisibility.Lobby; Visibility = MapVisibility.Lobby;
} }
public void UpdateFromMap(Map m, MapClassification classification) public void UpdateFromMap(IReadOnlyPackage p, MapClassification classification, string[] mapCompatibility, MapGridType gridType)
{ {
Path = m.Path; Dictionary<string, MiniYaml> yaml;
Title = m.Title; using (var yamlStream = p.GetStream("map.yaml"))
Type = m.Type; {
Type = m.Type; if (yamlStream == null)
Author = m.Author; throw new FileNotFoundException("Required file map.yaml not present in this map");
Bounds = m.Bounds;
SpawnPoints = m.SpawnPoints.Value; yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, "map.yaml")).ToDictionary();
GridType = m.Grid.Type; }
CustomPreview = m.CustomPreview;
Status = MapStatus.Available; Path = p.Name;
GridType = gridType;
Class = classification; Class = classification;
Visibility = m.Visibility;
var players = new MapPlayers(m.PlayerDefinitions).Players; MiniYaml temp;
if (yaml.TryGetValue("MapFormat", out temp))
{
var format = FieldLoader.GetValue<int>("MapFormat", temp.Value);
if (format != Map.SupportedMapFormat)
throw new InvalidDataException("Map format {0} is not supported.".F(format));
}
if (yaml.TryGetValue("Title", out temp))
Title = temp.Value;
if (yaml.TryGetValue("Type", out temp))
Type = temp.Value;
if (yaml.TryGetValue("Author", out temp))
Author = temp.Value;
if (yaml.TryGetValue("Bounds", out temp))
Bounds = FieldLoader.GetValue<Rectangle>("Bounds", temp.Value);
if (yaml.TryGetValue("Visibility", out temp))
Visibility = FieldLoader.GetValue<MapVisibility>("Visibility", temp.Value);
string requiresMod = string.Empty;
if (yaml.TryGetValue("RequiresMod", out temp))
requiresMod = temp.Value;
Status = mapCompatibility == null || mapCompatibility.Contains(requiresMod) ? MapStatus.Available : MapStatus.Unavailable;
try
{
// Actor definitions may change if the map format changes
MiniYaml actorDefinitions;
if (yaml.TryGetValue("Actors", out actorDefinitions))
{
var spawns = new List<CPos>();
foreach (var kv in actorDefinitions.Nodes.Where(d => d.Value.Value == "mpspawn"))
{
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
spawns.Add(s.InitDict.Get<LocationInit>().Value(null));
}
SpawnPoints = spawns.ToArray();
}
else
SpawnPoints = new CPos[0];
}
catch (Exception)
{
SpawnPoints = new CPos[0];
Status = MapStatus.Unavailable;
}
try
{
// Player definitions may change if the map format changes
MiniYaml playerDefinitions;
if (yaml.TryGetValue("Players", out playerDefinitions))
{
var players = new MapPlayers(playerDefinitions.Nodes).Players;
PlayerCount = players.Count(x => x.Value.Playable); PlayerCount = players.Count(x => x.Value.Playable);
SuitableForInitialMap = EvaluateUserFriendliness(players); SuitableForInitialMap = EvaluateUserFriendliness(players);
} }
}
catch (Exception)
{
Status = MapStatus.Unavailable;
}
if (p.Contains("map.png"))
using (var dataStream = p.GetStream("map.png"))
CustomPreview = new Bitmap(dataStream);
}
bool EvaluateUserFriendliness(Dictionary<string, PlayerReference> players) bool EvaluateUserFriendliness(Dictionary<string, PlayerReference> players)
{ {
@@ -210,6 +275,7 @@ namespace OpenRA
if (!Directory.Exists(baseMapPath)) if (!Directory.Exists(baseMapPath))
Directory.CreateDirectory(baseMapPath); Directory.CreateDirectory(baseMapPath);
var modData = Game.ModData;
new Thread(() => new Thread(() =>
{ {
// Request the filename from the server // Request the filename from the server
@@ -247,7 +313,11 @@ namespace OpenRA
} }
Log.Write("debug", "Downloaded map to '{0}'", mapPath); Log.Write("debug", "Downloaded map to '{0}'", mapPath);
Game.RunAfterTick(() => UpdateFromMap(new Map(mapPath), MapClassification.User)); Game.RunAfterTick(() =>
{
using (var package = modData.ModFiles.OpenPackage(mapPath))
UpdateFromMap(package, MapClassification.User, null, GridType);
});
}; };
download = new Download(mapUrl, mapPath, onDownloadProgress, onDownloadComplete); download = new Download(mapUrl, mapPath, onDownloadProgress, onDownloadComplete);

View File

@@ -168,7 +168,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Update the map cache so it can be loaded without restarting the game // Update the map cache so it can be loaded without restarting the game
var classification = mapDirectories[directoryDropdown.Text]; var classification = mapDirectories[directoryDropdown.Text];
modData.MapCache[map.Uid].UpdateFromMap(map, classification); modData.MapCache[map.Uid].UpdateFromMap(map.Container, classification, null, map.Grid.Type);
Console.WriteLine("Saved current map at {0}", combinedPath); Console.WriteLine("Saved current map at {0}", combinedPath);
Ui.CloseWindow(); Ui.CloseWindow();