/// ---------------------------------------------- /// FUNCTION: GameState /// /// DATE: April 2 , 2019 /// /// REVISIONS: /// /// DESIGNER: Cameron Roberts, Kieran Lee /// /// PROGRAMMER: Cameron Roberts, Kieran Lee /// /// INTERFACE: private static void GameState (UDPSocket socket, State state, ServerStateMessageBridge bridge) /// socket: socket to send and receive from /// state: gives access to client manager /// ServerStateMessageBridge: allows packets to be processed properly /// /// RETURNS: void /// /// NOTES: function that server remains while game is in progress /// Expect gameplay packets, discard all else. /// does initial game setup then /// receives and processes packets /// ---------------------------------------------- private static void GameState(UDPSocket socket, State state, ServerStateMessageBridge bridge) { state.GameState.CollisionBuffer.requiredValidity = Math.Max((int)(state.ClientManager.CountCurrConnections * 0.8), 1); Console.WriteLine("set required validity to {0}", state.GameState.CollisionBuffer.requiredValidity); //give each player their starting ability for (int i = 0; i < state.GameState.CreatedPlayersCount; i++) { Player player = (Player)state.GameState.actors [i]; int newSkillId = AbilityEffects.ReturnRandomAbilityId(player); state.GameState.OutgoingReliableElements.Enqueue(new AbilityAssignmentElement(i, newSkillId)); player.AddAbility(1, (AbilityType)newSkillId); } //spawn test tower at 100,100 state.GameState.AddTower(new GameUtility.Coordinate(355, 187)); state.GameState.AddTower(new GameUtility.Coordinate(356, 302)); state.GameState.AddTower(new GameUtility.Coordinate(150, 312)); state.GameState.AddTower(new GameUtility.Coordinate(152, 193)); // Fire Timer.Elapsed event every 1/30th second (sending Game State at 30 fps) StartGameStateTimer(socket, state); //Timer for keeping track of the game progress state.GameState.StartGamePlayTimer(); while (state.TimesEndGameSent < 80) { if (!state.GameOver) { try { Packet packet = socket.Receive(); if (ReliableUDPConnection.GetPacketType(packet) != PacketType.GameplayPacket) { continue; } int actorId = ReliableUDPConnection.GetPlayerID(packet); state.ClientManager.FindClientByActorId(actorId).MarkPacketReceive(); UnpackedPacket unpacked = state.ClientManager.FindClientByActorId(actorId).Connection.ProcessPacket(packet, unpackingArr); ThreadPool.QueueUserWorkItem(ProcessIncomingPacket, unpacked); } catch (Exception e) { Console.WriteLine(e); continue; } } } }
/// ---------------------------------------------- /// FUNCTION: LobbyState /// /// DATE: April 2 , 2019 /// /// REVISIONS: /// /// DESIGNER: Cameron Roberts, Kieran Lee /// /// PROGRAMMER: Cameron Roberts, Kieran Lee, Segal Au /// /// INTERFACE: private static void LobbyState (UDPSocket socket, State state, ServerStateMessageBridge bridge) /// socket: socket to send and receive from /// state: gives access to client manager /// ServerStateMessageBridge: allows packets to be processed properly /// /// RETURNS: void /// /// NOTES: function that server remains in until lobyy is left and game is started. /// Expect request packets and hearbeat packets, discard all else. /// waits until all players are ready, then sends start game message. /// does not move to game state until all clients have started sending game packets /// ---------------------------------------------- private static void LobbyState(UDPSocket socket, State state, ServerStateMessageBridge bridge) { StartHeartBeat(socket, state); while (state.TimesEndGameSent < 80) { Packet packet; try { Console.WriteLine("Waiting for packet in lobby state"); packet = socket.Receive(); } catch (TimeoutException e) { Console.WriteLine("Timeout"); continue; } switch (ReliableUDPConnection.GetPacketType(packet)) { case PacketType.HeartbeatPacket: Console.WriteLine("Got heartbeat packet"); int clientId = ReliableUDPConnection.GetPlayerID(packet); state.ClientManager.Connections [clientId].MarkPacketReceive(); if (state.ClientManager.Connections [clientId] == null) { continue; } UnpackedPacket unpacked = state.ClientManager.Connections [clientId].Connection.ProcessPacket(packet, lobbyUnpackingArr); foreach (var element in unpacked.UnreliableElements) { element.UpdateState(bridge); } foreach (var element in unpacked.ReliableElements) { element.UpdateState(bridge); } break; case PacketType.RequestPacket: Console.WriteLine("Got request packet"); try { string name = ReliableUDPConnection.GetClientNameFromRequestPacket(packet); int newClient = state.ClientManager.AddConnection(socket.LastReceivedFrom, name); socket.Send(ReliableUDPConnection.CreateConfirmationPacket(newClient), state.ClientManager.Connections [newClient].Destination); Console.WriteLine("Sent confirmation packet to client " + newClient + " with name " + state.ClientManager.Connections [newClient].Name); } catch (OutOfMemoryException e) { } break; default: Log.V("Got unexpected packet type, discarding"); break; } Console.WriteLine("Checking if all players ready"); //TODO If all players ready start game send start packet and go to gamestate. Log.V("Checking if all players are ready"); bool allReady = state.ClientManager.CountCurrConnections > 0; for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } PlayerConnection client = state.ClientManager.Connections [i]; Log.V("Client " + i + ", " + client.Ready); allReady &= client.Ready; //bitwise operater to check that every connection is ready } Log.V("Current connections " + state.ClientManager.CountCurrConnections); if (allReady) { Log.D("All are ready sending startgame packet"); List <UpdateElement> unreliableElements = new List <UpdateElement> (); List <UpdateElement> reliableElements = new List <UpdateElement> (); int players = 0; for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } state.ClientManager.Connections [i].ActorId = state.GameState.AddPlayer(state.ClientManager.Connections [i].Team); players++; } reliableElements.Add(new GameStartElement(players)); var playerInfo = new List <LobbyStatusElement.PlayerInfo> (); for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } playerInfo.Add(new LobbyStatusElement.PlayerInfo(state.ClientManager.Connections [i].ClientId, state.ClientManager.Connections [i].Name, state.ClientManager.Connections [i].Team, state.ClientManager.Connections [i].Ready)); } unreliableElements.Add(new LobbyStatusElement(playerInfo)); for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } PlayerConnection client = state.ClientManager.Connections [i]; Packet startPacket = client.Connection.CreatePacket(unreliableElements, reliableElements, PacketType.HeartbeatPacket); socket.Send(startPacket, client.Destination); } //wait for each client to start sending gameplay packets, which indicates //that each client has received the gamestart Message bool allSendGame = false; int playerId; while (!allSendGame) { try{ packet = socket.Receive(); switch (ReliableUDPConnection.GetPacketType(packet)) { case PacketType.GameplayPacket: playerId = ReliableUDPConnection.GetPlayerID(packet); state.ClientManager.FindClientByActorId(playerId).startedGame = true; allSendGame = true; Console.WriteLine("Received packet from {0}", playerId); for (int i = 0; i < state.ClientManager.CountCurrConnections; i++) { if (state.ClientManager.Connections [i] == null) { continue; } PlayerConnection client = state.ClientManager.Connections [i]; Console.WriteLine("Client {0}, {1} sent a game packet while server in lobby", i, client.startedGame); allSendGame &= client.startedGame; //bitwise operater to check that every connection is ready } break; default: break; } } catch (TimeoutException e) { continue; } } sendHeartBeatPing.Enabled = false; GameState(socket, state, bridge); return; } else { Log.V("All players not ready"); } } }