from enum import Enum from kennel.engine.entities.entity import EntityManager from .system import System, SystemType from abc import abstractmethod import asyncio class EventType(str, Enum): ENTITY_BORN = "ENTITY_BORN" ENTITY_POSITION_UPDATE = "ENTITY_POSITION_UPDATE" ENTITY_DEATH = "ENTITY_DEATH" class Event: def __init__(self, event_type: EventType, data: dict): self.event_type = event_type self.data = data def __str__(self): return f"Event({self.event_type}, {self.data})" def dict(self): return {"event_type": self.event_type, "data": self.data} @staticmethod def from_dict(data: dict): return Event(EventType(data["event_type"]), data["data"]) class Publishable: @abstractmethod async def publish(self, event: Event): pass class ClientEventTransformer: @abstractmethod def apply(self, event: Event) -> Event: pass class EventProcessor: @abstractmethod def accept(self, entity_manager: EntityManager, event: Event) -> None: pass class NetworkSystem(System): def __init__( self, event_processor: EventProcessor, client_event_transformer: ClientEventTransformer, ): super().__init__(SystemType.NETWORK) self.event_processor = event_processor self.client_event_transformer = client_event_transformer self.events = [] self.clients = {} async def update(self, entity_manager: EntityManager, delta_time: float) -> None: for event in self.events: self.event_processor.accept(entity_manager, event) client_events = [ self.client_event_transformer.apply(entity_manager, event) for event in self.events ] await asyncio.gather( *[ client.publish(event) for client in self.clients.values() for event in client_events ] ) self.events = [] def client_event(self, client_id: str, event: Event) -> None: event.data["client_id"] = client_id self.events.append(event) def add_event(self, event: Event) -> None: self.events.append(event) def add_client(self, client_id: str, client: Publishable) -> None: self.clients[client_id] = client def remove_client(self, client_id: str) -> None: del self.clients[client_id]