Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
paopao
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
cocktail-party
paopao
Commits
c8fd4e62
提交
c8fd4e62
authored
3月 31, 2026
作者:
lidongxu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
修复:先2v2以后,复用同一个房间号进入1v1发现游戏结束2/4等待
上级
f537fb4b
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
49 行增加
和
11 行删除
+49
-11
rooms.js
server/src/routes/rooms.js
+10
-6
index.js
server/src/socket/index.js
+24
-1
roomHandler.js
server/src/socket/roomHandler.js
+15
-4
没有找到文件。
server/src/routes/rooms.js
浏览文件 @
c8fd4e62
...
@@ -2,6 +2,7 @@ const express = require('express');
...
@@ -2,6 +2,7 @@ const express = require('express');
const
router
=
express
.
Router
();
const
router
=
express
.
Router
();
const
prisma
=
require
(
'../prisma/client'
);
const
prisma
=
require
(
'../prisma/client'
);
const
{
getWaitingRoomTeamInfo
}
=
require
(
'../socket/roomHandler'
);
const
{
getWaitingRoomTeamInfo
}
=
require
(
'../socket/roomHandler'
);
const
{
getActiveRoomSubscriberCount
}
=
require
(
'../socket'
);
// GET /api/rooms — 获取所有房间列表(进行中房间含当前分数)
// GET /api/rooms — 获取所有房间列表(进行中房间含当前分数)
router
.
get
(
'/'
,
async
(
_req
,
res
,
next
)
=>
{
router
.
get
(
'/'
,
async
(
_req
,
res
,
next
)
=>
{
...
@@ -91,20 +92,23 @@ router.post('/allocate', async (_req, res, next) => {
...
@@ -91,20 +92,23 @@ router.post('/allocate', async (_req, res, next) => {
/**
/**
* 分配房间号:
* 分配房间号:
* 1. 优先复用已结束(finished)的最小房间号
* 1. 优先复用已结束(finished)的最小房间号
* 2. 没有可复用的,则取最大房间号 +1 递增
* 2. 复用前要求该房间当前没有任何活跃订阅连接
* 3. 从 1 开始,无上限
* 3. 没有可复用的,则取最大房间号 +1 递增
* 4. 从 1 开始,无上限
* @returns {Promise<string>} 房间号字符串
* @returns {Promise<string>} 房间号字符串
*/
*/
async
function
allocateRoomId
()
{
async
function
allocateRoomId
()
{
// 优先找一个已结束的房间号复用(取最小的)
// 优先找一个已结束
且当前无人订阅
的房间号复用(取最小的)
const
finished
=
await
prisma
.
room
.
findFirst
({
const
finished
Rooms
=
await
prisma
.
room
.
findMany
({
where
:
{
status
:
'finished'
},
where
:
{
status
:
'finished'
},
orderBy
:
{
roomId
:
'asc'
},
orderBy
:
{
roomId
:
'asc'
},
select
:
{
roomId
:
true
},
select
:
{
roomId
:
true
},
});
});
if
(
finished
)
{
for
(
const
room
of
finishedRooms
)
{
return
finished
.
roomId
;
if
(
getActiveRoomSubscriberCount
(
room
.
roomId
)
===
0
)
{
return
room
.
roomId
;
}
}
}
// 没有可复用的,取最大房间号 +1
// 没有可复用的,取最大房间号 +1
...
...
server/src/socket/index.js
浏览文件 @
c8fd4e62
...
@@ -70,6 +70,21 @@ function leaveAllRooms(ws) {
...
@@ -70,6 +70,21 @@ function leaveAllRooms(ws) {
}
}
}
}
/**
* 获取房间内当前活跃订阅连接数。
* role 为空时统计全部角色,传入后只统计指定角色。
*/
function
getActiveRoomSubscriberCount
(
roomId
,
role
=
null
)
{
const
subs
=
roomSubscribers
.
get
(
String
(
roomId
));
if
(
!
subs
)
return
0
;
return
[...
subs
].
filter
(
ws
=>
{
if
(
ws
.
readyState
!==
ws
.
OPEN
)
return
false
;
if
(
!
role
)
return
true
;
return
ws
.
ctx
?.
role
===
role
;
}).
length
;
}
/**
/**
* 初始化原生 WebSocket 服务,挂载到 /ws 路径
* 初始化原生 WebSocket 服务,挂载到 /ws 路径
*/
*/
...
@@ -147,4 +162,12 @@ function initSocket(httpServer) {
...
@@ -147,4 +162,12 @@ function initSocket(httpServer) {
return
wss
;
return
wss
;
}
}
module
.
exports
=
{
initSocket
,
broadcastToRoom
,
sendToScreen
,
joinRoom
,
leaveAllRooms
,
screenSockets
};
module
.
exports
=
{
initSocket
,
broadcastToRoom
,
sendToScreen
,
joinRoom
,
leaveAllRooms
,
getActiveRoomSubscriberCount
,
screenSockets
,
};
server/src/socket/roomHandler.js
浏览文件 @
c8fd4e62
...
@@ -68,6 +68,9 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
...
@@ -68,6 +68,9 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
const
duration
=
Number
(
gameDuration
)
||
0
;
// 0 表示不限时
const
duration
=
Number
(
gameDuration
)
||
0
;
// 0 表示不限时
try
{
try
{
// 同一个连接重新建房前,先退出旧房间,避免旧订阅残留到新局。
leaveAllRooms
(
ws
);
// 写库:waiting 状态
// 写库:waiting 状态
await
prisma
.
room
.
upsert
({
await
prisma
.
room
.
upsert
({
where
:
{
roomId
:
rid
},
where
:
{
roomId
:
rid
},
...
@@ -127,6 +130,9 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
...
@@ -127,6 +130,9 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
// 如果等待表里没有,说明是旧流程(游戏中直接 join),兼容处理
// 如果等待表里没有,说明是旧流程(游戏中直接 join),兼容处理
if
(
!
waiting
)
{
if
(
!
waiting
)
{
try
{
try
{
// 同一个连接重新进房前,先退出旧房间,避免旧订阅残留到新局。
leaveAllRooms
(
ws
);
await
prisma
.
room
.
upsert
({
await
prisma
.
room
.
upsert
({
where
:
{
roomId
:
rid
},
where
:
{
roomId
:
rid
},
update
:
{
status
:
'playing'
},
update
:
{
status
:
'playing'
},
...
@@ -150,6 +156,9 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
...
@@ -150,6 +156,9 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
return
;
return
;
}
}
// 同一个连接重新进房前,先退出旧房间,避免旧订阅残留到新局。
leaveAllRooms
(
ws
);
// 校验:房间是否已满
// 校验:房间是否已满
if
(
waiting
.
joined
.
size
>=
waiting
.
totalSeats
)
{
if
(
waiting
.
joined
.
size
>=
waiting
.
totalSeats
)
{
ws
.
sendEvent
(
'error'
,
{
message
:
'房间已满'
});
ws
.
sendEvent
(
'error'
,
{
message
:
'房间已满'
});
...
@@ -260,10 +269,12 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
...
@@ -260,10 +269,12 @@ function registerRoomHandlers(ws, { broadcastToRoom, joinRoom, leaveAllRooms, ro
const
roomScores
=
gameOverScores
.
get
(
roomId
);
const
roomScores
=
gameOverScores
.
get
(
roomId
);
roomScores
.
set
(
playerId
,
{
score
:
score
??
0
,
nickname
,
team
:
ws
.
ctx
.
team
});
roomScores
.
set
(
playerId
,
{
score
:
score
??
0
,
nickname
,
team
:
ws
.
ctx
.
team
});
// 获取房间内所有连接的 minigame 玩家数量
// 完成总人数以本局房间座位数为准,避免旧连接残留导致 1v1 被算成 4 人局。
const
subs
=
roomSubscribers
.
get
(
roomId
);
const
room
=
await
prisma
.
room
.
findUnique
({
const
minigamePlayers
=
subs
?
[...
subs
].
filter
(
s
=>
s
.
ctx
?.
role
===
'minigame'
)
:
[];
where
:
{
roomId
},
const
totalPlayers
=
minigamePlayers
.
length
;
select
:
{
totalSeats
:
true
},
});
const
totalPlayers
=
Number
(
room
?.
totalSeats
)
||
roomScores
.
size
;
const
reportedPlayers
=
roomScores
.
size
;
const
reportedPlayers
=
roomScores
.
size
;
console
.
log
(
`[Room] 游戏结束分数收集 roomId=
${
roomId
}
playerId=
${
playerId
}
score=
${
score
??
0
}
(
$
{
reportedPlayers
}
/${totalPlayers}
)
`
)
;
console
.
log
(
`[Room] 游戏结束分数收集 roomId=
${
roomId
}
playerId=
${
playerId
}
score=
${
score
??
0
}
(
$
{
reportedPlayers
}
/${totalPlayers}
)
`
)
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论