package mapPlayer import ( capp "f1-game/internal/cherry_app" nameActor "f1-game/internal/name/actor" nameEvent "f1-game/internal/name/event" nameRemote "f1-game/internal/name/remote" "f1-game/internal/sessions" "f1-game/nodes/map/player/quest" "time" cslice "github.com/cherry-game/cherry/extend/slice" cstring "github.com/cherry-game/cherry/extend/string" ctime "github.com/cherry-game/cherry/extend/time" cfacade "github.com/cherry-game/cherry/facade" clog "github.com/cherry-game/cherry/logger" cactor "github.com/cherry-game/cherry/net/actor" ) // actor 玩家管理 type actor struct { cactor.Base cleanChildTime time.Duration mapEventRemote map[string]string } func Init(app cfacade.IApplication) { actor := NewActor() app.ActorSystem().CreateActor(actor.AliasID(), actor) } func NewActor() *actor { return &actor{ cleanChildTime: 10 * time.Minute, mapEventRemote: map[string]string{ nameEvent.Map_PlayerResGather: nameRemote.MapPlayer_ResGatherStats, nameEvent.Map_PlayerCrusadeBattle: nameRemote.MapPlayer_CrusadeBattleStats, nameEvent.Map_PlayerTileOccupy: nameRemote.MapPlayer_TileOccupyStats, nameEvent.Map_MarchArrive: nameRemote.MapPlayer_MarchArrive, nameEvent.Map_ResOccupy: nameRemote.MapPlayer_ResOccupy, nameEvent.Map_ResUpdate: nameRemote.MapPlayer_ResUpdate, }, } } func (p *actor) AliasID() string { return nameActor.Map_Player } func (p *actor) OnInit() { p.Timer().Add(p.cleanChildTime, p.cleanChildTimer) // 注册任务事件 p.Event().Registers(cslice.Unique[string](quest.Service().EventNames()...), p.onQuestEvent) for eventName := range p.mapEventRemote { p.Event().Register(eventName, p.onEvent) } } func (p *actor) OnLocalReceived(m *cfacade.Message) (bool, bool) { playerID := m.Session.GetString(sessions.PlayerID) if playerID == "" { clog.Warnf("[OnLocalReceived] player not found. m = %+v", m) return false, false } if child, found := p.Child().Get(playerID); found { child.PostLocal(m) } else { child := newActorPlayer(cstring.ToInt64D(playerID)) p.Child().Create(playerID, &child) child.PostLocal(m) } return false, false } func (p *actor) OnRemoteReceived(m *cfacade.Message) (bool, bool) { // 不拦截父actor的remote消息 if m.TargetPath().IsParent() { return true, false } playerID := m.TargetPath().ChildID if playerID == "" { clog.Warnf("[OnRemoteReceived] player not found. m = %+v", m) return false, false } if child, found := p.Child().Get(playerID); found { child.PostRemote(m) } else { child := newActorPlayer(cstring.ToInt64D(playerID)) p.Child().Create(playerID, &child) child.PostRemote(m) } return false, false } // cleanChildTimer 定期清理actorPlayer func (p *actor) cleanChildTimer() { // 玩家已下线,并且超过childExitTime时间没有收发消息,则退出actor deadline := ctime.Now().Add(-p.cleanChildTime).Unix() p.Child().Each(func(iActor cfacade.IActor) { if iActor.LastAt() < deadline { p.Call(iActor.Path().String(), nameRemote.MapPlayer_OnCheckExit, nil) } }) } func (p *actor) onQuestEvent(e cfacade.IEventData) { playerID := e.UniqueID() if playerID <= 0 { clog.Warnf("[onQuestEvent] playerID is invalid. playerID = %d, e = %+v", playerID, e) return } // remote到玩家 targetPath := cfacade.NewChildPath("", nameActor.Map_Player, playerID) capp.Call(targetPath, nameRemote.MapPlayer_QuestEvent, e) } func (p *actor) onEvent(e cfacade.IEventData) { playerID := e.UniqueID() if playerID <= 0 { clog.Warnf("[onEvent] playerID is invalid. name = %s, playerID = %d, e = %+v", e.Name(), playerID, e) return } // remote到玩家 targetPath := cfacade.NewChildPath("", nameActor.Map_Player, playerID) capp.Call(targetPath, p.mapEventRemote[e.Name()], e) }