diff --git a/src/engine/functions/index.ts b/src/engine/functions/index.ts index 88923f6..59e3f89 100644 --- a/src/engine/functions/index.ts +++ b/src/engine/functions/index.ts @@ -16,7 +16,6 @@ export type BehaviourLink = { } export type BehaviourInput = BehaviourResourcePin & { - rate: number; // per second of tick deltaTime link: BehaviourLink; } @@ -25,7 +24,6 @@ export type BehaviourInputs = { } export type BehaviourOutput = BehaviourResourcePin & { - rate: number; // per second of tick deltaTime } export type BehaviourOutputs = { @@ -51,13 +49,11 @@ export abstract class Behaviour { this.outputs = { pins: source.outputs.pins.map((output) => ({ resource: output.resource, - rate: output.rate, })), } this.inputs = { pins: source.inputs.pins.map((input) => ({ resource: input.resource, - rate: input.rate, link: input.link, })), } @@ -71,7 +67,7 @@ export abstract class Behaviour { abstract getDisplayInfo(): BehaviourDisplayInfo; /** Withdraws up to `amount` of `resource` from this behaviour's storage, returning how much was actually taken. */ - protected take(resource: Resource, amount: number): number { + public take(resource: Resource, amount: number): number { const available = this.storage[resource] ?? 0; const taken = Math.min(available, amount); this.storage[resource] = available - taken; @@ -82,30 +78,46 @@ export abstract class Behaviour { this.storage[resource] = (this.storage[resource] ?? 0) + amount; } - /** Fills this behaviour's own storage from its outputs' production rates. */ - public produce(deltaTime: number): void { - for (const output of this.outputs.pins) - this.give(output.resource, output.rate * deltaTime); + abstract produce(deltaTime: number): void; + + abstract pull(deltaTime: number, resolve: (id: string) => Behaviour | undefined): void; +} + +export class Converter extends Behaviour { + public readonly inputRates: Partial; + public readonly outputRates: Partial; + + constructor(source: SerializedNodeBehaviour & SerializedConverter) { + if (source.kind !== 'converter') + throw new Error('Invalid source'); + super(source); + + this.inputRates = {}; + for (const pin of source.inputs.pins) + this.inputRates[pin.resource] = pin.rate; + + this.outputRates = {}; + for (const pin of source.outputs.pins) + this.outputRates[pin.resource] = pin.rate; } - /** Pulls resources into this behaviour's storage from whatever each input pin is linked to. */ + /** Fills this converter's own storage from its outputs' production rates. */ + public produce(deltaTime: number): void { + for (const output of this.outputs.pins) + this.give(output.resource, (this.outputRates[output.resource] ?? 0) * deltaTime); + } + + /** Pulls resources into this converter's storage from whatever each input pin is linked to. */ public pull(deltaTime: number, resolve: (id: string) => Behaviour | undefined): void { for (const input of this.inputs.pins) { const source = resolve(input.link.target); if (!source) continue; - const taken = source.take(input.link.resource, input.rate * deltaTime); + const rate = this.inputRates[input.resource] ?? 0; + const taken = source.take(input.link.resource, rate * deltaTime); this.give(input.resource, taken); } } -} - -export class Converter extends Behaviour { - constructor(source: SerializedNodeBehaviour & SerializedConverter) { - if (source.kind !== 'converter') - throw new Error('Invalid source'); - super(source); - } public getDisplayInfo(): BehaviourDisplayInfo { return { diff --git a/src/engine/saveLoad.ts b/src/engine/saveLoad.ts index 9a0639d..b9fd064 100644 --- a/src/engine/saveLoad.ts +++ b/src/engine/saveLoad.ts @@ -1,20 +1,28 @@ import { defaultGame } from "../prefabs/game"; import { Game, SerializedGame, SerializedNodeBehaviour } from "../types"; -import { Behaviour, behaviours } from "./functions"; +import { Behaviour, behaviours, Converter } from "./functions"; export function serializeBehaviour(behaviour: Behaviour): SerializedNodeBehaviour { switch (behaviour.kind) { - case 'converter': + case 'converter': { + const converter = behaviour as Converter; return { - id: behaviour.id, + id: converter.id, kind: 'converter', inputs: { - pins: behaviour.inputs.pins.map((pin) => ({ ...pin })), + pins: converter.inputs.pins.map((pin) => ({ + ...pin, + rate: converter.inputRates[pin.resource] ?? 0, + })), }, outputs: { - pins: behaviour.outputs.pins.map((pin) => ({ ...pin })), + pins: converter.outputs.pins.map((pin) => ({ + ...pin, + rate: converter.outputRates[pin.resource] ?? 0, + })), }, }; + } default: throw new Error('Unknown behaviour'); }