internal static void ForceClose(Client client, GameDataAction Error) { if (client.RawClient.Connected) { client.Writer.SendAction(Error); } }
private void AddLine(GameDataAction input) { var sb = new StringBuilder(); sb.Append($"{input.Action} : "); foreach (var kvp in input.Data) { sb.Append($"['{kvp.Key}' = {kvp.Value}] "); } AddLine(sb.ToString()); }
private static async void HandleClientComm(object connection) { var tcpClient = (TcpClient) connection; // Create an instance of our custom client handling object var client = new Client(tcpClient); Clients.Add(client); var player = new Player { DataWriter = client.Writer }; client.Player = player; Players.Add(player); if (Players.Count == 1) { // First player setup ServerRandom.Initialise(); } // Initial Handshake as per protocol s2.0 should start with the // protocol version to make sure client and server are compatible client.Writer.SendAction(GameAction.Meta, new Dictionary<string, GameData> {{"protocol", GameActionWriter.PROTOCOL_VERSION.ToString()}}); var phase = ConnectionPhase.Handshake; while (tcpClient.Connected) { var line = await client.Reader.ReadLineAsync(); if (string.IsNullOrEmpty(line)) { // This happens when the client disconnects unexpectedly break; } var input = new GameDataAction(line); Console.WriteLine($"--> Recieved: {input.Action}"); foreach (var kvp in input.Data) { Console.WriteLine($" + '{kvp.Key}' => {kvp.Value}"); } var handled = false; if (input.Action == GameAction.Ping) { // Network Protocol s2.1 if (input.Data["counter"] == (++client.PingCounter)) { client.Writer.SendAction(GameAction.Ping, new Dictionary<string, GameData> {{"counter", (++client.PingCounter)}}); } else { // Use ForceClose here? // Should never occur -- just incase! client.Writer.SendAction(GameAction.Error, new Dictionary<string, GameData> { {"code", ErrorCode.PingMismatch}, { "message", $"Server was Expecting: {client.PingCounter}, Client Sent: {input.Data["counter"]}" } }); } handled = true; } if (input.Action == GameAction.Meta) { switch (phase) { case ConnectionPhase.Handshake: HandleHandshake(client, ref phase, input, ref handled); break; case ConnectionPhase.Setup: handled = HandleSetup(client, ref phase, input, ref handled); break; } if (!handled) { Game.Board.RecieveCommand(player, input); } } } }
private static void HandleHandshake(Client client, ref ConnectionPhase phase, GameDataAction input, ref bool handled) { if (input.Data.ContainsKey("protocol")) { if (input.Data["protocol"] != GameActionWriter.PROTOCOL_VERSION.ToString()) { CloseConnection(client, ErrorCode.VersionMismatch, $"Server version: {GameActionWriter.PROTOCOL_VERSION} - Client Version: {input.Data["protocol"]}"); handled = true; } } if (input.Data.ContainsKey("name")) { client.Player.Name = input.Data["name"]; handled = true; phase = ConnectionPhase.Setup; client.Writer.SendAction(GameAction.Meta, new Dictionary<string, GameData> { {"phase", ConnectionPhase.Setup} }); } }
private static bool HandleSetup(Client client, ref ConnectionPhase phase, GameDataAction input, ref bool handled) { if (input.Data.ContainsKey("deck")) { handled = true; var deckData = input.Data["deck"].String(); var ids = deckData.Split(','); if (ids.Length == Deck.CardLimit) { client.Player.Deck = new Deck(); var usedIDs = new Dictionary<string, int>(); foreach (var id in ids) { int current; if (usedIDs.TryGetValue(id, out current)) { if (current < Deck.CardDuplicateLimit) { usedIDs[id] = current+1; } else { CloseConnection(client, ErrorCode.InvalidDeck, $"More than {Deck.CardDuplicateLimit} of card id '{id}' detected in deck."); } } else { usedIDs.Add(id, 1); } var card = Game.Cards[id].CreateInstance(); //Game.Board.Cards.Add(card.UID, card); client.Player.Deck.PushRandom(card); } client.Writer.SendAction(GameAction.Meta, new Dictionary<string, GameData> { { "deckvalid", 1 } }); client.Player.SetupComplete = true; if (Players.Count == PlayerAmount && Players.All(x => x.SetupComplete)) { Game.StartGame(Players); } } else { CloseConnection(client, ErrorCode.InvalidDeck, $"Invalid amount of cards, deck requires {Deck.CardLimit}. {ids.Length} cards were recieved."); } } return handled; }
public void SendAction(GameDataAction gameDataAction) { SendAction(gameDataAction.Action, gameDataAction.Data); }
/// <summary> /// Handles a GameAction command sent by a player. /// </summary> /// <param name="player">The player that sent the command</param> /// <param name="action">What type of action it is</param> /// <param name="data">The data, such as who to target or the player's name</param> public void RecieveCommand(Player player, GameDataAction dataAction) { // TODO: Finish the command recieved events var data = dataAction.Data; var action = dataAction.Action; if (player == ActivePlayer) { switch (action) { case GameAction.TurnEnd: EndTurn(null); break; case GameAction.PlayCard: Card card; // Attempt to get the card matching the UID if (player.Cards.TryGetValue(data["uid"], out card)) { GameData targetID; if (data.TryGetValue("target", out targetID)) { } card.Play(); } break; case GameAction.GameStart: break; case GameAction.TurnStart: break; case GameAction.DrawCard: break; case GameAction.SetMana: break; case GameAction.SetHealth: break; case GameAction.Attack: break; case GameAction.Trigger: break; case GameAction.Kill: break; case GameAction.MinionSummoned: break; case GameAction.SpellCast: break; case GameAction.GameOver: break; case GameAction.Meta: break; case GameAction.Ping: break; default: throw new ArgumentOutOfRangeException(nameof(action), action, null); } } }
private async void GetData(Client c) { while (c.RawClient.Connected) { var line = await c.Reader.ReadLineAsync(); var input = new GameDataAction(line); AddLine(input); if (input.Action == GameAction.Ping) { if (input.Data["counter"].Int() == (++_pingCounter)) { AddLine("Ping Success."); } else { AddLine("WARNING: Ping Failure!!!!!!"); } } } lbRecieved.Items.Add("Disconnected."); }
private async void GetData(Client c) { while (c.RawClient.Connected) { var line = await c.Reader.ReadLineAsync(); var input = new GameDataAction(line); AddLine(input); if (input.Action == GameAction.Ping) { if (input.Data["counter"].Int() == (++_pingCounter)) { AddLine("Ping Success."); } else { AddLine("WARNING: Ping Failure!!!!!!"); } } else if (input.Action == GameAction.Meta) { if (input.Data.ContainsKey("phase")) { Phase = input.Data["phase"]; switch (Phase) { case ConnectionPhase.Handshake: // This shouldn't occur, is the starting phase. break; case ConnectionPhase.Setup: OnSetupPhase(); break; case ConnectionPhase.Game: OnGamePhase(); break; default: throw new ArgumentOutOfRangeException(); } } } else if (input.Action == GameAction.GameStart) { PlayerID = input.Data["number"]; Players = input.Data["players"]; } else if (input.Action == GameAction.DrawCard) { if (input.Data["player"] == PlayerID) { string cardID = input.Data["card"]; var card = Game.Cards[cardID].CreateInstance(); AddCard($"{cardID}\n{card.Cost}\n{card.Type}"); } } } lbRecieved.Items.Add("Disconnected."); }