//----------------------------------------------------------------------------- // MainMenuScreen.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Net; using Microsoft.Xna.Framework.Graphics; namespace NetRumble { /// /// The main menu screen is the first thing displayed when the game starts up. /// public class MainMenuScreen : MenuScreen { /// /// The potential states of the main menu. /// enum MainMenuState { Empty, SignedOut, SignedInLocal, SignedInLive, } /// /// Flag that tracks last known value of IsTrialMode /// bool trialMode; bool updateState; /// /// The current state of the main menu. /// MainMenuState state = MainMenuState.Empty; MainMenuState State { get { return state; } set { // exit early from trivial sets if (state == value && trialMode == Guide.IsTrialMode && !updateState) { return; } updateState = false; // reset the flag, in case it was set state = value; trialMode = Guide.IsTrialMode; if (MenuEntries != null) { switch (state) { case MainMenuState.SignedInLive: { MenuEntries.Clear(); MenuEntries.Add("Quick Match"); MenuEntries.Add("Create Xbox LIVE Session"); MenuEntries.Add("Join Xbox LIVE Session"); MenuEntries.Add("Create System Link Session"); MenuEntries.Add("Join System Link Session"); if (Guide.IsTrialMode) { MenuEntries.Add("Unlock Full Game"); } else if (ScreenManager.invited != null) { MenuEntries.Add("Join Invited Game"); } MenuEntries.Add("Exit"); break; } case MainMenuState.SignedInLocal: { MenuEntries.Clear(); MenuEntries.Add("Create LAN Session"); MenuEntries.Add("Join LAN Session"); MenuEntries.Add("Exit"); break; } case MainMenuState.SignedOut: { MenuEntries.Clear(); MenuEntries.Add("Sign In"); MenuEntries.Add("Exit"); break; } } } } } /// /// Constructs a new MainMenu object. /// public MainMenuScreen() : base() { // set the transition times TransitionOnTime = TimeSpan.FromSeconds(1.0); TransitionOffTime = TimeSpan.FromSeconds(0.0); // capture current value of trial mode flag trialMode = Guide.IsTrialMode; updateState = false; } /// /// Updates the screen. This method checks the GameScreen.IsActive /// property, so the game will stop updating when the pause menu is active, /// or if you tab away to a different application. /// public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen) { bool signedIntoLive = false; if (Gamer.SignedInGamers.Count > 0) { foreach (SignedInGamer signedInGamer in Gamer.SignedInGamers) { if (signedInGamer.IsSignedInToLive) { signedIntoLive = true; break; } } State = signedIntoLive ? MainMenuState.SignedInLive : MainMenuState.SignedInLocal; } else { State = MainMenuState.SignedOut; } base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen); } /// /// Responds to user menu selections. /// protected override void OnSelectEntry(int entryIndex) { switch (state) { case MainMenuState.SignedInLive: { switch (entryIndex) { case 0: // Quick Match QuickMatchSession(); break; case 1: // Create Internet Session CreateSession(NetworkSessionType.PlayerMatch); break; case 2: // Join Internet Session FindSession(NetworkSessionType.PlayerMatch); break; case 3: // Create System Link Session CreateSession(NetworkSessionType.SystemLink); break; case 4: // Join System Link Session FindSession(NetworkSessionType.SystemLink); break; case 5: // Exit or Unlock Full Game (depending on trialMode flag) if (trialMode) ShowOffer(); else if (ScreenManager.invited != null) JoinInvitedGame(); else OnCancel(); break; case 6: // Exit OnCancel(); break; } break; } case MainMenuState.SignedInLocal: { switch (entryIndex) { case 0: // Create System Link Session CreateSession(NetworkSessionType.SystemLink); break; case 1: // Join System Link Session FindSession(NetworkSessionType.SystemLink); break; case 2: // Exit OnCancel(); break; } break; } case MainMenuState.SignedOut: { switch (entryIndex) { case 0: // Sign In if (!Guide.IsVisible) { Guide.ShowSignIn(1, false); } break; case 1: // Exit OnCancel(); break; } break; } } } /// /// Show the marketplace offer for a trial mode game. /// private void ShowOffer() { // NOTE: This chooses the first signed in gamer, since we don't have any information // about which gamepad clicked on the button. Guide.ShowMarketplace(Gamer.SignedInGamers[0].PlayerIndex); } /// /// Attempt to join a session using an invite that was received. /// public void JoinInvitedGame() { try { // start async join for the invited game var joinTask = NetworkSession.JoinInvitedAsync(Gamer.SignedInGamers); var busyScreen = new NetworkBusyScreen("Joining the session...", joinTask); busyScreen.OperationCompleted += InvitedSessionJoined; ScreenManager.AddScreen(busyScreen); } catch { // could not begin to join invited game, so default to the pre-existing MainMenuScreen } ScreenManager.invited = null; updateState = true; } /// /// When the user cancels the main menu, ask if they want to exit the sample. /// protected override void OnCancel() { const string message = "Exit Net Rumble?"; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += ExitMessageBoxAccepted; ScreenManager.AddScreen(messageBox); } /// /// Event handler for when the user selects ok on the "are you sure /// you want to exit" message box. /// void ExitMessageBoxAccepted(object sender, EventArgs e) { ScreenManager.Game.Exit(); } /// /// Screen-specific update to gamer rich presence. /// public override void UpdatePresence() { foreach (SignedInGamer signedInGamer in Gamer.SignedInGamers) { if (signedInGamer.IsSignedInToLive) { signedInGamer.Presence.PresenceMode = GamerPresenceMode.AtMenu; } } } private void QuickMatchSession() { // start the search try { var findTask = NetworkSession.FindAsync( NetworkSessionType.PlayerMatch, 1, new Dictionary()); var busyScreen = new NetworkBusyScreen( "Searching for a session...", findTask); busyScreen.OperationCompleted += QuickMatchSearchCompleted; ScreenManager.AddScreen(busyScreen); } catch (NetworkException ne) { const string message = "Failed searching for the session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to search for session: " + ne.Message); } catch (GamerPrivilegeException gpe) { const string message = "You do not have permission to search for a session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine( "Insufficient privilege to search for session: " + gpe.Message); } } /// /// Start creating a session of the given type. /// /// The type of session to create. void CreateSession(NetworkSessionType sessionType) { // create the session try { var createTask = NetworkSession.CreateAsync(sessionType, 1, World.MaximumPlayers, 0, new Dictionary()); var busyScreen = new NetworkBusyScreen( "Creating a session...", createTask); busyScreen.OperationCompleted += SessionCreated; ScreenManager.AddScreen(busyScreen); } catch (NetworkException ne) { const string message = "Failed creating the session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to create session: " + ne.Message); } catch (GamerPrivilegeException gpe) { const string message = "You do not have permission to create a session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine( "Insufficient privilege to create session: " + gpe.Message); } } /// /// Start searching for a session of the given type. /// /// The type of session to look for. void FindSession(NetworkSessionType sessionType) { // create the Search screen ScreenManager.AddScreen(new SearchResultsScreen(sessionType)); } /// /// Callback to receive the network-session search results from quick-match. /// void QuickMatchSearchCompleted(object sender, OperationCompletedEventArgs e) { var availableSessions = e.Result as AvailableNetworkSessionCollection; if (e.Exception != null) { string message = e.Exception is GamerPrivilegeException ? "You do not have permission to search for a session." : "Failed searching for the session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to search for session: " + e.Exception.Message); return; } if ((availableSessions != null) && (availableSessions.Count > 0)) { try { var joinTask = NetworkSession.JoinAsync(availableSessions[0]); var busyScreen = new NetworkBusyScreen( "Joining the session...", joinTask); busyScreen.OperationCompleted += QuickMatchSessionJoined; ScreenManager.AddScreen(busyScreen); } catch (Exception ex) { const string message = "Failed joining the session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to join session: " + ex.Message); } } else { const string message = "No matches were found."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); } } /// /// Callback when a session is created. /// void SessionCreated(object sender, OperationCompletedEventArgs e) { var networkSession = e.Result as NetworkSession; if (e.Exception != null || networkSession == null) { string message = e.Exception is GamerPrivilegeException ? "You do not have permission to create a session. " + e.Exception.Message : "Failed creating the session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to create session: " + e.Exception?.Message); return; } if (networkSession != null) { networkSession.AllowHostMigration = true; networkSession.AllowJoinInProgress = false; LoadLobbyScreen(networkSession); } } /// /// Callback when a session is quick-matched. /// void QuickMatchSessionJoined(object sender, OperationCompletedEventArgs e) { var networkSession = e.Result as NetworkSession; if (e.Exception != null || networkSession == null) { string message = e.Exception is GamerPrivilegeException ? "You do not have permission to join a session." : "Failed joining the session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to join session: " + e.Exception?.Message); return; } if (networkSession != null) { LoadLobbyScreen(networkSession); } } /// /// Load the lobby screen with the new session. /// void LoadLobbyScreen(NetworkSession networkSession) { if (networkSession != null) { LobbyScreen lobbyScreen = new LobbyScreen(networkSession); lobbyScreen.ScreenManager = this.ScreenManager; ScreenManager.AddScreen(lobbyScreen); } } /// /// Finishes the asynchronous process of joining a game from an invitation, /// joining the lobby of a hosted game if the join was successful. /// void InvitedSessionJoined(object sender, OperationCompletedEventArgs e) { var networkSession = e.Result as NetworkSession; if (e.Exception != null || networkSession == null) { string message = e.Exception is NetworkSessionJoinException je ? "Failed joining the session (" + je.JoinError.ToString() + ")." : "Failed joining the session (" + (e.Exception?.Message ?? "Unknown error") + ")."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to join session: " + e.Exception?.Message); return; } // Start the lobby if we got the session! // Otherwise the MainMenuScreen will be available. LobbyScreen lobbyScreen = new LobbyScreen(networkSession); lobbyScreen.ScreenManager = ScreenManager; ScreenManager.AddScreen(lobbyScreen); } /// /// Event handler for when the user selects ok on the network-operation-failed /// message box. /// void FailedMessageBox(object sender, EventArgs e) { } } }