private void ProcessLobbyGamePhaseData(ClientGameSnapshot gameSnapshot) { if (lobbyGamePhase.lobby == null) { return; } if (gameSnapshot.gameStarts && !lobbyGamePhase.IsGameStarting) { lobbyGamePhase.InitiateGameStart(); } if (gameSnapshot.gameStarted && !lobbyGamePhase.IsGameStarted) { List <int> impostorPlayerIds = new List <int>(); bool isPlayingAsImpostor = gameSnapshot.playersInfo[playersManager.controlledClientPlayer.basePlayer.information.id].isImpostor; if (isPlayingAsImpostor) { foreach (SnapshotPlayerInfo snapshotPlayerInfo in gameSnapshot.playersInfo.Values) { if (snapshotPlayerInfo.isImpostor) { impostorPlayerIds.Add(snapshotPlayerInfo.id); } } } lobbyGamePhase.StartGame(isPlayingAsImpostor, gameSnapshot.impostorsAmount, impostorPlayerIds.ToArray()); } }
private void Reconcile(ClientControllablePlayer clientControllablePlayer, ClientGameSnapshot gameSnapshot) { ClientControllable clientControllable = clientControllablePlayer.clientControllable; Vector2 incorrectClientPosition = clientControllable.stateSnapshots[gameSnapshot.yourLastProcessedInputId].position; Vector2 correctServerPosition = gameSnapshot.playersInfo[clientControllablePlayer.basePlayer.information.id].position; Physics2D.simulationMode = SimulationMode2D.Script; // Teleport to server location clientControllablePlayer.basePlayer.movable.Teleport(correctServerPosition); Physics2D.Simulate(Time.fixedDeltaTime); clientControllable.UpdateSnapshotStatePosition(gameSnapshot.yourLastProcessedInputId, clientControllablePlayer.transform.position); // Apply not yet processed by server inputs for (int inputId = gameSnapshot.yourLastProcessedInputId + 1; inputId <= clientControllable.stateSnapshots.Keys.Max(); inputId++) { clientControllablePlayer.basePlayer.movable.MoveByPlayerInput(clientControllable.stateSnapshots[inputId].input); Physics2D.Simulate(Time.fixedDeltaTime); clientControllable.UpdateSnapshotStatePosition(inputId, clientControllablePlayer.transform.position); } Physics2D.simulationMode = SimulationMode2D.FixedUpdate; Logger.LogEvent(LoggerSection.ServerReconciliation, $"Reconciled position with the server position. SnapshotId: {gameSnapshot.id}. YourLastProcessedInputId: {gameSnapshot.yourLastProcessedInputId}. Server position: {correctServerPosition}. Client position: {incorrectClientPosition}."); }
private void UpdateExistentPlayers(ClientGameSnapshot gameSnapshot) { if (!ShouldProcessServerSnapshots()) { return; } foreach (SnapshotPlayerInfo snapshotPlayerInfo in gameSnapshot.playersInfo.Values) { if (!playersManager.players.ContainsKey(snapshotPlayerInfo.id)) { continue; } ClientPlayer clientPlayer = playersManager.players[snapshotPlayerInfo.id]; if (clientPlayer == playersManager.controlledClientPlayer.clientPlayer) { UpdateControlledPlayerWithServerState(gameSnapshot); } else if (gameSnapshot.playersInfo.ContainsKey(clientPlayer.basePlayer.information.id)) { UpdateNotControlledPlayerWithServerState(gameSnapshot.playersInfo[clientPlayer.basePlayer.information.id]); } } }
public void Write(ClientGameSnapshot clientGameSnapshot) { Write(clientGameSnapshot.id); Write(clientGameSnapshot.yourLastProcessedInputId); Write(clientGameSnapshot.playersInfo.Count); foreach (SnapshotPlayerInfo snapshotPlayerInfo in clientGameSnapshot.playersInfo.Values) { Write(snapshotPlayerInfo.id); Write(snapshotPlayerInfo.name); Write(snapshotPlayerInfo.isLobbyHost); Write(snapshotPlayerInfo.input); Write(snapshotPlayerInfo.position); Write(snapshotPlayerInfo.unseen); Write((int)snapshotPlayerInfo.color); Write(snapshotPlayerInfo.isImpostor); } Write(clientGameSnapshot.gameStarts); Write(clientGameSnapshot.gameStarted); Write(clientGameSnapshot.impostorsAmount); Write(clientGameSnapshot.adminPanelPositions.Count); foreach (KeyValuePair <int, int> pair in clientGameSnapshot.adminPanelPositions) { Write(pair.Key); Write(pair.Value); } Write(clientGameSnapshot.securityCamerasEnabled); }
public void ProcessSnapshot(ClientGameSnapshot gameSnapshot) { ProcessPlayersData(gameSnapshot); ProcessLobbyGamePhaseData(gameSnapshot); ProcessPlayGamePhaseData(gameSnapshot); Logger.LogEvent(LoggerSection.GameSnapshots, $"Updated game state with snapshot {gameSnapshot}"); }
private void ProcessGameSnapshotPacket(Packet packet) { Action action = () => { ClientGameSnapshot gameSnapshot = packet.ReadClientGameSnapshot(); gameSnapshots.ProcessSnapshot(gameSnapshot); }; networkSimulation.ReceiveThroughNetwork(action); }
private void RemoveDisconnectedPlayers(ClientGameSnapshot gameSnapshot) { foreach (int playerId in playersManager.players.Keys.ToList()) { if (gameSnapshot.playersInfo.ContainsKey(playerId)) { continue; } playersManager.RemovePlayer(playerId); } }
public void RemoveObsoleteSnapshotStates(ClientGameSnapshot gameSnapshot) { // No snapshots to remove if (stateSnapshots.Count == 0) { return; } for (int inputId = stateSnapshots.Keys.Min(); inputId < gameSnapshot.yourLastProcessedInputId; inputId++) { stateSnapshots.Remove(inputId); } }
public void UpdateControlledPlayerWithServerState(ClientGameSnapshot gameSnapshot) { ClientControllablePlayer controlledClientPlayer = playersManager.controlledClientPlayer; controlledClientPlayer.clientControllable.RemoveObsoleteSnapshotStates(gameSnapshot); if (IsReconciliationNeeded(controlledClientPlayer, gameSnapshot)) { Reconcile(controlledClientPlayer, gameSnapshot); } UpdatePlayerWithServerState(gameSnapshot.playersInfo[controlledClientPlayer.basePlayer.information.id]); }
public void SendGameSnapshotPackets(GameSnapshot gameSnapshot) { const ServerPacketType packetType = ServerPacketType.GameSnapshot; foreach (Client client in playersManager.clients.Values.ToList()) { if (!client.IsFullyInitialized()) { continue; } ClientGameSnapshot clientGameSnapshot = clientGameSnapshotsManager.CreateClientGameSnapshot(client, gameSnapshot); Packet packet = new Packet((int)packetType); packet.Write(clientGameSnapshot); SendUdpPacket(client.playerId, packetType, packet); } }
private void ProcessPlayGamePhaseData(ClientGameSnapshot gameSnapshot) { if (playGamePhase.clientSkeld == null) { return; } if (gameSnapshot.adminPanelPositions.Count != 0) { playGamePhase.UpdateAdminPanelMinimap(gameSnapshot.adminPanelPositions); } SecurityPanel securityPanel = playGamePhase.clientSkeld.securityPanel; if (gameSnapshot.securityCamerasEnabled && !securityPanel.CamerasEnabled) { securityPanel.EnableSecurityCameras(); } else if (!gameSnapshot.securityCamerasEnabled && securityPanel.CamerasEnabled) { securityPanel.DisableSecurityCameras(); } }
private void AddNewlyConnectedPlayers(ClientGameSnapshot gameSnapshot) { if (!mainMenuGamePhase.connectionToServer.IsConnected) { return; } foreach (SnapshotPlayerInfo snapshotPlayerInfo in gameSnapshot.playersInfo.Values) { if (playersManager.players.ContainsKey(snapshotPlayerInfo.id)) { continue; } if (scenesManager.GetActiveScene() == Scene.MainMenu) { mainMenuGamePhase.InitializeLobby(snapshotPlayerInfo.id, snapshotPlayerInfo.name, snapshotPlayerInfo.color, snapshotPlayerInfo.position, snapshotPlayerInfo.isLobbyHost); } else { lobbyGamePhase.AddPlayerToLobby(snapshotPlayerInfo.id, snapshotPlayerInfo.name, snapshotPlayerInfo.color, snapshotPlayerInfo.position, snapshotPlayerInfo.isLobbyHost); } } }
private void ProcessPlayersData(ClientGameSnapshot gameSnapshot) { AddNewlyConnectedPlayers(gameSnapshot); UpdateExistentPlayers(gameSnapshot); RemoveDisconnectedPlayers(gameSnapshot); }
private bool IsReconciliationNeeded(ClientControllablePlayer controlledClientPlayer, ClientGameSnapshot gameSnapshot) { // If player has just spawned, he might not have gameSnapshots with which he may reconcile if (!controlledClientPlayer.clientControllable.stateSnapshots.ContainsKey(gameSnapshot.yourLastProcessedInputId)) { return(false); } const float acceptablePositionError = 0.01f; Vector2 serverPosition = gameSnapshot.playersInfo[controlledClientPlayer.basePlayer.information.id].position; Vector2 clientPosition = controlledClientPlayer.clientControllable.stateSnapshots[gameSnapshot.yourLastProcessedInputId].position; Vector2 positionDifference = serverPosition - clientPosition; return(positionDifference.magnitude > acceptablePositionError); }