| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- package player
- import (
- actorRemote "f1-game/internal/actor_remote"
- capp "f1-game/internal/cherry_app"
- "f1-game/internal/code"
- "f1-game/internal/component/rate"
- "f1-game/internal/constant"
- "f1-game/internal/data"
- "f1-game/internal/event"
- nameLocal "f1-game/internal/name/local"
- nameRemote "f1-game/internal/name/remote"
- "f1-game/internal/pb"
- "f1-game/internal/sessions"
- "f1-game/nodes/game/internal/db"
- gameFacade "f1-game/nodes/game/internal/facade"
- ao "f1-game/nodes/game/player/asset/origin"
- "fmt"
- "math/rand/v2"
- ctime "github.com/cherry-game/cherry/extend/time"
- cfacade "github.com/cherry-game/cherry/facade"
- cproto "github.com/cherry-game/cherry/net/proto"
- )
- var (
- kickRsp = &pb.I32{
- Value: code.AccountLoginTimeout,
- }
- )
- // actorPlayer 每个玩家一个PlayerActor
- type actorPlayer struct {
- capp.ActorLogger
- playerID int64 // 当前玩家id
- isOnline bool // 玩家是否在线
- now *ctime.CherryTime // 玩家当前时间
- loggerPrefix string // logger prefix
- funcLimiter rate.FuncLimiter // 函数访问限速
- funcErrCode int32 // 函数访问的错误码
- }
- func newActorPlayer(playerID int64) actorPlayer {
- return actorPlayer{
- ActorLogger: capp.NewLoggerPrefix("playerID", playerID),
- playerID: playerID,
- isOnline: false,
- now: nil,
- loggerPrefix: fmt.Sprintf("[playerID = %d] ", playerID),
- funcLimiter: rate.NewFuncLimiter(30, 3, code.NodeRateLimiter),
- funcErrCode: code.NodeRateLimiter,
- }
- }
- func (p *actorPlayer) OnInit() {
- p.updateNowTime()
- p.initRateLimits()
- p.initRemote()
- p.initPlayer()
- p.initGM()
- p.initCharge()
- p.initItem()
- p.initQuest()
- p.initHero()
- p.initEquip()
- p.initRecruit()
- p.initLineup()
- p.initAsset()
- p.initFriend()
- p.initChat()
- p.initChapter()
- p.initShop()
- p.initLord()
- p.initMarquee()
- p.initVip()
- p.initMiniGame()
- }
- func (p *actorPlayer) initRemote() {
- p.Remote().Register(nameRemote.Player_OnEnter, p.enter)
- p.Remote().Register(nameRemote.Player_OnSessionClosed, p.onSessionClosed)
- p.Remote().Register(nameRemote.Player_OnCheckExit, p.onCheckExit)
- }
- func (p *actorPlayer) OnStop() {
- p.Info("[actorPlayer] OnStop() playerID = %d", p.playerID)
- p.Timer().RemoveAll()
- p.ActorLogger.Destory()
- }
- func (p *actorPlayer) OnLocalReceived(m *cfacade.Message) (bool, bool) {
- if !p.isOnline {
- p.Kick(m.Session, kickRsp, true)
- return false, false
- }
- p.funcErrCode = p.funcLimiter.Check(m.BuildTime, m.FuncName)
- if code.IsFail(p.funcErrCode) {
- p.ResponseCode(m.Session, p.funcErrCode)
- return false, false
- }
- return true, false
- }
- func (p *actorPlayer) updateNowTime() {
- now := ctime.Now()
- p.now = &now
- }
- func (p *actorPlayer) initRateLimits() {
- //p.limiter.Add(playerName.ChatChannelList, chatConst.SendFrequency, code.ChatGetListTooFast)
- //p.limiter.Add(playerName.ChatSend, chatConst.SendFrequency, code.ChatSendTextTooFast)
- // 举报频率限制
- p.funcLimiter.Add(nameLocal.Player_Complaint, constant.ComplaintFrequency, 1, code.ComplaintTooFast)
- }
- // enter 玩家进入游戏
- func (p *actorPlayer) enter(session *cproto.Session) {
- p.updateNowTime()
- p.playerID = sessions.GetPlayerID(session)
- isNewPlayer := session.Contains(sessions.IsNewPlayer)
- if isNewPlayer {
- // TODO 随机名字功能应该由客户端实现
- isMale := rand.Float32() < 0.5
- name := data.LordName.RandomName(isMale)
- playerTable, ok := db.NewPlayer(p.playerID, session, name)
- if !ok {
- p.ResponseCode(session, code.PlayerCreateFail)
- return
- }
- // 抛出玩家创建事件
- p.PostEvent(event.NewPlayerCreate(playerTable.PlayerID, playerTable.Lord.Name))
- } else {
- _, found := db.GetPlayerTable(p.playerID)
- if !found {
- p.ResponseCode(session, code.PlayerIDError)
- return
- }
- }
- p.Debug("[onEnter] sid = %s, isNewPlayer = %v", session.Sid, isNewPlayer)
- playerTable := p.PlayerTable()
- // TODO 先放这里,后面再看看放哪里合理
- if isNewPlayer {
- p.onNewPlayer()
- }
- p.onReset(playerTable, true)
- gameFacade.ServiceOnLogin(playerTable, session)
- p.onEnterResponse(playerTable, session)
- gameFacade.ServiceOnLogined(playerTable, session)
- }
- func (p *actorPlayer) onNewPlayer() {
- // 添加初始道具
- for _, asset := range data.Const.PlayerInitItems {
- gameFacade.Asset.Add(p.playerID, asset.ID, asset.Num, ao.CreatePlayer, false)
- }
- // 添加初始英雄
- for _, asset := range data.Const.PlayerInitHeros {
- gameFacade.Hero.AddOne(p.playerID, asset.ID, int32(asset.Num), ao.CreatePlayer, false)
- }
- // 添加初始装备
- for _, asset := range data.Const.PlayerInitEquips {
- gameFacade.Equip.Add(p.playerID, asset.ID, asset.Num, ao.CreatePlayer, false)
- }
- }
- // logout gate发送网络断开请求
- func (p *actorPlayer) onSessionClosed() {
- p.Info("[onLogout] playerID = %d", p.playerID)
- // 不在线则忽略
- if !p.isOnline {
- return
- }
- // 设置为离线状态
- // 必需设置为 false,如果玩家被顶号,actor 不会被销毁,不设置会导致玩家无法登录
- p.isOnline = false
- //移除当前玩家所有定时器
- p.Timer().RemoveAll()
- if playerTable := p.PlayerTable(); playerTable != nil {
- gameFacade.ServiceOnLogout(playerTable)
- }
- p.Info("[onLogout] finished! playerID = %d", p.playerID)
- }
- // 父actor检测到当前子actor很久收到消息,确认是否要退出
- func (p *actorPlayer) onCheckExit() {
- // 不在线则销毁当前actor
- if !p.isOnline {
- p.Exit()
- }
- }
- // setSession 设置gate的session属性
- func (p *actorPlayer) setSession(playerTable *db.PlayerTable, session *cproto.Session) {
- // 更新gate节点的session
- sessionProto := pb.StrStrList{}
- sessionProto.Add(sessions.GameNodeID, p.App().NodeID())
- sessionProto.Add(sessions.PlayerID, p.playerID)
- if playerTable.Map.MapNodeID != "" {
- sessionProto.Add(sessions.MapNodeID, playerTable.Map.MapNodeID)
- }
- actorRemote.GateUser.SetSession(session.ActorPath(), &sessionProto)
- }
- // onReset 重置处理(每次登录、跨天触发)
- func (p *actorPlayer) onReset(playerTable *db.PlayerTable, byLogin bool) {
- playerTable.Stats.CheckReset(p.now)
- // 无需重置,则跳过
- if !playerTable.Stats.IsCanReset() {
- return
- }
- p.Debug("[onReset] playerID = %d", p.playerID)
- // 各系统模块执行重置
- gameFacade.ServiceOnReset(playerTable, p.now, byLogin)
- // 发送跨天重置事件
- p.PostEvent(event.NewPlayerReset(p.playerID))
- p.Warn("daily reset finish. playerID=%d", p.playerID)
- }
- // onEnterEnd 推送各模块数据给客户端
- func (p *actorPlayer) onEnterResponse(playerTable *db.PlayerTable, session *cproto.Session) {
- // 推送数据列表
- gameFacade.ServicePush(playerTable, session)
- // 推送完各个模块数据后再设置session
- p.setSession(playerTable, session)
- // 推送 玩家进入游戏响应结果 客户端收到表示登录数据推送完成
- playerPB := playerTable.ToPlayerProto()
- response := &pb.PlayerEnterResponse{
- Player: &playerPB,
- }
- p.Response(session, response)
- // 登录完成后,设置玩家在线状态
- p.isOnline = true
- // 在线状态设置后,再启动定时器
- p.startTimer()
- // 提交 玩家登录事件
- p.PostEvent(event.NewPlayerLogin(p.playerID, session))
- p.Debug("[onEnterResponse]")
- }
|