From 65f7d460257263827339378f0cd51615747b633b Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 27 Mar 2016 13:11:37 +0100 Subject: [PATCH] Parse map rules and players from remote maps. --- OpenRA.Game/Map/MapCache.cs | 4 +-- OpenRA.Game/Map/MapPreview.cs | 28 +++++++++++++++++-- .../Widgets/Logic/Lobby/LobbyLogic.cs | 27 ++++++++++++------ 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/OpenRA.Game/Map/MapCache.cs b/OpenRA.Game/Map/MapCache.cs index a05bd954f3..de966d3252 100644 --- a/OpenRA.Game/Map/MapCache.cs +++ b/OpenRA.Game/Map/MapCache.cs @@ -112,7 +112,7 @@ namespace OpenRA } } - public void QueryRemoteMapDetails(IEnumerable uids) + public void QueryRemoteMapDetails(IEnumerable uids, Action mapDetailsReceived = null) { var maps = uids.Distinct() .Select(uid => previews[uid]) @@ -144,7 +144,7 @@ namespace OpenRA { var yaml = MiniYaml.FromString(data); foreach (var kv in yaml) - maps[kv.Key].UpdateRemoteSearch(MapStatus.DownloadAvailable, kv.Value); + maps[kv.Key].UpdateRemoteSearch(MapStatus.DownloadAvailable, kv.Value, mapDetailsReceived); } catch { diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index d3a0a5ec9e..e21fa9df54 100644 --- a/OpenRA.Game/Map/MapPreview.cs +++ b/OpenRA.Game/Map/MapPreview.cs @@ -17,6 +17,7 @@ using System.Drawing; using System.IO; using System.Linq; using System.Net; +using System.Text; using System.Threading; using OpenRA.FileSystem; using OpenRA.Graphics; @@ -51,6 +52,9 @@ namespace OpenRA public readonly MapGridType map_grid_type; public readonly string minimap; public readonly bool downloading; + public readonly string tileset; + public readonly string rules; + public readonly string players_block; } public class MapPreview : IDisposable, IReadOnlyFileSystem @@ -334,7 +338,7 @@ namespace OpenRA return true; } - public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml) + public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action parseMetadata = null) { var newData = innerData.Clone(); newData.Status = status; @@ -358,14 +362,31 @@ namespace OpenRA newData.Author = r.author; newData.PlayerCount = r.players; newData.Bounds = r.bounds; + newData.TileSet = r.tileset; var spawns = new CPos[r.spawnpoints.Length / 2]; for (var j = 0; j < r.spawnpoints.Length; j += 2) spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]); newData.SpawnPoints = spawns; newData.GridType = r.map_grid_type; - newData.Preview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap))); + + var playersString = Encoding.UTF8.GetString(Convert.FromBase64String(r.players_block)); + newData.Players = new MapPlayers(MiniYaml.FromString(playersString)); + + newData.SetRulesetGenerator(modData, () => + { + var rulesString = Encoding.UTF8.GetString(Convert.FromBase64String(r.rules)); + var rulesYaml = new MiniYaml("", MiniYaml.FromString(rulesString)).ToDictionary(); + var ruleDefinitions = LoadRuleSection(rulesYaml, "Rules"); + var weaponDefinitions = LoadRuleSection(rulesYaml, "Weapons"); + var voiceDefinitions = LoadRuleSection(rulesYaml, "Voices"); + var musicDefinitions = LoadRuleSection(rulesYaml, "Music"); + var notificationDefinitions = LoadRuleSection(rulesYaml, "Notifications"); + var sequenceDefinitions = LoadRuleSection(rulesYaml, "Sequences"); + return Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions, + voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions); + }); } catch (Exception) { } @@ -374,6 +395,9 @@ namespace OpenRA if (innerData.Preview != null) cache.CacheMinimap(this); + + if (parseMetadata != null) + parseMetadata(this); } // Update the status and class unconditionally diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index e6bfdfbf78..ad4f177d31 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -326,7 +326,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var startGameButton = lobby.GetOrNull("START_GAME_BUTTON"); if (startGameButton != null) { - startGameButton.IsDisabled = () => configurationDisabled() || + startGameButton.IsDisabled = () => configurationDisabled() || Map.Status != MapStatus.Available || orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null) || (orderManager.LobbyInfo.GlobalSettings.DisableSingleplayer && orderManager.LobbyInfo.IsSinglePlayer); @@ -464,8 +464,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; startingUnits.IsDisabled = () => configurationDisabled() || startUnitsLocked.Update(Map); - startingUnits.GetText = () => Map.Status != MapStatus.Available || - !Map.RulesLoaded || startUnitsLocked.Update(Map) ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass); + startingUnits.GetText = () => !Map.RulesLoaded || startUnitsLocked.Update(Map) ? + "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass); startingUnits.OnMouseDown = _ => { var classes = startUnitsInfos.Update(Map).Select(a => a.Class).Distinct(); @@ -496,8 +496,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic map => map.Rules.Actors["player"].TraitInfo()); startingCash.IsDisabled = () => configurationDisabled() || playerResources.Update(Map).DefaultCashLocked; - startingCash.GetText = () => Map.Status != MapStatus.Available || - !Map.RulesLoaded || playerResources.Update(Map).DefaultCashLocked ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash); + startingCash.GetText = () => !Map.RulesLoaded || playerResources.Update(Map).DefaultCashLocked ? + "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash); startingCash.OnMouseDown = _ => { var options = playerResources.Update(Map).SelectableCash.Select(c => new DropDownOption @@ -533,8 +533,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic techLevelDescription.IsVisible = techLevel.IsVisible; techLevel.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).TechLevelLocked; - techLevel.GetText = () => Map.Status != MapStatus.Available || - !Map.RulesLoaded || mapOptions.Update(Map).TechLevelLocked ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel); + techLevel.GetText = () => !Map.RulesLoaded || mapOptions.Update(Map).TechLevelLocked ? + "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel); techLevel.OnMouseDown = _ => { var options = techLevels.Update(Map).Select(c => new DropDownOption @@ -776,6 +776,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic return true; } + void LoadMapPreviewRules(MapPreview map) + { + new Task(() => + { + // Force map rules to be loaded on this background thread + var unused = map.Rules; + }).Start(); + } + void UpdateCurrentMap() { var uid = orderManager.LobbyInfo.GlobalSettings.Map; @@ -814,8 +823,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic }); }).Start(); } + else if (Map.Status == MapStatus.DownloadAvailable) + LoadMapPreviewRules(Map); else if (Game.Settings.Game.AllowDownloading) - modData.MapCache.QueryRemoteMapDetails(new[] { uid }); + modData.MapCache.QueryRemoteMapDetails(new[] { uid }, LoadMapPreviewRules); } void UpdatePlayerList()