From fde43f0e3245efc00c4dfb46b1473572a7fd88ea Mon Sep 17 00:00:00 2001 From: sophie Date: Wed, 17 Jul 2024 12:35:47 +0300 Subject: [PATCH] turn this into more of a library and allow for the pianoverse_pb and .proto to be exposed --- client.ts | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++ dotproto.ts | 2 + index.ts | 189 +--------------------------------------------------- 3 files changed, 192 insertions(+), 186 deletions(-) create mode 100644 client.ts create mode 100644 dotproto.ts diff --git a/client.ts b/client.ts new file mode 100644 index 0000000..5ce31f5 --- /dev/null +++ b/client.ts @@ -0,0 +1,187 @@ +import * as proto from "./pianoverse_pb"; +import EventEmitter from "node:events"; +import type TypedEmitter from "typed-emitter"; +import UserAgent from "user-agents"; + +const CEventType = proto.ClientMessage_EventType; +const SEventType = proto.ServerMessage_EventType; + +type MessageEvents = { + open: () => void; + close: () => void; + message: ( + user: { id: string; name: string; color: string }, + content: string + ) => void; + welcome: () => void; + rooms: (rooms: proto.ServerMessage_Room[]) => void; + join: (join: proto.ServerMessage_Join) => void; + leave: (id: string) => void; +}; + +interface Player { + id: string; + name: string; + color: string; + role?: number; + x?: number; + y?: number; +} + + +export class Client extends (EventEmitter as new () => TypedEmitter) { + private ws: WebSocket; + me!: Player; + chatHistory: proto.ServerMessage_Chat[] = []; + room: { + name?: string; + owner?: string; + } = {}; + rooms: proto.ServerMessage_Room[] = []; + + players = new Map(); + move(x: number, y: number) { + this.ws.send( + new proto.ClientMessage({ + event: CEventType.MOVE, + move: { + x, + y, + }, + }).toBinary() + ); + } + message(chat: string) { + chat.match(/.{1,200}/gm)?.forEach((z, i) => { + setTimeout(() => { + this.ws.send( + new proto.ClientMessage({ + event: CEventType.CHAT, + chat: z, + }).toBinary() + ); + }, 500 * i); + }); + } + keyDown(key: number, velocity: number) { + this.ws.send( + new proto.ClientMessage({ + event: CEventType.PRESS, + press: { + key, + vel: velocity, + }, + }).toBinary() + ); + } + keyUp(key: number) { + this.ws.send( + new proto.ClientMessage({ + event: CEventType.RELEASE, + release: { + key, + }, + }).toBinary() + ); + } + setProfile(name: string, color: string) { + this.ws.send( + new proto.ClientMessage({ + event: CEventType.PROFILE, + profile: { + name, + color, + }, + }).toBinary() + ); + } + + setRoom(room: string, priv?: boolean) { + this.ws.send( + new proto.ClientMessage({ + event: CEventType.ROOM, + room: { + room: room, + private: priv, + }, + }).toBinary() + ); + } + constructor(url: string) { + super(); + this.ws = new WebSocket(url.replace("http", "ws"), { + //@ts-expect-error + headers: { + Origin: url, + "User-Agent": new UserAgent().toString(), + }, + protocol: "pianoverse", + }); + + this.ws.addEventListener("open", () => { + this.ws.binaryType = "arraybuffer"; + setInterval(() => { + this.ws.send( + new proto.ClientMessage({ + event: CEventType.HEARTBEAT, + }).toBinary() + ); + }, 2000); + this.emit("open"); + }); + + this.ws.addEventListener("message", (e) => { + let data = new Uint8Array(e.data); + let decode; + try { + decode = proto.ServerMessage.fromBinary(data); + } catch { + console.log("Could not decode data."); + console.log(data); + return; + } + if (decode.event == SEventType.RATELIMIT) { + console.log("Ratelimit reached! Type: " + decode.rateLimit); + } + if (decode.event == SEventType.JOIN) { + this.players.set(decode.join!.id, decode.join!); + this.emit("join", decode.join!); + } + + if (decode.event == SEventType.LEAVE) { + this.emit("leave", decode.leave); + this.players.delete(decode.leave!); + } + + if (decode.event == SEventType.ROOMS) { + this.rooms = decode.rooms; + this.emit("rooms", decode.rooms); + } + if (decode.event == SEventType.WELCOME) { + this.me = { + id: decode.welcome!.id, + name: decode.welcome!.name, + color: decode.welcome!.color, + }; + this.room = { + name: decode.welcome!.room, + owner: decode.welcome!.owner, + }; + this.chatHistory = decode.welcome!.chat; + + this.emit("welcome"); + } + if (decode.event == SEventType.CHAT) { + this.emit( + "message", + { + id: decode.chat!.id, + name: decode.chat!.name, + color: decode.chat!.color, + }, + decode.chat!.content + ); + } + }); + } +} diff --git a/dotproto.ts b/dotproto.ts new file mode 100644 index 0000000..a41ab08 --- /dev/null +++ b/dotproto.ts @@ -0,0 +1,2 @@ +import {readFileSync} from "fs"; +export const dotproto = readFileSync("pianoverse.proto").toString() diff --git a/index.ts b/index.ts index c5624bb..bb8cadc 100644 --- a/index.ts +++ b/index.ts @@ -1,186 +1,3 @@ -import * as proto from "./pianoverse_pb"; -import EventEmitter from "node:events"; -import type TypedEmitter from "typed-emitter"; -import UserAgent from "user-agents"; - -const CEventType = proto.ClientMessage_EventType; -const SEventType = proto.ServerMessage_EventType; - -type MessageEvents = { - open: () => void; - close: () => void; - message: ( - user: { id: string; name: string; color: string }, - content: string - ) => void; - welcome: () => void; - rooms: (rooms: proto.ServerMessage_Room[]) => void; - join: (join: proto.ServerMessage_Join) => void; - leave: (id: string) => void; -}; - -interface Player { - id: string; - name: string; - color: string; - role?: number; - x?: number; - y?: number; -} - -export class Client extends (EventEmitter as new () => TypedEmitter) { - private ws: WebSocket; - me!: Player; - chatHistory: proto.ServerMessage_Chat[] = []; - room: { - name?: string; - owner?: string; - } = {}; - rooms: proto.ServerMessage_Room[] = []; - - players = new Map(); - move(x: number, y: number) { - this.ws.send( - new proto.ClientMessage({ - event: CEventType.MOVE, - move: { - x, - y, - }, - }).toBinary() - ); - } - message(chat: string) { - chat.match(/.{1,200}/gm)?.forEach((z, i) => { - setTimeout(() => { - this.ws.send( - new proto.ClientMessage({ - event: CEventType.CHAT, - chat: z, - }).toBinary() - ); - }, 500 * i); - }); - } - keyDown(key: number, velocity: number) { - this.ws.send( - new proto.ClientMessage({ - event: CEventType.PRESS, - press: { - key, - vel: velocity, - }, - }).toBinary() - ); - } - keyUp(key: number) { - this.ws.send( - new proto.ClientMessage({ - event: CEventType.RELEASE, - release: { - key, - }, - }).toBinary() - ); - } - setProfile(name: string, color: string) { - this.ws.send( - new proto.ClientMessage({ - event: CEventType.PROFILE, - profile: { - name, - color, - }, - }).toBinary() - ); - } - - setRoom(room: string, priv?: boolean) { - this.ws.send( - new proto.ClientMessage({ - event: CEventType.ROOM, - room: { - room: room, - private: priv, - }, - }).toBinary() - ); - } - constructor(url: string) { - super(); - this.ws = new WebSocket(url.replace("http", "ws"), { - //@ts-expect-error - headers: { - Origin: url, - "User-Agent": new UserAgent().toString(), - }, - protocol: "pianoverse", - }); - - this.ws.addEventListener("open", () => { - this.ws.binaryType = "arraybuffer"; - setInterval(() => { - this.ws.send( - new proto.ClientMessage({ - event: CEventType.HEARTBEAT, - }).toBinary() - ); - }, 2000); - this.emit("open"); - }); - - this.ws.addEventListener("message", (e) => { - let data = new Uint8Array(e.data); - let decode; - try { - decode = proto.ServerMessage.fromBinary(data); - } catch { - console.log("Could not decode data."); - console.log(data); - return; - } - if (decode.event == SEventType.RATELIMIT) { - console.log("Ratelimit reached! Type: " + decode.rateLimit); - } - if (decode.event == SEventType.JOIN) { - this.players.set(decode.join!.id, decode.join!); - this.emit("join", decode.join!); - } - - if (decode.event == SEventType.LEAVE) { - this.emit("leave", decode.leave); - this.players.delete(decode.leave!); - } - - if (decode.event == SEventType.ROOMS) { - this.rooms = decode.rooms; - this.emit("rooms", decode.rooms); - } - if (decode.event == SEventType.WELCOME) { - this.me = { - id: decode.welcome!.id, - name: decode.welcome!.name, - color: decode.welcome!.color, - }; - this.room = { - name: decode.welcome!.room, - owner: decode.welcome!.owner, - }; - this.chatHistory = decode.welcome!.chat; - - this.emit("welcome"); - } - if (decode.event == SEventType.CHAT) { - this.emit( - "message", - { - id: decode.chat!.id, - name: decode.chat!.name, - color: decode.chat!.color, - }, - decode.chat!.content - ); - } - }); - } -} +export * as proto from "./pianoverse_pb"; +export * from "./dotproto" +export * from "./client"