From my understanding you want to keep the source of truth as the data in the components. It should then be ok to derive state from here. An example of this would be something like the following:
I have an entity with a sprite component, a transform component and a renderable tag. We then get our render system to to query for these, load up our sprite and set its position and add it to the app stage. You then have two options you can save the sprite into a WeakMap, using the entity as the key, or you can create a system state component. You then do something similar if the item needs to be added to the physics system (as discussed in the previous thread). Some of these libraries allow you to tag the object with a name and do a lookup (see below). Pixi.js, Three.js and Cannon.js can do this.
The entity itself is still just data but we have different derived states in the respective systems (audio, ai, physics, rendering, etc). Were we to save the entities into a db and then deserialise you should be able to recreate the world again from it.
So for something like pixi you could do something like:
class RenderSystem extends System {
constructor(world, attributes){
super(world, attributes);
this.pixiApp = new PIXI.Application();
}
execute(delta, time){
this.spritesToBeRendered.results.forEach((entities) => {
const spriteComponent = entity.getComponent(SpriteComponent);
this.pixiApp.loader.add(spriteComponent.name, spriteComponent.file).load((loader, resources) => {
const sprite = new PIXI.Sprite(resources[spriteComponent.name].texture);
// Setup the position of the sprite
const {x, y} = entity.getComponent(TransformComponent);
sprite.x = x;
sprite.y = y;
// we give the entity a name that we can use for lookup later on
// this will allow us to fetch the sprite like so: this.pixiApp.stage.getChildByName(entity.id)
sprite.name = entity.id
this.pixiApp.stage.addChild(sprite);
});
})
}
}
You might want to make liberal use of tags and components to save the entity state into. Even Unity3D has a monolithic physics engine and the same for the dsp audio engine. You can wrap those worlds in a system and give an external API that would be component based. The hardest part of this is managing resources, making sure that you add, update and cleanup resources in each of these ‘worlds’. This is where system state components are probably your go to for anything that touches these worlds. At least then you can check for their removal and cleanup.
Also in the above example I’m not sure what effect doing an async call has on the game loop. It’s something I haven’t had to deal with too much yet (a lot of my assets are procedurally generated before the game begins and kept in memory).