Closed sb3rg closed 6 months ago
The shared event system in v2.x was a limitation, not a feature. The current behavior mentioned in the README:
Registered events and handlers are part of the current World context.
The event system in esper is provided to allow inter-Process communications. This is a farily common feature in ECS libraries, and has some specific use cases. Keeping events contained to the active context is the common case.
For games with multiple contexts, you often have several instances of the same Processors across multiple World contexts, dispatching events to each other. Processors in inactive contexts generally shouldn't be receiving events from the active context. For example, common events would be things such as the current player picked up a coin, or the map should changed, etc. This is a limited scope event framework. If you are looking for something higher level, such as handling application wide mouse events, it will not fill that need.
Got it. Thank you for clarifying. I suppose that makes sense. However, I will say that this can make it quite hairy to debug for anyone else who makes extensive use of different worlds and has to switch context in novel ways--i.e. I don't use worlds at all for switching scenes as I'm not building a game. Tracing your own code, it may not always be clear whether you're in the right context to get access the right set of handlers.
For me, this meant wrapping your entire library with an adapter then putting guards in place to protect myself from accidentally being in the wrong context. It works for me and protects me from any more breaking changes in this library. But, I imagine I'm going to be taking a performance hit and now I have to make checks that I didn't have to in v2.
def add_comp_to( world, v_id, component_class ):
# world.add_component( v_id, component_class() )
switch_cx( world )
esper.add_component( v_id, component_class() )
def has_comp( world, v_id, component_class ):
# return world.has_component( v_id, component_class )
switch_cx( world )
return esper.has_component( v_id, component_class )
def get_ent_comp( world, v_id, component_class ):
# return world.component_for_entity( v_id, component_class )
switch_cx( world )
return esper.component_for_entity( v_id, component_class )
I'll mark this closed.
There shouldn't be all that much overhead to do that. The context switch itself is essentially nothing more than the cost of a function call and a dozen attribute assignments. For example, switching between two contexts a million times:
>>> timeit.timeit("esper.switch_world('new'); esper.switch_world('old')", setup="import esper", number=1_000_000)
0.3097645400002875
For games in particular, this is only done once or twice per frame (or not at all), so it's pretty much negligible. For your case, I suppose it depends on how many times you're switching contexts.
You might also consider making a simple Python context manager to do this. I haven't tested this code, but it should work:
class WorldContext:
def __init__(self, name):
self.name = name
def __enter__(self):
esper.switch_world(self.name)
def __exit__(self, exc_type, exc_val, exc_tb):
pass
Then just make an instance of each World you need, and use them with the with
operator:
worlda = WorldContext('a')
worldb = WorldContext('b')
with worlda:
esper.get_components(......)
Thank you! This is very helpful. I will incorporate this into my wrapper. I appreciate the time and attention you give to your project. I think esper is quite the special little library. It's small, easy to understand and performant and I hope to contribute to it down the road.
Describe the bug Event System does not preserve event handlers cache upon switching context
To Reproduce
Expected behavior If the event_registry is a part of the module, why would it clear the event_registry upon switching worlds? Expect event_registry to preserve the reference to the handlers regardless of which world is the current_context (Don't you think?)
Development environment:
Additional context Perhaps this is what is supposed to happen in v3? But in the versions less than 3, switching worlds didn't affect the event_registry because you were explicitly passing around world references vs now having to manage the implicit context.