sync
This commit is contained in:
@@ -14,8 +14,11 @@ import {
|
||||
getSettingsTableDict,
|
||||
MATCH_ENTRY_FEE_RC,
|
||||
registerMatchRoutes,
|
||||
getAdminMmrLeaderboard,
|
||||
updateMatchUserBlue,
|
||||
type CreateRematchRoomFn,
|
||||
type OnMatchSettledFn,
|
||||
type OnBothPlayersConnectedFn,
|
||||
type MatchRoomSuccessEnvelope,
|
||||
} from './matches';
|
||||
import {
|
||||
@@ -97,6 +100,38 @@ function removeUserFromQueue(userId: number): void {
|
||||
}
|
||||
}
|
||||
|
||||
function removeRoomByMatchId(matchId: number): void {
|
||||
const index = Rooms.findIndex((room) => room.match_id === matchId);
|
||||
if (index < 0) return;
|
||||
const room = Rooms[index]!;
|
||||
const names = room.Players.map((p) => p.Name).join(', ');
|
||||
Rooms.splice(index, 1);
|
||||
logInfo('Room removed after match settled', { match_id: matchId, port: room.Port });
|
||||
recordHistory(
|
||||
`Room on port ${room.Port} removed (match ${matchId} settled) — had: ${names || 'nobody'}`
|
||||
);
|
||||
}
|
||||
|
||||
const onMatchSettled: OnMatchSettledFn = async (matchId) => {
|
||||
await runMatchmakerExclusive(async () => {
|
||||
removeRoomByMatchId(matchId);
|
||||
});
|
||||
};
|
||||
|
||||
function markRoomBothConnected(matchId: number): void {
|
||||
const room = Rooms.find((r) => r.match_id === matchId);
|
||||
if (!room || room.both_connected) return;
|
||||
room.both_connected = true;
|
||||
logInfo('Both players connected to match', { match_id: matchId, port: room.Port });
|
||||
recordHistory(`Both players connected on port ${room.Port} (match ${matchId})`);
|
||||
}
|
||||
|
||||
const onBothPlayersConnected: OnBothPlayersConnectedFn = async (matchId) => {
|
||||
await runMatchmakerExclusive(async () => {
|
||||
markRoomBothConnected(matchId);
|
||||
});
|
||||
};
|
||||
|
||||
/** GET / JSON only: same order as match DB — first joined = red, second = blue. Always includes `entry_fee`. */
|
||||
function roomResponseForViewer(room: Room, viewerUserId: number, betFeePercent: number): Room {
|
||||
const idx = room.Players.findIndex((p) => p.UserId === viewerUserId);
|
||||
@@ -176,7 +211,7 @@ const createRematchRoom: CreateRematchRoomFn = async ({ userRedId, userBlueId, e
|
||||
});
|
||||
};
|
||||
|
||||
registerMatchRoutes(app, typedSettings, { createRematchRoom });
|
||||
registerMatchRoutes(app, typedSettings, { createRematchRoom, onMatchSettled, onBothPlayersConnected });
|
||||
|
||||
app.get('/settings', async (req: Request, res: Response) => {
|
||||
if (req.query.password !== typedSettings.password) {
|
||||
@@ -242,6 +277,21 @@ app.get('/admin/history', (req: Request, res: Response) => {
|
||||
res.json({ ok: true, entries });
|
||||
});
|
||||
|
||||
/** Hidden MMR leaderboard (not shown to players). */
|
||||
app.get('/admin/mmr', async (req: Request, res: Response) => {
|
||||
if (req.query.password !== typedSettings.password) {
|
||||
res.status(403).send('403 Unauthorized');
|
||||
return;
|
||||
}
|
||||
const limit = parseAdminLinesParam(req.query.limit, 100, 500);
|
||||
const result = await getAdminMmrLeaderboard(typedSettings, limit);
|
||||
if (!result.ok) {
|
||||
res.status(503).json({ ok: false, error: result.error });
|
||||
return;
|
||||
}
|
||||
res.json({ ok: true, players: result.players });
|
||||
});
|
||||
|
||||
app.get('/', async (req: Request, res: Response) => {
|
||||
const auth = await authenticateMatchmakingRequest(req, typedSettings);
|
||||
if (!auth.ok) {
|
||||
@@ -306,12 +356,26 @@ app.get('/', async (req: Request, res: Response) => {
|
||||
return !expired;
|
||||
});
|
||||
}
|
||||
element.Players.forEach(player => {
|
||||
if (player.UserId === userId) {
|
||||
player.LastSeen = Date.now();
|
||||
joinedRoom = element;
|
||||
if (element.both_connected) {
|
||||
const seated = element.Players.find((player) => player.UserId === userId);
|
||||
if (seated) {
|
||||
element.Players = element.Players.filter((player) => player.UserId !== userId);
|
||||
logInfo(`${username} left connected match to matchmake again`, {
|
||||
port: element.Port,
|
||||
match_id: element.match_id ?? null,
|
||||
});
|
||||
recordHistory(
|
||||
`${username} left connected match on port ${element.Port} (match id ${element.match_id ?? '—'}) — matchmaking again`
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
element.Players.forEach((player) => {
|
||||
if (player.UserId === userId) {
|
||||
player.LastSeen = Date.now();
|
||||
joinedRoom = element;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (element.Players.length === 0) {
|
||||
// This room is empty, remove it
|
||||
|
||||
@@ -426,8 +490,10 @@ app.get('/cancel', async (req: Request, res: Response) => {
|
||||
const { userId } = auth.user;
|
||||
|
||||
await runMatchmakerExclusive(async () => {
|
||||
const isInRoom = Rooms.some((room) => room.Players.some((player) => player.UserId === userId));
|
||||
if (isInRoom) {
|
||||
const isInWaitingRoom = Rooms.some(
|
||||
(room) => !room.instance_started && room.Players.some((player) => player.UserId === userId)
|
||||
);
|
||||
if (isInWaitingRoom) {
|
||||
res.status(409).send("Can't cancel while already in a room");
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user