-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwebsocket.ts
More file actions
112 lines (104 loc) · 3.43 KB
/
websocket.ts
File metadata and controls
112 lines (104 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import type { ServerWebSocket } from 'bun';
import { logger } from '.';
import api from './api';
export const websocketHandlers = {
async message(ws: ServerWebSocket, message: string | Buffer) {
if (!ws.data.authed) {
// Expecting auth message as JSON: { type: "auth", roomId, userId }
logger("Received message before auth: " + message);
if (typeof message !== "string") {
logger("Received non-string message before auth");
ws.send(JSON.stringify({ type: "auth", status: "fail" }));
return;
}
try {
const msg = JSON.parse(message);
if (msg.type !== "auth" || !msg.roomId || !msg.userId) {
ws.send(JSON.stringify({ type: "auth", status: "fail" }));
return;
}
const auth = api.connect(msg.roomId, msg.userId, ws);
if (!auth) {
ws.send(JSON.stringify({ type: "auth", status: "fail" }));
ws.close();
return;
}
logger(`WebSocket connected: ${msg.userId} in room ${msg.roomId}`);
ws.send(JSON.stringify({ type: "auth", status: "success" }));
ws.data.roomId = msg.roomId;
ws.data.userId = msg.userId;
ws.data.authed = true;
} catch (error) {
logger("Error processing auth message: " + error);
ws.send(JSON.stringify({ type: "auth", status: "fail" }));
}
return;
}
if (Buffer.isBuffer(message)) {
const players = api.rooms[ws.data.roomId];
if (!players) {
logger("Players object is undefined for room: " + ws.data.roomId);
return;
}
const self = players[ws.data.userId];
if (self?.mutedServerside) {
return;
}
if (players && typeof players === "object") {
for (const playerId in players) {
const player = players[playerId];
if (
player &&
ws.data &&
player.connected &&
player.websocket &&
player.websocket.readyState === 1 &&
playerId !== ws.data.userId
) {
if (self?.broadcastTo?.includes(playerId)) {
player.websocket.send(message);
continue;
}
let playerPosition = player.position || { x: 0, y: 0, z: 0 };
let selfPosition = self.position || { x: 0, y: 0, z: 0 };
let distance = Math.sqrt(
Math.pow(playerPosition.x - selfPosition.x, 2) +
Math.pow(playerPosition.y - selfPosition.y, 2) +
Math.pow(playerPosition.z - selfPosition.z, 2)
);
const maxDistance = 15;
if (distance > maxDistance) {
continue;
}
let processed = Buffer.allocUnsafe(message.length);
let falloff = 1 - distance / maxDistance;
logger(falloff.toString())
for (let i = 0; i < processed.length; i += 2) {
let sample = message.readInt16LE(i);
let adjustedSample = sample * falloff;
processed.writeInt16LE(Math.max(Math.min(adjustedSample, 32767), -32768), i);
}
player.websocket.send(processed);
}
}
}
}
},
open(ws: ServerWebSocket) {
ws.send(JSON.stringify({ type: "auth", status: "wait" }));
ws.data = { authed: false };
ws.data.intervalId = setInterval(() => {
if (ws.readyState === ws.OPEN && ws.data.authed) {
const muted = api.getUser(ws.data.roomId, ws.data.userId, false)?.mutedServerside;
ws.send(JSON.stringify({ type: "muted", value: muted !== undefined ? muted : "undefined" }));
}
}, 1000);
},
close(ws: ServerWebSocket) {
if (ws.data.authed) {
logger(`WebSocket disconnected: ${ws.data.userId} from room ${ws.data.roomId}`);
api.disconnect(ws.data.roomId, ws.data.userId);
}
clearInterval(ws.data.intervalId);
},
};