mirror of
https://github.com/genxium/DelayNoMore
synced 2025-10-09 00:26:39 +00:00
Added network doctor for frontend.
This commit is contained in:
@@ -2,6 +2,7 @@ const i18n = require('LanguageData');
|
||||
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
|
||||
|
||||
const RingBuffer = require('./RingBuffer');
|
||||
const NetworkDoctor = require('./NetworkDoctor');
|
||||
const PriorityQueue = require("./PriorityQueue");
|
||||
|
||||
window.ALL_MAP_STATES = {
|
||||
@@ -96,15 +97,21 @@ cc.Class({
|
||||
type: cc.Integer,
|
||||
default: 4 // implies (renderFrameIdLagTolerance >> inputScaleFrames) count of inputFrameIds
|
||||
},
|
||||
jigglingEps1D: {
|
||||
type: cc.Float,
|
||||
default: 1e-3
|
||||
sendingQLabel: {
|
||||
type: cc.Label,
|
||||
default: null
|
||||
},
|
||||
bulletTriggerEnabled: {
|
||||
default: false
|
||||
inputFrameDownsyncQLabel: {
|
||||
type: cc.Label,
|
||||
default: null
|
||||
},
|
||||
closeOnForcedtoResyncNotSelf: {
|
||||
default: true
|
||||
peerInputFrameUpsyncQLabel: {
|
||||
type: cc.Label,
|
||||
default: null
|
||||
},
|
||||
rollbackFramesLabel: {
|
||||
type: cc.Label,
|
||||
default: null
|
||||
},
|
||||
},
|
||||
|
||||
@@ -184,6 +191,7 @@ cc.Class({
|
||||
// Upon resync, "self.lastUpsyncInputFrameId" might not have been updated properly.
|
||||
batchInputFrameIdSt = self.recentInputCache.StFrameId;
|
||||
}
|
||||
self.networkDoctor.logSending(batchInputFrameIdSt, latestLocalInputFrameId);
|
||||
for (let i = batchInputFrameIdSt; i <= latestLocalInputFrameId; ++i) {
|
||||
const inputFrameDownsync = self.recentInputCache.GetByFrameId(i);
|
||||
if (null == inputFrameDownsync) {
|
||||
@@ -342,6 +350,8 @@ cc.Class({
|
||||
self.othersForcedDownsyncRenderFrameDict = new Map();
|
||||
self.rdfIdToActuallyUsedInput = new Map();
|
||||
|
||||
self.networkDoctor = new NetworkDoctor(20);
|
||||
|
||||
self.countdownNanos = null;
|
||||
if (self.countdownLabel) {
|
||||
self.countdownLabel.string = "";
|
||||
@@ -409,6 +419,7 @@ cc.Class({
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
cc.game.setFrameRate(60);
|
||||
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
|
||||
cc.view.enableAutoFullScreen(true);
|
||||
|
||||
@@ -417,6 +428,7 @@ cc.Class({
|
||||
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
|
||||
|
||||
self.showCriticalCoordinateLabels = false;
|
||||
self.showNetworkDoctorInfo = true;
|
||||
|
||||
console.warn("+++++++ Map onLoad()");
|
||||
|
||||
@@ -796,6 +808,7 @@ cc.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
self.networkDoctor.logInputFrameDownsync(batch[0].inputFrameId, batch[batch.length - 1].inputFrameId);
|
||||
let firstPredictedYetIncorrectInputFrameId = null;
|
||||
for (let k in batch) {
|
||||
const inputFrameDownsync = batch[k];
|
||||
@@ -839,6 +852,7 @@ cc.Class({
|
||||
--------------------------------------------------------
|
||||
*/
|
||||
// The actual rollback-and-chase would later be executed in update(dt).
|
||||
self.networkDoctor.immediateRollbackFrames = (self.renderFrameId - renderFrameId1);
|
||||
console.log(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
|
||||
lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}
|
||||
recentInputCache=${self._stringifyRecentInputCache(false)}
|
||||
@@ -860,6 +874,7 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
||||
return;
|
||||
}
|
||||
|
||||
self.networkDoctor.logPeerInputFrameUpsync(batch[0].inputFrameId, batch[batch.length - 1].inputFrameId);
|
||||
//console.log(`Received peer inputFrameUpsync batch w/ inputFrameId in [${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}] for prediction assistance`);
|
||||
for (let k in batch) {
|
||||
const inputFrameDownsync = batch[k];
|
||||
@@ -1005,6 +1020,9 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
||||
}
|
||||
self.applyRoomDownsyncFrameDynamics(rdf, prevRdf);
|
||||
self.showDebugBoundaries(rdf);
|
||||
if (self.showNetworkDoctorInfo) {
|
||||
self.showNetworkDoctorLabels();
|
||||
}
|
||||
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
|
||||
self.lastRenderFrameIdTriggeredAt = performance.now();
|
||||
let t3 = performance.now();
|
||||
@@ -1499,4 +1517,12 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
showNetworkDoctorLabels() {
|
||||
const self = this;
|
||||
self.sendingQLabel.string = self.networkDoctor.statSending();
|
||||
self.inputFrameDownsyncQLabel.string = self.networkDoctor.statInputFrameDownsync();
|
||||
self.peerInputFrameUpsyncQLabel.string = self.networkDoctor.statPeerInputFrameUpsync();
|
||||
self.rollbackFramesLabel.string = self.networkDoctor.statRollbackFrames();
|
||||
},
|
||||
});
|
||||
|
74
frontend/assets/scripts/NetworkDoctor.js
Normal file
74
frontend/assets/scripts/NetworkDoctor.js
Normal file
@@ -0,0 +1,74 @@
|
||||
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;
|
||||
};
|
||||
|
||||
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.statSending = function() {
|
||||
if (1 >= this.sendingQ.cnt) return `0 fps sending`;
|
||||
const st = this.sendingQ.getByFrameId(this.sendingQ.stFrameId);
|
||||
const ed = this.sendingQ.getByFrameId(this.sendingQ.edFrameId - 1);
|
||||
const elapsedMillis = ed.t - st.t;
|
||||
const fps = Math.round((ed.j - st.i) * 1000 / elapsedMillis);
|
||||
return `${fps} fps sending`;
|
||||
};
|
||||
|
||||
NetworkDoctor.prototype.statInputFrameDownsync = function() {
|
||||
if (1 >= this.inputFrameDownsyncQ.cnt) return `0 fps srv downsync`;
|
||||
const st = this.inputFrameDownsyncQ.getByFrameId(this.inputFrameDownsyncQ.stFrameId);
|
||||
const ed = this.inputFrameDownsyncQ.getByFrameId(this.inputFrameDownsyncQ.edFrameId - 1);
|
||||
const elapsedMillis = ed.t - st.t;
|
||||
const fps = Math.round((ed.j - st.i) * 1000 / elapsedMillis);
|
||||
return `${fps} fps srv downsync`;
|
||||
};
|
||||
|
||||
NetworkDoctor.prototype.statPeerInputFrameUpsync = function() {
|
||||
if (1 >= this.peerInputFrameUpsyncQ.cnt) return `0 fps peer upsync`;
|
||||
const st = this.peerInputFrameUpsyncQ.getByFrameId(this.peerInputFrameUpsyncQ.stFrameId);
|
||||
const ed = this.peerInputFrameUpsyncQ.getByFrameId(this.peerInputFrameUpsyncQ.edFrameId - 1);
|
||||
const elapsedMillis = ed.t - st.t;
|
||||
const fps = Math.round(this.peerInputFrameUpsyncCnt * 1000 / elapsedMillis);
|
||||
return `${fps} fps peer upsync`;
|
||||
};
|
||||
|
||||
NetworkDoctor.prototype.statRollbackFrames = function() {
|
||||
return `${this.immediateRollbackFrames} rollback frames`;
|
||||
};
|
||||
|
||||
module.exports = NetworkDoctor;
|
9
frontend/assets/scripts/NetworkDoctor.js.meta
Normal file
9
frontend/assets/scripts/NetworkDoctor.js.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "affd726a-02f0-4079-aace-39fe525d7478",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
@@ -11,11 +11,13 @@ cc.Class({
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
cc.game.setFrameRate(60);
|
||||
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
|
||||
cc.view.enableAutoFullScreen(true);
|
||||
const self = this;
|
||||
window.mapIns = self;
|
||||
self.showCriticalCoordinateLabels = false;
|
||||
self.showNetworkDoctorInfo = true;
|
||||
|
||||
const mapNode = self.node;
|
||||
const canvasNode = mapNode.parent;
|
||||
|
@@ -13,9 +13,12 @@ var RingBuffer = function(capacity) {
|
||||
};
|
||||
|
||||
RingBuffer.prototype.put = function(item) {
|
||||
let firstPopped = null;
|
||||
while (0 < this.cnt && this.cnt >= this.n) {
|
||||
// Make room for the new element
|
||||
this.pop();
|
||||
const popped = this.pop();
|
||||
if (null == firstPopped)
|
||||
firstPopped = popped;
|
||||
}
|
||||
this.eles[this.ed] = item
|
||||
this.edFrameId++;
|
||||
@@ -24,6 +27,7 @@ RingBuffer.prototype.put = function(item) {
|
||||
if (this.ed >= this.n) {
|
||||
this.ed -= this.n; // Deliberately not using "%" operator for performance concern
|
||||
}
|
||||
return firstPopped;
|
||||
};
|
||||
|
||||
RingBuffer.prototype.pop = function() {
|
||||
|
Reference in New Issue
Block a user