package entity import ( "context" "fmt" "sync" "time" "github.com/gogf/gf/v2/frame/g" ) type Player struct { MainConn Conn UserID uint32 //用户ID IsLogin bool //是否登录 mu sync.Mutex MapId uint32 //当前所在的地图ID loginChan chan struct{} // 登录完成通知通道 Nick string //昵称 StopChan chan struct{} //停止刷怪协程 context.Context } // PlayerOption 定义配置 Player 的函数类型 type PlayerOption func(*Player) // WithUserID 设置用户ID的选项函数 func WithUserID(userID uint32) PlayerOption { return func(p *Player) { p.UserID = userID } } func WithConn(c Conn) PlayerOption { return func(p *Player) { p.MainConn = c } } // NewPlayer 使用 Options 模式创建 Player 实例 func NewPlayer(opts ...PlayerOption) *Player { p := &Player{ loginChan: make(chan struct{}), } for _, opt := range opts { opt(p) } return p } func (p *Player) GetUserID() uint32 { return p.UserID } func (p *Player) SetData(key any) uint32 { return p.UserID } func (p *Player) SendPack(b []byte) error { err := p.MainConn.SendPack(b) return err } func (p *Player) Cheak(b error) { if b != nil { g.Log().Error(context.Background(), "出现错误", p.UserID, b.Error()) } } // IsLoggedIn 检查是否已登录 func (lw *Player) IsLoggedIn() bool { lw.mu.Lock() defer lw.mu.Unlock() return lw.IsLogin } // WaitForLogin 等待登录完成,无超时 func (lw *Player) WaitForLogin() error { if lw.IsLoggedIn() { return nil } // 阻塞等待登录完成 <-lw.loginChan return nil } // WaitForLoginWithTimeout 带超时的登录等待 func (lw *Player) WaitForLoginWithTimeout(timeout time.Duration) error { if lw.IsLoggedIn() { return nil } // 使用定时器实现超时 timer := time.NewTimer(timeout) defer timer.Stop() select { case <-lw.loginChan: return nil case <-timer.C: return fmt.Errorf("登录等待超时: %v", timeout) } } // WaitForLoginWithCtx 带上下文的登录等待 func (lw *Player) WaitForLoginWithCtx(ctx context.Context) error { if lw.IsLoggedIn() { return nil } select { case <-lw.loginChan: return nil case <-ctx.Done(): return ctx.Err() // 上下文取消或超时 } } // CompleteLogin 标记登录完成并通知等待者 func (lw *Player) CompleteLogin() { lw.mu.Lock() defer lw.mu.Unlock() if !lw.IsLogin { lw.IsLogin = true close(lw.loginChan) // 关闭通道以通知所有等待者 } }