service.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. package lord
  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/constant"
  7. "f1-game/internal/data"
  8. "f1-game/internal/enum"
  9. "f1-game/internal/event"
  10. "f1-game/internal/extend/times"
  11. "f1-game/internal/extend/utils"
  12. facade "f1-game/internal/facade"
  13. nameActor "f1-game/internal/name/actor"
  14. nameRemote "f1-game/internal/name/remote"
  15. nameRoute "f1-game/internal/name/route"
  16. "f1-game/internal/pb"
  17. "f1-game/internal/sessions"
  18. "f1-game/nodes/game/internal/db"
  19. ctime "github.com/cherry-game/cherry/extend/time"
  20. cfacade "github.com/cherry-game/cherry/facade"
  21. clog "github.com/cherry-game/cherry/logger"
  22. cproto "github.com/cherry-game/cherry/net/proto"
  23. )
  24. var srv = &service{}
  25. func Service() *service {
  26. return srv
  27. }
  28. type service struct {
  29. facade.PlayerServiceBase[*db.PlayerTable]
  30. }
  31. func (p *service) OnLogin(playerTable *db.PlayerTable, session *cproto.Session) {
  32. playerTable.Stats.LastLoginIP = session.Ip
  33. // 默认赛季1
  34. if playerTable.Lord.SeasonID <= 0 {
  35. playerTable.Lord.SeasonID = 1
  36. }
  37. playerTable.Save2Queue()
  38. // 检测玩家头像
  39. p.CheckPlayerShow(playerTable)
  40. clog.Debugf("[lord.OnLogin] PlayerID = %d, IP = %s", playerTable.PlayerID, session.Ip)
  41. }
  42. func (p *service) OnLogined(playerTable *db.PlayerTable, session *cproto.Session) {
  43. // 更新玩家最后登录信息
  44. p.syncLastPlayer(playerTable)
  45. }
  46. func (*service) OnLogout(playerTable *db.PlayerTable) {
  47. now := ctime.Now()
  48. loginTime := ctime.NewMillisecond(playerTable.Stats.LastLoginTime)
  49. second := loginTime.DiffInSeconds(&now)
  50. if second > 0 {
  51. // 累计在线时间
  52. playerTable.Stats.TotalOnlineSecond += second
  53. }
  54. // 最后登出时间
  55. playerTable.Stats.LastLogoutTime = now.ToMillisecond()
  56. playerTable.Save2Queue()
  57. clog.Debugf("[lord.OnLogout] PlayerID = %d, OnlineTime = %d(s)", playerTable.PlayerID, second)
  58. }
  59. func (*service) OnReset(playerTable *db.PlayerTable, curTime *ctime.CherryTime, byLogin bool) {
  60. // 判断当前时间是否开启时间
  61. openTime, err := times.ParseDateFormat(data.Const.MailDaysOpenTime)
  62. if err != nil {
  63. clog.Warnf("send daily mail fail. err:%+v", err)
  64. return
  65. }
  66. openTimeSecond := openTime.Unix()
  67. // 当前时间还没到
  68. if curTime.ToSecond() < openTimeSecond {
  69. return
  70. }
  71. // 如果是 则获取已领取的每日邮件天数
  72. days := playerTable.Stats.DailyMailDays + 1
  73. mailDailyRow, found := data.MailDaily.GetByLoginDays(days)
  74. if !found {
  75. return
  76. }
  77. // 更新已领取天数
  78. playerTable.Stats.DailyMailDays = days
  79. playerTable.Save2Queue()
  80. // 发送邮件
  81. actorRemote.GameMail.Send(playerTable.NodeID, &pb.SendMail{
  82. ToPlayerID: playerTable.PlayerID,
  83. TemplateID: constant.MailID_DailyMail,
  84. Rewards: mailDailyRow.Rewards.ToProto(),
  85. TemplateParams: utils.ToStringSlice(days),
  86. })
  87. clog.Debugf("send daily mail finish. playerID:%d, day:%d", playerTable.PlayerID, days)
  88. }
  89. func (p *service) Push(playerTable *db.PlayerTable, session *cproto.Session) {
  90. proto := playerTable.Lord.ToProto()
  91. sessions.PushWithSession(session, nameRoute.PushGamePlayer_Lord, proto)
  92. // 推送外显列表
  93. showRsp := &pb.LordShows{}
  94. for showID, show := range playerTable.Shows.ShowMap {
  95. showRsp.Shows = append(showRsp.Shows, show.ToProto(showID))
  96. }
  97. sessions.PushWithSession(session, nameRoute.PushGamePlayer_LordShow, showRsp)
  98. }
  99. // ChangePush 外显变更推送
  100. func (p *service) ChangePush(playerID int64, updateShowIDs ...int32) {
  101. if len(updateShowIDs) <= 0 {
  102. return
  103. }
  104. var (
  105. playerTable, _ = db.GetPlayerTable(playerID)
  106. rsp = &pb.LordShows{}
  107. )
  108. for _, showID := range updateShowIDs {
  109. show, found := playerTable.Shows.GetShow(showID)
  110. if !found {
  111. continue
  112. }
  113. rsp.Shows = append(rsp.Shows, show.ToProto(showID))
  114. }
  115. sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_LordShowAdd, rsp)
  116. }
  117. // 检测外显过期
  118. func (p *service) CheckShowExpireTimer(playerID int64, nowSecond int64) {
  119. playerTable, _ := db.GetPlayerTable(playerID)
  120. if playerTable.Shows.ShowMap.Empty() {
  121. return
  122. }
  123. expireShowIDs, changeShows := playerTable.CheckShowExpire(nowSecond)
  124. if len(expireShowIDs) <= 0 {
  125. return
  126. }
  127. // 推送删除外显列表
  128. expireResp := &pb.I32List{
  129. List: expireShowIDs,
  130. }
  131. sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_LordShowExpire, expireResp)
  132. // 推送外显变更列表
  133. if len(changeShows) > 0 {
  134. changeShowsResp := &pb.I32I32List{
  135. List: changeShows,
  136. }
  137. sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_LordShowChange, changeShowsResp)
  138. }
  139. playerTable.Save2Queue()
  140. }
  141. func (p *service) AddExp(playerID int64, exp int64) int32 {
  142. var (
  143. playerTable, _ = db.GetPlayerTable(playerID)
  144. lord = &playerTable.Lord
  145. seasonID = playerTable.Lord.SeasonID
  146. maxLevel = data.LordLevel.GetLevelLimitBySeason(seasonID)
  147. levelUp bool
  148. )
  149. // 已满级
  150. if lord.Level >= maxLevel {
  151. return code.OK
  152. }
  153. lord.Exp += exp
  154. // 是否升级
  155. for lord.Level < maxLevel {
  156. row, ok := data.LordLevel.GetByLevel(lord.Level)
  157. if !ok {
  158. return code.ConfigNotFound_LordLevel
  159. }
  160. if row.Exp > lord.Exp {
  161. break
  162. }
  163. lord.Exp -= row.Exp
  164. lord.Level++
  165. // 等级已达上限,设置经验为0
  166. if lord.Level >= maxLevel {
  167. lord.Exp = 0
  168. }
  169. levelUp = true
  170. }
  171. // 保存
  172. playerTable.Save2Queue()
  173. // 推送
  174. if session, found := sessions.GetSession(playerID); found {
  175. p.Push(playerTable, session)
  176. }
  177. // 抛升级事件
  178. if levelUp {
  179. capp.PostEvent(event.NewLordLevelUp(playerID, lord.Level))
  180. // 发送系统消息事件
  181. capp.PostEvent(event.NewChatSystemMsg(playerID, enum.ChatMsgType_LordUp, nil, nil, lord.Level))
  182. }
  183. return code.OK
  184. }
  185. // syncLastPlayer 同步最后登录信息
  186. func (p *service) syncLastPlayer(playerTable *db.PlayerTable) {
  187. protoUpdatePlayer := &pb.UpdateLastPlayer{
  188. PID: playerTable.PID,
  189. OpenID: playerTable.OpenID,
  190. UID: playerTable.UID,
  191. GameNodeID: playerTable.NodeID,
  192. PlayerID: playerTable.PlayerID,
  193. PlayerName: playerTable.Lord.Name,
  194. PlayerLevel: playerTable.Lord.Level,
  195. Icon: 0,
  196. }
  197. actorRemote.CenterPlayer.UpdateLastPlayer(protoUpdatePlayer)
  198. }
  199. // 更新领主声望 // TODO 后面模块多了需要把功能整成模块 而不是现在这样所有模块在一个方法中枚举类型作为service_type的类型
  200. func (p *service) UpdatePrestige(playerID int64) {
  201. var (
  202. playerTable, _ = db.GetPlayerTable(playerID)
  203. mapNodeID = playerTable.Map.MapNodeID
  204. )
  205. // 没有地图不算
  206. if len(mapNodeID) <= 0 {
  207. return
  208. }
  209. prestiges := map[int32]int32{}
  210. // 计算英雄星级增加
  211. heroTable := db.GetHeroTable(playerID)
  212. heroStars := heroTable.Heroes.GetHeroStarCount()
  213. for star, count := range heroStars {
  214. heroStarRow, found := data.HeroStar.GetByStar(star)
  215. if !found {
  216. clog.Warnf("[UpdateLordPrestige] hero star config not found. playerID:%d, star:%d", playerID, star)
  217. continue
  218. }
  219. prestiges[int32(enum.Prestige_Type_HeroStar)] += heroStarRow.AddPrestige * count
  220. }
  221. // TODO 其他模块计算
  222. // 判断是否存在地图,如果存在地图则通知地图
  223. target := cfacade.NewChildPath(mapNodeID, nameActor.Map_Player, playerID)
  224. capp.Call(target, nameRemote.MapPlayer_UpdatePrestige, &pb.I32Map{
  225. Value: prestiges,
  226. })
  227. clog.Infof("[UpdateLordPrestige] prestiges:%+v", prestiges)
  228. }
  229. func (p *service) CheckPlayerShow(playerTable *db.PlayerTable) {
  230. // 检测初始化外显
  231. for _, lordShow := range data.LordShow.List() {
  232. if lordShow.ActiveCondition.Key <= 0 {
  233. if _, found := playerTable.Shows.GetShow(lordShow.ShowID); !found {
  234. playerTable.Shows.ActiveShow(lordShow.ShowID, lordShow.ExpireTime)
  235. }
  236. }
  237. }
  238. // 检测外显过期
  239. playerTable.CheckShowExpire(ctime.Now().ToSecond())
  240. }