service.go 9.9 KB

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