diff --git a/__init__.py b/__init__.py index 07b3ea7..e69de29 100644 --- a/__init__.py +++ b/__init__.py @@ -1,57 +0,0 @@ -from dataclasses import dataclass, field -from typing import Any, Iterator, Protocol - -type Entity = int -type Archetype = frozenset[type] -type ComponentMap = dict[type, Any] -type EntityComponentStorage = dict[Entity, ComponentMap] - - -class System(Protocol): - @classmethod - def process(cls, world: "World") -> None: ... - - -@dataclass -class World: - registry: dict[Archetype, EntityComponentStorage] = field(default_factory=dict) - next_entity_index: int = 0 - systems: list[type[System]] = field(default_factory=list) - - def generate_id(self) -> int: - self.next_entity_index += 1 - return self.next_entity_index - - def spawn(self, *components) -> int: - archetype = frozenset([type(c) for c in components]) - - if archetype not in self.registry: - self.registry[archetype] = {} - - entity = self.generate_id() - self.registry[archetype][entity] = {type(c): c for c in components} - return entity - - def query( - self, *component_types, exact=False - ) -> Iterator[tuple[Entity, ComponentMap]]: - component_subset_signature = frozenset(component_types) - for archetype, entity_component_storage in self.registry.items(): - if (exact and component_subset_signature == archetype) or ( - not exact and component_subset_signature.issubset(archetype) - ): - for entity, component_storage in entity_component_storage.items(): - yield entity, component_storage - - def get_components(self, entity: int, pop=False): - for componentstorage in self.registry.values(): - if entity in componentstorage: - if pop: - return componentstorage.pop(entity, None) - else: - return componentstorage[entity] - return None - - def tick(self, *args, **kwargs): - for system in self.systems: - system.process(self, *args, **kwargs) diff --git a/event.py b/event.py new file mode 100644 index 0000000..4b6ff37 --- /dev/null +++ b/event.py @@ -0,0 +1,9 @@ +class EventBus: + def __init__(self): + self.events = [] + + def publish(self, event): + self.events.append(event) + + def pop(self): + return self.events.pop(0) diff --git a/system.py b/system.py new file mode 100644 index 0000000..bf844a3 --- /dev/null +++ b/system.py @@ -0,0 +1,7 @@ +from __future__ import annotations +from typing import Protocol + + +class System(Protocol): + @classmethod + def process(cls, world, *args, **kwargs) -> None: ... diff --git a/world.py b/world.py new file mode 100644 index 0000000..c983345 --- /dev/null +++ b/world.py @@ -0,0 +1,54 @@ +from dataclasses import dataclass, field +from typing import Any, Iterator + +from .system import System + +type Entity = int +type Archetype = frozenset[type] +type ComponentMap = dict[type, Any] +type EntityComponentStorage = dict[Entity, ComponentMap] + + +@dataclass +class World: + registry: dict[Archetype, EntityComponentStorage] = field(default_factory=dict) + next_entity_index: int = 0 + systems: list[type[System]] = field(default_factory=list) + + def generate_id(self) -> int: + self.next_entity_index += 1 + return self.next_entity_index + + def spawn(self, *components) -> int: + archetype = frozenset([type(c) for c in components]) + + if archetype not in self.registry: + self.registry[archetype] = {} + + entity = self.generate_id() + self.registry[archetype][entity] = {type(c): c for c in components} + return entity + + def query( + self, *component_types, exact=False + ) -> Iterator[tuple[Entity, ComponentMap]]: + component_subset_signature = frozenset(component_types) + for archetype, entity_component_storage in self.registry.items(): + if (exact and component_subset_signature == archetype) or ( + not exact and component_subset_signature.issubset(archetype) + ): + for entity, component_storage in entity_component_storage.items(): + yield entity, component_storage + + def get_components(self, entity: int, pop=False): + for componentstorage in self.registry.values(): + if entity in componentstorage: + if pop: + return componentstorage.pop(entity, None) + else: + return componentstorage[entity] + return None + + def tick(self, *args, **kwargs): + for system in self.systems: + system.process(self, *args, **kwargs)