From d4f8fe16660ae70f70df59e9c53b734c647bd469 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 29 Feb 2016 22:34:20 +0000 Subject: [PATCH] Move map configuration to rules. --- OpenRA.Game/Map/Map.cs | 29 ------------- OpenRA.Game/Network/Session.cs | 2 +- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../ServerTraits/LobbyCommands.cs | 39 ++++++++--------- .../Traits/Player/ProvidesTechPrerequisite.cs | 3 +- OpenRA.Mods.Common/Traits/World/MapOptions.cs | 43 +++++++++++++++++++ .../Widgets/Logic/Lobby/LobbyLogic.cs | 30 ++++++++----- .../Widgets/Logic/MissionBrowserLogic.cs | 20 ++++++--- .../UtilityCommands/ImportTSMapCommand.cs | 1 - mods/cnc/mod.yaml | 1 - mods/cnc/rules/world.yaml | 1 + mods/d2k/mod.yaml | 2 - mods/d2k/rules/world.yaml | 1 + mods/ra/mod.yaml | 2 - mods/ra/rules/world.yaml | 1 + mods/ts/mod.yaml | 1 - mods/ts/rules/world.yaml | 1 + 17 files changed, 102 insertions(+), 76 deletions(-) create mode 100644 OpenRA.Mods.Common/Traits/World/MapOptions.cs diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 23680ea3d7..3b1e217609 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -56,19 +56,6 @@ namespace OpenRA } } - public class MapOptions - { - public string TechLevel; - public string[] Difficulties = { }; - public bool? ShortGame; - - public void UpdateServerSettings(Session.Global settings) - { - if (ShortGame.HasValue) - settings.ShortGame = ShortGame.Value; - } - } - public class MapVideos { public string BackgroundInfo; @@ -122,18 +109,6 @@ namespace OpenRA return SubCellOffsets[(int)subCell]; } - [FieldLoader.LoadUsing("LoadOptions")] public MapOptions Options; - - static object LoadOptions(MiniYaml y) - { - var options = new MapOptions(); - var nodesDict = y.ToDictionary(); - if (nodesDict.ContainsKey("Options")) - FieldLoader.Load(options, nodesDict["Options"]); - - return options; - } - [FieldLoader.LoadUsing("LoadVideos")] public MapVideos Videos; static object LoadVideos(MiniYaml y) @@ -253,7 +228,6 @@ namespace OpenRA MapSize = new int2(size); Tileset = tileset.Id; Videos = new MapVideos(); - Options = new MapOptions(); MapResources = Exts.Lazy(() => new CellLayer(Grid.Type, size)); @@ -495,9 +469,6 @@ namespace OpenRA } root.Add(new MiniYamlNode("Videos", FieldSaver.SaveDifferences(Videos, new MapVideos()))); - - root.Add(new MiniYamlNode("Options", FieldSaver.SaveDifferences(Options, new MapOptions()))); - root.Add(new MiniYamlNode("Players", null, PlayerDefinitions)); root.Add(new MiniYamlNode("Actors", null, ActorDefinitions)); diff --git a/OpenRA.Game/Network/Session.cs b/OpenRA.Game/Network/Session.cs index 3eb3ea5267..63eeb34af5 100644 --- a/OpenRA.Game/Network/Session.cs +++ b/OpenRA.Game/Network/Session.cs @@ -190,7 +190,7 @@ namespace OpenRA.Network public bool Fog = true; public bool AllyBuildRadius = true; public int StartingCash = 5000; - public string TechLevel = "none"; + public string TechLevel; public string StartingUnitsClass; public string GameSpeedType = "default"; public bool ShortGame = true; diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 4190885ebc..48f6a2d047 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -734,6 +734,7 @@ + diff --git a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs index 8f8310da0f..d8d1c12a14 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs @@ -348,7 +348,6 @@ namespace OpenRA.Mods.Common.Server var oldSlots = server.LobbyInfo.Slots.Keys.ToArray(); LoadMap(server); - SetDefaultDifficulty(server); // Reset client states foreach (var c in server.LobbyInfo.Clients) @@ -587,19 +586,23 @@ namespace OpenRA.Mods.Common.Server { "difficulty", s => { - if (!server.Map.Options.Difficulties.Any()) - return true; - if (!client.IsAdmin) { server.SendOrderTo(conn, "Message", "Only the host can set that option."); return true; } - if (s != null && !server.Map.Options.Difficulties.Contains(s)) + var mapOptions = server.Map.Rules.Actors["world"].TraitInfo(); + if (mapOptions.DifficultyLocked || !mapOptions.Difficulties.Any()) + { + server.SendOrderTo(conn, "Message", "Map has disabled difficulty configuration."); + return true; + } + + if (s != null && !mapOptions.Difficulties.Contains(s)) { server.SendOrderTo(conn, "Message", "Invalid difficulty selected: {0}".F(s)); - server.SendOrderTo(conn, "Message", "Supported values: {0}".F(server.Map.Options.Difficulties.JoinWith(", "))); + server.SendOrderTo(conn, "Message", "Supported values: {0}".F(mapOptions.Difficulties.JoinWith(", "))); return true; } @@ -683,7 +686,8 @@ namespace OpenRA.Mods.Common.Server return true; } - if (server.Map.Options.TechLevel != null) + var mapOptions = server.Map.Rules.Actors["world"].TraitInfo(); + if (mapOptions.TechLevelLocked) { server.SendOrderTo(conn, "Message", "Map has disabled Tech configuration."); return true; @@ -939,7 +943,8 @@ namespace OpenRA.Mods.Common.Server return true; } - if (server.Map.Options.ShortGame.HasValue) + var mapOptions = server.Map.Rules.Actors["world"].TraitInfo(); + if (mapOptions.ShortGameLocked) { server.SendOrderTo(conn, "Message", "Map has disabled short game configuration."); return true; @@ -990,7 +995,6 @@ namespace OpenRA.Mods.Common.Server public void ServerStarted(S server) { LoadMap(server); - SetDefaultDifficulty(server); } static Session.Slot MakeSlotFromPlayerReference(PlayerReference pr) @@ -1039,19 +1043,10 @@ namespace OpenRA.Mods.Common.Server var mapBuildRadius = server.Map.Rules.Actors["world"].TraitInfoOrDefault(); gs.AllyBuildRadius = mapBuildRadius != null && mapBuildRadius.AllyBuildRadiusEnabled; - server.Map.Options.UpdateServerSettings(server.LobbyInfo.GlobalSettings); - } - - static void SetDefaultDifficulty(S server) - { - if (!server.Map.Options.Difficulties.Any()) - { - server.LobbyInfo.GlobalSettings.Difficulty = null; - return; - } - - if (!server.Map.Options.Difficulties.Contains(server.LobbyInfo.GlobalSettings.Difficulty)) - server.LobbyInfo.GlobalSettings.Difficulty = server.Map.Options.Difficulties.First(); + var mapOptions = server.Map.Rules.Actors["world"].TraitInfo(); + gs.ShortGame = mapOptions.ShortGameEnabled; + gs.TechLevel = mapOptions.TechLevel; + gs.Difficulty = mapOptions.Difficulty ?? mapOptions.Difficulties.FirstOrDefault(); } static HSLColor SanitizePlayerColor(S server, HSLColor askedColor, int playerIndex, Connection connectionToEcho = null) diff --git a/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs b/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs index eac51c5720..c35c7a1ac5 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs @@ -40,8 +40,7 @@ namespace OpenRA.Mods.Common.Traits public ProvidesTechPrerequisite(ProvidesTechPrerequisiteInfo info, ActorInitializer init) { this.info = info; - var tech = init.World.Map.Options.TechLevel ?? init.World.LobbyInfo.GlobalSettings.TechLevel; - enabled = info.Name == tech; + enabled = info.Name == init.World.LobbyInfo.GlobalSettings.TechLevel; } } } diff --git a/OpenRA.Mods.Common/Traits/World/MapOptions.cs b/OpenRA.Mods.Common/Traits/World/MapOptions.cs new file mode 100644 index 0000000000..a86fc39046 --- /dev/null +++ b/OpenRA.Mods.Common/Traits/World/MapOptions.cs @@ -0,0 +1,43 @@ +#region Copyright & License Information +/* + * Copyright 2007-2016 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, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("Controls the map difficulty, tech level, and short game lobby options.")] + public class MapOptionsInfo : TraitInfo + { + [Desc("Default value of the short game checkbox in the lobby.")] + public readonly bool ShortGameEnabled = true; + + [Desc("Prevent the short game enabled state from being changed in the lobby.")] + public readonly bool ShortGameLocked = false; + + [Desc("Default tech level.")] + public readonly string TechLevel = "Unrestricted"; + + [Desc("Prevent the tech level from being changed in the lobby.")] + public readonly bool TechLevelLocked = false; + + [Desc("Difficulty levels supported by the map.")] + public readonly string[] Difficulties = { }; + + [Desc("Default difficulty level.")] + public readonly string Difficulty = null; + + [Desc("Prevent the difficulty from being changed in the lobby.")] + public readonly bool DifficultyLocked = false; + } + + public class MapOptions { } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index d4d61c6d5f..5084aa284d 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -406,8 +406,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic var shortGame = optionsBin.GetOrNull("SHORTGAME_CHECKBOX"); if (shortGame != null) { + var shortGameLocked = new CachedTransform( + map => map.Rules.Actors["world"].TraitInfo().ShortGameLocked); + shortGame.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.ShortGame; - shortGame.IsDisabled = () => configurationDisabled() || Map.Options.ShortGame.HasValue; + shortGame.IsDisabled = () => configurationDisabled() || shortGameLocked.Update(Map); shortGame.OnClick = () => orderManager.IssueOrder(Order.Command( "shortgame {0}".F(!orderManager.LobbyInfo.GlobalSettings.ShortGame))); } @@ -415,12 +418,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic var difficulty = optionsBin.GetOrNull("DIFFICULTY_DROPDOWNBUTTON"); if (difficulty != null) { - difficulty.IsVisible = () => Map != null && Map.Options.Difficulties.Any(); - difficulty.IsDisabled = configurationDisabled; + var mapOptions = new CachedTransform( + map => map.Rules.Actors["world"].TraitInfo()); + + difficulty.IsVisible = () => Map != null && mapOptions.Update(Map).Difficulties.Any(); + difficulty.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).DifficultyLocked; difficulty.GetText = () => orderManager.LobbyInfo.GlobalSettings.Difficulty; difficulty.OnMouseDown = _ => { - var options = Map.Options.Difficulties.Select(d => new DropDownOption + var options = mapOptions.Update(Map).Difficulties.Select(d => new DropDownOption { Title = d, IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d, @@ -514,19 +520,23 @@ namespace OpenRA.Mods.Common.Widgets.Logic var techLevel = optionsBin.GetOrNull("TECHLEVEL_DROPDOWNBUTTON"); if (techLevel != null) { - var techTraits = modRules.Actors["player"].TraitInfos().ToList(); - techLevel.IsVisible = () => techTraits.Count > 0; + var mapOptions = new CachedTransform( + map => map.Rules.Actors["world"].TraitInfo()); + var techLevels = new CachedTransform>( + map => map.Rules.Actors["player"].TraitInfos().ToList()); + + techLevel.IsVisible = () => Map != null && techLevels.Update(Map).Any(); var techLevelDescription = optionsBin.GetOrNull("TECHLEVEL_DESC"); if (techLevelDescription != null) - techLevelDescription.IsVisible = () => techTraits.Count > 0; + techLevelDescription.IsVisible = techLevel.IsVisible; - techLevel.IsDisabled = () => configurationDisabled() || Map.Options.TechLevel != null || techTraits.Count <= 1; + techLevel.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).TechLevelLocked; techLevel.GetText = () => MapPreview.Status != MapStatus.Available || - Map == null || Map.Options.TechLevel != null ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel); + Map == null || mapOptions.Update(Map).TechLevelLocked ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel); techLevel.OnMouseDown = _ => { - var options = techTraits.Select(c => new DropDownOption + var options = techLevels.Update(Map).Select(c => new DropDownOption { Title = "{0}".F(c.Name), IsSelected = () => orderManager.LobbyInfo.GlobalSettings.TechLevel == c.Name, diff --git a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs index 2baa8bfa2f..8e201b70cb 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs @@ -15,6 +15,7 @@ using System.IO; using System.Linq; using System.Threading; using OpenRA.Graphics; +using OpenRA.Mods.Common.Traits; using OpenRA.Network; using OpenRA.Primitives; using OpenRA.Widgets; @@ -177,7 +178,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic selectedMapPreview = preview; // Cache the rules on a background thread to avoid jank - new Thread(() => selectedMap.PreloadRules()).Start(); + var difficultyDisabled = true; + var difficulties = new string[0]; + + new Thread(() => + { + selectedMap.PreloadRules(); + var mapOptions = selectedMap.Rules.Actors["world"].TraitInfo(); + + difficulty = mapOptions.Difficulty ?? mapOptions.Difficulties.FirstOrDefault(); + difficulties = mapOptions.Difficulties; + difficultyDisabled = mapOptions.DifficultyLocked || mapOptions.Difficulties.Length <= 1; + }).Start(); var briefingVideo = selectedMap.Videos.Briefing; var briefingVideoVisible = briefingVideo != null; @@ -204,13 +216,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (difficultyButton != null) { - difficultyButton.IsDisabled = () => !selectedMap.Options.Difficulties.Any(); - - difficulty = selectedMap.Options.Difficulties.FirstOrDefault(); + difficultyButton.IsDisabled = () => difficultyDisabled; difficultyButton.GetText = () => difficulty ?? "Normal"; difficultyButton.OnMouseDown = _ => { - var options = selectedMap.Options.Difficulties.Select(d => new DropDownOption + var options = difficulties.Select(d => new DropDownOption { Title = d, IsSelected = () => difficulty == d, diff --git a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs index 0f42b7e616..9407683635 100644 --- a/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs +++ b/OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs @@ -236,7 +236,6 @@ namespace OpenRA.Mods.TS.UtilityCommands map.MapTiles = Exts.Lazy(() => new CellLayer(map.Grid.Type, size)); map.MapHeight = Exts.Lazy(() => new CellLayer(map.Grid.Type, size)); - map.Options = new MapOptions(); map.RequiresMod = modData.Manifest.Mod.Id; return map; diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index eac9c02431..fde435bd22 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -163,7 +163,6 @@ ServerTraits: LobbySettingsNotification LobbyDefaults: - TechLevel: Unrestricted ChromeMetrics: common|metrics.yaml diff --git a/mods/cnc/rules/world.yaml b/mods/cnc/rules/world.yaml index 7a0a5d3b46..3322a2dd44 100644 --- a/mods/cnc/rules/world.yaml +++ b/mods/cnc/rules/world.yaml @@ -75,6 +75,7 @@ World: MapCreeps: SpawnMapActors: MapBuildRadius: + MapOptions: MPStartLocations: CreateMPPlayers: MPStartUnits@mcvonly: diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index b28cfdf68c..c13df25f65 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -156,8 +156,6 @@ ServerTraits: LobbySettingsNotification LobbyDefaults: - StartingUnitsClass: none - TechLevel: Unrestricted ChromeMetrics: common|metrics.yaml diff --git a/mods/d2k/rules/world.yaml b/mods/d2k/rules/world.yaml index 74e52b12ca..4da9d90426 100644 --- a/mods/d2k/rules/world.yaml +++ b/mods/d2k/rules/world.yaml @@ -90,6 +90,7 @@ World: MapCreeps: SpawnMapActors: MapBuildRadius: + MapOptions: CreateMPPlayers: MPStartLocations: MPStartUnits@mcv: diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index d721eff3e2..35163e80f4 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -166,8 +166,6 @@ ServerTraits: LobbySettingsNotification LobbyDefaults: - StartingUnitsClass: none - TechLevel: Unrestricted ChromeMetrics: common|metrics.yaml diff --git a/mods/ra/rules/world.yaml b/mods/ra/rules/world.yaml index 78c91500c7..2b78cfc0e9 100644 --- a/mods/ra/rules/world.yaml +++ b/mods/ra/rules/world.yaml @@ -121,6 +121,7 @@ World: WarheadDebugOverlay: SpawnMapActors: MapBuildRadius: + MapOptions: CreateMPPlayers: MPStartUnits@mcvonly: Class: none diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index e3f6d5ef1c..64903791f4 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -215,7 +215,6 @@ ServerTraits: LobbySettingsNotification LobbyDefaults: - StartingUnitsClass: none ChromeMetrics: common|metrics.yaml diff --git a/mods/ts/rules/world.yaml b/mods/ts/rules/world.yaml index cecc6d4194..2dca965534 100644 --- a/mods/ts/rules/world.yaml +++ b/mods/ts/rules/world.yaml @@ -99,6 +99,7 @@ World: WarheadDebugOverlay: SpawnMapActors: MapBuildRadius: + MapOptions: CreateMPPlayers: MPStartUnits@MCV: Class: none