133 lines
2.6 KiB
Go
133 lines
2.6 KiB
Go
package ws
|
||
|
||
import (
|
||
"sync"
|
||
|
||
chatmodel "leke/ws/model" // 按实际路径修改
|
||
)
|
||
|
||
// Hub 聊天中枢:管理所有连接和房间
|
||
type Hub struct {
|
||
mu sync.RWMutex
|
||
|
||
// 所有在线用户:userId -> Client
|
||
clients map[uint64]*Client
|
||
|
||
// 房间成员:roomId -> (userId -> Client)
|
||
rooms map[string]map[uint64]*Client
|
||
}
|
||
|
||
// 全局唯一 Hub(简单起见用一个全局变量)
|
||
var ChatHub = NewHub()
|
||
|
||
// NewHub 创建一个新的 Hub 实例
|
||
func NewHub() *Hub {
|
||
return &Hub{
|
||
clients: make(map[uint64]*Client),
|
||
rooms: make(map[string]map[uint64]*Client),
|
||
}
|
||
}
|
||
|
||
// Register 注册新连接
|
||
func (h *Hub) Register(c *Client) {
|
||
h.mu.Lock()
|
||
defer h.mu.Unlock()
|
||
|
||
h.clients[c.UserId] = c
|
||
// 默认认为所有在线用户都在世界频道,这里你可以根据需要扩展
|
||
}
|
||
|
||
// Unregister 移除连接(断线/退出)
|
||
func (h *Hub) Unregister(c *Client) {
|
||
h.mu.Lock()
|
||
defer h.mu.Unlock()
|
||
|
||
delete(h.clients, c.UserId)
|
||
|
||
// 同时把他从所有房间移除
|
||
for roomId, members := range h.rooms {
|
||
if _, ok := members[c.UserId]; ok {
|
||
delete(members, c.UserId)
|
||
if len(members) == 0 {
|
||
delete(h.rooms, roomId)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// JoinRoom 加入房间
|
||
func (h *Hub) JoinRoom(userId uint64, roomId string) {
|
||
h.mu.Lock()
|
||
defer h.mu.Unlock()
|
||
|
||
client, ok := h.clients[userId]
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
members, ok := h.rooms[roomId]
|
||
if !ok {
|
||
members = make(map[uint64]*Client)
|
||
h.rooms[roomId] = members
|
||
}
|
||
members[userId] = client
|
||
client.Rooms[roomId] = true
|
||
}
|
||
|
||
// LeaveRoom 离开房间
|
||
func (h *Hub) LeaveRoom(userId uint64, roomId string) {
|
||
h.mu.Lock()
|
||
defer h.mu.Unlock()
|
||
|
||
client, ok := h.clients[userId]
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
if members, ok := h.rooms[roomId]; ok {
|
||
delete(members, userId)
|
||
if len(members) == 0 {
|
||
delete(h.rooms, roomId)
|
||
}
|
||
}
|
||
delete(client.Rooms, roomId)
|
||
}
|
||
|
||
// BroadcastWorld 向所有在线用户发送世界频道消息
|
||
func (h *Hub) BroadcastWorld(msg *chatmodel.ChatMessage) {
|
||
h.mu.RLock()
|
||
defer h.mu.RUnlock()
|
||
|
||
for _, client := range h.clients {
|
||
_ = client.EnqueueMessage(msg)
|
||
}
|
||
}
|
||
|
||
// BroadcastRoom 向房间内所有用户发送消息
|
||
func (h *Hub) BroadcastRoom(roomId string, msg *chatmodel.ChatMessage) {
|
||
h.mu.RLock()
|
||
defer h.mu.RUnlock()
|
||
|
||
members, ok := h.rooms[roomId]
|
||
if !ok {
|
||
return
|
||
}
|
||
for _, client := range members {
|
||
_ = client.EnqueueMessage(msg)
|
||
}
|
||
}
|
||
|
||
// SendPrivate 发送私聊消息
|
||
func (h *Hub) SendPrivate(fromUserId, toUserId uint64, msg *chatmodel.ChatMessage) {
|
||
h.mu.RLock()
|
||
defer h.mu.RUnlock()
|
||
|
||
toClient, ok := h.clients[toUserId]
|
||
if !ok {
|
||
return // 对方不在线,可以后面扩展:离线消息存DB
|
||
}
|
||
|
||
msg.FromUserId = fromUserId
|
||
_ = toClient.EnqueueMessage(msg)
|
||
}
|