This commit is contained in:
React User
2026-05-05 20:01:28 +00:00
parent a09b33e158
commit 04b3463b19
24 changed files with 594 additions and 37 deletions
+31 -20
View File
@@ -9,6 +9,8 @@ import {
insertRematchMatch,
loadUsernamesForUserPair,
computeRcPrizeFromEntryFee,
getBetFeePercentFromSettings,
getDefaultMatchEntryFeeRc,
MATCH_ENTRY_FEE_RC,
registerMatchRoutes,
updateMatchUserBlue,
@@ -95,31 +97,32 @@ function removeUserFromQueue(userId: number): void {
}
/** GET / JSON only: same order as match DB — first joined = red, second = blue. Always includes `entry_fee`. */
function roomResponseForViewer(room: Room, viewerUserId: number): Room {
function roomResponseForViewer(room: Room, viewerUserId: number, betFeePercent: number): Room {
const idx = room.Players.findIndex((p) => p.UserId === viewerUserId);
const your_team: 'red' | 'blue' | null = idx === 0 ? 'red' : idx === 1 ? 'blue' : null;
const entry_fee = room.entry_fee ?? MATCH_ENTRY_FEE_RC;
const rc_prize = computeRcPrizeFromEntryFee(entry_fee);
const rc_prize = computeRcPrizeFromEntryFee(entry_fee, betFeePercent);
return { ...room, entry_fee, rc_prize, your_team };
}
/** Same envelope as `POST /internal/rematch` success: both sides when seated, else `null` for open slot. */
function roomMatchSuccessEnvelope(room: Room): MatchRoomSuccessEnvelope {
function roomMatchSuccessEnvelope(room: Room, betFeePercent: number): MatchRoomSuccessEnvelope {
const entry_fee = room.entry_fee ?? MATCH_ENTRY_FEE_RC;
const rc_prize = computeRcPrizeFromEntryFee(entry_fee);
const rc_prize = computeRcPrizeFromEntryFee(entry_fee, betFeePercent);
const redId = room.Players[0]?.UserId;
const blueId = room.Players[1]?.UserId;
return {
ok: true,
entry_fee,
rc_prize,
for_red: redId != null ? roomResponseForViewer(room, redId) : null,
for_blue: blueId != null ? roomResponseForViewer(room, blueId) : null,
for_red: redId != null ? roomResponseForViewer(room, redId, betFeePercent) : null,
for_blue: blueId != null ? roomResponseForViewer(room, blueId, betFeePercent) : null,
};
}
const createRematchRoom: CreateRematchRoomFn = async ({ userRedId, userBlueId, entryFee }) => {
return runMatchmakerExclusive(async () => {
const betFeePercent = await getBetFeePercentFromSettings(typedSettings);
const names = await loadUsernamesForUserPair(typedSettings, userRedId, userBlueId);
if (!names) {
return { ok: false, status: 404, error: 'One or both players not found' };
@@ -168,24 +171,30 @@ const createRematchRoom: CreateRematchRoomFn = async ({ userRedId, userBlueId, e
`Rematch room port ${newPort} match ${matchId}${redName} vs ${blueName} (entry_fee ${entryFee})`
);
return roomMatchSuccessEnvelope(newRoom);
return roomMatchSuccessEnvelope(newRoom, betFeePercent);
});
};
registerMatchRoutes(app, typedSettings, { createRematchRoom });
app.get('/settings', (req: Request, res: Response) => {
app.get('/settings', async (req: Request, res: Response) => {
if (req.query.password !== typedSettings.password) {
res.send("403 Unauthorized");
return;
}
const entry_fee = await getDefaultMatchEntryFeeRc(typedSettings);
const bet_fee = await getBetFeePercentFromSettings(typedSettings);
const rc_prize = computeRcPrizeFromEntryFee(entry_fee, bet_fee);
const m_settings = {
minimum_players: typedSettings.minimum_players,
maximum_players: typedSettings.maximum_players,
waiting_time: typedSettings.waiting_time,
port_range_min: typedSettings.port_range_min,
port_range_max: typedSettings.port_range_max,
games: typedSettings.games
games: typedSettings.games,
entry_fee,
bet_fee,
rc_prize,
};
logInfo(m_settings);
res.send(m_settings);
@@ -236,6 +245,8 @@ app.get('/', async (req: Request, res: Response) => {
try {
await runMatchmakerExclusive(async () => {
const betFeePercent = await getBetFeePercentFromSettings(typedSettings);
// Check query
let joinedRoom: Room | null = null;
let alreadyOnQueue = false;
@@ -306,13 +317,14 @@ app.get('/', async (req: Request, res: Response) => {
if (joinedRoom !== null) { // Already in a room. Stopping here
removeUserFromQueue(userId);
res.json(roomMatchSuccessEnvelope(joinedRoom));
res.json(roomMatchSuccessEnvelope(joinedRoom, betFeePercent));
return;
}
// Neither in a room nor in queue, Let's see
if (possibleRoom === null) {
if (Queue.length >= typedSettings.minimum_players) {
const insertResult = await insertMatchForNewRoom(typedSettings, userId);
const newPort = GetRandomPort(typedSettings.port_range_min, typedSettings.port_range_max);
const l10 = await getPlayerLast10MatchRecord(typedSettings, userId);
const newRoom: Room = {
@@ -320,18 +332,17 @@ app.get('/', async (req: Request, res: Response) => {
GameName: gameName,
Port: newPort,
InitTime: Date.now(),
entry_fee: MATCH_ENTRY_FEE_RC,
entry_fee: insertResult.entry_fee,
};
const matchId = await insertMatchForNewRoom(typedSettings, userId);
if (matchId != null) {
newRoom.match_id = matchId;
if (insertResult.matchId != null) {
newRoom.match_id = insertResult.matchId;
}
Rooms.push(newRoom);
removeUserFromQueue(userId);
recordHistory(
`${username} created a room on port ${newPort} (match id ${newRoom.match_id ?? '—'}) — waiting for opponent`
);
res.json(roomMatchSuccessEnvelope(newRoom));
res.json(roomMatchSuccessEnvelope(newRoom, betFeePercent));
return;
}
} else {
@@ -353,7 +364,7 @@ app.get('/', async (req: Request, res: Response) => {
`new room created with port ${room.Port} and matchId ${room.match_id ?? '—'} for ${p0.Name} and ${p1.Name}`
);
}
res.json(roomMatchSuccessEnvelope(room));
res.json(roomMatchSuccessEnvelope(room, betFeePercent));
return;
}
@@ -443,17 +454,17 @@ app.get('/reopen', async (req: Request, res: Response) => {
return;
}
const insertResult = await insertMatchForNewRoom(typedSettings);
const newRoom: Room = {
Players: [],
GameName: gameName,
Port: port,
InitTime: Date.now(),
entry_fee: MATCH_ENTRY_FEE_RC,
entry_fee: insertResult.entry_fee,
instance_started: true,
};
const matchId = await insertMatchForNewRoom(typedSettings);
if (matchId != null) {
newRoom.match_id = matchId;
if (insertResult.matchId != null) {
newRoom.match_id = insertResult.matchId;
}
Rooms.push(newRoom);