private void OnTick(Error error, CommandsBundle payload) { if (m_matchServer.HasError(error)) { Error(error); m_matchServer.Disconnect(); return; } m_cmdQueue.Enqueue(payload); }
/// <summary> /// This method will return command which must be executed. Run it while returned command is not null /// </summary> /// <returns></returns> public CommandsBundle Tick(out long tick) { tick = m_tick; CommandsBundle cmd = null; if (m_commands.Count > 0) { CommandsBundle nextCmd = m_commands.Peek(); if (m_tick > nextCmd.Tick) { cmd = m_commands.Dequeue(); } else { if (m_tick == nextCmd.Tick) { cmd = m_commands.Dequeue(); } if (m_hold == 0) { m_tick++; } else { m_hold--; } } } else { if (m_hold == 0) { m_tick++; } else { m_hold--; } } return(cmd); }
private void FixedUpdate() { if (Time.realtimeSinceStartup < m_nextTickTime) { return; } long tick; CommandsBundle commands = m_cmdQueue.Tick(out tick); if (commands != null) { Error error = new Error(StatusCode.OK); if (commands.Tick < tick) { error.Code = StatusCode.Outdated; } else { m_nextTickTime += GameConstants.MatchEngineTick; OnTick(); } if (ExecuteCommands != null) { ExecuteCommands(error, tick, commands); } if (commands.TasksStateInfo != null && commands.TasksStateInfo.Count > 0) { HandleTaskStateChanged(commands.TasksStateInfo); } if (commands.ClientRequests != null && commands.ClientRequests.Count > 0) { ProcessRequest(commands.ClientRequests); } } else { m_nextTickTime += GameConstants.MatchEngineTick; OnTick(); } }
public void Enqueue(CommandsBundle command) { long maxExpectedSrvTick = m_tick + m_maxPing; if (maxExpectedSrvTick < command.Tick) { Dependencies.Logger.LogWarningFormat("Command arrived too early. Tick {0}, Cmd Tick {1}", m_tick, command.Tick); m_tick = command.Tick - m_maxPing; } else if (command.Tick < m_tick) { Dependencies.Logger.LogWarningFormat("Command arrived too late. Tick {0}, Cmd Tick {1}", m_tick, command.Tick); if (m_hold == 0) { m_hold = m_tick - command.Tick; } } m_commands.Enqueue(command); }
public bool Tick(long tick, out CommandsBundle commands) { for (int i = 0; i < m_players.Length; ++i) { m_pathFinders[i].Tick(); m_taskRunners[i].Tick(); } List <IMatchPlayerController> defeatedPlayers = null; for (int i = 0; i < m_players.Length; ++i) { IMatchPlayerController playerController = m_players[i]; bool wasInRoom = playerController.IsPlayerInRoom; CommandsArray playerCommands; if (playerController.Tick(tick, out playerCommands)) { m_hasNewCommands = true; } if (wasInRoom && !playerController.IsPlayerInRoom) { playerCommands = new CommandsArray(playerCommands); Array.Resize(ref playerCommands.Commands, playerCommands.Commands.Length + 1); playerCommands.Commands[playerCommands.Commands.Length - 1] = new Cmd(CmdCode.LeaveRoom, -1); if (defeatedPlayers == null) { defeatedPlayers = new List <IMatchPlayerController>(); } defeatedPlayers.Add(playerController); } else if (!playerController.HasControllableUnits) { if (defeatedPlayers == null) { defeatedPlayers = new List <IMatchPlayerController>(); } defeatedPlayers.Add(playerController); } m_serverCommands.Commands[i] = playerCommands; } if (defeatedPlayers != null) { for (int i = 0; i < defeatedPlayers.Count; ++i) { IMatchPlayerController defeatedPlayer = defeatedPlayers[i]; defeatedPlayer.DestroyAllUnitsAndAssets(); } } bool wasGameCompleted = m_serverCommands.IsGameCompleted; m_serverCommands.IsGameCompleted = IsCompleted(); if (wasGameCompleted != m_serverCommands.IsGameCompleted) { m_hasNewCommands = true; } if (m_hasNewCommands) { commands = m_serializer.DeepClone(m_serverCommands); if (m_serverCommands.TasksStateInfo.Count > 0) { m_serverCommands.TasksStateInfo.Clear(); } if (m_serverCommands.ClientRequests.Count > 0) { m_serverCommands.ClientRequests.Clear(); } m_hasNewCommands = false; for (int i = 0; i < m_taskEngines.Length; ++i) { m_taskEngines[i].Tick(); } return(true); } commands = null; for (int i = 0; i < m_taskEngines.Length; ++i) { m_taskEngines[i].Tick(); } return(false); }
private void OnEngineCommands(Error error, long clientTick, CommandsBundle commandBundle) { if (m_engine.HasError(error)) { if (error.Code != StatusCode.Outdated) { m_notification.ShowError(error); return; } } long serverTick = commandBundle.Tick; CommandsArray[] playersCommands = commandBundle.Commands; //List<TaskStateInfo> taskStateInfo = commandBundle.TasksStateInfo; bool isGameCompleted = commandBundle.IsGameCompleted; m_minimap.BeginUpdate(); List <IMatchPlayerControllerCli> defeatedPlayers = null; for (int p = 0; p < playersCommands.Length; ++p) { CommandsArray commands = playersCommands[p]; if (commands.Commands == null) { continue; } if (error.Code == StatusCode.Outdated) { Debug.LogWarning("Executing outdated command a little bit faster " + serverTick); } IMatchPlayerControllerCli playerController = m_playerControllers[p]; long lagTicks = clientTick - serverTick; Debug.Assert(lagTicks >= 0); playerController.Execute(commands.Commands, clientTick, lagTicks); PlayerStats stats = m_playerStats[p]; if (stats.IsInRoom && !playerController.IsInRoom) { stats.IsInRoom = false; //Raise player deactivated event; Debug.Log("Player " + m_players[p].Name + " has left the game"); if (defeatedPlayers == null) { defeatedPlayers = new List <IMatchPlayerControllerCli>(); } defeatedPlayers.Add(playerController); } else if (playerController.ControllableUnitsCount == 0) { if (defeatedPlayers == null) { defeatedPlayers = new List <IMatchPlayerControllerCli>(); } defeatedPlayers.Add(playerController); } stats.ControllableUnitsCount = playerController.ControllableUnitsCount; } if (defeatedPlayers != null) { for (int i = 0; i < defeatedPlayers.Count; ++i) { IMatchPlayerControllerCli defeatedPlayer = defeatedPlayers[i]; //#warning Temporary disabled due to strange bugs defeatedPlayer.DestroyAllUnitsAndAssets(); if (PlayerDefeated != null) { PlayerDefeated(defeatedPlayer.Index); } } } if (!m_gSettings.DisableFogOfWar) { m_minimap.EndUpdate(); } IsCompleted = isGameCompleted; }