diff --git a/common/data/entity/player.go b/common/data/entity/player.go index fc7dff3e..36c0a6b9 100644 --- a/common/data/entity/player.go +++ b/common/data/entity/player.go @@ -2,6 +2,10 @@ package entity import ( "blazing/cool" + "context" + "fmt" + "sync" + "time" "github.com/panjf2000/gnet/v2" ) @@ -10,7 +14,9 @@ type Player struct { MainConn Conn UserID uint32 //用户ID IsLogin bool //是否登录 //TODO 待实现登录包为第一个包,后续再发其他的包 + mu sync.Mutex + loginChan chan struct{} // 登录完成通知通道 } // PlayerOption 定义配置 Player 的函数类型 @@ -30,7 +36,9 @@ func WithConn(c gnet.Conn) PlayerOption { // NewPlayer 使用 Options 模式创建 Player 实例 func NewPlayer(opts ...PlayerOption) *Player { - p := &Player{} + p := &Player{ + loginChan: make(chan struct{}), + } for _, opt := range opts { opt(p) } @@ -56,3 +64,64 @@ func ConutPlayer() int { return count //fmt.Println("元素数量:", count) // 输出: 3 } + +// 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) // 关闭通道以通知所有等待者 + } +} diff --git a/logic/controller/controller.go b/logic/controller/controller.go index a6479a09..e973a873 100644 --- a/logic/controller/controller.go +++ b/logic/controller/controller.go @@ -194,9 +194,14 @@ func Recv(c gnet.Conn, data handler.TomeeHeader) { if nameField.IsValid() && nameField.CanSet() { nameField.Set(reflect.ValueOf(data)) } - if cmdlister.Type().In(1) == reflect.TypeOf(entity.Player{}) { + if cmdlister.Type().In(1) == reflect.TypeOf(&entity.Player{}) { + c1 := service.GetPlayer(c, data.UserID) + err := c1.WaitForLoginWithCtx(context.Background()) + if err != nil { + fmt.Println("登录失败") + } - params = append(params, ptrValue1, reflect.ValueOf(service.GetPlayer(c, data.UserID))) + params = append(params, ptrValue1, reflect.ValueOf(c1)) } else { params = append(params, ptrValue1, reflect.ValueOf(c)) @@ -205,22 +210,7 @@ func Recv(c gnet.Conn, data handler.TomeeHeader) { cmdlister.Call(params) r := entity.Conn{MainConn: c} - // // 遍历结构体字段 - // // fmt.Printf("结构体 %s 的字段信息:\n", t.Name()) - // for i := 0; i < ptrValue1.Type().NumField(); i++ { - // field := ptrValue1.Type().Field(i) - // if field.Name == "Ret" { //判断Ret - - // } - - // } - // if cmdlister.Type().In(0).Implements(reflect.TypeOf((*Blazingservice)(nil)).Elem()) { - // fmt.Printf("参数 %d 是结构体且实现了 MyInterface 接口\n" ) - // tt1 - - // } else { - // fmt.Printf("参数 %d 是结构体但未实现 MyInterface 接口\n", i) // } aa := ptrValue1.Elem().Field(0).Addr().Interface() @@ -228,6 +218,7 @@ func Recv(c gnet.Conn, data handler.TomeeHeader) { //st, ok := aa.(Blazingservice) //fmt.Println(t.Ret()) if t.Ret() != nil { + err := r.SendPack(t.Ret()) if err != nil { fmt.Println(err) diff --git a/logic/controller/login.go b/logic/controller/login.go index 1ea448da..8eab8cfd 100644 --- a/logic/controller/login.go +++ b/logic/controller/login.go @@ -4,6 +4,7 @@ import ( "blazing/common/data/share" "blazing/logic/service" "blazing/logic/service/login" + "time" "github.com/panjf2000/gnet/v2" ) @@ -15,9 +16,11 @@ func (h *Controller) Login(data *login.LoginSidInfo, c gnet.Conn) { //这个时 h.RPCClient.Kick(data.Head.UserID) //先踢人 // h.RPCClient.UserLogin(int32(h.Port), int32(data.Head.UserID)) //初始化用户登录 - service.SetPlayer(c, data.Head.UserID) + t := service.SetPlayer(c, data.Head.UserID) share.ShareManager.SetUserOnline(data.Head.UserID, h.Port) //设置用户登录服务器 + t.CompleteLogin() //通知客户端登录成功 + <-time.After(3000) data.Def() } //data.Def() diff --git a/logic/controller/maphot.go b/logic/controller/maphot.go new file mode 100644 index 00000000..9c30dbc5 --- /dev/null +++ b/logic/controller/maphot.go @@ -0,0 +1,13 @@ +package controller + +import ( + "blazing/common/data/entity" + "blazing/logic/service/maps" +) + +func (h Controller) MapHot(data *maps.MapHotInboundInfo, c *entity.Player) { + + data.Def() + //fmt.Println("登录成功") + //log.Printf("任务 %s 执行中,已登录状态: %v\n", , lw.IsLoggedIn()) +} diff --git a/logic/controller/systemtime.go b/logic/controller/systemtime.go new file mode 100644 index 00000000..eaaec52a --- /dev/null +++ b/logic/controller/systemtime.go @@ -0,0 +1,12 @@ +package controller + +import ( + "blazing/common/data/entity" + "blazing/logic/service/system" +) + +func (h Controller) SystemTimeInfo(data *system.SystemTimeInfo, c *entity.Player) { + data.Def() + //fmt.Println("登录成功") + //log.Printf("任务 %s 执行中,已登录状态: %v\n", , lw.IsLoggedIn()) +} diff --git a/logic/service/maps/maphot.go b/logic/service/maps/maphot.go new file mode 100644 index 00000000..3ce6d9ca --- /dev/null +++ b/logic/service/maps/maphot.go @@ -0,0 +1,27 @@ +package maps + +import "blazing/common/socket/handler" + +// MapHotInfo 表示地图热度信息 +type MapHotInfo struct { + MapID uint64 `json:"mapId"` // 地图ID + Count uint64 `json:"count"` // 地图里的人数 +} +type MapHotInboundInfo struct { + Head handler.TomeeHeader `cmd:"1004" struc:"[0]pad"` //玩家登录 +} + +func (m *MapHotInboundInfo) Def() { + + m.Head.Set(MapHotOutboundInfo{ + + HotInfos: make([]MapHotInfo, 0), + }) //返回传参 + +} + +// MapHotOutboundInfo 表示地图热度的出站消息 +type MapHotOutboundInfo struct { + HotInfosLen uint32 `json:"hotInfosLen" struc:"sizeof=HotInfos"` // 热度信息列表长度 + HotInfos []MapHotInfo `json:"hotInfos"` // 热度信息列表 +} diff --git a/logic/service/system/System.go b/logic/service/system/System.go new file mode 100644 index 00000000..bbfa2d89 --- /dev/null +++ b/logic/service/system/System.go @@ -0,0 +1,30 @@ +package system + +import ( + "blazing/common/socket/handler" + "time" +) + +// LoginSidInfo 登录携带的凭证结构体 +type SystemTimeInfo struct { //这里直接使用组合来实现将传入的原始头部数据和结构体参数序列化 + Head handler.TomeeHeader `cmd:"1002" struc:"[0]pad"` //玩家登录 + +} + +func (s *SystemTimeInfo) Def() { //默认返回方法 + + s.Head.Set(NewSystemTimeOutboundInfo) //返回传参 + +} + +// SystemTimeOutboundInfo 表示系统时间的出站消息 +type SystemTimeOutboundInfo struct { + SystemTime uint32 `json:"systemTime"` // 对应Java的@UInt long类型 +} + +// NewSystemTimeOutboundInfo 创建新的系统时间消息实例 +func NewSystemTimeOutboundInfo() *SystemTimeOutboundInfo { + return &SystemTimeOutboundInfo{ + SystemTime: uint32(time.Now().Unix()), // 获取当前时间戳(秒) + } +}