I Want To Heal 2 build v1.0.5 code

This commit is contained in:
Warren H
2026-06-28 13:29:39 -04:00
parent 8abb44ea02
commit 257c34fc8d
53 changed files with 18187 additions and 1199 deletions
+134
View File
@@ -19,6 +19,10 @@ const port = Number(process.env.PORT ?? 4173)
const pool = createPool()
const sessionCookieName = 'iwanttoheal2_session'
const sessionLifetimeSeconds = 60 * 60 * 24 * 30
const arenaQueue = new Map()
const arenaMatches = new Map()
const arenaQueueTtlMs = 15 * 1000
const arenaMatchTtlMs = 60 * 60 * 1000
const corsOrigins = new Set(
(process.env.CORS_ORIGINS ?? '')
@@ -144,6 +148,10 @@ async function handleApi(request, response, url) {
if (!user) return
const body = await readJson(request)
const mode = String(body?.mode ?? 'action-healer')
if (mode === 'arenas') {
sendJson(response, 200, joinArenaQueue(user))
return
}
const rating = Number(body?.rating ?? 1000)
const queued = await pool.query(
`
@@ -159,6 +167,14 @@ async function handleApi(request, response, url) {
return
}
const arenaQueueTicket = url.pathname.match(/^\/api\/pvp\/queue\/([A-Za-z0-9_-]+)$/)
if (request.method === 'GET' && arenaQueueTicket) {
const user = await requireUser(request, response)
if (!user) return
sendJson(response, 200, checkArenaQueue(user, arenaQueueTicket[1]))
return
}
if (request.method === 'DELETE' && url.pathname === '/api/pvp/queue') {
const user = await requireUser(request, response)
if (!user) return
@@ -168,9 +184,127 @@ async function handleApi(request, response, url) {
return
}
if (request.method === 'DELETE' && arenaQueueTicket) {
const user = await requireUser(request, response)
if (!user) return
cancelArenaQueue(user, arenaQueueTicket[1])
sendJson(response, 200, { ok: true })
return
}
sendJson(response, 404, { error: 'not_found' })
}
function cleanupArenaMemory(now = Date.now()) {
for (const [ticketId, ticket] of arenaQueue.entries()) {
if (now - ticket.updatedAt > arenaQueueTtlMs) arenaQueue.delete(ticketId)
}
for (const [matchId, match] of arenaMatches.entries()) {
if (now - match.updatedAt > arenaMatchTtlMs) arenaMatches.delete(matchId)
}
}
function arenaPlayerInfo(user) {
return {
accountId: user.id,
displayName: user.display_name ?? user.username ?? 'Arena Player',
username: user.username ?? user.auth_subject,
}
}
function arenaSnapshot(match) {
return {
id: match.id,
mode: 'arenas',
createdAt: match.createdAt,
players: match.players,
updatedAt: match.updatedAt,
}
}
function createArenaMatch(players, now = Date.now()) {
const match = {
id: randomBytes(12).toString('base64url'),
players,
createdAt: now,
updatedAt: now,
}
arenaMatches.set(match.id, match)
return match
}
function joinArenaQueue(user) {
const now = Date.now()
cleanupArenaMemory(now)
const existingTicket = [...arenaQueue.values()].find((ticket) => ticket.accountId === user.id)
if (existingTicket?.matchId) {
const match = arenaMatches.get(existingTicket.matchId)
if (match) {
const side = match.players.a.accountId === user.id ? 'a' : 'b'
return { ticketId: existingTicket.id, status: 'matched', side, match: arenaSnapshot(match) }
}
}
const opponent = [...arenaQueue.values()]
.filter((ticket) => !ticket.matchId && ticket.accountId !== user.id)
.sort((left, right) => left.createdAt - right.createdAt)[0]
const player = arenaPlayerInfo(user)
if (opponent) {
const match = createArenaMatch({
a: { side: 'a', ...opponent.player },
b: { side: 'b', ...player },
}, now)
opponent.matchId = match.id
opponent.updatedAt = now
const ticketId = randomBytes(12).toString('base64url')
arenaQueue.set(ticketId, {
id: ticketId,
accountId: user.id,
player,
matchId: match.id,
createdAt: now,
updatedAt: now,
})
return { ticketId, status: 'matched', side: 'b', match: arenaSnapshot(match) }
}
if (existingTicket) {
existingTicket.updatedAt = now
return { ticketId: existingTicket.id, status: 'waiting' }
}
const ticketId = randomBytes(12).toString('base64url')
arenaQueue.set(ticketId, {
id: ticketId,
accountId: user.id,
player,
createdAt: now,
updatedAt: now,
})
return { ticketId, status: 'waiting' }
}
function checkArenaQueue(user, ticketId) {
cleanupArenaMemory()
const ticket = arenaQueue.get(ticketId)
if (!ticket || ticket.accountId !== user.id) {
const error = new Error('Arena queue ticket not found.')
error.status = 404
throw error
}
ticket.updatedAt = Date.now()
if (!ticket.matchId) return { ticketId, status: 'waiting' }
const match = arenaMatches.get(ticket.matchId)
if (!match) return { ticketId, status: 'waiting' }
const side = match.players.a.accountId === user.id ? 'a' : 'b'
return { ticketId, status: 'matched', side, match: arenaSnapshot(match) }
}
function cancelArenaQueue(user, ticketId) {
const ticket = arenaQueue.get(ticketId)
if (ticket && ticket.accountId === user.id && !ticket.matchId) arenaQueue.delete(ticketId)
}
async function handleAuthApi(request, response, url) {
if (!url.pathname.startsWith('/api/auth/')) return false