From 8de2d6e4e78b60f5186a0f45bc3067760a162892 Mon Sep 17 00:00:00 2001 From: genxium Date: Tue, 31 Jan 2023 09:57:37 +0800 Subject: [PATCH] Enhancement for type#1 force-confirmation trigger. --- battle_srv/models/room.go | 21 ++++++++++++--------- battle_srv/ws/serve.go | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/battle_srv/models/room.go b/battle_srv/models/room.go index 0d1097b..978b592 100644 --- a/battle_srv/models/room.go +++ b/battle_srv/models/room.go @@ -574,7 +574,7 @@ func (pR *Room) StartBattle() { }) } -func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) { +func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq, fromUDP bool) { /* [WARNING] This function "OnBattleCmdReceived" could be called by different ws sessions and thus from different threads! @@ -619,7 +619,7 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) { //Logger.Debug(fmt.Sprintf("OnBattleCmdReceived-InputsBufferLock unlocked: roomId=%v, fromPlayerId=%v", pR.Id, playerId)) }() - inputsBufferSnapshot := pR.markConfirmationIfApplicable(inputFrameUpsyncBatch, playerId, player) + inputsBufferSnapshot := pR.markConfirmationIfApplicable(inputFrameUpsyncBatch, playerId, player, fromUDP) if nil != inputsBufferSnapshot { pR.downsyncToAllPlayers(inputsBufferSnapshot) } /*else { @@ -1159,7 +1159,7 @@ func (pR *Room) getOrPrefabInputFrameDownsync(inputFrameId int32) *battle.InputF return currInputFrameDownsync } -func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*pb.InputFrameUpsync, playerId int32, player *Player) *pb.InputsBufferSnapshot { +func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*pb.InputFrameUpsync, playerId int32, player *Player, fromUDP bool) *pb.InputsBufferSnapshot { // [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked! // Step#1, put the received "inputFrameUpsyncBatch" into "pR.InputsBuffer" for _, inputFrameUpsync := range inputFrameUpsyncBatch { @@ -1182,11 +1182,14 @@ func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*pb.InputFr targetInputFrameDownsync.InputList[player.JoinIndex-1] = inputFrameUpsync.Encoded targetInputFrameDownsync.ConfirmedList |= uint64(1 << uint32(player.JoinIndex-1)) - player.LastReceivedInputFrameId = clientInputFrameId - pR.LastIndividuallyConfirmedInputList[player.JoinIndex-1] = inputFrameUpsync.Encoded - - if clientInputFrameId > pR.LatestPlayerUpsyncedInputFrameId { - pR.LatestPlayerUpsyncedInputFrameId = clientInputFrameId + if false == fromUDP { + // [WARNING] We have to distinguish whether or not the incoming batch is from UDP here, otherwise "pR.LatestPlayerUpsyncedInputFrameId - pR.LastAllConfirmedInputFrameId" might become unexpectedly large in case of "UDP packet loss + slow ws session"! + player.LastReceivedInputFrameId = clientInputFrameId + if clientInputFrameId > pR.LatestPlayerUpsyncedInputFrameId { + pR.LatestPlayerUpsyncedInputFrameId = clientInputFrameId + } + // It's safe (in terms of getting an eventually correct "RenderFrameBuffer") to put the following update of "pR.LastIndividuallyConfirmedInputList" which is ONLY used for prediction in "InputsBuffer" out of "false == fromUDP" block, but I'm still putting it in for convenient debugging. + pR.LastIndividuallyConfirmedInputList[player.JoinIndex-1] = inputFrameUpsync.Encoded } } @@ -1760,7 +1763,7 @@ func (pR *Room) startBattleUdpTunnel() { Logger.Warn(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d failed to forward upsync from (playerId:%d, joinIndex:%d, addr:%s) to (otherPlayerId:%d, otherPlayerJoinIndex:%d, otherPlayerAddr:%s)\n", pR.Id, playerId, peerJoinIndex, remote, otherPlayer.Id, otherPlayer.JoinIndex, otherPlayer.BattleUdpTunnelAddr)) } } - pR.OnBattleCmdReceived(pReq) // To help advance "pR.LastAllConfirmedInputFrameId" asap + pR.OnBattleCmdReceived(pReq, true) // To help advance "pR.LastAllConfirmedInputFrameId" asap, and even if "pR.LastAllConfirmedInputFrameId" is not advanced due to packet loss, these UDP packets would help prefill the "InputsBuffer" with correct player "future inputs (compared to ws session)" such that when "forceConfirmation" occurs we have as many correct predictions as possible } } diff --git a/battle_srv/ws/serve.go b/battle_srv/ws/serve.go index cea53ef..93efea9 100644 --- a/battle_srv/ws/serve.go +++ b/battle_srv/ws/serve.go @@ -388,7 +388,7 @@ func Serve(c *gin.Context) { startOrFeedHeartbeatWatchdog(conn) case models.UPSYNC_MSG_ACT_PLAYER_CMD: startOrFeedHeartbeatWatchdog(conn) - pRoom.OnBattleCmdReceived(pReq) + pRoom.OnBattleCmdReceived(pReq, false) case models.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK: res := pRoom.OnPlayerBattleColliderAcked(int32(playerId)) if false == res {