更新功能、刷新不立即解散房间

This commit is contained in:
李琦
2026-08-15 09:14:40 +08:00
parent b7c629a797
commit 81159196b1
2 changed files with 59 additions and 10 deletions

View File

@@ -319,3 +319,30 @@ func (h *Hub) removeUserRoom(uid int) {
delete(h.userRoom, uid)
h.mu.Unlock()
}
// onStarveOfflineTimeout 饥荒等待中断线保护超时30秒内未重连才清座若房间无真人则解散
func (h *Hub) onStarveOfflineTimeout(r *Room, userID, seatIndex int) {
h.mu.Lock()
defer h.mu.Unlock()
r.mu.Lock()
defer r.mu.Unlock()
seat := r.seatByUser(userID)
if seat == nil || seat.Index != seatIndex || seat.Online || seat.client != nil || r.closed {
return
}
r.clearSeatLocked(seat)
r.broadcastStateLocked()
delete(h.userRoom, userID)
empty := true
for _, s := range r.seats {
if s.UserID > 0 {
empty = false
break
}
}
if empty {
delete(h.rooms, r.Code)
}
}

View File

@@ -31,16 +31,17 @@ const (
// Seat 房间内的一个座位
type Seat struct {
Index int // 座位号斗地主0-2象棋0红1黑
UserID int // 真人用户IDAI 座位为 0
Name string // 显示昵称
Avatar string // 头像
Skin string // 皮肤编码(饥荒组队联机:更衣室选择的皮肤)
IsAI bool // 是否 AI 座位
Ready bool // 是否已准备AI 恒为 true
Online bool // 是否在线(断线重连用)
Auto bool // 真人主动托管中(每回合由规则 AI 代打,结算后自动取消)
client *Client // 关联的连接AI 为 nil
Index int // 座位号斗地主0-2象棋0红1黑
UserID int // 真人用户IDAI 座位为 0
Name string // 显示昵称
Avatar string // 头像
Skin string // 皮肤编码(饥荒组队联机:更衣室选择的皮肤)
IsAI bool // 是否 AI 座位
Ready bool // 是否已准备AI 恒为 true
Online bool // 是否在线(断线重连用)
Auto bool // 真人主动托管中(每回合由规则 AI 代打,结算后自动取消)
client *Client // 关联的连接AI 为 nil
offlineTimer *time.Timer // 饥荒等待中断线保护30秒后仍未重连才清座
}
// chessState 象棋对局状态
@@ -93,6 +94,7 @@ type Room struct {
// 同一好友再次邀请的最短间隔
const inviteCooldown = 60 * time.Second
const starveOfflineGrace = 30 * time.Second // 饥荒等待中断线保护30秒内重连不散房
// newRoom 构造房间:按游戏类型确定座位数,按配置构造 AI 实例
func newRoom(code, game, mode, aiProvider, aiDifficulty string) *Room {
@@ -202,6 +204,10 @@ func (r *Room) reattach(c *Client) {
defer r.mu.Unlock()
for _, s := range r.seats {
if s.UserID == c.userID {
if s.offlineTimer != nil {
s.offlineTimer.Stop()
s.offlineTimer = nil
}
s.client = c
s.Online = true
r.touch()
@@ -223,6 +229,18 @@ func (r *Room) onOffline(c *Client) (leftRoom bool) {
seat.client = nil
seat.Online = false
if r.status == "waiting" {
if r.Game == "starve" {
// 饥荒等待中断线保护:保留座位 30 秒,刷新/断线重连成功后取消清理
if seat.offlineTimer != nil {
seat.offlineTimer.Stop()
}
offlineUID, offlineSeat := seat.UserID, seat.Index
seat.offlineTimer = time.AfterFunc(starveOfflineGrace, func() {
c.hub.onStarveOfflineTimeout(r, offlineUID, offlineSeat)
})
r.broadcastStateLocked()
return false
}
r.clearSeatLocked(seat)
r.broadcastStateLocked()
return true
@@ -301,6 +319,10 @@ func (r *Room) leave(c *Client) {
// clearSeatLocked 清空座位;房主离开时移交房主(需持锁)
func (r *Room) clearSeatLocked(seat *Seat) {
uid := seat.UserID
if seat.offlineTimer != nil {
seat.offlineTimer.Stop()
seat.offlineTimer = nil
}
*seat = Seat{Index: seat.Index}
if uid == r.hostUserID {
r.hostUserID = 0