A Typescript server emulator for Box Critters, a defunct virtual world.
1import { Server, Socket } from "https://deno.land/x/socket_io@0.2.0/mod.ts";
2import z from "zod";
3
4import * as world from "@/constants/world.ts";
5import * as utils from "@/utils.ts";
6import * as types from "@/types.ts";
7
8export function listen(
9 io: Server,
10 socket: Socket,
11 ctx: types.SocketHandlerContext,
12) {
13 socket.on("moveTo", (x: number, y: number) => {
14 if (!ctx.localPlayer || !ctx.localCrumb) return;
15
16 const roomData =
17 world.rooms[ctx.localCrumb._roomId][ctx.localPlayer._partyId] ||
18 world.rooms[ctx.localCrumb._roomId].default;
19 if (
20 z.object({
21 x: z.number().min(0).max(roomData.width),
22 y: z.number().min(0).max(roomData.height),
23 }).safeParse({ x: x, y: y }).success == false
24 ) return;
25
26 const newDirection = utils.getDirection(
27 ctx.localPlayer.x,
28 ctx.localPlayer.y,
29 x,
30 y,
31 );
32
33 ctx.localPlayer.x = x;
34 ctx.localPlayer.y = y;
35 ctx.localPlayer.rotation = newDirection;
36
37 ctx.localCrumb.x = x;
38 ctx.localCrumb.y = y;
39 ctx.localCrumb.r = newDirection;
40
41 io.in(ctx.localCrumb._roomId).volatile.emit("X", {
42 i: ctx.localPlayer.playerId,
43 x: x,
44 y: y,
45 r: newDirection,
46 });
47 });
48
49 socket.on("updateGear", (gear: Array<string>) => {
50 if (!ctx.localPlayer || !ctx.localCrumb) return;
51
52 if (
53 z.object({
54 gear: z.array(z.string().nonempty()).default([]),
55 }).strict().safeParse({ gear: gear }).success == false
56 ) return;
57
58 const _gear = [];
59 for (const itemId of gear) {
60 if (ctx.localPlayer.inventory.includes(itemId)) {
61 _gear.push(itemId);
62 }
63 }
64 ctx.localPlayer.gear = _gear;
65
66 io.in(ctx.localCrumb._roomId).emit("G", {
67 i: ctx.localPlayer.playerId,
68 g: ctx.localPlayer.gear,
69 });
70
71 socket.emit("updateGear", ctx.localPlayer.gear);
72 });
73}