123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- package game
- import (
- "encoding/json"
- "fmt"
- "log"
- "microGame/app/usercenter/cmd/api/internal/types"
- "microGame/pkg/common"
- "microGame/pkg/result"
- "sync"
- "time"
- )
- // Hub maintains the set of active Players and broadcasts messages to the Players.
- type Hub struct {
- Rooms map[int64]*Room // 保存所有连接实例
- Players map[int64]*Player // 保存所有连接实例
- Broadcast chan []byte // 消息存放在这里
- Register chan *Player
- Unregister chan *Player
- Mutex sync.Mutex // 并发安全锁
- }
- func NewHub() *Hub {
- return &Hub{
- Broadcast: make(chan []byte),
- Register: make(chan *Player),
- Unregister: make(chan *Player),
- Rooms: make(map[int64]*Room),
- Players: make(map[int64]*Player),
- }
- }
- func (r *Hub) Run() {
- // 启动调度任务
- //go r.GoCronRoom(3 * time.Second)
- for {
- select {
- case player := <-r.Register:
- r.handleRegister(player)
- case player := <-r.Unregister:
- r.handleUnregister(player)
- case message := <-r.Broadcast:
- r.handleBroadcast(message)
- }
- }
- }
- // 处理用户注册逻辑 此处仅仅记录所有的长连接用户
- func (r *Hub) handleRegister(o *Player) {
- if _, ok := r.Players[o.Uid]; !ok {
- r.Players[o.Uid] = o
- }
- o.WriteMsg(result.WSSuccess("register", types.MSG_SUCCESS))
- fmt.Printf("Player %d registered in Players", o.Uid)
- }
- // 处理用户注销逻辑
- func (r *Hub) handleUnregister(p *Player) {
- if r.removePlayerFromRoom(p.Uid, p.RoomId) {
- close(p.Send)
- close(p.actions)
- }
- r.tellUserLeave(p)
- fmt.Printf("Player %d unregistered from Room %d\n", p.Uid, p.RoomId)
- }
- // 处理消息广播逻辑
- func (r *Hub) handleBroadcast(message []byte) {
- d := &types.WSMessage{}
- if err := json.Unmarshal(message, d); err != nil {
- fmt.Printf("Failed to unmarshal message: %v\n", err)
- return
- }
- switch d.Type {
- case "join":
- //判断游戏是否开始,如果游戏已经开始 用户进入观察者组;如果没开始 用户直接进入room
- room, code := r.addPlayerToRoom(d)
- if code == 200 {
- room.startGame()
- }
- case "leave":
- r.removePlayerFromRoom(d.Uid, d.Rid)
- log.Printf("玩家/观察者 %d 退出", d.Uid)
- case "destroy":
- r.destroyRoom(d.Rid)
- log.Printf("玩家/观察者 %d 退出", d.Uid)
- case "bet":
- room, exists := r.Rooms[d.Rid]
- if exists {
- room.bet(d, r.Players[d.Uid])
- }
- log.Printf("玩家下注 %d 退出", d.Uid)
- case "sitDown":
- room, exists := r.Rooms[d.Rid]
- if exists {
- room.sitDown(d, r.Players[d.Uid])
- }
- case "standUp":
- room, exists := r.Rooms[d.Rid]
- if exists {
- room.standUp(d, r.Players[d.Uid])
- }
- default:
- log.Println("未知消息类型:", d.Type)
- }
- }
- // 将玩家添加到房间
- func (r *Hub) addPlayerToRoom(d *types.WSMessage) (*Room, int) {
- r.Mutex.Lock()
- o, ok := r.Players[d.Uid]
- if !ok {
- r.Mutex.Unlock()
- log.Printf("观察者 %s 加入房间", o.Username)
- return nil, -1000
- }
- room, exists := r.Rooms[d.Rid]
- if !exists {
- room = NewRoom(9, SB, BB, CHIPS, Timeout)
- r.Rooms[d.Rid] = room
- }
- r.Mutex.Unlock()
- //加入房间之前先判断房间是否已经满了
- if room.Len() >= room.Cap() {
- o.WriteMsg(result.WSError("register", types.MSG_ROOM_FULL, -1001))
- return nil, -1001
- }
- joinRoom := &types.JoinRoom{Uid: d.Uid, RoomNumber: r.Rooms[d.Rid].RoomNumber, RoomPwd: ""}
- res := room.joinRoom(joinRoom, o)
- if !res {
- return nil, -1002
- }
- return room, 200
- }
- // 从房间移除玩家
- func (r *Hub) removePlayerFromRoom(uid int64, rid int64) bool {
- r.Mutex.Lock()
- defer r.Mutex.Unlock()
- p, ok := r.Players[uid]
- if !ok {
- r.Mutex.Unlock()
- log.Printf("从房间移除玩家 %s", p.Username)
- return false
- }
- room, exists := r.Rooms[rid]
- if !exists {
- return false
- }
- p.RoomId = 0
- room.removePlayer(p)
- room.removeObserve(p)
- return true
- }
- // CreateRoom 创建房间
- func (r *Hub) CreateRoom(uid int64) *Room {
- r.Mutex.Lock()
- defer r.Mutex.Unlock()
- p, ok := r.Players[uid]
- if !ok {
- return nil
- }
- room, exists := r.Rooms[p.RoomId]
- if !exists {
- room = NewRoom(9, SB, BB, CHIPS, Timeout)
- r.Rooms[p.RoomId] = room
- p.RoomId = room.Rid
- fmt.Printf("房间 %d 创建成功\n", p.RoomId)
- return room
- }
- fmt.Printf("房间 %d 已存在\n", p.RoomId)
- go room.startGame()
- return room
- }
- // GoCronRoom 启动房间 Goroutine
- func (r *Hub) GoCronRoom(tickerInterval time.Duration) {
- ticker := time.NewTicker(tickerInterval)
- defer ticker.Stop()
- for {
- select {
- case <-ticker.C:
- r.checkAndStartRooms()
- }
- }
- }
- func (r *Hub) checkAndStartRooms() {
- r.Mutex.Lock()
- rooms := make(map[int64]*Room, len(r.Rooms))
- for rid, v := range r.Rooms {
- rooms[rid] = v
- }
- r.Mutex.Unlock()
- for rid, room := range rooms {
- if room == nil || room.isEmpty() {
- r.destroyRoom(rid) // 清理无效或空房间
- continue
- }
- // 防止重复启动
- if room.isRunning {
- continue
- }
- // 标记房间正在运行
- room.isRunning = true
- go common.RunWithRecover(func() {
- room.startGame()
- })
- }
- }
- // **destroyRoom**: 房间销毁时调用
- func (r *Hub) destroyRoom(roomID int64) {
- //如果房间中游戏正在进行中 不允许销毁房间
- r.Mutex.Lock()
- room, exists := r.Rooms[roomID]
- if !exists {
- r.Mutex.Unlock()
- return
- }
- if room.status == 1 {
- r.Mutex.Unlock()
- return
- }
- // 关闭房间,通知 Goroutine 退出
- room.CloseRoomChannel()
- delete(r.Rooms, roomID) // 从 Hub 中删除
- r.Mutex.Unlock()
- log.Printf("房间 %d 已销毁\n", roomID)
- }
- // GetRoom 获取房间
- func (r *Hub) GetRoom(roomID int64) *Room {
- if room, exists := r.Rooms[roomID]; exists {
- return room
- }
- return nil
- }
- // DeleteRoom 删除房间
- func (r *Hub) DeleteRoom(roomID int64) {
- r.Mutex.Lock()
- defer r.Mutex.Unlock()
- delete(r.Rooms, roomID)
- }
- // 用户离开 广播给所有其他会员用户离开
- func (r *Hub) tellUserLeave(o *Player) {
- r.Mutex.Lock()
- room, exists := r.Rooms[o.RoomId]
- r.Mutex.Unlock() // 提前释放锁,避免阻塞
- if !exists {
- o.WriteMsg(result.WSSuccess("register", types.MSG_NOT_IN_ROOM))
- return
- }
- // 构造广播消息
- msg := &types.WSMessage{
- Type: "leave",
- Data: "",
- Uid: 100,
- Rid: 100,
- }
- // 发送广播
- room.Broadcast(result.WSSuccess("leave", msg), true, 100)
- }
- //func (r *Hub) getMapKeys(m map[int64]*Player) []int64 {
- // keys := make([]int64, 0, len(m))
- // for k := range m {
- // keys = append(keys, k)
- // }
- // return keys
- //}
|