System.register(["__unresolved_0", "cc"], function (_export, _context) {
  "use strict";

  var _reporterNs, _cclegacy, FrameSyncExecutor, _crd;

  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

  function _reportPossibleCrUseOfGameClient(extras) {
    _reporterNs.report("GameClient", "../../shared/gameClient/gameClient", _context.meta, extras);
  }

  function _reportPossibleCrUseOfConnectionInputOperate(extras) {
    _reporterNs.report("ConnectionInputOperate", "../../shared/gameClient/GameSyncFrame", _context.meta, extras);
  }

  function _reportPossibleCrUseOfGameSyncFrame(extras) {
    _reporterNs.report("GameSyncFrame", "../../shared/gameClient/GameSyncFrame", _context.meta, extras);
  }

  function _reportPossibleCrUseOfMsgAfterFrames(extras) {
    _reporterNs.report("MsgAfterFrames", "../../shared/gameClient/protocols/MsgAfterFrames", _context.meta, extras);
  }

  function _reportPossibleCrUseOfMsgSyncFrame(extras) {
    _reporterNs.report("MsgSyncFrame", "../../shared/gameClient/protocols/MsgSyncFrame", _context.meta, extras);
  }

  _export("FrameSyncExecutor", void 0);

  return {
    setters: [function (_unresolved_) {
      _reporterNs = _unresolved_;
    }, function (_cc) {
      _cclegacy = _cc.cclegacy;
    }],
    execute: function () {
      _crd = true;

      _cclegacy._RF.push({}, "9a442kR9khHO41neTdH+ghr", "FrameSyncExecutor", undefined);

      /**帧同步执行器,对接帧同步的实现*/
      _export("FrameSyncExecutor", FrameSyncExecutor = class FrameSyncExecutor {
        /**当前执行到的帧索引*/

        /**执行帧已经停止*/

        /**最大可执行帧索引*/

        /**
         * 
         * @date 2022/2/21 - 下午3:43:43
         *
         * @constructor
         * @param inputHandler 输入帧处理器,实现函数: execInput_<操作类型>(connId: string, inputFrame: ConnectionInputOperate, dt: number)
         * @param onSyncStateData 触发追帧时,需要同步状态数据,可以当作重新初始化游戏数据,一般只发生在刚连上服务器或断线重连成功时
         * @param onExecFrame 执行每一帧的回调,数据帧和渲染帧要区分开来
         * @param getSyncState 当要求状态同步时,需要返回当前状态数据, 方便快速追帧, 不传表示禁用本功能
         */
        constructor(gameClient, inputHandler, onSyncStateData, onExecFrame, getSyncState) {
          _defineProperty(this, "inputHandler", void 0);

          _defineProperty(this, "serverSyncFrameRate", 60);

          _defineProperty(this, "renderFrameInvMs", 1000 / this.serverSyncFrameRate);

          _defineProperty(this, "renderFrameDt", 1 / this.serverSyncFrameRate);

          _defineProperty(this, "afterFrames", []);

          _defineProperty(this, "stateData", null);

          _defineProperty(this, "stateFrameIndex", -1);

          _defineProperty(this, "executeFrameIndex", -1);

          _defineProperty(this, "executeFrameStop", true);

          _defineProperty(this, "executeNextFrameHandler", void 0);

          _defineProperty(this, "executeNextFrameTimerHD", 0);

          _defineProperty(this, "gameClient", void 0);

          _defineProperty(this, "maxCanRenderFrameIndex", -1);

          _defineProperty(this, "onSyncStateData", void 0);

          _defineProperty(this, "onExecFrame", void 0);

          _defineProperty(this, "getSyncState", void 0);

          this.gameClient = gameClient;
          this.inputHandler = inputHandler;
          this.onSyncStateData = onSyncStateData;
          this.onExecFrame = onExecFrame;
          this.getSyncState = getSyncState;
          this.executeNextFrameHandler = this.executeNextFrame.bind(this);
          gameClient.client.listenMsg("AfterFrames", msg => {
            this.onMsgAfterFrames(msg);
          });
          gameClient.client.listenMsg("SyncFrame", msg => {
            this.onSyncFrame(msg);
          });
          gameClient.client.listenMsg("RequireSyncState", msg => {
            if (this.getSyncState) {
              const stateData = this.getSyncState();
              const stateFrameIndex = this.executeFrameIndex;
              const arrIndexEnd = this.getAfterFramesArrIndex(stateFrameIndex);
              this.stateData = stateData;
              this.stateFrameIndex = stateFrameIndex;
              this.afterFrames.splice(0, arrIndexEnd);
              gameClient.client.sendMsg("SyncState", {
                stateData: stateData,
                stateFrameIndex: stateFrameIndex
              });
            }
          });
        }

        async dispose() {
          var _this$gameClient;

          this.stopExecuteFrame();
          await ((_this$gameClient = this.gameClient) === null || _this$gameClient === void 0 ? void 0 : _this$gameClient.disconnect());
        }

        onMsgAfterFrames(msg) {
          var _this$onSyncStateData;

          this.serverSyncFrameRate = msg.serverSyncFrameRate;
          this.renderFrameInvMs = 1000 / this.serverSyncFrameRate;
          this.renderFrameDt = 1 / this.serverSyncFrameRate;
          this.afterFrames = msg.afterFrames;
          this.stateData = msg.stateData;
          this.stateFrameIndex = msg.stateFrameIndex;
          this.maxCanRenderFrameIndex = msg.maxSyncFrameIndex;
          this.executeFrameIndex = this.stateFrameIndex;
          (_this$onSyncStateData = this.onSyncStateData) === null || _this$onSyncStateData === void 0 ? void 0 : _this$onSyncStateData.call(this, this.stateData);

          if (this.executeFrameStop) {
            //如果执行已经停下来,则开始执行
            this.executeNextFrame();
          }
        }

        onSyncFrame(frame) {
          const arrIndex = this.getAfterFramesArrIndex(frame.frameIndex);
          this.afterFrames[arrIndex] = frame.syncFrame;

          if (this.maxCanRenderFrameIndex + 1 == frame.frameIndex) {
            //同步下来的帧,是按顺序的,直接更新最大可执行帧索引
            this.maxCanRenderFrameIndex = frame.frameIndex; //正常tcp通讯,数据包顺序不会错乱,但为了防止错乱,这里做一下处理
            //接下去判断之后的是否不为空,直接推到不为空的前一个索引

            for (let fi = this.maxCanRenderFrameIndex + 1, i = this.getAfterFramesArrIndex(fi); i < this.afterFrames.length; fi++, i++) {
              if (this.afterFrames[i]) {
                this.maxCanRenderFrameIndex = fi;
              } else {
                break;
              }
            }
          }

          if (this.executeFrameStop) {
            //如果执行已经停下来,则开始执行
            this.executeNextFrame();
          }
        }

        getAfterFramesArrIndex(frameIndex) {
          return frameIndex - this.stateFrameIndex - 1;
        }
        /**执行一帧服务端的同步帧,并返回是否执行完所有帧了*/


        executeOneFrame(dt) {
          var _this$onExecFrame;

          const frameIndex = this.executeFrameIndex + 1;
          if (frameIndex > this.maxCanRenderFrameIndex) return true;
          this.executeFrameIndex = frameIndex;
          const arrIndex = this.getAfterFramesArrIndex(frameIndex);
          const frame = this.afterFrames[arrIndex];

          if (!frame) {
            console.error(`this.afterFrames[${arrIndex}]为空,frameIndex:${frameIndex}`);
          } else {
            const inputs = frame.connectionInputs;

            if (inputs) {
              for (let i = 0; i < inputs.length; i++) {
                const inp = inputs[i];

                for (let j = 0; j < inp.operates.length; j++) {
                  const op = inp.operates[j];
                  const fn = this.inputHandler['execInput_' + op.inputType];
                  if (fn) fn.call(this.inputHandler, inp.connectionId, op, dt);
                }
              }
            }
          }

          (_this$onExecFrame = this.onExecFrame) === null || _this$onExecFrame === void 0 ? void 0 : _this$onExecFrame.call(this, dt, frameIndex);

          if (frameIndex >= this.maxCanRenderFrameIndex) {
            return true;
          } else {
            return false;
          }
        }
        /**执行下一帧,并且自动根据情况执行之后的帧,执行完则自动停下来,设置renderFrameStop=true*/


        executeNextFrame() {
          //处理帧信息
          if (this.executeOneFrame(this.renderFrameDt)) {
            //已经执行完所有帧了,等待服务器新消息
            this.executeFrameStop = true;
            return;
          } //为执行的帧数


          const unRenderFrameCount = this.stateFrameIndex + 1 + this.afterFrames.length - this.executeFrameIndex; //根据性能动态计算,下一帧要执行的间隔

          let frameInv = 0;

          if (unRenderFrameCount > 10) {
            //当缓存帧过多时,一次处理多个帧信息(卡着线程处理,会让有些物理引擎计算偏差)
            for (let i = 0; i < unRenderFrameCount; i++) {
              if (this.executeOneFrame(this.renderFrameDt)) {
                //已经执行完所有帧了,等待服务器新消息
                this.executeFrameStop = true;
                return;
              }
            }

            frameInv = 0;
          } else if (unRenderFrameCount > 3) {
            //相差一点,开始追帧(setTimetout 0,不卡死又能快速执行)
            frameInv = 0;
          } else {
            //正常速度
            frameInv = this.renderFrameInvMs;
          }

          if (this.executeFrameStop) return;
          /*
          //累计1k清理一波过期帧
          if (this.currFrameIndex > 1000) {
              this.frames.splice(0, this.currFrameIndex);
              this.currFrameIndex = 0;
          }
          */

          this.executeNextFrameTimerHD = setTimeout(this.executeNextFrameHandler, frameInv);
        }

        stopExecuteFrame() {
          this.executeFrameStop = true;
          clearTimeout(this.executeNextFrameTimerHD);
        }

        sendInputFrames(ops) {
          var _this$gameClient2;

          //正常输入实现,应当:即时操作推到一个数组,定时器发送然后清空
          (_this$gameClient2 = this.gameClient) === null || _this$gameClient2 === void 0 ? void 0 : _this$gameClient2.client.sendMsg("InpFrame", {
            operates: ops
          });
        }

        sendInputFrame(op) {
          var _this$gameClient3;

          //正常输入实现,应当:即时操作推到一个数组,定时器发送然后清空
          (_this$gameClient3 = this.gameClient) === null || _this$gameClient3 === void 0 ? void 0 : _this$gameClient3.client.sendMsg("InpFrame", {
            operates: [op]
          });
        }

      });

      _cclegacy._RF.pop();

      _crd = false;
    }
  };
});
//# sourceMappingURL=FrameSyncExecutor.js.map