import { Failure, IMAGES, LambdaTransformSound, SOUNDS, SPRITE_SPECS, SpriteSpec, Sprites, } from "../config"; import { Entity, EntityNames, FunctionBox } from "."; import { BoundingBox, Colliding, ComponentNames, Grid, GridSpawn, Highlight, Interactable, Modal, Sprite, Text, } from "../components"; import { Coord2D, Direction } from "../interfaces"; import { tryWrap } from "../utils"; import { parse } from "../../interpreter"; export class LambdaFactory extends Entity { private static spriteSpec: SpriteSpec = SPRITE_SPECS.get( Sprites.LAMBDA_FACTORY ) as SpriteSpec; private spawns: number; private code: string; constructor(gridPosition: Coord2D, code: string, spawns: number) { super(EntityNames.LambdaFactory); this.spawns = spawns; this.code = code; this.addComponent( new BoundingBox( { x: 0, y: 0, }, { width: LambdaFactory.spriteSpec.width, height: LambdaFactory.spriteSpec.height, }, 0 ) ); this.addComponent(new Text(spawns.toString())); this.addComponent(new Colliding()); this.addComponent( new GridSpawn( this.spawns, () => new FunctionBox({ x: 0, y: 0 }, this.code) ) ); this.addComponent(new Grid(gridPosition)); this.addComponent( new Sprite( IMAGES.get(LambdaFactory.spriteSpec.sheet)!, { x: 0, y: 0 }, { width: LambdaFactory.spriteSpec.width, height: LambdaFactory.spriteSpec.height, }, LambdaFactory.spriteSpec.msPerFrame, LambdaFactory.spriteSpec.frames ) ); this.addComponent( new Highlight(this.onHighlight.bind(this), this.onUnhighlight.bind(this)) ); } private codeConsumer(code: string) { const parsed = tryWrap(() => parse(code)); if (parsed.error) { return { error: parsed.error }; } this.code = code; this.removeComponent(ComponentNames.Modal); return { consumed: true }; } private onHighlight(direction: Direction) { if (direction === Direction.LEFT || direction === Direction.RIGHT) { this.addComponent(new Interactable(() => this.spawnNewLambda(direction))); return; } this.addComponent(new Interactable(this.interaction.bind(this))); } private interaction() { if (this.hasComponent(ComponentNames.Modal)) { return; } this.addComponent( new Modal({ type: "CODE_EDITOR", codeInit: { code: this.code, codeConsumer: this.codeConsumer.bind(this), }, }) ); } private onUnhighlight() { this.removeComponent(ComponentNames.Modal); this.removeComponent(ComponentNames.Interactable); } private spawnNewLambda(direction: Direction) { const parsed = tryWrap(() => parse(this.code)); if (parsed.error) { SOUNDS.get(Failure.name)!.play(); return; } const spawner = this.getComponent(ComponentNames.GridSpawn); spawner.spawnEntity(direction); const textComponent = this.getComponent(ComponentNames.Text); textComponent.text = spawner.spawnsLeft.toString(); this.addComponent(textComponent); SOUNDS.get(LambdaTransformSound.name)!.play(); } }