package vip import ( capp "f1-game/internal/cherry_app" "f1-game/internal/code" "f1-game/internal/data" "f1-game/internal/event" facade "f1-game/internal/facade" nameActor "f1-game/internal/name/actor" nameRemote "f1-game/internal/name/remote" nameRoute "f1-game/internal/name/route" "f1-game/internal/pb" "f1-game/internal/sessions" "f1-game/nodes/game/internal/db" ctime "github.com/cherry-game/cherry/extend/time" cfacade "github.com/cherry-game/cherry/facade" clog "github.com/cherry-game/cherry/logger" cproto "github.com/cherry-game/cherry/net/proto" ) var srv = &service{} func Service() *service { return srv } type service struct { facade.PlayerServiceBase[*db.PlayerTable] } func (*service) OnReset(playerTable *db.PlayerTable, curTime *ctime.CherryTime, byLogin bool) { playerTable.Vip.DailyReset() playerTable.Save2Queue() } func (p *service) OnLogin(playerTable *db.PlayerTable, session *cproto.Session) { // 新用户初始化vip属性 if session.Contains(sessions.IsNewPlayer) { row := data.Vip.GetMinLevelRow() playerTable.Vip.Level = row.Level playerTable.Vip.Exp = 0 playerTable.Vip.Attrs = row.Attrs } } func (p *service) Push(playerTable *db.PlayerTable, session *cproto.Session) { proto := playerTable.Vip.ToProto() proto.ContinuousLoginDays = playerTable.Stats.ContinueLoginDays sessions.PushWithSession(session, nameRoute.PushGamePlayer_VipInfo, proto) } func (p *service) VipPush(playerTable *db.PlayerTable) { if session, found := sessions.GetSession(playerTable.PlayerID); found { p.Push(playerTable, session) } } func (p *service) AddExp(playerID int64, exp int64) int32 { var ( playerTable, _ = db.GetPlayerTable(playerID) vip = &playerTable.Vip levelUp bool maxLevel = data.Vip.GetMaxLevel() ) vip.Exp += exp // 是否升级 for vip.Level < maxLevel { row, ok := data.Vip.GetByLevel(vip.Level) if !ok { return code.ConfigNotFound_VipLevel } if row.Exp > vip.Exp { break } vip.Exp -= row.Exp // 升级 vip.Level++ // 更新属性 vip.Attrs = row.Attrs levelUp = true } // 保存 playerTable.Save2Queue() // 推送 if session, found := sessions.GetSession(playerID); found { p.Push(playerTable, session) } // 抛升级事件 if levelUp { capp.PostEvent(event.NewVipLevelUp(playerID, vip.Level)) // 升级也需要重新激活新的属性 if !vip.IsExpired { p.SyncMapActiveVip(playerTable) } // 发送系统消息事件 // capp.PostEvent(event.NewChatSystemMsg(playerID, enum.ChatMsgType_VipUp, nil, nil, vip.Level)) } return code.OK } // 增加VIP有效期天数 func (p *service) AddDay(playerID int64, day int32) int32 { var ( playerTable, _ = db.GetPlayerTable(playerID) vip = &playerTable.Vip now = ctime.Now() isActive = false // 是否是激活 ) // 先判断是否已经过期 if vip.ExpireTime < now.ToMillisecond() { vip.ExpireTime = now.ToMillisecond() isActive = true // 设置不过期 vip.IsExpired = false } vip.ExpireTime += int64(day * ctime.MillisecondsPerDay) playerTable.Save2Queue() // 推送 if session, found := sessions.GetSession(playerID); found { p.Push(playerTable, session) } if isActive { p.SyncMapActiveVip(playerTable) } return code.OK } // 同步到地图玩家激活的vip信息 func (p *service) SyncMapActiveVip(playerTable *db.PlayerTable) { // 如果地图还没开放就不同步,等地图开启再激活 if playerTable.Map.MapNodeID == "" { return } targetPath := cfacade.NewChildPath(playerTable.Map.MapNodeID, nameActor.Map_Player, playerTable.PlayerID) vipProto := &pb.SyncMapPlayerVip{ PlayerID: playerTable.PlayerID, Level: playerTable.Vip.Level, Attrs: playerTable.Vip.Attrs.ToProto(), ExpireTime: playerTable.Vip.ExpireTime, } capp.Call(targetPath, nameRemote.MapPlayer_SyncVip, vipProto) } // 检查VIP是否过期 func (p *service) CheckVipExpired(playerID int64) { playerTable, _ := db.GetPlayerTable(playerID) if playerTable.Vip.IsExpired { return } if playerTable.Vip.ExpireTime < ctime.Now().ToMillisecond() { playerTable.Vip.IsExpired = true playerTable.Save2Queue() clog.Debugf("[CheckVipExpired] playerID = %d, vip expired", playerID) } } // 获取VIP加成值 func (p *service) GetVipAttrAdd(playerID int64, attrID int32) int64 { playerTable, _ := db.GetPlayerTable(playerID) if playerTable.Vip.IsExpired { return 0 } return playerTable.Vip.Attrs.GetI64(attrID) }