mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-08 22:51:30 -07:00
Merge branch 'main' into photon-testing
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
RoomInstanceType,
|
||||
setPresence,
|
||||
setRoomInstanceInProgress,
|
||||
subRoomDataBlob,
|
||||
} from '@repo/domain'
|
||||
import { logger, withCleanSpec, withNotFound, withOnError } from '@repo/hono-helpers'
|
||||
import { generatePhotonAuthToken, validateAndGetAccountId } from '@repo/jwt'
|
||||
@@ -34,7 +35,6 @@ import { generatePhotonAuthToken, validateAndGetAccountId } from '@repo/jwt'
|
||||
// Value import of the notify worker's NotificationType enum (its bundle has no runtime
|
||||
// deps), so /invite sends a typed MessageReceived frame instead of a magic number.
|
||||
import { NotificationType } from '../../notify/src/notification-types'
|
||||
|
||||
import {
|
||||
AUTHED,
|
||||
ConnectionInfoResponse,
|
||||
@@ -413,7 +413,11 @@ function instanceFieldsFromRoom(room: Room, subRoomId?: number) {
|
||||
roomId: num(room.RoomId, 1),
|
||||
subRoomId: num(sub?.SubRoomId, 1),
|
||||
location: str(sub?.UnitySceneId),
|
||||
dataBlob: str(sub?.DataBlob),
|
||||
// Always the PUBLISHED save. A creator who wants their unpublished work is offered
|
||||
// the choice client-side from the `/subrooms/{id}/saves` list — matchmaking is not
|
||||
// involved, and serving a staged blob here would put two people in one instance on
|
||||
// different versions.
|
||||
dataBlob: subRoomDataBlob(sub),
|
||||
name,
|
||||
maxCapacity: num(sub?.MaxPlayers, 4),
|
||||
roomInstanceType: room.IsDorm === true ? RoomInstanceType.Dormroom : RoomInstanceType.Public,
|
||||
@@ -743,7 +747,10 @@ const app = new Hono<App>()
|
||||
'`PlayerId`/`RoomInstanceId`). Currently just logged and acked — presence is cleared',
|
||||
'by logout and otherwise expires on its TTL — but the hook is here for a future check.',
|
||||
].join(' '),
|
||||
requestBody: form(NotifyDisconnectRequest, 'The disconnecting player and the instance they left'),
|
||||
requestBody: form(
|
||||
NotifyDisconnectRequest,
|
||||
'The disconnecting player and the instance they left'
|
||||
),
|
||||
responses: { 200: EMPTY_OK },
|
||||
}),
|
||||
async (c) => {
|
||||
|
||||
@@ -351,6 +351,59 @@ describe('public endpoints', () => {
|
||||
expect(unknown).toMatchObject({ subRoomId: 34, location: RECCENTER_SCENE })
|
||||
})
|
||||
|
||||
test('matchmaking serves the PUBLISHED save to everyone, creator included', async () => {
|
||||
// The client offers the owner "latest or published" itself, from the
|
||||
// `/subrooms/{id}/saves` list — matchmaking never picks. Serving a staged blob to
|
||||
// the creator here would put them on a different version to everyone else in the
|
||||
// same instance.
|
||||
const room = {
|
||||
RoomId: 78,
|
||||
Name: 'StagedRoom',
|
||||
IsDorm: false,
|
||||
Accessibility: 1,
|
||||
CreatorAccountId: 400,
|
||||
Roles: [{ AccountId: 401, Role: 30, LastChangedByAccountId: null, InvitedRole: 0 }],
|
||||
SubRooms: [
|
||||
{
|
||||
SubRoomId: 36,
|
||||
UnitySceneId: RECCENTER_SCENE,
|
||||
MaxPlayers: 10,
|
||||
// Seeded as the published save (seedRoomWithSubRooms mirrors the backfill).
|
||||
CurrentSave: { DataBlob: 'published.room' },
|
||||
},
|
||||
],
|
||||
}
|
||||
await seedRoomWithSubRooms(env.DB, room as unknown as Record<string, unknown>)
|
||||
// Stage a newer save the creator hasn't published.
|
||||
const staged = await env.DB.prepare(
|
||||
'INSERT INTO subroom_save (sub_room_id, data) VALUES (?1, ?2) RETURNING sub_room_data_save_id'
|
||||
)
|
||||
.bind(36, JSON.stringify({ DataBlob: 'staged.room' }))
|
||||
.first<{ sub_room_data_save_id: number }>()
|
||||
await env.DB.prepare('UPDATE subroom SET staged_save_id = ?2 WHERE sub_room_id = ?1')
|
||||
.bind(36, staged!.sub_room_data_save_id)
|
||||
.run()
|
||||
|
||||
const matchmake = async (sub: string) => {
|
||||
const res = await exports.default.fetch(`${ORIGIN}/matchmake/room/78/36`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...(await bearer(sub)),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'JoinMode=0',
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
return ((await res.json()) as { roomInstance: { dataBlob: string } }).roomInstance
|
||||
}
|
||||
|
||||
// Creator, co-owner and ordinary player all land on the same published version —
|
||||
// having a newer staged save changes nothing here.
|
||||
expect((await matchmake('400')).dataBlob).toBe('published.room')
|
||||
expect((await matchmake('401')).dataBlob).toBe('published.room')
|
||||
expect((await matchmake('402')).dataBlob).toBe('published.room')
|
||||
})
|
||||
|
||||
test('POST /matchmake/club/:clubId places members into the clubhouse', async () => {
|
||||
const matchmake = async (path: string, sub?: string) =>
|
||||
exports.default.fetch(`${ORIGIN}${path}`, {
|
||||
|
||||
Reference in New Issue
Block a user