package quest import ( "f1-game/internal/data" "f1-game/internal/enum" facade "f1-game/internal/facade" nameRoute "f1-game/internal/name/route" "f1-game/internal/pb" "f1-game/internal/sessions" "f1-game/nodes/map/internal/db" dbMapPlayer "f1-game/nodes/map/internal/db/data/player" "slices" ctime "github.com/cherry-game/cherry/extend/time" cfacade "github.com/cherry-game/cherry/facade" cproto "github.com/cherry-game/cherry/net/proto" clog "github.com/cherry-game/cherry/logger" ) var srv = &service{ groupOpen: newServiceGroupOpen(), typ: newServiceType(), } func Service() *service { return srv } type service struct { facade.PlayerServiceBase[*db.MapPlayerTable] typ serviceType groupOpen serviceGroupOpen } func (p *service) OnLogin(playerTable *db.MapPlayerTable, session *cproto.Session) { for _, quest := range playerTable.Quests.MapQuests { if quest.Status != enum.QuestStatus_Running { continue } row, ok := data.Quest.GetByQuestGroupIDQuestID(quest.QuestGroupID, quest.QuestID) if !ok { continue } if len(row.QuestParams) < 1 { clog.Warnf("[OnLogin] quest params is empty. playerID = %d, questID = %d", playerTable.PlayerID, quest.QuestID) continue } quest.CheckDataFinish(row.QuestParams[0]) } } // func (p *service) OnLogined(playerTable *db.PlayerTable, _ *cproto.Session) { // } // func (p *service) OnLogout(playerTable *db.PlayerTable) { // } func (p *service) OnReset(playerTable *db.MapPlayerTable, _ *ctime.CherryTime, byLogin bool) { if !playerTable.Stats.IsCanReset() { return } save := false // 删除每日/周玩家任务 if update := p.clearMapPlayerQuest(playerTable); update { save = true } // 删除每日/周联盟任务 if update := p.clearLeagueQuest(playerTable); update { save = true } if save { playerTable.Save2Queue() } // 重置检查是否有新任务 TODO 地图不配置每日/周任务 //p.checkQuestReset(playerTable.PlayerID) } func (p *service) clearMapPlayerQuest(playerTable *db.MapPlayerTable) bool { delIDList := []int32{} for _, questEntity := range playerTable.Quests.MapQuests { groupRow, found := data.QuestGroup.GetByGroupID(questEntity.QuestGroupID) // 删除配表找不到的任务 if !found { delIDList = append(delIDList, questEntity.QuestID) continue } // 删除 日循环任务 if playerTable.Stats.IsDayReset && groupRow.ResetType == enum.QuestResetType_HourOfDay { delIDList = append(delIDList, questEntity.QuestID) continue } // 删除 周循环任务 if playerTable.Stats.IsWeekReset && groupRow.ResetType == enum.QuestResetType_DayOfWeek { delIDList = append(delIDList, questEntity.QuestID) continue } } if len(delIDList) <= 0 { return false } playerTable.Quests.DeleteQuests(delIDList) return true } func (p *service) clearLeagueQuest(playerTable *db.MapPlayerTable) bool { removeLeagueQuestIDs := []int32{} // 删除联盟任务 for questID := range playerTable.Quests.LeagueQuestIDs { questRow, found := data.Quest.GetByQuestID(questID) // 配置不存在删除 if !found { removeLeagueQuestIDs = append(removeLeagueQuestIDs, questID) continue } groupRow, found := data.QuestGroup.GetByGroupID(questRow.QuestGroupID) if !found { removeLeagueQuestIDs = append(removeLeagueQuestIDs, questID) continue } // 删除 联盟日循环任务 if playerTable.Stats.IsDayReset && groupRow.ResetType == enum.QuestResetType_HourOfDay { removeLeagueQuestIDs = append(removeLeagueQuestIDs, questID) continue } // 删除 联盟周循环任务 if playerTable.Stats.IsWeekReset && groupRow.ResetType == enum.QuestResetType_DayOfWeek { removeLeagueQuestIDs = append(removeLeagueQuestIDs, questID) continue } } if len(removeLeagueQuestIDs) <= 0 { return false } playerTable.Quests.DeleteLeagueQuests(removeLeagueQuestIDs) return true } func (p *service) Push(playerTable *db.MapPlayerTable, session *cproto.Session) { p.ChangePushWithSession(session, playerTable.Quests.List()) // 推送联盟任务领取列表 push := playerTable.Quests.ToLeagueQuestList() sessions.PushWithSession(session, nameRoute.PushMapPlayer_QuestsLeague, push) } func (p *service) ChangePush(playerID int64, changeList []*dbMapPlayer.Quest) { session, found := sessions.GetSession(playerID) if !found { clog.Warnf("[ChangePushWithPlayerID] session not found. [playerID = %d]", playerID) return } p.ChangePushWithSession(session, changeList) } // ChangePush 推送任务变更列表 func (p *service) ChangePushWithSession(session *cproto.Session, changeList []*dbMapPlayer.Quest) { if len(changeList) < 1 { return } push := &pb.QuestList{} for _, quest := range changeList { protoQuest := quest.ToProto() push.Quests = append(push.Quests, &protoQuest) } sessions.PushWithSession(session, nameRoute.PushMapPlayer_Quests, push) } // CheckNewAndPush 检查是否有新的任务组&推送 func (p *service) checkQuestReset(playerID int64) { var ( playerTable = db.GetMapPlayerTable(playerID) groupRows = []*data.QuestGroupRow{} ) // 检查玩家表是否存在 if playerTable == nil { return } // 遍历配置,获取是否有新增加的任务&组 for _, groupRow := range data.QuestGroup.List() { // 功能触发类型的跳过 if groupRow.OpenType == enum.QuestOpenType_TriggerOpen { continue } //验证本组是否开放 if !p.groupOpen.validate(groupRow.OpenType, playerID, groupRow) { continue } // 添加满足的任务组配置 groupRows = append(groupRows, groupRow) } // 添加本组的任务 p.AddQuestWithGroups(playerTable, groupRows...) } // AddQuestWithGroups 根据任务组添加任务列表 func (p *service) AddQuestWithGroups(playerTable *db.MapPlayerTable, groupRows ...*data.QuestGroupRow) bool { if len(groupRows) < 1 { return false } changeList := []*dbMapPlayer.Quest{} for _, groupRow := range groupRows { questRows, found := data.Quest.ListByQuestGroupID(groupRow.GroupID) if !found { clog.Warnf("add quest with group fail, quest config not found. playerID:%d", playerTable.PlayerID) continue } for _, newQuestRow := range questRows { // 当前任务禁用, 跳过 if newQuestRow.Disabled { continue } newQuestEntity, ok := p.AddQuest(playerTable, newQuestRow) if !ok { continue } changeList = append(changeList, newQuestEntity) } } if len(changeList) < 1 { return false } // 保存任务数据 playerTable.Save2Queue() // 推送给客户端 p.ChangePush(playerTable.PlayerID, changeList) return true } // // AddQuest 添加一个任务 func (p *service) AddQuest(playerTable *db.MapPlayerTable, questRow *data.QuestRow) (*dbMapPlayer.Quest, bool) { if questRow == nil { clog.Warnf("quest is nil. [config = %+v]", questRow) return nil, false } if questRow.QuestType < 1 { clog.Warnf("quest type error. [config = %+v]", questRow) return nil, false } if playerTable.Quests.ContainQuest(questRow.QuestID) { return nil, false } if len(questRow.QuestParams) < 1 { clog.Warnf("quest params is empty. [config = %+v]", questRow) return nil, false } // 获取任务类型解析器 parser, found := p.typ.get(questRow.QuestType) if !found { clog.Warnf("quest type not implemented. [config = %+v]", questRow) return nil, false } // 创建任务 newQuestEntity := dbMapPlayer.NewQuest(questRow.QuestGroupID, questRow.QuestID) if !parser.OnCreate(playerTable.PlayerID, &newQuestEntity, questRow) { clog.Warnf("create new questID fail. [questID = %d]", questRow.QuestID) return nil, false } // 检查任务是否完成 newQuestEntity.CheckDataFinish(questRow.QuestParams[0]) // 添加任务到存储 isAdd := playerTable.Quests.AddQuest(&newQuestEntity) return &newQuestEntity, isAdd } // TriggerOpenGroup 触发添加任务组(手工调用该函数) func (p *service) TriggerOpenGroup(playerID int64, groupID int32) bool { playerTable := db.GetMapPlayerTable(playerID) if playerTable == nil { clog.Warnf("[TriggerOpenGroup] player not found. playerID:%d, groupID:%d", playerID, groupID) return false } if playerTable.Quests.ContainGroup(groupID) { return false } groupRow, found := data.QuestGroup.GetByGroupID(groupID) if !found { clog.Warnf("[TriggerOpenGroup] quest group not exist. playerID:%d, groupID:%d", playerID, groupID) return false } if groupRow.OpenType != enum.QuestOpenType_TriggerOpen { clog.Infof("[TriggerOpenGroup] openType != trigger open. playerID:%d, groupID:%d", playerID, groupID) return false } // 添加任务 success := p.AddQuestWithGroups(playerTable, groupRow) return success } func (p *service) DoQuestEvent(playerID int64, e cfacade.IEventData, isOnline bool) { var ( playerTable = db.GetMapPlayerTable(playerID) changeList []*dbMapPlayer.Quest // 任务变更列表 ) // 检查玩家表是否存在 if playerTable == nil { return } for _, questEntity := range playerTable.Quests.MapQuests { // 已完成或已结束的任务 则跳过 if questEntity.IsFinish() { continue } // 获取任务配置 questRow, found := data.Quest.GetByQuestGroupIDQuestID(questEntity.QuestGroupID, questEntity.QuestID) if !found { clog.Warnf("[playerID = %d, quest = %+v] quest config not found.", playerID, questEntity) continue } parser, found := p.typ.get(questRow.QuestType) if !found { clog.Warnf("[playerID = %d, quest = %+v] quest type not found.", playerID, questRow) continue } if !slices.Contains(parser.EventNames(), e.Name()) { continue } // 通过事件更新任务数据 if parser.OnUpdate(playerID, questEntity, questRow, e) { // add to change list changeList = append(changeList, questEntity) // 检查是否完成 questEntity.CheckDataFinish(questRow.QuestParams[0]) } } if len(changeList) > 0 { // 推送变更数据 playerTable.Save2Queue() // 玩家在线 推送任务列表 if isOnline { p.ChangePush(playerID, changeList) } } } func (p *service) EventNames() []string { return p.typ.eventNames() }