stub /goto/room

This commit is contained in:
Devin Zuczek
2026-06-09 00:58:37 -04:00
parent 6222216993
commit 0fea1fff14
3 changed files with 61 additions and 7 deletions
+3 -2
View File
@@ -13,8 +13,9 @@ C# `MatchmakingController`. EF Core (`AppDbContext`) queries are stubbed for now
(the C# fell back to that file when the account/room instance wasn't found). (the C# fell back to that file when the account/room instance wasn't found).
- **`POST /goto/none`** returns the static offline-dorm instance with a fresh - **`POST /goto/none`** returns the static offline-dorm instance with a fresh
`photonRoomId`. `photonRoomId`.
- **`POST /goto/room/:room`** 404s — without a Rooms binding the room can't be - **`POST /goto/room/:room`** synthesizes the room-instance response (no Rooms
resolved, matching the C# `NotFound` path. binding yet). The dorm gets its known scene id and a private instance; other
rooms get an empty `location` and respect the posted `JoinMode` (2 = private).
- **`POST /player/heartbeat`** echoes the posted heartbeat fields; `roomInstance` - **`POST /player/heartbeat`** echoes the posted heartbeat fields; `roomInstance`
is always null and `isOnline` false until there's a DB binding. is always null and `isOnline` false until there's a DB binding.
- **`/player/login`, `/player/statusvisibility`, `/roominstance/:id/reportjoinresult`** - **`/player/login`, `/player/statusvisibility`, `/roominstance/:id/reportjoinresult`**
+34 -3
View File
@@ -123,9 +123,40 @@ const app = new Hono<App>()
.post('/goto/room/:room', async (c) => { .post('/goto/room/:room', async (c) => {
const id = await authedId(c) const id = await authedId(c)
if (id === null) return unauthorized(c) if (id === null) return unauthorized(c)
// No Rooms binding → the room can never be found (C# returns NotFound here).
// TODO: resolve the Room, upsert a RoomInstance, and return it. const room = c.req.param('room')
return c.text('Room not found', 404) const isDorm = room.toLowerCase() === 'dormroom'
const body = await c.req.parseBody().catch(() => ({}) as Record<string, unknown>)
const joinMode = typeof body.JoinMode === 'string' ? Number.parseInt(body.JoinMode, 10) || 0 : 0
const isPrivate = joinMode === 2 || isDorm
// No Rooms/SubRooms/RoomInstances bindings yet, so synthesize the instance
// the C# would build. The dorm scene id is known; other rooms get an empty
// location until there's real Room data.
// TODO: resolve the Room + SubRoom and upsert a RoomInstance once a DB binding exists.
return c.json({
errorCode: 0,
roomInstance: {
roomInstanceId: 1,
roomId: isDorm ? 1 : Number.parseInt(room, 10) || 1,
subRoomId: isDorm ? 1 : 0,
roomInstanceType: 2,
location: isDorm ? '76d98498-60a1-430c-ab76-b54a29b7a163' : '',
dataBlob: '',
eventId: 0,
clubId: 0,
roomCode: '',
photonRegionId: 'us',
photonRoomId: crypto.randomUUID(),
name: isDorm ? 'DormRoom' : room,
maxCapacity: 4,
isFull: false,
isPrivate,
isInProgress: false,
EncryptVoiceChat: false,
},
})
}) })
.post('/goto/none', (c) => .post('/goto/none', (c) =>
+24 -2
View File
@@ -81,12 +81,34 @@ describe('auth-gated endpoints', () => {
expect(res.status).toBe(401) expect(res.status).toBe(401)
}) })
test('POST /goto/room/:room 404s with a valid token (no DB)', async () => { test('POST /goto/room/dormroom returns the dorm instance', async () => {
const res = await exports.default.fetch(`${ORIGIN}/goto/room/dormroom`, { const res = await exports.default.fetch(`${ORIGIN}/goto/room/dormroom`, {
method: 'POST', method: 'POST',
headers: await bearer(), headers: await bearer(),
}) })
expect(res.status).toBe(404) expect(res.status).toBe(200)
const body = (await res.json()) as {
errorCode: number
roomInstance: { name: string; location: string; isPrivate: boolean; roomId: number }
}
expect(body.errorCode).toBe(0)
expect(body.roomInstance).toMatchObject({
name: 'DormRoom',
location: '76d98498-60a1-430c-ab76-b54a29b7a163',
isPrivate: true,
roomId: 1,
})
})
test('POST /goto/room/:id synthesizes an instance and honors JoinMode', async () => {
const res = await exports.default.fetch(`${ORIGIN}/goto/room/42`, {
method: 'POST',
headers: { ...(await bearer()), 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({ JoinMode: '2' }).toString(),
})
expect(res.status).toBe(200)
const body = (await res.json()) as { roomInstance: { roomId: number; isPrivate: boolean; name: string } }
expect(body.roomInstance).toMatchObject({ roomId: 42, isPrivate: true, name: '42' })
}) })
test('POST /player/heartbeat 401s without a token', async () => { test('POST /player/heartbeat 401s without a token', async () => {