void AddLagometerSnapshotInfo(snapshot_t snap) { if (snap == null) { // Dropped Client.Instance.lagometer.snapshotSamples[Client.Instance.lagometer.snapshotCount++ & Lagometer.LAGBUFFER-1] = -1; return; } // Add this snapshots info Client.Instance.lagometer.snapshotSamples[Client.Instance.lagometer.snapshotCount & Lagometer.LAGBUFFER - 1] = snap.ping; Client.Instance.lagometer.snapshotFlags[Client.Instance.lagometer.snapshotCount & Lagometer.LAGBUFFER - 1] = snap.snapFlags; Client.Instance.lagometer.snapshotCount++; }
snapshot_t GetSnapshot(int snapshotNumber) { if (snapshotNumber > Client.Instance.cl.snap.messageNum) { Common.Instance.Error("GetSnapshot: snapshotNumber > cl.snap.messageNum"); } // if the frame has fallen out of the circular buffer, we can't return it if (Client.Instance.cl.snap.messageNum - snapshotNumber >= 32) return null; // if the frame is not valid, we can't return it clSnapshot_t clsnap = Client.Instance.cl.snapshots[snapshotNumber & 31]; if (!clsnap.valid) return null; // if the entities in the frame have fallen out of their // circular buffer, we can't return it if (Client.Instance.cl.parseEntitiesNum - clsnap.parseEntitiesNum >= 2048) return null; // write the snapshot snapshot_t snap = new snapshot_t(); snap.snapFlags = clsnap.snapFlags; snap.serverCommandSequence = clsnap.ServerCommandNum; snap.ping = clsnap.ping; snap.serverTime = clsnap.serverTime; snap.areamask = clsnap.areamask; snap.ps = clsnap.ps; int count = clsnap.numEntities; if (count > 256) { Common.Instance.WriteLine("Truncated {0} entitied to 256", clsnap.numEntities); count = 256; } snap.numEntities = count; snap.entities = new Common.entityState_t[count]; for (int i = 0; i < count; i++) { snap.entities[i] = Client.Instance.cl.parseEntities[(clsnap.parseEntitiesNum + i) & 2047]; } return snap; }
/* =================== CG_SetNextSnap A new snapshot has just been read in from the client system. =================== */ void SetNextSnap(snapshot_t snap) { cg.nextSnap = snap; PlayerStateToEntityState(snap.ps, Entities[snap.ps.clientNum].nextState, false); Entities[cg.snap.ps.clientNum].interpolate = true; // check for extrapolation errors for (int i = 0; i < snap.numEntities; i++) { Common.entityState_t es = snap.entities[i]; centity_t cent = Entities[es.number]; cent.nextState = es; // if this frame is a teleport, or the entity wasn't in the // previous frame, don't interpolate if (!cent.currentValid || (((cent.currentState.eFlags ^ es.eFlags) & Common.EntityFlags.EF_TELEPORT_BIT) == Common.EntityFlags.EF_TELEPORT_BIT)) { cent.interpolate = false; } else cent.interpolate = true; } // if the next frame is a teleport for the playerstate, we // can't interpolate during demos if (cg.snap != null && ((snap.ps.eFlags ^ cg.snap.ps.eFlags) & Common.EntityFlags.EF_TELEPORT_BIT) == Common.EntityFlags.EF_TELEPORT_BIT) { cg.nextFrameTeleport = true; } else cg.nextFrameTeleport = false; // if changing follow mode, don't interpolate if (cg.nextSnap.ps.clientNum != cg.snap.ps.clientNum) { cg.nextFrameTeleport = true; } // if changing server restarts, don't interpolate if (((cg.nextSnap.snapFlags ^ cg.snap.snapFlags) & 4) == 4) { cg.nextFrameTeleport = true; } // sort out solid entities BuildSolidList(); }
/* ================== CG_SetInitialSnapshot This will only happen on the very first snapshot, or on tourney restarts. All other times will use CG_TransitionSnapshot instead. FIXME: Also called by map_restart? ================== */ void SetInitialSnapshot(snapshot_t snap) { cg.snap = snap; PlayerStateToEntityState(snap.ps, Entities[snap.ps.clientNum].currentState, false); ExecuteNewServerCommands(snap.serverCommandSequence); for (int i = 0; i < cg.snap.numEntities; i++) { Common.entityState_t state = cg.snap.entities[i]; centity_t cent = Entities[state.number]; cent.currentState = state; cent.interpolate = false; cent.currentValid = true; ResetEntity(cent); // Fix: Check events } if (Net.Instance.ClientStatistic != null) Net.Instance.ClientStatistic.Reset(); }