Beispiel #1
0
        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);
            }
        }
        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 AddPlayer(ConnectedClient client)
        {
            Player player = new Player(client.Name, client.ClientId, client.Callback, ColorPool.Pop());
            Players.Add(player);
            ConsoleLogger.Push(string.Format("{0} with ClientId {1} has joined game {2}", player.Name, player.ClientId, Name));
            SendUpdatedGameInfo();
            player.IsReady.ValueChanged += (from, to) =>
            {
                PlayerInfoMessage playerInfo = new PlayerInfoMessage()
                {
                    ClientId = player.ClientId,
                    Name = player.Name,
                    Color = player.PlayerColor,
                    IsReady = to
                };

                NotifyAllPlayers(playerInfo.ToXml());

                if (to)
                {
                    CheckIfAllAreReady();
                }
                else
                {
                    m_GameMachine.Fire(Trigger.PlayerNotReady);
                }
            };

            AggregateMessage aggregate = new AggregateMessage();

            PlayerGameInfoMessage playerGameInfo = new PlayerGameInfoMessage()
            {
                GameId = this.GameId,
                IsCreator = (Players.Count == 1) ? true : false
            };

            aggregate.MessageList.Add(playerGameInfo);

            PlayerInfoMessage playerInfoMessage = new PlayerInfoMessage()
            {
                ClientId = player.ClientId,
                Name = player.Name,
                Color = player.PlayerColor,
                IsReady = false
            };

            foreach (Player p in Players)
            {
                if (p.ClientId != player.ClientId)
                {
                    p.Callback.SendMessage(playerInfoMessage.ToXml());
                }
                aggregate.MessageList.Add(new PlayerInfoMessage()
                {
                    ClientId = p.ClientId,
                    Name = p.Name,
                    Color = p.PlayerColor,
                    IsReady = p.IsReady.Value
                });
            }
            player.Callback.SendMessage(aggregate.ToXml());
        }