package game import ( "fmt" "server/db" "server/game/mod/activity" "server/game/mod/msg" Msg "server/game/mod/msg" GoUtil "server/game_util" protoMsg "server/msg" "sync" "gitea.bywaystudios.com/pet_home/leaf/log" "google.golang.org/protobuf/encoding/protojson" ) type ActivityMgr struct { data *ActivityData } type ActivityData struct { List map[int]*ActivityCfg // 玩家排行榜 mu sync.Mutex } type ActivityCfg struct { Id int AId int Type int Startime int64 Endtime int64 Level int Title string MailTitle string MailContent string cfg interface{} Interval int64 Extra map[string]interface{} } func (ac *ActivityCfg) String() string { return fmt.Sprintf("Id: %d, Type: %d, StartTime: %d, EndTime: %d, Level: %d, Title: %s, MailTitle: %s, MailContent: %s, cfg: %v, Extra: %v", ac.Id, ac.Type, ac.Startime, ac.Endtime, ac.Level, ac.Title, ac.MailTitle, ac.MailContent, ac.cfg, ac.Extra) } func (ac *ActivityCfg) Copy() ActivityCfg { return ActivityCfg{ Id: ac.Id, AId: ac.AId, Type: ac.Type, Startime: ac.Startime, Endtime: ac.Endtime, Level: ac.Level, Title: ac.Title, MailTitle: ac.MailTitle, MailContent: ac.MailContent, cfg: ac.cfg, Interval: ac.Interval, Extra: ac.Extra, } } const () func (r *ActivityMgr) Init() { r.data = &ActivityData{ List: make(map[int]*ActivityCfg, 0), } r.Reload() } func (r *ActivityMgr) getData() *ActivityData { return r.data } // 零点更新 重置榜单 func (r *ActivityMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) { return nil, nil } func (r *ActivityMgr) GetActivityList() []ActivityCfg { // 获取活动列表 data := r.getData() data.mu.Lock() defer data.mu.Unlock() list := make([]ActivityCfg, 0, len(data.List)) now := GoUtil.Now() for _, v := range data.List { info := v.Copy() //循环活动,重新计算活动时间 if info.Interval > 0 { info.AId = int(info.Startime) list = append(list, info) internal := (now - info.Startime) / info.Interval for i := int64(0); i <= internal; i++ { newInfo := info.Copy() newInfo.Startime += info.Interval newInfo.Endtime += info.Interval newInfo.AId = int(newInfo.Startime) //活动id用开始时间表示,方便客户端排序 list = append(list, newInfo) } } else { list = append(list, info) } } return list } func (r *ActivityMgr) GetActivityListByType(atype int) ActivityCfg { // 获取活动列表 data := r.getData() data.mu.Lock() defer data.mu.Unlock() list := make([]ActivityCfg, 0, len(data.List)) now := GoUtil.Now() for _, v := range data.List { if v.Type == atype { info := v.Copy() //循环活动,重新计算活动时间 if info.Interval > 0 { info.AId = int(info.Startime) list = append(list, info) internal := (now - info.Startime) / info.Interval for i := int64(0); i <= internal; i++ { newInfo := info.Copy() newInfo.Startime += info.Interval newInfo.Endtime += info.Interval newInfo.AId = int(newInfo.Startime) //活动id用开始时间表示,方便客户端排序 list = append(list, newInfo) } } else { list = append(list, info) } } } for _, v := range list { if v.Startime <= GoUtil.Now() && v.Endtime > GoUtil.Now() { return v } } return ActivityCfg{} } func (r *ActivityMgr) GetActivityCfg(Id int) ActivityCfg { // 获取活动配置 data := r.getData() data.mu.Lock() defer data.mu.Unlock() cfg, ok := data.List[Id] if !ok { return ActivityCfg{} } return *cfg } func (r *ActivityMgr) Reload() error { // 重新加载活动配置 // 从数据库加载邮件 log.Debug("reload activity data") data := r.getData() data.mu.Lock() defer data.mu.Unlock() cfgList := make([]*db.SqlActivityCfgStruct, 0) err := db.GetActivityData(&cfgList) if err != nil { log.Error("LoadActivityData error: %v", err) return err } data.List = make(map[int]*ActivityCfg, 0) for _, v := range cfgList { activityCfg, err := unmarshalActivityCfg(v.Type, []byte(v.Cfg)) if err != nil { log.Error("Unmarshal activity cfg error: %v", err) continue } cfg := &ActivityCfg{ Id: v.Id, Type: v.Type, Startime: v.Start_time, Endtime: v.End_time, Level: v.Level, Title: v.Title, MailTitle: v.MailTitle, MailContent: v.MailContent, cfg: activityCfg, Interval: v.Interval, } log.Debug("load activity cfg: %v", cfg) data.List[v.Id] = cfg } go func() { actList := r.GetActivityList() for _, v := range actList { log.Debug("activity load success: type :%d, id :%d, startTime :%s, endTime :%s", v.Type, v.Id, GoUtil.FormatTime(v.Startime), GoUtil.FormatTime(v.Endtime)) } }() G_GameLogicPtr.NotifyAll(&Msg.Msg{Type: Msg.HANDLE_TYPE_ACTIVITY_RELOAD}) return nil } func unmarshalActivityCfg(atype int, buf []byte) (interface{}, error) { if len(buf) == 0 { return nil, nil } switch atype { case 1: cfg := &protoMsg.MiningCfg{} err := protojson.Unmarshal(buf, cfg) if err != nil { return nil, err } return cfg, nil case 9: cfg := &protoMsg.ChampionshipCfg{} err := protojson.Unmarshal(buf, cfg) if err != nil { return nil, err } return cfg, nil case 10: cfg := &protoMsg.CatReturnGiftCfg{} err := protojson.Unmarshal(buf, cfg) if err != nil { return nil, err } return cfg, nil } return nil, nil } func (r *ActivityMgr) GetCatReturnGiftCfg(id int) *protoMsg.CatReturnGiftCfg { data := r.getData() data.mu.Lock() defer data.mu.Unlock() for _, v := range data.List { if v.Type == activity.ACT_TYPE_CAT_RETURN_GIFT && v.Id == id { if cfg, ok := v.cfg.(*protoMsg.CatReturnGiftCfg); ok { return cfg } } } return nil } func (r *ActivityMgr) GetChampshipCfg(id int) *protoMsg.ChampionshipCfg { data := r.getData() data.mu.Lock() defer data.mu.Unlock() for _, v := range data.List { if v.Type == activity.ACT_TYPE_CHAMPION && v.Id == id { if cfg, ok := v.cfg.(*protoMsg.ChampionshipCfg); ok { cfg.Title = v.Title return cfg } } } return nil }