fixed room and subroom saving, add room saves

This commit is contained in:
Devin Zuczek
2026-07-28 20:29:20 -04:00
parent a28b9b4561
commit d5ccad51d3
8 changed files with 728 additions and 58 deletions
+37 -14
View File
@@ -25,6 +25,7 @@ import {
getRoomsByCreator,
getRoomsByIds,
getSimilarRooms,
getSubRoomSaves,
getVisitedRooms,
modifySubRoom,
removeCheer,
@@ -1448,34 +1449,50 @@ const app = new Hono<App>()
}
)
// A subroom's saved-data versions — the room-history / "restore a save" list, paged as
// PagedResultsDTO<SubRoomDataSaveDTO> (`{ Results, TotalResults }`). We don't keep a save
// history yet: a save (POST …/data) overwrites the current blob inline on the subroom, so
// there are no distinct versions to list — this returns an empty page. The
// unityAssetTarget/unityAssetVersion/skip/take query params are accepted and ignored.
// A subroom's saved-data versions — the room-history / "restore a save" list. Every
// save is its own `subroom_save` row (nothing is overwritten), so this is real
// history, newest first, paged by skip/take.
.get(
'/rooms/:roomId{[0-9]+}/subrooms/:subRoomId{[0-9]+}/saves',
describeRoute({
tags: ['Subrooms'],
summary: 'A subrooms saved-data versions',
description: [
'The room-history / “restore a save” list, paged as',
'`PagedResultsDTO<SubRoomDataSaveDTO>`. We keep no save history — a save (`POST',
'…/data`) overwrites the subrooms current blob inline, so there are no distinct',
'versions to list — and this is always an empty page. The',
'`unityAssetTarget`/`unityAssetVersion`/`skip`/`take` params are accepted and ignored.',
'The room-history / “restore a save” list, newest first. Every room save appends a',
'row rather than overwriting, so this is the subrooms full history; it is empty',
'only when the subroom has never been saved.',
'`unityAssetTarget`/`unityAssetVersion` are accepted and ignored.',
'',
'`TotalResults` and `TotalCount` carry the same number: the clients paged DTO and',
'the reference disagree on the name, so both are emitted.',
].join(' '),
parameters: [
roomIdParam,
subRoomIdParam,
stringQuery('unityAssetTarget', 'Accepted and ignored'),
stringQuery('unityAssetVersion', 'Accepted and ignored'),
stringQuery('skip', 'Accepted and ignored — the page is always empty'),
stringQuery('take', 'Accepted and ignored — the page is always empty'),
stringQuery('skip', 'How many saves to skip (default 0)'),
stringQuery('take', 'How many saves to return (default all)'),
],
responses: { 200: json(SubRoomSavesPage, 'Always an empty page') },
responses: { 200: json(SubRoomSavesPage, 'The subrooms saves, newest first') },
}),
(c) => c.json({ Results: [], TotalResults: 0 })
async (c) => {
const roomId = Number.parseInt(c.req.param('roomId'), 10)
const subRoomId = Number.parseInt(c.req.param('subRoomId'), 10)
// Scoped through the room so a subroom id from another room can't read its saves.
const room = await getRoomById(c.env.DB, roomId)
if (!room || !findSubRoom(room, subRoomId)) {
return c.json({ Results: [], TotalResults: 0, TotalCount: 0 })
}
const saves = await getSubRoomSaves(c.env.DB, subRoomId)
const skip = Number.parseInt(c.req.query('skip') ?? '', 10)
const take = Number.parseInt(c.req.query('take') ?? '', 10)
const from = Number.isNaN(skip) || skip < 0 ? 0 : skip
const page = saves.slice(from, Number.isNaN(take) || take < 0 ? undefined : from + take)
return c.json({ Results: page, TotalResults: saves.length, TotalCount: saves.length })
}
)
// Save a subroom's data (room save). Auth-gated (401 with empty body). Editable
@@ -1531,9 +1548,14 @@ const app = new Hono<App>()
// already returned 401 for a missing/invalid token).
if (!canManageRoom(room, accountId)) return c.body(null, 403)
// The client uploads BOTH blobs to `storage` first and sends their keys here:
// `SubRoomData` is the scene blob (what the loader downloads), `RoomData` the
// metadata blob. `UnityAssetId`/`AutoPublish`/`OwnershipProof` are accepted
// and ignored.
const body = (await c.req.json().catch(() => ({}))) as {
RoomData?: { Filename?: string }
SubRoomData?: { Filename?: string }
UnityAssetId?: string | null
Description?: string
PersistenceVersion?: number
InventionUsage?: string
@@ -1542,6 +1564,7 @@ const app = new Hono<App>()
const updated = await saveSubRoomData(c.env.DB, roomId, subRoomId, accountId, {
subRoomDataFilename: body.SubRoomData?.Filename,
roomDataFilename: body.RoomData?.Filename,
unityAssetId: typeof body.UnityAssetId === 'string' ? body.UnityAssetId : undefined,
description: typeof body.Description === 'string' ? body.Description : undefined,
persistenceVersion:
typeof body.PersistenceVersion === 'number' ? body.PersistenceVersion : undefined,