/// <summary> /// Get the player's opponent /// </summary> /// <param name="player">Backgammon player to be checked</param> /// <returns>null if player is not part of a game session</returns> public NetworkBackgammonPlayer GetOpposingPlayer(NetworkBackgammonPlayer player) { NetworkBackgammonPlayer retval = null; // Get the game session associated with this player NetworkBackgammonGameSession gameSession = GetGameSession(player); if (gameSession != null) { retval = gameSession.GetOpponent(player); } return(retval); }
/// <summary> /// Get the game session the the "player" is currently apart of /// </summary> /// <param name="player">Backgammon player to be checked</param> /// <returns>null if player is not part of a game session</returns> public NetworkBackgammonGameSession GetGameSession(NetworkBackgammonPlayer player) { NetworkBackgammonGameSession retval = null; // Look through the list of game sessions and make sure the player is not already playing in another room foreach (NetworkBackgammonGameSession session in gameSessions) { if (session.ContainsPlayer(player)) { retval = session; break; } } return(retval); }
/// <summary> /// Game session monitor (worker thread) /// </summary> public void GameSessionsMonitorThreadFunc() { NetworkBackgammonEventQueueElement queueElement = null; while (gameSessionsMonitorKeepRunning) { gameSessionsSemaphore.WaitOne(); lock (gameSessionsEventQueue) { if (gameSessionsEventQueue.Count > 0) { queueElement = gameSessionsEventQueue.Dequeue(); } } if (queueElement != null) { if (queueElement.Notifier is NetworkBackgammonGameSession && queueElement.Event is NetworkBackgammonGameSessionEvent) { NetworkBackgammonGameSession gameSession = (NetworkBackgammonGameSession)queueElement.Notifier; NetworkBackgammonGameSessionEvent gameSessionEvent = (NetworkBackgammonGameSessionEvent)queueElement.Event; if (gameSessionEvent.EventType == NetworkBackgammonGameSessionEvent.GameSessionEventType.GameFinished) { // Broadcast the game active event to all registered listeners Broadcast(new NetworkBackgammonGameRoomEvent(NetworkBackgammonGameRoomEvent.GameRoomEventType.PlayerFinished)); gameSession.Stop(); gameSessions.Remove(gameSession); gameSession = null; GC.Collect(); } } } queueElement = null; } }
/// <summary> /// Exit the game room by player /// </summary> /// <param name="_player">Backgammon player who wants to leave the game room</param> public void Leave(NetworkBackgammonPlayer _player) { if (connectedPlayers.Contains(_player)) { // The disconnected player should no longer be listening... RemoveListener(_player); // Stop listening to this player _player.RemoveListener(this); // Check if player is associated with a game room and remove if necessary NetworkBackgammonGameSession _playerGameSession = GetGameSession(_player); if (_playerGameSession != null) { // Disconnect the player from the game session _player.RemoveListener(_playerGameSession); // Disconnect the game session from the player _playerGameSession.RemoveListener(_player); // Get the opposing player NetworkBackgammonPlayer opposingPlayer = _playerGameSession.GetOpponent(_player); if (opposingPlayer != null) { // Disconnect the player from the game session opposingPlayer.RemoveListener(_playerGameSession); // Disconnect the game session from the player _playerGameSession.RemoveListener(opposingPlayer); } // Halt the game sesssion _playerGameSession.Stop(); } // Remove player from connected player list connectedPlayers.Remove(_player); // Broadcast the player disconnected event to all registered listeners Broadcast(new NetworkBackgammonGameRoomEvent(NetworkBackgammonGameRoomEvent.GameRoomEventType.PlayerDisconnected)); } }
public void OnEventNotification(INetworkBackgammonNotifier sender, INetworkBackgammonEvent e) { if (sender is NetworkBackgammonPlayer) { NetworkBackgammonPlayer player = (NetworkBackgammonPlayer)sender; if (e is NetworkBackgammonChallengeResponseEvent) { NetworkBackgammonChallengeResponseEvent challengeResponseEvent = (NetworkBackgammonChallengeResponseEvent)e; if (challengeSyncList.Keys.Contains(player)) { if (challengeSyncList[player] != null) { challengeSyncList[player].ChallengeAccepted = challengeResponseEvent.ChallengeAccepted; try { challengeSyncList[player].ChallengeSemaphore.Release(); } catch (SemaphoreFullException ex) { // TODO: If this exception occurs calling Release too many times... } } } } else if (e is NetworkBackgammonChatEvent) { // Pass the message through to the listeners Broadcast((NetworkBackgammonChatEvent)e); } } else if (sender is NetworkBackgammonGameSession) { NetworkBackgammonGameSession gameSession = (NetworkBackgammonGameSession)sender; if (e is NetworkBackgammonGameSessionEvent) { NetworkBackgammonGameSessionEvent gameSessionEvent = (NetworkBackgammonGameSessionEvent)e; if (gameSessionEvent.EventType == NetworkBackgammonGameSessionEvent.GameSessionEventType.GameFinished) { bool newQueueItemAdd = true; NetworkBackgammonEventQueueElement newQueueItem = new NetworkBackgammonEventQueueElement(e, sender); lock (newQueueItem) { /* * if (gameSessionsEventQueue.Count > 0) * { * NetworkBackgammonEventQueueElement lastQueueItem = gameSessionsEventQueue.Last(); * // Avoid adding the same event (from the same sender) twice * // Reason: Game Room listens to events from all players, i.e. also * // both players that are in one Game Session. Thus, all events broadcasted * // by the Game Session arrive here (at the Game Room) twice * if (gameSessionsEventQueue.Last().Notifier == sender && * gameSessionsEventQueue.Last().Event == e) * { * newQueueItemAdd = false; * } * } */ if (newQueueItemAdd) { gameSessionsEventQueue.Enqueue(new NetworkBackgammonEventQueueElement(e, sender)); gameSessionsSemaphore.Release(); } } } } } }
/// <summary> /// Challenge an opponent to a game /// </summary> /// <param name="_challengingPlayer">Challenging backgammon player</param> /// <param name="_challengedPlayer">Challenged backgammon player</param> /// <returns></returns> public bool Challenge(string _challengingPlayerName, string _challengedPlayerName) { bool retval = false; NetworkBackgammonPlayer _challengingPlayer = GetPlayerByName(_challengingPlayerName); NetworkBackgammonPlayer _challengedPlayer = GetPlayerByName(_challengedPlayerName); // Check if the players are in the available player game room list //if (connectedPlayers.Contains(_challengingPlayer) && connectedPlayers.Contains(_challengedPlayer)) if (_challengingPlayer != null && _challengedPlayer != null) { // Check if players are currently free to participate in a game session if (!IsPlayerInGameSession(_challengingPlayer) && !IsPlayerInGameSession(_challengedPlayer)) { Semaphore challengeSemaphore = new Semaphore(0, 1); // Add game challenge data container instance to be used for the (asynchronous) challenge procedure challengeSyncList.Add(_challengedPlayer, new NetworkBackgammonChallengeDataContainer(challengeSemaphore)); // Broadcast the player challenge event Broadcast(new NetworkBackgammonChallengeEvent(_challengingPlayerName, _challengedPlayerName)); // Wait for response from challenged player (or timeout) if (challengeSemaphore.WaitOne(challengeRequestTimeoutMs)) { retval = challengeSyncList[_challengedPlayer].ChallengeAccepted; // Create and start game session if challenge has been accepted by challenged player if (retval) { // Create game session monitor if it doesn't exist yet StartGameSessionMonitor(); // Create game session instance NetworkBackgammonGameSession gameSession = new NetworkBackgammonGameSession(_challengingPlayer, _challengedPlayer); // Append to list of game sessions... gameSessions.Add(gameSession); // Start the game... gameSession.Start(); // Broadcast the game active event to all registered listeners Broadcast(new NetworkBackgammonGameRoomEvent(NetworkBackgammonGameRoomEvent.GameRoomEventType.PlayerPlaying)); } challengeSyncList.Remove(_challengedPlayer); // Give the challenging player the challenge response Broadcast(new NetworkBackgammonChallengeResponseEvent(retval, _challengedPlayerName, _challengingPlayerName)); } else { challengeSyncList.Remove(_challengedPlayer); retval = false; } } } return(retval); }
public void OnEventNotification(INetworkBackgammonNotifier sender, INetworkBackgammonEvent e) { if (InvokeRequired) { Invoke(new NotifyDelegate(OnEventNotification), new object[] { sender, e }); } else { buttonAction.Enabled = false; buttonAction.Text = "[No Action]"; #region Sender: Game Room if (sender is NetworkBackgammonRemoteGameRoom) { try { if (e is NetworkBackgammonGameRoomEvent) { NetworkBackgammonGameRoomEvent gameRoomEvent = (NetworkBackgammonGameRoomEvent)e; switch (gameRoomEvent.EventType) { case NetworkBackgammonGameRoomEvent.GameRoomEventType.PlayerConnected: UpdateConnectedPlayersList(); break; case NetworkBackgammonGameRoomEvent.GameRoomEventType.PlayerDisconnected: UpdateConnectedPlayersList(); break; } } else if (e is NetworkBackgammonChallengeEvent) { NetworkBackgammonChallengeEvent challengeEvent = (NetworkBackgammonChallengeEvent)e; string challengingPlayer = challengeEvent.ChallengingPlayer; string challengedPlayer = challengeEvent.ChallengedPlayer; if (challengingPlayer.CompareTo(player.PlayerName) != 0 && challengedPlayer.CompareTo(player.PlayerName) == 0) { bool challengeResponse = MessageBox.Show( "Accept game challenge from " + challengeEvent.ChallengingPlayer + "?", "Game Challenge", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes; player.RespondToChallenge(challengeResponse, challengeEvent.ChallengingPlayer); groupBoxGameControls.Enabled = challengeResponse; } } } catch (Exception ex) { listBoxLog.Items.Add(ex.Message); } } #endregion #region Sender: Game Session else if (sender is NetworkBackgammonGameSession) { // Filter out broadcasts from our own player if (sender != player) { try { NetworkBackgammonGameSession gameSession = (NetworkBackgammonGameSession)sender; if (e is NetworkBackgammonGameSessionEvent) { // Generate warning if last event has been overwritten // (Currently every event received is supposed to be responded too by means of an // action (e.g. move, dice roll acknowledge, etc), which resets the last event type to invalid) if (lastGameSessionEventType != null) { listBoxLog.Items.Add("Warning: Overwriting last event (" + lastGameSessionEventType.ToString() + ") with new event " + e.GetType().ToString() + " (i.e. last event hasn't been responded to by means of an action)"); } // Latch the event type lastGameSessionEventType = e.GetType(); } #region Actions for initial dice roll if (e is GameSessionInitialDiceRollEvent) { listBoxCheckers.Items.Clear(); listBoxMoves.Items.Clear(); GameSessionInitialDiceRollEvent gameSessionInitialDiceRollEvent = (GameSessionInitialDiceRollEvent)e; // if (player.InitialDice != null) if (gameSessionInitialDiceRollEvent.GetDiceForPlayer(player.PlayerName) != null) { listBoxLog.Items.Add("Initial dice rolled: " + gameSessionInitialDiceRollEvent.GetDiceForPlayer(player.PlayerName).CurrentValue); buttonAction.Enabled = true; buttonAction.Text = "Confirm initial dice roll"; } else { listBoxLog.Items.Add("Warning: Event received is " + e.GetType().ToString() + " but dice values are missing"); } } #endregion #region Actions for checker update else if (e is GameSessionCheckerUpdatedEvent) { listBoxCheckers.Items.Clear(); listBoxMoves.Items.Clear(); GameSessionCheckerUpdatedEvent gameSessionCheckerUpdateEvent = (GameSessionCheckerUpdatedEvent)e; player = gameSessionCheckerUpdateEvent.GetPlayerByName(player.PlayerName); string strDice = ""; foreach (NetworkBackgammonDice d in gameSessionCheckerUpdateEvent.DiceRolled) { strDice += " " + d.CurrentValue; } listBoxLog.Items.Add("Dice: " + strDice); foreach (NetworkBackgammonChecker checker in player.Checkers) { listBoxCheckers.Items.Add(checker); } } #endregion #region Actions for move expected else if (e is GameSessionMoveExpectedEvent) { GameSessionMoveExpectedEvent gameSessionMoveExpectedEvent = (GameSessionMoveExpectedEvent)e; if (player.PlayerName == gameSessionMoveExpectedEvent.ActivePlayer) { listBoxLog.Items.Add("I'm the active player, expected to make the next move ..."); groupBoxGameControls.BackColor = Color.DarkGreen; buttonAction.Enabled = true; buttonAction.Text = "Make Move"; } else { groupBoxGameControls.BackColor = Color.DarkRed; } } #endregion #region Actions for no (valid) move else if (e is GameSessionNoPossibleMovesEvent) { GameSessionNoPossibleMovesEvent gameSessionNoPossibleMovesEvent = (GameSessionNoPossibleMovesEvent)e; if (player.PlayerName == gameSessionNoPossibleMovesEvent.PlayerName) { listBoxLog.Items.Add("I'm the active player, but have no (valid) moves ..."); groupBoxGameControls.BackColor = Color.DarkGreen; buttonAction.Enabled = true; buttonAction.Text = "Confirm"; } else { groupBoxGameControls.BackColor = Color.DarkRed; } } #endregion #region Actions for player resignation else if (e is GameSessionPlayerResignationEvent) { listBoxCheckers.Items.Clear(); listBoxMoves.Items.Clear(); GameSessionPlayerResignationEvent gameSessionPlayerResignationEvent = (GameSessionPlayerResignationEvent)e; listBoxLog.Items.Add("Player " + gameSessionPlayerResignationEvent.ResigningPlayer + " has resigned from current game"); listBoxCheckers.Items.Clear(); groupBoxGameControls.BackColor = SystemColors.Control; groupBoxGameControls.Enabled = false; } #endregion #region Actions for player won game else if (e is GameSessionPlayerWonEvent) { listBoxCheckers.Items.Clear(); listBoxMoves.Items.Clear(); GameSessionPlayerWonEvent gameSessionPlayerWonEvent = (GameSessionPlayerWonEvent)e; if (gameSessionPlayerWonEvent.WinningPlayer == player.PlayerName) { listBoxLog.Items.Add("Yeah!!! I won the game!!!"); } else { listBoxLog.Items.Add("Player " + gameSessionPlayerWonEvent.WinningPlayer + " won the game"); } listBoxCheckers.Items.Clear(); groupBoxGameControls.BackColor = SystemColors.Control; groupBoxGameControls.Enabled = false; } #endregion else if (e is NetworkBackgammonGameSessionEvent) { listBoxCheckers.Items.Clear(); listBoxMoves.Items.Clear(); NetworkBackgammonGameSessionEvent gameSessionEvent = (NetworkBackgammonGameSessionEvent)e; switch (gameSessionEvent.EventType) { case NetworkBackgammonGameSessionEvent.GameSessionEventType.GameFinished: { listBoxLog.Items.Add("Game finished"); } break; } } } catch (Exception ex) { listBoxLog.Items.Add(ex.Message); } } } #endregion } }