Exemplo n.º 1
0
        public void CheckModVersion()
        {
            Task.Run(async() =>
            {
                var queryURL = new HttpQueryBuilder(VersionCheck)
                {
                    { "protocol", VersionCheckProtocol },
                    { "engine", Game.EngineVersion },
                    { "mod", Game.ModData.Manifest.Id },
                    { "version", Game.ModData.Manifest.Metadata.Version }
                }.ToString();

                var client = HttpClientFactory.Create();

                var httpResponseMessage = await client.GetAsync(queryURL);
                var result = await httpResponseMessage.Content.ReadAsStringAsync();

                var status = ModVersionStatus.Latest;
                switch (result)
                {
                case "outdated": status = ModVersionStatus.Outdated; break;

                case "unknown": status = ModVersionStatus.Unknown; break;

                case "playtest": status = ModVersionStatus.PlaytestAvailable; break;
                }

                Game.RunAfterTick(() => ModVersionStatus = status);
            });
        }
Exemplo n.º 2
0
        public void RefreshServerList()
        {
            // Query in progress
            if (activeQuery)
            {
                return;
            }

            searchStatus = SearchStatus.Fetching;

            var queryURL = new HttpQueryBuilder(services.ServerList)
            {
                { "protocol", GameServer.ProtocolVersion },
                { "engine", Game.EngineVersion },
                { "mod", Game.ModData.Manifest.Id },
                { "version", Game.ModData.Manifest.Metadata.Version }
            }.ToString();

            Task.Run(async() =>
            {
                List <GameServer> games = null;
                activeQuery             = true;

                try
                {
                    var client = HttpClientFactory.Create();
                    var httpResponseMessage = await client.GetAsync(queryURL);
                    var result = await httpResponseMessage.Content.ReadAsStreamAsync();

                    var yaml = MiniYaml.FromStream(result);
                    games    = new List <GameServer>();
                    foreach (var node in yaml)
                    {
                        try
                        {
                            var gs = new GameServer(node.Value);
                            if (gs.Address != null)
                            {
                                games.Add(gs);
                            }
                        }
                        catch
                        {
                            // Ignore any invalid games advertised.
                        }
                    }
                }
                catch (Exception e)
                {
                    searchStatus = SearchStatus.Failed;
                    Log.Write("debug", $"Failed to query server list with exception: {e}");
                }

                var lanGames = new List <GameServer>();
                foreach (var bl in lanGameLocations)
                {
                    try
                    {
                        if (string.IsNullOrEmpty(bl.Data))
                        {
                            continue;
                        }

                        var game   = MiniYaml.FromString(bl.Data)[0].Value;
                        var idNode = game.Nodes.FirstOrDefault(n => n.Key == "Id");

                        // Skip beacons created by this instance and replace Id by expected int value
                        if (idNode != null && idNode.Value.Value != Platform.SessionGUID.ToString())
                        {
                            idNode.Value.Value = "-1";

                            // Rewrite the server address with the correct IP
                            var addressNode = game.Nodes.FirstOrDefault(n => n.Key == "Address");
                            if (addressNode != null)
                            {
                                addressNode.Value.Value = bl.Address.ToString().Split(':')[0] + ":" + addressNode.Value.Value.Split(':')[1];
                            }

                            game.Nodes.Add(new MiniYamlNode("Location", "Local Network"));

                            lanGames.Add(new GameServer(game));
                        }
                    }
                    catch
                    {
                        // Ignore any invalid LAN games advertised.
                    }
                }

                var groupedLanGames = lanGames.GroupBy(gs => gs.Address).Select(g => g.Last());
                if (games != null)
                {
                    games.AddRange(groupedLanGames);
                }
                else if (groupedLanGames.Any())
                {
                    games = groupedLanGames.ToList();
                }

                Game.RunAfterTick(() => RefreshServerListInner(games));

                activeQuery = false;
            });
        }
Exemplo n.º 3
0
        public MainMenuLogic(Widget widget, World world, ModData modData)
        {
            rootMenu = widget;
            rootMenu.Get <LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Metadata.Version;

            // Menu buttons
            var mainMenu = widget.Get("MAIN_MENU");

            mainMenu.IsVisible = () => menuType == MenuType.Main;

            mainMenu.Get <ButtonWidget>("SINGLEPLAYER_BUTTON").OnClick = () => SwitchMenu(MenuType.Singleplayer);

            mainMenu.Get <ButtonWidget>("MULTIPLAYER_BUTTON").OnClick = OpenMultiplayerPanel;

            mainMenu.Get <ButtonWidget>("CONTENT_BUTTON").OnClick = () =>
            {
                // Switching mods changes the world state (by disposing it),
                // so we can't do this inside the input handler.
                Game.RunAfterTick(() =>
                {
                    var content = modData.Manifest.Get <ModContent>();
                    Game.InitializeMod(content.ContentInstallerMod, new Arguments(new[] { "Content.Mod=" + modData.Manifest.Id }));
                });
            };

            mainMenu.Get <ButtonWidget>("SETTINGS_BUTTON").OnClick = () =>
            {
                SwitchMenu(MenuType.None);
                Game.OpenWindow("SETTINGS_PANEL", new WidgetArgs
                {
                    { "onExit", () => SwitchMenu(MenuType.Main) }
                });
            };

            mainMenu.Get <ButtonWidget>("EXTRAS_BUTTON").OnClick = () => SwitchMenu(MenuType.Extras);

            mainMenu.Get <ButtonWidget>("QUIT_BUTTON").OnClick = Game.Exit;

            // Singleplayer menu
            var singleplayerMenu = widget.Get("SINGLEPLAYER_MENU");

            singleplayerMenu.IsVisible = () => menuType == MenuType.Singleplayer;

            var missionsButton = singleplayerMenu.Get <ButtonWidget>("MISSIONS_BUTTON");

            missionsButton.OnClick = OpenMissionBrowserPanel;

            var hasCampaign = modData.Manifest.Missions.Any();
            var hasMissions = modData.MapCache
                              .Any(p => p.Status == MapStatus.Available && p.Visibility.HasFlag(MapVisibility.MissionSelector));

            missionsButton.Disabled = !hasCampaign && !hasMissions;

            var hasMaps        = modData.MapCache.Any(p => p.Visibility.HasFlag(MapVisibility.Lobby));
            var skirmishButton = singleplayerMenu.Get <ButtonWidget>("SKIRMISH_BUTTON");

            skirmishButton.OnClick  = StartSkirmishGame;
            skirmishButton.Disabled = !hasMaps;

            var loadButton = singleplayerMenu.Get <ButtonWidget>("LOAD_BUTTON");

            loadButton.IsDisabled = () => !GameSaveBrowserLogic.IsLoadPanelEnabled(modData.Manifest);
            loadButton.OnClick    = OpenGameSaveBrowserPanel;

            singleplayerMenu.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => SwitchMenu(MenuType.Main);

            // Extras menu
            var extrasMenu = widget.Get("EXTRAS_MENU");

            extrasMenu.IsVisible = () => menuType == MenuType.Extras;

            extrasMenu.Get <ButtonWidget>("REPLAYS_BUTTON").OnClick = OpenReplayBrowserPanel;

            extrasMenu.Get <ButtonWidget>("MUSIC_BUTTON").OnClick = () =>
            {
                SwitchMenu(MenuType.None);
                Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
                {
                    { "onExit", () => SwitchMenu(MenuType.Extras) },
                    { "world", world }
                });
            };

            extrasMenu.Get <ButtonWidget>("MAP_EDITOR_BUTTON").OnClick = () => SwitchMenu(MenuType.MapEditor);

            var assetBrowserButton = extrasMenu.GetOrNull <ButtonWidget>("ASSETBROWSER_BUTTON");

            if (assetBrowserButton != null)
            {
                assetBrowserButton.OnClick = () =>
                {
                    SwitchMenu(MenuType.None);
                    Game.OpenWindow("ASSETBROWSER_PANEL", new WidgetArgs
                    {
                        { "onExit", () => SwitchMenu(MenuType.Extras) },
                    });
                }
            }
            ;

            extrasMenu.Get <ButtonWidget>("CREDITS_BUTTON").OnClick = () =>
            {
                SwitchMenu(MenuType.None);
                Ui.OpenWindow("CREDITS_PANEL", new WidgetArgs
                {
                    { "onExit", () => SwitchMenu(MenuType.Extras) },
                });
            };

            extrasMenu.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => SwitchMenu(MenuType.Main);

            // Map editor menu
            var mapEditorMenu = widget.Get("MAP_EDITOR_MENU");

            mapEditorMenu.IsVisible = () => menuType == MenuType.MapEditor;

            // Loading into the map editor
            Game.BeforeGameStart += RemoveShellmapUI;

            var onSelect = new Action <string>(uid => LoadMapIntoEditor(modData.MapCache[uid].Uid));

            var newMapButton = widget.Get <ButtonWidget>("NEW_MAP_BUTTON");

            newMapButton.OnClick = () =>
            {
                SwitchMenu(MenuType.None);
                Game.OpenWindow("NEW_MAP_BG", new WidgetArgs()
                {
                    { "onSelect", onSelect },
                    { "onExit", () => SwitchMenu(MenuType.MapEditor) }
                });
            };

            var loadMapButton = widget.Get <ButtonWidget>("LOAD_MAP_BUTTON");

            loadMapButton.OnClick = () =>
            {
                SwitchMenu(MenuType.None);
                Game.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
                {
                    { "initialMap", null },
                    { "initialTab", MapClassification.User },
                    { "onExit", () => SwitchMenu(MenuType.MapEditor) },
                    { "onSelect", onSelect },
                    { "filter", MapVisibility.Lobby | MapVisibility.Shellmap | MapVisibility.MissionSelector },
                });
            };

            loadMapButton.Disabled = !hasMaps;

            mapEditorMenu.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => SwitchMenu(MenuType.Extras);

            var newsBG = widget.GetOrNull("NEWS_BG");

            if (newsBG != null)
            {
                newsBG.IsVisible = () => Game.Settings.Game.FetchNews && menuType != MenuType.None && menuType != MenuType.StartupPrompts;

                newsPanel    = Ui.LoadWidget <ScrollPanelWidget>("NEWS_PANEL", null, new WidgetArgs());
                newsTemplate = newsPanel.Get("NEWS_ITEM_TEMPLATE");
                newsPanel.RemoveChild(newsTemplate);

                newsStatus = newsPanel.Get <LabelWidget>("NEWS_STATUS");
                SetNewsStatus("Loading news");
            }

            Game.OnRemoteDirectConnect += OnRemoteDirectConnect;

            // Check for updates in the background
            var webServices = modData.Manifest.Get <WebServices>();

            if (Game.Settings.Debug.CheckVersion)
            {
                webServices.CheckModVersion();
            }

            var updateLabel = rootMenu.GetOrNull("UPDATE_NOTICE");

            if (updateLabel != null)
            {
                updateLabel.IsVisible = () => !newsOpen && menuType != MenuType.None &&
                                        menuType != MenuType.StartupPrompts &&
                                        webServices.ModVersionStatus == ModVersionStatus.Outdated;
            }

            var playerProfile = widget.GetOrNull("PLAYER_PROFILE_CONTAINER");

            if (playerProfile != null)
            {
                Func <bool> minimalProfile = () => Ui.CurrentWindow() != null;
                Game.LoadWidget(world, "LOCAL_PROFILE_PANEL", playerProfile, new WidgetArgs()
                {
                    { "minimalProfile", minimalProfile }
                });
            }

            menuType = MenuType.StartupPrompts;

            Action onIntroductionComplete = () =>
            {
                Action onSysInfoComplete = () =>
                {
                    LoadAndDisplayNews(webServices, newsBG);
                    SwitchMenu(MenuType.Main);
                };

                if (SystemInfoPromptLogic.ShouldShowPrompt())
                {
                    Ui.OpenWindow("MAINMENU_SYSTEM_INFO_PROMPT", new WidgetArgs
                    {
                        { "onComplete", onSysInfoComplete }
                    });
                }
                else
                {
                    onSysInfoComplete();
                }
            };

            if (IntroductionPromptLogic.ShouldShowPrompt())
            {
                Game.OpenWindow("MAINMENU_INTRODUCTION_PROMPT", new WidgetArgs
                {
                    { "onComplete", onIntroductionComplete }
                });
            }
            else
            {
                onIntroductionComplete();
            }

            Game.OnShellmapLoaded += OpenMenuBasedOnLastGame;

            DiscordService.UpdateStatus(DiscordState.InMenu);
        }

        void LoadAndDisplayNews(WebServices webServices, Widget newsBG)
        {
            if (newsBG != null && Game.Settings.Game.FetchNews)
            {
                var cacheFile   = Path.Combine(Platform.SupportDir, webServices.GameNewsFileName);
                var currentNews = ParseNews(cacheFile);
                if (currentNews != null)
                {
                    DisplayNews(currentNews);
                }

                var newsButton = newsBG.GetOrNull <DropDownButtonWidget>("NEWS_BUTTON");
                if (newsButton != null)
                {
                    if (!fetchedNews)
                    {
                        Task.Run(async() =>
                        {
                            try
                            {
                                var client = HttpClientFactory.Create();

                                // Send the mod and engine version to support version-filtered news (update prompts)
                                var url = new HttpQueryBuilder(webServices.GameNews)
                                {
                                    { "version", Game.EngineVersion },
                                    { "mod", Game.ModData.Manifest.Id },
                                    { "modversion", Game.ModData.Manifest.Metadata.Version }
                                }.ToString();

                                // Parameter string is blank if the player has opted out
                                url += SystemInfoPromptLogic.CreateParameterString();

                                var response = await client.GetStringAsync(url);
                                await File.WriteAllTextAsync(cacheFile, response);

                                Game.RunAfterTick(() =>                                 // run on the main thread
                                {
                                    fetchedNews = true;
                                    var newNews = ParseNews(cacheFile);
                                    if (newNews == null)
                                    {
                                        return;
                                    }

                                    DisplayNews(newNews);

                                    if (currentNews == null || newNews.Any(n => !currentNews.Select(c => c.DateTime).Contains(n.DateTime)))
                                    {
                                        OpenNewsPanel(newsButton);
                                    }
                                });
                            }
                            catch (Exception e)
                            {
                                Game.RunAfterTick(() =>                                 // run on the main thread
                                {
                                    SetNewsStatus($"Failed to retrieve news: {e}");
                                });
                            }
                        });
                    }

                    newsButton.OnClick = () => OpenNewsPanel(newsButton);
                }
            }
        }

        void OpenNewsPanel(DropDownButtonWidget button)
        {
            newsOpen = true;
            button.AttachPanel(newsPanel, () => newsOpen = false);
        }

        void OnRemoteDirectConnect(ConnectionTarget endpoint)
        {
            SwitchMenu(MenuType.None);
            Ui.OpenWindow("MULTIPLAYER_PANEL", new WidgetArgs
            {
                { "onStart", RemoveShellmapUI },
                { "onExit", () => SwitchMenu(MenuType.Main) },
                { "directConnectEndPoint", endpoint },
            });
        }

        void LoadMapIntoEditor(string uid)
        {
            ConnectionLogic.Connect(Game.CreateLocalServer(uid),
                                    "",
                                    () => { Game.LoadEditor(uid); },
                                    () => { Game.CloseServer(); SwitchMenu(MenuType.MapEditor); });

            DiscordService.UpdateStatus(DiscordState.InMapEditor);

            lastGameState = MenuPanel.MapEditor;
        }

        void SetNewsStatus(string message)
        {
            message            = WidgetUtils.WrapText(message, newsStatus.Bounds.Width, Game.Renderer.Fonts[newsStatus.Font]);
            newsStatus.GetText = () => message;
        }