Compare commits
	
		
			1 Commits
		
	
	
		
			6f374aac7f
			...
			88be03b689
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 88be03b689 | 
|  | @ -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" | ||||
|  |  | |||
|  | @ -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} | ||||
|  |  | |||
|  | @ -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()} | ||||
|  |  | |||
|  | @ -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" | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ from abc import abstractmethod | |||
| 
 | ||||
| class SystemType(str, Enum): | ||||
|     NETWORK = "NETWORK" | ||||
|     WORLD = "WORLD" | ||||
| 
 | ||||
| 
 | ||||
| class System: | ||||
|  |  | |||
|  | @ -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) | ||||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
|  | @ -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> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue