diff --git a/battle_srv/models/room.go b/battle_srv/models/room.go index de158fa..ea71837 100644 --- a/battle_srv/models/room.go +++ b/battle_srv/models/room.go @@ -473,7 +473,7 @@ func (pR *Room) StartBattle() { f := tmp.(*pb.InputFrameDownsync) if pR.inputFrameIdDebuggable(candidateToSendInputFrameId) { debugSendingInputFrameId = candidateToSendInputFrameId - Logger.Info("inputFrame lifecycle#3[sending]:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("playerAckingInputFrameId", player.AckingInputFrameId), zap.Any("inputFrameId", candidateToSendInputFrameId), zap.Any("inputFrameId-doublecheck", f.InputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString(false)), zap.Any("ConfirmedList", f.ConfirmedList)) + Logger.Debug("inputFrame lifecycle#3[sending]:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("playerAckingInputFrameId", player.AckingInputFrameId), zap.Any("inputFrameId", candidateToSendInputFrameId), zap.Any("inputFrameId-doublecheck", f.InputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString(false)), zap.Any("ConfirmedList", f.ConfirmedList)) } toSendInputFrames = append(toSendInputFrames, f) candidateToSendInputFrameId++ @@ -511,7 +511,7 @@ func (pR *Room) StartBattle() { f := pR.AllPlayerInputsBuffer.Pop().(*pb.InputFrameDownsync) if pR.inputFrameIdDebuggable(f.InputFrameId) { // Popping of an "inputFrame" would be AFTER its being all being confirmed, because it requires the "inputFrame" to be all acked - Logger.Info("inputFrame lifecycle#5[popped]:", zap.Any("roomId", pR.Id), zap.Any("inputFrameId", f.InputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString(false))) + Logger.Debug("inputFrame lifecycle#5[popped]:", zap.Any("roomId", pR.Id), zap.Any("inputFrameId", f.InputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString(false))) } } @@ -579,15 +579,14 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) { inputFrameDownsync := tmp2.(*pb.InputFrameDownsync) oldConfirmedList := atomic.LoadUint64(&(inputFrameDownsync.ConfirmedList)) if (oldConfirmedList & joinMask) > 0 { - Logger.Warn(fmt.Sprintf("Cmd already confirmed but getting set attempt, omitting this upsync cmd: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString(false))) + Logger.Debug(fmt.Sprintf("Cmd already confirmed but getting set attempt, omitting this upsync cmd: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString(false))) return } // In Golang 1.12, there's no "compare-and-swap primitive" on a custom struct (or it's pointer, unless it's an unsafe pointer https://pkg.go.dev/sync/atomic@go1.12#CompareAndSwapPointer). Although CAS on custom struct is possible in Golang 1.19 https://pkg.go.dev/sync/atomic@go1.19.1#Value.CompareAndSwap, using a single word is still faster whenever possible. - if swapped := atomic.CompareAndSwapUint64(&inputFrameDownsync.InputList[indiceInJoinIndexBooleanArr], uint64(0), encodedInput); !swapped { - Logger.Warn(fmt.Sprintf("Failed input CAS: roomId=%v, playerId=%v, clientInputFrameId=%v", pR.Id, playerId, clientInputFrameId)) - return - } + + // [WARNING] No need to use CAS for updating "inputFrameDownsync.InputList[indiceInJoinIndexBooleanArr]", the upsync from frontend takes top priority. + atomic.StoreUint64(&inputFrameDownsync.InputList[indiceInJoinIndexBooleanArr], encodedInput); newConfirmedList := (oldConfirmedList | joinMask) if swapped := atomic.CompareAndSwapUint64(&(inputFrameDownsync.ConfirmedList), oldConfirmedList, newConfirmedList); !swapped { diff --git a/frontend/assets/scenes/login.fire b/frontend/assets/scenes/login.fire index 6324f99..cee1e6c 100644 --- a/frontend/assets/scenes/login.fire +++ b/frontend/assets/scenes/login.fire @@ -440,7 +440,7 @@ "array": [ 0, 0, - 209.57814771583418, + 209.63606633899616, 0, 0, 0, diff --git a/frontend/assets/scripts/Map.js b/frontend/assets/scripts/Map.js index 739b185..d719ab1 100644 --- a/frontend/assets/scripts/Map.js +++ b/frontend/assets/scripts/Map.js @@ -947,6 +947,7 @@ cc.Class({ rdf.id > self.lastAllConfirmedRenderFrameId ) { self.lastAllConfirmedRenderFrameId = rdf.id; + self.chaserRenderFrameId = rdf.id; // it must be true that "chaserRenderFrameId >= lastAllConfirmedRenderFrameId" } self._dumpToRenderCache(rdf); return rdf; @@ -978,7 +979,7 @@ cc.Class({ }, rollbackAndChase(renderFrameIdSt, renderFrameIdEd, collisionSys, collisionSysMap) { - if (renderFrameSt >= renderFrameIdEd) { + if (renderFrameIdSt >= renderFrameIdEd) { return; } diff --git a/frontend/assets/scripts/WsSessionMgr.js b/frontend/assets/scripts/WsSessionMgr.js index da2abec..38bd561 100644 --- a/frontend/assets/scripts/WsSessionMgr.js +++ b/frontend/assets/scripts/WsSessionMgr.js @@ -179,7 +179,7 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) { break; case window.DOWNSYNC_MSG_ACT_FORCED_RESYNC: if (window.handleInputFrameDownsyncBatch && window.handleRoomDownsyncFrame) { - console.warn("Got forced resync:", resp.toString(), " @localRenderFrameId=", mapIns.renderFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false)); + console.warn("Got forced resync:", JSON.stringify(resp), " @localRenderFrameId=", mapIns.renderFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false)); // The following order of execution is important, because "handleInputFrameDownsyncBatch" is only available when state is IN_BATTLE window.handleRoomDownsyncFrame(resp.rdf); window.handleInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch);