mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-28 04:28:04 +00:00
99 lines
3.8 KiB
JavaScript
99 lines
3.8 KiB
JavaScript
const RingBuffer = require('./RingBuffer');
|
|
|
|
var NetworkDoctor = function(capacity) {
|
|
this.reset(capacity);
|
|
};
|
|
|
|
NetworkDoctor.prototype.reset = function(capacity) {
|
|
this.sendingQ = new RingBuffer(capacity);
|
|
this.inputFrameDownsyncQ = new RingBuffer(capacity);
|
|
this.peerInputFrameUpsyncQ = new RingBuffer(capacity);
|
|
this.peerInputFrameUpsyncCnt = 0;
|
|
this.immediateRollbackFrames = 0;
|
|
this.skippedRenderFrameCnt = 0;
|
|
|
|
this.inputRateThreshold = gopkgs.ConvertToNoDelayInputFrameId(60);
|
|
this.peerUpsyncThreshold = 8;
|
|
this.rollbackFramesThreshold = 8; // Roughly the minimum "TurnAroundFramesToRecover".
|
|
};
|
|
|
|
NetworkDoctor.prototype.logSending = function(stFrameId, edFrameId) {
|
|
this.sendingQ.put({
|
|
i: stFrameId,
|
|
j: edFrameId,
|
|
t: Date.now()
|
|
});
|
|
};
|
|
|
|
NetworkDoctor.prototype.logInputFrameDownsync = function(stFrameId, edFrameId) {
|
|
this.inputFrameDownsyncQ.put({
|
|
i: stFrameId,
|
|
j: edFrameId,
|
|
t: Date.now()
|
|
});
|
|
};
|
|
|
|
NetworkDoctor.prototype.logPeerInputFrameUpsync = function(stFrameId, edFrameId) {
|
|
const firstPopped = this.peerInputFrameUpsyncQ.put({
|
|
i: stFrameId,
|
|
j: edFrameId,
|
|
t: Date.now()
|
|
});
|
|
if (null != firstPopped) {
|
|
this.peerInputFrameUpsyncCnt -= (firstPopped.j - firstPopped.i + 1);
|
|
}
|
|
this.peerInputFrameUpsyncCnt += (edFrameId - stFrameId + 1);
|
|
};
|
|
|
|
NetworkDoctor.prototype.logRollbackFrames = function(x) {
|
|
this.immediateRollbackFrames = x;
|
|
};
|
|
|
|
NetworkDoctor.prototype.stats = function() {
|
|
let sendingFps = 0,
|
|
srvDownsyncFps = 0,
|
|
peerUpsyncFps = 0,
|
|
rollbackFrames = this.immediateRollbackFrames;
|
|
if (1 < this.sendingQ.cnt) {
|
|
const st = this.sendingQ.getByFrameId(this.sendingQ.stFrameId);
|
|
const ed = this.sendingQ.getByFrameId(this.sendingQ.edFrameId - 1);
|
|
const elapsedMillis = ed.t - st.t;
|
|
sendingFps = Math.round((ed.j - st.i) * 1000 / elapsedMillis);
|
|
}
|
|
if (1 < this.inputFrameDownsyncQ.cnt) {
|
|
const st = this.inputFrameDownsyncQ.getByFrameId(this.inputFrameDownsyncQ.stFrameId);
|
|
const ed = this.inputFrameDownsyncQ.getByFrameId(this.inputFrameDownsyncQ.edFrameId - 1);
|
|
const elapsedMillis = ed.t - st.t;
|
|
srvDownsyncFps = Math.round((ed.j - st.i) * 1000 / elapsedMillis);
|
|
}
|
|
if (1 < this.peerInputFrameUpsyncQ.cnt) {
|
|
const st = this.peerInputFrameUpsyncQ.getByFrameId(this.peerInputFrameUpsyncQ.stFrameId);
|
|
const ed = this.peerInputFrameUpsyncQ.getByFrameId(this.peerInputFrameUpsyncQ.edFrameId - 1);
|
|
const elapsedMillis = ed.t - st.t;
|
|
peerUpsyncFps = Math.round(this.peerInputFrameUpsyncCnt * 1000 / elapsedMillis);
|
|
}
|
|
return [sendingFps, srvDownsyncFps, peerUpsyncFps, rollbackFrames, this.skippedRenderFrameCnt];
|
|
};
|
|
|
|
NetworkDoctor.prototype.logSkippedRenderFrameCnt = function() {
|
|
this.skippedRenderFrameCnt += 1;
|
|
}
|
|
|
|
NetworkDoctor.prototype.isTooFast = function() {
|
|
return false;
|
|
const [sendingFps, srvDownsyncFps, peerUpsyncFps, rollbackFrames, skippedRenderFrameCnt] = this.stats();
|
|
if (sendingFps >= this.inputRateThreshold + 2) {
|
|
// Don't send too fast
|
|
return true;
|
|
} else if (sendingFps >= this.inputRateThreshold && srvDownsyncFps >= this.inputRateThreshold) {
|
|
// An outstanding lag within the "inputFrameDownsyncQ" will reduce "srvDownsyncFps", HOWEVER, a constant lag wouldn't impact "srvDownsyncFps"! In native platforms we might use PING value might help as a supplement information to confirm that the "selfPlayer" is not lagged within the time accounted by "inputFrameDownsyncQ".
|
|
if (rollbackFrames >= this.rollbackFramesThreshold) {
|
|
// I got many frames rolled back while none of my peers effectively helped my preciction. Deliberately not using "peerUpsyncThreshold" here because when using UDP p2p upsync broadcasting, we expect to receive effective p2p upsyncs from every other player.
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
module.exports = NetworkDoctor;
|