mirror of
https://github.com/djdevin/recflare.git
synced 2026-10-25 15:09:18 -07:00
[rooms] load Studio export dependencies (#142)
This commit is contained in:
@@ -962,9 +962,15 @@ function pickBakedBundle(
|
|||||||
target: number | null
|
target: number | null
|
||||||
): { filename: string; hash: string | null } | null {
|
): { filename: string; hash: string | null } | null {
|
||||||
if (!Array.isArray(save.UnitySubAssets)) return null
|
if (!Array.isArray(save.UnitySubAssets)) return null
|
||||||
|
const rootId = typeof save.UnityAssetId === 'string' ? save.UnityAssetId.toLowerCase() : null
|
||||||
const rows = save.UnitySubAssets.filter(
|
const rows = save.UnitySubAssets.filter(
|
||||||
(item): item is { Target?: unknown; Filename?: unknown; Hash?: unknown } =>
|
(item): item is { Target?: unknown; Filename?: unknown; Hash?: unknown } =>
|
||||||
typeof item === 'object' && item !== null
|
typeof item === 'object' &&
|
||||||
|
item !== null &&
|
||||||
|
(rootId === null ||
|
||||||
|
('UnityAssetId' in item &&
|
||||||
|
typeof item.UnityAssetId === 'string' &&
|
||||||
|
item.UnityAssetId.toLowerCase() === rootId))
|
||||||
)
|
)
|
||||||
const chosen =
|
const chosen =
|
||||||
target === null
|
target === null
|
||||||
|
|||||||
@@ -6331,6 +6331,84 @@ describe('studio room bundles', () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it('serves partitioned prefab and shared-material exports as save dependencies', async () => {
|
||||||
|
await reset()
|
||||||
|
await storeFiles()
|
||||||
|
const prefab = '00111111-2222-4333-8444-555555555555'
|
||||||
|
const shared = '00222222-2222-4333-8444-555555555555'
|
||||||
|
await env.DB.prepare(
|
||||||
|
"UPDATE subroom_save SET data=json_set(data,'$.ServerData',json(?1)) WHERE sub_room_id=99011"
|
||||||
|
)
|
||||||
|
.bind(
|
||||||
|
JSON.stringify({
|
||||||
|
Exports: [
|
||||||
|
{ e: 'prefab', u: prefab.toUpperCase() },
|
||||||
|
{ e: 'shared', u: shared },
|
||||||
|
{ e: 'duplicate', u: prefab },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.run()
|
||||||
|
for (const id of [prefab, shared]) {
|
||||||
|
for (const target of [0, 2]) {
|
||||||
|
for (const kind of ['main', 'stripped'] as const) {
|
||||||
|
await putUnityAsset(
|
||||||
|
env.DB,
|
||||||
|
{
|
||||||
|
UnityAssetId: id,
|
||||||
|
Target: target,
|
||||||
|
Version: 5,
|
||||||
|
Filename: publicStudioBundleFilename(
|
||||||
|
9901,
|
||||||
|
id,
|
||||||
|
target === 0 ? 'windows' : 'android',
|
||||||
|
kind
|
||||||
|
),
|
||||||
|
Hash: winHash,
|
||||||
|
},
|
||||||
|
kind
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const target of [0, 2]) {
|
||||||
|
const response = await SELF.fetch(`${ORIGIN}/rooms/9901?unityAssetTarget=${target}`)
|
||||||
|
const room = (await response.json()) as {
|
||||||
|
SubRooms: Array<{
|
||||||
|
CurrentSave: {
|
||||||
|
SubRoomDataSaveId: number
|
||||||
|
UnitySubAssets: Array<{ UnityAssetId: string; Target: number }>
|
||||||
|
}
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
const current = room.SubRooms[0]!.CurrentSave
|
||||||
|
expect(current.UnitySubAssets.map((asset) => asset.UnityAssetId).sort()).toEqual(
|
||||||
|
[ASSET, prefab, shared].sort()
|
||||||
|
)
|
||||||
|
expect(current.UnitySubAssets.every((asset) => asset.Target === target)).toBe(true)
|
||||||
|
const detailResponse = await SELF.fetch(
|
||||||
|
`${ORIGIN}/rooms/9901/subrooms/99011/saves/${current.SubRoomDataSaveId}?unityAssetTarget=${target}`,
|
||||||
|
{ headers: await bearer('1') }
|
||||||
|
)
|
||||||
|
expect(await detailResponse.json()).toMatchObject({
|
||||||
|
UnityAsset: target === 0 ? winName : androidName,
|
||||||
|
UnitySubAssets: [prefab, shared].map((id) => ({
|
||||||
|
UnityAssetId: id,
|
||||||
|
UnityAsset: publicStudioBundleFilename(
|
||||||
|
9901,
|
||||||
|
id,
|
||||||
|
target === 0 ? 'windows' : 'android',
|
||||||
|
'main'
|
||||||
|
),
|
||||||
|
UnityAssetHash: winHash,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await env.DB.prepare('DELETE FROM unity_asset WHERE unity_asset_id IN (?1,?2)')
|
||||||
|
.bind(prefab, shared)
|
||||||
|
.run()
|
||||||
|
})
|
||||||
|
|
||||||
it('loads baked bundles onto the room and serves the unity asset', async () => {
|
it('loads baked bundles onto the room and serves the unity asset', async () => {
|
||||||
await reset()
|
await reset()
|
||||||
|
|
||||||
|
|||||||
@@ -2512,13 +2512,21 @@ export async function attachStudioUnityAssets(
|
|||||||
db: D1Database,
|
db: D1Database,
|
||||||
saves: SubRoomDataSave[]
|
saves: SubRoomDataSave[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const ids = [
|
// The cloud build partitions prefab/material exports into separate bundles.
|
||||||
...new Set(
|
// The main scene keeps external references to them, so the loader must receive
|
||||||
saves
|
// every export, including shared dependencies, before it instantiates the scene.
|
||||||
.map((save) => save.UnityAssetId)
|
const assetIds = (save: SubRoomDataSave): string[] => {
|
||||||
.filter((id): id is string => typeof id === 'string' && id !== '')
|
if (typeof save.UnityAssetId !== 'string' || save.UnityAssetId === '') return []
|
||||||
),
|
const serverData = save.ServerData as { Exports?: unknown } | null | undefined
|
||||||
]
|
const exports = Array.isArray(serverData?.Exports) ? serverData.Exports : []
|
||||||
|
const ids = new Set([save.UnityAssetId.toLowerCase()])
|
||||||
|
for (const item of exports) {
|
||||||
|
const id = (item as { u?: unknown } | null)?.u
|
||||||
|
if (typeof id === 'string' && id !== '') ids.add(id.toLowerCase())
|
||||||
|
}
|
||||||
|
return [...ids]
|
||||||
|
}
|
||||||
|
const ids = [...new Set(saves.flatMap(assetIds))]
|
||||||
if (ids.length === 0) return
|
if (ids.length === 0) return
|
||||||
const builds = (await listUnityAssetBuilds(db, ids)).filter((build) =>
|
const builds = (await listUnityAssetBuilds(db, ids)).filter((build) =>
|
||||||
isStudioBundleFilename(build.Filename)
|
isStudioBundleFilename(build.Filename)
|
||||||
@@ -2533,7 +2541,7 @@ export async function attachStudioUnityAssets(
|
|||||||
for (const save of saves) {
|
for (const save of saves) {
|
||||||
const id = save.UnityAssetId
|
const id = save.UnityAssetId
|
||||||
if (typeof id !== 'string') continue
|
if (typeof id !== 'string') continue
|
||||||
const baked = bakedUnityAssets(byAsset.get(id.toLowerCase()) ?? [])
|
const baked = bakedUnityAssets(assetIds(save).flatMap((assetId) => byAsset.get(assetId) ?? []))
|
||||||
if (baked.length === 0) continue
|
if (baked.length === 0) continue
|
||||||
save.UnitySubAssets = baked
|
save.UnitySubAssets = baked
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user