[rooms] Support 2026 Studio loading of legacy baked bundles (#129)

* [rooms] Preserve legacy Unity bundle save DTOs for the Studio loader

* [rooms] Resolve JSON baked bundle requests with exact target and version
This commit is contained in:
dukedotdev
2026-10-12 14:17:43 -04:00
committed by GitHub
parent 585cf68637
commit a3a5851373
2 changed files with 214 additions and 1 deletions
+117
View File
@@ -6497,3 +6497,120 @@ describe('sweep cron', () => {
expect(await inviterIds()).toEqual([])
})
})
it('2026 room experience retains upstream progression in the native object shape', async () => {
await seedRoomWithSubRooms(env.DB, {
RoomId: 900092,
Name: '2026ExperienceTest',
CreatorAccountId: 42,
SubRooms: [],
})
const res = await SELF.fetch(`${ORIGIN}/rooms/900092/experience/player`, {
headers: await bearer('42', undefined, '20260323.14'),
})
expect(res.status).toBe(200)
expect(await res.json()).toEqual({
RoomExperienceEnabled: false,
Experience: 0,
ConcurrencyCode: expect.any(String),
})
})
describe('Studio baked Unity asset downloads', () => {
const mainId = 'aa0320e1-2e47-4cf5-9129-5366c3c5f824'
const childId = 'e6da76fb-f990-4299-8724-d786f5723a5a'
const filename = 'imports/test-room/main.SubRoom.Main.0.5.assetbundle'
const path = '/unity_assets/baked/bulk'
beforeAll(async () => {
await seedRoomWithSubRooms(env.DB, {
RoomId: 900090,
Name: 'StudioDownloadTest',
CreatorAccountId: 1,
Accessibility: 1,
SubRooms: [
{
SubRoomId: 900090,
RoomId: 900090,
Name: 'Home',
CurrentSave: {
UnityAssetId: mainId,
UnityAsset: filename,
UnityAssetHash: 'main-hash',
DataBlob: 'scene.room',
UnitySubAssets: [
{
UnityAssetId: childId,
UnityAsset: 'child.SubRoom.SubAsset.0.5.assetbundle',
UnityAssetHash: 'child-hash',
},
],
},
},
],
})
})
async function bulk(body: unknown, authenticated = true) {
return SELF.fetch(ORIGIN + path, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...(authenticated ? await bearer('2') : {}) },
body: JSON.stringify(body),
})
}
it('resolves the main and subasset GUIDs with their exact target and version', async () => {
const res = await bulk({
UnityAssetIds: [mainId.toUpperCase(), childId, mainId],
Target: 0,
Version: 5,
})
expect(res.status).toBe(200)
expect(await res.json()).toEqual([
{ UnityAssetId: mainId, Target: 0, Version: 5, Filename: filename, Hash: 'main-hash' },
{
UnityAssetId: childId,
Target: 0,
Version: 5,
Filename: 'child.SubRoom.SubAsset.0.5.assetbundle',
Hash: 'child-hash',
},
])
})
it('returns the Studio loader DTO with its main bundle and dependencies', async () => {
const row = await env.DB.prepare(
'SELECT current_save_id FROM subroom WHERE sub_room_id=900090'
).first<{ current_save_id: number }>()
const res = await SELF.fetch(
`${ORIGIN}/rooms/900090/subrooms/900090/saves/${row!.current_save_id}`,
{ headers: await bearer('1') }
)
expect(res.status).toBe(200)
expect(await res.json()).toMatchObject({
UnityAsset: filename,
UnityAssetHash: 'main-hash',
UnitySubAssets: [
{
UnityAssetId: childId,
UnityAsset: 'child.SubRoom.SubAsset.0.5.assetbundle',
UnityAssetHash: 'child-hash',
},
],
})
})
it('does not substitute Windows bundles for an unavailable target or version', async () => {
for (const options of [
{ Target: 2, Version: 5 },
{ Target: 0, Version: 6 },
]) {
expect(await (await bulk({ UnityAssetIds: [mainId], ...options })).json()).toEqual([])
}
})
it('rejects unauthenticated and malformed requests', async () => {
expect((await bulk({ UnityAssetIds: [mainId] }, false)).status).toBe(401)
expect((await bulk({ UnityAssetIds: ['invalid'] })).status).toBe(400)
})
it('does not expose private-room assets to an unrelated caller', async () => {
await env.DB.prepare(
"UPDATE room SET data=json_set(data, '$.Accessibility', 0) WHERE room_id=900090"
).run()
expect(await (await bulk({ UnityAssetIds: [mainId] })).json()).toEqual([])
})
})