bag.lua 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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 isExchangeDiamond = false
  79. local tempMap = {}
  80. for _, v in ipairs(items) do
  81. if not tempMap[v.id] then
  82. tempMap[v.id] = v.count
  83. else
  84. tempMap[v.id] = tempMap[v.id] + v.count
  85. end
  86. if v.id == gameConst.ITEM_ID.DIAMOND then
  87. isExchangeDiamond = true
  88. end
  89. end
  90. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  91. local ret = true
  92. for k, v in pairs(tempMap) do
  93. local item = table.key_find(itemList, "id", k)
  94. if not item or not item.count or item.count < v then
  95. ret = false
  96. break
  97. end
  98. end
  99. -- 转换绑金
  100. if ret == false and isExchangeDiamond then
  101. local item = table.key_find(itemList, "id", gameConst.ITEM_ID.DIAMOND)
  102. local addGold = tempMap[gameConst.ITEM_ID.DIAMOND]
  103. if item and not is_empty(item.count) then
  104. addGold = addGold - item.count
  105. end
  106. -- 增加金币消耗
  107. if addGold >= 0 then
  108. tempMap[gameConst.ITEM_ID.GOLD] = (tempMap[gameConst.ITEM_ID.GOLD] or 0) + addGold
  109. ret = true
  110. -- 重新检查是否充足
  111. for k, v in pairs(tempMap) do
  112. local _item = table.key_find(itemList, "id", k)
  113. if not _item or not _item.count or _item.count < v then
  114. ret = false
  115. break
  116. end
  117. end
  118. end
  119. if ret == true then
  120. -- 修改消耗物品列表
  121. local costItems = {}
  122. for k, v in pairs(tempMap) do
  123. table.insert(costItems, {id = k, count = v})
  124. end
  125. return true, costItems
  126. end
  127. end
  128. if ret == true then
  129. return true, items
  130. end
  131. return ret
  132. end
  133. function root:is_enough_by_bid(uid, items)
  134. -- 求和
  135. local tempMap = {}
  136. for _, v in ipairs(items) do
  137. if not tempMap[v.bid] then
  138. tempMap[v.bid] = v.count
  139. else
  140. tempMap[v.bid] = tempMap[v.bid] + v.count
  141. end
  142. end
  143. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  144. local ret = true
  145. for k, v in pairs(tempMap) do
  146. local item = table.key_find(itemList, "bid", k)
  147. if not item or not item.count or item.count < v then
  148. ret = false
  149. break
  150. end
  151. end
  152. return ret
  153. end
  154. --[[ 增加资源
  155. 返回的是 DataResUpdateItem 列表
  156. ]]
  157. function root:add_items(uid, items, reason)
  158. return self:update_items(uid, items, reason)
  159. end
  160. --[[ 消耗资源。资源不足也会消耗,消耗到0为止
  161. 返回的是 DataResUpdateItem 列表
  162. ]]
  163. function root:consume_items(uid, items, reason)
  164. local tempList = {}
  165. for _, v in ipairs(items) do
  166. table.insert(tempList, {id = v.id, count = -v.count, bid = v.bid})
  167. end
  168. return self:update_items(uid, tempList, reason)
  169. end
  170. -- 获取资源数量
  171. function root:get_item_count(uid, itemId)
  172. -- log.info("get_item_count uid:%s itemId:%s", uid, itemId)
  173. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  174. local item = table.key_find(itemList, "id", itemId) or {}
  175. return item.count or 0
  176. end
  177. -- 获取资源数量
  178. function root:get_item_by_bid(uid, bid)
  179. -- log.info("get_item_by_bid uid:%s bid:%s", uid, bid)
  180. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  181. local item = table.key_find(itemList, "bid", bid) or {}
  182. return item
  183. end
  184. -- 已获得类型物品ID列表
  185. function root:get_own_type_item_id_list(uid, resType)
  186. if uid == nil or resType == nil then
  187. return
  188. end
  189. local resIdList = {}
  190. local itemList = moduleData:hget_json(uid, MODULE_NAME, "itemList") or {}
  191. for k, v in ipairs(itemList) do
  192. if resAdapt:is_type(v.id, resType) then
  193. table.insert(resIdList, v.id)
  194. end
  195. end
  196. return resIdList
  197. end
  198. ----------------------------------------
  199. -- 以下是私有方法
  200. ----------------------------------------
  201. -- 获取新的bid
  202. function root:_new_bid(uid)
  203. local lastBid = moduleData:hget_int(uid, MODULE_NAME, "lastBid") or 0
  204. lastBid = lastBid + 1
  205. moduleData:hset(uid, MODULE_NAME, "lastBid", lastBid)
  206. return lastBid
  207. end
  208. -- 最后初始化资源的时间戳
  209. function root:_get_last_init_time(uid)
  210. return moduleData:hget_int(uid, MODULE_NAME, "lastInitTime") or 0
  211. end
  212. function root:_set_last_init_time(uid, timestamp)
  213. moduleData:hset(uid, MODULE_NAME, "lastInitTime", timestamp)
  214. end
  215. function root:_AddExpirationTime(resConfing, uid)
  216. -- 计算失效时间/过期时间,expiration time ==> expTime;
  217. local expTime
  218. if resConfing then
  219. local curTime = timeUtil.now(uid)
  220. if resConfing.activeDays then
  221. expTime = curTime + (expTime or 0) + 86400 * tonumber(resConfing.activeDays)
  222. end
  223. if resConfing.termOfValidity then
  224. expTime = curTime + (expTime or 0) + tonumber(resConfing.termOfValidity)
  225. end
  226. end
  227. return expTime
  228. end
  229. function root:_AddItemByBid(uid, itemList, itemId, count, bid, resConfing, composite)
  230. local item
  231. if count > 0 and composite then
  232. local newBid = self:_new_bid(uid)
  233. item = {
  234. id = itemId,
  235. count = 0,
  236. bid = newBid
  237. }
  238. table.insert(itemList, item)
  239. else
  240. -- 不可叠加的物品只能通过bid来获取,但只有装备是通过bid来获取.
  241. item = table.key_find(itemList, "bid", bid)
  242. if not item and not bid then
  243. item = table.key_find(itemList, "id", itemId)
  244. end
  245. end
  246. -- 都没有获取到,就新建一个.
  247. if not item then
  248. local newBid = self:_new_bid(uid)
  249. item = {
  250. id = itemId,
  251. count = 0,
  252. bid = newBid
  253. }
  254. table.insert(itemList, item)
  255. end
  256. local oldCount = item.count or 0
  257. local newCount = oldCount + count
  258. newCount = math.max(newCount, 0)
  259. item.count = newCount
  260. item.expTime = self:_AddExpirationTime(resConfing, uid)
  261. return {{id = itemId, deltaCount = count, count = newCount, bid = item.bid}}
  262. end
  263. -- 更新单个资源
  264. function root:_update_item(uid, itemList, itemId, count, bid)
  265. local conf = resAdapt:get_item_conf(itemId)
  266. if not conf then
  267. log.error("更新资源异常,未找到[%s]资源配置", tostring(itemId))
  268. return
  269. end
  270. return self:_AddItemByBid(uid, itemList, itemId, count, bid, conf, conf.enableComposite)
  271. end
  272. -- 推送资源变化
  273. function root:_on_res_update(uid, updateItems, reason)
  274. local msg = {
  275. reason = reason,
  276. items = updateItems
  277. }
  278. util_user:user_proto_notify(uid, "on_user_items", msg)
  279. end
  280. -- 资源变化事件
  281. function root:_dispatch_event(uid, updateItems)
  282. for _, v in ipairs(updateItems) do
  283. local conf = resAdapt:get_item_conf(v.id) or {}
  284. local evtParams = {
  285. times = 1,
  286. id = v.id,
  287. count = math.abs(v.deltaCount),
  288. add = v.deltaCount,
  289. type = conf.type,
  290. bId = v.bid,
  291. totalCount = v.count
  292. }
  293. util_user:user_dispatch_event(uid, gameConst.EVENT_ID.RES, evtParams)
  294. end
  295. end
  296. -- 资源变化事件
  297. function root:_log_resource(uid, updateItems, reason)
  298. for _, v in ipairs(updateItems) do
  299. util_user:log_resource(uid, reason, v.id, v.deltaCount, v.count)
  300. end
  301. end
  302. return root