service.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. package asset
  2. import (
  3. actorRemote "f1-game/internal/actor_remote"
  4. capp "f1-game/internal/cherry_app"
  5. "f1-game/internal/code"
  6. "f1-game/internal/data"
  7. "f1-game/internal/enum"
  8. "f1-game/internal/event"
  9. nameRoute "f1-game/internal/name/route"
  10. "f1-game/internal/sessions"
  11. "f1-game/internal/types"
  12. "f1-game/nodes/game/internal/db"
  13. ao "f1-game/nodes/game/player/asset/origin"
  14. clog "github.com/cherry-game/cherry/logger"
  15. )
  16. // 构造一个资源对外服务类
  17. var srv = &service{
  18. typ: newServiceType(),
  19. }
  20. // Service 用于初始化资产接口
  21. func Service() *service {
  22. return srv
  23. }
  24. type service struct {
  25. typ serviceType // 资源类型服务类(封装各种资源类型的细节)
  26. }
  27. func (p *service) Add(playerID int64, id int32, num int64, origin ao.Origin, push bool) (types.Assets, int32) {
  28. itemRow, found := data.Item.GetByID(id)
  29. if !found {
  30. return nil, code.ConfigNotFound_Item
  31. }
  32. parser, errCode := p.typ.get(itemRow.ParseType)
  33. if code.IsFail(errCode) {
  34. return nil, errCode
  35. }
  36. // 超过单次最大添加数量
  37. if num > parser.MaxAddOnce() {
  38. return nil, code.ItemAddOnceNumLimit
  39. }
  40. addAsset := &types.Asset{
  41. ID: id,
  42. Num: num,
  43. }
  44. retAssets := types.Assets{}
  45. if enum.IsMapCurrency(id) || enum.IsLeagueCurrency(id) {
  46. playerTable, _ := db.GetPlayerTable(playerID)
  47. if playerTable.Map.MapNodeID != "" {
  48. actorRemote.MapPlayer.AddAssets(playerTable.Map.MapNodeID, playerID, types.Assets{addAsset}, origin)
  49. retAssets.AddAsset(addAsset)
  50. } else {
  51. clog.Warnf("Add map assets fail: map node not found. playerID=%d, assets = %+v", playerID, addAsset)
  52. }
  53. } else {
  54. if errCode = parser.Add(playerID, addAsset, origin, &retAssets); code.IsOK(errCode) {
  55. assets := types.Assets{addAsset}
  56. // 发送系统消息事件
  57. capp.PostEvent(event.NewChatSystemMsg(playerID, enum.ChatMsgType_reward, assets, nil))
  58. capp.PostEvent(event.NewItemAdd(playerID, assets, origin))
  59. if push {
  60. parser.Push(playerID, retAssets)
  61. }
  62. }
  63. }
  64. return retAssets, errCode
  65. }
  66. // Adds 添加资源
  67. func (p *service) Adds(playerID int64, assets types.Assets, origin ao.Origin, push bool) (types.Assets, int32) {
  68. if len(assets) < 1 {
  69. return nil, code.AssetIsEmpty
  70. }
  71. var (
  72. retAssets = types.Assets{}
  73. mapAssets = types.Assets{}
  74. gameAssets = types.Assets{}
  75. )
  76. for _, asset := range assets {
  77. if enum.IsMapCurrency(asset.ID) || enum.IsLeagueCurrency(asset.ID) {
  78. mapAssets.Add(asset.ID, asset.Num)
  79. } else {
  80. gameAssets.Add(asset.ID, asset.Num)
  81. }
  82. }
  83. if mapAssets.Len() > 0 {
  84. playerTable, _ := db.GetPlayerTable(playerID)
  85. if playerTable.Map.MapNodeID != "" {
  86. actorRemote.MapPlayer.AddAssets(playerTable.Map.MapNodeID, playerID, mapAssets, origin)
  87. retAssets.AddAssets(mapAssets)
  88. } else {
  89. clog.Warnf("Add map assets fail: map node not found. playerID=%d, assets = %+v", playerID, mapAssets)
  90. }
  91. }
  92. if gameAssets.Len() > 0 {
  93. for _, asset := range gameAssets {
  94. parser, errCode := p.typ.getWithAssetID(asset.ID)
  95. if code.IsFail(errCode) {
  96. clog.Warnf("Add assets fail. playerID=%d, assets = %+v, code = %v", playerID, asset, errCode)
  97. continue
  98. }
  99. errCode = parser.Add(playerID, asset, origin, &retAssets)
  100. if code.IsFail(errCode) {
  101. clog.Warnf("Add assets fail. playerID=%d, assets = %+v, code = %v", playerID, retAssets, errCode)
  102. continue
  103. }
  104. }
  105. // 发送系统消息事件
  106. capp.PostEvent(event.NewChatSystemMsg(playerID, enum.ChatMsgType_reward, gameAssets, nil))
  107. capp.PostEvent(event.NewItemAdd(playerID, gameAssets, origin))
  108. }
  109. // push by asset type
  110. if push {
  111. groupRetAssets, _ := p.groupAssets(retAssets)
  112. for parser, pushAssets := range groupRetAssets {
  113. parser.Push(playerID, pushAssets)
  114. }
  115. }
  116. return retAssets, code.OK
  117. }
  118. func (p *service) Sub(playerID int64, id int32, num int64, origin ao.Origin) (types.Assets, int32) {
  119. if num < 1 {
  120. return nil, code.ItemNumError
  121. }
  122. itemRow, found := data.Item.GetByID(id)
  123. if !found {
  124. return nil, code.ConfigNotFound_Item
  125. }
  126. parser, errCode := p.typ.get(itemRow.ParseType)
  127. if code.IsFail(errCode) {
  128. return nil, errCode
  129. }
  130. var addAssets types.Assets
  131. addAssets.Add(id, num)
  132. retAssets := types.Assets{}
  133. errCode = parser.Sub(playerID, addAssets, origin, &retAssets)
  134. if code.IsOK(errCode) {
  135. parser.Push(playerID, retAssets)
  136. }
  137. return retAssets, errCode
  138. }
  139. func (p *service) Subs(playerID int64, assets types.Assets, origin ao.Origin) (types.Assets, int32) {
  140. if len(assets) < 1 {
  141. return nil, code.AssetIsEmpty
  142. }
  143. assetsGroup, errCode := p.groupAssets(assets)
  144. if code.IsFail(errCode) {
  145. return nil, errCode
  146. }
  147. //检测资产数量是否满足
  148. for parser, opAssets := range assetsGroup {
  149. for _, asset := range opAssets {
  150. if errCode = parser.IsEnough(playerID, asset); code.IsFail(errCode) {
  151. return nil, errCode
  152. }
  153. }
  154. }
  155. retAssets := types.Assets{}
  156. for parser, opAssets := range assetsGroup {
  157. errCode = parser.Sub(playerID, opAssets, origin, &retAssets)
  158. if code.IsFail(errCode) {
  159. clog.Warnf("Sub assets fail. playerID=%d, assets = %+v, code = %v", playerID, retAssets, errCode)
  160. continue
  161. }
  162. }
  163. // push by asset type
  164. groupRetAssets, _ := p.groupAssets(retAssets)
  165. for assetType, pushAssets := range groupRetAssets {
  166. assetType.Push(playerID, pushAssets)
  167. }
  168. return retAssets, code.OK
  169. }
  170. func (p *service) Enough(playerID int64, itemID int32, num int64) int32 {
  171. parser, errCode := p.typ.getWithAssetID(itemID)
  172. if code.IsFail(errCode) {
  173. return errCode
  174. }
  175. asset := types.NewAsset(itemID, num)
  176. errCode = parser.IsEnough(playerID, &asset)
  177. return errCode
  178. }
  179. func (p *service) IsAllEnough(playerID int64, assets types.Assets) int32 {
  180. for _, asset := range assets {
  181. if errCode := p.Enough(playerID, asset.ID, asset.Num); code.IsFail(errCode) {
  182. return errCode
  183. }
  184. }
  185. return code.OK
  186. }
  187. func (p *service) Get(playerID int64, assetID int32) int64 {
  188. parser, errCode := p.typ.getWithAssetID(assetID)
  189. if code.IsFail(errCode) {
  190. return 0
  191. }
  192. return parser.Get(playerID, assetID)
  193. }
  194. // Check 检查资产类型
  195. func (p *service) Check(assets types.Assets) int32 {
  196. for _, asset := range assets {
  197. _, errCode := p.typ.getWithAssetID(asset.ID)
  198. if code.IsFail(errCode) {
  199. return errCode
  200. }
  201. }
  202. return code.OK
  203. }
  204. func (p *service) groupAssets(assets types.Assets) (map[typeParser]types.Assets, int32) {
  205. groupMap := make(map[typeParser]types.Assets)
  206. for _, asset := range assets {
  207. effector, errCode := p.typ.getWithAssetID(asset.ID)
  208. if code.IsFail(errCode) {
  209. return nil, errCode
  210. }
  211. assetsSlice, found := groupMap[effector]
  212. if !found {
  213. assetsSlice = make(types.Assets, 0)
  214. }
  215. assetsSlice = append(assetsSlice, asset)
  216. groupMap[effector] = assetsSlice
  217. }
  218. return groupMap, code.OK
  219. }
  220. func (p *service) RewardPush(playerID int64, assets types.Assets) {
  221. sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_Reward, assets.ToAssetListProto())
  222. }