import { assert, assertEquals } from "@std/assert"; import { PROTOCOL_VERSION } from "$/common/protocol.ts"; import { TICKS_PER_SECOND } from "$/common/constants.ts"; import { test_game } from "./helpers.ts"; Deno.test("a different protocol version is rejected before anything else", async () => { const { game, take, send, closed } = await test_game("mods"); game.on_connect(1); send(1, { type: "hello", name: "old", protocol: PROTOCOL_VERSION - 1 }); const [message] = take(1); assertEquals(message.type, "rejected"); assert(message.reason.includes(`protocol ${PROTOCOL_VERSION}`), message.reason); assert(closed.has(1)); game.on_connect(2); send(2, { type: "hello", name: "ancient" }); assertEquals(take(2)[0].type, "rejected"); }); Deno.test("welcome lists what to download, and nothing happens until ready", async () => { const { game, take, send, join } = await test_game("mods"); join(1, "alice"); take(1); let joined = 0; game.mods.after.player_join.for_mod("test").subscribe(() => joined++); game.on_connect(2); send(2, { type: "hello", name: "bob", protocol: PROTOCOL_VERSION }); const [welcome] = take(2); assertEquals(welcome.type, "welcome"); assertEquals(welcome.mods.map((m: { id: string }) => m.id), ["bworld"]); assert(welcome.atlas.png && welcome.atlas.sha256); assert(!("players" in welcome) && !("changes" in welcome), "welcome shouldn't have world state"); // not in the world yet: others don't hear about bob, and bob can't act send(2, { type: "chat", text: "am I here?" }); send(2, { type: "break_block", x: 0, y: 60, z: 0 }); assertEquals(take(1), []); assertEquals(take(2), []); assertEquals(joined, 0); send(2, { type: "ready" }); const messages = take(2); assertEquals(messages[0].type, "join"); assertEquals(messages[0].name, "bob"); assertEquals(messages[0].players.map((p: { name: string }) => p.name), ["alice"]); assert(messages.some((m) => m.type === "container" && m.container === "inventory")); assertEquals(joined, 1); assert(take(1).some((m) => m.type === "player_join" && m.player.name === "bob")); // a second ready or hello does nothing send(2, { type: "ready" }); send(2, { type: "hello", name: "bob", protocol: PROTOCOL_VERSION }); assertEquals(take(2).filter((m) => m.type === "join" || m.type === "welcome"), []); assertEquals(joined, 1); }); Deno.test("clients that never get ready are dropped", async () => { const { game, take, send, closed } = await test_game("mods"); game.on_connect(1); send(1, { type: "hello", name: "slow", protocol: PROTOCOL_VERSION }); take(1); for (let i = 0; i < 59 * TICKS_PER_SECOND; i++) game.tick(); assert(!closed.has(1), "dropped too early"); for (let i = 0; i < 2 * TICKS_PER_SECOND; i++) game.tick(); assert(closed.has(1)); assertEquals(take(1)[0].type, "rejected"); // too late now send(1, { type: "ready" }); assertEquals(take(1), []); });