//-----------------------------------------------------------------------------
// 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) { }
}
}