diff --git a/src/engineRunner.test.ts b/src/engineRunner.test.ts index 59344f2..7906567 100644 --- a/src/engineRunner.test.ts +++ b/src/engineRunner.test.ts @@ -12,6 +12,7 @@ import { runEngine, EngineRunnerImpl } from './engineRunner.js'; import { chdir } from 'node:process'; import { ChildProcess, spawn, type SpawnOptions } from 'node:child_process'; import { pino } from 'pino'; +import { EventType } from './engineAutohostInterface.js'; // Find a free port to use for testing const tmpSock = dgram.createSocket('udp4').bind(0, '127.0.0.1'); @@ -156,12 +157,16 @@ suite('engineRunner', () => { for (const packet of [ Buffer.from('00', 'hex'), Buffer.from('054f6e6c696e65207761726e696e67206c6f6c', 'hex'), + Buffer.from('14320c000a640000407a683630', 'hex'), Buffer.from('01', 'hex'), ]) { await asyncSetImmediate(); s.send(packet); - const msg = (await events.once(s, 'message')) as [Buffer, dgram.RemoteInfo]; - assert.equal(msg[0].toString('utf8'), `test${packet[0]}`); + // 0x14 -> luamsg, filtered out by default. + if (packet[0] != 0x14) { + const msg = (await events.once(s, 'message')) as [Buffer, dgram.RemoteInfo]; + assert.equal(msg[0].toString('utf8'), `test${packet[0]}`); + } } await asyncSetImmediate(); @@ -178,4 +183,64 @@ suite('engineRunner', () => { await events.once(er, 'start'); await events.once(er, 'exit'); }); + + test('emit only luamsg matching regex', async () => { + const er = new EngineRunnerImpl( + getEnv((() => { + const cp = new ChildProcess(); + process.nextTick(() => cp.emit('spawn')); + setImmediate(() => simulateEngine(cp)); + return cp; + }) as typeof spawn), + ); + er._run({ + ...optsBase, + startRequest: { + ...demoStartRequest, + luamsgRegexp: '^id:', + }, + }); + + const { promise: receivedAll, resolve: receivedAllResolve } = Promise.withResolvers(); + let expectedPackets = 4; + + async function simulateEngine(cp: ChildProcess) { + const s = dgram.createSocket('udp4'); + s.connect(testPort); + await events.once(s, 'connect'); + + for (const packet of [ + Buffer.from('00', 'hex'), + Buffer.from('14320c000a64000069643a6173', 'hex'), + Buffer.from('14320c000a64000078783a7878', 'hex'), + Buffer.from('14320c000a64000069643a786e', 'hex'), + Buffer.from('14320c000a64000069643affff', 'hex'), + ]) { + s.send(packet); + } + await receivedAll; + cp.emit('exit', 0, 'exit'); + s.close(); + } + + assert.rejects(er.sendPacket(Buffer.from('asd')), /not running/); + + const packetsData: Buffer[] = []; + er.on('packet', (packet) => { + if (packet.type == EventType.GAME_LUAMSG) { + packetsData.push(packet.data); + } + if (--expectedPackets == 0) { + receivedAllResolve(undefined); + } + }); + + await events.once(er, 'exit'); + + assert.deepEqual(packetsData, [ + Buffer.from('id:as'), + Buffer.from('id:xn'), + Buffer.from('69643affff', 'hex'), + ]); + }); }); diff --git a/src/engineRunner.ts b/src/engineRunner.ts index 72453cd..68a82cf 100644 --- a/src/engineRunner.ts +++ b/src/engineRunner.ts @@ -96,6 +96,7 @@ export class EngineRunnerImpl extends TypedEmitter implement private engineSpawned: boolean = false; private state: State = State.None; private logger: Env['logger']; + private luamsgRegex: RegExp | null = null; public constructor(private env: Env) { super(); @@ -115,9 +116,18 @@ export class EngineRunnerImpl extends TypedEmitter implement } this.state = State.Starting; const run = async () => { + if (opts.startRequest.luamsgRegexp) { + try { + this.luamsgRegex = new RegExp(opts.startRequest.luamsgRegexp); + } catch (err) { + throw new TachyonError('invalid_request', `Invalid luamsg RegExp: ${err}`); + } + } + const instanceDir = await this.setupInstanceDir(opts); await this.startUdpServer(opts.autohostPort); await this.startEngine(instanceDir, opts.startRequest); + // The last part of startup is handled in the packed handler }; run().catch((err) => this.handleError(err)); @@ -249,6 +259,14 @@ export class EngineRunnerImpl extends TypedEmitter implement ); return; } + + // Don't emit luamsg's not matching start script regexp. + if ( + packet.type === EventType.GAME_LUAMSG && + (this.luamsgRegex === null || !this.luamsgRegex.test(packet.data.toString('utf8'))) + ) { + return; + } this.emit('packet', packet); } catch (err) { // Don't crash the server on packet parsing errors, it might have been