gtn/ecs.py

58 lines
2.1 KiB
Python

from typing import Iterator
class World:
def __init__(self):
self.entities: set[Entity] = set()
self.mapping: dict[type, set[Entity]] = {}
def query(self, *needed: type, without: tuple[type] = []) -> Iterator['Entity']:
if not needed:
for entity in self.entities:
for without_type in without:
if without_type in entity:
break
else:
yield entity
else:
first_component = needed[0]
for entity in self.mapping.get(first_component, set()):
for component_type in needed[1:]:
if entity not in self.mapping.get(component_type, set()):
break
else:
for without_type in without:
if without_type in entity:
break
else:
yield entity
class Entity:
def __init__(self, world: World):
self.world = world
self.world.entities.add(self)
self.components: dict[type, object] = {}
def __getitem__(self, component_type):
return self.components[component_type]
def __setitem__(self, component_type, component):
self.components[component_type] = component
self.world.mapping.setdefault(component_type, set()).add(self)
def __delitem__(self, component_type):
del self.components[component_type]
self.world.mapping[component_type].remove(self)
if len(self.world.mapping[component_type]) == 0:
del self.world.mapping[component_type]
def __contains__(self, component_type):
return component_type in self.components
def __del__(self): # TODO: Réparer ça marche pas car il n'est pas détruit car il est toujours dans World
self.world.entities.remove(self)
for component_type in self.components:
self.world.mapping[component_type].remove(self)
if len(self.world.mapping[component_type]) == 0:
del self.world.mapping[component_type]