local Bag_Model = {} local private = {} local EventSystem = require('Event/EventSystem') local item_op_pb = require('Proto/item_op_pb') local sell_item_pb = require 'Proto/sell_item_pb' local discard_item_pb = require 'Proto/discard_item_pb' local item_pb = require 'Proto/item_pb' --region -- **************** 数据部分 ******************* -- --需要提示的背包里的新格子ID列表 local _newTipIds={} local _newIdKey="NewItemIds" --背包页签存储的数据 key:Bag_Model.BagType, value:arr local _BagPageDataArr; --背包中格子数据{itemData} local _bagItemCellDataArr = {} --过期的物品存储 key:id, value:pagetype, cfgid, count local _expireItemArr = {}; local _hasNewExpireItem = false; --合成物品的字典 key 物品碎片 value 可合成的物品 缓存起来不用每次查找遍历 local batchItemDict = {} --变化的物品,临时用来派发事件用,用完清空 local _totalUpdateItemCfgIds = {} --英雄置换反悔道具额外信息 local _heroSubstituteItemExtraData = {} --endregion function Bag_Model.OnStartup() NetManager.RegisterMsgCB(MessageEnums.MessageUseItemByCfgId, private.UseItemByCfgIdResp) NetManager.RegisterMsgCB(MessageEnums.MessageUseItem, private.UseItemResp) NetManager.RegisterMsgCB(MessageEnums.MessageUseHeroSubstituteItem, private.UseHeroSubstituteItemResp) NetManager.RegisterMsgCB(MessageEnums.MessageSellItem, private.SellItemResponse) NetManager.RegisterMsgCB(MessageEnums.MessageDiscardOverdueItem, private.DiscardOverdueItemResp) NetManager.RegisterMsgCB(MessageEnums.MessageItemCompose, private.OnItemCompose) --背包分页类型(装备不在背包中) Bag_Model.BagType = {Consumables = 1, Materials = 2, Fragments = 3, Pet = 4}; Bag_Model.BagTypeTabData = { {pageType = Bag_Model.BagType.Consumables, pageTextId = "IDS_Bag_Consume"}, {pageType = Bag_Model.BagType.Materials, pageTextId = "IDS_Bag_Material"}, {pageType = Bag_Model.BagType.Fragments, pageTextId = "IDS_Bag_Fragment"}, {pageType = Bag_Model.BagType.Pet, pageTextId = "IDS_Pet"} }; if GameAppInfo.IsVietnamPackage() then Bag_Model.BagType = {Consumables = 1, Materials = 2, Fragments = 3} Bag_Model.BagTypeTabData = { {pageType = Bag_Model.BagType.Consumables, pageTextId = "IDS_Bag_Consume"}, {pageType = Bag_Model.BagType.Materials, pageTextId = "IDS_Bag_Material"}, {pageType = Bag_Model.BagType.Fragments, pageTextId = "IDS_Bag_Fragment"}, } end _BagPageDataArr = {}; for __, bagType in pairs(Bag_Model.BagType) do _BagPageDataArr[bagType] = {}; end Bag_Model.ItemOperType = {UpdateAll = 1, AddOneItem = 2, UpdateOneItem = 3, DeleteOneItem=4}; Bag_Model.ItemIconPathTemplete = ConstAssetPathConfig.ItemIconPath; --道具底色枚举 Bag_Model.ItemColorName={"green","blue","purple","orange","red","yellow"} --道具底色背景枚举 Bag_Model.ItemColorBgName={"greenBg","blueBg","purpleBg","orangeBg","redBg","yellowBg"} --道具合成数据初始化 for i, v in DataSheetManager.ItemCompose:GetEnumerator() do for _, item in ipairs(v.Item_Table) do batchItemDict[item.ItemID] = v.ID end end private.IsHasInitBagItems = false Bag_Model.IsNeedDelayShowHeroSubstituteReward = false end function Bag_Model.OnShutdown() if private.IsHasInitBagItems then private.SaveNewTipIds() end end --根据道具ID获取某一个格子里的道具数量 function Bag_Model.GetItemCountInOneCell(itemId) --道具数据 local itemData = DataSheetManager.ItemData:GetDataByID(itemId) local itemList = _BagPageDataArr[itemData.BagType]; if itemList == nil then return 0 end if itemList and table.getn(itemList)>0 then for i = 1, #itemList do if(itemList[i].CfgId==itemId) then return itemList[i].Count end end end return 0 end function Bag_Model.GetItemCount(itemId) local itemData = DataSheetManager.ItemData:GetDataByID(itemId) local itemList = _BagPageDataArr[itemData.BagType]; if itemList == nil then return 0 end local count = 0 if itemList and table.getn(itemList)>0 then for i = 1, #itemList do if(itemList[i].CfgId==itemId) then count = count + itemList[i].Count end end end return count end function Bag_Model.GetOneCellItemCount(itemId, id) local itemData = DataSheetManager.ItemData:GetDataByID(itemId) local itemList = _BagPageDataArr[itemData.BagType] if itemList and table.getn(itemList) > 0 then for _, item in ipairs(itemList) do if item.Id == id then return item.Count end end end return 0 end --获取道具 function Bag_Model.GetItemInOneCell(itemId) --道具数据 local itemData = DataSheetManager.ItemData:GetDataByID(itemId) local itemList = _BagPageDataArr[itemData.BagType]; if itemList == nil then return nil end if itemList and table.getn(itemList)>0 then for i = 1, #itemList do if(itemList[i].CfgId==itemId) then return itemList[i] end end end return nil end -- 根据物品ID获取全部道具数据 function Bag_Model.GetItemsByCfgId(cfgId) local itemData = DataSheetManager.ItemData:GetDataByID(cfgId) local itemList = _BagPageDataArr[itemData.BagType] local items = {} if itemList and table.getn(itemList) > 0 then for _, item in ipairs(itemList) do if item.CfgId == cfgId then table.insert(items, item) end end end return items end --获取可合成道具id function Bag_Model.GetBatchItemId(id) return batchItemDict[id] end ----------------------------------过期道具处理---------------------------- --检测过期的道具 function Bag_Model.CheckExpireItems() local curServerTime = UTL.Time.GetServerTimestamp(); for pageType, pageTypeDatas in pairs(_BagPageDataArr) do for __, itemData in ipairs(pageTypeDatas) do if itemData.ExpireTime > 0 and itemData.ExpireTime - curServerTime<=0 then private.AddOneExpireItem(pageType, itemData); end end end end function private.AddOneExpireItem(pageType, itemData) if not _expireItemArr[itemData.Id] then _hasNewExpireItem = true; _expireItemArr[itemData.Id] = {pageType = pageType, cfgId = itemData.CfgId, count = itemData.Count, sendServer = false}; end end function Bag_Model.GetExpireItems() return _expireItemArr; end function Bag_Model.ClearExpireItems() table.clear(_expireItemArr); end function Bag_Model.DiscardOverdueItemReq() if not _hasNewExpireItem then return; end _hasNewExpireItem = false; local msg = discard_item_pb.DiscardOverdueItemReq(); for deleteId, deleteValue in pairs(_expireItemArr) do if not deleteValue.sendServer then local discardData = item_pb.ItemsIdToBagType(); discardData.id = deleteId; discardData.bagType = deleteValue.pageType; table.insert(msg.items, discardData); deleteValue.sendServer = true; end end NetManager.SendMessage(MessageEnums.MessageDiscardOverdueItem, msg) end function private.DiscardOverdueItemResp(msgResp) logging.log(LTAG.LOG, "DiscardOverdueItemResp",msgResp) if msgResp.Resp.Code == 0 then end end ---------------------背包新格子数据操作------------------------------------- function Bag_Model.IsNewTip(id) return false and table.containValue(_newTipIds,id) end function private.InsertNewTipIds(id) table.insert(_newTipIds,id) end function Bag_Model.ClearAllNewTips() table.clear(_newTipIds) end function Bag_Model.RemoveOneNewTip(id) for i,v in ipairs(_newTipIds) do if v == id then table.remove(_newTipIds,i) return end end end function private.InitNewTipIds() local idsString= PersistentData.PlayerData:Get(_newIdKey, "") _newTipIds=string.split(idsString,",") end function private.SaveNewTipIds() if(_newTipIds and #_newTipIds >0) then local result="" for i = 1, #_newTipIds do if(i==1) then result=_newTipIds[i] else result=result..",".._newTipIds[i] end end PersistentData.PlayerData:Set(_newIdKey, result, true) else PersistentData.PlayerData:Set(_newIdKey, "", true) end end --region -- **************** 和服务器交互 ******************* -- --初始化背包数据,此时不派发事件 function Bag_Model.SetBagInfo(materials, fragments, consumables, pets) private.IsHasInitBagItems = true private.InitNewTipIds() _BagPageDataArr[Bag_Model.BagType.Materials] = private.SetBagListItems(materials); _BagPageDataArr[Bag_Model.BagType.Fragments] = private.SetBagListItems(fragments); _BagPageDataArr[Bag_Model.BagType.Consumables] = private.SetBagListItems(consumables); if not GameAppInfo.IsVietnamPackage() then _BagPageDataArr[Bag_Model.BagType.Pet] = private.SetBagListItems(pets); end private.SortBagInfo() end --初始化背包英雄置换反悔道具额外信息数据 function Bag_Model.SetBagHeroSubstituteItemInfo(heroSubstituteItemExtra) for _, v in ipairs(heroSubstituteItemExtra) do _heroSubstituteItemExtraData[v.id] = { hero1ID = v.hero1ID, hero2ID = v.hero2ID, } end end --更新背包英雄置换反悔道具额外信息数据 function Bag_Model.UpdateBagHeroSubstituteItemExtra(heroSubstituteItemExtra) for _, v in ipairs(heroSubstituteItemExtra) do if not _heroSubstituteItemExtraData[v.id] then _heroSubstituteItemExtraData[v.id] = { hero1ID = v.hero1ID, hero2ID = v.hero2ID, } end end end --将服务器发过来的消息转换为本地存储结构存(这里来自C#的List的数据,特殊处理) function private.SetBagListItems(items) local result={} local itemCount = items ~= nil and table.getn(items) or 0; for i = 1, itemCount, 1 do result[i]={} result[i].Id=items[i].id result[i].CfgId=items[i].cfgId result[i].Count=items[i].count result[i].ExpireTime=items[i].expireTime result[i].binding=items[i].binding end return result end --新增或更新背包信息(增量更新) function Bag_Model.UpdateOrAddBagInfo(msgId, bagInfo) if not IsProtoDataNotNil(bagInfo.materials) and not IsProtoDataNotNil(bagInfo.shreds) and not IsProtoDataNotNil(bagInfo.consumables) and not IsProtoDataNotNil(bagInfo.pets) then return end _BagPageDataArr[Bag_Model.BagType.Materials] = private.UpdateBagInfoByData(_BagPageDataArr[Bag_Model.BagType.Materials], bagInfo.materials) _BagPageDataArr[Bag_Model.BagType.Fragments] = private.UpdateBagInfoByData(_BagPageDataArr[Bag_Model.BagType.Fragments], bagInfo.shreds) _BagPageDataArr[Bag_Model.BagType.Consumables] = private.UpdateBagInfoByData(_BagPageDataArr[Bag_Model.BagType.Consumables], bagInfo.consumables) if not GameAppInfo.IsVietnamPackage() then _BagPageDataArr[Bag_Model.BagType.Pet] = private.UpdateBagInfoByData(_BagPageDataArr[Bag_Model.BagType.Pet], bagInfo.pets) end private.SortBagInfo() --TODO 临时优化方案,未来需要将道具变化事件拆分成更细粒度,各个模块只监听自己需要的道具事件,避免无必要的响应 if msgId ~= MessageEnums.MessageTreasureSoulSlotRefresh then EventSystem.Dispatch(EventID.BagItem_Update) end CTL.Bag.CheckAndDispatchItemEvent(msgId, _totalUpdateItemCfgIds) table.clearArray(_totalUpdateItemCfgIds) end function private.UpdateBagInfoByData(base,new) if(not new or table.getn(new)==0) then return base end local oldIds={} for i = 1, #base do table.insert(oldIds, base[i].Id) end local newIds={} for i = 1, #new do table.insert(newIds,new[i].id) table.insert(_totalUpdateItemCfgIds, new[i].cfgId) end local updateData={} for i = 1, #newIds do if table.containValue(oldIds,newIds[i]) then updateData[new[i].id]=new[i] else private.AddOneItem(base, new[i]); end end for __, updateItem in pairs(updateData) do private.UpdateOneItem(base, updateItem); end return base end function private.AddOneItem(srcArr, serverItem) -- private.InsertNewTipIds(serverItem.Id) local index=table.getn(srcArr)+1 srcArr[index] = {}; srcArr[index].Id = serverItem.id srcArr[index].CfgId = serverItem.cfgId srcArr[index].Count = serverItem.count srcArr[index].ExpireTime = serverItem.expireTime srcArr[index].binding = serverItem.binding -- 显示外显窗口和Tips CTL.Bag.ShowGainItem(serverItem.cfgId) EventSystem.Dispatch(EventID.Bag_OperateItem, Bag_Model.ItemOperType.AddOneItem, srcArr[index]); end function private.UpdateOneItem(srcArr, serverItem) for i = 1, #srcArr do if srcArr[i].Id == serverItem.id then -- 显示在原有上新增的物品的TIPS local countNum = serverItem.count - srcArr[i].Count srcArr[i].Count = serverItem.count srcArr[i].ExpireTime = serverItem.expireTime srcArr[i].binding = serverItem.binding; if(countNum >= 1) then CTL.Bag.ShowGainItem(serverItem.cfgId) end EventSystem.Dispatch(EventID.Bag_OperateItem, Bag_Model.ItemOperType.UpdateOneItem, srcArr[i]); return; end end end --删除背包信息 function Bag_Model.DeleteBagInfo(msgId, bagInfo) if not IsProtoDataNotNil(bagInfo.materials) and not IsProtoDataNotNil(bagInfo.shreds) and not IsProtoDataNotNil(bagInfo.consumables) and not IsProtoDataNotNil(bagInfo.pets) then return end private.DeleteDataByPageType(Bag_Model.BagType.Materials, bagInfo.materials); private.DeleteDataByPageType(Bag_Model.BagType.Fragments, bagInfo.shreds); private.DeleteDataByPageType(Bag_Model.BagType.Consumables, bagInfo.consumables); if not GameAppInfo.IsVietnamPackage() then private.DeleteDataByPageType(Bag_Model.BagType.Pet, bagInfo.pets); end private.SortBagInfo() EventSystem.Dispatch(EventID.BagItem_Update) CTL.Bag.CheckAndDispatchItemEvent(msgId, _totalUpdateItemCfgIds) table.clearArray(_totalUpdateItemCfgIds) end function private.DeleteDataByPageType(pageType, deleteItems) local srcPageItems = Bag_Model.GetItemDataByPageType(pageType); if not srcPageItems then return; end if not deleteItems or table.getn(deleteItems) <= 0 then return; end for i = 1, table.getn(deleteItems) do private.DeleteBagInfoById(srcPageItems, deleteItems[i]); end end function private.DeleteBagInfoById(array,id) if(not array or table.getn(array)==0) then return end --查找要删除的元素 local index=-1 for i = 1, #array do if array[i].Id == id then index= i end end --找到就删除 local deleteItem = array[index]; if(index>0) then table.remove(array,index) Bag_Model.RemoveOneNewTip(id) table.insert(_totalUpdateItemCfgIds, deleteItem.CfgId) end EventSystem.Dispatch(EventID.Bag_OperateItem, Bag_Model.ItemOperType.DeleteOneItem, deleteItem); end function Bag_Model.GetItemDataByPageType(pageType) return _BagPageDataArr[pageType]; end function Bag_Model.GetHeroReSubstituteItemExtraDataById(id) return _heroSubstituteItemExtraData[id] end ------------------------Item操作------------------------------------------ function Bag_Model.UseItemByCfgIdReq(cfgId, count, selfSelectGiftItems) local msg = item_op_pb.UseItemByCfgIdReq() msg.cfgId = cfgId msg.count = count --自选礼包数据 if selfSelectGiftItems ~= nil then for __, value in ipairs(selfSelectGiftItems) do local placeData = item_op_pb.PlaceToCount() placeData.place = value.place; placeData.count = value.count; table.insert(msg.placeData, placeData); end end NetManager.SendMessage(MessageEnums.MessageUseItemByCfgId, msg) EventSystem.Dispatch(EventID.BI_UseItem, cfgId) end function private.UseItemByCfgIdResp(msgResp) logging.log(LTAG.LOG, "UseItemByCfgIdResponse",msgResp) if msgResp.Resp.Code == 0 then if msgResp.combineIDSId > 0 then CTL.Tips.AddTipsMsg(UTL.String.FormatCombineTextByID(msgResp.combineIDSId)) end end end -- 使用道具请求 function Bag_Model.UseItemReq(id, count, bagType) local msg = item_op_pb.UseItemReq() msg.id = id-- 实例id msg.count = count--数量 msg.bagTyp= bagType --背包类型 NetManager.SendMessage(MessageEnums.MessageUseItem, msg) end function private.UseItemResp(msgResp) logging.log(LTAG.LOG, "UseItemResponse", msgResp) if msgResp.Resp.Code == 0 then end end Bag_Model.HeroSubstituteType = { substitute = item_op_pb.substituteType, -- 武将置换 regret = item_op_pb.regret, -- 武将置换后悔 } -- 使用武将置换道具请求 function Bag_Model.UseHeroSubstituteItemReq(id, heroId1, heroId2, type) Bag_Model.IsNeedDelayShowHeroSubstituteReward = true local msg = item_op_pb.UseHeroSubstituteItemReq() msg.id = id -- 道具实例id msg.heroId1 = heroId1 msg.heroId2 = heroId2 msg.type = type NetManager.SendMessage(MessageEnums.MessageUseHeroSubstituteItem, msg) end function private.UseHeroSubstituteItemResp(msgResp) if msgResp.Resp.Code == 0 then local isRegretSubstitute = msgResp.type == Bag_Model.HeroSubstituteType.regret UIManager.OpenView(Const_UI_Lua.UIEnum.UIHeroSubstituteSuccess,{isRegretSubstitute = isRegretSubstitute, heroId1 = msgResp.heroId1, heroId2 = msgResp.heroId2}) EventSystem.Dispatch(EventID.UI_HeroSubstitute_Success) end end --出售道具请求 function Bag_Model.SellItemReq(id, count, bagType) local msg = sell_item_pb.SellItemReq() msg.id = id msg.count = count msg.bagType = bagType NetManager.SendMessage(MessageEnums.MessageSellItem, msg) end --出售道具Rsp function private.SellItemResponse(msgResp) logging.log(LTAG.LOG, "SellItemResponse", msgResp) if msgResp.Resp.Code == 0 then end end function private.IsBagEmpty() for __, pageTypeDatas in pairs(_BagPageDataArr) do if table.getn(pageTypeDatas)>0 then return false; end end return true; end --背包排序逻辑 local _sortBagFunction=function(a , b) local sortA = DataSheetManager.ItemData:GetDataByID(a.CfgId).SortId local sortB = DataSheetManager.ItemData:GetDataByID(b.CfgId).SortId if sortA == sortB then if a.CfgId == b.CfgId then return a.Count > b.Count else return a.CfgId < b.CfgId end else return sortA0 then table.sort(pageTypeDatas , _sortBagFunction) end end end --物品合成 function Bag_Model.ItemComposeReq(itemId, count) local msg = item_op_pb.ItemComposeReq() msg.itemId = itemId msg.count = count NetManager.SendMessage(MessageEnums.MessageItemCompose, msg) end function private.OnItemCompose(msgResp) end --endregion ----------------------------------背包界面逻辑---------------------------- function Bag_Model.GetBagDisplayDataByType(currentShowItemType) local lastTotalCount = table.getn(_bagItemCellDataArr); local pageTypeDatas = _BagPageDataArr[currentShowItemType]; local itemCount = table.getn(pageTypeDatas); -- local rowCount = math.ceil(itemCount/7)+5; local totalCount = itemCount;--rowCount * 7; for i=1, totalCount do if _bagItemCellDataArr[i] then _bagItemCellDataArr[i].itemData = pageTypeDatas[i]; else _bagItemCellDataArr[i] = {itemData = pageTypeDatas[i]}; end end for i=lastTotalCount, totalCount+1, -1 do table.remove(_bagItemCellDataArr, i); end return _bagItemCellDataArr; end function Bag_Model.ClearBagDisplayData() for __, bagCellData in ipairs(_bagItemCellDataArr) do bagCellData.itemData = nil; end end return Bag_Model