73 lines
2.8 KiB
TypeScript
73 lines
2.8 KiB
TypeScript
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), []);
|
|
});
|