service.go 8.3 KB

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