aboutsummaryrefslogtreecommitdiff
path: root/kennel/engine/systems
diff options
context:
space:
mode:
authorElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-08-24 19:11:26 -0700
committerElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-08-24 19:16:22 -0700
commita0a2068b66204d7d06eb3c3b4aa61b28469121f6 (patch)
treee9706970af1ce8b4d12df9c0a3f64fa17ca74b97 /kennel/engine/systems
parentb144ad5df76e458297bd6dc030cad4af0f344901 (diff)
downloadkennel.hatecomputers.club-a0a2068b66204d7d06eb3c3b4aa61b28469121f6.tar.gz
kennel.hatecomputers.club-a0a2068b66204d7d06eb3c3b4aa61b28469121f6.zip
improve event parsing and begin sending events from the client
Diffstat (limited to 'kennel/engine/systems')
-rw-r--r--kennel/engine/systems/network.py104
1 files changed, 79 insertions, 25 deletions
diff --git a/kennel/engine/systems/network.py b/kennel/engine/systems/network.py
index c9696c8..8dbf4cf 100644
--- a/kennel/engine/systems/network.py
+++ b/kennel/engine/systems/network.py
@@ -1,15 +1,17 @@
from enum import Enum
-from kennel.engine.entities.entity import EntityManager
+from kennel.engine.entities.entity import Entity, EntityType, EntityManager
from .system import System, SystemType
from abc import abstractmethod
+from typing import Optional, List
import asyncio
class EventType(str, Enum):
INITIAL_STATE = "INITIAL_STATE"
+ SET_CONTROLLABLE = "SET_CONTROLLABLE"
ENTITY_BORN = "ENTITY_BORN"
- ENTITY_POSITION_UPDATE = "ENTITY_POSITION_UPDATE"
ENTITY_DEATH = "ENTITY_DEATH"
+ ENTITY_POSITION_UPDATE = "ENTITY_POSITION_UPDATE"
class Event:
@@ -17,26 +19,83 @@ class Event:
self.event_type = event_type
self.data = data
- def __str__(self):
+ def __str__(self) -> str:
return f"Event({self.event_type}, {self.data})"
- def dict(self):
+ def to_dict(self) -> dict:
return {"event_type": self.event_type, "data": self.data}
@staticmethod
- def from_dict(data: dict):
+ def from_dict(data: dict) -> Optional["Event"]:
+ if "event_type" not in data or "data" not in data:
+ return
+ event_type = data["event_type"]
+ if event_type == EventType.INITIAL_STATE:
+ return InitialStateEvent(
+ data["data"]["world"]["width"],
+ data["data"]["world"]["height"],
+ data["data"]["entities"],
+ )
+ if event_type == EventType.SET_CONTROLLABLE:
+ return SetControllableEvent(data["data"]["id"], data["data"]["client_id"])
+ if event_type == EventType.ENTITY_BORN:
+ return EntityBornEvent(data["data"])
+ if event_type == EventType.ENTITY_POSITION_UPDATE:
+ return EntityPositionUpdateEvent(
+ data["data"]["id"], data["data"]["position"]
+ )
+ if event_type == EventType.ENTITY_DEATH:
+ return EntityDeathEvent(data["data"]["id"])
+
+ logger.warn(f"Unknown event type: {data['event_type']}")
return Event(EventType(data["event_type"]), data["data"])
-class Publishable:
- @abstractmethod
- async def publish(self, event: Event):
- pass
+class InitialStateEvent(Event):
+ def __init__(self, world_width: int, world_height: int, entities: List[Entity]):
+ self.world_width = world_width
+ self.world_height = world_height
+ self.entities = entities
+ super().__init__(
+ EventType.INITIAL_STATE,
+ {
+ "world": {"width": world_width, "height": world_height},
+ "entities": [entity.to_dict() for entity in entities],
+ },
+ )
+
+
+class SetControllableEvent(Event):
+ def __init__(self, entity_id: str, client_id: str):
+ self.entity_id = entity_id
+ self.client_id = client_id
+ super().__init__(
+ EventType.SET_CONTROLLABLE, {"id": entity_id, "client_id": client_id}
+ )
-class ClientEventTransformer:
+class EntityBornEvent(Event):
+ def __init__(self, entity: Entity):
+ self.entity = entity
+ super().__init__(EventType.ENTITY_BORN, {"entity": entity.to_dict()})
+
+
+class EntityPositionUpdateEvent(Event):
+ def __init__(self, entity_id: str, position: dict):
+ super().__init__(
+ EventType.ENTITY_POSITION_UPDATE,
+ {"id": entity_id, "position": position},
+ )
+
+
+class EntityDeathEvent(Event):
+ def __init__(self, entity_id: str):
+ super().__init__(EventType.ENTITY_DEATH, {"id": entity_id})
+
+
+class Publishable:
@abstractmethod
- def apply(self, event: Event) -> Event:
+ async def publish(self, event: Event):
pass
@@ -47,37 +106,32 @@ class EventProcessor:
class NetworkSystem(System):
- def __init__(
- self,
- event_processor: EventProcessor,
- client_event_transformer: ClientEventTransformer,
- ):
+ def __init__(self, event_processor: EventProcessor):
super().__init__(SystemType.NETWORK)
self.event_processor = event_processor
- self.client_event_transformer = client_event_transformer
self.events = []
+ self.client_events = []
self.clients = {}
async def update(self, entity_manager: EntityManager, delta_time: float) -> None:
- for event in self.events:
+ if len(self.events) + len(self.client_events) == 0:
+ return
+ for event in self.events + self.client_events:
self.event_processor.accept(entity_manager, event)
- client_events = [
- self.client_event_transformer.apply(entity_manager, event)
- for event in self.events
- ]
+ client_sendable = self.events + [event for event, _ in self.client_events]
await asyncio.gather(
*[
client.publish(event)
for client in self.clients.values()
- for event in client_events
+ for event in client_sendable
]
)
self.events = []
+ self.client_events = []
def client_event(self, client_id: str, event: Event) -> None:
- event.data["client_id"] = client_id
- self.events.append(event)
+ self.client_events.append((event, client_id))
def add_event(self, event: Event) -> None:
self.events.append(event)