Reewrite project #430
							
								
								
									
										82
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										82
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -9,7 +9,7 @@
 | 
			
		||||
			"version": "4.0.0",
 | 
			
		||||
			"license": "GPL-3.0",
 | 
			
		||||
			"dependencies": {
 | 
			
		||||
				"@the-bds-maneger/server_versions": "^3.0.0",
 | 
			
		||||
				"@the-bds-maneger/server_versions": "^3.0.1",
 | 
			
		||||
				"adm-zip": "^0.5.9",
 | 
			
		||||
				"axios": "^0.27.2",
 | 
			
		||||
				"cron": "^2.1.0",
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
				"@types/adm-zip": "^0.5.0",
 | 
			
		||||
				"@types/cron": "^2.0.0",
 | 
			
		||||
				"@types/mocha": "^9.1.1",
 | 
			
		||||
				"@types/node": "^18.7.13",
 | 
			
		||||
				"@types/node": "^18.7.14",
 | 
			
		||||
				"@types/tar": "^6.1.2",
 | 
			
		||||
				"mocha": "^10.0.0",
 | 
			
		||||
				"ts-node": "^10.9.1",
 | 
			
		||||
@@ -68,9 +68,9 @@
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@the-bds-maneger/server_versions": {
 | 
			
		||||
			"version": "3.0.0",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@the-bds-maneger/server_versions/-/server_versions-3.0.0.tgz",
 | 
			
		||||
			"integrity": "sha512-+t2r7+iJHNbcF1A3o953Dcxm3LLN138tiC7CMWAa7IoJFhpqjYZcijlJEUZ4y6ueTE59yqtwninOtmRnhrqE/g==",
 | 
			
		||||
			"version": "3.0.1",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@the-bds-maneger/server_versions/-/server_versions-3.0.1.tgz",
 | 
			
		||||
			"integrity": "sha512-PRpmjigZlfOtjVKE5371ZF0vjDV30L256hohAZYeoIWuHxzpSi6oJdT3gGp/qyUsXJ7r7Ac7A9OnFGJqgkwk5g==",
 | 
			
		||||
			"dependencies": {
 | 
			
		||||
				"axios": "^0.27.2",
 | 
			
		||||
				"cors": "^2.8.5",
 | 
			
		||||
@@ -145,9 +145,9 @@
 | 
			
		||||
			"dev": true
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/node": {
 | 
			
		||||
			"version": "18.7.13",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz",
 | 
			
		||||
			"integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw=="
 | 
			
		||||
			"version": "18.7.14",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
 | 
			
		||||
			"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA=="
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/tar": {
 | 
			
		||||
			"version": "6.1.2",
 | 
			
		||||
@@ -160,9 +160,9 @@
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/webidl-conversions": {
 | 
			
		||||
			"version": "6.1.1",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
 | 
			
		||||
			"integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q=="
 | 
			
		||||
			"version": "7.0.0",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
 | 
			
		||||
			"integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog=="
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/whatwg-url": {
 | 
			
		||||
			"version": "8.2.2",
 | 
			
		||||
@@ -787,9 +787,9 @@
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/diff": {
 | 
			
		||||
			"version": "4.0.2",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
 | 
			
		||||
			"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
 | 
			
		||||
			"version": "5.0.0",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
 | 
			
		||||
			"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
 | 
			
		||||
			"dev": true,
 | 
			
		||||
			"engines": {
 | 
			
		||||
				"node": ">=0.3.1"
 | 
			
		||||
@@ -1758,15 +1758,6 @@
 | 
			
		||||
			"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
 | 
			
		||||
			"dev": true
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/mocha/node_modules/diff": {
 | 
			
		||||
			"version": "5.0.0",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
 | 
			
		||||
			"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
 | 
			
		||||
			"dev": true,
 | 
			
		||||
			"engines": {
 | 
			
		||||
				"node": ">=0.3.1"
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/mocha/node_modules/ms": {
 | 
			
		||||
			"version": "2.1.3",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
 | 
			
		||||
@@ -2543,6 +2534,15 @@
 | 
			
		||||
				"node": ">=0.4.0"
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/ts-node/node_modules/diff": {
 | 
			
		||||
			"version": "4.0.2",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
 | 
			
		||||
			"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
 | 
			
		||||
			"dev": true,
 | 
			
		||||
			"engines": {
 | 
			
		||||
				"node": ">=0.3.1"
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/type-check": {
 | 
			
		||||
			"version": "0.3.2",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
 | 
			
		||||
@@ -2896,9 +2896,9 @@
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"@the-bds-maneger/server_versions": {
 | 
			
		||||
			"version": "3.0.0",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@the-bds-maneger/server_versions/-/server_versions-3.0.0.tgz",
 | 
			
		||||
			"integrity": "sha512-+t2r7+iJHNbcF1A3o953Dcxm3LLN138tiC7CMWAa7IoJFhpqjYZcijlJEUZ4y6ueTE59yqtwninOtmRnhrqE/g==",
 | 
			
		||||
			"version": "3.0.1",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@the-bds-maneger/server_versions/-/server_versions-3.0.1.tgz",
 | 
			
		||||
			"integrity": "sha512-PRpmjigZlfOtjVKE5371ZF0vjDV30L256hohAZYeoIWuHxzpSi6oJdT3gGp/qyUsXJ7r7Ac7A9OnFGJqgkwk5g==",
 | 
			
		||||
			"requires": {
 | 
			
		||||
				"axios": "^0.27.2",
 | 
			
		||||
				"cors": "^2.8.5",
 | 
			
		||||
@@ -2970,9 +2970,9 @@
 | 
			
		||||
			"dev": true
 | 
			
		||||
		},
 | 
			
		||||
		"@types/node": {
 | 
			
		||||
			"version": "18.7.13",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz",
 | 
			
		||||
			"integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw=="
 | 
			
		||||
			"version": "18.7.14",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
 | 
			
		||||
			"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA=="
 | 
			
		||||
		},
 | 
			
		||||
		"@types/tar": {
 | 
			
		||||
			"version": "6.1.2",
 | 
			
		||||
@@ -2985,9 +2985,9 @@
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"@types/webidl-conversions": {
 | 
			
		||||
			"version": "6.1.1",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
 | 
			
		||||
			"integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q=="
 | 
			
		||||
			"version": "7.0.0",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
 | 
			
		||||
			"integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog=="
 | 
			
		||||
		},
 | 
			
		||||
		"@types/whatwg-url": {
 | 
			
		||||
			"version": "8.2.2",
 | 
			
		||||
@@ -3450,9 +3450,9 @@
 | 
			
		||||
			"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
 | 
			
		||||
		},
 | 
			
		||||
		"diff": {
 | 
			
		||||
			"version": "4.0.2",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
 | 
			
		||||
			"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
 | 
			
		||||
			"version": "5.0.0",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
 | 
			
		||||
			"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
 | 
			
		||||
			"dev": true
 | 
			
		||||
		},
 | 
			
		||||
		"domexception": {
 | 
			
		||||
@@ -4140,12 +4140,6 @@
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"diff": {
 | 
			
		||||
					"version": "5.0.0",
 | 
			
		||||
					"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
 | 
			
		||||
					"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
 | 
			
		||||
					"dev": true
 | 
			
		||||
				},
 | 
			
		||||
				"ms": {
 | 
			
		||||
					"version": "2.1.3",
 | 
			
		||||
					"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
 | 
			
		||||
@@ -4712,6 +4706,12 @@
 | 
			
		||||
					"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
 | 
			
		||||
					"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
 | 
			
		||||
					"dev": true
 | 
			
		||||
				},
 | 
			
		||||
				"diff": {
 | 
			
		||||
					"version": "4.0.2",
 | 
			
		||||
					"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
 | 
			
		||||
					"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
 | 
			
		||||
					"dev": true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@
 | 
			
		||||
		"node": ">=16.0.0"
 | 
			
		||||
	},
 | 
			
		||||
	"dependencies": {
 | 
			
		||||
		"@the-bds-maneger/server_versions": "^3.0.0",
 | 
			
		||||
		"@the-bds-maneger/server_versions": "^3.0.1",
 | 
			
		||||
		"adm-zip": "^0.5.9",
 | 
			
		||||
		"axios": "^0.27.2",
 | 
			
		||||
		"cron": "^2.1.0",
 | 
			
		||||
@@ -41,7 +41,7 @@
 | 
			
		||||
		"@types/adm-zip": "^0.5.0",
 | 
			
		||||
		"@types/cron": "^2.0.0",
 | 
			
		||||
		"@types/mocha": "^9.1.1",
 | 
			
		||||
		"@types/node": "^18.7.13",
 | 
			
		||||
		"@types/node": "^18.7.14",
 | 
			
		||||
		"@types/tar": "^6.1.2",
 | 
			
		||||
		"mocha": "^10.0.0",
 | 
			
		||||
		"ts-node": "^10.9.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,5 @@ export async function startServer() {
 | 
			
		||||
    else throw new Error("Cannot emulate x64 architecture. Check the documentents in \"https://github.com/The-Bds-Maneger/Bds-Maneger-Core/wiki/Server-Platforms#minecraft-bedrock-server-alpha\"");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const serverProcess = exec(command, args, {cwd: serverPath, maxBuffer: Infinity, env: {LD_LIBRARY_PATH: process.platform === "win32"?undefined:serverPath}});
 | 
			
		||||
  const serverActions = new actions(serverProcess, serverConfig);
 | 
			
		||||
  return {serverProcess, serverActions};
 | 
			
		||||
  return new actions(exec(command, args, {cwd: serverPath, maxBuffer: Infinity, env: {LD_LIBRARY_PATH: process.platform === "win32"?undefined:serverPath}}), serverConfig);
 | 
			
		||||
}
 | 
			
		||||
@@ -28,8 +28,7 @@ export function execFileAsync(command: string, args?: execOptions|string[], opti
 | 
			
		||||
 | 
			
		||||
export class customChild {
 | 
			
		||||
  private eventMiter = new EventEmitter({captureRejections: false});
 | 
			
		||||
  private tempLog = {};
 | 
			
		||||
  private child?: ChildProcess;
 | 
			
		||||
  public child?: ChildProcess;
 | 
			
		||||
 | 
			
		||||
  public kill(signal?: number|NodeJS.Signals) {if(this.child?.killed) return this.child?.killed;return this.child?.kill(signal);}
 | 
			
		||||
  public writeStdin(command: string, args?: string[]) {
 | 
			
		||||
@@ -61,17 +60,24 @@ export class customChild {
 | 
			
		||||
  public once(act: "breakStderr", fn: (data: string) => void): this;
 | 
			
		||||
  public once(act: string, fn: (...args: any[]) => void): this {this.eventMiter.once(act, fn);return this;}
 | 
			
		||||
 | 
			
		||||
  private tempLog = {};
 | 
			
		||||
  constructor(child: ChildProcess) {
 | 
			
		||||
    this.child = child;
 | 
			
		||||
    child.on("close", (code, signal) => this.emit("close", {code, signal}));
 | 
			
		||||
    child.on("exit", (code, signal) => this.emit("close", {code, signal}));
 | 
			
		||||
    child.on("error", err => this.emit("error", err));
 | 
			
		||||
    child.stdout.on("data", data => this.eventMiter.emit("stdoutRaw", data instanceof Buffer ? data.toString("utf8"):data));
 | 
			
		||||
    child.stderr.on("data", data => this.eventMiter.emit("stderrRaw", data instanceof Buffer ? data.toString("utf8"):data));
 | 
			
		||||
    // Storage tmp lines
 | 
			
		||||
    const parseLog = (to: "breakStdout"|"breakStderr", data: string): any => {
 | 
			
		||||
      if (this.tempLog[to] === undefined) this.tempLog[to] = "";
 | 
			
		||||
      const lines = data.split(/\r?\n/);
 | 
			
		||||
      if (lines.length === 1) return this.tempLog[to] += lines[0];
 | 
			
		||||
      for (const line of lines.slice(0, -1)) {
 | 
			
		||||
      if (lines.length === 1) {
 | 
			
		||||
        if (this.tempLog[to] === undefined) this.tempLog[to] = "";
 | 
			
		||||
        return this.tempLog[to] += lines[0];
 | 
			
		||||
      }
 | 
			
		||||
      const a = lines.pop();
 | 
			
		||||
      if (a !== "") lines.push(a);
 | 
			
		||||
      for (const line of lines) {
 | 
			
		||||
        if (!this.tempLog[to]) return this.eventMiter.emit(to, line);
 | 
			
		||||
        this.eventMiter.emit(to, this.tempLog[to]+line);
 | 
			
		||||
        delete this.tempLog[to];
 | 
			
		||||
@@ -79,8 +85,6 @@ export class customChild {
 | 
			
		||||
    }
 | 
			
		||||
    child.stdout.on("data", data => parseLog("breakStdout", data));
 | 
			
		||||
    child.stderr.on("data", data => parseLog("breakStderr", data));
 | 
			
		||||
    child.stdout.on("data", data => this.eventMiter.emit("stdoutRaw", data instanceof Buffer ? data.toString("utf8"):data));
 | 
			
		||||
    child.stderr.on("data", data => this.eventMiter.emit("stderrRaw", data instanceof Buffer ? data.toString("utf8"):data));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -92,7 +96,7 @@ export function exec(command: string, args?: ObjectEncodingOptions & ExecFileOpt
 | 
			
		||||
  let childOptions: ObjectEncodingOptions & ExecFileOptions = {};
 | 
			
		||||
  let childArgs: string[] = [];
 | 
			
		||||
  if (args instanceof Array) childArgs = args; else if (args instanceof Object) childOptions = args as execOptions;
 | 
			
		||||
  if (!options) childOptions = options;
 | 
			
		||||
  if (options) childOptions = options;
 | 
			
		||||
  if (childOptions?.env) childOptions.env = {...process.env, ...childOptions.env};
 | 
			
		||||
  return new customChild(execFile(command, childArgs, childOptions));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import type { customChild } from "./childPromisses";
 | 
			
		||||
import { EventEmitter } from "node:events";
 | 
			
		||||
 | 
			
		||||
export type playerClass = {[player: string]: {action: "connect"|"disconnect"|"unknown"; date: Date; history: Array<{action: "connect"|"disconnect"|"unknown"; date: Date}>}};
 | 
			
		||||
export type playerBase = {playerName: string, connectTime: Date, xuid?: string};
 | 
			
		||||
export type actionsPlayer = {
 | 
			
		||||
  name: "playerConnect"|"playerDisconnect"|"playerUnknown",
 | 
			
		||||
@@ -19,22 +20,104 @@ export type actionsServerStarted = {
 | 
			
		||||
  callback: (data: string, done: (started: serverStarted) => void) => void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type actionConfig = actionsPlayer|actionsPort|actionsServerStarted|actionsServerStarted;
 | 
			
		||||
export type actionsServerStop = {
 | 
			
		||||
  name: "serverStop",
 | 
			
		||||
  run: (childProcess: customChild) => void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type actionTp = {
 | 
			
		||||
  name: "tp",
 | 
			
		||||
  run: (childProcess: customChild, x: number|string, y: number|string, z: number|string) => void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type actionRun = actionsServerStop|actionTp;
 | 
			
		||||
export type actionCallback = actionsPlayer|actionsPort|actionsServerStarted|actionsServerStarted;
 | 
			
		||||
export type actionConfig = actionCallback|actionRun;
 | 
			
		||||
export class actions {
 | 
			
		||||
  private events = new EventEmitter({captureRejections: false});
 | 
			
		||||
  private childProcess: customChild;
 | 
			
		||||
  private stopServerFunction?: (childProcess: customChild) => void;
 | 
			
		||||
  private tpfunction?: (childProcess: customChild, x: number|string, y: number|string, z: number|string) => void;
 | 
			
		||||
 | 
			
		||||
  on(act: "playerConnect"|"playerDisconnect"|"playerUnknown", fn: (data: playerBase) => void): this;
 | 
			
		||||
  on(act: "portListening", fn: (data: portListen) => void): this;
 | 
			
		||||
  on(act: "serverStarted", fn: (data: serverStarted) => void): this;
 | 
			
		||||
  on(act: string, fn: (...args: any[]) => void) {this.events.on(act, fn); return this;}
 | 
			
		||||
  public on(act: "playerConnect"|"playerDisconnect"|"playerUnknown", fn: (data: playerBase) => void): this;
 | 
			
		||||
  public on(act: "portListening", fn: (data: portListen) => void): this;
 | 
			
		||||
  public on(act: "serverStarted", fn: (data: serverStarted) => void): this;
 | 
			
		||||
  public on(act: "log_stderr", fn: (data: string) => void): this;
 | 
			
		||||
  public on(act: "log_stdout", fn: (data: string) => void): this;
 | 
			
		||||
  public on(act: "exit", fn: (data: {code: number, signal: NodeJS.Signals}) => void): this;
 | 
			
		||||
  public on(act: string, fn: (...args: any[]) => void) {this.events.on(act, fn); return this;}
 | 
			
		||||
 | 
			
		||||
  once(act: "playerConnect"|"playerDisconnect"|"playerUnknown", fn: (data: playerBase) => void): this;
 | 
			
		||||
  once(act: "portListening", fn: (data: portListen) => void): this;
 | 
			
		||||
  once(act: "serverStarted", fn: (data: serverStarted) => void): this;
 | 
			
		||||
  once(act: string, fn: (...args: any[]) => void) {this.events.once(act, fn); return this;}
 | 
			
		||||
  public once(act: "playerConnect"|"playerDisconnect"|"playerUnknown", fn: (data: playerBase) => void): this;
 | 
			
		||||
  public once(act: "portListening", fn: (data: portListen) => void): this;
 | 
			
		||||
  public once(act: "serverStarted", fn: (data: serverStarted) => void): this;
 | 
			
		||||
  public once(act: "log_stderr", fn: (data: string) => void): this;
 | 
			
		||||
  public once(act: "log_stdout", fn: (data: string) => void): this;
 | 
			
		||||
  public once(act: "exit", fn: (data: {code: number, signal: NodeJS.Signals}) => void): this;
 | 
			
		||||
  public once(act: string, fn: (...args: any[]) => void) {this.events.once(act, fn); return this;}
 | 
			
		||||
 | 
			
		||||
  public stopServer() {
 | 
			
		||||
    if (typeof this.stopServer === "undefined") this.childProcess.kill("SIGKILL");
 | 
			
		||||
    this.stopServerFunction(this.childProcess);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public tp(x: number|string = 0, y: number|string = 0, z: number|string = 0) {
 | 
			
		||||
    if (typeof this.stopServer === "undefined") throw new Error("TP command not configured!");
 | 
			
		||||
    this.tpfunction(this.childProcess, x, y, z);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public runCommand(...command: Array<string|number>) {
 | 
			
		||||
    const psCommand = command.map(a => String(a));
 | 
			
		||||
    this.childProcess.writeStdin(psCommand.join(" "));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public portListening: portListen[] = [];
 | 
			
		||||
  public playerActions: playerClass = {};
 | 
			
		||||
 | 
			
		||||
  constructor(child: customChild, config: actionConfig[]) {
 | 
			
		||||
    child.on("breakStdout", data => config.forEach(fn => fn.callback(data, (...args) => this.events.emit(fn.name, ...args))));
 | 
			
		||||
    child.on("breakStderr", data => config.forEach(fn => fn.callback(data, (...args) => this.events.emit(fn.name, ...args))));
 | 
			
		||||
    this.childProcess = child;
 | 
			
		||||
    child.on("close", data => this.events.emit("exit", data));
 | 
			
		||||
    child.on("breakStdout", data => this.events.emit("log_stdout", data));
 | 
			
		||||
    child.on("breakStderr", data => this.events.emit("log_stderr", data));
 | 
			
		||||
 | 
			
		||||
    this.on("portListening", data => this.portListening.push(data));
 | 
			
		||||
    this.on("playerConnect", (data): any => {
 | 
			
		||||
      if (!this.playerActions[data.playerName]) return this.playerActions[data.playerName] = {
 | 
			
		||||
        action: "connect",
 | 
			
		||||
        date: data.connectTime,
 | 
			
		||||
        history: [{action: "connect", date: data.connectTime}]
 | 
			
		||||
      }
 | 
			
		||||
      this.playerActions[data.playerName].action = "connect";
 | 
			
		||||
      this.playerActions[data.playerName].date = data.connectTime;
 | 
			
		||||
      this.playerActions[data.playerName].history.push({action: "connect", date: data.connectTime});
 | 
			
		||||
    });
 | 
			
		||||
    this.on("playerDisconnect", (data): any => {
 | 
			
		||||
      if (!this.playerActions[data.playerName]) return this.playerActions[data.playerName] = {
 | 
			
		||||
        action: "disconnect",
 | 
			
		||||
        date: data.connectTime,
 | 
			
		||||
        history: [{action: "disconnect", date: data.connectTime}]
 | 
			
		||||
      }
 | 
			
		||||
      this.playerActions[data.playerName].action = "disconnect";
 | 
			
		||||
      this.playerActions[data.playerName].date = data.connectTime;
 | 
			
		||||
      this.playerActions[data.playerName].history.push({action: "disconnect", date: data.connectTime});
 | 
			
		||||
    });
 | 
			
		||||
    this.on("playerUnknown", (data): any => {
 | 
			
		||||
      if (!this.playerActions[data.playerName]) return this.playerActions[data.playerName] = {
 | 
			
		||||
        action: "unknown",
 | 
			
		||||
        date: data.connectTime,
 | 
			
		||||
        history: [{action: "unknown", date: data.connectTime}]
 | 
			
		||||
      }
 | 
			
		||||
      this.playerActions[data.playerName].action = "unknown";
 | 
			
		||||
      this.playerActions[data.playerName].date = data.connectTime;
 | 
			
		||||
      this.playerActions[data.playerName].history.push({action: "unknown", date: data.connectTime});
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const actions = config.filter((a: actionCallback) => typeof a?.callback === "function") as actionCallback[];
 | 
			
		||||
    child.on("breakStdout", data => actions.forEach(fn => fn.callback(data, (...args: any[]) => this.events.emit(fn.name, ...args))));
 | 
			
		||||
    child.on("breakStderr", data => actions.forEach(fn => fn.callback(data, (...args: any[]) => this.events.emit(fn.name, ...args))));
 | 
			
		||||
    for (const action of (config.filter((a: actionRun) => typeof a?.run === "function") as actionRun[])) {
 | 
			
		||||
      if (action.name === "serverStop") this.stopServerFunction = action.run;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -40,10 +40,6 @@ export async function startServer(Config?: {maxMemory?: number, minMemory?: numb
 | 
			
		||||
    if (Config?.minMemory) args.push(`-Xms${Config?.minMemory}m`);
 | 
			
		||||
    if (Config?.maxMemory) args.push(`-Xmx${Config?.maxMemory}m`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  args.push(jarPath);
 | 
			
		||||
  const serverProcess = exec(command, args, {cwd: serverPath, maxBuffer: Infinity});
 | 
			
		||||
  const serverActions = new actions(serverProcess, serverConfig);
 | 
			
		||||
  return {serverProcess, serverActions};
 | 
			
		||||
  return new actions(exec(command, args, {cwd: serverPath, maxBuffer: Infinity}), serverConfig);
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@ import * as fs from "node:fs/promises";
 | 
			
		||||
import * as os from "node:os";
 | 
			
		||||
import * as tar from "tar";
 | 
			
		||||
import { existsSync as  fsExistsSync } from "node:fs";
 | 
			
		||||
import { getPocketminePhar, versionUrl } from "@the-bds-maneger/server_versions";
 | 
			
		||||
import { getPocketminePhar, versionAPIs } from "@the-bds-maneger/server_versions";
 | 
			
		||||
import { execFileAsync, exec } from './childPromisses';
 | 
			
		||||
import { serverRoot } from "./pathControl";
 | 
			
		||||
import { getBuffer } from "./httpRequest";
 | 
			
		||||
@@ -12,6 +12,7 @@ import AdmZip from "adm-zip";
 | 
			
		||||
import { promisify } from 'node:util';
 | 
			
		||||
export const serverPath = path.join(serverRoot, "pocketmine");
 | 
			
		||||
export const serverPhar = path.join(serverPath, "pocketmine.phar");
 | 
			
		||||
export const phpBinPath = path.join(serverPath, "bin", (process.platform === "win32"?"php":"bin"), "php");
 | 
			
		||||
 | 
			
		||||
async function Readdir(pathRead: string, filter?: Array<RegExp>) {
 | 
			
		||||
if (!filter) filter = [/.*/];
 | 
			
		||||
@@ -54,7 +55,7 @@ async function buildPhp() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function installPhp(): Promise<void> {
 | 
			
		||||
  const file = (await getBuffer(`${versionUrl}/pocketmine/bin?os=${process.platform}&arch=${process.arch}`).then(res => JSON.parse(res.toString("utf8")) as {url: string, name: string}[]))[0];
 | 
			
		||||
  const file = (await getBuffer(`${versionAPIs[0]}/pocketmine/bin?os=${process.platform}&arch=${process.arch}`).then(res => JSON.parse(res.toString("utf8")) as {url: string, name: string}[]))[0];
 | 
			
		||||
  if (!file) return buildPhp();
 | 
			
		||||
  if (fsExistsSync(path.resolve(serverPath, "bin"))) await fs.rm(path.resolve(serverPath, "bin"), {recursive: true});
 | 
			
		||||
  await fs.mkdir(path.resolve(serverPath, "bin"), {recursive: true});
 | 
			
		||||
@@ -68,16 +69,17 @@ async function installPhp(): Promise<void> {
 | 
			
		||||
  }
 | 
			
		||||
  if (process.platform === "linux"||process.platform === "android"||process.platform === "darwin") {
 | 
			
		||||
    const ztsFind = await Readdir(path.resolve(serverPath, "bin"), [/.*debug-zts.*/]);
 | 
			
		||||
    if (ztsFind.length === 0) return;
 | 
			
		||||
    const phpIniPath = (await Readdir(path.resolve(serverPath, "bin"), [/php\.ini$/]))[0].path;
 | 
			
		||||
    let phpIni = await fs.readFile(phpIniPath, "utf8");
 | 
			
		||||
    if (phpIni.includes("extension_dir")) await fs.writeFile(phpIniPath, phpIni.replace(/extension_dir=.*/g, ""));
 | 
			
		||||
    phpIni = phpIni+`\nextension_dir=${ztsFind[0].path}`
 | 
			
		||||
    await fs.writeFile(phpIniPath, phpIni);
 | 
			
		||||
    if (ztsFind.length > 0) {
 | 
			
		||||
      const phpIniPath = (await Readdir(path.resolve(serverPath, "bin"), [/php\.ini$/]))[0].path;
 | 
			
		||||
      let phpIni = await fs.readFile(phpIniPath, "utf8");
 | 
			
		||||
      if (phpIni.includes("extension_dir")) await fs.writeFile(phpIniPath, phpIni.replace(/extension_dir=.*/g, ""));
 | 
			
		||||
      phpIni = phpIni+`\nextension_dir=${path.resolve(ztsFind[0].path, "..")}`
 | 
			
		||||
      await fs.writeFile(phpIniPath, phpIni);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  // test it's works php
 | 
			
		||||
  await fs.writeFile(path.join(os.tmpdir(), "test.php"), `<?php echo "Hello World";`);
 | 
			
		||||
  await execFileAsync(path.join(serverPath, "bin", process.platform === "win32" ? "php/php.exe" : "php"), ["-f", path.join(os.tmpdir(), "test.php")]).catch(buildPhp);
 | 
			
		||||
  await execFileAsync(phpBinPath, ["-f", path.join(os.tmpdir(), "test.php")]).catch(buildPhp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function installServer(version: string|boolean) {
 | 
			
		||||
@@ -109,9 +111,5 @@ const serverConfig: actionConfig[] = [
 | 
			
		||||
 | 
			
		||||
export async function startServer() {
 | 
			
		||||
  if (!fsExistsSync(serverPath)) throw new Error("Install server fist!");
 | 
			
		||||
  const phpFile = path.join(serverPath, "bin", process.platform === "win32"?"php":"bin", "php");
 | 
			
		||||
 | 
			
		||||
  const serverProcess = exec(phpFile, [serverPhar], {cwd: serverPath, maxBuffer: Infinity});
 | 
			
		||||
  const serverActions = new actions(serverProcess, serverConfig);
 | 
			
		||||
  return {serverProcess, serverActions};
 | 
			
		||||
  return new actions(exec(phpBinPath, [serverPhar], {cwd: serverPath, maxBuffer: Infinity}), serverConfig);
 | 
			
		||||
}
 | 
			
		||||
@@ -41,9 +41,6 @@ export async function startServer(Config?: {maxMemory?: number, minMemory?: numb
 | 
			
		||||
    if (Config?.maxMemory) args.push(`-Xmx${Config?.maxMemory}m`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  args.push(jarPath);
 | 
			
		||||
  const serverProcess = exec(command, args, {cwd: serverPath, maxBuffer: Infinity});
 | 
			
		||||
  const serverActions = new actions(serverProcess, serverConfig);
 | 
			
		||||
  return {serverProcess, serverActions};
 | 
			
		||||
  return new actions(exec(command, args, {cwd: serverPath, maxBuffer: Infinity}), serverConfig);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,10 @@ import { installServer, startServer } from "../src/bedrock";
 | 
			
		||||
describe("Bedrock", () => {
 | 
			
		||||
  it("Install and Start", async function(){
 | 
			
		||||
    this.timeout(1000*60*60*15);
 | 
			
		||||
    await installServer(true);
 | 
			
		||||
    await installServer("latest");
 | 
			
		||||
    const serverManeger = await startServer();
 | 
			
		||||
    serverManeger.serverProcess.on("stdoutRaw", data => process.stdout.write(data));
 | 
			
		||||
    serverManeger.serverActions.once("serverStarted", () => serverManeger.serverProcess.writeStdin("stop"));
 | 
			
		||||
    return new Promise((done, reject) => serverManeger.serverProcess.on("close", ({code}) => code === 0?done():reject(new Error("Exit another code "+code))));
 | 
			
		||||
    serverManeger.on("log_stdout", data => process.stdout.write(data));
 | 
			
		||||
    serverManeger.once("serverStarted", () => serverManeger.stopServer());
 | 
			
		||||
    return new Promise((done, reject) => serverManeger.on("exit", ({code}) => code === 0?done():reject(new Error("Exit another code "+code))));
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								tests/pocketmine.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tests/pocketmine.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import { installServer, startServer } from "../src/pocketmine";
 | 
			
		||||
 | 
			
		||||
describe("Pocketmine", () => {
 | 
			
		||||
  it("Install and Start", async function() {
 | 
			
		||||
    this.timeout(1000*60*60*15);
 | 
			
		||||
    await installServer("latest");
 | 
			
		||||
    const serverManeger = await startServer();
 | 
			
		||||
    serverManeger.on("log_stdout", console.log);
 | 
			
		||||
    serverManeger.on("log_stdout", data => {
 | 
			
		||||
      if(/set-up.*wizard/.test(data)) {
 | 
			
		||||
        serverManeger.runCommand("eng");
 | 
			
		||||
        serverManeger.runCommand("y");
 | 
			
		||||
        serverManeger.runCommand("y");
 | 
			
		||||
        serverManeger.runCommand("");
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    serverManeger.on("serverStarted", () => serverManeger.stopServer());
 | 
			
		||||
    return new Promise((done, reject) => serverManeger.on("exit", ({code}) => code === 0?done():reject(new Error("Exit another code "+code))));
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
		Reference in New Issue
	
	Block a user