public static void DisbandGame(string gameId) { if (m_Games.ContainsKey(gameId)) { BesiegedGameInstance removedGame; m_Games.TryRemove(gameId, out removedGame); GenericClientMessage remove = new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.RemoveGame, GameId = removedGame.GameId }; NotifyAllConnectedClients(remove.ToXml()); ConsoleLogger.Push(string.Format("Game disbanded: {0}", removedGame.Name)); removedGame.Dispose(); } }
private void ProcessMessages() { // All generic server messages are handled here m_GenericServerMessageSubscriber = MessageSubject .Where(message => message is GenericServerMessage) .Subscribe(message => { var genericMessage = message as GenericServerMessage; switch (genericMessage.MessageEnum) { case ServerMessage.ServerMessageEnum.StartServer: break; case ServerMessage.ServerMessageEnum.ServerStarted: break; default: ConsoleLogger.Push("Unhandled GenericServerMessage was received: " + genericMessage.MessageEnum.ToString()); break; } }); // All server messages are handled here m_ServerMessageSubscriber = MessageSubject .Where(message => message is ServerMessage && !(message is GenericServerMessage)) .Subscribe(message => { if (message is CreateGameMessage) { //CommandCreateGame commandCreateGame = command as CommandCreateGame; // create the new game instance CreateGameMessage gameMessage = message as CreateGameMessage; string gameId = Guid.NewGuid().ToString(); BesiegedGameInstance gameInstance = new BesiegedGameInstance(gameId, gameMessage.GameName, gameMessage.MaxPlayers, gameMessage.Password, gameMessage.ClientId); m_Games.GetOrAdd(gameId, gameInstance); JoinGameMessage join = new JoinGameMessage() { ClientId = message.ClientId, Password = gameMessage.Password, GameId = gameId }; // add the client that requested the new game to the game instance m_MessageQueue.Add(join); //string capacity = string.Format("{0}/{1} players", gameInstance.Players.Count, gameInstance.MaxPlayers); // notify all connect clients of the updated game instance //GameInfoMessage gameInfo = new GameInfoMessage(gameInstance.GameId, gameInstance.Name, capacity, gameInstance.IsGameInstanceFull, gameInstance.Password != string.Empty ? true : false); ConsoleLogger.Push(string.Format("{0} has created a new game called: {1}", m_ConnectedClients[message.ClientId].Name, gameInstance.Name)); //NotifyAllConnectedClients(gameInfo.ToXml()); } }); // Game messages that are no longer valid are handled here m_BadGameMessageSubscriber = MessageSubject .Where(message => message is GameMessage && !m_Games.ContainsKey(message.GameId)) .Subscribe(message => { GenericClientMessage notFound = new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.GameNotFound }; m_ConnectedClients[message.ClientId].Callback.SendMessage(notFound.ToXml()); }); }
private void ConfigureMachine() { m_GameMachine = new StateMachine<State, Trigger>(() => m_CurrentState, newState => m_CurrentState = newState); ProcessMessages(); #region WaitingForPlayers m_GameMachine.Configure(State.WaitingForPlayers) .Permit(Trigger.AllPlayersReady, State.AllPlayersReady) .OnEntryFrom(Trigger.PlayerNotReady, x => { GenericClientMessage waiting = new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.PlayerNotReady }; LookupPlayerById(m_GameCreatorClientId).Callback.SendMessage(waiting.ToXml()); }) .OnEntryFrom(Trigger.PlayerLeft, x => { SendUpdatedGameInfo(); }) .PermitReentry(Trigger.PlayerLeft) .Ignore(Trigger.PlayerNotReady) .Ignore(Trigger.CreatorPressedStart); #endregion #region AllPlayersReady m_GameMachine.Configure(State.AllPlayersReady) .OnEntry(x => { GenericClientMessage ready = new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.AllPlayersReady }; LookupPlayerById(m_GameCreatorClientId).Callback.SendMessage(ready.ToXml()); }) .Permit(Trigger.PlayerNotReady, State.WaitingForPlayers) .Permit(Trigger.PlayerLeft, State.WaitingForPlayers) .Permit(Trigger.CreatorPressedStart, State.GameStarted); #endregion #region GameStarted m_GameMachine.Configure(State.GameStarted) .OnEntry(x => { List<KeyValuePair<string, Army.ArmyTypeEnum>> PlayerInfos = new List<KeyValuePair<string, Army.ArmyTypeEnum>>(); foreach (Player player in Players) { PlayerInfos.Add(new KeyValuePair<string, Army.ArmyTypeEnum>(player.ClientId, player.ArmyType)); m_PlayerTurnOrder.Enqueue(player.ClientId); } GameState = new GameState(PlayerInfos); pathFinder = new PathFinder(GameState); ConsoleLogger.Push(String.Format("Game {0} has been started", Name)); NotifyAllPlayers(new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.TransitionToLoadingState }.ToXml()); // switch all the players to loading while we send the gamestate ClientGameStateMessage gamestate = new ClientGameStateMessage() { State = GameState }; GenericClientMessage start = new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.StartGame }; AggregateMessage aggregate = new AggregateMessage(); aggregate.MessageList.Add(gamestate); aggregate.MessageList.Add(start); NotifyAllPlayers(aggregate.ToXml()); m_GameMachine.Fire(Trigger.GameStarted); }) .Permit(Trigger.GameStarted, State.PlayerTurn) .Ignore(Trigger.PlayerNotReady); #endregion #region PlayerTurn m_GameMachine.Configure(State.PlayerTurn) .PermitReentry(Trigger.PlayerTurn) .Permit(Trigger.PlayerLeft, State.Reconfigure) .Permit(Trigger.StartBattlePhase, State.BattlePhase) .Permit(Trigger.Cheatcode, State.EndGame) .OnEntry(x => { // notify the current player that its their turn m_CurrentPlayerId = m_PlayerTurnOrder.Dequeue(); LookupPlayerById(m_CurrentPlayerId).Callback.SendMessage((new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.ActiveTurn }).ToXml()); // notify all other players that they have to wait foreach (string playerId in m_PlayerTurnOrder) { LookupPlayerById(playerId).Callback.SendMessage((new WaitingForTurnMessage() { ActivePlayerName = LookupPlayerById(m_CurrentPlayerId).Name }).ToXml()); } // add the current player back on the queue m_PlayerTurnOrder.Enqueue(m_CurrentPlayerId); }); #endregion m_GameMachine.Configure(State.BattlePhase) .OnEntry(x => { }); #region EndGame m_GameMachine.Configure(State.EndGame) .OnEntry(x => { var winner = LookupPlayerById(m_WinnerId); var gameOverMessage = new GameOverMessage() { WinnerId = m_WinnerId, WinnerName = winner.Name }; NotifyAllPlayers(gameOverMessage.ToXml()); }); #endregion #region Reconfigure m_GameMachine.Configure(State.Reconfigure) .OnEntry(x => { // this state allows us to reconfigure the players involved in the game in case someone leaves or is defeated Queue<string> tempPlayers = new Queue<string>(); foreach (string playerId in m_PlayerTurnOrder) { if (Players.FirstOrDefault(p => p.ClientId == playerId) != null) { tempPlayers.Enqueue(playerId); } } if (tempPlayers.Count > 0) { m_PlayerTurnOrder.Clear(); m_PlayerTurnOrder = tempPlayers; m_GameMachine.Fire(Trigger.PlayerTurn); } }) .Permit(Trigger.PlayerTurn, State.PlayerTurn); #endregion }
public void SendMessage(string serializedMessage) { try { BesiegedMessage message = serializedMessage.FromXml<BesiegedMessage>(); if (message is GenericServerMessage && (message as GenericServerMessage).MessageEnum == ServerMessage.ServerMessageEnum.StartServer) { m_ServerCallback = OperationContext.Current.GetCallbackChannel<IClient>(); GenericServerMessage started = new GenericServerMessage() { MessageEnum = ServerMessage.ServerMessageEnum.ServerStarted }; m_ServerCallback.SendMessage(started.ToXml()); m_IsServerInitialized.Value = true; //StartProcessingMessages(); ProcessMessages(); } else if (message is ConnectMessage) { IClient callback = OperationContext.Current.GetCallbackChannel<IClient>(); string clientId = Guid.NewGuid().ToString(); ConnectedClient connectedClient = new ConnectedClient((message as ConnectMessage).Name, clientId, callback); AggregateMessage aggregate = new AggregateMessage(); GenericClientMessage success = new GenericClientMessage() { ClientId = clientId, MessageEnum = ClientMessage.ClientMessageEnum.ConnectSuccessful }; aggregate.MessageList.Add(success); if (m_Games.Count > 0) // notify the client of any pre-existing game instances that they might be able to join { foreach (KeyValuePair<string, BesiegedGameInstance> game in m_Games) { if (!game.Value.IsGameInstanceFull) { string capacity = string.Format("{0}/{1} players", game.Value.Players.Count, game.Value.MaxPlayers); GameInfoMessage gameInfo = new GameInfoMessage(game.Value.GameId, game.Value.Name, capacity, false, game.Value.Password != string.Empty ? true : false); aggregate.MessageList.Add(gameInfo); } } } callback.SendMessage(aggregate.ToXml()); ConsoleLogger.Push(string.Format("{0} has joined the server", connectedClient.Name)); m_ConnectedClients.GetOrAdd(clientId, connectedClient); // Add an entry to the global client hook } else { m_MessageQueue.Add(message); } } catch (Exception ex) { ErrorLogger.Push(ex); } }
public void RemovePlayer(string clientId) { if (clientId == m_GameCreatorClientId) { GenericClientMessage disbanded = new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.GameDisbanded }; NotifyAllPlayers(disbanded.ToXml()); BesiegedServer.DisbandGame(GameId); } else { Player player = Players.FirstOrDefault(x => x.ClientId == clientId); Players.Remove(player); ConsoleLogger.Push(string.Format("{0} with ClientId {1} has left game {2}", player.Name, player.ClientId, Name)); AggregateMessage aggregate = new AggregateMessage(); GenericClientMessage remove = new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.RemovePlayer, ClientId = player.ClientId }; ClientChatMessage chatMessage = new ClientChatMessage() { Contents = string.Format("* {0} has left the game *", player.Name) }; aggregate.MessageList.Add(remove); aggregate.MessageList.Add(chatMessage); NotifyAllPlayers(aggregate.ToXml()); ColorPool.Push(player.PlayerColor); player.Callback.SendMessage((new GenericClientMessage() { MessageEnum = ClientMessage.ClientMessageEnum.TransitionToMultiplayerMenuState }).ToXml()); player = null; m_GameMachine.Fire(Trigger.PlayerLeft); } }