private void StartGamePacket(DataPacket.FromServer packet) { SceneManager.LoadScene(1); ServerSettings.instance.numberOfClients = packet.numberOfClients; ServerSettings.instance.playerId = packet.playerId; Debug.LogFormat("Client ID: {0}", ServerSettings.instance.playerId); }
//A constant loop that updates the clients on the position of other clients and the host private IEnumerator UpdateClients(float timeBetweenPackets) { while (true) { yield return(new WaitForSeconds(timeBetweenPackets)); SerializableVector[] pos = new SerializableVector[clients.Count + 1]; // bool[] posUpdates = new bool[clients.Count + 1]; //The first position is that of the host pos[0] = hostPlayer.transform.position; posUpdates[0] = true; //Get all the clients latest positions, load them into the packet along with whether that client sent in a position update foreach (var serverClient in clients) { pos[serverClient.clientId] = serverClient.position; posUpdates[serverClient.clientId] = serverClient.positionUpdated; serverClient.positionUpdated = false; } var serverPacket = new DataPacket.FromServer(); serverPacket = DataPacket.GetFromServerPositionPacket(pos, posUpdates, 0); //We don't particularly mind if movement packets occasionally get lost //It'll help with network bandwidth to just send these frequently without care for them BroadcastWithLoss(serverPacket); } }
private void FireGun(float angleToMouse) { int seed = Random.Range(0, 300); if (ServerSettings.instance.playerId != 0) { var packet = new DataPacket.FromClient(); packet = DataPacket.GetFromClientHealthPacket(angleToMouse, seed, bulletSpawnPoint.position, ServerSettings.instance.playerId); StartCoroutine(ClientTCP.instance.SendData(packet)); } else { var packet = new DataPacket.FromServer(); packet = DataPacket.GetFromServerPositionPacket(angleToMouse, seed, bulletSpawnPoint.position, ServerSettings.instance.playerId); StartCoroutine(ServerTCP.instance.Broadcast(packet)); } isShooting = true; KnockBack(); SpawnAndFireBullets(angleToMouse, seed, bulletSpawnPoint.position, ServerSettings.instance.playerId, true); cameraController.MoveBasedOnAngle(angleToMouse); nextFire = fireDelay; storeTime = 0.0f; }
public IEnumerator Broadcast(DataPacket.FromServer packet) { //Cycle through all clients and update them foreach (var client in clients) { bool ready = false; //Check if the socket is ready, if not wait a frame then check again //Consider reducing socket wait time to help frame rate on higher ping while (!ready) { ArrayList listenList = new ArrayList(); listenList.Add(client.tcp.Client); //Second conversion to microseconds int waitTime = (int)ServerSettings.instance.TimeBetweenUpdatesClient * 1000000; Socket.Select(null, listenList, null, waitTime); if (!listenList.Contains(client.tcp.Client)) { yield return(new WaitForEndOfFrame()); } else { ready = true; } } //Change the playerID in the packet to be the client we're sending the packet to packet.playerId = client.clientId; StreamWriter writer = null; NetworkStream tcpStream = client.tcp.GetStream(); while (!tcpStream.CanWrite) { yield return(new WaitForEndOfFrame()); } try { if (tcpStream.CanWrite) { Byte[] msg = Serializer.BinarySerialize(packet); Debug.Log(msg); tcpStream.Write(msg, 0, msg.Length); tcpStream.Flush(); } } catch (Exception e) { Debug.LogError(e); throw; } finally { if (writer != null) { writer.Close(); } } } }
//Used for broadcasting positions, doesn't bother to loop if the socket isn't ready to be written to //Just goes onto the next client //Good for keeping packet usage down public void BroadcastWithLoss(DataPacket.FromServer packet) { foreach (var client in clients) { ArrayList listenList = new ArrayList(); listenList.Add(client.tcp.Client); //Second conversion to microseconds int waitTime = (int)ServerSettings.instance.TimeBetweenUpdatesClient * 1000000; Socket.Select(null, listenList, null, waitTime); if (!listenList.Contains(client.tcp.Client)) { continue; } packet.playerId = client.clientId; StreamWriter writer = null; try { NetworkStream tcpStream = client.tcp.GetStream(); if (tcpStream.CanWrite) { Byte[] msg = Serializer.BinarySerialize(packet); Debug.Log(msg); tcpStream.Write(msg, 0, msg.Length); tcpStream.Flush(); } } catch (Exception e) { Debug.LogError(e); throw; } finally { if (writer != null) { writer.Close(); } } } }
private void Update() { if (!serverStarted) { return; } foreach (var client in clients) { //is the client still connected //if so check for messages if (IsConnected(client.tcp)) { NetworkStream stream = client.tcp.GetStream(); //Is there something to be read? if (stream.DataAvailable && stream.CanRead) { StartCoroutine(OnIncomingData(client)); } } } //Some unity functions can only be called from the main thread, so we'll call them here if (startGame) { //Add one since the houst counts as a client var serverPacket = new DataPacket.FromServer(); serverPacket = DataPacket.GetFromServerStartGamePacket(0, clients.Count + 1); StartCoroutine(Broadcast(serverPacket)); ServerSettings.instance.numberOfClients = clients.Count + 1; ServerSettings.instance.playerId = 0; SceneManager.LoadScene(1); SceneManager.sceneLoaded += OnSceneLoaded; startGame = false; } }
//If we get hit by a shotgun blast, wait a bit and see how many bullets hit us before reporting it private IEnumerator WaitForDamagePacket() { yield return(new WaitForSeconds(ServerSettings.instance.TimeBetweenUpdatesClient)); //If this is on a client, let the server know this enemy has been hit if (ServerSettings.instance.playerId != 0) { //Update the enemy's hp on this client ReceivePacketDamage(damageOverTime, characterNumber, -1); var packet = new DataPacket.FromClient(); packet = DataPacket.GetFromClientHealthPacket(damageOverTime, characterNumber, ServerSettings.instance.playerId); StartCoroutine(ClientTCP.instance.SendData(packet)); } else { //Update the enemy's hp on this client ReceivePacketDamage(damageOverTime, characterNumber, -1); var packet = new DataPacket.FromServer(); packet = DataPacket.GetFromServerHealthPacket(damageOverTime, characterNumber, 0); //Let the clients know the host has hit someone StartCoroutine(ServerTCP.instance.Broadcast(packet)); } damaged = false; }
private IEnumerator OnIncomingData(ServerClient client) { bool ready = false; //Check if the socket's open for reading while (!ready) { ArrayList listenList = new ArrayList(); listenList.Add(client.tcp.Client); //Second conversion to microseconds int waitTime = (int)ServerSettings.instance.TimeBetweenUpdatesClient * 1000000; Socket.Select(listenList, null, null, waitTime); if (!listenList.Contains(client.tcp.Client)) { yield return(new WaitForEndOfFrame()); } else { ready = true; } } //Get the binary data from the stream var stream = client.tcp.GetStream(); while (!stream.CanRead) { yield return(new WaitForEndOfFrame()); } byte[] data = new byte[DataPacket.byteSize]; BinaryReader br = new BinaryReader(stream); br.Read(data, 0, DataPacket.byteSize); try { DataPacket.FromClient packet = (DataPacket.FromClient)Serializer.BinaryDeserialize(data); var serverPacket = new DataPacket.FromServer(); switch (packet.packetType) { case ServerMessages.POSITION: //Don't rebroadcast the position instantly, it can wait since we might get other client updates inbetween DataPacket.RaiseUpdateClientPosition(packet.positionVector, true, packet.playerId); foreach (var serverClient in clients) { if (serverClient.clientId == packet.playerId) { serverClient.position = packet.positionVector; serverClient.positionUpdated = true; } } break; case ServerMessages.FIREGUN: DataPacket.RaiseClientFiredGun(packet.angle, packet.seed, packet.gunPosition, packet.playerId); //Instantly send this packet out as it's important serverPacket = DataPacket.GetFromServerPositionPacket(packet.angle, packet.seed, packet.gunPosition, packet.playerId); StartCoroutine(Broadcast(serverPacket)); break; case ServerMessages.HEALTH: DataPacket.RaiseClientHit(packet.damage, packet.damageId, packet.shooterId); //Instantly send this packet out as it's important serverPacket = DataPacket.GetFromServerHealthPacket(packet.damage, packet.damageId, packet.shooterId); StartCoroutine(Broadcast(serverPacket)); break; default: break; } } catch (Exception e) { Debug.LogWarning(e); } }
private IEnumerator OnIncomingData() { bool ready = false; //Check if the socket is ready, if not wait a frame then check again //Consider reducing socket wait time to help frame rate on higher ping while (!ready) { ArrayList listenList = new ArrayList(); listenList.Add(client.Client); int waitTime = (int)ServerSettings.instance.TimeBetweenUpdatesClient * 1000000; Socket.Select(listenList, null, null, waitTime); if (!listenList.Contains(client.Client)) { yield return(new WaitForEndOfFrame()); } else { ready = true; } } var stream = client.GetStream(); while (!stream.CanRead) { yield return(new WaitForEndOfFrame()); } byte[] data = new byte[DataPacket.byteSize]; //Get the binary data from the network stream BinaryReader br = new BinaryReader(stream); //Read it into data br.Read(data, 0, DataPacket.byteSize); try { var packet = new DataPacket.FromServer(); //Deserialize the binary back into a DataPacket type packet = (DataPacket.FromServer)Serializer.BinaryDeserialize(data); switch (packet.packetType) { case ServerMessages.STARTGAME: StartGamePacket(packet); break; case ServerMessages.POSITION: for (int i = 0; i < ServerSettings.instance.numberOfClients; i++) { DataPacket.RaiseUpdateClientPosition(packet.positionVectors[i], packet.positionUpdates[i], i); } break; case ServerMessages.FIREGUN: DataPacket.RaiseClientFiredGun(packet.angle, packet.seed, packet.gunPosition, packet.shotId); break; case ServerMessages.HEALTH: DataPacket.RaiseClientHit(packet.damage, packet.damageId, packet.shooterId); break; default: break; } } catch (Exception e) { Debug.LogWarning(e); } }