| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- //-----------------------------------------------------------------------------
- // SessionBrowserScreen.cs
- //
- // Shows available sessions and allows hosting a new game.
- //-----------------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Net;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Input;
- using GameStateManagement;
- using CardsFramework;
- namespace Blackjack
- {
- class SessionBrowserScreen : MenuScreen
- {
- MenuEntry hostGameMenuEntry;
- MenuEntry refreshMenuEntry;
- MenuEntry backMenuEntry;
- List<MenuEntry> sessionEntries = new List<MenuEntry>();
- List<AvailableNetworkSession> availableSessions = new List<AvailableNetworkSession>();
- TimeSpan timeSinceLastSearch = TimeSpan.Zero;
- const float AutoRefreshInterval = 5.0f; // Auto-refresh every 5 seconds
- bool isSearching = false;
- public SessionBrowserScreen()
- : base(Resources.JoinOrHostGame)
- {
- }
- public override void LoadContent()
- {
- hostGameMenuEntry = new MenuEntry(Resources.HostNewGame);
- refreshMenuEntry = new MenuEntry(Resources.Refresh);
- backMenuEntry = new MenuEntry(Resources.Back);
- hostGameMenuEntry.Selected += HostGameMenuEntrySelected;
- refreshMenuEntry.Selected += RefreshMenuEntrySelected;
- backMenuEntry.Selected += OnCancel;
- MenuEntries.Add(hostGameMenuEntry);
- MenuEntries.Add(refreshMenuEntry);
- MenuEntries.Add(backMenuEntry);
- // Start async session discovery
- BeginFindSessions();
- base.LoadContent();
- }
- void RefreshMenuEntrySelected(object sender, EventArgs e)
- {
- // Manually trigger a refresh
- if (!isSearching)
- {
- BeginFindSessions();
- timeSinceLastSearch = TimeSpan.Zero;
- }
- }
- void HostGameMenuEntrySelected(object sender, EventArgs e)
- {
- // Host a new session and go to lobby
- // Use SystemLink for local network testing (PlayerMatch requires online services)
- var asyncResult = NetworkSession.CreateAsync(
- NetworkSessionType.SystemLink,
- BlackjackConstants.MinPlayers, // local gamers
- BlackjackConstants.MaxPlayers, // max gamers
- 0, // private slots
- null);
- var busyScreen = new NetworkBusyScreen<NetworkSession>(asyncResult);
- busyScreen.OperationCompleted += (s, evt) =>
- {
- var networkSession = evt.Result as NetworkSession;
- if (networkSession != null)
- {
- NetworkSessionComponent.Create(ScreenManager, networkSession);
- ScreenManager.AddScreen(new BlackjackLobbyScreen(networkSession), null);
- }
- else
- {
- ScreenManager.AddScreen(new MessageBoxScreen(Resources.FailedToCreateSession), null);
- }
- };
- ScreenManager.AddScreen(busyScreen, null);
- }
- void JoinSessionMenuEntrySelected(object sender, EventArgs e)
- {
- var entry = sender as AvailableSessionMenuEntry;
- var availableSession = entry?.AvailableSession;
- if (availableSession != null)
- {
- var asyncResult = NetworkSession.JoinAsync(availableSession);
- var busyScreen = new NetworkBusyScreen<NetworkSession>(asyncResult);
- busyScreen.OperationCompleted += (s, evt) =>
- {
- var networkSession = evt.Result as NetworkSession;
- if (networkSession != null)
- {
- NetworkSessionComponent.Create(ScreenManager, networkSession);
- ScreenManager.AddScreen(new BlackjackLobbyScreen(networkSession), null);
- }
- else
- {
- ScreenManager.AddScreen(new MessageBoxScreen(Resources.FailedToJoinSession), null);
- }
- };
- ScreenManager.AddScreen(busyScreen, null);
- }
- }
- void RefreshSessionList()
- {
- // Remove all existing session entries from MenuEntries
- foreach (var entry in sessionEntries)
- {
- MenuEntries.Remove(entry);
- }
- sessionEntries.Clear();
- // Don't add session entries to MenuEntries - we'll draw them separately
- // Just create the entries for the available sessions
- foreach (var session in availableSessions)
- {
- var entry = new AvailableSessionMenuEntry(session);
- entry.Selected += JoinSessionMenuEntrySelected;
- sessionEntries.Add(entry);
- }
- }
- public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
- {
- base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
- // Auto-refresh session list periodically
- if (!isSearching && !coveredByOtherScreen)
- {
- timeSinceLastSearch += gameTime.ElapsedGameTime;
- if (timeSinceLastSearch.TotalSeconds >= AutoRefreshInterval)
- {
- BeginFindSessions();
- timeSinceLastSearch = TimeSpan.Zero;
- }
- }
- // Update refresh button text to show status
- if (refreshMenuEntry != null)
- {
- refreshMenuEntry.Text = isSearching ? Resources.NetworkBusy : Resources.Refresh;
- }
- }
- public override void HandleInput(InputState input)
- {
- // Handle input for session entries (manual click detection)
- // Check if mouse button was clicked (pressed then released)
- if (input.CurrentMouseState.LeftButton == ButtonState.Released &&
- input.LastMouseState.LeftButton == ButtonState.Pressed)
- {
- Vector2 mousePosition = new Vector2(input.CurrentMouseState.X, input.CurrentMouseState.Y);
- SpriteFont font = ScreenManager.Font;
- // Check if clicked on a session entry
- if (availableSessions.Count > 0)
- {
- Vector2 headerPosition = new Vector2(ScreenManager.SafeArea.Left + 100, ScreenManager.SafeArea.Top + 150);
- Vector2 sessionPosition = new Vector2(ScreenManager.SafeArea.Left + 120, headerPosition.Y + font.LineSpacing * 1.5f);
- float scale = 0.85f;
- for (int i = 0; i < sessionEntries.Count; i++)
- {
- var sessionEntry = sessionEntries[i];
- Vector2 textSize = font.MeasureString(sessionEntry.Text) * scale;
- Rectangle hitBox = new Rectangle(
- (int)sessionPosition.X,
- (int)sessionPosition.Y,
- (int)textSize.X,
- (int)(font.LineSpacing * scale)
- );
- if (hitBox.Contains(mousePosition))
- {
- // Clicked on this session - join it
- JoinSessionMenuEntrySelected(sessionEntry, EventArgs.Empty);
- return;
- }
- sessionPosition.Y += font.LineSpacing * scale + 10;
- }
- }
- }
- // Let base class handle button input
- base.HandleInput(input);
- }
- protected override void OnCancel(PlayerIndex playerIndex)
- {
- // Exit all screens and return to main menu (without BackgroundScreen to avoid logo)
- foreach (GameScreen screen in ScreenManager.GetScreens())
- screen.ExitScreen();
- ScreenManager.AddScreen(new BackgroundScreen(), null);
- ScreenManager.AddScreen(new MainMenuScreen(), null);
- }
- public override void Draw(GameTime gameTime)
- {
- // Draw solid background to cover any BackgroundScreen logo
- ScreenManager.GraphicsDevice.Clear(new Color(50, 20, 20)); // Dark red background
- // Draw menu entries (bottom buttons) and title from base class
- base.Draw(gameTime);
- SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
- SpriteFont font = ScreenManager.Font;
- spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
- // Draw "Available Games:" section header and session list
- if (availableSessions.Count > 0)
- {
- // Draw header
- Vector2 headerPosition = new Vector2(ScreenManager.SafeArea.Left + 100, ScreenManager.SafeArea.Top + 150);
- spriteBatch.DrawString(font, Resources.AvailableGames, headerPosition, Color.Yellow, 0f, Vector2.Zero, 0.9f, SpriteEffects.None, 0f);
- // Draw session entries in a vertical list below the header
- Vector2 sessionPosition = new Vector2(ScreenManager.SafeArea.Left + 120, headerPosition.Y + font.LineSpacing * 1.5f);
- for (int i = 0; i < sessionEntries.Count; i++)
- {
- var sessionEntry = sessionEntries[i];
- Color color = Color.White;
- float scale = 0.85f;
- // Draw the session entry text
- string sessionText = sessionEntry.Text;
- spriteBatch.DrawString(font, sessionText, sessionPosition, color, 0f, Vector2.Zero, scale, SpriteEffects.None, 0f);
- // Move down for next entry
- sessionPosition.Y += font.LineSpacing * scale + 10; // Add some padding
- }
- }
- // Draw status at bottom left
- Vector2 statusPosition = new Vector2(ScreenManager.SafeArea.Left + 50, ScreenManager.SafeArea.Bottom - 80);
- var pluralGames = availableSessions.Count == 0 || availableSessions.Count > 1 ? "s" : "";
- string statusText = isSearching
- ? Resources.SearchingForGames
- : string.Format(Resources.FoundGames, availableSessions.Count, pluralGames);
- spriteBatch.DrawString(font, statusText, statusPosition, Color.LightGreen, 0f, Vector2.Zero, 0.8f, SpriteEffects.None, 0f);
- // Show auto-refresh timer
- if (!isSearching)
- {
- int secondsUntilRefresh = (int)(AutoRefreshInterval - timeSinceLastSearch.TotalSeconds);
- string timerText = string.Format(Resources.AutoRefreshIn, secondsUntilRefresh);
- statusPosition.Y += font.LineSpacing;
- spriteBatch.DrawString(font, timerText, statusPosition, Color.Gray, 0f, Vector2.Zero, 0.7f, SpriteEffects.None, 0f);
- }
- spriteBatch.End();
- }
- // Helper class for session info
- // Deprecated: AvailableSession replaced by AvailableNetworkSession
- void BeginFindSessions()
- {
- if (isSearching)
- return; // Already searching
- isSearching = true;
- var asyncResult = NetworkSession.FindAsync(
- NetworkSessionType.SystemLink,
- 1, // local gamers
- null);
- var busyScreen = new NetworkBusyScreen<AvailableNetworkSessionCollection>(asyncResult);
- busyScreen.OperationCompleted += (s, evt) =>
- {
- isSearching = false;
- var foundSessions = evt.Result as AvailableNetworkSessionCollection;
- availableSessions.Clear();
- if (foundSessions != null)
- {
- foreach (var session in foundSessions)
- availableSessions.Add(session);
- }
- RefreshSessionList();
- };
- ScreenManager.AddScreen(busyScreen, null);
- }
- }
- }
|