mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 11:48:56 +00:00
Minor update.
This commit is contained in:
parent
d37ebd4c33
commit
5cfcac6cf6
@ -894,8 +894,12 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self._markConfirmationIfApplicable();
|
self._markConfirmationIfApplicable();
|
||||||
|
self._handleIncorrectlyRenderedPrediction(firstPredictedYetIncorrectInputFrameId, batch, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleIncorrectlyRenderedPrediction(firstPredictedYetIncorrectInputFrameId, batch, fromUDP) {
|
||||||
if (null == firstPredictedYetIncorrectInputFrameId) return;
|
if (null == firstPredictedYetIncorrectInputFrameId) return;
|
||||||
|
const self = this;
|
||||||
const renderFrameId1 = gopkgs.ConvertToFirstUsedRenderFrameId(firstPredictedYetIncorrectInputFrameId) - 1;
|
const renderFrameId1 = gopkgs.ConvertToFirstUsedRenderFrameId(firstPredictedYetIncorrectInputFrameId) - 1;
|
||||||
if (renderFrameId1 >= self.chaserRenderFrameId) return;
|
if (renderFrameId1 >= self.chaserRenderFrameId) return;
|
||||||
|
|
||||||
@ -911,12 +915,17 @@ cc.Class({
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
// The actual rollback-and-chase would later be executed in update(dt).
|
// The actual rollback-and-chase would later be executed in update(dt).
|
||||||
console.log(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
|
console.log(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by
|
||||||
|
firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
|
||||||
lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}
|
lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}
|
||||||
recentInputCache=${self._stringifyRecentInputCache(false)}
|
recentInputCache=${self._stringifyRecentInputCache(false)}
|
||||||
batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}]`);
|
batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}]
|
||||||
|
fromUDP=${fromUDP}`);
|
||||||
self.chaserRenderFrameId = renderFrameId1;
|
self.chaserRenderFrameId = renderFrameId1;
|
||||||
self.networkDoctor.logRollbackFrames(self.renderFrameId - self.chaserRenderFrameId);
|
let rollbackFrames = (self.renderFrameId - self.chaserRenderFrameId);
|
||||||
|
if (0 > rollbackFrames)
|
||||||
|
rollbackFrames = 0;
|
||||||
|
self.networkDoctor.logRollbackFrames(rollbackFrames);
|
||||||
},
|
},
|
||||||
|
|
||||||
onPeerInputFrameUpsync(peerJoinIndex, batch, fromUDP) {
|
onPeerInputFrameUpsync(peerJoinIndex, batch, fromUDP) {
|
||||||
@ -935,12 +944,24 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
|
|
||||||
let effCnt = 0;
|
let effCnt = 0;
|
||||||
//console.log(`Received peer inputFrameUpsync batch w/ inputFrameId in [${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}] for prediction assistance`);
|
//console.log(`Received peer inputFrameUpsync batch w/ inputFrameId in [${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}] for prediction assistance`);
|
||||||
|
let firstPredictedYetIncorrectInputFrameId = null;
|
||||||
const renderedInputFrameIdUpper = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId);
|
const renderedInputFrameIdUpper = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId);
|
||||||
for (let k in batch) {
|
for (let k in batch) {
|
||||||
const inputFrame = batch[k]; // could be either "pb.InputFrameDownsync" or "pb.InputFrameUpsync", depending on "fromUDP"
|
const inputFrame = batch[k]; // could be either "pb.InputFrameDownsync" or "pb.InputFrameUpsync", depending on "fromUDP"
|
||||||
const inputFrameId = inputFrame.inputFrameId;
|
const inputFrameId = inputFrame.inputFrameId;
|
||||||
|
const peerEncodedInput = (true == fromUDP ? inputFrame.encoded : inputFrame.inputList[peerJoinIndex - 1]);
|
||||||
if (inputFrameId <= renderedInputFrameIdUpper) {
|
if (inputFrameId <= renderedInputFrameIdUpper) {
|
||||||
// [WARNING] Avoid obfuscating already rendered history, even at "inputFrameId == renderedInputFrameIdUpper", due to the use of "INPUT_SCALE_FRAMES" some previous render frames might already be rendered with "inputFrameId"!
|
// [WARNING] Avoid obfuscating already rendered history, even at "inputFrameId == renderedInputFrameIdUpper", due to the use of "INPUT_SCALE_FRAMES" some previous render frames might already be rendered with "inputFrameId"!
|
||||||
|
// TODO: Shall we update the "chaserRenderFrameId" if the rendered history was wrong? It doesn't seem to impact eventual correctness if we allow the update of "chaserRenderFrameId" upon "inputFrameId <= renderedInputFrameIdUpper" here, however UDP upsync doesn't reserve order from a same sender and there might be multiple other senders, hence it might result in unnecessarily frequent chasing.
|
||||||
|
const localInputFrame = self.recentInputCache.GetByFrameId(inputFrameId);
|
||||||
|
if (null != localInputFrame
|
||||||
|
&&
|
||||||
|
null == firstPredictedYetIncorrectInputFrameId
|
||||||
|
&&
|
||||||
|
localInputFrame.InputList[peerJoinIndex - 1] != peerEncodedInput
|
||||||
|
) {
|
||||||
|
firstPredictedYetIncorrectInputFrameId = inputFrameId;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (inputFrameId <= self.lastAllConfirmedInputFrameId) {
|
if (inputFrameId <= self.lastAllConfirmedInputFrameId) {
|
||||||
@ -953,7 +974,6 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
if (0 < (existingInputFrame.ConfirmedList & peerJoinIndexMask)) {
|
if (0 < (existingInputFrame.ConfirmedList & peerJoinIndexMask)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const peerEncodedInput = (true == fromUDP ? inputFrame.encoded : inputFrame.inputList[peerJoinIndex - 1]);
|
|
||||||
if (inputFrameId > self.lastIndividuallyConfirmedInputFrameId[peerJoinIndex - 1]) {
|
if (inputFrameId > self.lastIndividuallyConfirmedInputFrameId[peerJoinIndex - 1]) {
|
||||||
self.lastIndividuallyConfirmedInputFrameId[peerJoinIndex - 1] = inputFrameId;
|
self.lastIndividuallyConfirmedInputFrameId[peerJoinIndex - 1] = inputFrameId;
|
||||||
self.lastIndividuallyConfirmedInputList[peerJoinIndex - 1] = peerEncodedInput;
|
self.lastIndividuallyConfirmedInputList[peerJoinIndex - 1] = peerEncodedInput;
|
||||||
@ -964,13 +984,14 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
newInputList[peerJoinIndex - 1] = peerEncodedInput;
|
newInputList[peerJoinIndex - 1] = peerEncodedInput;
|
||||||
let newConfirmedList = (existingInputFrame.ConfirmedList | peerJoinIndex);
|
let newConfirmedList = (existingInputFrame.ConfirmedList | peerJoinIndex);
|
||||||
const newInputFrameDownsyncLocal = gopkgs.NewInputFrameDownsync(inputFrameId, newInputList, newConfirmedList);
|
const newInputFrameDownsyncLocal = gopkgs.NewInputFrameDownsync(inputFrameId, newInputList, newConfirmedList);
|
||||||
console.log(`Updated encoded input of peerJoinIndex=${peerJoinIndex} to ${peerEncodedInput} for inputFrameId=${inputFrameId}/renderedInputFrameIdUpper=${renderedInputFrameIdUpper} from ${JSON.stringify(inputFrame)}; newInputFrameDownsyncLocal=${self.gopkgsInputFrameDownsyncStr(newInputFrameDownsyncLocal)}; existingInputFrame=${self.gopkgsInputFrameDownsyncStr(existingInputFrame)}`);
|
//console.log(`Updated encoded input of peerJoinIndex=${peerJoinIndex} to ${peerEncodedInput} for inputFrameId=${inputFrameId}/renderedInputFrameIdUpper=${renderedInputFrameIdUpper} from ${JSON.stringify(inputFrame)}; newInputFrameDownsyncLocal=${self.gopkgsInputFrameDownsyncStr(newInputFrameDownsyncLocal)}; existingInputFrame=${self.gopkgsInputFrameDownsyncStr(existingInputFrame)}`);
|
||||||
self.recentInputCache.SetByFrameId(newInputFrameDownsyncLocal, inputFrameId);
|
self.recentInputCache.SetByFrameId(newInputFrameDownsyncLocal, inputFrameId);
|
||||||
}
|
}
|
||||||
if (0 < effCnt) {
|
if (0 < effCnt) {
|
||||||
//self._markConfirmationIfApplicable();
|
//self._markConfirmationIfApplicable();
|
||||||
self.networkDoctor.logPeerInputFrameUpsync(batch[0].inputFrameId, batch[batch.length - 1].inputFrameId);
|
self.networkDoctor.logPeerInputFrameUpsync(batch[0].inputFrameId, batch[batch.length - 1].inputFrameId);
|
||||||
}
|
}
|
||||||
|
self._handleIncorrectlyRenderedPrediction(firstPredictedYetIncorrectInputFrameId, batch, fromUDP);
|
||||||
},
|
},
|
||||||
|
|
||||||
onPlayerAdded(rdf /* pb.RoomDownsyncFrame */ ) {
|
onPlayerAdded(rdf /* pb.RoomDownsyncFrame */ ) {
|
||||||
@ -1115,7 +1136,7 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
|
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
|
||||||
self.lastRenderFrameIdTriggeredAt = performance.now();
|
self.lastRenderFrameIdTriggeredAt = performance.now();
|
||||||
let t3 = performance.now();
|
let t3 = performance.now();
|
||||||
self.skipRenderFrameFlag = self.networkDoctor.isTooFast();
|
self.skipRenderFrameFlag = self.networkDoctor.isTooFast(self);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error during Map.update", err);
|
console.error("Error during Map.update", err);
|
||||||
self.onBattleStopped(); // TODO: Popup to ask player to refresh browser
|
self.onBattleStopped(); // TODO: Popup to ask player to refresh browser
|
||||||
|
@ -79,19 +79,31 @@ NetworkDoctor.prototype.logSkippedRenderFrameCnt = function() {
|
|||||||
this.skippedRenderFrameCnt += 1;
|
this.skippedRenderFrameCnt += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkDoctor.prototype.isTooFast = function() {
|
NetworkDoctor.prototype.isTooFast = function(mapIns) {
|
||||||
return false;
|
|
||||||
const [sendingFps, srvDownsyncFps, peerUpsyncFps, rollbackFrames, skippedRenderFrameCnt] = this.stats();
|
const [sendingFps, srvDownsyncFps, peerUpsyncFps, rollbackFrames, skippedRenderFrameCnt] = this.stats();
|
||||||
if (sendingFps >= this.inputRateThreshold + 2) {
|
if (sendingFps >= this.inputRateThreshold + 3) {
|
||||||
// Don't send too fast
|
// Don't send too fast
|
||||||
|
console.log(`Sending too fast, sendingFps=${sendingFps}`);
|
||||||
return true;
|
return true;
|
||||||
} else if (sendingFps >= this.inputRateThreshold && srvDownsyncFps >= this.inputRateThreshold) {
|
} else {
|
||||||
|
const sendingFpsNormal = (sendingFps >= 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".
|
// 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) {
|
const recvFpsNormal = (srvDownsyncFps >= this.inputRateThreshold || peerUpsyncFps >= this.inputRateThreshold * (window.boundRoomCapacity - 1));
|
||||||
// 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.
|
if (sendingFpsNormal && recvFpsNormal) {
|
||||||
|
let selfInputFrameIdFront = gopkgs.ConvertToNoDelayInputFrameId(mapIns.renderFrameId);
|
||||||
|
let minInputFrameIdFront = Number.MAX_VALUE;
|
||||||
|
for (let k = 0; k < window.boundRoomCapacity; ++k) {
|
||||||
|
if (k + 1 == mapIns.selfPlayerInfo.JoinIndex) continue;
|
||||||
|
if (mapIns.lastIndividuallyConfirmedInputFrameId[k] >= minInputFrameIdFront) continue;
|
||||||
|
minInputFrameIdFront = mapIns.lastIndividuallyConfirmedInputFrameId[k];
|
||||||
|
}
|
||||||
|
if ((selfInputFrameIdFront > minInputFrameIdFront) && ((selfInputFrameIdFront - minInputFrameIdFront) > (mapIns.inputFrameUpsyncDelayTolerance+2))) {
|
||||||
|
// first comparison condition is to avoid numeric overflow
|
||||||
|
console.log(`Game logic ticking too fast, selfInputFrameIdFront=${selfInputFrameIdFront}, minInputFrameIdFront=${minInputFrameIdFront}, inputFrameUpsyncDelayTolerance=${mapIns.inputFrameUpsyncDelayTolerance}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user