actor_mail.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. package mail
  2. import (
  3. "f1-game/internal/code"
  4. "f1-game/internal/data"
  5. "f1-game/internal/enum"
  6. "f1-game/internal/event"
  7. nameLocal "f1-game/internal/name/local"
  8. nameRemote "f1-game/internal/name/remote"
  9. nameRoute "f1-game/internal/name/route"
  10. "f1-game/internal/pb"
  11. "f1-game/internal/sessions"
  12. "f1-game/internal/types"
  13. "f1-game/nodes/game/internal/db"
  14. dbMail "f1-game/nodes/game/internal/db/data/mail"
  15. "f1-game/nodes/game/player/asset"
  16. ao "f1-game/nodes/game/player/asset/origin"
  17. ctime "github.com/cherry-game/cherry/extend/time"
  18. clog "github.com/cherry-game/cherry/logger"
  19. "github.com/cherry-game/cherry/net/parser/pomelo"
  20. cproto "github.com/cherry-game/cherry/net/proto"
  21. )
  22. type actorMail struct {
  23. pomelo.ActorBase
  24. }
  25. func (p *actorMail) OnInit() {
  26. p.Local().Register(nameLocal.Mail_TakeReward, p.takeReward)
  27. p.Local().Register(nameLocal.Mail_TakeAllReward, p.takeAllReward)
  28. p.Local().Register(nameLocal.Mail_Read, p.read)
  29. p.Local().Register(nameLocal.Mail_Delete, p.delete)
  30. p.Remote().Register(nameRemote.Mail_OnLogin, p.onLogin)
  31. p.Remote().Register(nameRemote.Mail_Send, p.send)
  32. p.Remote().Register(nameRemote.Mail_GetList, p.getMailList)
  33. }
  34. // takeReward 领取邮件奖励
  35. func (p *actorMail) takeReward(session *cproto.Session, req *pb.I64) {
  36. playerID := sessions.GetPlayerID(session)
  37. if playerID < 1 {
  38. p.ResponseCode(session, code.MailRequestDataError)
  39. return
  40. }
  41. var (
  42. mailTable = db.GetMailTable(playerID)
  43. mailID = req.Value
  44. )
  45. if mailID < 1 {
  46. p.ResponseCode(session, code.MailRequestDataError)
  47. return
  48. }
  49. mailEntity, found := mailTable.Get(mailID)
  50. if !found {
  51. p.ResponseCode(session, code.MailDataNotFound)
  52. return
  53. }
  54. if mailEntity.IsReward {
  55. p.ResponseCode(session, code.MailRewardHadTake)
  56. return
  57. }
  58. if len(mailEntity.Rewards) <= 0 {
  59. p.ResponseCode(session, code.MailRewardEmpty)
  60. return
  61. }
  62. retAssets, errCode := asset.Service().Adds(playerID, mailEntity.Rewards, ao.MailGet, true)
  63. if code.IsFail(errCode) {
  64. p.ResponseCode(session, errCode)
  65. return
  66. }
  67. mailEntity.TakeReward()
  68. mailTable.Save2Queue()
  69. resp := retAssets.ToAssetListProto()
  70. p.Response(session, &resp)
  71. }
  72. // takeAllReward 一键阅读领取奖励
  73. func (p *actorMail) takeAllReward(session *cproto.Session, _ *pb.None) {
  74. playerID := sessions.GetPlayerID(session)
  75. if playerID < 1 {
  76. p.ResponseCode(session, code.MailRequestDataError)
  77. return
  78. }
  79. var (
  80. mailTable = db.GetMailTable(playerID)
  81. mailIDs []int64
  82. addRewards types.Assets
  83. isChange = false
  84. )
  85. // 领取所有邮件
  86. for _, mailEntity := range mailTable.Data {
  87. if mailEntity.CanTakeReward() {
  88. addRewards.AddAssets(mailEntity.TakeReward())
  89. mailIDs = append(mailIDs, mailEntity.MailID)
  90. mailEntity.IsRead = true
  91. isChange = true
  92. continue
  93. }
  94. if !mailEntity.IsRead {
  95. mailEntity.IsRead = true
  96. mailIDs = append(mailIDs, mailEntity.MailID)
  97. isChange = true
  98. }
  99. }
  100. if !isChange {
  101. p.ResponseCode(session, code.MailRewardEmpty)
  102. return
  103. }
  104. resp := &pb.TakeMailReward{
  105. MailIDs: mailIDs,
  106. }
  107. if !addRewards.IsEmpty() {
  108. returnAssets, _ := asset.Service().Adds(playerID, addRewards, ao.MailGet, true)
  109. resp.List = returnAssets.ToProto()
  110. }
  111. mailTable.Save2Queue()
  112. p.Response(session, resp)
  113. }
  114. // read 邮件设置已读取
  115. func (p *actorMail) read(session *cproto.Session, req *pb.I64) {
  116. playerID := sessions.GetPlayerID(session)
  117. if playerID < 1 {
  118. p.ResponseCode(session, code.MailRequestDataError)
  119. return
  120. }
  121. var (
  122. mailTable = db.GetMailTable(playerID)
  123. mailID = req.Value
  124. )
  125. if mailID < 1 {
  126. p.ResponseCode(session, code.MailRequestDataError)
  127. return
  128. }
  129. mailEntity, found := mailTable.Get(mailID)
  130. if !found {
  131. p.ResponseCode(session, code.MailDataNotFound)
  132. return
  133. }
  134. if !mailEntity.IsRead {
  135. mailEntity.IsRead = true
  136. mailTable.Save2Queue()
  137. }
  138. p.ResponseCode(session, code.OK)
  139. }
  140. // delete 请求邮件删除
  141. func (p *actorMail) delete(session *cproto.Session, req *pb.I64) {
  142. playerID := sessions.GetPlayerID(session)
  143. if playerID < 1 {
  144. p.ResponseCode(session, code.MailRequestDataError)
  145. return
  146. }
  147. var (
  148. mailTable = db.GetMailTable(playerID)
  149. mailID = req.Value
  150. delIDList []int64
  151. )
  152. if mailID > 0 {
  153. mailEntity, found := mailTable.Get(mailID)
  154. if !found {
  155. p.ResponseCode(session, code.MailDataNotFound)
  156. return
  157. }
  158. if !mailEntity.IsRead {
  159. p.ResponseCode(session, code.MailNotRead)
  160. return
  161. }
  162. if mailEntity.CanTakeReward() {
  163. p.ResponseCode(session, code.MailNotClaim)
  164. return
  165. }
  166. if mailTable.Remove(mailEntity.MailID) {
  167. delIDList = append(delIDList, mailEntity.MailID)
  168. }
  169. } else {
  170. mailList := mailTable.GetMailWithType(dbMail.DeletableMailFilter)
  171. for _, mailEntity := range mailList {
  172. if mailTable.Remove(mailEntity.MailID) {
  173. delIDList = append(delIDList, mailEntity.MailID)
  174. }
  175. }
  176. }
  177. if len(delIDList) > 0 {
  178. // 保存
  179. mailTable.Save2Queue()
  180. resp := &pb.I64List{
  181. List: delIDList,
  182. }
  183. sessions.PushPlayer(playerID, nameRoute.PushGameMail_Delete, resp)
  184. clog.Debugf("playerID = %d, delMailID = %+v", playerID, delIDList)
  185. }
  186. p.ResponseCode(session, code.OK)
  187. }
  188. // onLogin 登录时检查玩家邮件&下发邮件
  189. func (p *actorMail) onLogin(PlayerLogin *event.PlayerLogin) {
  190. var (
  191. now = ctime.Now()
  192. playerID = PlayerLogin.PlayerID()
  193. )
  194. mailTable := db.GetMailTable(playerID)
  195. //检测添加群发邮件
  196. p.checkAndAddBulkMail(mailTable)
  197. // 推送邮件列表
  198. p.mailListPush(PlayerLogin.Session(), mailTable, &now)
  199. }
  200. // send 发送邮件
  201. func (p *actorMail) send(req *pb.SendMail) {
  202. if req.ToPlayerID < 1 {
  203. clog.Warnf("mail to playerID not found. req = %+v", req)
  204. return
  205. }
  206. if req.TemplateID <= 0 {
  207. clog.Warnf("mail template not found. req = %+v", req)
  208. return
  209. }
  210. templateRow, found := data.MailTemplate.GetByID(req.TemplateID)
  211. if !found {
  212. clog.Warnf("mail template not found. req = %+v", req)
  213. return
  214. }
  215. //合并邮件奖励
  216. var addRewards types.Assets
  217. if len(req.Rewards) > 0 {
  218. addRewards = types.FillAssets(req.Rewards)
  219. } else {
  220. addRewards = templateRow.Rewards
  221. }
  222. mailTable := db.GetMailTable(req.ToPlayerID)
  223. newMail := &dbMail.Mail{
  224. MailID: mailTable.NewMailID(),
  225. FromID: req.FromPlayerID,
  226. FromName: req.FromPlayerName,
  227. TemplateID: req.TemplateID,
  228. TemplateParams: req.TemplateParams,
  229. IsReward: false,
  230. IsRead: false,
  231. SendTime: ctime.Now().ToSecond(),
  232. RewardTime: 0,
  233. Rewards: addRewards,
  234. }
  235. newMail.ExpireTime = newMail.SendTime + int64(templateRow.ExpireDays*ctime.SecondsPerDay)
  236. //添加邮件
  237. delMailList, isChange := mailTable.Add(newMail, true)
  238. // 删除邮件处理
  239. p.delMailSendReward(req.ToPlayerID, delMailList, true)
  240. if isChange {
  241. // 新邮件推送
  242. pushList := &pb.MailList{}
  243. pbNewMail := newMail.ToProto()
  244. pushList.List = append(pushList.List, pbNewMail)
  245. sessions.PushPlayer(req.ToPlayerID, nameRoute.PushGameMail_New, pushList)
  246. }
  247. clog.Debugf("playerID = %d, mailNum = %d", req.ToPlayerID, len(mailTable.Data))
  248. clog.Debugf("delMailID = %+v", delMailList)
  249. }
  250. // 获取邮件列表
  251. func (p *actorMail) getMailList(req *pb.I64) (*pb.MailList, int32) {
  252. playerID := req.Value
  253. if playerID <= 0 {
  254. clog.Warnf("ops get mail list fail, playerID fail.")
  255. return nil, code.MailRequestDataError
  256. }
  257. mailTable := db.GetMailTable(playerID)
  258. mails := mailTable.ToProto()
  259. mailList := &pb.MailList{
  260. List: mails,
  261. }
  262. return mailList, code.OK
  263. }
  264. // checkAndAddBulkMail 检测并添加群发邮件
  265. func (p *actorMail) checkAndAddBulkMail(mailTable *db.MailTable) {
  266. mailBulkList := data.MailBulk.List()
  267. if len(mailBulkList) < 1 {
  268. return
  269. }
  270. for _, mailBulkRow := range mailBulkList {
  271. bulkID := mailBulkRow.BulkID
  272. if !mailBulkRow.IsOpen || mailTable.InBulk(bulkID) {
  273. continue
  274. }
  275. templateID := mailBulkRow.TemplateID
  276. mailTemplateRow, found := data.MailTemplate.GetByID(templateID)
  277. if !found {
  278. clog.Warnf("check and add bulk mail fail, template not found. PlayerID= %d, bulkID = %d, templateID = %d", mailTable.PlayerID, bulkID, templateID)
  279. continue
  280. }
  281. //合并群发&邮件模板的奖励内容
  282. var addRewards types.Assets
  283. if len(mailTemplateRow.Rewards) > 0 {
  284. addRewards.AddAssets(mailTemplateRow.Rewards)
  285. }
  286. newMail := &dbMail.Mail{
  287. MailID: mailTable.NewMailID(),
  288. TemplateID: templateID,
  289. IsReward: false,
  290. IsRead: false,
  291. SendTime: ctime.Now().ToSecond(),
  292. RewardTime: 0,
  293. Rewards: addRewards,
  294. }
  295. //计算邮件结束时间
  296. newMail.ExpireTime = newMail.SendTime + int64(mailTemplateRow.ExpireDays*ctime.SecondsPerDay)
  297. //添加邮件
  298. var _, isChange = mailTable.Add(newMail, true)
  299. if isChange {
  300. // 添加已发群发ID
  301. mailTable.AddBulkID(bulkID)
  302. clog.Infof("add bulk mail success. playerID= %d, bulkID = %d, templateID = %d", mailTable.PlayerID, bulkID, templateID)
  303. }
  304. }
  305. }
  306. func (p *actorMail) mailListPush(session *cproto.Session, mailTable *db.MailTable, now *ctime.CherryTime) {
  307. // 清理当前玩家过期的邮件
  308. delMailList := mailTable.CheckExpire(now)
  309. // 删除邮件发送奖励
  310. p.delMailSendReward(mailTable.PlayerID, delMailList, false)
  311. mailList := &pb.MailList{
  312. MailType: enum.MailType_System,
  313. List: mailTable.ToProto(),
  314. }
  315. // 推送邮件列表
  316. sessions.PushWithSession(session, nameRoute.PushGameMail_List, mailList)
  317. }
  318. func (p *actorMail) delMailSendReward(playerID int64, delMailList []*dbMail.Mail, pushDel bool) {
  319. if len(delMailList) < 1 {
  320. return
  321. }
  322. var (
  323. addRewards = types.Assets{}
  324. delMailIDList = []int64{}
  325. )
  326. for _, mail := range delMailList {
  327. if mail.CanTakeReward() {
  328. addRewards.AddAssets(mail.Rewards)
  329. }
  330. delMailIDList = append(delMailIDList, mail.MailID)
  331. }
  332. // 发送删除邮件奖励
  333. if len(addRewards) > 0 {
  334. asset.Service().Adds(playerID, addRewards, ao.MailGet, true)
  335. }
  336. if pushDel {
  337. sessions.PushPlayer(playerID, nameRoute.PushGameMail_Delete, &pb.I64List{
  338. List: delMailIDList,
  339. })
  340. }
  341. }