Beispiel #1
0
    private void InterpolatePlayerState(bool grabAngles)
    {
        float       f;
        int         i;
        var         gamestate = CDataModel.GameState;
        PlayerState outP      = predictedPlayerState;
        SnapShot    prev      = gamestate.snap;
        SnapShot    next      = gamestate.nextSnap;

        gamestate.snap.playerState.CopyTo(outP);

        var cl = CDataModel.GameState.ClActive;

        if (grabAngles)
        {
            UserCmd cmd;
            int     cmdNum = cl.cmdNum;

            CDataModel.GameState.GetUserCmd(cmdNum, out cmd);

            PMove.UpdateViewAngles(outP, cmd);
        }

        if (gamestate.nextFrameTeleport)
        {
            return;
        }

        if (next == null || next.serverTime <= prev.serverTime)
        {
            return;
        }

        f = (float)(gamestate.time - prev.serverTime) / (next.serverTime - prev.serverTime);
        i = next.playerState.bobCycle;
        if (i < prev.playerState.bobCycle)
        {
            i += 256;
        }
        outP.bobCycle = prev.playerState.bobCycle + (int)(f * (i - prev.playerState.bobCycle));

        for (i = 0; i < 3; i++)
        {
            outP.origin[i] = prev.playerState.origin[i] * (int)(f * (next.playerState.origin[i] - prev.playerState.origin[i]));
            if (!grabAngles)
            {
                outP.viewangles[i] = CUtils.LerpAngles(prev.playerState.viewangles[i], next.playerState.viewangles[i], f);
            }
            outP.velocity[i] = prev.playerState.velocity[i] + f * (next.playerState.velocity[i] - prev.playerState.velocity[i]);
        }
    }
Beispiel #2
0
    private void PredictPlayerState()
    {
        int         cmdNum, current;
        PlayerState oldPlayerState;
        bool        moved;
        UserCmd     oldestCmd;
        UserCmd     latestCmd;

        int stateIndex = 0, predictCmd = 0;
        int numPredicted = 0, numPlayedBack = 0;

        var gamestate = CDataModel.GameState;

        gamestate.hyperspace = false;

        if (!validPPS)
        {
            validPPS             = true;
            predictedPlayerState = gamestate.snap.playerState;
        }

        //如果是播回放,那么就复制移动,不做预测
        if (gamestate.demoPlayback || (gamestate.snap.playerState.pmFlags & PMoveFlags.FOLLOW) != PMoveFlags.NONE)
        {
            InterpolatePlayerState(false);
            return;
        }

        //非预测的本地移动会抓取最近的视角
        if (CConstVar.NoPredict || CConstVar.SynchronousClients)
        {
            InterpolatePlayerState(true);
            return;
        }

        pmove.playerState = predictedPlayerState;
        if (pmove.playerState.pmType == PMoveType.DEAD)
        {
            // pmove.tracemask =
        }
        else
        {
            // pmove.tracemask
        }

        // if(gamestate.snap.playerState.persistant[3] == )

        // pmove.noFootsteps = gamestate.dm

        oldPlayerState = predictedPlayerState;
        current        = CDataModel.GameState.ClActive.cmdNum;

        //如果没有紧接着snapshot之后的comands,就不能精确预测当前的位置,所以就停在最后的正确位置上
        cmdNum = current - CConstVar.CMD_BACKUP + 1;
        CDataModel.GameState.GetUserCmd(cmdNum, out oldestCmd);
        if (oldestCmd.serverTime > gamestate.snap.playerState.commandTime && oldestCmd.serverTime < gamestate.time)
        {
            if (CConstVar.ShowMiss > 0)
            {
                CLog.Info("exceeded Packet_Backup on commands");
            }
            return;
        }

        CDataModel.GameState.GetUserCmd(current, out latestCmd);

        if (gamestate.nextSnap != null && !gamestate.nextFrameTeleport && !gamestate.thisFrameTeleport)
        {
            predictedPlayerState  = gamestate.nextSnap.playerState;
            gamestate.physicsTime = gamestate.nextSnap.serverTime;
        }
        else
        {
            predictedPlayerState  = gamestate.snap.playerState;
            gamestate.physicsTime = gamestate.snap.serverTime;
        }

        if (CConstVar.PMoveMsec < 8)
        {
            CConstVar.PMoveMsec = 8;
        }
        else if (CConstVar.PMoveMsec > 33)
        {
            CConstVar.PMoveMsec = 33;
        }

        pmove.pmoveFixed = CConstVar.PMoveFixed;
        pmove.pmoveMsec  = CConstVar.PMoveMsec;
        pmove.pmoveFloat = CConstVar.PMoveFloat;
        // pmove.pmv

        if (CConstVar.OptimizePrediction)
        {
            if (gamestate.nextFrameTeleport || gamestate.thisFrameTeleport)
            {
                gamestate.lastPredictedCommand = 0;
                gamestate.stateTail            = gamestate.stateHead;
                predictCmd = current - CConstVar.CMD_BACKUP + 1;
            }
            else if (gamestate.time == gamestate.lastServerTime)
            {
                predictCmd = gamestate.lastPredictedCommand + 1;
            }
            else
            {
                bool error = true;
                for (int i = gamestate.stateHead; i != gamestate.stateTail; i = (i + 1) % CConstVar.NUM_SAVED_STATES)
                {
                    if (gamestate.savedPmoveState[i].commandTime == predictedPlayerState.commandTime)
                    {
                        int errorcode = IsUnacceptableError(predictedPlayerState, gamestate.savedPmoveState[i]);

                        if (errorcode > 0)
                        {
                            if (CConstVar.ShowMiss > 0)
                            {
                                CLog.Info("errorcode %d at %d", errorcode, gamestate.time);
                            }
                            break;
                        }

                        pmove.playerState = gamestate.savedPmoveState[i];

                        gamestate.stateHead = (i + 1) % CConstVar.NUM_SAVED_STATES;

                        predictCmd = gamestate.lastPredictedCommand + 1;

                        error = false;
                        break;
                    }
                }

                if (error)
                {
                    gamestate.lastPredictedCommand = 0;
                    gamestate.stateTail            = gamestate.stateHead;
                    predictCmd = current - CConstVar.CMD_BACKUP + 1;
                }
            }

            gamestate.lastServerTime = gamestate.physicsTime;
            stateIndex = gamestate.stateHead;
        }

        moved = false;
        for (cmdNum = current - CConstVar.CMD_BACKUP + 1; cmdNum <= current; cmdNum++)
        {
            CDataModel.GameState.GetUserCmd(current, out pmove.cmd);

            if (pmove.pmoveFixed > 0)
            {
                PMove.UpdateViewAngles(pmove.playerState, pmove.cmd);
            }

            if (pmove.cmd.serverTime <= predictedPlayerState.commandTime)
            {
                continue;
            }
            if (pmove.cmd.serverTime > latestCmd.serverTime)
            {
                continue;
            }

            if (predictedPlayerState.commandTime == oldPlayerState.commandTime)
            {
                Vector3 delta;
                float   len;

                if (gamestate.thisFrameTeleport)
                {
                    gamestate.predictedError = Vector3.zero;
                    if (CConstVar.ShowMiss > 0)
                    {
                        CLog.Info("PredictionTeleport");
                    }
                    gamestate.thisFrameTeleport = false;
                }
                else
                {
                    Vector3 adjusted, new_angles;
                    AdjustPositionForMover(predictedPlayerState.origin, predictedPlayerState.groundEntityNum, gamestate.physicsTime, gamestate.oldTime, out adjusted, predictedPlayerState.viewangles, out new_angles);

                    if (CConstVar.ShowMiss > 0)
                    {
                        if (oldPlayerState.origin != adjusted)
                        {
                            CLog.Info("prediction error");
                        }
                    }

                    delta = oldPlayerState.origin - adjusted;
                    len   = delta.magnitude;
                    if (len > 0.1)
                    {
                        if (CConstVar.ShowMiss > 0)
                        {
                            CLog.Info("Prediction miss: %d", len);
                        }
                        if (CConstVar.ErrorDecay > 0)
                        {
                            int   t = gamestate.time - gamestate.predictedErrorTime;
                            float f = (CConstVar.ErrorDecay - t) / CConstVar.ErrorDecay;
                            if (f < 0f)
                            {
                                f = 0f;
                            }
                            if (f > 0f && CConstVar.ShowMiss > 0)
                            {
                                CLog.Info("Double prediction decay: %d", f);
                            }
                            gamestate.predictedError = gamestate.predictedError * f;
                        }
                        else
                        {
                            gamestate.predictedError = Vector3.zero;
                        }

                        gamestate.predictedError     = delta + gamestate.predictedError;
                        gamestate.predictedErrorTime = gamestate.oldTime;
                    }
                }
            }

            pmove.gauntletHit = false;
            if (pmove.pmoveFixed > 0)
            {
                pmove.cmd.serverTime = ((pmove.cmd.serverTime + CConstVar.PMoveMsec - 1) / CConstVar.PMoveMsec) * CConstVar.PMoveMsec;
            }

            if (CConstVar.OptimizePrediction)
            {
                if (cmdNum >= predictCmd || (stateIndex + 1) % CConstVar.NUM_SAVED_STATES == gamestate.stateHead)
                {
                    pmove.Move();

                    numPredicted++;

                    gamestate.lastPredictedCommand = cmdNum;

                    if ((stateIndex + 1) % CConstVar.NUM_SAVED_STATES != gamestate.stateHead)
                    {
                        gamestate.savedPmoveState[stateIndex] = pmove.playerState;
                        stateIndex          = (stateIndex + 1) % CConstVar.NUM_SAVED_STATES;
                        gamestate.stateTail = stateIndex;
                    }
                }
                else
                {
                    numPlayedBack++;
                    if (CConstVar.ShowMiss > 0 && gamestate.savedPmoveState[stateIndex].commandTime != pmove.cmd.serverTime)
                    {
                        CLog.Info("saved state miss");
                    }

                    pmove.playerState = gamestate.savedPmoveState[stateIndex];
                    stateIndex        = (stateIndex + 1) % CConstVar.NUM_SAVED_STATES;
                }
            }
            else
            {
                pmove.Move();
                numPredicted++;
            }

            moved = true;
        }

        if (CConstVar.ShowMiss > 1)
        {
            CLog.Info("[%d : %d] ", pmove.cmd.serverTime, gamestate.time);
        }
        if (!moved)
        {
            if (CConstVar.ShowMiss > 0)
            {
                CLog.Info("not moved");
            }
            return;
        }
        AdjustPositionForMover(predictedPlayerState.origin, predictedPlayerState.groundEntityNum, gamestate.physicsTime, gamestate.time, out predictedPlayerState.origin, predictedPlayerState.viewangles, out predictedPlayerState.viewangles);
        if (CConstVar.ShowMiss > 0)
        {
            if (predictedPlayerState.eventSequence > oldPlayerState.eventSequence + CConstVar.MAX_PS_EVENTS)
            {
                CLog.Info("dropped event");
            }
        }
    }