diff --git a/OpenRA.Mods.Common/WebServices.cs b/OpenRA.Mods.Common/WebServices.cs index dc4344ceef..6c0706e966 100644 --- a/OpenRA.Mods.Common/WebServices.cs +++ b/OpenRA.Mods.Common/WebServices.cs @@ -9,16 +9,55 @@ */ #endregion -using System.Collections.Generic; +using System; +using System.Net; +using System.Text; -namespace OpenRA +namespace OpenRA.Mods.Common { + public enum ModVersionStatus { NotChecked, Latest, Outdated, Unknown, PlaytestAvailable } + public class WebServices : IGlobalModData { public readonly string ServerList = "http://master.openra.net/games"; public readonly string ServerAdvertise = "http://master.openra.net/ping"; public readonly string MapRepository = "http://resource.openra.net/map/"; public readonly string GameNews = "http://master.openra.net/gamenews"; - public readonly string MPNotices = "http://master.openra.net/notices"; + public readonly string VersionCheck = "http://master.openra.net/versioncheck"; + + public ModVersionStatus ModVersionStatus { get; private set; } + const int VersionCheckProtocol = 1; + + public void CheckModVersion() + { + Action onComplete = i => + { + if (i.Error != null) + return; + try + { + var data = Encoding.UTF8.GetString(i.Result); + + var status = ModVersionStatus.Latest; + switch (data) + { + case "outdated": status = ModVersionStatus.Outdated; break; + case "unknown": status = ModVersionStatus.Unknown; break; + case "playtest": status = ModVersionStatus.PlaytestAvailable; break; + } + + Game.RunAfterTick(() => ModVersionStatus = status); + } + catch { } + }; + + var queryURL = VersionCheck + "?protocol={0}&engine={1}&mod={2}&version={3}".F( + VersionCheckProtocol, + Uri.EscapeUriString(Game.EngineVersion), + Uri.EscapeUriString(Game.ModData.Manifest.Id), + Uri.EscapeUriString(Game.ModData.Manifest.Metadata.Version)); + + new Download(queryURL, _ => { }, onComplete); + } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs index 61e366c05c..3a898b7c94 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs @@ -237,7 +237,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic Game.OnRemoteDirectConnect += OnRemoteDirectConnect; - var newsURL = modData.Manifest.Get().GameNews; + // Check for updates in the background + var webServices = modData.Manifest.Get(); + webServices.CheckModVersion(); // System information opt-out prompt var sysInfoPrompt = widget.Get("SYSTEM_INFO_PROMPT"); @@ -267,11 +269,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic Game.Settings.Debug.SystemInformationVersionPrompt = SystemInformationVersion; Game.Settings.Save(); SwitchMenu(MenuType.Main); - LoadAndDisplayNews(newsURL, newsBG); + LoadAndDisplayNews(webServices.GameNews, newsBG); }; } else - LoadAndDisplayNews(newsURL, newsBG); + LoadAndDisplayNews(webServices.GameNews, newsBG); } void LoadAndDisplayNews(string newsURL, Widget newsBG) diff --git a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs index 47e1d3d01b..fb410b43f9 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs @@ -52,15 +52,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic GameServer currentServer; MapPreview currentMap; + bool showNotices; Action onStart; Action onExit; enum SearchStatus { Fetching, Failed, NoGames, Hidden } - enum NoticeType { None, Outdated, Unknown, PlaytestAvailable } SearchStatus searchStatus = SearchStatus.Fetching; - NoticeType notice = NoticeType.None; Download currentQuery; IEnumerable lanGameLocations; @@ -100,10 +99,27 @@ namespace OpenRA.Mods.Common.Widgets.Logic noticeContainer = widget.GetOrNull("NOTICE_CONTAINER"); if (noticeContainer != null) { - noticeContainer.IsVisible = () => notice != NoticeType.None; - noticeContainer.Get("OUTDATED_VERSION_LABEL").IsVisible = () => notice == NoticeType.Outdated; - noticeContainer.Get("UNKNOWN_VERSION_LABEL").IsVisible = () => notice == NoticeType.Unknown; - noticeContainer.Get("PLAYTEST_AVAILABLE_LABEL").IsVisible = () => notice == NoticeType.PlaytestAvailable; + noticeContainer.IsVisible = () => showNotices; + noticeContainer.Get("OUTDATED_VERSION_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.Outdated; + noticeContainer.Get("UNKNOWN_VERSION_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.Unknown; + noticeContainer.Get("PLAYTEST_AVAILABLE_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.PlaytestAvailable; + } + + var noticeWatcher = widget.Get("NOTICE_WATCHER"); + if (noticeWatcher != null && noticeContainer != null) + { + var containerHeight = noticeContainer.Bounds.Height; + noticeWatcher.OnTick = () => + { + var show = services.ModVersionStatus != ModVersionStatus.NotChecked && services.ModVersionStatus != ModVersionStatus.Latest; + if (show != showNotices) + { + var dir = show ? 1 : -1; + serverList.Bounds.Y += dir * containerHeight; + serverList.Bounds.Height -= dir * containerHeight; + showNotices = show; + } + }; } joinButton = widget.Get("JOIN_BUTTON"); @@ -288,7 +304,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic } RefreshServerList(); - QueryNotices(); if (directConnectHost != null) { @@ -318,48 +333,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic game.Spectators > 0 ? ", {0} Spectator{1}".F(game.Spectators, game.Spectators != 1 ? "s" : "") : ""); } - void QueryNotices() - { - if (noticeContainer == null) - return; - - Action onComplete = i => - { - if (i.Error != null) - return; - try - { - var data = Encoding.UTF8.GetString(i.Result); - var n = NoticeType.None; - switch (data) - { - case "outdated": n = NoticeType.Outdated; break; - case "unknown": n = NoticeType.Unknown; break; - case "playtest": n = NoticeType.PlaytestAvailable; break; - } - - if (n == NoticeType.None) - return; - - Game.RunAfterTick(() => - { - notice = n; - serverList.Bounds.Y += noticeContainer.Bounds.Height; - serverList.Bounds.Height -= noticeContainer.Bounds.Height; - }); - } - catch { } - }; - - var queryURL = services.MPNotices + "?protocol={0}&engine={1}&mod={2}&version={3}".F( - GameServer.ProtocolVersion, - Uri.EscapeUriString(Game.EngineVersion), - Uri.EscapeUriString(Game.ModData.Manifest.Id), - Uri.EscapeUriString(Game.ModData.Manifest.Metadata.Version)); - - new Download(queryURL, _ => { }, onComplete); - } - void RefreshServerList() { // Query in progress diff --git a/mods/cnc/chrome/multiplayer-browser.yaml b/mods/cnc/chrome/multiplayer-browser.yaml index 42a1df1a5b..e8814721cf 100644 --- a/mods/cnc/chrome/multiplayer-browser.yaml +++ b/mods/cnc/chrome/multiplayer-browser.yaml @@ -48,6 +48,7 @@ Container@MULTIPLAYER_PANEL: Height: 25 Text: Status Font: Bold + LogicTicker@NOTICE_WATCHER: Container@NOTICE_CONTAINER: X: 15 Y: 30 diff --git a/mods/common/chrome/multiplayer-browser.yaml b/mods/common/chrome/multiplayer-browser.yaml index d1cd79f7d1..02d39da9c5 100644 --- a/mods/common/chrome/multiplayer-browser.yaml +++ b/mods/common/chrome/multiplayer-browser.yaml @@ -43,6 +43,7 @@ Background@MULTIPLAYER_PANEL: Height: 25 Text: Status Font: Bold + LogicTicker@NOTICE_WATCHER: Background@NOTICE_CONTAINER: X: 20 Y: 67