inventorymgr.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. package handler
  2. import (
  3. "bet24.com/log"
  4. "bet24.com/servers/common"
  5. //"bet24.com/servers/coreservice/limiteditems"
  6. item "bet24.com/servers/micros/item_inventory/proto"
  7. notification "bet24.com/servers/micros/notification/proto"
  8. "encoding/json"
  9. "strconv"
  10. "sync"
  11. "time"
  12. )
  13. const DELAY_REMOVE = 300 // 300秒后删除用户
  14. const DELAY_CHECK = 60 // 每分钟检查一次
  15. var inventorymgr *inventory
  16. func getInventoryManager() *inventory {
  17. if inventorymgr == nil {
  18. inventorymgr = newInventory()
  19. }
  20. return inventorymgr
  21. }
  22. type inventory struct {
  23. lock *sync.RWMutex
  24. userInventory map[int]*user_inventory
  25. lockRemove *sync.RWMutex
  26. userRemove map[int]int64
  27. }
  28. func newInventory() *inventory {
  29. ret := new(inventory)
  30. ret.lock = &sync.RWMutex{}
  31. ret.userInventory = make(map[int]*user_inventory)
  32. ret.lockRemove = &sync.RWMutex{}
  33. ret.userRemove = make(map[int]int64)
  34. go ret.checkRemoveUser()
  35. return ret
  36. }
  37. func (this *inventory) checkRemoveUser() {
  38. time.AfterFunc(DELAY_CHECK*time.Second, this.checkRemoveUser)
  39. var toRemove []int
  40. latestRemoveTime := time.Now().Unix() - DELAY_REMOVE
  41. this.lockRemove.RLock()
  42. for k, v := range this.userRemove {
  43. if v < latestRemoveTime {
  44. toRemove = append(toRemove, k)
  45. }
  46. }
  47. this.lockRemove.RUnlock()
  48. if len(toRemove) == 0 {
  49. return
  50. }
  51. this.lockRemove.Lock()
  52. for _, v := range toRemove {
  53. delete(this.userRemove, v)
  54. }
  55. this.lockRemove.Unlock()
  56. for _, v := range toRemove {
  57. this.destroyUser(v)
  58. }
  59. }
  60. func (this *inventory) onUserEnter(userId int, ipAddress string) *user_inventory {
  61. this.lockRemove.Lock()
  62. delete(this.userRemove, userId)
  63. this.lockRemove.Unlock()
  64. this.lock.RLock()
  65. ui, ok := this.userInventory[userId]
  66. this.lock.RUnlock()
  67. if ok {
  68. return ui
  69. }
  70. ui = newUserInventory(userId, ipAddress)
  71. this.lock.Lock()
  72. this.userInventory[userId] = ui
  73. this.lock.Unlock()
  74. return ui
  75. }
  76. func (this *inventory) onUserExit(userId int) {
  77. this.lockRemove.Lock()
  78. this.userRemove[userId] = time.Now().Unix()
  79. this.lockRemove.Unlock()
  80. }
  81. func (this *inventory) destroyUser(userId int) {
  82. this.lock.RLock()
  83. s, _ := this.userInventory[userId]
  84. this.lock.RUnlock()
  85. if s == nil {
  86. return
  87. }
  88. s.destructor()
  89. this.lock.Lock()
  90. delete(this.userInventory, userId)
  91. this.lock.Unlock()
  92. }
  93. func (this *inventory) consume(userId int, itemId int, bullet int, count int, isGift int) (bool, string) {
  94. this.lock.RLock()
  95. ui, ok := this.userInventory[userId]
  96. this.lock.RUnlock()
  97. if !ok {
  98. ui = this.onUserEnter(userId, "")
  99. if ui != nil {
  100. return ui.consume(itemId, bullet, count, bullet, isGift)
  101. }
  102. log.Debug("inventory.consume userId[%d] not exist", userId)
  103. return false, "user not exist"
  104. }
  105. return ui.consume(itemId, bullet, count, bullet, isGift)
  106. }
  107. func (this *inventory) sell(userId, itemId, count, logType int) (bool, string) {
  108. this.lock.RLock()
  109. ui, ok := this.userInventory[userId]
  110. this.lock.RUnlock()
  111. if !ok {
  112. ui = this.onUserEnter(userId, "")
  113. if ui != nil {
  114. return ui.sell(itemId, count, logType)
  115. }
  116. log.Debug("inventory.sell userId[%d] not exist", userId)
  117. return false, "user not exist"
  118. }
  119. return ui.sell(itemId, count, logType)
  120. }
  121. func (this *inventory) consumeBulk(userId int, items []item.ItemPack, logType int) bool {
  122. this.lock.RLock()
  123. ui, ok := this.userInventory[userId]
  124. this.lock.RUnlock()
  125. if !ok {
  126. ui = this.onUserEnter(userId, "")
  127. if ui != nil {
  128. return ui.consumeBulk(items, logType)
  129. }
  130. log.Debug("inventory.consume userId[%d] not exist", userId)
  131. return false
  132. }
  133. return ui.consumeBulk(items, logType)
  134. }
  135. func (this *inventory) consumeLottery(userId, count int) (bool, string) {
  136. this.lock.RLock()
  137. ui, ok := this.userInventory[userId]
  138. this.lock.RUnlock()
  139. if !ok {
  140. ui = this.onUserEnter(userId, "")
  141. if ui != nil {
  142. return ui.consumeLottery(count)
  143. }
  144. log.Debug("inventory.consumeLottery userId[%d] not exist", userId)
  145. return false, "user not exist"
  146. }
  147. return ui.consumeLottery(count)
  148. }
  149. func (this *inventory) getUser(userId int, forceCreate bool) *user_inventory {
  150. this.lock.RLock()
  151. ret, ok := this.userInventory[userId]
  152. this.lock.RUnlock()
  153. if !ok {
  154. if forceCreate {
  155. return this.onUserEnter(userId, "")
  156. }
  157. return nil
  158. }
  159. return ret
  160. }
  161. func (this *inventory) addItemsWithExpireTime(userId int, items []item.ItemPack,
  162. desc string, logType int, expireTime int) bool {
  163. user := this.getUser(userId, false)
  164. toRemove := false
  165. if user == nil {
  166. user = newUserInventory(userId, "127.0.0.1")
  167. toRemove = true
  168. }
  169. ret := user.addItemsWithExpireTime(items, logType, expireTime)
  170. if toRemove {
  171. // 用户没有进来,不需要保存
  172. user.destructor()
  173. }
  174. return ret
  175. }
  176. func (this *inventory) addItems(userId int, items []item.ItemPack, desc string, logType int) bool {
  177. // log.Debug("iventorymgr.addItems userId=%d items=%+v desc=%s", userId, items, desc)
  178. user := this.getUser(userId, false)
  179. toRemove := false
  180. if user == nil {
  181. user = newUserInventory(userId, "127.0.0.1")
  182. toRemove = true
  183. }
  184. var itemIds []int
  185. for _, v := range items {
  186. //v.Count = limiteditems.AddItem(userId, v.ItemId, v.Count)
  187. user.addItem(v, logType)
  188. itemIds = append(itemIds, v.ItemId)
  189. }
  190. //通知客户端
  191. d, _ := json.Marshal(notification.NotificationInventory{ItemIds: itemIds, Action: Inventory_Add})
  192. notification.AddNotification(userId, notification.Notification_Inventory, string(d))
  193. if toRemove {
  194. // 用户没有进来,不需要保存
  195. user.destructor()
  196. }
  197. return true
  198. }
  199. func (this *inventory) getUserItems(userId int) []*item.UserItem {
  200. user := this.getUser(userId, true)
  201. if user == nil {
  202. log.Debug("inventory.getUserItems userId[%d] not exist", userId)
  203. return nil
  204. }
  205. return user.getItemList()
  206. }
  207. func (this *inventory) getItemCount(userId int, itemId int) int {
  208. user := this.getUser(userId, true)
  209. if user == nil {
  210. log.Debug("inventory.getItemCount userId[%d] not exist", userId)
  211. return 0
  212. }
  213. return user.getItemCount(itemId)
  214. }
  215. // 获取抽奖券
  216. func (this *inventory) getUserLottery(userId int) *item.UserItem {
  217. user := this.getUser(userId, true)
  218. if user == nil {
  219. log.Debug("inventory.getUserLottery userId[%d] not exist", userId)
  220. return nil
  221. }
  222. return user.getLottery()
  223. }
  224. // 赠送
  225. func (this *inventory) gift(userId, toUserId, itemId, count int) (bool, string) {
  226. // 先扣减
  227. retCode, msg := this.consume(userId, itemId, common.LOGTYPE_TRANSFER_CONSUME, count, 1)
  228. if !retCode {
  229. return retCode, msg
  230. }
  231. var items []item.ItemPack
  232. items = append(items, item.ItemPack{
  233. ItemId: itemId,
  234. Count: count,
  235. })
  236. // 加道具
  237. retCode = this.addItems(toUserId, items, "赠送", common.LOGTYPE_TRANSFER_ADD)
  238. return retCode, "成功"
  239. }
  240. func (iv *inventory) dumpSys(param string) {
  241. log.Release("-------------------------------")
  242. log.Release("inventory.dumpSys %s", param)
  243. defer func() {
  244. log.Release("+++++++++++++++++++++++++++++++")
  245. log.Release("")
  246. }()
  247. if param == "" {
  248. d, _ := json.Marshal(getItemManager().getItems())
  249. log.Release(string(d))
  250. } else {
  251. var itemId int
  252. var err error
  253. if itemId, err = strconv.Atoi(param); err != nil {
  254. log.Release("atoi error %v", err)
  255. return
  256. }
  257. d, _ := json.Marshal(getItemManager().getItem(itemId))
  258. log.Release(string(d))
  259. }
  260. }
  261. func (iv *inventory) dumpUser(param string) {
  262. log.Release("-------------------------------")
  263. log.Release("inventory.dumpUser %s", param)
  264. defer func() {
  265. log.Release("+++++++++++++++++++++++++++++++")
  266. log.Release("")
  267. }()
  268. if param == "all" {
  269. for k, v := range iv.userInventory {
  270. log.Release("%d:%d", k, v.userId)
  271. }
  272. return
  273. }
  274. var userId int
  275. var err error
  276. if userId, err = strconv.Atoi(param); err != nil {
  277. log.Release("atoi error %v", err)
  278. return
  279. }
  280. si := iv.getUserItems(userId)
  281. if si == nil {
  282. log.Release("user %d has no items", userId)
  283. return
  284. }
  285. d, _ := json.Marshal(si)
  286. log.Release(string(d))
  287. }
  288. func (this *inventory) reduceItemByAdmin(opUserID int, opUserName string, userId, itemId, count int) (bool, string) {
  289. toRemove := false
  290. user := this.getUser(userId, false)
  291. if user == nil {
  292. user = newUserInventory(userId, "127.0.0.1")
  293. toRemove = true
  294. }
  295. ok, msg := user.reduceItemByAdmin(opUserID, opUserName, itemId, count)
  296. if toRemove {
  297. // 用户没有进来,不需要保存
  298. user.destructor()
  299. }
  300. return ok, msg
  301. }
  302. func (this *inventory) checkDecortaionType(itemId int, t int, userId int) bool {
  303. userItem := this.getUser(userId, true)
  304. if userItem == nil {
  305. log.Release("inventory.checkDecortaionType userItem not found %d", userId)
  306. return false
  307. }
  308. // 有没有?
  309. if userItem.getItemCount(itemId) == 0 {
  310. log.Release("inventory.checkDecortaionType user[%d] do not have [%d]", userId, itemId)
  311. return false
  312. }
  313. return getItemManager().checkDecortaionType(itemId, t)
  314. }