mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 11:18:55 +00:00
Improved stability.
This commit is contained in:
parent
b9beee549f
commit
ea14ced958
@ -157,7 +157,6 @@ type Room struct {
|
||||
TmxPolygonsMap StrToPolygon2DListMap
|
||||
|
||||
rdfIdToActuallyUsedInput map[int32]*pb.InputFrameDownsync
|
||||
allowUpdateInputFrameInPlaceUponDynamics bool
|
||||
LastIndividuallyConfirmedInputFrameId []int32
|
||||
LastIndividuallyConfirmedInputList []uint64
|
||||
|
||||
@ -808,7 +807,6 @@ func (pR *Room) OnDismissed() {
|
||||
pR.RenderFrameBuffer = resolv.NewRingBuffer(pR.RenderCacheSize)
|
||||
pR.InputsBuffer = resolv.NewRingBuffer((pR.RenderCacheSize >> 1) + 1)
|
||||
pR.rdfIdToActuallyUsedInput = make(map[int32]*pb.InputFrameDownsync)
|
||||
pR.allowUpdateInputFrameInPlaceUponDynamics = true
|
||||
pR.LastIndividuallyConfirmedInputFrameId = make([]int32, pR.Capacity)
|
||||
for i := 0; i < pR.Capacity; i++ {
|
||||
pR.LastIndividuallyConfirmedInputFrameId[i] = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
|
||||
@ -847,7 +845,7 @@ func (pR *Room) OnDismissed() {
|
||||
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for logging FAST FRAME
|
||||
dilutedServerFps := float64(58.0) // Don't set this value too small, otherwise we might miss force confirmation needs for slow tickers!
|
||||
pR.dilutedRollbackEstimatedDtNanos = int64(float64(pR.RollbackEstimatedDtNanos) * float64(serverFps) / dilutedServerFps)
|
||||
pR.BattleDurationFrames = int32(60 * serverFps)
|
||||
pR.BattleDurationFrames = int32(20 * serverFps)
|
||||
//pR.BattleDurationFrames = int32(20 * serverFps)
|
||||
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
|
||||
pR.InputFrameUpsyncDelayTolerance = battle.ConvertToNoDelayInputFrameId(pR.NstDelayFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche
|
||||
@ -856,7 +854,7 @@ func (pR *Room) OnDismissed() {
|
||||
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
|
||||
pR.ForceAllResyncOnAnyActiveSlowTicker = true // See tradeoff discussion in "downsyncToAllPlayers"
|
||||
|
||||
pR.FrameDataLoggingEnabled = false // [WARNING] DON'T ENABLE ON LONG BATTLE DURATION! It consumes A LOT OF MEMORY!
|
||||
pR.FrameDataLoggingEnabled = true // [WARNING] DON'T ENABLE ON LONG BATTLE DURATION! It consumes A LOT OF MEMORY!
|
||||
pR.BattleUdpTunnelLock.Lock()
|
||||
pR.BattleUdpTunnel = nil
|
||||
pR.BattleUdpTunnelAddr = nil
|
||||
@ -1309,9 +1307,6 @@ func (pR *Room) forceConfirmationIfApplicable(prevRenderFrameId int32) uint64 {
|
||||
panic(fmt.Sprintf("inputFrameId=%v doesn't exist for roomId=%v! InputsBuffer=%v", j, pR.Id, pR.InputsBufferString(false)))
|
||||
}
|
||||
inputFrameDownsync := tmp.(*battle.InputFrameDownsync)
|
||||
if pR.allowUpdateInputFrameInPlaceUponDynamics {
|
||||
battle.UpdateInputFrameInPlaceUponDynamics(j, pR.Capacity, inputFrameDownsync.ConfirmedList, inputFrameDownsync.InputList, pR.LastIndividuallyConfirmedInputFrameId, pR.LastIndividuallyConfirmedInputList, int32(MAGIC_JOIN_INDEX_INVALID))
|
||||
}
|
||||
unconfirmedMask |= (allConfirmedMask ^ inputFrameDownsync.ConfirmedList)
|
||||
inputFrameDownsync.ConfirmedList = allConfirmedMask
|
||||
pR.onInputFrameDownsyncAllConfirmed(inputFrameDownsync, -1)
|
||||
@ -1392,7 +1387,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
||||
}
|
||||
}
|
||||
|
||||
battle.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(pR.InputsBuffer, currRenderFrame.Id, pR.Space, pR.CollisionSysMap, pR.SpaceOffsetX, pR.SpaceOffsetY, pR.CharacterConfigsArr, pR.RenderFrameBuffer, pR.collisionHolder, pR.effPushbacks, pR.hardPushbackNormsArr, pR.jumpedOrNotList, pR.dynamicRectangleColliders, pR.LastIndividuallyConfirmedInputFrameId, pR.LastIndividuallyConfirmedInputList, false, MAGIC_JOIN_INDEX_INVALID) // "allowUpdateInputFrameInPlaceUponDynamics" is instead used in "forceConfirmationIfApplicable"
|
||||
battle.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(pR.InputsBuffer, currRenderFrame.Id, pR.Space, pR.CollisionSysMap, pR.SpaceOffsetX, pR.SpaceOffsetY, pR.CharacterConfigsArr, pR.RenderFrameBuffer, pR.collisionHolder, pR.effPushbacks, pR.hardPushbackNormsArr, pR.jumpedOrNotList, pR.dynamicRectangleColliders, pR.LastIndividuallyConfirmedInputFrameId, pR.LastIndividuallyConfirmedInputList, false, MAGIC_JOIN_INDEX_INVALID) // DON'T mutate inputs upon dynamics on backend to avoid complicating the edge cases
|
||||
pR.CurDynamicsRenderFrameId++
|
||||
}
|
||||
}
|
||||
|
@ -461,7 +461,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
210.4441731196186,
|
||||
209.57814771583418,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -713,9 +713,9 @@ cc.Class({
|
||||
if (notSelfUnconfirmed) {
|
||||
shouldForceDumping2 = false;
|
||||
shouldForceResync = false;
|
||||
self.othersForcedDownsyncRenderFrameDict.set(rdfId, rdf);
|
||||
self.othersForcedDownsyncRenderFrameDict.set(rdfId, [pbRdf, rdf]);
|
||||
if (CC_DEBUG) {
|
||||
console.warn(`Someone else is forced to resync! renderFrameId=${rdf.GetId()}
|
||||
console.warn(`Someone else is forced to resync! renderFrameId=${rdfId}
|
||||
backendUnconfirmedMask=${pbRdf.backendUnconfirmedMask}
|
||||
accompaniedInputFrameDownsyncBatchRange=[${null == accompaniedInputFrameDownsyncBatch ? null : accompaniedInputFrameDownsyncBatch[0].inputFrameId}, ${null == accompaniedInputFrameDownsyncBatch ? null : accompaniedInputFrameDownsyncBatch[accompaniedInputFrameDownsyncBatch.length - 1].inputFrameId}]`);
|
||||
}
|
||||
@ -947,7 +947,7 @@ accompaniedInputFrameDownsyncBatchRange=[${accompaniedInputFrameDownsyncBatch[0]
|
||||
_handleIncorrectlyRenderedPrediction(firstPredictedYetIncorrectInputFrameId, batch, fromUDP) {
|
||||
if (null == firstPredictedYetIncorrectInputFrameId) return;
|
||||
const self = this;
|
||||
const renderFrameId1 = gopkgs.ConvertToFirstUsedRenderFrameId(firstPredictedYetIncorrectInputFrameId) - 1;
|
||||
const renderFrameId1 = gopkgs.ConvertToFirstUsedRenderFrameId(firstPredictedYetIncorrectInputFrameId);
|
||||
if (renderFrameId1 >= self.chaserRenderFrameId) return;
|
||||
|
||||
/*
|
||||
@ -1164,25 +1164,25 @@ fromUDP=${fromUDP}`);
|
||||
rollbackFrames = 0;
|
||||
}
|
||||
self.networkDoctor.logRollbackFrames(rollbackFrames);
|
||||
let prevRdf = latestRdfResults[0],
|
||||
rdf = latestRdfResults[1];
|
||||
let prevRdf = latestRdfResults[0], // Having "prevRdf.Id == self.renderFrameId"
|
||||
rdf = latestRdfResults[1]; // Having "rdf.Id == self.renderFrameId+1"
|
||||
/*
|
||||
const nonTrivialChaseEnded = (prevChaserRenderFrameId < nextChaserRenderFrameId && nextChaserRenderFrameId == self.renderFrameId);
|
||||
if (nonTrivialChaseEnded) {
|
||||
console.debug("Non-trivial chase ended, prevChaserRenderFrameId=" + prevChaserRenderFrameId + ", nextChaserRenderFrameId=" + nextChaserRenderFrameId);
|
||||
}
|
||||
*/
|
||||
// [WARNING] Don't try to get "prevRdf(i.e. renderFrameId == latest-1)" by "self.recentRenderCache.GetByFrameId(...)" here, as the cache might have been updated by asynchronous "onRoomDownsyncFrame(...)" calls!
|
||||
if (self.othersForcedDownsyncRenderFrameDict.has(rdf.GetId())) {
|
||||
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(rdf.GetId());
|
||||
const othersForcedDownsyncRenderFrame = self.othersForcedDownsyncRenderFrameDict.get(rdf.GetId());
|
||||
const [pbOthersForcedDownsyncRenderFrame, othersForcedDownsyncRenderFrame] = self.othersForcedDownsyncRenderFrameDict.get(rdf.GetId());
|
||||
if (self.lastAllConfirmedInputFrameId >= delayedInputFrameId && !self.equalRoomDownsyncFrames(othersForcedDownsyncRenderFrame, rdf)) {
|
||||
if (CC_DEBUG) {
|
||||
console.warn(`Mismatched render frame@rdf.id=${rdf.GetId()} w/ inputFrameId=${delayedInputFrameId}:
|
||||
rdf=${self._stringifyGopkgRdfForFrameDataLogging(rdf)}
|
||||
othersForcedDownsyncRenderFrame=${self._stringifyGopkgRdfForFrameDataLogging(othersForcedDownsyncRenderFrame)}`);
|
||||
}
|
||||
rdf = othersForcedDownsyncRenderFrame;
|
||||
// [WARNING] When this happens, something is intrinsically wrong -- to avoid having an inconsistent history in the "recentRenderCache", thus a wrong prediction all the way from here on, clear the history!
|
||||
pbOthersForcedDownsyncRenderFrame.backendUnconfirmedMask = ((1 << window.boundRoomCapacity) - 1);
|
||||
self.onRoomDownsyncFrame(pbOthersForcedDownsyncRenderFrame, null);
|
||||
self.othersForcedDownsyncRenderFrameDict.delete(rdf.GetId());
|
||||
}
|
||||
}
|
||||
@ -1438,19 +1438,11 @@ othersForcedDownsyncRenderFrame=${self._stringifyGopkgRdfForFrameDataLogging(oth
|
||||
const j = gopkgs.ConvertToDelayedInputFrameId(i);
|
||||
const delayedInputFrame = gopkgs.GetInputFrameDownsync(self.recentInputCache, j);
|
||||
|
||||
const allowUpdateInputFrameInPlaceUponDynamics = (!isChasing);
|
||||
const allowUpdateInputFrameInPlaceUponDynamics = (!isChasing); // [WARNING] Input mutation could trigger chasing on frontend, thus don't trigger mutation when chasing to avoid confusing recursion.
|
||||
const hasInputFrameUpdatedOnDynamics = gopkgs.ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(self.recentInputCache, i, collisionSys, collisionSysMap, self.spaceOffsetX, self.spaceOffsetY, self.chConfigsOrderedByJoinIndex, self.recentRenderCache, self.collisionHolder, self.effPushbacks, self.hardPushbackNormsArr, self.jumpedOrNotList, self.dynamicRectangleColliders, self.lastIndividuallyConfirmedInputFrameId, self.lastIndividuallyConfirmedInputList, allowUpdateInputFrameInPlaceUponDynamics, self.selfPlayerInfo.joinIndex);
|
||||
if (hasInputFrameUpdatedOnDynamics) {
|
||||
const ii = gopkgs.ConvertToFirstUsedRenderFrameId(j);
|
||||
if (ii < i) {
|
||||
/*
|
||||
[WARNING]
|
||||
If we don't rollback at this spot, when the mutated "delayedInputFrame.inputList" a.k.a. "inputFrame#j" matches the later downsynced version, rollback WOULDN'T be triggered for the incorrectly rendered "renderFrame#(ii+1)", and it would STAY IN HISTORY FOREVER -- as the history becomes incorrect, EVERY LATEST renderFrame since "inputFrame#j" was mutated would be ALWAYS incorrectly rendering too!
|
||||
|
||||
The backend counterpart doesn't need this rollback because
|
||||
1. Backend only applies all-confirmed inputFrames to calc dynamics.
|
||||
2. Backend applies an all-confirmed inputFrame to all applicable render frames at once.
|
||||
*/
|
||||
self._handleIncorrectlyRenderedPrediction(j, null, false);
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ bool DelayNoMore::UdpSession::pollUdpRecvRingBuff() {
|
||||
// This function is called by GameThread 60 fps.
|
||||
|
||||
//uv_mutex_lock(&recvRingBuffLock);
|
||||
while (true) {
|
||||
while (true && NULL != recvLoop) {
|
||||
RecvWork f;
|
||||
bool res = recvRingBuff->pop(&f);
|
||||
if (!res) {
|
||||
|
@ -76,7 +76,7 @@
|
||||
"shelter_z_reducer",
|
||||
"shelter"
|
||||
],
|
||||
"last-module-event-record-time": 1677337364473,
|
||||
"last-module-event-record-time": 1678432182471,
|
||||
"simulator-orientation": false,
|
||||
"simulator-resolution": {
|
||||
"height": 640,
|
||||
|
Loading…
Reference in New Issue
Block a user