local Replay_Model = {} local private = { cacheReplayBytesList = {}, -- 回放数据拆分数据分段列表 } local fair_play_replay_pb = require "Proto.fair_play_replay_pb" local EventSystem = require('Event/EventSystem') local rank_pb = require 'Proto/rank_pb' Replay_Model.FairPlayType = { Solo = 0,--1v1 TVT = 1,--3v3 Boss = 2,-- bossChallenge } Replay_Model.FairPlayFightType = { fight = 0, --切磋 rank = 1, -- 排位赛 } function Replay_Model.OnStartup() -- 龙脉的超大数据使用 ↓ NetManager.RegisterMsgCB(MessageEnums.MessageG2CFairPlayReplay, private.OnG2CFairPlayReplay) --龙脉的超大数据使用 ↑ NetManager.RegisterMsgCB(MessageEnums.MessageFairPlayReplay, private.FairPlayReplayResp) NetManager.RegisterMsgCB(MessageEnums.MessageFairPlayMyRecordPanel, private.FairPlayMyRecordPanelResp) -- 战斗记录界面 NetManager.RegisterMsgCB(MessageEnums.MessageFairPlayMyRecordLike, private.FairPlayMyRecordLikeResp) -- 战斗记录喜欢 NetManager.RegisterMsgCB(MessageEnums.MessageFairPlayMyRecordReplay, private.FairPlayMyRecordReplayResp) -- 战斗记录回放 NetManager.RegisterMsgCB(MessageEnums.MessageFairPlayMyRecordSeasonPanel, private.FairPlayMyRecordSeasonPanelResp) -- 战斗记录赛季 NetManager.RegisterMsgCB(MessageEnums.MessageFairPlayHeroWinRate, private.FairPlayHeroWinRateResp) -- 武将胜率 NetManager.RegisterMsgCB(MessageEnums.MessageG2CImportantBattleList, private.G2CImportantBattleList) -- cheat专用获取重要比赛回放 EventSystem.Regist(EventID.UI_RefreshRankInfo, private.RefreshRankInfo) private.replayData = {} --回放二进制数据 private.AllRecords = {} --公平竞技战绩数据 private.seasonInfo = {} --公平竞技赛季信息 private.winRateInfo = {} --武将使用胜率数据,其实在private.seasonInfo[type].lists也是一样的数据。这里单独抽出来一个协议用作选将优化使用,不影响赛季信息逻辑 private.likeRecords = {} --收藏的战绩 end function Replay_Model.OnShutdown() private.replayData = nil private.AllRecords = nil private.seasonInfo = nil private.winRateInfo = nil private.likeRecords = nil end -- 下载或者重播 回放 请求 function Replay_Model.FairPlayReplayReq(rankType, replayId, url, isImportant) local msg = fair_play_replay_pb.FairPlayReplayReq() msg.rankType = rankType -- 请求的排行榜类型。 msg.replayId = replayId -- 目标数据唯一id。(RankPerRecordInfo.replayId) msg.isReplay = private.replayData[replayId] ~= nil if url ~= nil then msg.url = url -- 云服务器链接,重播时候不用传 end private.lastReplayId = replayId -- 非个人数据使用 if isImportant then msg.isImportant = isImportant --告知服务器只需要获取重要回放,减少服务器检索计算。cheat专用 end NetManager.SendMessage(MessageEnums.MessageFairPlayReplay, msg) end -- 给cheat使用 :如龙脉 function Replay_Model.C2GFairPlayReplayReq(rankType, replayId, url, isImportant) local msg = fair_play_replay_pb.C2GFairPlayReplay() msg.rankType = rankType -- 请求的排行榜类型。 msg.replayId = replayId -- 目标数据唯一id。(RankPerRecordInfo.replayId) msg.isReplay = private.replayData[replayId] ~= nil if url ~= nil then msg.url = url -- 云服务器链接,重播时候不用传 end private.lastReplayId = replayId -- 非个人数据使用 msg.isImportant = isImportant --告知服务器只需要获取重要回放,减少服务器检索计算。cheat专用 NetManager.SendMessage(MessageEnums.MessageC2GFairPlayReplay, msg) table.clear(private.cacheReplayBytesList) end -- 这个协议只有非个人回放时才会用到 function private.FairPlayReplayResp(msg) if msg.Resp.Code == 0 then local replayPlayerID = 1 --首次下载 if not msg.isReplay then private.replayData[private.lastReplayId] = msg.data --回放二进制数据 private.rankType = msg.rankType EventSystem.Dispatch(EventID.UI_Replay_PlayReplay,msg.data) CTL.Replay.StartPlay(msg.data, replayPlayerID) else --重播 EventSystem.Dispatch(EventID.UI_Replay_PlayReplay,private.GetFairPlayReplayDataById(private.lastReplayId)) if BattleDataGetter.IsReplayBattle() then CTL.Replay.ReplayAgain() else CTL.Replay.StartPlay(private.replayData[private.lastReplayId], replayPlayerID) end end end end -- 这个协议只有cheat:回放龙脉使用 function private.OnG2CFairPlayReplay(msg) table.insert(private.cacheReplayBytesList, msg.data) if not msg.IsEnd then return end local allBytes = table.concat(private.cacheReplayBytesList) table.clear(private.cacheReplayBytesList) local replayPlayerID = 1 --首次下载 if not msg.isReplay then private.replayData[private.lastReplayId] = allBytes --回放二进制数据 private.rankType = msg.rankType EventSystem.Dispatch(EventID.UI_Replay_PlayReplay,allBytes) CTL.Replay.StartPlay(allBytes, replayPlayerID) else --重播 EventSystem.Dispatch(EventID.UI_Replay_PlayReplay,private.GetFairPlayReplayDataById(private.lastReplayId)) if BattleDataGetter.IsReplayBattle() then CTL.Replay.ReplayAgain() else CTL.Replay.StartPlay(private.replayData[private.lastReplayId], replayPlayerID) end end end --我的战绩-战斗记录界面请求Req function Replay_Model.FairPlayMyRecordPanelReq(fairPlayType) local msg = fair_play_replay_pb.FairPlayMyRecordPanelReq() msg.typ = fairPlayType NetManager.SendMessage(MessageEnums.MessageFairPlayMyRecordPanel, msg) end --我的战绩-战斗记录界面请求Rsp function private.FairPlayMyRecordPanelResp(msg) if msg.Resp.Code == 0 then private.AllRecords[msg.typ] = msg.records --保存战绩 EventSystem.Dispatch(EventID.UI_FairPlayHistory_ShowBattle,msg.typ) CTL.Replay.TryDeleteFileButRecords(msg.allGRoomIds) end end --显示战绩(战斗结算界面)详情 Req function Replay_Model.ShowHistory(gRoomId,typ) if typ == Replay_Model.FairPlayType.Boss then logging.error(LTAG.ERROR, "Boss 挑战是不能查看战绩(战斗结果)的") end local find = false local records = private.AllRecords[typ] if records then for _, myRecord in ipairs(records) do if myRecord.gRoomId == gRoomId then find = true CTL.Replay.ShowBattleResult(typ, myRecord.battleResult) end end end if not find then logging.error(LTAG.ERROR, "我的数据中没有找到战斗结算信息 battleResult 。gRoomId = ",gRoomId, "Type = ", typ) end end -- 战斗记录喜欢 Req function Replay_Model.FairPlayMyRecordLikeReq(gRoomId,typ) if not LuaExt.FileExists(LuaConst.SaveReplayFileDirPath .. gRoomId) then --logging.error(LTAG.ERROR, "[gws] 上传本地数据时 ,发现本地根本没有这个数据文件 。gRoomId = ", gRoomId) CTL.Tips.AddTipsMsg(Const_IDS.IDS_FairPlay_Record_LoseCantUpload) return end local msg = fair_play_replay_pb.FairPlayMyRecordLikeReq() msg.data = CTL.Replay.GetFrameBytesFromFile(gRoomId) --战斗回放数据 msg.gRoomId = gRoomId --数据ID msg.typ = typ -- 1v1、3v3、无双挑战 NetManager.SendMessage(MessageEnums.MessageFairPlayMyRecordLike, msg) end -- 战斗记录喜欢 Rsp function private.FairPlayMyRecordLikeResp(msg) if msg.Resp.Code == 0 then local fairPlayType = msg.typ --1v1、3v3、无双挑战 local gRoomId = msg.gRoomId --数据id Replay_Model.UpdateRecordsLikeState(fairPlayType,gRoomId) CTL.Tips.AddTipsMsg(Const_IDS.IDS_FairPlay_Record_Upload) EventSystem.Dispatch(EventID.UI_FairPlayHistory_RefreshBattleInfo) end end -- 战斗记录回放 Req function Replay_Model.FairPlayMyRecordReplayReq(gRoomId,typ) local msg = fair_play_replay_pb.FairPlayMyRecordReplayReq() msg.gRoomId = gRoomId --数据ID msg.typ = typ -- 1v1、3v3、无双挑战 msg.isDownLoad = not LuaExt.FileExists(LuaConst.SaveReplayFileDirPath .. gRoomId) NetManager.SendMessage(MessageEnums.MessageFairPlayMyRecordReplay, msg) BIManager.DispatchBIClientEvent(BIManager.EventName.FairPlayMyRecordReplay, "gRoomId", gRoomId, "typ", typ, "isDownLoad", msg.isDownLoad) end -- 战斗记录回放 Rsp function private.FairPlayMyRecordReplayResp(msg) if msg.Resp.Code == 0 then CTL.Replay.TryReplayMyRecords(msg.gRoomId, msg.typ, msg.data) end end -- 战斗记录赛季 Req function Replay_Model.FairPlayMyRecordSeasonPanelReq(typ) local msg = fair_play_replay_pb.FairPlayMyRecordSeasonPanelReq() msg.typ = typ -- 1v1、3v3、无双挑战 NetManager.SendMessage(MessageEnums.MessageFairPlayMyRecordSeasonPanel, msg) end -- 战斗记录赛季 Rsp function private.FairPlayMyRecordSeasonPanelResp(msg) if msg.Resp.Code == 0 then private.seasonInfo[msg.typ] = msg.infos --赛季信息 EventSystem.Dispatch(EventID.UI_FairPlayHistory_SetCurrentSeasonIndex,msg.typ) EventSystem.Dispatch(EventID.UI_FairPlayHistory_ShowSeason,msg.typ) end end --获取一周重要战斗回放,目前只有cheat内部使用 function Replay_Model.NoticeC2GImportantBattle(type) local msg = fair_play_replay_pb.C2GImportantBattleList() msg.battleType = type private.tempImportantBattleType = type NetManager.SendMessage(MessageEnums.MessageC2GImportantBattleList, msg) end function private.G2CImportantBattleList(msg) EventSystem.Dispatch(EventID.UI_CheatReplay_RefreshList,msg.infos) end --战斗记录删除id function Replay_Model.SyncFairPlayMyRecordDelId(fairPlayMyRecordDelId) private.fairPlayMyRecordDelId = fairPlayMyRecordDelId CTL.Replay.TryDeleteFiles(fairPlayMyRecordDelId) end --重播 function Replay_Model.ReplayAgain() Replay_Model.FairPlayReplayReq(private.rankType,private.lastReplayId) end --获取回放的二进制数据 function private.GetFairPlayReplayDataById(replayId) local data = private.replayData[replayId] if data == nil then logging.error(LTAG.ERROR,"GetFairPlayReplayDataById not find",replayId) end return data end --请求榜单后, 刷新榜单数据 function private.RefreshRankInfo(rankType) --非回放类型榜单不处理 if rankType < MDL.Rank.RankType.FairPlayReplay1v1MyServer or rankType > MDL.Rank.RankType.FairPlayReplayBCAllServer then return end private.rankInfo = MDL.Rank.GetRankInfoDataByType(rankType) --缓存回放时间 private.timeArray = {} for i,v in ipairs(private.rankInfo) do if v.extraParamBytes ~= nil then local replayInfo = MDL.Replay.ParseRankPerRecordReplayInfoFromBytes(v.extraParamBytes) if replayInfo then private.timeArray[v.replayId] = replayInfo.fightTime end end end EventSystem.Dispatch(EventID.UI_Replay_RefreshRankInfo,private.rankInfo) end function private.GetTimeByReplayId(replayId) if replayId and private.timeArray then return private.timeArray[replayId] end end --解析战斗回放的信息 function Replay_Model.ParseRankPerRecordReplayInfoFromBytes(dataBytes) if dataBytes == nil then return nil end local recordReplayInfo = rank_pb.RankPerRecordReplayInfo() recordReplayInfo:ParseFromString(dataBytes) return recordReplayInfo end function Replay_Model.GetRankInfo() return private.rankInfo end function Replay_Model.GetCurBattleFightTime() local ret = BattleDataGetter.GetLevelTotalFrame() * LuaConst.TimeSpan --本地数据保底 if not CTL.Replay.IsReplayFromMyRecords() then -- 非个人数据,优先使用服务器数据 local serverData = private.GetTimeByReplayId(private.lastReplayId) if serverData then ret = serverData end end return ret end --获取战绩 function Replay_Model.GetAllRecordsByType(type) return private.AllRecords[type] end --清空缓存数据 function Replay_Model.ClearCacheData() table.clear(private.AllRecords) --清空缓存战绩 table.clear(private.seasonInfo) --清空缓存赛季 end --更新收藏状态 function Replay_Model.UpdateRecordsLikeState(typ,gRoomId) local records = Replay_Model.GetAllRecordsByType(typ) for i,v in ipairs(records) do if v.gRoomId == gRoomId then table.insert(private.likeRecords,gRoomId) end end end --辅助判断是否收藏 function Replay_Model.IsLike(gRoomId) return table.containValue(private.likeRecords,gRoomId) end --获取赛季信息 function Replay_Model.GetSeasonInfoByType(type) return private.seasonInfo[type] end --region 根据武将胜率信息来优化选将列表 --武将胜率信息(把赛季信息info里的lists单独提了出来 function Replay_Model.FairPlayHeroWinRateReq(typ) local msg = fair_play_replay_pb.FairPlayHeroWinRateReq() msg.typ = typ -- 1v1、3v3、无双挑战 NetManager.SendMessage(MessageEnums.MessageFairPlayHeroWinRate, msg) end function private.FairPlayHeroWinRateResp(msg) if msg.Resp.Code == 0 then local winRate = {} for _, v in ipairs(msg.list) do table.insert(winRate, { heroId = v.heroId, gameCount = v.gameCount, winCount = v.winCount }) end private.winRateInfo[msg.typ] = winRate EventSystem.Dispatch(EventID.UI_FairPlay_RefreshHeroWinRateInfo, msg.typ) end end --排序后的已解锁武将,不包括体验卡武将 function Replay_Model.GetSortedSelectHeroList(type) local sortedList = {} for i, v in ipairs(MDL.HeroSelect.GetHasHeroList()) do sortedList[i] = v end private.heroSelectSortType = type table.sort(sortedList, private.SortSelectHeroOrder) return sortedList end --已解锁武将(包括可用体验卡武将),公平竞技选将用 function Replay_Model.GetSortedAvailableSelectHeroList(type, isSort) private.heroSelectSortType = type local sortedList = {} for i, v in ipairs(MDL.HeroSelect.GetHasHeroList()) do sortedList[i] = v end -- 体验卡武将 if UTL.Item.GetItemStockCount(CTL.FairPlayCard.experienceCardId) > 0 then local unactiveGoldenHeros = MDL.HeroSelect.GetUnactiveGoldenHeroData() for _, v in ipairs(unactiveGoldenHeros) do local isTestHeroAndOpen = MDL.SyncSolo.CheckIsTestHero(v) local isTemporaryFreeHero = MDL.SyncSolo.CheckIsTemporaryFreeHero(v) if not isTestHeroAndOpen and not isTemporaryFreeHero then table.insert(sortedList, {heroId = v.ID}) end end end if isSort then table.sort(sortedList, private.SortSelectHeroOrder) end return sortedList end function private.SortSelectHeroOrder(infoA, infoB) local idA, idB = infoA.heroId, infoB.heroId local heroDataA = DataSheetManager.HeroNum:GetDataByID(idA) local heroDataB = DataSheetManager.HeroNum:GetDataByID(idB) if heroDataA.HeroQuality ~= heroDataB.HeroQuality then return heroDataA.HeroQuality > heroDataB.HeroQuality --1.按品质排序 else local countA, winRateA = private.GetHeroWinRateData(idA) local countB, winRateB = private.GetHeroWinRateData(idB) if countA ~= countB then return countA > countB --2.按使用次数排序 else if winRateA ~= winRateB then return winRateA > winRateB --3.按胜率排序 else return idA < idB --4.按ID排序 end end end end function private.GetHeroWinRateData(heroID) for _, v in ipairs(private.winRateInfo[private.heroSelectSortType]) do if heroID == v.heroId then return v.gameCount, v.winCount / v.gameCount --返回使用次数、胜率 end end return 0, 0 --这个将没用过 end function Replay_Model.ClearWinRateCacheData(type) if private.winRateInfo[type] then table.clear(private.winRateInfo[type]) end end --endregion 根据武将胜率信息来优化选将列表 function Replay_Model.GetLastWatchID() return private.lastWatchPlayerID end function Replay_Model.SetLastWatchID(playerID) private.lastWatchPlayerID = playerID end return Replay_Model