Optionaloptions: TimerPluginOptions<G>const ecs = ECSpresso.create()
.withPlugin(createTimerPlugin())
.withComponentTypes<{ spawner: true }>()
.build();
ecs.spawn({
spawner: true,
timers: { wave: createRepeatingTimer(5.0) },
});
ecs.addSystem('spawn-on-timer')
.addQuery('spawners', { with: ['timers', 'spawner'] })
.setProcess(({ queries, ecs }) => {
for (const { components } of queries.spawners) {
if (components.timers.wave?.justFinished) {
ecs.spawn({ enemy: true });
}
}
});
Typed slot names — pass a string-union generic to lock the set of legal
slot names. Spawn sites reject typos, autocomplete works on slot access,
and slot is narrowed in onComplete callbacks. Defaults to string
(any slot name) when omitted.
const ecs = ECSpresso.create()
.withPlugin(createTimerPlugin<'launch' | 'hangarCycle'>())
.build();
ecs.spawn({ timers: { launch: createTimer(2.0) } }); // ok
ecs.spawn({ timers: { typo: createTimer(2.0) } }); // type error
createTimer<'launch' | 'hangarCycle'>(1.0, {
onComplete: ({ slot }) => {
// slot is 'launch' | 'hangarCycle', not string
},
});
Only one timer plugin can be installed per world. Feature plugins should
re-export their slot union as a type so the app can assemble them:
createTimerPlugin<FighterSlots | CarrierSlots>().
Create a timer plugin for ECSpresso.
The plugin installs one update system that ticks every slot of every
timerscomponent each frame. It does not touch entity lifecycle — react tojustFinished(or useonComplete) and despawn yourself if needed.