import { ComponentType, PositionComponent, TrailingPositionComponent, } from "./component"; import { create_cat, create_laser, Entity, EntityType } from "./entity"; import { EntityBornEvent, EntityDeathEvent, EntityPositionUpdateEvent, EventPublisher, EventQueue, EventType, InitialStateEvent, SetControllableEvent, } from "./events"; import { Game } from "./game"; import { InputSystem } from "./input"; import { RenderSystem } from "./render"; import { System, SystemType } from "./system"; export class NetworkSystem extends System { constructor( private readonly event_queue: EventQueue, private readonly event_publisher: EventPublisher, ) { super(SystemType.NETWORK); } public update(_dt: number, game: Game) { const events = this.event_queue.peek(); for (const event of events) { switch (event.event_type) { case EventType.INITIAL_STATE: this.process_initial_state_event(event as InitialStateEvent, game); break; case EventType.SET_CONTROLLABLE: this.process_set_controllable_event( event as SetControllableEvent, game, ); break; case EventType.ENTITY_BORN: this.process_entity_born_event(event as EntityBornEvent, game); break; case EventType.ENTITY_POSITION_UPDATE: this.process_entity_position_update_event( event as EntityPositionUpdateEvent, game, ); break; case EventType.ENTITY_DEATH: this.process_entity_death_event(event as EntityDeathEvent, game); break; } } this.event_queue.clear(); this.event_publisher.publish(); } private process_initial_state_event(event: InitialStateEvent, game: Game) { console.log("received initial state", event); const { world, entities } = event.data; const render_system = game.get_system(SystemType.RENDER); if (!render_system) { console.error("render system not found"); return; } render_system.set_world_dimensions(world.width, world.height); Object.values(entities).forEach((entity) => game.put_entity(this.process_new_entity(entity)), ); } private process_entity_position_update_event( event: EntityPositionUpdateEvent, game: Game, ) { console.log("received entity position update", event); const { position, id } = event.data; const entity = game.get_entity(id); if (typeof entity === "undefined") return; const position_component = entity.components[ ComponentType.POSITION ] as PositionComponent; position_component.x = position.x; position_component.y = position.y; if (ComponentType.TRAILING_POSITION in entity.components) { const trailing_position = entity.components[ ComponentType.TRAILING_POSITION ] as TrailingPositionComponent; trailing_position.trails.push({ x: position_component.x, y: position_component.y, time: Date.now(), }); } } private process_entity_born_event(event: EntityBornEvent, game: Game) { console.log("received a new entity", event); const { entity } = event.data; game.put_entity(this.process_new_entity(entity)); } private process_new_entity(entity: Entity): Entity { if (entity.entity_type === EntityType.LASER) { return create_laser(entity); } if (entity.entity_type === EntityType.CAT) { return create_cat(entity); } return entity; } private process_entity_death_event(event: EntityDeathEvent, game: Game) { console.log("an entity died D:", event); const { id } = event.data; game.remove_entity(id); } private process_set_controllable_event( event: SetControllableEvent, game: Game, ) { console.log("got a controllable event", event); if (event.data.client_id !== game.client_id) { console.warn("got controllable event for client that is not us"); return; } const input_system = game.get_system(SystemType.INPUT)!; input_system.add_controllable_entity(event.data.id); } }