Add city gameplay, snapshot migrations, administration and Compose operations

This commit is contained in:
mrleo1nid committed 2026-10-30 22:17:17 +03:00
1 parent 3b1fcd996a
commit 85df37c26e
24 files changed
+1042 -55

No files matched your search

+4 -1
View File
@@ -1,5 +1,5 @@
import { create, fromBinary, toBinary } from '@bufbuild/protobuf';
import { ClientMessageSchema, ServerMessageSchema, type ClientMessage, type Welcome, type Clock, type VoteState } from './generated/city_pb';
import { ClientMessageSchema, ServerMessageSchema, type ClientMessage, type Welcome, type Clock, type VoteState, type Gameplay } from './generated/city_pb';
import type { Bounds } from '../src/city/format';
import { EntityState } from './entities';
@@ -15,6 +15,7 @@ export class RoomConnection {
constructor(room: string, nickname: string, private events: {
welcome: (welcome: Welcome) => void; status: (text: string) => void;
clock: (clock: Clock) => void; vote: (vote: VoteState) => void;
gameplay: (state: Gameplay) => void;
}) {
const url = new URL(`/api/rooms/${encodeURIComponent(room)}/ws`, location.href);
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
@@ -42,6 +43,7 @@ export class RoomConnection {
} else events.status(b.value.code === 'VOTE_LIMIT' ? 'Дождитесь завершения голосования или 30-секундного интервала между предложениями' : `${b.value.code}: ${b.value.message}`);
break;
case 'clock': events.clock(b.value); break;
case 'gameplay': events.gameplay(b.value); break;
case 'voteState': events.vote(b.value); break;
}
} catch (error) { events.status((error as Error).message); this.destroy(); }
@@ -64,5 +66,6 @@ export class RoomConnection {
}
propose(speed: number) { this.send({ case: 'propose', value: { speed } }); }
vote(yes: boolean) { this.send({ case: 'vote', value: { yes } }); }
intervene(action: string) { this.send({ case: 'intervene', value: { action } }); }
destroy() { this.closed = true; clearTimeout(this.retry); clearInterval(this.ping); this.socket.close(); this.entities.clear(); }
}