#region File Description //----------------------------------------------------------------------------- // MainMenuScreen.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Net; #endregion namespace NetRumble { /// /// The main menu screen is the first thing displayed when the game starts up. /// public class MainMenuScreen : MenuScreen { #region State Data /// /// 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 System Link Session"); MenuEntries.Add("Join System Link Session"); MenuEntries.Add("Exit"); break; } case MainMenuState.SignedOut: { MenuEntries.Clear(); MenuEntries.Add("Sign In"); MenuEntries.Add("Exit"); break; } } } } } #endregion #region Initialization /// /// 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; } #endregion #region Updating Methods /// /// 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 Xbox LIVE Session CreateSession(NetworkSessionType.PlayerMatch); break; case 2: // Join Xbox LIVE 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 { // begin to join the game we were invited to IAsyncResult asyncResult = NetworkSession.BeginJoinInvited(1, null, null); // create the busy screen NetworkBusyScreen busyScreen = new NetworkBusyScreen("Joining the session...", asyncResult); 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; } } } #endregion #region Networking Methods private void QuickMatchSession() { // start the search try { IAsyncResult asyncResult = NetworkSession.BeginFind( NetworkSessionType.PlayerMatch, 1, null, null, null); // create the busy screen NetworkBusyScreen busyScreen = new NetworkBusyScreen( "Searching for a session...", asyncResult); 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 { IAsyncResult asyncResult = NetworkSession.BeginCreate(sessionType, 1, World.MaximumPlayers, null, null); // create the busy screen NetworkBusyScreen busyScreen = new NetworkBusyScreen( "Creating a session...", asyncResult); 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 new screen SearchResultsScreen searchResultsScreen = new SearchResultsScreen(sessionType); searchResultsScreen.ScreenManager = this.ScreenManager; ScreenManager.AddScreen(searchResultsScreen); // start the search try { IAsyncResult asyncResult = NetworkSession.BeginFind(sessionType, 1, null, null, null); // create the busy screen NetworkBusyScreen busyScreen = new NetworkBusyScreen( "Searching for a session...", asyncResult); busyScreen.OperationCompleted += searchResultsScreen.SessionsFound; 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); } } /// /// Callback to receive the network-session search results from quick-match. /// void QuickMatchSearchCompleted(object sender, OperationCompletedEventArgs e) { try { AvailableNetworkSessionCollection availableSessions = NetworkSession.EndFind(e.AsyncResult); if ((availableSessions != null) && (availableSessions.Count > 0)) { // join the session try { IAsyncResult asyncResult = NetworkSession.BeginJoin( availableSessions[0], null, null); // create the busy screen NetworkBusyScreen busyScreen = new NetworkBusyScreen( "Joining the session...", asyncResult); busyScreen.OperationCompleted += QuickMatchSessionJoined; ScreenManager.AddScreen(busyScreen); } catch (NetworkException ne) { 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: " + ne.Message); } catch (GamerPrivilegeException gpe) { const string message = "You do not have permission to join a session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine( "Insufficient privilege to join session: " + gpe.Message); } } else { const string message = "No matches were found."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); } } catch (GamerPrivilegeException gpe){ MessageBoxScreen messageBox = new MessageBoxScreen(gpe.Message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); } } /// /// Callback when a session is created. /// void SessionCreated(object sender, OperationCompletedEventArgs e) { NetworkSession networkSession = null; try { networkSession = NetworkSession.EndCreate(e.AsyncResult); } 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+gpe.Message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine( "Insufficient privilege to create session: " + gpe.Message); } if (networkSession != null) { networkSession.AllowHostMigration = true; networkSession.AllowJoinInProgress = false; LoadLobbyScreen(networkSession); } } /// /// Callback when a session is quick-matched. /// void QuickMatchSessionJoined(object sender, OperationCompletedEventArgs e) { NetworkSession networkSession = null; try { networkSession = NetworkSession.EndJoin(e.AsyncResult); } catch (NetworkException ne) { 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: " + ne.Message); } catch (GamerPrivilegeException gpe) { const string message = "You do not have permission to join a session."; MessageBoxScreen messageBox = new MessageBoxScreen(message); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine( "Insufficient privilege to join session: " + gpe.Message); } 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) { NetworkSession networkSession = null; try { networkSession = NetworkSession.EndJoinInvited(e.AsyncResult); } catch (NetworkSessionJoinException je) { const string message = "Failed joining the session ("; MessageBoxScreen messageBox = new MessageBoxScreen(message + je.JoinError.ToString() + ")."); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to join session: " + je.Message); } catch (Exception ge) { const string message = "Failed joining the session ("; MessageBoxScreen messageBox = new MessageBoxScreen(message + ge.Message + ")."); messageBox.Accepted += FailedMessageBox; messageBox.Cancelled += FailedMessageBox; ScreenManager.AddScreen(messageBox); System.Console.WriteLine("Failed to join session: " + ge.Message); } // Start the lobby if we got the session! // Otherwise the MainMenuScreen will be available. if (networkSession != null) { 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) { } #endregion } }