Different Send/Receive Message Channel Types

and some other minor stuff
This commit is contained in:
Dinhero21 2024-01-08 04:25:38 -03:00
parent 8a58ee0ae5
commit 6cba62e78c
9 changed files with 41 additions and 134 deletions

View file

@ -17,7 +17,7 @@ const MODULE_DIR_PATH = resolve(__dirname, '../module')
const VERSION = '1.19.4' const VERSION = '1.19.4'
export const TARGET_OPTIONS = { export const TARGET_OPTIONS = {
host: 'grandma-does.tech', host: 'kaboom.pw',
port: 25565, port: 25565,
keepAlive: false, keepAlive: false,
username: 'Player137', username: 'Player137',
@ -71,14 +71,14 @@ export class Instance {
} satisfies Message) } satisfies Message)
} }
public createChannel<T> (id: string): Channel<T> { public createChannel<TSend, TReceive = TSend> (id: string): Channel<TSend, TReceive> {
const channel = new Channel<T>(id) const channel = new Channel<TSend, TReceive>(id)
channel._subscribe(data => { channel._subscribe(data => {
this.postMessage(id, data) this.postMessage(id, data)
}) })
this.worker.on('message', (message: Message<T>) => { this.worker.on('message', (message: Message<TReceive>) => {
if (message.channel !== id) return if (message.channel !== id) return
channel._write(message.data) channel._write(message.data)

5
src/module/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
*
!.gitignore
# internal modules
!proxy

View file

@ -1,22 +1,17 @@
import { type Side, type Message } from './shared.js' import { type Side, type Message } from './shared.js'
import { type AsyncVoid, EventHandler } from '../../util/events.js' import { PublicEventHandler } from '../../util/events.js'
import { createChannel } from '../../worker/parent.js' import { createChannel } from '../../worker/parent.js'
import { Packet, type RawPacket } from '../../util/packet.js' import { Packet, type RawPacket } from '../../util/packet.js'
import { type AsyncVoid } from '../../util/types.js'
export type EventMap = Record<string, (packet: Packet) => AsyncVoid> export type PacketEventMap = Record<string, (packet: Packet) => AsyncVoid>
export class EventEmitter extends EventHandler<EventMap> {
public async emit (name: string, packet: Packet): Promise<void> {
await this._emit(name, packet)
}
}
// ? Should I export the channel // ? Should I export the channel
export const channel = createChannel<Message>('proxy') export const channel = createChannel<Message>('proxy')
export class Proxy { export class Proxy {
public readonly client = new EventEmitter() public readonly client = new PublicEventHandler<PacketEventMap>()
public readonly server = new EventEmitter() public readonly server = new PublicEventHandler<PacketEventMap>()
constructor () { constructor () {
channel.subscribe(({ side, packet: raw }: Message) => { channel.subscribe(({ side, packet: raw }: Message) => {
@ -65,4 +60,6 @@ export class Proxy {
} }
} }
export default new Proxy() export const proxy = new Proxy()
export default proxy

View file

@ -1,39 +1,41 @@
export type Listener<T> = (data: T) => void
// _x -> x // _x -> x
// x -> _x // x -> _x
export class Channel<T> { export class Channel<TSend, TReceive = TSend> {
public readonly id public readonly id
constructor (id: string) { constructor (id: string) {
this.id = id this.id = id
} }
private readonly listeners = new Set<(data: T) => void>() private readonly listeners = new Set<Listener<TReceive>>()
public subscribe (listener: (data: T) => void): void { public subscribe (listener: Listener<TReceive>): void {
this.listeners.add(listener) this.listeners.add(listener)
} }
public unsubscribe (listener: (data: T) => void): void { public unsubscribe (listener: Listener<TReceive>): void {
this.listeners.delete(listener) this.listeners.delete(listener)
} }
public write (data: T): void { public write (data: TSend): void {
for (const listener of this._listeners) { for (const listener of this._listeners) {
listener(data) listener(data)
} }
} }
private readonly _listeners = new Set<(data: T) => void>() private readonly _listeners = new Set<Listener<TSend>>()
public _subscribe (listener: (data: T) => void): void { public _subscribe (listener: Listener<TSend>): void {
this._listeners.add(listener) this._listeners.add(listener)
} }
public _unsubscribe (listener: (data: T) => void): void { public _unsubscribe (listener: Listener<TSend>): void {
this._listeners.delete(listener) this._listeners.delete(listener)
} }
public _write (data: T): void { public _write (data: TReceive): void {
for (const listener of this.listeners) { for (const listener of this.listeners) {
listener(data) listener(data)
} }

View file

@ -1,4 +1,4 @@
export type AsyncVoid = void | Promise<void> import { type AsyncVoid } from './types.js'
export type EventMap<T> = { [K in keyof T]: (...args: any[]) => AsyncVoid } export type EventMap<T> = { [K in keyof T]: (...args: any[]) => AsyncVoid }
@ -40,3 +40,9 @@ export class EventHandler<T extends EventMap<T>> {
map.clear() map.clear()
} }
} }
export class PublicEventHandler<T extends EventMap<T>> extends EventHandler<T> {
public async emit<E extends keyof T> (name: E, ...data: Parameters<T[E]>): Promise<void> {
await this._emit(name, ...data)
}
}

View file

@ -3,13 +3,13 @@ export interface RawPacket {
data: unknown data: unknown
} }
export class Packet<T = unknown> { export class Packet<Data = unknown> {
public name public name
public data public data
public canceled: boolean = false public canceled: boolean = false
constructor (name: string, data: T) { constructor (name: string, data: Data) {
this.name = name this.name = name
this.data = data this.data = data
} }

1
src/util/types.ts Normal file
View file

@ -0,0 +1 @@
export type AsyncVoid = void | Promise<void>

View file

@ -1,104 +0,0 @@
// import { type UUID } from 'crypto'
// import { type AsyncVoid, EventHandler } from '../../util/events.js'
// import { type Packet } from '../util/packet.js'
// import proxy from './proxy.js'
// export type i64 = [number, number]
// export interface ClientChatPacketData {
// timestamp: i64
// salt: i64
// acknowledged: Uint8Array
// }
// export type Signature = Uint8Array
// export interface ClientChatMessagePacketData extends ClientChatPacketData {
// message: string
// signature: Signature | undefined
// offset: number
// }
// export interface ClientChatCommandPacketData extends ClientChatPacketData {
// command: string
// argumentSignatures: Signature[]
// messageCount: number
// }
// export interface ProfileLessChatPacketData {
// message: string
// type: number
// name: string
// // TODO: find out what target is supposed to be
// target: undefined
// }
// export interface PlayerChatPacketData {
// senderUuid: UUID
// index: number
// signature: Signature | undefined
// plainMessage: string
// timestamp: i64
// salt: i64
// // TODO: find out what previousMessages is supposed to be
// previousMessages: never[]
// unsignedChatContent: string
// filterType: number
// // TODO: Find out what filterTypeMask is supposed to be
// filterTypeMask: undefined
// type: number
// networkName: string
// // TODO: find out what networkTargetName is supposed to be
// networkTargetName: undefined
// }
// export interface SystemChatPacketData {
// content: string
// isActionBar: boolean
// }
// export interface ChatEventMap {
// 'client.command': (packet: Packet<ClientChatCommandPacketData>) => AsyncVoid
// 'client.message': (packet: Packet<ClientChatMessagePacketData>) => AsyncVoid
// 'server.profiless': (packet: Packet<ProfileLessChatPacketData>) => AsyncVoid
// 'server.player': (packet: Packet<PlayerChatPacketData>) => AsyncVoid
// 'server.system': (packet: Packet<SystemChatPacketData>) => AsyncVoid
// }
// export class Chat extends EventHandler<ChatEventMap> {
// constructor () {
// super()
// proxy.client.on('chat_command', async packet => {
// await this._emit('client.command', packet as Packet<ClientChatCommandPacketData>)
// })
// proxy.client.on('chat_message', async packet => {
// await this._emit('client.message', packet as Packet<ClientChatMessagePacketData>)
// })
// proxy.server.on('profileless_chat', async packet => {
// await this._emit('server.profiless', packet as Packet<ProfileLessChatPacketData>)
// })
// proxy.server.on('player_chat', async packet => {
// await this._emit('server.player', packet as Packet<PlayerChatPacketData>)
// })
// proxy.server.on('system_chat', async packet => {
// await this._emit('server.system', packet as Packet<SystemChatPacketData>)
// })
// }
// // // TODO: Fix
// // public writeClientCommand (command: string): void {
// // proxy.writeClient('chat_command', { command })
// // }
// // public writeClientMessage (message: string): void {
// // proxy.writeClient('chat_message', { message })
// // }
// }
// export default new Chat()

View file

@ -17,14 +17,14 @@ function postMessage (channel: string, data: any): void {
}) })
} }
export function createChannel<T> (id: string): Channel<T> { export function createChannel<TSend, TReceive = TSend> (id: string): Channel<TSend, TReceive> {
const channel = new Channel<T>(id) const channel = new Channel<TSend, TReceive>(id)
channel._subscribe(message => { channel._subscribe(message => {
postMessage(id, message) postMessage(id, message)
}) })
port.on('message', (message: Message<T>) => { port.on('message', (message: Message<TReceive>) => {
if (message.channel !== id) return if (message.channel !== id) return
channel._write(message.data) channel._write(message.data)