Fixed prediction update upon last all-confirmed input frame changes.

This commit is contained in:
genxium 2022-09-22 17:09:49 +08:00
parent f0e624aa85
commit 58add91a54
2 changed files with 42 additions and 32 deletions

View File

@ -440,7 +440,7 @@
"array": [ "array": [
0, 0,
0, 0,
216.05530045313827, 209.7912853806815,
0, 0,
0, 0,
0, 0,

View File

@ -138,18 +138,26 @@ cc.Class({
_dumpToFullFrameCache: function(fullFrame) { _dumpToFullFrameCache: function(fullFrame) {
const self = this; const self = this;
while (self.recentFrameCacheEd - self.recentFrameCacheSt >= self.recentFrameCacheMaxCount) { self.recentFrameCache.set(fullFrame.id, fullFrame);
delete self.recentFrameCache[self.recentFrameCacheSt++]; if (fullFrame.id >= self.recentFrameCacheEd) {
// Should be consecutive
++self.recentFrameCacheEd;
}
while (self.recentFrameCacheEd - self.recentFrameCacheSt >= self.recentFrameCacheMaxCount) {
self.recentFrameCache.delete(self.recentFrameCacheSt++);
} }
self.recentFrameCache[self.recentFrameCacheEd++] = fullFrame;
}, },
_dumpToInputCache: function(inputFrameDownsync) { _dumpToInputCache: function(inputFrameDownsync) {
const self = this; const self = this;
while (self.recentInputCacheEd - self.recentInputCacheSt >= self.recentInputCacheMaxCount) { self.recentInputCache.set(inputFrameDownsync.inputFrameId, inputFrameDownsync);
delete self.recentInputCache[self.recentInputCacheSt++]; if (inputFrameDownsync.inputFrameId >= self.recentInputCacheEd) {
// Should be consecutive
++self.recentInputCacheEd;
}
while (self.recentInputCacheEd - self.recentInputCacheSt >= self.recentInputCacheMaxCount) {
self.recentInputCache.delete(self.recentInputCacheSt++);
} }
self.recentInputCache[self.recentInputCacheEd++] = inputFrameDownsync;
}, },
_convertToInputFrameId(renderFrameId, inputDelayFrames) { _convertToInputFrameId(renderFrameId, inputDelayFrames) {
@ -180,11 +188,11 @@ cc.Class({
if (0 == instance.recentInputCacheEd) { if (0 == instance.recentInputCacheEd) {
prefabbedInputList = new Array(instance.playerRichInfoDict.size).fill(0); prefabbedInputList = new Array(instance.playerRichInfoDict.size).fill(0);
} else { } else {
if (null == instance.recentInputCache || null == instance.recentInputCache[instance.recentInputCacheEd-1]) { if (!instance.recentInputCache.has(instance.recentInputCacheEd-1)) {
console.warn("_generateInputFrameUpsync: recentInputCache is NOT having inputFrameId=", instance.recentInputCacheEd-1, "; recentInputCache=", instance._stringifyRecentInputCache(false)); console.warn("_generateInputFrameUpsync: recentInputCache is NOT having inputFrameId=", instance.recentInputCacheEd-1, "; recentInputCache=", instance._stringifyRecentInputCache(false));
prefabbedInputList = new Array(instance.playerRichInfoDict.size).fill(0); prefabbedInputList = new Array(instance.playerRichInfoDict.size).fill(0);
} else { } else {
prefabbedInputList = Array.from(instance.recentInputCache[instance.recentInputCacheEd-1].inputList); prefabbedInputList = Array.from(instance.recentInputCache.get(instance.recentInputCacheEd-1).inputList);
selfPlayerLastInputFrameInput = prefabbedInputList[(instance.selfPlayerInfo.joinIndex-1)]; // it's an integer, thus making a copy here, not impacted by later assignments selfPlayerLastInputFrameInput = prefabbedInputList[(instance.selfPlayerInfo.joinIndex-1)]; // it's an integer, thus making a copy here, not impacted by later assignments
} }
} }
@ -216,9 +224,9 @@ cc.Class({
const instance = this; const instance = this;
let inputFrameUpsyncBatch = []; let inputFrameUpsyncBatch = [];
for (let i = instance.lastUpsyncInputFrameId+1; i <= inputFrameId; ++i) { for (let i = instance.lastUpsyncInputFrameId+1; i <= inputFrameId; ++i) {
const inputFrameDownsync = instance.recentInputCache[i]; const inputFrameDownsync = instance.recentInputCache.get(i);
if (null == inputFrameDownsync) { if (null == inputFrameDownsync) {
console.warn("_sendInputFrameUpsyncBatch: recentInputCache is NOT having inputFrameId=", i, "; recentInputCache=", JSON.stringify(instance.recentInputCache)); console.warn("_sendInputFrameUpsyncBatch: recentInputCache is NOT having inputFrameId=", i, "; recentInputCache=", instance._stringifyRecentInputCache(false));
} else { } else {
const inputFrameUpsync = { const inputFrameUpsync = {
inputFrameId: i, inputFrameId: i,
@ -328,19 +336,19 @@ cc.Class({
self.lastRoomDownsyncFrameId = 0; self.lastRoomDownsyncFrameId = 0;
self.renderFrameId = 0; // After battle started self.renderFrameId = 0; // After battle started
self.inputDelayFrames = 8; self.inputDelayFrames = 8;
self.inputScaleFrames = 3; self.inputScaleFrames = 2;
self.lastDownsyncInputFrameId = -1; self.lastDownsyncInputFrameId = -1;
self.lastAllConfirmedInputFrameId = -1; self.lastAllConfirmedInputFrameId = -1;
self.lastUpsyncInputFrameId = -1; self.lastUpsyncInputFrameId = -1;
self.inputFrameUpsyncDelayTolerance = 3; self.inputFrameUpsyncDelayTolerance = 2;
self.recentFrameCache = {}; self.recentFrameCache = new Map();
self.recentFrameCacheSt = 0; // closed index self.recentFrameCacheSt = 0; // closed index
self.recentFrameCacheEd = 0; // open index self.recentFrameCacheEd = 0; // open index
self.recentFrameCacheMaxCount = 1024; self.recentFrameCacheMaxCount = 1024;
self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others". self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others".
self.recentInputCache = {}; // TODO: Use a ringbuf instead self.recentInputCache = new Map(); // TODO: Use a ringbuf instead
self.recentInputCacheSt = 0; // closed index self.recentInputCacheSt = 0; // closed index
self.recentInputCacheEd = 0; // open index self.recentInputCacheEd = 0; // open index
self.recentInputCacheMaxCount = 1024; self.recentInputCacheMaxCount = 1024;
@ -580,13 +588,13 @@ cc.Class({
return; return;
} }
// console.log("Received inputFrameDownsyncBatch=", batch, ", now correspondingLastLocalInputFrame=", self.recentInputCache[batch[batch.length-1].inputFrameId]); // console.log("Received inputFrameDownsyncBatch=", batch, ", now correspondingLastLocalInputFrame=", self.recentInputCache.get(batch[batch.length-1].inputFrameId));
let firstPredictedYetIncorrectInputFrameId = null; let firstPredictedYetIncorrectInputFrameId = null;
let firstPredictedYetIncorrectInputFrameJoinIndex = null; let firstPredictedYetIncorrectInputFrameJoinIndex = null;
for (let k in batch) { for (let k in batch) {
const inputFrameDownsync = batch[k]; const inputFrameDownsync = batch[k];
const inputFrameDownsyncId = inputFrameDownsync.inputFrameId; const inputFrameDownsyncId = inputFrameDownsync.inputFrameId;
const localInputFrame = self.recentInputCache[inputFrameDownsyncId]; const localInputFrame = self.recentInputCache.get(inputFrameDownsyncId);
if (null == localInputFrame) { if (null == localInputFrame) {
console.warn("handleInputFrameDownsyncBatch: recentInputCache is NOT having inputFrameDownsyncId=", inputFrameDownsyncId, "; now recentInputCache=", self._stringifyRecentInputCache(false)); console.warn("handleInputFrameDownsyncBatch: recentInputCache is NOT having inputFrameDownsyncId=", inputFrameDownsyncId, "; now recentInputCache=", self._stringifyRecentInputCache(false));
} else { } else {
@ -714,10 +722,9 @@ cc.Class({
let s = []; let s = [];
s.push("Battle stats: lastUpsyncInputFrameId=" + self.lastUpsyncInputFrameId + ", lastDownsyncInputFrameId=" + self.lastDownsyncInputFrameId + ", lastAllConfirmedInputFrameId=" + self.lastAllConfirmedInputFrameId); s.push("Battle stats: lastUpsyncInputFrameId=" + self.lastUpsyncInputFrameId + ", lastDownsyncInputFrameId=" + self.lastDownsyncInputFrameId + ", lastAllConfirmedInputFrameId=" + self.lastAllConfirmedInputFrameId);
for (let inputFrameDownsyncId in self.recentInputCache) { self.recentInputCache.forEach((inputFrameDownsync, inputFrameId) => {
const inputFrameDownsync = self.recentInputCache[inputFrameDownsyncId];
s.push(JSON.stringify(inputFrameDownsync)); s.push(JSON.stringify(inputFrameDownsync));
} });
console.log(s.join('\n')); console.log(s.join('\n'));
}, },
@ -786,7 +793,7 @@ cc.Class({
const delayedInputFrameDownsync = self.assembleInputFrameDownsync(delayedInputFrameId); const delayedInputFrameDownsync = self.assembleInputFrameDownsync(delayedInputFrameId);
if (null == delayedInputFrameDownsync) { if (null == delayedInputFrameDownsync) {
console.warn("update(dt): recentInputCache is NOT having inputFrameId=", delayedInputFrameId, "; recentInputCache=", instance._stringifyRecentInputCache(false)); console.warn("update(dt): recentInputCache is NOT having inputFrameId=", delayedInputFrameId, "; recentInputCache=", self._stringifyRecentInputCache(false));
} else { } else {
self._applyInputFrameDownsyncDynamics(delayedInputFrameDownsync, false); self._applyInputFrameDownsyncDynamics(delayedInputFrameDownsync, false);
} }
@ -957,9 +964,9 @@ cc.Class({
assembleInputFrameDownsync(inputFrameId) { assembleInputFrameDownsync(inputFrameId) {
const self = this; const self = this;
let inputFrameDownsync = self.recentInputCache[inputFrameId]; let inputFrameDownsync = self.recentInputCache.get(inputFrameId);
if (-1 != self.lastAllConfirmedInputFrameId && inputFrameId > self.lastAllConfirmedInputFrameId) { if (-1 != self.lastAllConfirmedInputFrameId && inputFrameId > self.lastAllConfirmedInputFrameId) {
const lastAllConfirmedInputFrame = self.recentInputCache[self.lastAllConfirmedInputFrameId]; const lastAllConfirmedInputFrame = self.recentInputCache.get(self.lastAllConfirmedInputFrameId);
for (let i = 0; i < inputFrameDownsync.inputList.length; ++i) { for (let i = 0; i < inputFrameDownsync.inputList.length; ++i) {
if (i == self.selfPlayerInfo.joinIndex-1) continue; if (i == self.selfPlayerInfo.joinIndex-1) continue;
inputFrameDownsync.inputList[i] = lastAllConfirmedInputFrame.inputList[i]; inputFrameDownsync.inputList[i] = lastAllConfirmedInputFrame.inputList[i];
@ -993,7 +1000,7 @@ cc.Class({
_rollbackAndReplay(inputFrameId1, renderFrameId1, inputFrameId2, renderFrameId2) { _rollbackAndReplay(inputFrameId1, renderFrameId1, inputFrameId2, renderFrameId2) {
const self = this; const self = this;
const rdf1 = self.recentFrameCache[renderFrameId1]; const rdf1 = self.recentFrameCache.get(renderFrameId1);
if (null == rdf1) { if (null == rdf1) {
console.error("renderFrameId1=", renderFrameId1, "doesn't exist in recentFrameCache ", self._stringifyRecentFrameCache(false), ": COULDN'T ROLLBACK!"); console.error("renderFrameId1=", renderFrameId1, "doesn't exist in recentFrameCache ", self._stringifyRecentFrameCache(false), ": COULDN'T ROLLBACK!");
return; return;
@ -1036,12 +1043,10 @@ cc.Class({
_stringifyRecentFrameCache(usefullOutput) { _stringifyRecentFrameCache(usefullOutput) {
if (true == usefullOutput) { if (true == usefullOutput) {
let s = []; let s = [];
for (let renderFrameId in self.recentFrameCache) { self.recentFrameCache.forEach((roomDownsyncFrame, renderFrameId) => {
const roomDownsyncFrame = self.recentFrameCache[renderFrameId];
s.push(JSON.stringify(roomDownsyncFrame)); s.push(JSON.stringify(roomDownsyncFrame));
} });
return s.join('\n'); return s.join('\n');
} }
@ -1050,7 +1055,12 @@ cc.Class({
_stringifyRecentInputCache(usefullOutput) { _stringifyRecentInputCache(usefullOutput) {
if (true == usefullOutput) { if (true == usefullOutput) {
return JSON.stringify(this.recentInputCache); let s = [];
self.recentInputCache.forEach((inputFrameDownsync, inputFrameId) => {
s.push(JSON.stringify(inputFrameDownsync));
});
return s.join('\n');
} }
return "[stInputFrameId=" + self.recentInputCacheSt + ", edInputFrameId=" + self.recentInputCacheEd + ")"; return "[stInputFrameId=" + self.recentInputCacheSt + ", edInputFrameId=" + self.recentInputCacheEd + ")";
}, },