LastOliveGames / becsy

A multithreaded Entity Component System (ECS) for TypeScript and JavaScript, inspired by ECSY and bitecs.
MIT License
196 stars 17 forks source link

Run the initialize functions within the default frame #6

Closed Myrannas closed 2 years ago

Myrannas commented 2 years ago

At the moment initialize functions are not run within a frame, so any entity created via createEntity is marked as invalid, and cannot be interacted with further. This first surfaced in 0.8.2 with the new entity validity checking.

A minimal case:

await World.create({
  defs: [TestComponent, class extends System {
    initialize() {
      output = this.createEntity(TestComponent).hold();
    }
  }]
});

An example error:

entity.ts:199 Uncaught Error: Entity handle no longer valid
    at EntityImpl.__checkValid (entity.ts:199)
    at EntityImpl.hold (entity.ts:173)
    at eval (eval at return (registry.ts:49), <anonymous>:17:29)
    at EntityPool.return (registry.ts:49)
    at EntityPool.returnTemporaryBorrows (registry.ts:39)
    at Registry.flush (registry.ts:124)
    at Dispatcher.flush (dispatcher.ts:276)
    at Dispatcher.createEntity (dispatcher.ts:284)

I went ahead and created a test + PR for this, hope that's ok; happy to discuss the approach further :)

pkaminski commented 2 years ago

Thanks for reporting this! It was actually a symptom of bigger problems with System.initialize -- I forgot to keep it up to date as the rest of the project evolved. I borrowed your test (thanks!) and patched things up a bit in v0.8.4 (commit). System initialization will now enforce r/w masks from query declarations, but will no longer run initializations in parallel until I can do so safely, respecting scheduling constraints.