service.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. package quest
  2. import (
  3. "f1-game/internal/data"
  4. "f1-game/internal/enum"
  5. "f1-game/internal/facade"
  6. nameRoute "f1-game/internal/name/route"
  7. "f1-game/internal/pb"
  8. "f1-game/internal/sessions"
  9. "f1-game/nodes/game/internal/db"
  10. dbQuest "f1-game/nodes/game/internal/db/data/quest"
  11. "slices"
  12. ctime "github.com/cherry-game/cherry/extend/time"
  13. cfacade "github.com/cherry-game/cherry/facade"
  14. cactor "github.com/cherry-game/cherry/net/actor"
  15. cproto "github.com/cherry-game/cherry/net/proto"
  16. clog "github.com/cherry-game/cherry/logger"
  17. )
  18. var srv = &service{
  19. groupOpen: newServiceGroupOpen(),
  20. typ: newServiceType(),
  21. }
  22. func Service() *service {
  23. return srv
  24. }
  25. type service struct {
  26. facade.PlayerServiceBase[*db.PlayerTable]
  27. typ serviceType
  28. groupOpen serviceGroupOpen
  29. }
  30. func (p *service) OnLogin(playerTable *db.PlayerTable, _ *cproto.Session) {
  31. questTable := db.GetQuestTable(playerTable.PlayerID)
  32. for _, quest := range questTable.Quests {
  33. if quest.Status != enum.QuestStatus_Running {
  34. continue
  35. }
  36. row, ok := data.Quest.GetByQuestGroupIDQuestID(quest.QuestGroupID, quest.QuestID)
  37. if !ok {
  38. continue
  39. }
  40. if len(row.QuestParams) < 1 {
  41. clog.Warnf("[OnLogin] quest params is empty. playerID = %d, questID = %d", playerTable.PlayerID, quest.QuestID)
  42. continue
  43. }
  44. quest.CheckDataFinish(row.QuestParams[0])
  45. }
  46. }
  47. // func (p *service) OnLogined(playerTable *db.PlayerTable, _ *cproto.Session) {
  48. // }
  49. // func (p *service) OnLogout(playerTable *db.PlayerTable) {
  50. // }
  51. func (p *service) OnReset(playerTable *db.PlayerTable, _ *ctime.CherryTime, byLogin bool) {
  52. if !playerTable.Stats.IsCanReset() {
  53. return
  54. }
  55. var (
  56. questTable = db.GetQuestTable(playerTable.PlayerID)
  57. delIDList []int32
  58. )
  59. for _, questEntity := range questTable.Quests {
  60. groupRow, found := data.QuestGroup.GetByGroupID(questEntity.QuestGroupID)
  61. // 删除配表找不到的任务
  62. if !found {
  63. delIDList = append(delIDList, questEntity.QuestID)
  64. continue
  65. }
  66. // 删除 日循环任务
  67. if playerTable.Stats.IsDayReset && groupRow.ResetType == enum.QuestResetType_HourOfDay {
  68. delIDList = append(delIDList, questEntity.QuestID)
  69. continue
  70. }
  71. // 删除 周循环任务
  72. if playerTable.Stats.IsWeekReset && groupRow.ResetType == enum.QuestResetType_DayOfWeek {
  73. delIDList = append(delIDList, questEntity.QuestID)
  74. continue
  75. }
  76. }
  77. if len(delIDList) > 0 {
  78. questTable.DeleteQuests(delIDList)
  79. questTable.Save2Queue()
  80. }
  81. // 重置检查是否有新任务
  82. p.checkQuestReset(playerTable.PlayerID)
  83. }
  84. func (p *service) Push(playerTable *db.PlayerTable, session *cproto.Session) {
  85. questTable := db.GetQuestTable(playerTable.PlayerID)
  86. p.ChangePushWithSession(session, questTable.List())
  87. }
  88. func (p *service) ChangePush(playerID int64, changeList []*dbQuest.Quest) {
  89. session, found := sessions.GetSession(playerID)
  90. if !found {
  91. clog.Warnf("[ChangePushWithPlayerID] session not found. [playerID = %d]", playerID)
  92. return
  93. }
  94. p.ChangePushWithSession(session, changeList)
  95. }
  96. // ChangePush 推送任务变更列表
  97. func (p *service) ChangePushWithSession(session *cproto.Session, changeList []*dbQuest.Quest) {
  98. if len(changeList) < 1 {
  99. return
  100. }
  101. push := &pb.QuestList{}
  102. for _, quest := range changeList {
  103. protoQuest := quest.ToProto()
  104. push.Quests = append(push.Quests, &protoQuest)
  105. }
  106. sessions.PushWithSession(session, nameRoute.PushGamePlayer_Quests, push)
  107. }
  108. // CheckNewAndPush 检查是否有新的任务组&推送
  109. func (p *service) checkQuestReset(playerID int64) {
  110. var (
  111. questTable = db.GetQuestTable(playerID)
  112. groupRows = []*data.QuestGroupRow{}
  113. )
  114. // 遍历配置,获取是否有新增加的任务&组
  115. for _, groupRow := range data.QuestGroup.List() {
  116. // 功能触发类型的跳过
  117. if groupRow.OpenType == enum.QuestOpenType_TriggerOpen {
  118. continue
  119. }
  120. //验证本组是否开放
  121. if !p.groupOpen.validate(groupRow.OpenType, playerID, groupRow) {
  122. continue
  123. }
  124. // 添加满足的任务组配置
  125. groupRows = append(groupRows, groupRow)
  126. }
  127. // 添加本组的任务
  128. p.AddQuestWithGroups(questTable, groupRows...)
  129. }
  130. // AddQuestWithGroups 根据任务组添加任务列表
  131. func (p *service) AddQuestWithGroups(questTable *db.QuestTable, groupRows ...*data.QuestGroupRow) bool {
  132. if len(groupRows) < 1 {
  133. return false
  134. }
  135. changeList := []*dbQuest.Quest{}
  136. for _, groupRow := range groupRows {
  137. questRows, found := data.Quest.ListByQuestGroupID(groupRow.GroupID)
  138. if !found {
  139. clog.Warnf("add quest with group fail, quest config not found. playerID:%d", questTable.PlayerID)
  140. continue
  141. }
  142. for _, newQuestRow := range questRows {
  143. // 当前任务禁用, 跳过
  144. if newQuestRow.Disabled {
  145. continue
  146. }
  147. newQuestEntity, ok := p.AddQuest(questTable, newQuestRow)
  148. if !ok {
  149. continue
  150. }
  151. changeList = append(changeList, newQuestEntity)
  152. }
  153. }
  154. if len(changeList) < 1 {
  155. return false
  156. }
  157. // 保存任务数据
  158. questTable.Save2Queue()
  159. // 推送给客户端
  160. p.ChangePush(questTable.PlayerID, changeList)
  161. return true
  162. }
  163. // // AddQuest 添加一个任务
  164. func (p *service) AddQuest(questTable *db.QuestTable, questRow *data.QuestRow) (*dbQuest.Quest, bool) {
  165. if questRow == nil {
  166. clog.Warnf("quest is nil. [config = %+v]", questRow)
  167. return nil, false
  168. }
  169. if questRow.QuestType < 1 {
  170. clog.Warnf("quest type error. [config = %+v]", questRow)
  171. return nil, false
  172. }
  173. if questTable.ContainQuest(questRow.QuestID) {
  174. return nil, false
  175. }
  176. if len(questRow.QuestParams) < 1 {
  177. clog.Warnf("quest params is empty. [config = %+v]", questRow)
  178. return nil, false
  179. }
  180. // 获取任务类型解析器
  181. parser, found := p.typ.get(questRow.QuestType)
  182. if !found {
  183. clog.Warnf("quest type not implemented. [config = %+v]", questRow)
  184. return nil, false
  185. }
  186. // 创建任务
  187. newQuestEntity := dbQuest.NewQuest(questRow.QuestGroupID, questRow.QuestID)
  188. if !parser.OnCreate(questTable.PlayerID, &newQuestEntity, questRow) {
  189. clog.Warnf("create new questID fail. [questID = %d]", questRow.QuestID)
  190. return nil, false
  191. }
  192. // 检查任务是否完成
  193. newQuestEntity.CheckDataFinish(questRow.QuestParams[0])
  194. // 添加任务到存储
  195. isAdd := questTable.AddQuest(&newQuestEntity)
  196. return &newQuestEntity, isAdd
  197. }
  198. // TriggerOpenGroup 触发添加任务组(手工调用该函数)
  199. func (p *service) TriggerOpenGroup(playerID int64, groupID int32) bool {
  200. questTable := db.GetQuestTable(playerID)
  201. if questTable.ContainGroup(groupID) {
  202. return false
  203. }
  204. groupRow, found := data.QuestGroup.GetByGroupID(groupID)
  205. if !found {
  206. return false
  207. }
  208. if groupRow.OpenType != enum.QuestOpenType_TriggerOpen {
  209. clog.Infof("[playerID = %d] [groupID = %d] openType != trigger open")
  210. return false
  211. }
  212. // 添加任务
  213. return p.AddQuestWithGroups(questTable, groupRow)
  214. }
  215. func (p *service) InitEvents(event cactor.IEvent, playerID int64) {
  216. event.Registers(p.typ.eventNames(), p.onEvent, playerID)
  217. }
  218. func (p *service) onEvent(e cfacade.IEventData) {
  219. var (
  220. playerID = e.UniqueID()
  221. questTable = db.GetQuestTable(playerID) // quest table
  222. changeList []*dbQuest.Quest // 任务变更列表
  223. )
  224. for _, questEntity := range questTable.Quests {
  225. // 已完成或已结束的任务 则跳过
  226. if questEntity.IsFinish() {
  227. continue
  228. }
  229. // 获取任务配置
  230. questRow, found := data.Quest.GetByQuestGroupIDQuestID(questEntity.QuestGroupID, questEntity.QuestID)
  231. if !found {
  232. clog.Warnf("[playerID = %d, quest = %+v] quest config not found.", playerID, questEntity)
  233. continue
  234. }
  235. parser, found := p.typ.get(questRow.QuestType)
  236. if !found {
  237. clog.Warnf("[playerID = %d, quest = %+v] quest type not found.", playerID, questRow)
  238. continue
  239. }
  240. if !slices.Contains(parser.EventNames(), e.Name()) {
  241. continue
  242. }
  243. // 通过事件更新任务数据
  244. if parser.OnUpdate(playerID, questEntity, questRow, e) {
  245. // add to change list
  246. changeList = append(changeList, questEntity)
  247. // 检查是否完成
  248. questEntity.CheckDataFinish(questRow.QuestParams[0])
  249. }
  250. }
  251. if len(changeList) > 0 {
  252. // 推送变更数据
  253. questTable.Save2Queue()
  254. // 推送任务列表
  255. p.ChangePush(playerID, changeList)
  256. }
  257. }