bag.lua 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. -- 资源
  2. local code = require "code"
  3. local gameConst = require("const.gameConst")
  4. local util_user = require("utils.util_user")
  5. local timeUtil = require("utils.timeUtil")
  6. local resAdapt = require("adapt.resAdapt")
  7. local moduleData = require("data.module")
  8. local MODULE_NAME = "bag"
  9. local root = {}
  10. -- 玩家资源初始化(新手物品初始化)
  11. function root:init(uid)
  12. local lastInitTime = self:_get_last_init_time(uid)
  13. -- 仅初始化1次
  14. if lastInitTime > 0 then
  15. return
  16. end
  17. local initConfig = resAdapt:get_init_conf()
  18. local initItems = {}
  19. for _, v in ipairs(initConfig) do
  20. table.arry_merge(initItems, v.items)
  21. end
  22. if #initItems > 0 then
  23. self:update_items(uid, initItems, "init")
  24. end
  25. local curTime = timeUtil.now(uid)
  26. self:_set_last_init_time(uid, curTime)
  27. end
  28. -- 请求获取背包信息
  29. function root:get_info(uid)
  30. log.info("get_info uid:%s", uid)
  31. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  32. local isUpdate = false
  33. local curTime = timeUtil.now(uid)
  34. for i = #(itemList or {}), 1, -1 do
  35. local item = itemList[i]
  36. if item.expTime and curTime > item.expTime then
  37. -- 已经过期
  38. isUpdate = true
  39. item.count = 0
  40. end
  41. if item.count == 0 then
  42. isUpdate = true
  43. table.remove(itemList, i)
  44. end
  45. end
  46. if isUpdate then
  47. -- 存储
  48. moduleData:hset(uid, MODULE_NAME, "itemList", itemList)
  49. end
  50. return itemList
  51. end
  52. --[[ 请求增减资源列表
  53. 返回的是 DataResUpdateItem 列表
  54. ]]
  55. function root:update_items(uid, items, reason)
  56. -- log.info("update_items uid:%s items:%s reason:%s", uid, tostring(items), tostring(reason))
  57. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  58. local list = {}
  59. for _, v in ipairs(items) do
  60. local updateItems = self:_update_item(uid, itemList, v.id, v.count, v.bid)
  61. if updateItems then
  62. table.arry_merge(list, updateItems)
  63. end
  64. end
  65. -- 存储
  66. moduleData:hset(uid, MODULE_NAME, "itemList", itemList)
  67. -- 推送
  68. self:_on_res_update(uid, list, reason)
  69. -- 事件
  70. self:_dispatch_event(uid, list)
  71. -- 日志-资源变化
  72. self:_log_resource(uid, list, reason)
  73. return list
  74. end
  75. -- 判断资源是否足够
  76. function root:is_enough(uid, items)
  77. -- 求和
  78. local tempMap = {}
  79. for _, v in ipairs(items) do
  80. if not tempMap[v.id] then
  81. tempMap[v.id] = v.count
  82. else
  83. tempMap[v.id] = tempMap[v.id] + v.count
  84. end
  85. end
  86. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  87. local ret = true
  88. for k, v in pairs(tempMap) do
  89. local item = table.key_find(itemList, "id", k)
  90. if not item or not item.count or item.count < v then
  91. ret = false
  92. break
  93. end
  94. end
  95. return ret
  96. end
  97. function root:is_enough_by_bid(uid, items)
  98. -- 求和
  99. local tempMap = {}
  100. for _, v in ipairs(items) do
  101. if not tempMap[v.bid] then
  102. tempMap[v.bid] = v.count
  103. else
  104. tempMap[v.bid] = tempMap[v.bid] + v.count
  105. end
  106. end
  107. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  108. local ret = true
  109. for k, v in pairs(tempMap) do
  110. local item = table.key_find(itemList, "bid", k)
  111. if not item or not item.count or item.count < v then
  112. ret = false
  113. break
  114. end
  115. end
  116. return ret
  117. end
  118. --[[ 增加资源
  119. 返回的是 DataResUpdateItem 列表
  120. ]]
  121. function root:add_items(uid, items, reason)
  122. return self:update_items(uid, items, reason)
  123. end
  124. --[[ 消耗资源。资源不足也会消耗,消耗到0为止
  125. 返回的是 DataResUpdateItem 列表
  126. ]]
  127. function root:consume_items(uid, items, reason)
  128. local tempList = {}
  129. for _, v in ipairs(items) do
  130. table.insert(tempList, {id = v.id, count = -v.count, bid = v.bid})
  131. end
  132. return self:update_items(uid, tempList, reason)
  133. end
  134. -- 获取资源数量
  135. function root:get_item_count(uid, itemId)
  136. -- log.info("get_item_count uid:%s itemId:%s", uid, itemId)
  137. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  138. local item = table.key_find(itemList, "id", itemId) or {}
  139. return item.count or 0
  140. end
  141. -- 获取资源数量
  142. function root:get_item_by_bid(uid, bid)
  143. -- log.info("get_item_by_bid uid:%s bid:%s", uid, bid)
  144. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  145. local item = table.key_find(itemList, "bid", bid) or {}
  146. return item
  147. end
  148. -- 已获得类型物品ID列表
  149. function root:get_own_type_item_id_list(uid, resType)
  150. if uid == nil or resType == nil then
  151. return
  152. end
  153. local resIdList = {}
  154. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  155. for k, v in ipairs(itemList) do
  156. if resAdapt:is_type(v.id, resType) then
  157. table.insert(resIdList, v.id)
  158. end
  159. end
  160. return resIdList
  161. end
  162. ----------------------------------------
  163. -- 以下是私有方法
  164. ----------------------------------------
  165. -- 获取新的bid
  166. function root:_new_bid(uid)
  167. local lastBid = moduleData:hget_int(uid, MODULE_NAME, "lastBid") or 0
  168. lastBid = lastBid + 1
  169. moduleData:hset(uid, MODULE_NAME, "lastBid", lastBid)
  170. return lastBid
  171. end
  172. -- 最后初始化资源的时间戳
  173. function root:_get_last_init_time(uid)
  174. return moduleData:hget_int(uid, MODULE_NAME, "lastInitTime") or 0
  175. end
  176. function root:_set_last_init_time(uid, timestamp)
  177. moduleData:hset(uid, MODULE_NAME, "lastInitTime", timestamp)
  178. end
  179. function root:_AddExpirationTime(resConfing, uid)
  180. -- 计算失效时间/过期时间,expiration time ==> expTime;
  181. local expTime
  182. if resConfing then
  183. local curTime = timeUtil.now(uid)
  184. if resConfing.activeDays then
  185. expTime = curTime + (expTime or 0) + 86400 * tonumber(resConfing.activeDays)
  186. end
  187. if resConfing.termOfValidity then
  188. expTime = curTime + (expTime or 0) + tonumber(resConfing.termOfValidity)
  189. end
  190. end
  191. return expTime
  192. end
  193. function root:_AddItemByBid(uid, itemList, itemId, count, bid, resConfing, composite)
  194. local item
  195. if count > 0 and composite then
  196. local newBid = self:_new_bid(uid)
  197. item = {
  198. id = itemId,
  199. count = 0,
  200. bid = newBid
  201. }
  202. table.insert(itemList, item)
  203. else
  204. -- 不可叠加的物品只能通过bid来获取,但只有装备是通过bid来获取.
  205. item = table.key_find(itemList, "bid", bid)
  206. if not item and not bid then
  207. item = table.key_find(itemList, "id", itemId)
  208. end
  209. end
  210. -- 都没有获取到,就新建一个.
  211. if not item then
  212. local newBid = self:_new_bid(uid)
  213. item = {
  214. id = itemId,
  215. count = 0,
  216. bid = newBid
  217. }
  218. table.insert(itemList, item)
  219. end
  220. local oldCount = item.count or 0
  221. local newCount = oldCount + count
  222. newCount = math.max(newCount, 0)
  223. item.count = newCount
  224. item.expTime = self:_AddExpirationTime(resConfing, uid)
  225. return {{id = itemId, deltaCount = count, count = newCount, bid = item.bid}}
  226. end
  227. -- 更新单个资源
  228. function root:_update_item(uid, itemList, itemId, count, bid)
  229. local conf = resAdapt:get_item_conf(itemId)
  230. if not conf then
  231. log.error("更新资源异常,未找到[%s]资源配置", tostring(itemId))
  232. return
  233. end
  234. return self:_AddItemByBid(uid, itemList, itemId, count, bid, conf, conf.enableComposite)
  235. end
  236. -- 推送资源变化
  237. function root:_on_res_update(uid, updateItems, reason)
  238. local msg = {
  239. reason = reason,
  240. items = updateItems
  241. }
  242. util_user:user_proto_notify(uid, "on_res_update", msg)
  243. end
  244. -- 资源变化事件
  245. function root:_dispatch_event(uid, updateItems)
  246. for _, v in ipairs(updateItems) do
  247. local conf = resAdapt:get_item_conf(v.id) or {}
  248. local evtParams = {
  249. times = 1,
  250. id = v.id,
  251. count = math.abs(v.deltaCount),
  252. add = v.deltaCount,
  253. type = conf.type,
  254. bId = v.bid,
  255. totalCount = v.count
  256. }
  257. util_user:user_dispatch_event(uid, gameConst.EVENT_ID.RES, evtParams)
  258. end
  259. end
  260. -- 资源变化事件
  261. function root:_log_resource(uid, updateItems, reason)
  262. for _, v in ipairs(updateItems) do
  263. util_user:log_resource(uid, reason, v.id, v.deltaCount, v.count)
  264. end
  265. end
  266. return root