Skip to content

src/build-demo-castle.ts

49 lines · 1.6 KB · TypeScript
Raw
/**
 * Demo: your agent builds a castle that streams in live for every viewer.
 * Uses the same startBuild / placeBlocks / finishBuild path as any agent build.
 *
 * @param input - `{ room, agentName?, x?, z?, delayMs? }`. Center defaults to 0,0.
 * @returns `{ buildId, placed, batches }`
 * @example
 * import buildDemoCastle from 'kody:@kentcdodds/world-builder/build-demo-castle'
 * await buildDemoCastle({ room: 'abc123defg', agentName: 'Claude', x: 12, z: -10 })
 */
import { planCastle } from './shared/castle.ts'
import { requireAgent, streamBuildOps } from './lib/agent.ts'
import { finishBuild, resolveWorld, startBuild } from './lib/world-ops.ts'

export default async function buildDemoCastle(input?: {
	agentName?: string
	room?: string
	worldId?: string
	x?: number
	z?: number
	delayMs?: number
}) {
	const { player } = await requireAgent(input?.agentName ?? 'Agent')
	const worldId = await resolveWorld(input)
	const cx = Math.trunc(Number(input?.x ?? 0)) || 0
	const cz = Math.trunc(Number(input?.z ?? 0)) || 0
	const blocks = planCastle(cx, cz)
	const buildId = await startBuild(player, worldId, `A castle with four towers at (${cx}, ${cz})`)
	let placed = 0
	let batches = 0
	try {
		for (let i = 0; i < blocks.length; i += 600) {
			const out = await streamBuildOps({
				buildId,
				blocks: blocks.slice(i, i + 600),
				kind: 'put',
				batchSize: 24,
				delayMs: input?.delayMs ?? 120,
			})
			placed += out.placed
			batches += out.batches
		}
		await finishBuild(buildId, 'done')
	} catch (error) {
		await finishBuild(buildId, 'failed').catch(() => {})
		throw error
	}
	return { buildId, placed, batches }
}