aboutsummaryrefslogtreecommitdiff
path: root/kennel/engine/systems/network.py
blob: 7df8088b1841b4bf75370da5f11f50d08a973706 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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]