MainMenuScreen.cs 25 KB

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