diff --git a/package.json b/package.json index 56072a9..2904ac8 100755 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "scripts": { "dev": "rimraf ./build && tsc -w", "build": "rimraf ./build && tsc", - "prepublishOnly": "npm i && npm run build" + "prepublishOnly": "pnpm i && pnpm run build", + "prepare": "pnpm run build" }, + "packageManager": "pnpm@10.17.0", "engines": { "node": ">=18.0.0" }, diff --git a/src/Launch.ts b/src/Launch.ts index d1663f3..05fc0d9 100755 --- a/src/Launch.ts +++ b/src/Launch.ts @@ -200,7 +200,7 @@ export type LaunchOPTS = { export default class Launch extends EventEmitter { options: LaunchOPTS; - + pid: number | null = null; async Launch(opt: LaunchOPTS) { const defaultOptions: LaunchOPTS = { url: null, @@ -302,6 +302,7 @@ export default class Launch extends EventEmitter { this.emit('data', `Launching with arguments ${argumentsLogs}`); let minecraftDebug = spawn(java, Arguments, { cwd: logs, detached: this.options.detached }) + this.pid = minecraftDebug.pid; minecraftDebug.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))) minecraftDebug.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))) minecraftDebug.on('close', (code) => this.emit('close', 'Minecraft closed')) @@ -401,4 +402,33 @@ export default class Launch extends EventEmitter { minecraftJava: gameJava } } + + kill() { + if (!this.pid) { + this.emit('error', { error: 'No Minecraft process to kill' }); + return; + } + + try { + if (process.platform === 'win32') { + // On Windows, just kill the process + process.kill(this.pid, 'SIGTERM'); // use SIGTERM instead of default for safer termination + } else { + // On Unix-like systems, kill the process group + // Ensure the PID is negative to target the process group + process.kill(-this.pid, 'SIGTERM'); + } + this.emit('data', 'Minecraft process killed'); + } catch (e: any) { + if (e.code === 'ESRCH') { + // Process does not exist + this.emit('data', 'Minecraft process already exited'); + } else if (e.code === 'EPERM') { + // Permission error + this.emit('error', { error: 'Permission denied when killing process', details: e }); + } else { + this.emit('error', { error: 'Failed to kill Minecraft process', details: e }); + } + } + } } \ No newline at end of file