Recipes¶
Progress and an offline fallback in Compose¶
@Composable
fun GameIntro(packs: AssetPacks) {
val state by remember { packs.state("postdelivery") }.collectAsState(initial = null)
LaunchedEffect(Unit) { packs.fetch("postdelivery") }
when (val s = state) {
is PackState.Downloading -> ProgressLine(s.bytes, s.totalBytes)
is PackState.Failed -> if (s.reason == PackFailure.NoNetwork) PlayWithBuiltInArt()
PackState.Ready -> PlayWithPackArt()
else -> Unit
}
}
Construct AssetPacks(source, stallTimeoutMillis = 20_000) so an offline first play falls back
instead of waiting.
Hash once per install, not once per launch¶
Back VerifiedMarkers with persistent settings (multiplatform-settings shown):
class SettingsMarkers(private val settings: Settings) : VerifiedMarkers {
override fun isVerified(packId: String, version: Int) = settings.getInt("adk.$packId", -1) == version
override fun markVerified(packId: String, version: Int) = settings.putInt("adk.$packId", version)
override fun clear(packId: String) = settings.remove("adk.$packId")
}
val packs = AssetPacks(source = source, markers = SettingsMarkers(settings))
Reading a model and a texture¶
val glb = packs.readBytes("postdelivery", "town/sedan.glb") ?: return fallback()
val png = packs.readBytes("postdelivery", "town/colormap.png")?.decodeToImageBitmap()
readBytes runs on the dispatcher you gave AssetPacks; decode on a background dispatcher too.
One pack per game¶
Give each game its own pack ID (postdelivery, wordmaze), so a player downloads only the
games they open, and remove a game's pack when they have not played it in a while.
Unit tests¶
val fake = FakePackSource().apply {
pack(packId = "postdelivery", version = 1, files = mapOf("town/sedan.glb" to glbBytes))
script("postdelivery", PackState.NotDownloaded, PackState.Downloading(1, 2), PackState.Ready)
}
See Testing for scripting failures and cancellations.