mirror of
https://github.com/DinheroDevelopmentGroup/modular-minecraft-proxy.git
synced 2025-02-17 00:21:37 -05:00
lots of minor changes
This commit is contained in:
parent
6cba62e78c
commit
c5cc2c8c27
13 changed files with 248 additions and 84 deletions
6
.swcrc
6
.swcrc
|
@ -11,9 +11,13 @@
|
|||
"useDefineForClassFields": false
|
||||
},
|
||||
"externalHelpers": true,
|
||||
"target": "es5",
|
||||
"target": "esnext",
|
||||
"loose": true
|
||||
},
|
||||
"exclude": [
|
||||
"\\.js$",
|
||||
"\\.d\\.ts$"
|
||||
],
|
||||
"module": {
|
||||
"type": "es6"
|
||||
},
|
||||
|
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"files.exclude": {
|
||||
"src/module/*": false
|
||||
}
|
||||
}
|
32
package-lock.json
generated
32
package-lock.json
generated
|
@ -7,8 +7,9 @@
|
|||
"": {
|
||||
"name": "modular-minecraft-proxy",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^5.3.0",
|
||||
"minecraft-protocol": "^1.26.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1350,16 +1351,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
|
@ -2090,6 +2086,22 @@
|
|||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
|
|
|
@ -8,13 +8,15 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "scripty",
|
||||
"watch:build": "scripty",
|
||||
"copy": "scripty",
|
||||
"watch:copy": "scripty",
|
||||
"run": "scripty",
|
||||
"watch:run": "scripty",
|
||||
"watch": "scripty"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"config": {
|
||||
"scripty": {
|
||||
"parallel": true,
|
||||
|
@ -37,6 +39,7 @@
|
|||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^5.3.0",
|
||||
"minecraft-protocol": "^1.26.5"
|
||||
}
|
||||
}
|
||||
|
|
15
script/copy.sh
Executable file
15
script/copy.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
SOURCE=$1
|
||||
|
||||
if [ -z "$SOURCE" ]
|
||||
then
|
||||
SOURCE="src/"
|
||||
fi
|
||||
|
||||
# length of "src/" = 4
|
||||
TARGET="${SOURCE:4}"
|
||||
|
||||
TARGET="dist/$TARGET"
|
||||
|
||||
rsync -rav --exclude="*.ts" $SOURCE $TARGET
|
1
script/watch/copy.sh
Executable file
1
script/watch/copy.sh
Executable file
|
@ -0,0 +1 @@
|
|||
inotifywait -rm -e CLOSE_WRITE --format "%w" src | stdbuf -o0 sed 's@/$@@' | xargs -n1 -I{} ./script/copy.sh {}
|
16
src/index.ts
16
src/index.ts
|
@ -1,19 +1,15 @@
|
|||
import Instance from './instance/index.js'
|
||||
import { SERVER_OPTIONS } from './settings.js'
|
||||
import { createServer } from 'minecraft-protocol'
|
||||
|
||||
// See: https://nodejs.org/api/worker_threads.html#considerations-when-transferring-typedarrays-and-buffers
|
||||
Object.assign(Uint8Array.prototype, Buffer.prototype)
|
||||
|
||||
const VERSION = '1.19.4'
|
||||
|
||||
export const SERVER_OPTIONS = {
|
||||
host: '127.0.0.1',
|
||||
port: 25565,
|
||||
keepAlive: false,
|
||||
version: VERSION
|
||||
}
|
||||
|
||||
export const server = createServer(SERVER_OPTIONS)
|
||||
export const server = createServer({
|
||||
'online-mode': false,
|
||||
...SERVER_OPTIONS,
|
||||
keepAlive: false
|
||||
})
|
||||
|
||||
server.on('login', client => {
|
||||
// eslint-disable-next-line no-new
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import { type Message } from '../worker/parent.js'
|
||||
import { importModulesGenerator } from '../util/import-modules.js'
|
||||
import { Channel } from '../util/channel.js'
|
||||
import { TARGET_OPTIONS } from '../settings.js'
|
||||
import { dirname, resolve } from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import { Worker } from 'worker_threads'
|
||||
import { createClient, type ServerClient } from 'minecraft-protocol'
|
||||
import chalk from 'chalk'
|
||||
|
||||
if (!('require' in globalThis)) {
|
||||
globalThis.__filename = fileURLToPath(import.meta.url)
|
||||
|
@ -14,16 +16,6 @@ if (!('require' in globalThis)) {
|
|||
const WORKER_PATH = resolve(__dirname, '../worker')
|
||||
const MODULE_DIR_PATH = resolve(__dirname, '../module')
|
||||
|
||||
const VERSION = '1.19.4'
|
||||
|
||||
export const TARGET_OPTIONS = {
|
||||
host: 'kaboom.pw',
|
||||
port: 25565,
|
||||
keepAlive: false,
|
||||
username: 'Player137',
|
||||
version: VERSION
|
||||
}
|
||||
|
||||
export class Instance {
|
||||
public readonly client
|
||||
public readonly server
|
||||
|
@ -32,7 +24,13 @@ export class Instance {
|
|||
constructor (client: ServerClient) {
|
||||
this.client = client
|
||||
|
||||
const target = createClient(TARGET_OPTIONS)
|
||||
const target = createClient({
|
||||
auth: 'offline',
|
||||
username: client.username,
|
||||
...TARGET_OPTIONS,
|
||||
keepAlive: false
|
||||
})
|
||||
|
||||
this.server = target
|
||||
|
||||
target.on('error', error => {
|
||||
|
@ -50,7 +48,39 @@ export class Instance {
|
|||
}
|
||||
|
||||
private async _importModules (): Promise<void> {
|
||||
for await (const module of importModulesGenerator(MODULE_DIR_PATH, 'global.js')) {
|
||||
console.group('Loading modules... (global)')
|
||||
|
||||
const start = performance.now()
|
||||
|
||||
let moduleStart = NaN
|
||||
|
||||
for await (const module of importModulesGenerator(
|
||||
MODULE_DIR_PATH,
|
||||
'global.js',
|
||||
{
|
||||
pre (entry) {
|
||||
const now = performance.now()
|
||||
moduleStart = now
|
||||
|
||||
const module = entry.name
|
||||
console.group(`Loading ${module}...`)
|
||||
},
|
||||
post (entry) {
|
||||
const now = performance.now()
|
||||
const delta = now - moduleStart
|
||||
|
||||
console.groupEnd()
|
||||
console.info(`took ${delta.toPrecision(2)}ms`)
|
||||
},
|
||||
error (error, entry) {
|
||||
const module = entry.name
|
||||
|
||||
error.stack += `\n while loading module ${JSON.stringify(module)} (local)`
|
||||
|
||||
console.error(chalk.red(error.stack))
|
||||
}
|
||||
}
|
||||
)) {
|
||||
if (module === null) throw new Error('Expected module not to be null')
|
||||
if (typeof module !== 'object') throw new Error('Expected module to be an object')
|
||||
|
||||
|
@ -62,6 +92,13 @@ export class Instance {
|
|||
|
||||
await (f as (instance: Instance) => Promise<void>)(this)
|
||||
}
|
||||
|
||||
const end = performance.now()
|
||||
|
||||
const delta = end - start
|
||||
|
||||
console.groupEnd()
|
||||
console.info(`took ${delta.toFixed(2)}ms`)
|
||||
}
|
||||
|
||||
protected postMessage (channel: string, data: any): void {
|
||||
|
|
|
@ -9,57 +9,52 @@ export type PacketEventMap = Record<string, (packet: Packet) => AsyncVoid>
|
|||
// ? Should I export the channel
|
||||
export const channel = createChannel<Message>('proxy')
|
||||
|
||||
export class Proxy {
|
||||
public readonly client = new PublicEventHandler<PacketEventMap>()
|
||||
public readonly server = new PublicEventHandler<PacketEventMap>()
|
||||
function write (side: Side, packet: RawPacket): void {
|
||||
channel.write({
|
||||
side,
|
||||
packet
|
||||
})
|
||||
}
|
||||
|
||||
constructor () {
|
||||
channel.subscribe(({ side, packet: raw }: Message) => {
|
||||
void (async () => {
|
||||
const emitter = this[side]
|
||||
export const proxy = {
|
||||
client: new PublicEventHandler<PacketEventMap>(),
|
||||
server: new PublicEventHandler<PacketEventMap>(),
|
||||
|
||||
const packet = new Packet(raw.name, raw.data)
|
||||
|
||||
await emitter.emit('packet', packet)
|
||||
await emitter.emit(packet.name, packet)
|
||||
|
||||
if (packet.canceled) return
|
||||
|
||||
switch (side) {
|
||||
case 'client':
|
||||
side = 'server'
|
||||
break
|
||||
case 'server':
|
||||
side = 'client'
|
||||
break
|
||||
default:
|
||||
throw new Error(`Invalid side: ${side as any}`)
|
||||
}
|
||||
|
||||
channel.write({
|
||||
side,
|
||||
packet
|
||||
})
|
||||
})()
|
||||
})
|
||||
writeClient (name: string, data: unknown): void {
|
||||
write('client', { name, data })
|
||||
},
|
||||
writeServer (name: string, data: unknown): void {
|
||||
write('server', { name, data })
|
||||
}
|
||||
} as const
|
||||
|
||||
channel.subscribe(({ side, packet: raw }: Message) => {
|
||||
void (async () => {
|
||||
const emitter = proxy[side]
|
||||
|
||||
const packet = new Packet(raw.name, raw.data)
|
||||
|
||||
await emitter.emit('packet', packet)
|
||||
await emitter.emit(packet.name, packet)
|
||||
|
||||
if (packet.canceled) return
|
||||
|
||||
switch (side) {
|
||||
case 'client':
|
||||
side = 'server'
|
||||
break
|
||||
case 'server':
|
||||
side = 'client'
|
||||
break
|
||||
default:
|
||||
throw new Error(`Invalid side: ${side as any}`)
|
||||
}
|
||||
|
||||
protected write (side: Side, packet: RawPacket): void {
|
||||
channel.write({
|
||||
side,
|
||||
packet
|
||||
})
|
||||
}
|
||||
|
||||
public writeClient (name: string, data: unknown): void {
|
||||
this.write('client', { name, data })
|
||||
}
|
||||
|
||||
public writeServer (name: string, data: unknown): void {
|
||||
this.write('server', { name, data })
|
||||
}
|
||||
}
|
||||
|
||||
export const proxy = new Proxy()
|
||||
})()
|
||||
})
|
||||
|
||||
export default proxy
|
||||
|
|
21
src/settings.ts
Normal file
21
src/settings.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { type ClientOptions, type ServerOptions } from 'minecraft-protocol'
|
||||
|
||||
export const VERSION = '1.19.4'
|
||||
|
||||
interface TargetOptions extends Omit<ClientOptions, 'username'> {
|
||||
username?: ClientOptions['username']
|
||||
}
|
||||
|
||||
export const TARGET_OPTIONS: TargetOptions = {
|
||||
host: 'kaboom.pw',
|
||||
port: 25565,
|
||||
// username: 'RealDinhero21',
|
||||
// auth: 'microsoft',
|
||||
version: VERSION
|
||||
}
|
||||
|
||||
export const SERVER_OPTIONS: ServerOptions = {
|
||||
host: '127.0.0.1',
|
||||
port: 25565,
|
||||
version: VERSION
|
||||
}
|
|
@ -24,6 +24,17 @@ export class EventHandler<T extends EventMap<T>> {
|
|||
set.add(callback)
|
||||
}
|
||||
|
||||
public once<E extends keyof T>(name: E, callback: T[E]): void {
|
||||
const original = callback
|
||||
callback = function (this: ThisParameterType<T[E]>, ...args: Parameters<T[E]>): ReturnType<T[E]> {
|
||||
const output = original.apply(this, args)
|
||||
|
||||
return output as ReturnType<T[E]>
|
||||
} as unknown as T[E]
|
||||
|
||||
this.on(name, callback)
|
||||
}
|
||||
|
||||
public off<E extends keyof T> (name: E, callback: T[E]): void {
|
||||
const map = this.map
|
||||
|
||||
|
|
|
@ -5,22 +5,46 @@
|
|||
// }
|
||||
|
||||
import { exists } from './file.js'
|
||||
import { type AsyncVoid } from './types.js'
|
||||
import { type Dirent } from 'fs'
|
||||
import { readdir } from 'fs/promises'
|
||||
import { resolve } from 'path'
|
||||
|
||||
export async function * importModulesGenerator (directory: string, index: string): AsyncGenerator<unknown> {
|
||||
export interface Callbacks {
|
||||
pre?: (entry: Dirent) => AsyncVoid
|
||||
post?: (entry: Dirent) => AsyncVoid
|
||||
error?: (error: Error, entry: Dirent) => AsyncVoid
|
||||
}
|
||||
|
||||
export async function * importModulesGenerator (directory: string, index: string, callbacks?: Callbacks): AsyncGenerator<unknown> {
|
||||
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||||
const path = resolve(entry.path, entry.name, index)
|
||||
|
||||
if (!entry.isDirectory()) throw new Error(`Expected ${path} to be a directory`)
|
||||
if (!entry.isDirectory()) console.warn(`Expected ${entry.name} to be a directory (located at ${entry.path})`)
|
||||
|
||||
if (!await exists(path)) continue
|
||||
|
||||
yield await import(path)
|
||||
try {
|
||||
const preCallback = callbacks?.pre
|
||||
|
||||
if (preCallback !== undefined) await preCallback(entry)
|
||||
|
||||
yield await import(path)
|
||||
|
||||
const postCallback = callbacks?.post
|
||||
|
||||
if (postCallback !== undefined) await postCallback(entry)
|
||||
} catch (error) {
|
||||
const errorCallback = callbacks?.error
|
||||
|
||||
if (errorCallback === undefined) throw error
|
||||
|
||||
await errorCallback(error as Error, entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function importModules (directory: string, index: string): Promise<void> {
|
||||
export async function importModules (directory: string, index: string, callbacks?: Callbacks): Promise<void> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
for await (const _ of importModulesGenerator(directory, index));
|
||||
for await (const _ of importModulesGenerator(directory, index, callbacks));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { importModules } from '../util/import-modules.js'
|
||||
import { dirname, resolve } from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import chalk from 'chalk'
|
||||
|
||||
if (!('require' in globalThis)) {
|
||||
globalThis.__filename = fileURLToPath(import.meta.url)
|
||||
|
@ -9,4 +10,43 @@ if (!('require' in globalThis)) {
|
|||
|
||||
const MODULE_DIR_PATH = resolve(__dirname, '../module')
|
||||
|
||||
await importModules(MODULE_DIR_PATH, 'local.js')
|
||||
console.group('Loading modules... (local)')
|
||||
|
||||
const start = performance.now()
|
||||
|
||||
let moduleStart = NaN
|
||||
|
||||
await importModules(
|
||||
MODULE_DIR_PATH,
|
||||
'local.js',
|
||||
{
|
||||
pre (entry) {
|
||||
const module = entry.name
|
||||
console.group(`Loading ${module}...`)
|
||||
|
||||
const now = performance.now()
|
||||
moduleStart = now
|
||||
},
|
||||
post (entry) {
|
||||
const now = performance.now()
|
||||
const delta = now - moduleStart
|
||||
|
||||
console.groupEnd()
|
||||
console.info(`took ${delta.toFixed(2)}ms`)
|
||||
},
|
||||
error (error, entry) {
|
||||
const module = entry.name
|
||||
|
||||
error.stack += `\n while loading module ${JSON.stringify(module)} (local)`
|
||||
|
||||
console.error(chalk.red(error.stack))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const end = performance.now()
|
||||
|
||||
const delta = end - start
|
||||
|
||||
console.groupEnd()
|
||||
console.info(`took ${delta.toFixed(2)}ms`)
|
||||
|
|
Loading…
Reference in a new issue