private void ReadMessages() { NetIncomingMessage inMsg; if ((inMsg = client.ReadMessage()) != null) { #if DEBUG System.Console.WriteLine($"msg: {inMsg.MessageType}"); #endif switch (inMsg.MessageType) { case NetIncomingMessageType.Data: // Handle custom messages Process(inMsg); break; case NetIncomingMessageType.DiscoveryResponse: // Check if server already is found if (gameServers.ContainsKey(inMsg.SenderEndPoint)) { break; } // Parse server status data FoundGame fs = ByteSerializer.ByteArrayToObject <FoundGame>(inMsg.Data); // Add server to list gameServers.Add(inMsg.SenderEndPoint, fs); System.Console.WriteLine($"Discovered server at: {inMsg.SenderEndPoint}"); break; case NetIncomingMessageType.StatusChanged: // handle connection status messages switch (inMsg.SenderConnection.Status) { case NetConnectionStatus.Connected: case NetConnectionStatus.Disconnecting: case NetConnectionStatus.Disconnected: System.Console.WriteLine($"{inMsg.SenderConnection.Status} from {inMsg.SenderConnection.RemoteEndPoint}"); break; } break; case NetIncomingMessageType.DebugMessage: // handle debug messages (only received when compiled in DEBUG mode) System.Console.WriteLine(inMsg.ReadString()); break; } } }
private void Process(NetIncomingMessage inMsg) { // Read packet type PacketType packetType = (PacketType)inMsg.ReadUInt16(); #if DEBUG System.Console.WriteLine("type: " + packetType); #endif switch (packetType) { case PacketType.ClaimSquare: // Parse parameters string playerName = inMsg.ReadString(); Player pl = (from p in players where playerName == p.Name select p).Single(); int x = inMsg.ReadInt32(); int y = inMsg.ReadInt32(); // Claim square grid.ClaimSquare(new Point(x, y), pl); break; case PacketType.EndGame: EndGame(); gameActive = false; break; case PacketType.PlayerConnected: // Add player to players Player newPlayer = ByteSerializer.ByteArrayToObject <Player>(inMsg.ReadBytes(inMsg.Data.Length - 2)); players.Add(newPlayer); break; case PacketType.PlayerDisconnected: // Add player to players Player player = ByteSerializer.ByteArrayToObject <Player>(inMsg.ReadBytes(inMsg.Data.Length - 2)); players.Remove(player); break; case PacketType.NextTurn: string n = inMsg.ReadString(); System.Console.WriteLine($"It is {n}´s turn."); if (localPlayer.Name == n) { Thread t = new Thread(LocalPlayerTurn) { Name = nameof(LocalPlayerTurn) }; t.Start(); } break; case PacketType.FailedClaimSquare: Thread tr = new Thread(LocalPlayerTurn) { Name = nameof(LocalPlayerTurn) }; tr.Start(); break; case PacketType.GridData: grid = ByteSerializer.ByteArrayToObject <Grid>(inMsg.ReadBytes(inMsg.Data.Length - 2)); action += ConfigureCamera; break; case PacketType.StartGame: gameActive = true; break; default: throw new ArgumentOutOfRangeException(nameof(PacketType), "unknown packet type"); } }
void ReadMessage() { NetIncomingMessage inMsg; if ((inMsg = peer.ReadMessage()) != null) { #if DEBUG Console.WriteLine($"msg: {inMsg.MessageType}"); #endif switch (inMsg.MessageType) { case NetIncomingMessageType.Data: // Handle custom messages Process(inMsg); break; case NetIncomingMessageType.DiscoveryResponse: try { // Parse game data FoundGame fg = ByteSerializer.ByteArrayToObject <FoundGame>(inMsg.Data); // skip if game is already discovered / up to date if (DiscoveredHosts.Contains(new KeyValuePair <IPEndPoint, FoundGame>(inMsg.SenderEndPoint, fg))) { break; } // Add server to list DiscoveredHosts.Add(inMsg.SenderEndPoint, fg); Console.WriteLine($"Discovered host at: {inMsg.SenderEndPoint}"); } catch { } break; case NetIncomingMessageType.DiscoveryRequest: if (isHost && !gameActive) { peer.SendDiscoveryResponse(PacketFactory.CreateFoundGameMessage(peer, FoundGame.CreateFromGrid(grid, peer.ConnectionsCount + 1)), inMsg.SenderEndPoint); } break; case NetIncomingMessageType.StatusChanged: // handle connection status messages if (isHost) { switch (inMsg.SenderConnection.Status) { case NetConnectionStatus.Connected: if (isHost) { PlayerConnection np = new PlayerConnection(Player.GetRandomisedPlayer(), inMsg.SenderConnection.RemoteEndPoint); peers.Add(np); players.Add(np.player); } Console.WriteLine($"{inMsg.SenderConnection.RemoteEndPoint} {inMsg.SenderConnection.Status}"); Console.WriteLine($"{peers.Count + 1} players currently connected"); break; case NetConnectionStatus.Disconnected: if (isHost) { PlayerConnection p = (from peer in peers where Equals(inMsg.SenderConnection.RemoteEndPoint, peer.ipEndPoint) select peer).Single(); peers.Remove(p); players.Remove(p.player); } Console.WriteLine($"{inMsg.SenderConnection.RemoteEndPoint} {inMsg.SenderConnection.Status}"); Console.WriteLine($"{peers.Count + 1} players currently connected"); break; } } else { switch (inMsg.SenderConnection.Status) { case NetConnectionStatus.Connected: case NetConnectionStatus.Disconnected: Console.WriteLine($"{inMsg.SenderConnection.RemoteEndPoint} {inMsg.SenderConnection.Status}"); Console.WriteLine($"{peer.Connections.Count + 1} players currently connected"); break; } } break; case NetIncomingMessageType.ConnectionApproval: if (isHost) { if (gameActive) { inMsg.SenderConnection.Deny("Game already started"); break; } // not max players if (grid.maxPlayers >= peer.ConnectionsCount + 1) { inMsg.SenderConnection.Approve(); } else { inMsg.SenderConnection.Deny("Game is full"); } } else { inMsg.SenderConnection.Approve(); // TODO: Validate with gameID } break; case NetIncomingMessageType.DebugMessage: case NetIncomingMessageType.WarningMessage: Console.WriteLine(inMsg.ReadString()); break; default: throw new ArgumentOutOfRangeException(); } peer.Recycle(inMsg); } }
void Process(NetIncomingMessage inMsg) { // Read packet type PacketType packetType = (PacketType)inMsg.ReadUInt16(); #if DEBUG Console.WriteLine("type: " + packetType); #endif switch (packetType) { case PacketType.ClaimSquare: // Parse parameters string playerName = inMsg.ReadString(); Player pl = (from p in players where playerName == p.Name select p).Single(); int x = inMsg.ReadInt32(); int y = inMsg.ReadInt32(); // Claim square grid.ClaimSquare(new Point(x, y), pl); // Start next turn NextTurn(); CheckLocalTurn(); break; case PacketType.PlayerConnected: // connect PlayerConnection newPlayer = ByteSerializer.ByteArrayToObject <PlayerConnection>(inMsg.ReadBytes(inMsg.Data.Length - 2)); peer.Connect(newPlayer.ipEndPoint); break; case PacketType.PlayerDisconnected: // disconnect PlayerConnection player = ByteSerializer.ByteArrayToObject <PlayerConnection>(inMsg.ReadBytes(inMsg.Data.Length - 2)); (from connection in peer.Connections where Equals(connection.RemoteEndPoint, player.ipEndPoint) select connection).Single().Disconnect("BYE"); break; case PacketType.NextTurn: string n = inMsg.ReadString(); Console.WriteLine($"It is {n}´s turn."); if (localPlayer.Name == n) { Thread t = new Thread(LocalPlayerTurn) { Name = nameof(LocalPlayerTurn) }; t.Start(); } break; case PacketType.FailedClaimSquare: Thread tr = new Thread(LocalPlayerTurn) { Name = nameof(LocalPlayerTurn) }; tr.Start(); break; case PacketType.GridData: grid = ByteSerializer.ByteArrayToObject <Grid>(inMsg.ReadBytes(inMsg.Data.Length - 2)); action += confcam; break; case PacketType.Ready: // Set player to ready peers.Find(p => Equals(p.ipEndPoint, inMsg.SenderConnection.RemoteEndPoint)).isReady = true; // Start game if all players are ready if (StartGame()) { Console.WriteLine("Starting game."); } break; case PacketType.PlayerAssignment: // Read data int numberOfBytes = inMsg.ReadInt32(); List <PlayerConnection> newPlayers = ByteSerializer.ByteArrayToObject <List <PlayerConnection> >(inMsg.ReadBytes(numberOfBytes)); Grid newGrid = ByteSerializer.ByteArrayToObject <Grid>(inMsg.ReadBytes(inMsg.Data.Length - inMsg.PositionInBytes)); // Set new grid grid = newGrid; action += confcam; // set players players = new List <Player>(newPlayers.Count); peers = new List <PlayerConnection>(newPlayers.Count - 1); for (int i = 0; i < newPlayers.Count; i++) { try { // Add peers, not self or host //find a corresponding connection (from connection in peer.Connections where Equals(newPlayers[i].ipEndPoint, connection.RemoteEndPoint) select connection).Single(); peers.Add(newPlayers[i]); players.Add(newPlayers[i].player); } catch (Exception e) { // Sync failed, found invalid/no player/connection // Check host if (Equals(newPlayers[i].ipEndPoint, HostIdentIP)) { players.Add(newPlayers[i].player); peers.Add(new PlayerConnection(newPlayers[i].player, peer.Connections[0].RemoteEndPoint)); continue; } // Check self string pip = NetworkHelper.GetPublicIP(); string iip = NetworkHelper.GetLocalIPAddress(); if (Equals(newPlayers[i].ipEndPoint, new IPEndPoint(IPAddress.Parse(pip), peer.Port)) || Equals(newPlayers[i].ipEndPoint, new IPEndPoint(IPAddress.Parse(iip), peer.Port))) { localPlayer = newPlayers[i].player; selfTurnIndex = i; players.Add(newPlayers[i].player); continue; } // Not self either Console.WriteLine(e); throw; } } StartGame(); break; default: throw new ArgumentOutOfRangeException(nameof(PacketType), "unknown packet type"); } }
public void Run() { Running = true; Console.WriteLine("Starting network loop"); while (Running) { server.MessageReceivedEvent.WaitOne(); // Q: should we wait every loop or only the first? NetIncomingMessage inMsg; while ((inMsg = server.ReadMessage()) != null) { Console.WriteLine($"msg {inMsg.MessageType}"); switch (inMsg.MessageType) { case NetIncomingMessageType.Data: Process(inMsg); break; case NetIncomingMessageType.DebugMessage: Console.WriteLine(inMsg.ReadString()); break; case NetIncomingMessageType.StatusChanged: Console.WriteLine(inMsg.SenderConnection.Status); switch (inMsg.SenderConnection.Status) { case NetConnectionStatus.Connected: PlayerConnection c = GetPlayerConnection(inMsg.SenderConnection); Console.WriteLine($"{c.player.Name} has connected from {c.connection.RemoteEndPoint}."); SendGameData(c); // Check if there are enough players to start the game if (clients.Count >= grid.minPlayers) { // TODO: start voting to start game // Start game server.SendToAll(PacketFactory.CreateStartGameMessage(server), NetDeliveryMethod.ReliableOrdered); } break; case NetConnectionStatus.Disconnected: PlayerConnection pc = GetPlayerConnection(inMsg.SenderConnection); Console.WriteLine($"{pc.player.Name} has disconnected."); PlayerDisconnect(pc); break; } break; case NetIncomingMessageType.ConnectionApproval: // Compare existing connections if ((from client in clients where client.connection == inMsg.SenderConnection select client).Count() != 0) { // If there is an existing connection, reject connection string reason = "Connection already exists"; Console.WriteLine($"Player failed to connect: {reason}"); inMsg.SenderConnection.Deny(reason); break; } // Check max players if (clients.Count < grid.maxPlayers == false) { string reason = "Max players reached"; Console.WriteLine($"Player failed to connect: {reason}"); inMsg.SenderConnection.Deny(reason); break; } // Parse player data Player newPlayer = (Player)ByteSerializer.ByteArrayToObject(inMsg.Data); // Compare with existing players // If name or shape and drawingColor already is used if ((from client in clients where string.Equals(newPlayer.Name, client.player.Name, StringComparison.CurrentCultureIgnoreCase) || //TODO: refactor into two where newPlayer.Shape == client.player.Shape && newPlayer.Color == client.player.Color select client).Count() != 0) { // If there is a match, reject connection string reason = "Player already exists"; Console.WriteLine($"Player failed to connect: {reason}"); inMsg.SenderConnection.Deny(reason); break; } // If no match found, accept connection PlayerConnect(new PlayerConnection(inMsg.SenderConnection, (Player)ByteSerializer.ByteArrayToObject(inMsg.Data))); inMsg.SenderConnection.Approve(); // Send game data break; case NetIncomingMessageType.DiscoveryRequest: // TODO: send found server data Console.WriteLine("Discovery Request from Client"); NetOutgoingMessage outMsg = server.CreateMessage(); FoundServer v = new FoundServer(grid.sizeX, grid.sizeY, grid.maxPlayers, grid.minPlayers, clients.Count); outMsg.Write(ByteSerializer.ObjectToByteArray(v)); server.SendDiscoveryResponse(outMsg, inMsg.SenderEndPoint); break; default: Console.WriteLine($"Unhandled message received of type: {inMsg.MessageType}"); break; } server.Recycle(inMsg); } } Running = false; }