mirror of
https://github.com/djdevin/recflare.git
synced 2026-10-25 23:18:51 -07:00
[rooms] fix imported unity assets
This commit is contained in:
@@ -21,6 +21,7 @@ import { bindPlaceholders, chunkForBinds, MAX_BOUND_PARAMS } from './d1-binds'
|
||||
import { Accessibility, Role } from './enums'
|
||||
import { countPlayersByRoom } from './presence-db'
|
||||
import { resyncInstanceCapacity } from './room-instance-db'
|
||||
import { isStudioBundleFilename } from './studio-unity-assets'
|
||||
import { bakedUnityAssets, listUnityAssetBuilds } from './unity-assets-db'
|
||||
|
||||
import type { UnityAssetBuild } from './unity-assets-db'
|
||||
@@ -2303,6 +2304,14 @@ async function attachCurrentSaves(
|
||||
* including their empty arrays; so is a save whose asset has no stored build —
|
||||
* the scene blob still loads, and the bundle list stays empty.
|
||||
*
|
||||
* Only Studio (UGC) builds are folded in — rows whose filename passes
|
||||
* {@link isStudioBundleFilename}. A FIRST-PARTY bundle loaded by hand under
|
||||
* `unity/<roomId>/` shares the table but must stay out of this list: the 2025 client
|
||||
* resolves it through `POST /unity_assets/baked/bulk` (which serves both kinds), and
|
||||
* handed it inline in this five-key shape it stops asking, cannot name the file, and
|
||||
* loads nothing. That broke every imported first-party room when the splice moved from
|
||||
* the Studio-only table to `unity_asset`.
|
||||
*
|
||||
* Only main bundles are listed. Stripped bundles stay in the bucket.
|
||||
*/
|
||||
export async function attachStudioUnityAssets(
|
||||
@@ -2317,7 +2326,9 @@ export async function attachStudioUnityAssets(
|
||||
),
|
||||
]
|
||||
if (ids.length === 0) return
|
||||
const builds = await listUnityAssetBuilds(db, ids)
|
||||
const builds = (await listUnityAssetBuilds(db, ids)).filter((build) =>
|
||||
isStudioBundleFilename(build.Filename)
|
||||
)
|
||||
// Rows come back with the id lowercased; a save may spell its GUID either way.
|
||||
const byAsset = new Map<string, UnityAssetBuild[]>()
|
||||
for (const build of builds) {
|
||||
|
||||
@@ -40,6 +40,9 @@ export const STUDIO_ASSET_VERSION = 1
|
||||
/** The platforms a local Studio build posts, named as the multipart fields name them. */
|
||||
export type StudioBundlePlatform = 'windows' | 'android'
|
||||
|
||||
/** Where every Studio (UGC) bundle filename starts; see {@link publicStudioBundleFilename}. */
|
||||
const STUDIO_BUNDLE_PREFIX = 'studio/'
|
||||
|
||||
/**
|
||||
* A Studio bundle's `unity_asset.filename` — the name the client downloads, which it
|
||||
* prefixes with `/room/` (see {@link studioBundleR2Key}). Laid out like the official
|
||||
@@ -54,7 +57,20 @@ export function publicStudioBundleFilename(
|
||||
kind: string
|
||||
): string {
|
||||
const id = unityAssetId.replace(/-/g, '').toLowerCase()
|
||||
return `studio/${roomId}/${id}.${platform}.${kind}.assetbundle`
|
||||
return `${STUDIO_BUNDLE_PREFIX}${roomId}/${id}.${platform}.${kind}.assetbundle`
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a `unity_asset` filename is a Rec Room Studio build — UGC the studio worker
|
||||
* wrote — as opposed to a first-party bundle loaded by hand under the game's own
|
||||
* `unity/<roomId>/` layout. The two share the table, and only the Studio ones are
|
||||
* folded onto a save's `UnitySubAssets`: a 2025 client handed a first-party bundle
|
||||
* inline takes it instead of asking `POST /unity_assets/baked/bulk`, cannot name it
|
||||
* (its decoder reads `UnityAsset`/`UnityAssetHash`, not `Filename`/`Hash`), and loads
|
||||
* nothing. The bulk lookup serves both kinds.
|
||||
*/
|
||||
export function isStudioBundleFilename(filename: string): boolean {
|
||||
return filename.startsWith(STUDIO_BUNDLE_PREFIX)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
*
|
||||
* Two things read it. The client asks for main bundles in bulk from
|
||||
* `POST /unity_assets/baked/bulk` (the `rooms` worker) while loading a room — the step
|
||||
* Player.log times as `AssetBundle_Download` — and `GET /rooms/{id}` folds the same main
|
||||
* bundles onto `CurrentSave.UnitySubAssets`; either way the client then downloads
|
||||
* Player.log times as `AssetBundle_Download` — and `GET /rooms/{id}` folds the STUDIO
|
||||
* main bundles (filenames under `studio/`, see `isStudioBundleFilename`) onto
|
||||
* `CurrentSave.UnitySubAssets`. A first-party bundle loaded by hand under `unity/<roomId>/`
|
||||
* is served by the bulk lookup only; either way the client then downloads
|
||||
* `/room/<Filename>` from the bucket, and a lookup that answers no row,
|
||||
* or a row without a `Filename`, simply downloads nothing, with no error anywhere.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user