void CreateSurrenderButton() { if ((world.Type == WorldType.Shellmap || world.Type == WorldType.Editor) || world.LocalPlayer == null) { return; } if (world.Type != WorldType.Capmaign && world.Map.Visibility.HasFlag(MapVisibility.MissionSelector)) { return; } Action onSurrender = () => { world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false)); CloseMenu(); }; var button = AddButton("SURRENDER", "Surrender"); button.IsDisabled = () => world.LocalPlayer.WinState != WinState.Undefined || hasError || leaving; button.OnClick = () => { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Surrender", text: "Are you sure you want to surrender?", onConfirm: onSurrender, onCancel: ShowMenu, confirmText: "Surrender", cancelText: "Stay"); }; }
void Save(World world) { var filename = saveTextField.Text + ".orasav"; var testPath = Platform.ResolvePath( Platform.SupportDirPrefix, "Saves", modData.Manifest.Id, modData.Manifest.Metadata.Version, filename); Action inner = () => { world.RequestGameSave(filename); Ui.CloseWindow(); onExit(); }; if (selectedSave != null || File.Exists(testPath)) { ConfirmationDialogs.ButtonPrompt( title: "Overwrite save game?", text: "Overwrite {0}?".F(saveTextField.Text), onConfirm: inner, confirmText: "Overwrite", onCancel: () => { }); } else { inner(); } }
private void OpenWorldDominationPanel() { bool founded = File.Exists(Path.GetFullPath(Platform.ResolvePath("^Content/ra2/wdt.mix"))); if (!founded) { ConfirmationDialogs.ButtonPrompt( title: "Error", text: "Can't find wdt.mix!", confirmText: "Retry", cancelText: "Quit", onCancel: close, onConfirm: OpenWorldDominationPanel); } else { SwitchMenu(MenuType.None); Game.OpenWindow("WDT_PANEL", new WidgetArgs { { "onStart", () => { RemoveShellmapUI(); lastGameState = MenuPanel.Multiplayer; } }, { "onExit", () => SwitchMenu(MenuType.Multiplayer) }, { "directConnectHost", null }, { "directConnectPort", 0 }, }); } }
void CreateSurrenderButton() { if (world.Type != WorldType.Regular || isSinglePlayer || world.LocalPlayer == null) { return; } Action onSurrender = () => { world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false)); CloseMenu(); }; var button = AddButton("SURRENDER", "Surrender"); button.IsDisabled = () => world.LocalPlayer.WinState != WinState.Undefined || hasError || leaving; button.OnClick = () => { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Surrender", text: "Are you sure you want to surrender?", onConfirm: onSurrender, onCancel: ShowMenu, confirmText: "Surrender", cancelText: "Stay"); }; }
void CreateExitEditorButton() { if (world.Type != WorldType.Editor) { return; } var actionManager = world.WorldActor.Trait <EditorActionManager>(); var button = AddButton("EXIT_EDITOR", "Exit Map Editor"); // Show dialog only if updated since last save button.OnClick = () => { if (actionManager.HasUnsavedItems()) { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Exit Map Editor", text: "Exit and lose all unsaved changes?", onConfirm: OnQuit, onCancel: ShowMenu); } else { OnQuit(); } }; }
void PlayVideo(VideoPlayerWidget player, string video, PlayingVideo pv, Action onComplete = null) { if (!modData.DefaultFileSystem.Exists(video)) { ConfirmationDialogs.ButtonPrompt( title: "Video not installed", text: "The game videos can be installed from the\n\"Manage Content\" menu in the mod chooser.", cancelText: "Back", onCancel: () => { }); } else { StopVideo(player); playingVideo = pv; player.Load(video); // video playback runs asynchronously player.PlayThen(() => { StopVideo(player); onComplete?.Invoke(); }); // Mute other distracting sounds MuteSounds(); } }
static bool IncompatibleReplayDialog(string type, string name, Action onCancel) { var error = "It was recorded with an " + type; error += string.IsNullOrEmpty(name) ? "." : ":\n{0}".F(name); ConfirmationDialogs.ButtonPrompt("Incompatible Replay", error, onCancel: onCancel); return(false); }
public SettingsLogic(Widget widget, Action onExit, ModData modData, WorldRenderer worldRenderer, Dictionary <string, MiniYaml> logicArgs) { this.worldRenderer = worldRenderer; this.modData = modData; this.logicArgs = logicArgs; panelContainer = widget.Get("SETTINGS_PANEL"); tabContainer = widget.Get("TAB_CONTAINER"); RegisterSettingsPanel(PanelType.Display, InitDisplayPanel, ResetDisplayPanel, "DISPLAY_PANEL", "DISPLAY_TAB"); RegisterSettingsPanel(PanelType.Audio, InitAudioPanel, ResetAudioPanel, "AUDIO_PANEL", "AUDIO_TAB"); RegisterSettingsPanel(PanelType.Input, InitInputPanel, ResetInputPanel, "INPUT_PANEL", "INPUT_TAB"); RegisterSettingsPanel(PanelType.Hotkeys, InitHotkeysPanel, ResetHotkeysPanel, "HOTKEYS_PANEL", "HOTKEYS_TAB"); RegisterSettingsPanel(PanelType.Advanced, InitAdvancedPanel, ResetAdvancedPanel, "ADVANCED_PANEL", "ADVANCED_TAB"); panelContainer.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { leavePanelActions[settingsPanel](); var current = Game.Settings; current.Save(); Action closeAndExit = () => { Ui.CloseWindow(); onExit(); }; if (current.Sound.Device != OriginalSoundDevice || current.Graphics.Mode != OriginalGraphicsMode || current.Graphics.WindowedSize != OriginalGraphicsWindowedSize || current.Graphics.FullscreenSize != OriginalGraphicsFullscreenSize || current.Server.DiscoverNatDevices != OriginalServerDiscoverNatDevices) { Action restart = () => { var external = Game.ExternalMods[ExternalMod.MakeKey(Game.ModData.Manifest)]; Game.SwitchToExternalMod(external, null, closeAndExit); }; ConfirmationDialogs.ButtonPrompt( title: "Restart Now?", text: "Some changes will not be applied until\nthe game is restarted. Restart now?", onConfirm: restart, onCancel: closeAndExit, confirmText: "Restart Now", cancelText: "Restart Later"); } else { closeAndExit(); } }; panelContainer.Get <ButtonWidget>("RESET_BUTTON").OnClick = () => { resetPanelActions[settingsPanel](); Game.Settings.Save(); }; }
void CreateAndJoin() { var name = Settings.SanitizedServerName(panel.Get <TextFieldWidget>("SERVER_NAME").Text); int listenPort, externalPort; if (!Exts.TryParseIntegerInvariant(panel.Get <TextFieldWidget>("LISTEN_PORT").Text, out listenPort)) { listenPort = 1234; } if (!Exts.TryParseIntegerInvariant(panel.Get <TextFieldWidget>("EXTERNAL_PORT").Text, out externalPort)) { externalPort = 1234; } var passwordField = panel.GetOrNull <PasswordFieldWidget>("PASSWORD"); var password = passwordField != null ? passwordField.Text : ""; // Save new settings Game.Settings.Server.Name = name; Game.Settings.Server.ListenPort = listenPort; Game.Settings.Server.ExternalPort = externalPort; Game.Settings.Server.AdvertiseOnline = advertiseOnline; Game.Settings.Server.AllowPortForward = allowPortForward; Game.Settings.Server.Map = preview.Uid; Game.Settings.Server.Password = password; Game.Settings.Save(); // Take a copy so that subsequent changes don't affect the server var settings = Game.Settings.Server.Clone(); // Create and join the server try { Game.CreateServer(settings); } catch (System.Net.Sockets.SocketException e) { var message = "Could not listen on port {0}.".F(Game.Settings.Server.ListenPort); if (e.ErrorCode == 10048) // AddressAlreadyInUse (WSAEADDRINUSE) { message += "\nCheck if the port is already being used."; } else { message += "\nError is: \"{0}\" ({1})".F(e.Message, e.ErrorCode); } ConfirmationDialogs.ButtonPrompt("Server Creation Failed", message, onCancel: () => { }, cancelText: "Back"); return; } ConnectionLogic.Connect(IPAddress.Loopback.ToString(), Game.Settings.Server.ListenPort, password, onCreate, onExit); }
void CreateAbortMissionButton() { if (world.Type != WorldType.Regular) { return; } var button = AddButton("ABORT_MISSION", world.IsGameOver ? "Leave" : "Abort Mission"); button.OnClick = () => { hideMenu = true; if (world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Won) { Action restartAction = null; var iop = world.WorldActor.TraitsImplementing <IObjectivesPanel>().FirstOrDefault(); var exitDelay = iop != null ? iop.ExitDelay : 0; if (!world.LobbyInfo.GlobalSettings.Dedicated && world.LobbyInfo.NonBotClients.Count() == 1) { restartAction = () => { Ui.CloseWindow(); if (mpe != null) { if (Game.IsCurrentWorld(world)) { mpe.Fade(MenuPaletteEffect.EffectType.Black); } exitDelay += 40 * mpe.Info.FadeLength; } Game.RunAfterDelay(exitDelay, Game.RestartGame); }; } ConfirmationDialogs.ButtonPrompt( title: "Leave Mission", text: "Leave this game and return to the menu?", onConfirm: OnQuit, onCancel: ShowMenu, confirmText: "Leave", cancelText: "Stay", otherText: "Restart", onOther: restartAction); } else { OnQuit(); } }; }
void DeleteOneMap(string map, Action <string> after) { ConfirmationDialogs.ButtonPrompt( title: "Delete map", text: $"Delete the map '{modData.MapCache[map].Title}'?", onConfirm: () => { var newUid = DeleteMap(map); after?.Invoke(newUid); }, confirmText: "Delete", onCancel: () => { }); }
void DeleteAllMaps(string[] maps, Action <string> after) { ConfirmationDialogs.ButtonPrompt( title: "Delete maps", text: "Delete all maps on this page?", onConfirm: () => { maps.Do(m => DeleteMap(m)); after?.Invoke(Game.ModData.MapCache.ChooseInitialMap(null, Game.CosmeticRandom)); }, confirmText: "Delete", onCancel: () => { }); }
void DeleteOneMap(string map, Action<string> after) { ConfirmationDialogs.ButtonPrompt( title: "Delete map", text: "Delete the map '{0}'?".F(modData.MapCache[map].Title), onConfirm: () => { var newUid = DeleteMap(map); if (after != null) after(newUid); }, confirmText: "Delete", onCancel: () => { }); }
void CreateAndJoin() { var name = Game.Settings.SanitizedServerName(panel.Get <TextFieldWidget>("SERVER_NAME").Text); if (!Exts.TryParseIntegerInvariant(panel.Get <TextFieldWidget>("LISTEN_PORT").Text, out var listenPort)) { listenPort = 1234; } var passwordField = panel.GetOrNull <PasswordFieldWidget>("PASSWORD"); var password = passwordField != null ? passwordField.Text : ""; // Save new settings Game.Settings.Server.Name = name; Game.Settings.Server.ListenPort = listenPort; Game.Settings.Server.AdvertiseOnline = advertiseOnline; Game.Settings.Server.Map = preview.Uid; Game.Settings.Server.Password = password; Game.Settings.Save(); // Take a copy so that subsequent changes don't affect the server var settings = Game.Settings.Server.Clone(); // Create and join the server try { var endpoint = Game.CreateServer(settings); Ui.CloseWindow(); ConnectionLogic.Connect(endpoint, password, onCreate, onExit); } catch (System.Net.Sockets.SocketException e) { var message = $"Could not listen on port {Game.Settings.Server.ListenPort}."; // AddressAlreadyInUse (WSAEADDRINUSE) if (e.ErrorCode == 10048) { message += "\nCheck if the port is already being used."; } else { message += $"\nError is: \"{e.Message}\" ({e.ErrorCode})"; } ConfirmationDialogs.ButtonPrompt("Server Creation Failed", message, onCancel: () => { }, cancelText: "Back"); } }
public SettingsLogic(Widget widget, Action onExit, ModData modData, WorldRenderer worldRenderer) { this.worldRenderer = worldRenderer; this.modData = modData; panelContainer = widget.Get("SETTINGS_PANEL"); tabContainer = widget.Get("TAB_CONTAINER"); RegisterSettingsPanel(PanelType.Display, InitDisplayPanel, ResetDisplayPanel, "DISPLAY_PANEL", "DISPLAY_TAB"); RegisterSettingsPanel(PanelType.Audio, InitAudioPanel, ResetAudioPanel, "AUDIO_PANEL", "AUDIO_TAB"); RegisterSettingsPanel(PanelType.Input, InitInputPanel, ResetInputPanel, "INPUT_PANEL", "INPUT_TAB"); RegisterSettingsPanel(PanelType.Advanced, InitAdvancedPanel, ResetAdvancedPanel, "ADVANCED_PANEL", "ADVANCED_TAB"); panelContainer.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { leavePanelActions[settingsPanel](); var current = Game.Settings; current.Save(); Action closeAndExit = () => { Ui.CloseWindow(); onExit(); }; if (OriginalSoundDevice != current.Sound.Device || OriginalGraphicsMode != current.Graphics.Mode || OriginalGraphicsWindowedSize != current.Graphics.WindowedSize || OriginalGraphicsFullscreenSize != current.Graphics.FullscreenSize) { ConfirmationDialogs.ButtonPrompt( title: "Restart Now?", text: "Some changes will not be applied until\nthe game is restarted. Restart now?", onConfirm: Game.Restart, onCancel: closeAndExit, confirmText: "Restart Now", cancelText: "Restart Later"); } else { closeAndExit(); } }; panelContainer.Get <ButtonWidget>("RESET_BUTTON").OnClick = () => { resetPanelActions[settingsPanel](); Game.Settings.Save(); }; }
public static bool PromptConfirmReplayCompatibility(ReplayMetadata replayMeta, Action onCancel = null) { if (onCancel == null) { onCancel = DoNothing; } if (replayMeta == null) { ConfirmationDialogs.ButtonPrompt("Incompatible Replay", "Replay metadata could not be read.", onCancel: onCancel); return(false); } var version = replayMeta.GameInfo.Version; if (version == null) { return(IncompatibleReplayDialog("unknown version", version, onCancel)); } var mod = replayMeta.GameInfo.Mod; if (mod == null) { return(IncompatibleReplayDialog("unknown mod", mod, onCancel)); } if (!Game.Mods.ContainsKey(mod)) { return(IncompatibleReplayDialog("unavailable mod", mod, onCancel)); } if (Game.Mods[mod].Metadata.Version != version) { return(IncompatibleReplayDialog("incompatible version", version, onCancel)); } if (replayMeta.GameInfo.MapPreview.Status != MapStatus.Available) { return(IncompatibleReplayDialog("unavailable map", replayMeta.GameInfo.MapUid, onCancel)); } return(true); }
void CreateExitEditorButton() { if (world.Type != WorldType.Editor) { return; } var button = AddButton("EXIT_EDITOR", "Exit Map Editor"); button.OnClick = () => { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Exit Map Editor", text: "Exit and lose all unsaved changes?", onConfirm: OnQuit, onCancel: ShowMenu); }; }
void CreateRestartButton() { if (world.Type != WorldType.Regular || !isSinglePlayer) { return; } var iop = world.WorldActor.TraitsImplementing <IObjectivesPanel>().FirstOrDefault(); var exitDelay = iop?.ExitDelay ?? 0; Action onRestart = () => { Ui.CloseWindow(); if (mpe != null) { if (Game.IsCurrentWorld(world)) { mpe.Fade(MenuPaletteEffect.EffectType.Black); } exitDelay += 40 * mpe.Info.FadeLength; } Game.RunAfterDelay(exitDelay, Game.RestartGame); }; var button = AddButton("RESTART", "Restart"); button.IsDisabled = () => hasError || leaving; button.OnClick = () => { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Restart", text: "Are you sure you want to restart?", onConfirm: onRestart, onCancel: ShowMenu, confirmText: "Restart", cancelText: "Stay"); }; }
void CreateSaveMapButton() { if (world.Type != WorldType.Editor) { return; } var button = AddButton("SAVE_MAP", "Save Map"); button.OnClick = () => { hideMenu = true; var editorActorLayer = world.WorldActor.Trait <EditorActorLayer>(); var actionManager = world.WorldActor.Trait <EditorActionManager>(); var playerDefinitions = editorActorLayer.Players.ToMiniYaml(); var playerCount = new MapPlayers(playerDefinitions).Players.Count; if (playerCount > MapPlayers.MaximumPlayerCount) { ConfirmationDialogs.ButtonPrompt( title: "Error: Max player count exceeded", text: $"There are too many players defined ({playerCount}/{MapPlayers.MaximumPlayerCount}).", onConfirm: ShowMenu, confirmText: "Back"); return; } Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs() { { "onSave", (Action <string>)(_ => { hideMenu = false; actionManager.Modified = false; }) }, { "onExit", () => hideMenu = false }, { "map", world.Map }, { "playerDefinitions", playerDefinitions }, { "actorDefinitions", editorActorLayer.Save() } }); }; }
void CreateAbortMissionButton() { if (world.Type != WorldType.Regular) { return; } var button = AddButton("ABORT_MISSION", world.IsGameOver ? "Leave" : "Abort Mission"); button.OnClick = () => { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Leave Mission", text: "Leave this game and return to the menu?", onConfirm: OnQuit, onCancel: ShowMenu, confirmText: "Leave", cancelText: "Stay"); }; }
void PlayVideoStack(WsaPlayerWidget player, Action onComplete = null) { if (player.VideoStackList.Count == 0) { onComplete(); return; } string videowsa = player.VideoStackList.Dequeue(); if (!modData.DefaultFileSystem.Exists(videowsa)) { ConfirmationDialogs.ButtonPrompt( title: "Video not installed", text: "The game videos can be installed from the\n\"Manage Content\" menu in the mod chooser.", cancelText: "Back", onCancel: () => { }); } else { //StopVideo(player); // = pv; player.Load(videowsa); // video playback runs asynchronously player.PlayThen(() => { //StopVideo(player); if (onComplete != null) { onComplete(); } }); // Mute other distracting sounds //MuteSounds(); } }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager, WorldRenderer worldRenderer, Action <bool> hideMenu) { var player = world.LocalPlayer; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); if (player != null && !player.NonCombatant) { var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); checkbox.IsChecked = () => player.WinState != WinState.Undefined; checkbox.GetCheckType = () => player.WinState == WinState.Won ? "checked" : "crossed"; if (player.HasObjectives) { var mo = player.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : player.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } else { // Expand the stats window to cover the hidden objectives var objectiveGroup = widget.Get("OBJECTIVE"); var statsHeader = widget.Get("STATS_HEADERS"); objectiveGroup.Visible = false; statsHeader.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Height += objectiveGroup.Bounds.Height; } var teamTemplate = playerPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); var spectatorTemplate = playerPanel.Get("SPECTATOR_TEMPLATE"); playerPanel.RemoveChildren(); var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault <PlayerStatistics>())) .OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get <LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get <LabelWidget>("TEAM_SCORE"); var scoreCache = new CachedTransform <int, string>(s => s.ToString()); var teamMemberScores = t.Select(tt => tt.PlayerStatistics).Where(s => s != null).ToArray().Select(s => s.Experience); teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum()); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.Player; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); WidgetUtils.BindPlayerNameAndStatus(nameLabel, pp); nameLabel.GetColor = () => pp.Color; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.RelationshipWith(pp) == PlayerRelationship.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; var factionName = pp.Faction.Name != pp.DisplayFaction.Name ? "{0} ({1})".F(pp.DisplayFaction.Name, pp.Faction.Name) : pp.Faction.Name; item.Get <LabelWidget>("FACTION").GetText = () => factionName; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var scoreCache = new CachedTransform <int, string>(s => s.ToString()); item.Get <LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.PlayerStatistics?.Experience ?? 0); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get <LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = spectatorTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <(string Name, string Suffix), string>(c => WidgetUtils.TruncateText(c.Name, nameLabel.Bounds.Width - suffixLength.Update(c.Suffix), nameFont) + c.Suffix); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; return(name.Update((client.Name, suffix))); }; var kickButton = item.Get <ButtonWidget>("KICK"); kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient.Index && client.State != Session.ClientState.Disconnected; kickButton.OnClick = () => { hideMenu(true); ConfirmationDialogs.ButtonPrompt( title: "Kick {0}?".F(client.Name), text: "They will not be able to rejoin this game.", onConfirm: () => { orderManager.IssueOrder(Order.Command("kick {0} {1}".F(client.Index, false))); hideMenu(false); }, onCancel: () => hideMenu(false), confirmText: "Kick"); }; playerPanel.AddChild(item); } } }
public GameSaveBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart, bool isSavePanel, World world) { panel = widget; this.modData = modData; this.onStart = onStart; this.onExit = onExit; this.isSavePanel = isSavePanel; Game.BeforeGameStart += OnGameStart; panel.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); }; gameList = panel.Get <ScrollPanelWidget>("GAME_LIST"); var gameTemplate = panel.Get <ScrollItemWidget>("GAME_TEMPLATE"); var newTemplate = panel.Get <ScrollItemWidget>("NEW_TEMPLATE"); var mod = modData.Manifest; baseSavePath = Platform.ResolvePath(Platform.SupportDirPrefix, "Saves", mod.Id, mod.Metadata.Version); // Avoid filename conflicts when creating new saves if (isSavePanel) { panel.Get("SAVE_TITLE").IsVisible = () => true; defaultSaveFilename = world.Map.Title; var filenameAttempt = 0; while (true) { if (!File.Exists(Path.Combine(baseSavePath, defaultSaveFilename + ".orasav"))) { break; } defaultSaveFilename = world.Map.Title + " ({0})".F(++filenameAttempt); } var saveButton = panel.Get <ButtonWidget>("SAVE_BUTTON"); saveButton.OnClick = () => { Save(world); }; saveButton.IsVisible = () => true; var saveWidgets = panel.Get("SAVE_WIDGETS"); saveTextField = saveWidgets.Get <TextFieldWidget>("SAVE_TEXTFIELD"); gameList.Bounds.Height -= saveWidgets.Bounds.Height; saveWidgets.IsVisible = () => true; } else { panel.Get("LOAD_TITLE").IsVisible = () => true; var loadButton = panel.Get <ButtonWidget>("LOAD_BUTTON"); loadButton.IsVisible = () => true; loadButton.IsDisabled = () => selectedSave == null; loadButton.OnClick = () => { Load(); }; } if (Directory.Exists(baseSavePath)) { LoadGames(gameTemplate, newTemplate, world); } var renameButton = panel.Get <ButtonWidget>("RENAME_BUTTON"); renameButton.IsDisabled = () => selectedSave == null; renameButton.OnClick = () => { var initialName = Path.GetFileNameWithoutExtension(selectedSave); var invalidChars = Path.GetInvalidFileNameChars(); ConfirmationDialogs.TextInputPrompt( "Rename Save", "Enter a new file name:", initialName, onAccept: newName => Rename(initialName, newName), onCancel: null, acceptText: "Rename", cancelText: null, inputValidator: newName => { if (newName == initialName) { return(false); } if (string.IsNullOrWhiteSpace(newName)) { return(false); } if (newName.IndexOfAny(invalidChars) >= 0) { return(false); } if (File.Exists(Path.Combine(baseSavePath, newName))) { return(false); } return(true); }); }; var deleteButton = panel.Get <ButtonWidget>("DELETE_BUTTON"); deleteButton.IsDisabled = () => selectedSave == null; deleteButton.OnClick = () => { ConfirmationDialogs.ButtonPrompt( title: "Delete selected game save?", text: "Delete '{0}'?".F(Path.GetFileNameWithoutExtension(selectedSave)), onConfirm: () => { Delete(selectedSave); if (!games.Any() && !isSavePanel) { Ui.CloseWindow(); onExit(); } else { SelectFirstVisible(); } }, confirmText: "Delete", onCancel: () => { }); }; var deleteAllButton = panel.Get <ButtonWidget>("DELETE_ALL_BUTTON"); deleteAllButton.IsDisabled = () => !games.Any(); deleteAllButton.OnClick = () => { ConfirmationDialogs.ButtonPrompt( title: "Delete all game saves?", text: "Delete {0} game saves?".F(games.Count), onConfirm: () => { foreach (var s in games.ToList()) { Delete(s); } Ui.CloseWindow(); onExit(); }, confirmText: "Delete All", onCancel: () => { }); }; SelectFirstVisible(); }
void SetupManagement() { var renameButton = panel.Get <ButtonWidget>("MNG_RENSEL_BUTTON"); renameButton.IsDisabled = () => selectedReplay == null; renameButton.OnClick = () => { var r = selectedReplay; var initialName = Path.GetFileNameWithoutExtension(r.FilePath); var directoryName = Path.GetDirectoryName(r.FilePath); var invalidChars = Path.GetInvalidFileNameChars(); ConfirmationDialogs.TextInputPrompt( "Rename Replay", "Enter a new file name:", initialName, onAccept: newName => RenameReplay(r, newName), onCancel: null, acceptText: "Rename", cancelText: null, inputValidator: newName => { if (newName == initialName) { return(false); } if (string.IsNullOrWhiteSpace(newName)) { return(false); } if (newName.IndexOfAny(invalidChars) >= 0) { return(false); } if (File.Exists(Path.Combine(directoryName, newName))) { return(false); } return(true); }); }; Action <ReplayMetadata, Action> onDeleteReplay = (r, after) => { ConfirmationDialogs.ButtonPrompt( title: "Delete selected replay?", text: "Delete replay '{0}'?".F(Path.GetFileNameWithoutExtension(r.FilePath)), onConfirm: () => { DeleteReplay(r); after?.Invoke(); }, confirmText: "Delete", onCancel: () => { }); }; var deleteButton = panel.Get <ButtonWidget>("MNG_DELSEL_BUTTON"); deleteButton.IsDisabled = () => selectedReplay == null; deleteButton.OnClick = () => { onDeleteReplay(selectedReplay, () => { if (selectedReplay == null) { SelectFirstVisibleReplay(); } }); }; var deleteAllButton = panel.Get <ButtonWidget>("MNG_DELALL_BUTTON"); deleteAllButton.IsDisabled = () => replayState.Count(kvp => kvp.Value.Visible) == 0; deleteAllButton.OnClick = () => { var list = replayState.Where(kvp => kvp.Value.Visible).Select(kvp => kvp.Key).ToList(); if (list.Count == 0) { return; } if (list.Count == 1) { onDeleteReplay(list[0], () => { if (selectedReplay == null) { SelectFirstVisibleReplay(); } }); return; } ConfirmationDialogs.ButtonPrompt( title: "Delete all selected replays?", text: "Delete {0} replays?".F(list.Count), onConfirm: () => { list.ForEach(DeleteReplay); if (selectedReplay == null) { SelectFirstVisibleReplay(); } }, confirmText: "Delete All", onCancel: () => { }); }; }
public SettingsLogic(Widget widget, Action onExit, WorldRenderer worldRenderer, Dictionary <string, MiniYaml> logicArgs) { panelContainer = widget.Get("PANEL_CONTAINER"); var panelTemplate = panelContainer.Get <ContainerWidget>("PANEL_TEMPLATE"); panelContainer.RemoveChild(panelTemplate); tabContainer = widget.Get("SETTINGS_TAB_CONTAINER"); tabTemplate = tabContainer.Get <ButtonWidget>("BUTTON_TEMPLATE"); tabContainer.RemoveChild(tabTemplate); if (logicArgs.TryGetValue("ButtonStride", out var buttonStrideNode)) { buttonStride = FieldLoader.GetValue <int2>("ButtonStride", buttonStrideNode.Value); } if (logicArgs.TryGetValue("Panels", out var settingsPanels)) { panels = settingsPanels.ToDictionary(kv => kv.Value); foreach (var panel in panels) { var container = panelTemplate.Clone() as ContainerWidget; container.Id = panel.Key; panelContainer.AddChild(container); Game.LoadWidget(worldRenderer.World, panel.Key, container, new WidgetArgs() { { "registerPanel", (Action <string, string, Func <Widget, Func <bool> >, Func <Widget, Action> >)RegisterSettingsPanel }, { "panelID", panel.Key }, { "label", panel.Value } }); } } widget.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { needsRestart |= leavePanelActions[activePanel](); var current = Game.Settings; current.Save(); Action closeAndExit = () => { Ui.CloseWindow(); onExit(); }; if (needsRestart) { Action noRestart = () => ConfirmationDialogs.ButtonPrompt( title: "Restart Required", text: "Some changes will not be applied until\nthe game is restarted.", onCancel: closeAndExit, cancelText: "Continue"); if (!Game.ExternalMods.TryGetValue(ExternalMod.MakeKey(Game.ModData.Manifest), out var external)) { noRestart(); return; } ConfirmationDialogs.ButtonPrompt( title: "Restart Now?", text: "Some changes will not be applied until\nthe game is restarted. Restart now?", onConfirm: () => Game.SwitchToExternalMod(external, null, noRestart), onCancel: closeAndExit, confirmText: "Restart Now", cancelText: "Restart Later"); } else { closeAndExit(); } }; widget.Get <ButtonWidget>("RESET_BUTTON").OnClick = () => { Action reset = () => { resetPanelActions[activePanel](); Game.Settings.Save(); }; ConfirmationDialogs.ButtonPrompt( title: $"Reset \"{panels[activePanel]}\"", text: "Are you sure you want to reset\nall settings in this panel?", onConfirm: reset, onCancel: () => { }, confirmText: "Reset", cancelText: "Cancel"); }; }
public IngameMenuLogic(Widget widget, ModData modData, World world, Action onExit, WorldRenderer worldRenderer, IngameInfoPanel activePanel) { var leaving = false; menu = widget.Get("INGAME_MENU"); var mpe = world.WorldActor.TraitOrDefault <MenuPaletteEffect>(); if (mpe != null) { mpe.Fade(mpe.Info.MenuEffect); } menu.Get <LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Metadata.Version; var hideMenu = false; menu.Get("MENU_BUTTONS").IsVisible = () => !hideMenu; var scriptContext = world.WorldActor.TraitOrDefault <LuaScript>(); var hasError = scriptContext != null && scriptContext.FatalErrorOccurred; // TODO: Create a mechanism to do things like this cleaner. Also needed for scripted missions Action onQuit = () => { if (world.Type == WorldType.Regular) { Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", "Leave", world.LocalPlayer == null ? null : world.LocalPlayer.Faction.InternalName); } leaving = true; var iop = world.WorldActor.TraitsImplementing <IObjectivesPanel>().FirstOrDefault(); var exitDelay = iop != null ? iop.ExitDelay : 0; if (mpe != null) { Game.RunAfterDelay(exitDelay, () => { if (Game.IsCurrentWorld(world)) { mpe.Fade(MenuPaletteEffect.EffectType.Black); } }); exitDelay += 40 * mpe.Info.FadeLength; } Game.RunAfterDelay(exitDelay, () => { if (!Game.IsCurrentWorld(world)) { return; } Game.Disconnect(); Ui.ResetAll(); Game.LoadShellMap(); }); }; Action closeMenu = () => { Ui.CloseWindow(); if (mpe != null) { mpe.Fade(MenuPaletteEffect.EffectType.None); } onExit(); }; Action showMenu = () => hideMenu = false; var abortMissionButton = menu.Get <ButtonWidget>("ABORT_MISSION"); abortMissionButton.IsVisible = () => world.Type == WorldType.Regular; abortMissionButton.IsDisabled = () => leaving; if (world.IsGameOver) { abortMissionButton.GetText = () => "Leave"; } abortMissionButton.OnClick = () => { hideMenu = true; if (world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Won) { Action restartAction = null; var iop = world.WorldActor.TraitsImplementing <IObjectivesPanel>().FirstOrDefault(); var exitDelay = iop != null ? iop.ExitDelay : 0; if (world.LobbyInfo.IsSinglePlayer) { restartAction = () => { Ui.CloseWindow(); if (mpe != null) { if (Game.IsCurrentWorld(world)) { mpe.Fade(MenuPaletteEffect.EffectType.Black); } exitDelay += 40 * mpe.Info.FadeLength; } Game.RunAfterDelay(exitDelay, Game.RestartGame); }; } ConfirmationDialogs.ButtonPrompt( title: "Leave Mission", text: "Leave this game and return to the menu?", onConfirm: onQuit, onCancel: showMenu, confirmText: "Leave", cancelText: "Stay", otherText: "Restart", onOther: restartAction); } else { onQuit(); } }; var exitEditorButton = menu.Get <ButtonWidget>("EXIT_EDITOR"); exitEditorButton.IsVisible = () => world.Type == WorldType.Editor; exitEditorButton.OnClick = () => { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Exit Map Editor", text: "Exit and lose all unsaved changes?", onConfirm: onQuit, onCancel: showMenu); }; Action onSurrender = () => { world.IssueOrder(new Order("Surrender", world.LocalPlayer.PlayerActor, false)); closeMenu(); }; var surrenderButton = menu.Get <ButtonWidget>("SURRENDER"); surrenderButton.IsVisible = () => world.Type == WorldType.Regular; surrenderButton.IsDisabled = () => world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined || world.Map.Visibility.HasFlag(MapVisibility.MissionSelector) || hasError; surrenderButton.OnClick = () => { hideMenu = true; ConfirmationDialogs.ButtonPrompt( title: "Surrender", text: "Are you sure you want to surrender?", onConfirm: onSurrender, onCancel: showMenu, confirmText: "Surrender", cancelText: "Stay"); }; var saveMapButton = menu.Get <ButtonWidget>("SAVE_MAP"); saveMapButton.IsVisible = () => world.Type == WorldType.Editor; saveMapButton.OnClick = () => { hideMenu = true; var editorActorLayer = world.WorldActor.Trait <EditorActorLayer>(); Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs() { { "onSave", (Action <string>)(_ => hideMenu = false) }, { "onExit", () => hideMenu = false }, { "map", world.Map }, { "playerDefinitions", editorActorLayer.Players.ToMiniYaml() }, { "actorDefinitions", editorActorLayer.Save() } }); }; var musicButton = menu.Get <ButtonWidget>("MUSIC"); musicButton.IsDisabled = () => leaving; musicButton.OnClick = () => { hideMenu = true; Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs() { { "onExit", () => hideMenu = false }, { "world", world } }); }; var settingsButton = widget.Get <ButtonWidget>("SETTINGS"); settingsButton.IsDisabled = () => leaving; settingsButton.OnClick = () => { hideMenu = true; Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs() { { "world", world }, { "worldRenderer", worldRenderer }, { "onExit", () => hideMenu = false }, }); }; var resumeButton = menu.Get <ButtonWidget>("RESUME"); resumeButton.IsDisabled = () => leaving; if (world.IsGameOver) { resumeButton.GetText = () => "Return to map"; } resumeButton.OnClick = closeMenu; var panelRoot = widget.GetOrNull("PANEL_ROOT"); if (panelRoot != null && world.Type != WorldType.Editor) { var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs() { { "activePanel", activePanel } }); gameInfoPanel.IsVisible = () => !hideMenu; } }
public SaveMapLogic(Widget widget, ModData modData, Action <string> onSave, Action onExit, Map map, List <MiniYamlNode> playerDefinitions, List <MiniYamlNode> actorDefinitions) { var title = widget.Get <TextFieldWidget>("TITLE"); title.Text = map.Title; var author = widget.Get <TextFieldWidget>("AUTHOR"); author.Text = map.Author; var visibilityPanel = Ui.LoadWidget("MAP_SAVE_VISIBILITY_PANEL", null, new WidgetArgs()); var visOptionTemplate = visibilityPanel.Get <CheckboxWidget>("VISIBILITY_TEMPLATE"); visibilityPanel.RemoveChildren(); foreach (MapVisibility visibilityOption in Enum.GetValues(typeof(MapVisibility))) { // To prevent users from breaking the game only show the 'Shellmap' option when it is already set. if (visibilityOption == MapVisibility.Shellmap && !map.Visibility.HasFlag(visibilityOption)) { continue; } var checkbox = (CheckboxWidget)visOptionTemplate.Clone(); checkbox.GetText = () => visibilityOption.ToString(); checkbox.IsChecked = () => map.Visibility.HasFlag(visibilityOption); checkbox.OnClick = () => map.Visibility ^= visibilityOption; visibilityPanel.AddChild(checkbox); } var visibilityDropdown = widget.Get <DropDownButtonWidget>("VISIBILITY_DROPDOWN"); visibilityDropdown.OnMouseDown = _ => { visibilityDropdown.RemovePanel(); visibilityDropdown.AttachPanel(visibilityPanel); }; var writableDirectories = new List <SaveDirectory>(); SaveDirectory selectedDirectory = null; var directoryDropdown = widget.Get <DropDownButtonWidget>("DIRECTORY_DROPDOWN"); { Func <SaveDirectory, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, () => selectedDirectory == option, () => selectedDirectory = option); item.Get <LabelWidget>("LABEL").GetText = () => option.DisplayName; return(item); }; foreach (var kv in modData.MapCache.MapLocations) { var folder = kv.Key as Folder; if (folder == null) { continue; } try { using (var fs = File.Create(Path.Combine(folder.Name, ".testwritable"), 1, FileOptions.DeleteOnClose)) { // Do nothing: we just want to test whether we can create the file } writableDirectories.Add(new SaveDirectory(folder, kv.Value.ToString(), kv.Value)); } catch { // Directory is not writable } } if (map.Package != null) { selectedDirectory = writableDirectories.FirstOrDefault(k => k.Folder.Contains(map.Package.Name)); if (selectedDirectory == null) { selectedDirectory = writableDirectories.FirstOrDefault(k => Directory.GetDirectories(k.Folder.Name).Any(f => f.Contains(map.Package.Name))); } } // Prioritize MapClassification.User directories over system directories if (selectedDirectory == null) { selectedDirectory = writableDirectories.OrderByDescending(kv => kv.Classification).First(); } directoryDropdown.GetText = () => selectedDirectory?.DisplayName ?? ""; directoryDropdown.OnClick = () => directoryDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, writableDirectories, setupItem); } var mapIsUnpacked = map.Package != null && map.Package is Folder; var filename = widget.Get <TextFieldWidget>("FILENAME"); filename.Text = map.Package == null ? "" : mapIsUnpacked?Path.GetFileName(map.Package.Name) : Path.GetFileNameWithoutExtension(map.Package.Name); var fileType = mapIsUnpacked ? MapFileType.Unpacked : MapFileType.OraMap; var fileTypes = new Dictionary <MapFileType, MapFileTypeInfo>() { { MapFileType.OraMap, new MapFileTypeInfo { Extension = ".oramap", UiLabel = ".oramap" } }, { MapFileType.Unpacked, new MapFileTypeInfo { Extension = "", UiLabel = "(unpacked)" } } }; var typeDropdown = widget.Get <DropDownButtonWidget>("TYPE_DROPDOWN"); { Func <KeyValuePair <MapFileType, MapFileTypeInfo>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, () => fileType == option.Key, () => { typeDropdown.Text = option.Value.UiLabel; fileType = option.Key; }); item.Get <LabelWidget>("LABEL").GetText = () => option.Value.UiLabel; return(item); }; typeDropdown.Text = fileTypes[fileType].UiLabel; typeDropdown.OnClick = () => typeDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, fileTypes, setupItem); } var close = widget.Get <ButtonWidget>("BACK_BUTTON"); close.OnClick = () => { Ui.CloseWindow(); onExit(); }; var save = widget.Get <ButtonWidget>("SAVE_BUTTON"); save.OnClick = () => { if (string.IsNullOrEmpty(filename.Text)) { return; } map.Title = title.Text; map.Author = author.Text; if (actorDefinitions != null) { map.ActorDefinitions = actorDefinitions; } if (playerDefinitions != null) { map.PlayerDefinitions = playerDefinitions; } map.RequiresMod = modData.Manifest.Id; var combinedPath = Platform.ResolvePath(Path.Combine(selectedDirectory.Folder.Name, filename.Text + fileTypes[fileType].Extension)); try { if (!(map.Package is IReadWritePackage package) || package.Name != combinedPath) { selectedDirectory.Folder.Delete(combinedPath); if (fileType == MapFileType.OraMap) { package = ZipFileLoader.Create(combinedPath); } else { package = new Folder(combinedPath); } } map.Save(package); Console.WriteLine("Saved current map at {0}", combinedPath); Ui.CloseWindow(); onSave(map.Uid); } catch (Exception e) { Log.Write("debug", "Failed to save map at {0}: {1}", combinedPath, e.Message); Log.Write("debug", "{0}", e.StackTrace); ConfirmationDialogs.ButtonPrompt( title: "Failed to save map", text: "See debug.log for details.", onConfirm: () => { }, confirmText: "OK"); } }; }