UNPKG

moomooio-client

Version:

MooMooIO-Client is a client-side wrapper API designed for the game MooMoo.io. This package aims to provide a simple yet powerful API for creating clones, mods, or plugins for MooMoo.io.

118 lines (91 loc) 2.94 kB
import AntiKick from "./AntiKick"; import { decode } from "./ServerPackets"; import UnifyEmitter from "unify-emitter"; export interface MooMooIOConnectionEvents { close: { reason: string; code: number; }; error: null; open: null; message: ReturnType<typeof decode>; rawMessage: Uint8Array; deepSend: { data: Uint8Array; isTrusted: boolean }; send: Uint8Array; } export default class MooMooIOConnection extends UnifyEmitter<MooMooIOConnectionEvents> { #trusted: Uint8Array | null = null; #socket: WebSocket | null = null; protected antiKick = new AntiKick(); connect(ip: string, token: string) { const url = `wss://ip_${ip}.moomoo.io:8008/?gameIndex=0&token=${encodeURIComponent(token)}`; this.use(new WebSocket(url)); } disconnect() { if (!this.#socket || this.#socket.readyState == this.#socket.CLOSED) return; this.#socket.close(); } destroy() { this.#socket = null; this.antiKick.destroy(); this.removeListeners(); } /** * Sends the specified data through the socket connection. * @param data - The data to be sent as a Uint8Array. * @returns A boolean value indicating if the request has been successfully sent. */ send(data: Uint8Array): boolean { if (!this.#socket || this.#socket.readyState != this.#socket.OPEN) return false; const canSend = data instanceof Uint8Array && this.antiKick.canSend(data); if (canSend) { this.#trusted = data; this.#socket.send(data); this.emit("send", data); } return canSend; } use(socket: WebSocket) { this.socket = socket; } set socket(socket: WebSocket) { if (socket instanceof WebSocket) { this.#socket = socket; this.#initializeSocket(); } } isOPEN() { return this.#socket && this.#socket.readyState == this.#socket.OPEN; } #initializeSocket() { if (!this.#socket) return; this.#socket.binaryType = "arraybuffer"; this.#socket.addEventListener("message", (ev) => { if (ev.data instanceof ArrayBuffer) { this.emit("rawMessage", new Uint8Array(ev.data)); this.emit("message", decode(ev.data)); } }); this.#socket.addEventListener("open", () => { this.emit("open", null); }); this.#socket.addEventListener("close", (ev) => { this.emit("close", { reason: ev.reason, code: ev.code, }); }); this.#socket.addEventListener("error", () => { this.emit("error", null); }); const oldSend = this.#socket.send.bind(this.#socket); this.#socket.send = (data: Uint8Array) => { const isTrusted = this.#trusted == data; this.#trusted = null; if (data instanceof Uint8Array) { oldSend(data); this.emit("deepSend", { data, isTrusted }); } }; } }