From 301b698c81ead18a72c7c01f6c26f0c3fe624177 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 3 Sep 2015 21:40:45 +0100 Subject: [PATCH] Add game speed dropdown to the lobby. --- OpenRA.Game/GameSpeed.cs | 40 +++++++++++++++++++ OpenRA.Game/Network/Session.cs | 1 + OpenRA.Game/OpenRA.Game.csproj | 1 + .../ServerTraits/LobbyCommands.cs | 28 +++++++++++++ .../Widgets/Logic/Ingame/GameTimerLogic.cs | 4 +- .../Widgets/Logic/Lobby/LobbyLogic.cs | 38 ++++++++++++++++++ mods/cnc/chrome/lobby-dialogs.yaml | 40 ++++++++++++------- mods/cnc/mod.yaml | 20 +++++++++- mods/d2k/chrome/lobby-dialogs.yaml | 39 ++++++++++++------ mods/d2k/mod.yaml | 18 +++++++++ mods/ra/chrome/lobby-dialogs.yaml | 39 ++++++++++++------ mods/ra/mod.yaml | 18 +++++++++ mods/ts/mod.yaml | 18 +++++++++ 13 files changed, 261 insertions(+), 43 deletions(-) create mode 100644 OpenRA.Game/GameSpeed.cs diff --git a/OpenRA.Game/GameSpeed.cs b/OpenRA.Game/GameSpeed.cs new file mode 100644 index 0000000000..24e7eebac8 --- /dev/null +++ b/OpenRA.Game/GameSpeed.cs @@ -0,0 +1,40 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 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.Collections.Generic; +using System.Linq; +using OpenRA.Graphics; + +namespace OpenRA +{ + public class GameSpeed + { + [Translate] + public readonly string Name = "Default"; + public readonly int Timestep = 40; + public readonly int OrderLatency = 3; + } + + public class GameSpeeds : IGlobalModData + { + [FieldLoader.LoadUsing("LoadSpeeds")] + public readonly Dictionary Speeds; + + static object LoadSpeeds(MiniYaml y) + { + var ret = new Dictionary(); + foreach (var node in y.Nodes) + ret.Add(node.Key, FieldLoader.Load(node.Value)); + + return ret; + } + } +} diff --git a/OpenRA.Game/Network/Session.cs b/OpenRA.Game/Network/Session.cs index 9c7c6c5d22..d4a09185a0 100644 --- a/OpenRA.Game/Network/Session.cs +++ b/OpenRA.Game/Network/Session.cs @@ -188,6 +188,7 @@ namespace OpenRA.Network public int StartingCash = 5000; public string TechLevel = "none"; public string StartingUnitsClass = "none"; + public string GameSpeedType = "default"; public bool ShortGame = true; public bool AllowVersionMismatch; public string GameUid; diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index bb9a09f303..e8de19d10a 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -243,6 +243,7 @@ + diff --git a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs index 5799a5e04c..186a497b72 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs @@ -675,6 +675,34 @@ namespace OpenRA.Mods.Common.Server return true; } }, + { "gamespeed", + s => + { + if (!client.IsAdmin) + { + server.SendOrderTo(conn, "Message", "Only the host can set that option."); + return true; + } + + var gameSpeeds = Game.ModData.Manifest.Get(); + + GameSpeed speed; + if (!gameSpeeds.Speeds.TryGetValue(s, out speed)) + { + server.SendOrderTo(conn, "Message", "Invalid game speed selected."); + return true; + } + + server.LobbyInfo.GlobalSettings.GameSpeedType = s; + server.LobbyInfo.GlobalSettings.Timestep = speed.Timestep; + server.LobbyInfo.GlobalSettings.OrderLatency = speed.OrderLatency; + + server.SyncLobbyInfo(); + server.SendMessage("{0} changed Game Speed to {1}.".F(client.Name, speed.Name)); + + return true; + } + }, { "kick", s => { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs index 5fbdb7fab4..4de3ed228b 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameTimerLogic.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var status = widget.GetOrNull("GAME_TIMER_STATUS"); var startTick = Ui.LastTickTime; - Func shouldShowStatus = () => (world.Paused || world.Timestep != Game.Timestep) + Func shouldShowStatus = () => (world.Paused || world.Timestep != world.LobbyInfo.GlobalSettings.Timestep) && (Ui.LastTickTime - startTick) / 1000 % 2 == 0; Func statusText = () => @@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (world.Timestep == 1) return "Max Speed"; - return "{0}% Speed".F(Game.Timestep * 100 / world.Timestep); + return "{0}% Speed".F(world.LobbyInfo.GlobalSettings.Timestep * 100 / world.Timestep); }; if (timer != null) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index c22ce9ca99..db5a852100 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -490,6 +490,44 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; } + var gameSpeed = optionsBin.GetOrNull("GAMESPEED_DROPDOWNBUTTON"); + if (gameSpeed != null) + { + var speeds = Game.ModData.Manifest.Get().Speeds; + + gameSpeed.IsDisabled = () => Map.Status != MapStatus.Available || configurationDisabled(); + gameSpeed.GetText = () => + { + if (Map.Status != MapStatus.Available) + return "Not Available"; + + GameSpeed speed; + if (!speeds.TryGetValue(orderManager.LobbyInfo.GlobalSettings.GameSpeedType, out speed)) + return "Unknown"; + + return speed.Name; + }; + + gameSpeed.OnMouseDown = _ => + { + var options = speeds.Select(s => new DropDownOption + { + Title = s.Value.Name, + IsSelected = () => orderManager.LobbyInfo.GlobalSettings.GameSpeedType == s.Key, + OnClick = () => orderManager.IssueOrder(Order.Command("gamespeed {0}".F(s.Key))) + }); + + Func setupItem = (option, template) => + { + var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); + item.Get("LABEL").GetText = () => option.Title; + return item; + }; + + gameSpeed.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); + }; + } + var exploredMap = optionsBin.GetOrNull("EXPLORED_MAP_CHECKBOX"); if (exploredMap != null) { diff --git a/mods/cnc/chrome/lobby-dialogs.yaml b/mods/cnc/chrome/lobby-dialogs.yaml index c31a35e178..183b8494bc 100644 --- a/mods/cnc/chrome/lobby-dialogs.yaml +++ b/mods/cnc/chrome/lobby-dialogs.yaml @@ -175,19 +175,6 @@ Background@LOBBY_OPTIONS_BIN: Width: 140 Height: 25 Font: Regular - Label@DIFFICULTY_DESC: - X: PARENT_RIGHT - WIDTH - 135 - Y: 107 - Width: 120 - Height: 25 - Text: Mission Difficulty: - Align: Right - DropDownButton@DIFFICULTY_DROPDOWNBUTTON: - X: PARENT_RIGHT - WIDTH + 10 - Y: 107 - Width: 140 - Height: 25 - Font: Regular DropDownButton@TECHLEVEL_DROPDOWNBUTTON: X: 85 Y: 112 @@ -201,7 +188,32 @@ Background@LOBBY_OPTIONS_BIN: Height: 25 Text: Tech Level: Align: Right - + Label@GAMESPEED_DESC: + X: PARENT_RIGHT - WIDTH - 135 + Y: 112 + Width: 120 + Height: 25 + Text: Game Speed: + Align: Right + DropDownButton@GAMESPEED_DROPDOWNBUTTON: + X: PARENT_RIGHT - WIDTH + 10 + Y: 112 + Width: 140 + Height: 25 + Font: Regular + Label@DIFFICULTY_DESC: + X: PARENT_RIGHT - WIDTH - 135 + Y: 152 + Width: 120 + Height: 25 + Text: Mission Difficulty: + Align: Right + DropDownButton@DIFFICULTY_DROPDOWNBUTTON: + X: PARENT_RIGHT - WIDTH + 10 + Y: 152 + Width: 140 + Height: 25 + Font: Regular Background@FORCE_START_DIALOG: X: 15 Y: 30 diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 9c34f8b63e..4a7f7e5a0b 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -213,4 +213,22 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence WINTER: .win SNOW: .sno DESERT: .des - JUNGLE: .jun \ No newline at end of file + JUNGLE: .jun + +GameSpeeds: + slower: + Name: Slower + Timestep: 50 + OrderLatency: 3 + default: + Name: Default + Timestep: 40 + OrderLatency: 3 + faster: + Name: Faster + Timestep: 30 + OrderLatency: 4 + fastest: + Name: Fastest + Timestep: 20 + OrderLatency: 6 diff --git a/mods/d2k/chrome/lobby-dialogs.yaml b/mods/d2k/chrome/lobby-dialogs.yaml index 5a57019cd7..614777b41a 100644 --- a/mods/d2k/chrome/lobby-dialogs.yaml +++ b/mods/d2k/chrome/lobby-dialogs.yaml @@ -151,6 +151,19 @@ Background@LOBBY_OPTIONS_BIN: Width: 140 Height: 20 Text: Debug Menu + Label@DIFFICULTY_DESC: + X: PARENT_RIGHT - WIDTH - 145 + Y: 70 + Width: 120 + Height: 25 + Text: Mission Difficulty: + Align: Right + DropDownButton@DIFFICULTY_DROPDOWNBUTTON: + X: PARENT_RIGHT - WIDTH + Y: 70 + Width: 140 + Height: 25 + Font: Regular Label@STARTINGCASH_DESC: Y: 110 Width: 80 @@ -177,19 +190,6 @@ Background@LOBBY_OPTIONS_BIN: Width: 140 Height: 25 Font: Regular - Label@DIFFICULTY_DESC: - X: PARENT_RIGHT - WIDTH - 145 - Y: 150 - Width: 120 - Height: 25 - Text: Mission Difficulty: - Align: Right - DropDownButton@DIFFICULTY_DROPDOWNBUTTON: - X: PARENT_RIGHT - WIDTH - Y: 150 - Width: 140 - Height: 25 - Font: Regular DropDownButton@TECHLEVEL_DROPDOWNBUTTON: X: 85 Y: 150 @@ -203,6 +203,19 @@ Background@LOBBY_OPTIONS_BIN: Height: 25 Text: Tech Level: Align: Right + Label@GAMESPEED_DESC: + X: PARENT_RIGHT - WIDTH - 145 + Y: 150 + Width: 120 + Height: 25 + Text: Game Speed: + Align: Right + DropDownButton@GAMESPEED_DROPDOWNBUTTON: + X: PARENT_RIGHT - WIDTH + Y: 150 + Width: 140 + Height: 25 + Font: Regular Background@FORCE_START_DIALOG: X: 20 diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index 554bbdff1a..b638e3b2a5 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -193,3 +193,21 @@ SupportsMapsFrom: d2k SpriteFormats: R8, ShpTD, TmpRA SpriteSequenceFormat: DefaultSpriteSequence + +GameSpeeds: + slower: + Name: Slower + Timestep: 50 + OrderLatency: 3 + default: + Name: Default + Timestep: 40 + OrderLatency: 3 + faster: + Name: Faster + Timestep: 30 + OrderLatency: 4 + fastest: + Name: Fastest + Timestep: 20 + OrderLatency: 6 diff --git a/mods/ra/chrome/lobby-dialogs.yaml b/mods/ra/chrome/lobby-dialogs.yaml index cbc1dfd27d..efa06a8a20 100644 --- a/mods/ra/chrome/lobby-dialogs.yaml +++ b/mods/ra/chrome/lobby-dialogs.yaml @@ -145,6 +145,19 @@ Background@LOBBY_OPTIONS_BIN: Width: 140 Height: 20 Text: Debug Menu + Label@DIFFICULTY_DESC: + X: PARENT_RIGHT - WIDTH - 145 + Y: 70 + Width: 120 + Height: 25 + Text: Mission Difficulty: + Align: Right + DropDownButton@DIFFICULTY_DROPDOWNBUTTON: + X: PARENT_RIGHT - WIDTH + Y: 70 + Width: 140 + Height: 25 + Font: Regular Label@STARTINGCASH_DESC: Y: 110 Width: 80 @@ -171,19 +184,6 @@ Background@LOBBY_OPTIONS_BIN: Width: 140 Height: 25 Font: Regular - Label@DIFFICULTY_DESC: - X: PARENT_RIGHT - WIDTH - 145 - Y: 150 - Width: 120 - Height: 25 - Text: Mission Difficulty: - Align: Right - DropDownButton@DIFFICULTY_DROPDOWNBUTTON: - X: PARENT_RIGHT - WIDTH - Y: 150 - Width: 140 - Height: 25 - Font: Regular DropDownButton@TECHLEVEL_DROPDOWNBUTTON: X: 85 Y: 150 @@ -197,6 +197,19 @@ Background@LOBBY_OPTIONS_BIN: Height: 25 Text: Tech Level: Align: Right + Label@GAMESPEED_DESC: + X: PARENT_RIGHT - WIDTH - 145 + Y: 150 + Width: 120 + Height: 25 + Text: Game Speed: + Align: Right + DropDownButton@GAMESPEED_DROPDOWNBUTTON: + X: PARENT_RIGHT - WIDTH + Y: 150 + Width: 140 + Height: 25 + Font: Regular Background@FORCE_START_DIALOG: X: 20 diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 203c5c5013..2cded39907 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -213,3 +213,21 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence SNOW: .sno INTERIOR: .int DESERT: .des + +GameSpeeds: + slower: + Name: Slower + Timestep: 50 + OrderLatency: 3 + default: + Name: Default + Timestep: 40 + OrderLatency: 3 + faster: + Name: Faster + Timestep: 30 + OrderLatency: 4 + fastest: + Name: Fastest + Timestep: 20 + OrderLatency: 6 diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 92f5b64869..842f0719c5 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -258,3 +258,21 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence TilesetCodes: TEMPERATE: t SNOW: a + +GameSpeeds: + slower: + Name: Slower + Timestep: 50 + OrderLatency: 3 + default: + Name: Default + Timestep: 40 + OrderLatency: 3 + faster: + Name: Faster + Timestep: 30 + OrderLatency: 4 + fastest: + Name: Fastest + Timestep: 20 + OrderLatency: 6