예제 #1
0
        //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);
                }
            }
        }
예제 #2
0
        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;
        }