Compare commits

..

1 Commits

Author SHA1 Message Date
Elizabeth Hunt 88be03b689
init commit with base ECS and Network System
continuous-integration/drone/pr Build is failing Details
2024-08-20 12:42:57 -07:00
9 changed files with 17 additions and 63 deletions

View File

@ -5,8 +5,8 @@ load_dotenv()
class Config:
WORLD_WIDTH = int(os.getenv("WORLD_WIDTH", 1000))
WORLD_HEIGHT = int(os.getenv("WORLD_HEIGHT", 1000))
SIMULATION_WIDTH = int(os.getenv("SIMULATION_WIDTH", 1000))
SIMULATION_HEIGHT = int(os.getenv("SIMULATION_HEIGHT", 1000))
HATECOMPUTERS_ENDPOINT = os.getenv(
"HATECOMPUTERS_ENDPOINT", "https://hatecomputers.club"

View File

@ -10,5 +10,4 @@ class Controllable(Component):
return f"Controllable(by={self.by})"
def dict(self) -> dict:
# don't serialize who owns this
return {}
return {"by": self.by}

View File

@ -23,13 +23,6 @@ class Entity:
def add_component(self, component: Component) -> None:
self.components[component.component_type] = component
def to_dict(self) -> dict:
return {
"entity_type": self.entity_type,
"id": self.id,
"components": {k: v.dict() for k, v in self.components.items()},
}
class EntityManager:
def __init__(self):
@ -65,6 +58,3 @@ class EntityManager:
def get_entity(self, entity_id: str) -> Optional[Entity]:
return self.entities.get(entity_id)
def to_dict(self) -> dict:
return {k: v.to_dict() for k, v in self.entities.items()}

View File

@ -6,7 +6,6 @@ import asyncio
class EventType(str, Enum):
INITIAL_STATE = "INITIAL_STATE"
ENTITY_BORN = "ENTITY_BORN"
ENTITY_POSITION_UPDATE = "ENTITY_POSITION_UPDATE"
ENTITY_DEATH = "ENTITY_DEATH"

View File

@ -5,7 +5,6 @@ from abc import abstractmethod
class SystemType(str, Enum):
NETWORK = "NETWORK"
WORLD = "WORLD"
class System:

View File

@ -1,24 +0,0 @@
from kennel.engine.systems.system import System, SystemType
from kennel.engine.entities.entity import EntityManager
from kennel.engine.components.component import ComponentType
from kennel.app import logger
class WorldSystem(System):
def __init__(self, width: int, height: int):
super().__init__(SystemType.WORLD)
self.width = width
self.height = height
async def update(self, entity_manager: EntityManager, delta_time: float):
entities = entity_manager.get_entities_with_component(ComponentType.POSITION)
for entity in entities:
position = entity.get_component(ComponentType.POSITION)
if position is None:
logger.error(f"Entity {entity} has no position component")
continue
position.x = max(0, min(self.width, position.x))
position.y = max(0, min(self.height, position.y))
entity.add_component(position)

View File

@ -10,7 +10,6 @@ from kennel.engine.systems.network import (
Event,
EventType,
)
from kennel.engine.systems.world import WorldSystem
from kennel.config import config
from .app import logger
from typing import List
@ -60,6 +59,9 @@ class KennelClientEventTransformer(ClientEventTransformer):
logger.error(f"Entity {id} does not exist")
return event
for component_type in entity.components:
if component_type == ComponentType.CONTROLLABLE:
# Do not send controllable components to clients
continue
component = entity.get_component(component_type)
if component is not None:
event.data[component_type] = component.dict()
@ -67,9 +69,8 @@ class KennelClientEventTransformer(ClientEventTransformer):
return event
system_manager.add_system(WorldSystem(config.WORLD_WIDTH, config.WORLD_HEIGHT))
system_manager.add_system(
NetworkSystem(EventProcessor(), KennelClientEventTransformer()),
NetworkSystem(EventProcessor(), KennelClientEventTransformer())
)
kennel = Game(entity_manager, system_manager, config.MIN_TIME_STEP)

View File

@ -12,16 +12,16 @@ from fastapi.staticfiles import StaticFiles
from kennel.engine.systems.system import SystemType
from kennel.engine.systems.network import Event, Publishable, EventType
from typing import Annotated, Optional
from kennel.kennel import (
from .kennel import (
kennel,
system_manager,
entity_manager,
create_session_controllable_entities,
)
from kennel.app import app, templates, logger
from kennel.kennelcats import KennelCatService
from kennel.middleware import logger_middleware
from kennel.config import config
from .app import app, templates, logger
from .kennelcats import KennelCatService
from .middleware import logger_middleware
from .config import config
import asyncio
import uuid
@ -83,19 +83,8 @@ async def websocket_endpoint(
session: Annotated[str, Depends(get_cookie_or_token)],
):
await websocket.accept()
logger.info(f"Websocket connection established for session {session}")
await websocket.send_json(
{
"event_type": EventType.INITIAL_STATE,
"data": {
"world": {"width": config.WORLD_WIDTH, "height": config.WORLD_HEIGHT},
"entities": kennel.entity_manager.to_dict(),
},
}
)
session_entities = create_session_controllable_entities(session)
logger.info(f"Websocket connection established for session {session}")
try:
network_system = system_manager.get_system(SystemType.NETWORK)
if network_system is None:
@ -108,8 +97,9 @@ async def websocket_endpoint(
network_system.add_client(session, WebSocketClient(websocket))
while True:
message = await websocket.receive_json()
network_system.client_event(session, Event.from_dict(message))
network_system.client_event(
session, Event.from_dict(await websocket.receive_json())
)
except Exception as e:
logger.error(f"WebSocket exception {e}")
finally:

View File

@ -5,10 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Kennel Club</title>
<script src='https://unpkg.com/panzoom@9.4.0/dist/panzoom.min.js'></script>
</head>
<body>
<div id="kennel-window"></div>
<script src="{{ url_for('static', path='/index.js') }}"></script>
</body>
</html>