aboutsummaryrefslogtreecommitdiff
path: root/kennel/engine
diff options
context:
space:
mode:
Diffstat (limited to 'kennel/engine')
-rw-r--r--kennel/engine/components/component.py2
-rw-r--r--kennel/engine/components/controllable.py2
-rw-r--r--kennel/engine/components/position.py2
-rw-r--r--kennel/engine/entities/entity.py2
-rw-r--r--kennel/engine/systems/network.py104
5 files changed, 83 insertions, 29 deletions
diff --git a/kennel/engine/components/component.py b/kennel/engine/components/component.py
index c8ef2d0..da55138 100644
--- a/kennel/engine/components/component.py
+++ b/kennel/engine/components/component.py
@@ -12,5 +12,5 @@ class Component:
self.component_type = component_type
@abstractmethod
- def dict(self) -> dict:
+ def to_dict(self) -> dict:
pass
diff --git a/kennel/engine/components/controllable.py b/kennel/engine/components/controllable.py
index 25ec835..a9173af 100644
--- a/kennel/engine/components/controllable.py
+++ b/kennel/engine/components/controllable.py
@@ -9,6 +9,6 @@ class Controllable(Component):
def __repr__(self) -> str:
return f"Controllable(by={self.by})"
- def dict(self) -> dict:
+ def to_dict(self) -> dict:
# don't serialize who owns this
return {}
diff --git a/kennel/engine/components/position.py b/kennel/engine/components/position.py
index 2a4da4a..5c5b372 100644
--- a/kennel/engine/components/position.py
+++ b/kennel/engine/components/position.py
@@ -10,5 +10,5 @@ class Position(Component):
def __repr__(self) -> str:
return f"Position(x={self.x}, y={self.y})"
- def dict(self) -> dict:
+ def to_dict(self) -> dict:
return {"x": self.x, "y": self.y}
diff --git a/kennel/engine/entities/entity.py b/kennel/engine/entities/entity.py
index 6623512..1d8c34d 100644
--- a/kennel/engine/entities/entity.py
+++ b/kennel/engine/entities/entity.py
@@ -27,7 +27,7 @@ class Entity:
return {
"entity_type": self.entity_type,
"id": self.id,
- "components": {k: v.dict() for k, v in self.components.items()},
+ "components": {k: v.to_dict() for k, v in self.components.items()},
}
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)