WIP: ECS / Network System #1

Draft
simponic wants to merge 13 commits from websockets into main
5 changed files with 57 additions and 23 deletions
Showing only changes of commit 9f5e81327b - Show all commits

View File

@ -101,7 +101,7 @@ class Publishable:
class EventProcessor:
@abstractmethod
def accept(self, entity_manager: EntityManager, event: Event) -> None:
def accept(self, entity_manager: EntityManager, event: Event | tuple[Event, str]) -> None:
pass

View File

@ -23,7 +23,7 @@ system_manager = SystemManager()
class KennelEventProcessor(EventProcessor):
def accept(
self, entity_manager: EntityManager, event: type[Event | tuple[Event, str]]
self, entity_manager: EntityManager, event: Event | tuple[Event, str]
) -> None:
if isinstance(event, tuple):
client_event, client_id = event

View File

@ -1,16 +1,13 @@
import $ from "jquery";
import { Vec2 } from "./vector";
import {
EventType,
type SetControllableEvent,
type Event,
type EventPublisher,
} from "./event";
import { MouseController } from "./mouse_controller";
import {
EntityPositionUpdateEvent,
EventProcessor,
EventPublisher,
EventQueue,
EventType,
SetControllableEvent,
WebsocketEventPublisher,
WebSocketEventQueue,
} from "./network";
@ -18,10 +15,11 @@ class KennelClient {
private running: boolean;
private last_update: number;
private controllable_entities: Set<string>;
private controllable_entities: Set<string> = new Set();
private mouse_controller: MouseController;
constructor(
private readonly client_id: string,
private readonly event_queue: EventQueue,
private readonly event_publisher: EventPublisher,
) {
@ -39,21 +37,45 @@ class KennelClient {
this.mouse_controller.start();
const loop = (timestamp: number) => {
if (!this.running) return;
const dt = timestamp - this.last_update;
this.propogate_state_after(dt);
requestAnimationFrame(loop); // tail call recursion! /s
};
requestAnimationFrame(loop);
$(document).on("mousemove", (event) => {
this.mouse_controller.move(event.clientX, event.clientY);
});
}
public close() {
this.running = false;
this.mouse_controller.stop();
this.controllable_entities.clear();
$(document).off("mousemove");
}
private propogate_state_after(dt: number) {
// TODO: interpolate cats and lasers and stuff
const events = this.event_queue.peek();
for (const event of events) {
switch (event.event_type) {
case EventType.SET_CONTROLLABLE:
this.process_set_controllable_event(event as SetControllableEvent);
break;
}
}
console.log(events, dt);
this.event_queue.clear();
}
private process_set_controllable_event(event: SetControllableEvent) {
if (event.data.client_id !== this.client_id) {
console.warn("got controllable event for client that is not us");
return;
}
this.controllable_entities.add(event.data.id);
}
private on_mouse_move(position: Vec2) {
@ -62,13 +84,13 @@ class KennelClient {
event_type: EventType.ENTITY_POSITION_UPDATE,
data: { id, position: { x: position.x, y: position.y } },
};
this.event_publisher.send(event);
this.event_publisher.add(event);
}
}
}
$(async () => {
const session_id = await fetch("/assign", {
const client_id = await fetch("/assign", {
credentials: "include",
})
.then((res) => res.json())
@ -80,14 +102,9 @@ $(async () => {
});
const queue: EventQueue = new WebSocketEventQueue(ws);
const kennel_client = new KennelClient(session_id, null);
const publisher: EventPublisher = new WebsocketEventPublisher(ws);
const kennel_client = new KennelClient(client_id, queue, publisher);
ws.onclose = () => kennel_client.close();
const mouse_controller = new MouseController(on_mouse_move);
$(document).on("mousemove", (event) => {
mouse_controller.move(event.clientX, event.clientY);
});
mouse_controller.start();
kennel_client.start();
});

View File

@ -71,3 +71,20 @@ export class WebSocketEventQueue implements EventQueue {
};
}
}
export class WebsocketEventPublisher implements EventPublisher {
private queue: Event[];
constructor(private readonly websocket: WebSocket) {
this.queue = [];
}
public add(event: Event) {
this.queue.push(event);
}
public publish() {
this.websocket.send(JSON.stringify(this.queue));
this.queue = [];
}
}

View File

@ -1,7 +1,7 @@
export class Vec2 {
constructor(
private readonly x: number,
private readonly y: number,
public readonly x: number,
public readonly y: number,
) {}
public distance_to(that: Vec2): number {