MainMenuScreen.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // MainMenuScreen.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using Microsoft.Xna.Framework;
  12. using Microsoft.Xna.Framework.GamerServices;
  13. using Microsoft.Xna.Framework.Graphics;
  14. using Microsoft.Xna.Framework.Net;
  15. #endregion
  16. namespace NetRumble
  17. {
  18. /// <summary>
  19. /// The main menu screen is the first thing displayed when the game starts up.
  20. /// </summary>
  21. public class MainMenuScreen : MenuScreen
  22. {
  23. #region State Data
  24. /// <summary>
  25. /// The potential states of the main menu.
  26. /// </summary>
  27. enum MainMenuState
  28. {
  29. Empty,
  30. SignedOut,
  31. SignedInLocal,
  32. SignedInLive,
  33. }
  34. /// <summary>
  35. /// Flag that tracks last known value of IsTrialMode
  36. /// </summary>
  37. bool trialMode;
  38. bool updateState;
  39. /// <summary>
  40. /// The current state of the main menu.
  41. /// </summary>
  42. MainMenuState state = MainMenuState.Empty;
  43. MainMenuState State
  44. {
  45. get { return state; }
  46. set
  47. {
  48. // exit early from trivial sets
  49. if (state == value && trialMode == Guide.IsTrialMode && !updateState)
  50. {
  51. return;
  52. }
  53. updateState = false; // reset the flag, in case it was set
  54. state = value;
  55. trialMode = Guide.IsTrialMode;
  56. if (MenuEntries != null)
  57. {
  58. switch (state)
  59. {
  60. case MainMenuState.SignedInLive:
  61. {
  62. MenuEntries.Clear();
  63. MenuEntries.Add("Quick Match");
  64. MenuEntries.Add("Create Xbox LIVE Session");
  65. MenuEntries.Add("Join Xbox LIVE Session");
  66. MenuEntries.Add("Create System Link Session");
  67. MenuEntries.Add("Join System Link Session");
  68. if (Guide.IsTrialMode)
  69. {
  70. MenuEntries.Add("Unlock Full Game");
  71. }
  72. else if (ScreenManager.invited != null)
  73. {
  74. MenuEntries.Add("Join Invited Game");
  75. }
  76. MenuEntries.Add("Exit");
  77. break;
  78. }
  79. case MainMenuState.SignedInLocal:
  80. {
  81. MenuEntries.Clear();
  82. MenuEntries.Add("Create System Link Session");
  83. MenuEntries.Add("Join System Link Session");
  84. MenuEntries.Add("Exit");
  85. break;
  86. }
  87. case MainMenuState.SignedOut:
  88. {
  89. MenuEntries.Clear();
  90. MenuEntries.Add("Sign In");
  91. MenuEntries.Add("Exit");
  92. break;
  93. }
  94. }
  95. }
  96. }
  97. }
  98. #endregion
  99. #region Initialization
  100. /// <summary>
  101. /// Constructs a new MainMenu object.
  102. /// </summary>
  103. public MainMenuScreen() : base()
  104. {
  105. // set the transition times
  106. TransitionOnTime = TimeSpan.FromSeconds(1.0);
  107. TransitionOffTime = TimeSpan.FromSeconds(0.0);
  108. // capture current value of trial mode flag
  109. trialMode = Guide.IsTrialMode;
  110. updateState = false;
  111. }
  112. #endregion
  113. #region Updating Methods
  114. /// <summary>
  115. /// Updates the screen. This method checks the GameScreen.IsActive
  116. /// property, so the game will stop updating when the pause menu is active,
  117. /// or if you tab away to a different application.
  118. /// </summary>
  119. public override void Update(GameTime gameTime, bool otherScreenHasFocus,
  120. bool coveredByOtherScreen)
  121. {
  122. bool signedIntoLive = false;
  123. if (Gamer.SignedInGamers.Count > 0)
  124. {
  125. foreach (SignedInGamer signedInGamer in Gamer.SignedInGamers)
  126. {
  127. if (signedInGamer.IsSignedInToLive)
  128. {
  129. signedIntoLive = true;
  130. break;
  131. }
  132. }
  133. State = signedIntoLive ? MainMenuState.SignedInLive :
  134. MainMenuState.SignedInLocal;
  135. }
  136. else
  137. {
  138. State = MainMenuState.SignedOut;
  139. }
  140. base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
  141. }
  142. /// <summary>
  143. /// Responds to user menu selections.
  144. /// </summary>
  145. protected override void OnSelectEntry(int entryIndex)
  146. {
  147. switch (state)
  148. {
  149. case MainMenuState.SignedInLive:
  150. {
  151. switch (entryIndex)
  152. {
  153. case 0: // Quick Match
  154. QuickMatchSession();
  155. break;
  156. case 1: // Create Xbox LIVE Session
  157. CreateSession(NetworkSessionType.PlayerMatch);
  158. break;
  159. case 2: // Join Xbox LIVE Session
  160. FindSession(NetworkSessionType.PlayerMatch);
  161. break;
  162. case 3: // Create System Link Session
  163. CreateSession(NetworkSessionType.SystemLink);
  164. break;
  165. case 4: // Join System Link Session
  166. FindSession(NetworkSessionType.SystemLink);
  167. break;
  168. case 5: // Exit or Unlock Full Game (depending on trialMode flag)
  169. if (trialMode)
  170. ShowOffer();
  171. else if (ScreenManager.invited != null)
  172. JoinInvitedGame();
  173. else
  174. OnCancel();
  175. break;
  176. case 6: // Exit
  177. OnCancel();
  178. break;
  179. }
  180. break;
  181. }
  182. case MainMenuState.SignedInLocal:
  183. {
  184. switch (entryIndex)
  185. {
  186. case 0: // Create System Link Session
  187. CreateSession(NetworkSessionType.SystemLink);
  188. break;
  189. case 1: // Join System Link Session
  190. FindSession(NetworkSessionType.SystemLink);
  191. break;
  192. case 2: // Exit
  193. OnCancel();
  194. break;
  195. }
  196. break;
  197. }
  198. case MainMenuState.SignedOut:
  199. {
  200. switch (entryIndex)
  201. {
  202. case 0: // Sign In
  203. if (!Guide.IsVisible)
  204. {
  205. Guide.ShowSignIn(1, false);
  206. }
  207. break;
  208. case 1: // Exit
  209. OnCancel();
  210. break;
  211. }
  212. break;
  213. }
  214. }
  215. }
  216. /// <summary>
  217. /// Show the marketplace offer for a trial mode game.
  218. /// </summary>
  219. private void ShowOffer()
  220. {
  221. // NOTE: This chooses the first signed in gamer, since we don't have any information
  222. // about which gamepad clicked on the button.
  223. Guide.ShowMarketplace(Gamer.SignedInGamers[0].PlayerIndex);
  224. }
  225. /// <summary>
  226. /// Attempt to join a session using an invite that was received.
  227. /// </summary>
  228. public void JoinInvitedGame()
  229. {
  230. try
  231. {
  232. // begin to join the game we were invited to
  233. IAsyncResult asyncResult = NetworkSession.BeginJoinInvited(1, null, null);
  234. // create the busy screen
  235. NetworkBusyScreen busyScreen = new NetworkBusyScreen("Joining the session...", asyncResult);
  236. busyScreen.OperationCompleted += InvitedSessionJoined;
  237. ScreenManager.AddScreen(busyScreen);
  238. }
  239. catch
  240. {
  241. // could not begin to join invited game, so default to the pre-existing MainMenuScreen
  242. }
  243. ScreenManager.invited = null;
  244. updateState = true;
  245. }
  246. /// <summary>
  247. /// When the user cancels the main menu, ask if they want to exit the sample.
  248. /// </summary>
  249. protected override void OnCancel()
  250. {
  251. const string message = "Exit Net Rumble?";
  252. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  253. messageBox.Accepted += ExitMessageBoxAccepted;
  254. ScreenManager.AddScreen(messageBox);
  255. }
  256. /// <summary>
  257. /// Event handler for when the user selects ok on the "are you sure
  258. /// you want to exit" message box.
  259. /// </summary>
  260. void ExitMessageBoxAccepted(object sender, EventArgs e)
  261. {
  262. ScreenManager.Game.Exit();
  263. }
  264. /// <summary>
  265. /// Screen-specific update to gamer rich presence.
  266. /// </summary>
  267. public override void UpdatePresence()
  268. {
  269. foreach (SignedInGamer signedInGamer in Gamer.SignedInGamers)
  270. {
  271. if (signedInGamer.IsSignedInToLive)
  272. {
  273. signedInGamer.Presence.PresenceMode = GamerPresenceMode.AtMenu;
  274. }
  275. }
  276. }
  277. #endregion
  278. #region Networking Methods
  279. private void QuickMatchSession()
  280. {
  281. // start the search
  282. try
  283. {
  284. IAsyncResult asyncResult = NetworkSession.BeginFind(
  285. NetworkSessionType.PlayerMatch, 1, null, null, null);
  286. // create the busy screen
  287. NetworkBusyScreen busyScreen = new NetworkBusyScreen(
  288. "Searching for a session...", asyncResult);
  289. busyScreen.OperationCompleted += QuickMatchSearchCompleted;
  290. ScreenManager.AddScreen(busyScreen);
  291. }
  292. catch (NetworkException ne)
  293. {
  294. const string message = "Failed searching for the session.";
  295. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  296. messageBox.Accepted += FailedMessageBox;
  297. messageBox.Cancelled += FailedMessageBox;
  298. ScreenManager.AddScreen(messageBox);
  299. System.Console.WriteLine("Failed to search for session: " +
  300. ne.Message);
  301. }
  302. catch (GamerPrivilegeException gpe)
  303. {
  304. const string message =
  305. "You do not have permission to search for a session.";
  306. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  307. messageBox.Accepted += FailedMessageBox;
  308. messageBox.Cancelled += FailedMessageBox;
  309. ScreenManager.AddScreen(messageBox);
  310. System.Console.WriteLine(
  311. "Insufficient privilege to search for session: " + gpe.Message);
  312. }
  313. }
  314. /// <summary>
  315. /// Start creating a session of the given type.
  316. /// </summary>
  317. /// <param name="sessionType">The type of session to create.</param>
  318. void CreateSession(NetworkSessionType sessionType)
  319. {
  320. // create the session
  321. try
  322. {
  323. IAsyncResult asyncResult = NetworkSession.BeginCreate(sessionType, 1,
  324. World.MaximumPlayers, null, null);
  325. // create the busy screen
  326. NetworkBusyScreen busyScreen = new NetworkBusyScreen(
  327. "Creating a session...", asyncResult);
  328. busyScreen.OperationCompleted += SessionCreated;
  329. ScreenManager.AddScreen(busyScreen);
  330. }
  331. catch (NetworkException ne)
  332. {
  333. const string message = "Failed creating the session.";
  334. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  335. messageBox.Accepted += FailedMessageBox;
  336. messageBox.Cancelled += FailedMessageBox;
  337. ScreenManager.AddScreen(messageBox);
  338. System.Console.WriteLine("Failed to create session: " +
  339. ne.Message);
  340. }
  341. catch (GamerPrivilegeException gpe)
  342. {
  343. const string message =
  344. "You do not have permission to create a session.";
  345. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  346. messageBox.Accepted += FailedMessageBox;
  347. messageBox.Cancelled += FailedMessageBox;
  348. ScreenManager.AddScreen(messageBox);
  349. System.Console.WriteLine(
  350. "Insufficient privilege to create session: " + gpe.Message);
  351. }
  352. }
  353. /// <summary>
  354. /// Start searching for a session of the given type.
  355. /// </summary>
  356. /// <param name="sessionType">The type of session to look for.</param>
  357. void FindSession(NetworkSessionType sessionType)
  358. {
  359. // create the new screen
  360. SearchResultsScreen searchResultsScreen =
  361. new SearchResultsScreen(sessionType);
  362. searchResultsScreen.ScreenManager = this.ScreenManager;
  363. ScreenManager.AddScreen(searchResultsScreen);
  364. // start the search
  365. try
  366. {
  367. IAsyncResult asyncResult = NetworkSession.BeginFind(sessionType, 1, null,
  368. null, null);
  369. // create the busy screen
  370. NetworkBusyScreen busyScreen = new NetworkBusyScreen(
  371. "Searching for a session...", asyncResult);
  372. busyScreen.OperationCompleted += searchResultsScreen.SessionsFound;
  373. ScreenManager.AddScreen(busyScreen);
  374. }
  375. catch (NetworkException ne)
  376. {
  377. const string message = "Failed searching for the session.";
  378. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  379. messageBox.Accepted += FailedMessageBox;
  380. messageBox.Cancelled += FailedMessageBox;
  381. ScreenManager.AddScreen(messageBox);
  382. System.Console.WriteLine("Failed to search for session: " +
  383. ne.Message);
  384. }
  385. catch (GamerPrivilegeException gpe)
  386. {
  387. const string message =
  388. "You do not have permission to search for a session.";
  389. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  390. messageBox.Accepted += FailedMessageBox;
  391. messageBox.Cancelled += FailedMessageBox;
  392. ScreenManager.AddScreen(messageBox);
  393. System.Console.WriteLine(
  394. "Insufficient privilege to search for session: " + gpe.Message);
  395. }
  396. }
  397. /// <summary>
  398. /// Callback to receive the network-session search results from quick-match.
  399. /// </summary>
  400. void QuickMatchSearchCompleted(object sender, OperationCompletedEventArgs e)
  401. {
  402. try
  403. {
  404. AvailableNetworkSessionCollection availableSessions =
  405. NetworkSession.EndFind(e.AsyncResult);
  406. if ((availableSessions != null) && (availableSessions.Count > 0))
  407. {
  408. // join the session
  409. try
  410. {
  411. IAsyncResult asyncResult = NetworkSession.BeginJoin(
  412. availableSessions[0], null, null);
  413. // create the busy screen
  414. NetworkBusyScreen busyScreen = new NetworkBusyScreen(
  415. "Joining the session...", asyncResult);
  416. busyScreen.OperationCompleted += QuickMatchSessionJoined;
  417. ScreenManager.AddScreen(busyScreen);
  418. }
  419. catch (NetworkException ne)
  420. {
  421. const string message = "Failed joining the session.";
  422. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  423. messageBox.Accepted += FailedMessageBox;
  424. messageBox.Cancelled += FailedMessageBox;
  425. ScreenManager.AddScreen(messageBox);
  426. System.Console.WriteLine("Failed to join session: " +
  427. ne.Message);
  428. }
  429. catch (GamerPrivilegeException gpe)
  430. {
  431. const string message =
  432. "You do not have permission to join a session.";
  433. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  434. messageBox.Accepted += FailedMessageBox;
  435. messageBox.Cancelled += FailedMessageBox;
  436. ScreenManager.AddScreen(messageBox);
  437. System.Console.WriteLine(
  438. "Insufficient privilege to join session: " + gpe.Message);
  439. }
  440. }
  441. else
  442. {
  443. const string message = "No matches were found.";
  444. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  445. messageBox.Accepted += FailedMessageBox;
  446. messageBox.Cancelled += FailedMessageBox;
  447. ScreenManager.AddScreen(messageBox);
  448. }
  449. }
  450. catch (GamerPrivilegeException gpe){
  451. MessageBoxScreen messageBox = new MessageBoxScreen(gpe.Message);
  452. messageBox.Accepted += FailedMessageBox;
  453. messageBox.Cancelled += FailedMessageBox;
  454. ScreenManager.AddScreen(messageBox);
  455. }
  456. }
  457. /// <summary>
  458. /// Callback when a session is created.
  459. /// </summary>
  460. void SessionCreated(object sender, OperationCompletedEventArgs e)
  461. {
  462. NetworkSession networkSession = null;
  463. try
  464. {
  465. networkSession = NetworkSession.EndCreate(e.AsyncResult);
  466. }
  467. catch (NetworkException ne)
  468. {
  469. const string message = "Failed creating the session.";
  470. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  471. messageBox.Accepted += FailedMessageBox;
  472. messageBox.Cancelled += FailedMessageBox;
  473. ScreenManager.AddScreen(messageBox);
  474. System.Console.WriteLine("Failed to create session: " +
  475. ne.Message);
  476. }
  477. catch (GamerPrivilegeException gpe)
  478. {
  479. const string message =
  480. "You do not have permission to create a session. ";
  481. MessageBoxScreen messageBox = new MessageBoxScreen(message+gpe.Message);
  482. messageBox.Accepted += FailedMessageBox;
  483. messageBox.Cancelled += FailedMessageBox;
  484. ScreenManager.AddScreen(messageBox);
  485. System.Console.WriteLine(
  486. "Insufficient privilege to create session: " + gpe.Message);
  487. }
  488. if (networkSession != null)
  489. {
  490. networkSession.AllowHostMigration = true;
  491. networkSession.AllowJoinInProgress = false;
  492. LoadLobbyScreen(networkSession);
  493. }
  494. }
  495. /// <summary>
  496. /// Callback when a session is quick-matched.
  497. /// </summary>
  498. void QuickMatchSessionJoined(object sender, OperationCompletedEventArgs e)
  499. {
  500. NetworkSession networkSession = null;
  501. try
  502. {
  503. networkSession = NetworkSession.EndJoin(e.AsyncResult);
  504. }
  505. catch (NetworkException ne)
  506. {
  507. const string message = "Failed joining the session.";
  508. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  509. messageBox.Accepted += FailedMessageBox;
  510. messageBox.Cancelled += FailedMessageBox;
  511. ScreenManager.AddScreen(messageBox);
  512. System.Console.WriteLine("Failed to join session: " +
  513. ne.Message);
  514. }
  515. catch (GamerPrivilegeException gpe)
  516. {
  517. const string message =
  518. "You do not have permission to join a session.";
  519. MessageBoxScreen messageBox = new MessageBoxScreen(message);
  520. messageBox.Accepted += FailedMessageBox;
  521. messageBox.Cancelled += FailedMessageBox;
  522. ScreenManager.AddScreen(messageBox);
  523. System.Console.WriteLine(
  524. "Insufficient privilege to join session: " + gpe.Message);
  525. }
  526. if (networkSession != null)
  527. {
  528. LoadLobbyScreen(networkSession);
  529. }
  530. }
  531. /// <summary>
  532. /// Load the lobby screen with the new session.
  533. /// </summary>
  534. void LoadLobbyScreen(NetworkSession networkSession)
  535. {
  536. if (networkSession != null)
  537. {
  538. LobbyScreen lobbyScreen = new LobbyScreen(networkSession);
  539. lobbyScreen.ScreenManager = this.ScreenManager;
  540. ScreenManager.AddScreen(lobbyScreen);
  541. }
  542. }
  543. /// <summary>
  544. /// Finishes the asynchronous process of joining a game from an invitation,
  545. /// joining the lobby of a hosted game if the join was successful.
  546. /// </summary>
  547. void InvitedSessionJoined(object sender, OperationCompletedEventArgs e)
  548. {
  549. NetworkSession networkSession = null;
  550. try
  551. {
  552. networkSession = NetworkSession.EndJoinInvited(e.AsyncResult);
  553. }
  554. catch (NetworkSessionJoinException je)
  555. {
  556. const string message = "Failed joining the session (";
  557. MessageBoxScreen messageBox = new MessageBoxScreen(message + je.JoinError.ToString() + ").");
  558. messageBox.Accepted += FailedMessageBox;
  559. messageBox.Cancelled += FailedMessageBox;
  560. ScreenManager.AddScreen(messageBox);
  561. System.Console.WriteLine("Failed to join session: " +
  562. je.Message);
  563. }
  564. catch (Exception ge)
  565. {
  566. const string message = "Failed joining the session (";
  567. MessageBoxScreen messageBox = new MessageBoxScreen(message + ge.Message + ").");
  568. messageBox.Accepted += FailedMessageBox;
  569. messageBox.Cancelled += FailedMessageBox;
  570. ScreenManager.AddScreen(messageBox);
  571. System.Console.WriteLine("Failed to join session: " +
  572. ge.Message);
  573. }
  574. // Start the lobby if we got the session!
  575. // Otherwise the MainMenuScreen will be available.
  576. if (networkSession != null)
  577. {
  578. LobbyScreen lobbyScreen = new LobbyScreen(networkSession);
  579. lobbyScreen.ScreenManager = ScreenManager;
  580. ScreenManager.AddScreen(lobbyScreen);
  581. }
  582. }
  583. /// <summary>
  584. /// Event handler for when the user selects ok on the network-operation-failed
  585. /// message box.
  586. /// </summary>
  587. void FailedMessageBox(object sender, EventArgs e) { }
  588. #endregion
  589. }
  590. }