//This is where the ticks happen public void Tick() { //If playing back from recorded file, we do not need to do any calculations if (playbackMode) { return; } //Increment the fixed update counter if (isLocalPlayer || isServer) { curTimeDelta += Time.deltaTime; int fixedUpdateC = (int)(curTimeDelta / Time.fixedDeltaTime); currentFixedUpdates += fixedUpdateC; curTimeDelta -= Time.fixedDeltaTime * fixedUpdateC; } int ticksToRun = currentFixedUpdates / _sendUpdates; currentFixedUpdates -= ticksToRun * _sendUpdates; if (isLocalPlayer && isServer && startTick == 0u) { startTick.value = GameManager.tick; } if (isLocalPlayer && startTick != 0u && currentFixedUpdates > 0) { uint cmdTick = (startTick + currentTick); if (GameManager.tick > cmdTick) { windowError = -(int)(GameManager.tick - cmdTick - ticksToRun); } else { windowError = (int)(cmdTick + ticksToRun - GameManager.tick); } if (windowError > GameManager.settings.maxSlidingWindowInaccuracy) { ticksToRun -= GameManager.settings.maxSlidingWindowInaccuracy; currentFixedUpdates -= windowError * _sendUpdates; } else if (windowError < -GameManager.settings.maxSlidingWindowInaccuracy) { ticksToRun += GameManager.settings.maxSlidingWindowInaccuracy; currentFixedUpdates -= windowError * _sendUpdates; } } //Local player, generate all the commands needed for the server and send them out if (isLocalPlayer) { bool sendPacket = true; if (iSend == null) { iSend = new List <Inputs>(); } for (int i = 0; i < ticksToRun; i++) { curInput.timestamp = currentTick++; curInput.servertick = GameManager.tick; iSend.Add(curInput); clientInputs[curInput.timestamp % clientInputs.Length] = curInput; } if (iSend.Count <= 0 || isServer) { sendPacket = false; } if (ticksToRun > 0) { updateCount++; histResults[updateCount % 3] = lastResults; startTime = Mathf.Min(Time.time, Time.fixedTime); } PerformPrediction(); if (tickUpdate != null) { tickUpdate(lastResults, false); } if (tickUpdateNotify != null) { tickUpdateNotify(false); } if (data.debug && tickUpdateDebug != null) { tickUpdateDebug(curInput, lastResults, false); } //Send the inputs if (sendPacket) { SendInputs(ref iSend); } } if (isServer) { //If local player, then we just need to send the last results over, since the prediction is done //otherwise, we check the client if his simulation time is too low, then we can assume the client is timing out //but since we need to simulate it, we have to repeat last commands again if (isLocalPlayer) { sendResults = lastResults; //The dirty bit must be set to invoke serialization SetDirtyBit(1); } else if (GameManager.curtime - commandTime > data.maxLagTime && ticksToRun > 0) { controller.enabled = true; for (int i = 0; i < ticksToRun; i++) { curInput.timestamp++; curInput.servertick++; LagCompensation.StartLagCompensation(GameManager.players[gmIndex], ref curInput); RunCommand(ref lastResults, curInput); sendResults = lastResults; simulationTime = GameManager.curtime; LagCompensation.EndLagCompensation(GameManager.players[gmIndex]); } controller.enabled = false; if (tickUpdate != null) { tickUpdate(lastResults, false); } if (tickUpdateNotify != null) { tickUpdateNotify(false); } if (data.debug && tickUpdateDebug != null) { tickUpdateDebug(curInput, lastResults, false); } SetDirtyBit(1); } } }
void ProcessCommandsServer(ref Inputs[] commands, uint size) { controller.enabled = true; if (startTick == 0u) { startTick.value = GameManager.tick; } for (int i = 0; i < size; i++) { int valid = IsCommandValid(ref commands[i]); //If valid is -1, you are free to ban the player if (valid != 1) { continue; } curInput = commands[i]; LagCompensation.StartLagCompensation(GameManager.players[gmIndex], ref curInput); RunCommand(ref lastResults, curInput); LagCompensation.EndLagCompensation(GameManager.players[gmIndex]); if (data.debug && lastTick + 1 != curInput.timestamp && lastTick != 0) { Debug.Log("Missing tick " + lastTick + 1); } lastTick = curInput.timestamp; simulationTime = GameManager.curtime; commandTime = GameManager.curtime; SetDirtyBit(1); } if (size > 0) { updateCount++; histResults[updateCount % 3] = lastResults; sendResults = lastResults; startTime = Mathf.Min(Time.time, Time.fixedTime); } if (tickUpdate != null) { tickUpdate(lastResults, false); } if (tickUpdateNotify != null) { tickUpdateNotify(false); } if (data.debug && tickUpdateDebug != null) { tickUpdateDebug(curInput, lastResults, false); } controller.enabled = false; }