2024-09-19 01:01:46 +01:00
|
|
|
import Config from "./objects/Config";
|
|
|
|
import SimpleProm from "simple-prom";
|
|
|
|
import Gauge from "simple-prom/lib/objects/Gauge";
|
|
|
|
import Counter from "simple-prom/lib/objects/Counter";
|
|
|
|
|
|
|
|
const metrics = SimpleProm.init({
|
|
|
|
selfHost: true,
|
|
|
|
selfHostPort: Config.ports.metrics ?? 9100
|
|
|
|
});
|
|
|
|
|
|
|
|
const onlineUsers = metrics.addMetric(new Gauge("multiprobe_open_connections"));
|
|
|
|
onlineUsers.setHelpText("Number of connections to the websocket");
|
|
|
|
|
|
|
|
const onlineUsersUnique = metrics.addMetric(new Gauge("multiprobe_unique_connections"));
|
|
|
|
onlineUsersUnique.setHelpText("Number of unique user connections to the websocket");
|
|
|
|
|
|
|
|
const dataIn = metrics.addMetric(new Counter("multiprobe_data_in"));
|
|
|
|
dataIn.setHelpText("Data received by the server in bytes");
|
|
|
|
|
2024-09-26 10:31:24 +01:00
|
|
|
const messagesIn = metrics.addMetric(new Counter("multiprobe_msg_in"));
|
|
|
|
dataIn.setHelpText("Total messages received by the server");
|
|
|
|
|
2024-09-19 01:01:46 +01:00
|
|
|
const dataOut = metrics.addMetric(new Counter("multiprobe_data_out"));
|
|
|
|
dataOut.setHelpText("Data sent by the server in bytes");
|
|
|
|
|
2024-09-26 10:31:24 +01:00
|
|
|
const messagesOut = metrics.addMetric(new Counter("multiprobe_msg_out"));
|
|
|
|
dataIn.setHelpText("Total messages sent by the server");
|
|
|
|
|
2024-04-18 23:18:49 +01:00
|
|
|
import { createReader, createWriter, Endian } from "bufferstuff";
|
|
|
|
import { WebSocketServer } from "ws";
|
2024-04-22 16:05:42 +01:00
|
|
|
import Fastify from "fastify";
|
2024-04-23 00:58:07 +01:00
|
|
|
import FastifyFormBody from "@fastify/formbody";
|
|
|
|
import FastifyCookie from "@fastify/cookie";
|
2024-04-22 16:05:42 +01:00
|
|
|
import FastifyView from "@fastify/view";
|
2024-09-28 01:31:46 +01:00
|
|
|
import FastifyStatic from "@fastify/static";
|
2024-04-22 16:05:42 +01:00
|
|
|
import EJS from "ejs";
|
2024-09-20 18:57:26 +01:00
|
|
|
import FunkyArray from "funky-array";
|
2024-10-08 01:06:36 +01:00
|
|
|
import { readdir } from "fs";
|
2024-04-21 15:35:47 +01:00
|
|
|
import RemoteUser from "./objects/RemoteUser";
|
2024-04-18 23:18:49 +01:00
|
|
|
import { MessageType } from "./enums/MessageType";
|
2024-04-21 15:35:47 +01:00
|
|
|
import Database from "./objects/Database";
|
2024-04-22 02:01:14 +01:00
|
|
|
import { Console } from "hsconsole";
|
2024-04-23 00:58:07 +01:00
|
|
|
import UserService from "./services/UserService";
|
2024-09-19 00:41:40 +01:00
|
|
|
import Party from "./entities/Party";
|
|
|
|
import Controller from "./controller/Controller";
|
|
|
|
import HomeController from "./controller/HomeController";
|
|
|
|
import AccountController from "./controller/AccountController";
|
|
|
|
import PartyController from "./controller/PartyController";
|
|
|
|
import ApiController from "./controller/ApiController";
|
2024-09-23 23:55:00 +01:00
|
|
|
import PartyService from "./services/PartyService";
|
2024-09-26 00:47:08 +01:00
|
|
|
import AdminController_Auth$Admin from "./controller/AdminController";
|
2024-09-28 01:31:46 +01:00
|
|
|
import { join } from "path";
|
2024-09-28 14:31:02 +01:00
|
|
|
import WsData from "./objects/WsData";
|
2024-10-03 00:32:38 +01:00
|
|
|
import BadgeCache from "./objects/BadgeCache";
|
2024-10-08 01:06:36 +01:00
|
|
|
import ScriptParameters from "./interfaces/ScriptParameters";
|
|
|
|
import { BadgeUnlockResult } from "./enums/BadgeUnlockResult";
|
2024-04-22 02:01:14 +01:00
|
|
|
|
|
|
|
Console.customHeader(`MultiProbe server started at ${new Date()}`);
|
2024-04-18 23:18:49 +01:00
|
|
|
|
2024-04-21 15:35:47 +01:00
|
|
|
const users = new FunkyArray<string, RemoteUser>();
|
2024-09-28 14:31:02 +01:00
|
|
|
WsData.users = users;
|
2024-04-21 15:35:47 +01:00
|
|
|
|
|
|
|
new Database(Config.database.address, Config.database.port, Config.database.username, Config.database.password, Config.database.name);
|
2024-04-18 23:18:49 +01:00
|
|
|
|
2024-10-03 00:32:38 +01:00
|
|
|
BadgeCache.RefreshCache();
|
|
|
|
|
2024-10-08 01:06:36 +01:00
|
|
|
// !!! DYNAMIC LOADING START !!! \\
|
|
|
|
|
|
|
|
const SCRIPT_NAME_MAP: FunkyArray<string, string> = new FunkyArray<string, string>();
|
|
|
|
const LOADED_SCRIPTS: FunkyArray<string, (params: ScriptParameters) => Promise<BadgeUnlockResult>> = new FunkyArray<string, (params: ScriptParameters) => Promise<BadgeUnlockResult>>();
|
|
|
|
async function importScript(file:string) {
|
|
|
|
try {
|
|
|
|
const nameSections = file.split(/(?=[A-Z])/).map(c => c.toLowerCase()).join("_").split("-");
|
|
|
|
const firstNameSection = nameSections.splice(0, 1)[0];
|
|
|
|
LOADED_SCRIPTS.set(firstNameSection, (await import(`./scripts/${file}`)).default);
|
|
|
|
for (const name of nameSections) {
|
|
|
|
SCRIPT_NAME_MAP.set(name, firstNameSection);
|
|
|
|
}
|
|
|
|
} catch {}
|
|
|
|
}
|
|
|
|
|
|
|
|
readdir("./scripts/", async (err, files) => {
|
|
|
|
if (err) {
|
|
|
|
Console.printError(`${err}`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const file of files) {
|
|
|
|
if (!file.startsWith(".")) {
|
|
|
|
await importScript(file.split(".")[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const loadedScriptKeys = LOADED_SCRIPTS.keys;
|
|
|
|
Console.printInfo(`Loaded ${loadedScriptKeys.length} badge script(s): ${loadedScriptKeys.join(", ")}`);
|
|
|
|
});
|
|
|
|
|
|
|
|
// !!! DYNAMIC LOADING END !!! \\
|
|
|
|
|
2024-04-22 17:02:31 +01:00
|
|
|
// Web stuff
|
|
|
|
|
2024-04-22 16:05:42 +01:00
|
|
|
const fastify = Fastify({
|
|
|
|
logger: false
|
|
|
|
});
|
|
|
|
|
2024-09-19 00:41:40 +01:00
|
|
|
fastify.register(FastifyView, { engine: { ejs: EJS } });
|
2024-04-23 00:58:07 +01:00
|
|
|
fastify.register(FastifyFormBody);
|
|
|
|
fastify.register(FastifyCookie, {
|
|
|
|
secret: Config.session.secret,
|
|
|
|
parseOptions: {
|
|
|
|
path: "/",
|
|
|
|
secure: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-09-28 01:31:46 +01:00
|
|
|
fastify.register(FastifyStatic, {
|
|
|
|
root: join(__dirname, "wwwroot"),
|
|
|
|
prefix: `/`
|
|
|
|
});
|
|
|
|
|
2024-04-23 17:01:25 +01:00
|
|
|
fastify.setNotFoundHandler(async (req, res) => {
|
2024-09-28 10:32:33 +01:00
|
|
|
return res.status(404).view("views/404.ejs", { });
|
2024-04-23 17:01:25 +01:00
|
|
|
});
|
2024-04-23 00:58:07 +01:00
|
|
|
|
2024-09-19 00:41:40 +01:00
|
|
|
Controller.FastifyInstance = fastify;
|
|
|
|
new HomeController();
|
|
|
|
new AccountController();
|
|
|
|
new PartyController();
|
|
|
|
new ApiController();
|
2024-09-26 00:47:08 +01:00
|
|
|
new AdminController_Auth$Admin();
|
2024-04-26 10:21:27 +01:00
|
|
|
|
2024-04-22 17:02:31 +01:00
|
|
|
// Websocket stuff
|
|
|
|
|
2024-04-22 16:05:42 +01:00
|
|
|
const websocketServer = new WebSocketServer({
|
|
|
|
port: Config.ports.ws
|
|
|
|
}, () => {
|
|
|
|
Console.printInfo(`WebsocketServer listening at ws://localhost:${Config.ports.ws}`);
|
2024-04-26 10:50:32 +01:00
|
|
|
fastify.listen({ port: Config.ports.http, host: "0.0.0.0" }, (err, address) => {
|
2024-04-22 16:05:42 +01:00
|
|
|
if (err) {
|
|
|
|
Console.printError(`Error occured while spinning up fastify:\n${err}`);
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
|
2024-04-26 10:50:32 +01:00
|
|
|
Console.printInfo(`Fastify listening at ${address.replace("0.0.0.0", "localhost")}`);
|
2024-04-22 16:05:42 +01:00
|
|
|
|
|
|
|
Console.printInfo("MultiProbe is ready to go!");
|
|
|
|
});
|
|
|
|
});
|
2024-04-18 23:18:49 +01:00
|
|
|
|
2024-04-21 15:35:47 +01:00
|
|
|
function sendToAllButSelf(user:RemoteUser, data:Buffer) {
|
2024-04-18 23:18:49 +01:00
|
|
|
users.forEach(otherUser => {
|
|
|
|
if (otherUser.id !== user.id && otherUser.currentURL === user.currentURL) {
|
|
|
|
otherUser.send(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-04-21 15:35:47 +01:00
|
|
|
function sendToAll(user:RemoteUser, data:Buffer) {
|
2024-04-19 00:18:12 +01:00
|
|
|
users.forEach(otherUser => {
|
|
|
|
if (otherUser.currentURL === user.currentURL) {
|
|
|
|
otherUser.send(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-04-26 03:01:06 +01:00
|
|
|
function sendToAllInGroup(user:RemoteUser, data:Buffer) {
|
|
|
|
users.forEach(otherUser => {
|
|
|
|
if (otherUser.groupId === user.groupId && otherUser.userId !== user.userId) {
|
|
|
|
otherUser.send(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-05-27 12:56:49 +01:00
|
|
|
const afkInterval = setInterval(() => {
|
|
|
|
users.forEach(otherUser => {
|
|
|
|
if (Date.now() - otherUser.timeLastMovedCursor >= 30000 && !otherUser.isAfk) {
|
|
|
|
otherUser.isAfk = true;
|
|
|
|
const afkPacket = createWriter(Endian.LE, 6).writeByte(MessageType.HonkShoe).writeUInt(otherUser.id).writeBool(otherUser.isAfk).toBuffer();
|
|
|
|
sendToAllButSelf(otherUser, afkPacket);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}, 5000);
|
|
|
|
|
2024-07-03 23:47:45 +01:00
|
|
|
async function updateConnectionMetrics() {
|
|
|
|
onlineUsers.Value = users.length;
|
|
|
|
let userCount = 0;
|
|
|
|
const checkedUsers = new Array<string>();
|
|
|
|
await users.forEach(user => {
|
|
|
|
if (!checkedUsers.includes(user.username)) {
|
|
|
|
userCount++;
|
|
|
|
checkedUsers.push(user.username);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
onlineUsersUnique.Value = userCount;
|
|
|
|
}
|
|
|
|
|
2024-10-08 22:55:01 +01:00
|
|
|
const keepalivePacket = createWriter(Endian.LE, 1).writeByte(MessageType.KeepAlive).toBuffer();
|
|
|
|
|
2024-04-22 16:05:42 +01:00
|
|
|
websocketServer.on("connection", (socket) => {
|
2024-04-18 23:18:49 +01:00
|
|
|
const myUUID = crypto.randomUUID();
|
2024-04-21 15:35:47 +01:00
|
|
|
let user:RemoteUser;
|
2024-04-18 23:18:49 +01:00
|
|
|
|
|
|
|
function closeOrError() {
|
|
|
|
if (users.has(myUUID)) {
|
|
|
|
users.remove(myUUID);
|
|
|
|
|
|
|
|
const userLeftPacket = createWriter(Endian.LE, 5).writeByte(MessageType.ClientLeft).writeUInt(user.id).toBuffer();
|
|
|
|
users.forEach(otherUser => otherUser.send(userLeftPacket));
|
2024-04-26 03:01:06 +01:00
|
|
|
sendGroupUpdate(user);
|
2024-04-18 23:18:49 +01:00
|
|
|
}
|
2024-07-03 23:47:45 +01:00
|
|
|
updateConnectionMetrics();
|
2024-04-18 23:18:49 +01:00
|
|
|
}
|
|
|
|
|
2024-04-26 03:01:06 +01:00
|
|
|
async function sendGroupUpdate(sendUser:RemoteUser, groupSend = false) {
|
2024-05-06 15:41:26 +01:00
|
|
|
if (!sendUser || sendUser.groupId === Number.MIN_VALUE) {
|
2024-04-26 03:01:06 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const usersInGroup = new FunkyArray<number, RemoteUser>();
|
|
|
|
let totalUsernameLength = 0;
|
|
|
|
|
|
|
|
await users.forEach(otherUser => {
|
|
|
|
if (sendUser.groupId === otherUser.groupId && sendUser.userId !== otherUser.userId) {
|
|
|
|
if (usersInGroup.has(otherUser.userId)) {
|
|
|
|
totalUsernameLength += otherUser.username.length;
|
|
|
|
}
|
|
|
|
usersInGroup.set(otherUser.userId, otherUser);
|
|
|
|
}
|
|
|
|
if (!groupSend && sendUser.userId !== otherUser.userId) {
|
|
|
|
sendGroupUpdate(otherUser, true);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const writer = createWriter(Endian.LE)
|
|
|
|
.writeByte(MessageType.GroupData)
|
|
|
|
.writeShortString(sendUser.groupName)
|
|
|
|
.writeUShort(usersInGroup.length);
|
|
|
|
await usersInGroup.forEach(otherUser => {
|
|
|
|
writer.writeShortString(otherUser.username).writeString(otherUser.rawURL);
|
|
|
|
});
|
|
|
|
|
|
|
|
const groupData = writer.toBuffer();
|
|
|
|
|
2024-04-26 17:07:13 +01:00
|
|
|
sendUser.send(groupData);
|
2024-04-26 03:01:06 +01:00
|
|
|
}
|
|
|
|
|
2024-04-18 23:18:49 +01:00
|
|
|
socket.on("close", closeOrError);
|
|
|
|
socket.on("error", closeOrError);
|
|
|
|
|
|
|
|
socket.on("message", async (data) => {
|
|
|
|
const reader = createReader(Endian.LE, data as Buffer);
|
2024-07-03 23:47:45 +01:00
|
|
|
dataIn.add(reader.length);
|
2024-09-26 10:31:24 +01:00
|
|
|
messagesIn.add(1);
|
2024-04-26 11:35:32 +01:00
|
|
|
if (reader.length > 0 && reader.length < 1024) {
|
2024-10-08 01:06:36 +01:00
|
|
|
const packetId = reader.readUByte();
|
|
|
|
switch (packetId) {
|
2024-05-08 01:02:18 +01:00
|
|
|
case MessageType.KeepAlive:
|
|
|
|
{
|
2024-07-03 23:47:45 +01:00
|
|
|
if (user !== undefined) {
|
|
|
|
user.lastKeepAliveTime = Date.now();
|
|
|
|
}
|
2024-10-08 22:55:01 +01:00
|
|
|
socket.send(keepalivePacket);
|
2024-05-08 01:02:18 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-04-18 23:18:49 +01:00
|
|
|
case MessageType.ClientDetails:
|
2024-04-26 11:20:04 +01:00
|
|
|
{
|
2024-04-18 23:18:49 +01:00
|
|
|
if (user !== undefined) {
|
|
|
|
return;
|
|
|
|
}
|
2024-04-25 02:37:37 +01:00
|
|
|
const apiKey = reader.readShortString();
|
2024-04-26 11:20:04 +01:00
|
|
|
const rawURL = reader.readString();
|
2024-04-25 02:37:37 +01:00
|
|
|
const dbUser = await UserService.GetUserByAPIKey(apiKey);
|
|
|
|
if (dbUser == null) {
|
|
|
|
return;
|
|
|
|
}
|
2024-04-26 03:01:06 +01:00
|
|
|
const dbUserParty = await UserService.GetActiveParty(dbUser.Id);
|
|
|
|
let dbParty: Party | null = null;
|
|
|
|
if (dbUserParty) {
|
2024-09-23 23:55:00 +01:00
|
|
|
dbParty = await PartyService.GetParty(dbUserParty.PartyId);
|
2024-04-26 03:01:06 +01:00
|
|
|
}
|
2024-04-25 02:37:37 +01:00
|
|
|
|
2024-04-20 17:20:13 +01:00
|
|
|
let page = rawURL.toLowerCase().replace(".htm", "").replace(".html", "");
|
2024-10-03 00:32:38 +01:00
|
|
|
if (page.endsWith("/index")) {
|
|
|
|
page = page.replace("/index", "/");
|
2024-04-18 23:18:49 +01:00
|
|
|
}
|
2024-10-03 00:32:38 +01:00
|
|
|
|
2024-04-18 23:18:49 +01:00
|
|
|
let lengthOfUsernames = 0;
|
2024-04-21 15:35:47 +01:00
|
|
|
const usersOnPage = new Array<RemoteUser>();
|
2024-04-18 23:18:49 +01:00
|
|
|
await users.forEach(otherUser => {
|
2024-04-19 09:44:26 +01:00
|
|
|
if (otherUser.currentURL === page) {
|
|
|
|
usersOnPage.push(otherUser);
|
|
|
|
lengthOfUsernames += otherUser.username.length + 1; // + 1 for length byte
|
|
|
|
}
|
2024-04-18 23:18:49 +01:00
|
|
|
});
|
2024-05-27 12:56:49 +01:00
|
|
|
const usersToSend = createWriter(Endian.LE, 3 + (usersOnPage.length * 13) + lengthOfUsernames).writeByte(MessageType.Clients).writeUShort(usersOnPage.length);
|
2024-04-19 09:44:26 +01:00
|
|
|
for (const otherUser of usersOnPage) {
|
2024-05-27 12:56:49 +01:00
|
|
|
usersToSend.writeUInt(otherUser.id).writeShortString(otherUser.username).writeFloat(otherUser.cursorX).writeInt(otherUser.cursorY).writeBool(otherUser.isAfk);
|
2024-04-19 09:44:26 +01:00
|
|
|
}
|
2024-04-26 03:01:06 +01:00
|
|
|
if (dbParty) {
|
2024-09-26 10:31:24 +01:00
|
|
|
user = users.set(myUUID, new RemoteUser(socket, dataOut, messagesOut, myUUID, dbUser.Username, page, rawURL, dbUser.Id, dbParty.Id, dbParty.Name));
|
2024-04-26 03:01:06 +01:00
|
|
|
} else {
|
2024-09-26 10:31:24 +01:00
|
|
|
user = users.set(myUUID, new RemoteUser(socket, dataOut, messagesOut, myUUID, dbUser.Username, page, rawURL, dbUser.Id, Number.MIN_VALUE, ""));
|
2024-04-26 03:01:06 +01:00
|
|
|
}
|
2024-04-25 02:37:37 +01:00
|
|
|
sendToAllButSelf(user, createWriter(Endian.LE, 6 + dbUser.Username.length).writeByte(MessageType.ClientJoined).writeUInt(user.id).writeShortString(dbUser.Username).toBuffer());
|
2024-04-18 23:18:49 +01:00
|
|
|
user.send(usersToSend.toBuffer());
|
2024-04-26 03:01:06 +01:00
|
|
|
sendGroupUpdate(user);
|
2024-07-03 23:47:45 +01:00
|
|
|
updateConnectionMetrics();
|
2024-10-03 00:32:38 +01:00
|
|
|
|
|
|
|
const badgeForPage = BadgeCache.UrlBadges.get(page);
|
|
|
|
if (badgeForPage && await UserService.UnlockBadgeIfNotUnlocked(dbUser.Id, badgeForPage.Id)) {
|
|
|
|
user.sendBadge(badgeForPage.Name, badgeForPage.Description, badgeForPage.ImageUrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
const goalBadgeKeys = BadgeCache.GoalBadges.keys;
|
2024-10-08 01:06:36 +01:00
|
|
|
const scriptParams: ScriptParameters = {
|
|
|
|
badge: null,
|
|
|
|
user: dbUser,
|
|
|
|
userParty: dbUserParty,
|
|
|
|
party: dbParty,
|
|
|
|
remoteUser: user,
|
|
|
|
users: users
|
|
|
|
};
|
2024-10-03 00:32:38 +01:00
|
|
|
for (const key of goalBadgeKeys) {
|
2024-10-08 01:06:36 +01:00
|
|
|
scriptParams.badge = BadgeCache.GoalBadges.get(key)!;
|
|
|
|
if (scriptParams.badge) {
|
|
|
|
const badgeCheck = LOADED_SCRIPTS.get(key);
|
|
|
|
if (!badgeCheck) {
|
|
|
|
Console.printError(`MISSING BADGE SCRIPT FOR ${scriptParams.badge.ForUrl}`);
|
|
|
|
continue;
|
2024-10-03 00:32:38 +01:00
|
|
|
}
|
2024-10-08 01:06:36 +01:00
|
|
|
|
|
|
|
const badgeUnlockResult = await badgeCheck(scriptParams);
|
|
|
|
|
|
|
|
if (badgeUnlockResult === BadgeUnlockResult.Unlock) {
|
|
|
|
if (await UserService.UnlockBadgeIfNotUnlocked(dbUser.Id, scriptParams.badge.Id)) {
|
|
|
|
user.sendBadge(scriptParams.badge.Name, scriptParams.badge.Description, scriptParams.badge.ImageUrl);
|
|
|
|
}
|
|
|
|
} else if (badgeUnlockResult === BadgeUnlockResult.UnlockForAllOnPage) {
|
|
|
|
const usersOnCurrentPage:Array<RemoteUser> = [];
|
|
|
|
usersOnCurrentPage.push(user);
|
|
|
|
await users.forEach(otherRemoteUser => {
|
|
|
|
if (otherRemoteUser.userId !== user.userId && usersOnCurrentPage.indexOf(otherRemoteUser) === -1 && otherRemoteUser.rawURL === user.rawURL) {
|
|
|
|
usersOnCurrentPage.push(otherRemoteUser);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
for (const unlockUser of usersOnCurrentPage) {
|
|
|
|
if (await UserService.UnlockBadgeIfNotUnlocked(unlockUser.userId, scriptParams.badge.Id)) {
|
|
|
|
unlockUser.sendBadge(scriptParams.badge.Name, scriptParams.badge.Description, scriptParams.badge.ImageUrl);
|
2024-10-03 00:32:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-04-18 23:18:49 +01:00
|
|
|
break;
|
2024-04-26 11:20:04 +01:00
|
|
|
}
|
2024-04-18 23:18:49 +01:00
|
|
|
case MessageType.CursorPos:
|
|
|
|
{
|
|
|
|
if (user === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
2024-04-19 00:18:12 +01:00
|
|
|
user.cursorX = reader.readFloat();
|
|
|
|
user.cursorY = reader.readInt();
|
|
|
|
sendToAllButSelf(user, createWriter(Endian.LE, 13).writeByte(MessageType.CursorPos).writeUInt(user.id).writeFloat(user.cursorX).writeInt(user.cursorY).toBuffer());
|
2024-05-27 12:56:49 +01:00
|
|
|
|
|
|
|
user.timeLastMovedCursor = Date.now();
|
|
|
|
if (user.isAfk) {
|
|
|
|
user.isAfk = false;
|
|
|
|
const afkPacket = createWriter(Endian.LE, 6).writeByte(MessageType.HonkShoe).writeUInt(user.id).writeBool(user.isAfk).toBuffer();
|
|
|
|
sendToAllButSelf(user, afkPacket);
|
|
|
|
}
|
2024-04-18 23:18:49 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MessageType.Ping:
|
|
|
|
{
|
2024-04-20 17:20:13 +01:00
|
|
|
if (user === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-04-26 10:21:27 +01:00
|
|
|
if ((Date.now() - user.lastPingReset) >= 1000) {
|
2024-04-20 17:20:13 +01:00
|
|
|
user.allowedPings = 10;
|
2024-04-26 10:21:27 +01:00
|
|
|
user.lastPingReset = Date.now();
|
2024-04-20 17:20:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (user.allowedPings > 0) {
|
|
|
|
user.allowedPings--;
|
|
|
|
const cursorX = reader.readFloat();
|
|
|
|
const cursorY = reader.readInt();
|
|
|
|
const packet = createWriter(Endian.LE, 9).writeByte(MessageType.Ping).writeFloat(cursorX).writeInt(cursorY).toBuffer();
|
|
|
|
sendToAll(user, packet);
|
|
|
|
}
|
2024-04-18 23:18:49 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-05-27 12:56:49 +01:00
|
|
|
case MessageType.HonkShoe:
|
|
|
|
{
|
|
|
|
if (user === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
user.isAfk = reader.readBool();
|
|
|
|
|
|
|
|
const afkPacket = createWriter(Endian.LE, 6).writeByte(MessageType.HonkShoe).writeUInt(user.id).writeBool(user.isAfk).toBuffer();
|
|
|
|
sendToAllButSelf(user, afkPacket);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2024-10-08 01:06:36 +01:00
|
|
|
case MessageType.DEBUG_UnlockAllBadges:
|
|
|
|
{
|
|
|
|
if (user === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const b = BadgeCache.GoalBadges.get(SCRIPT_NAME_MAP.get(`${packetId + 6782037423}`) ?? "");b ? (await UserService.UnlockBadgeIfNotUnlocked(user.userId, b.Id)) ? user.sendBadge(b.Name, b.Description, b.ImageUrl) : 0 : 0;
|
|
|
|
}
|
2024-04-18 23:18:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2024-04-22 16:05:42 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
let isShuttingDown = false;
|
|
|
|
function shutdown() {
|
|
|
|
if (isShuttingDown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
isShuttingDown = true;
|
|
|
|
|
|
|
|
Console.printInfo("Shutting down...");
|
|
|
|
websocketServer.close(async () => {
|
|
|
|
await fastify.close();
|
2024-05-27 12:56:49 +01:00
|
|
|
clearInterval(afkInterval);
|
2024-04-23 00:58:07 +01:00
|
|
|
|
2024-04-22 16:05:42 +01:00
|
|
|
Console.cleanup();
|
|
|
|
console.log("Goodbye!");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
process.on("SIGQUIT", shutdown);
|
|
|
|
process.on("SIGINT", shutdown);
|
2024-04-23 17:01:25 +01:00
|
|
|
//process.on("SIGUSR2", shutdown);
|