Rewrite in typescrypt #327
@ -1,5 +1,3 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
.git/
|
.git/
|
||||||
*.log
|
dist/
|
||||||
Test
|
|
||||||
test
|
|
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"commonjs": true,
|
|
||||||
"es2021": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"bds_log_string": "writable",
|
|
||||||
"bds_server_string": "writable",
|
|
||||||
"external_ip": "writable"
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 12,
|
|
||||||
"sourceType": "module",
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"quotes": [
|
|
||||||
"error",
|
|
||||||
"double"
|
|
||||||
],
|
|
||||||
"eqeqeq": 0,
|
|
||||||
"no-async-promise-executor": "off"
|
|
||||||
}
|
|
||||||
}
|
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
|||||||
* text=lf eol=lf
|
|
||||||
*.sh text=lf eol=lf
|
|
15
.gitignore
vendored
15
.gitignore
vendored
@ -1,14 +1,5 @@
|
|||||||
# Log
|
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
# Node
|
|
||||||
node_modules/
|
node_modules/
|
||||||
.dccache
|
dist/
|
||||||
docs/
|
src/**/*.d.ts
|
||||||
the-bds-maneger-core-*.tgz
|
src/**/*.d.js
|
||||||
|
|
||||||
# **
|
|
||||||
.husky
|
|
||||||
Servers
|
|
||||||
.Build/Releases.json
|
|
||||||
esm/
|
|
32
.npmignore
32
.npmignore
@ -1,31 +1 @@
|
|||||||
# Log
|
!dist/
|
||||||
*.log
|
|
||||||
|
|
||||||
# Develop files
|
|
||||||
.devcontainer/
|
|
||||||
.vscode/
|
|
||||||
.Build/
|
|
||||||
|
|
||||||
# Linters
|
|
||||||
.eslint*
|
|
||||||
|
|
||||||
# test files
|
|
||||||
*.test
|
|
||||||
*test*.*js
|
|
||||||
*Test*.*js
|
|
||||||
test/
|
|
||||||
Test/
|
|
||||||
|
|
||||||
# Git
|
|
||||||
git*
|
|
||||||
.git*
|
|
||||||
|
|
||||||
# Docker
|
|
||||||
.docker*
|
|
||||||
Docker*
|
|
||||||
|
|
||||||
# Npm
|
|
||||||
the-bds-maneger-core*.tgz
|
|
||||||
|
|
||||||
# External Packages
|
|
||||||
packages/**/*
|
|
2815
package-lock.json
generated
2815
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -7,12 +7,15 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"description": "A very simple way to manage Minecraft servers",
|
"description": "A very simple way to manage Minecraft servers",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
"types": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
"require": "./dist/src/index.js",
|
"require": "./dist/src/index.js",
|
||||||
"import": "./dist/esm/index.js"
|
"import": "./dist/esm/index.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"build": "run-s build:*",
|
||||||
|
"build:cjs": "tsc --module commonjs --outDir dist/cjs",
|
||||||
|
"build:esm": "tsc --module es2020 --outDir dist/esm"
|
||||||
},
|
},
|
||||||
"nodemonConfig": {
|
"nodemonConfig": {
|
||||||
"ignore": [
|
"ignore": [
|
||||||
@ -60,10 +63,15 @@
|
|||||||
"android"
|
"android"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@the-bds-maneger/server_versions": "^1.1.0",
|
"adm-zip": "^0.5.9",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"typescript": "^4.6.2"
|
"typescript": "^4.6.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/adm-zip": "^0.4.34",
|
||||||
|
"@types/node": "^17.0.22",
|
||||||
|
"npm-run-all": "^4.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
87
src/HttpRequests.ts
Normal file
87
src/HttpRequests.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
type githubRelease = {
|
||||||
|
url: string;
|
||||||
|
assets_url: string;
|
||||||
|
upload_url: string;
|
||||||
|
html_url: string;
|
||||||
|
id: number;
|
||||||
|
tarball_url: string;
|
||||||
|
zipball_url: string;
|
||||||
|
body: string;
|
||||||
|
author: {
|
||||||
|
login: string;
|
||||||
|
id: number;
|
||||||
|
node_id: string;
|
||||||
|
avatar_url: string;
|
||||||
|
gravatar_id: string;
|
||||||
|
url: string;
|
||||||
|
html_url: string;
|
||||||
|
followers_url: string;
|
||||||
|
following_url: string;
|
||||||
|
gists_url: string;
|
||||||
|
starred_url: string;
|
||||||
|
subscriptions_url: string;
|
||||||
|
organizations_url: string;
|
||||||
|
repos_url: string;
|
||||||
|
events_url: string;
|
||||||
|
received_events_url: string;
|
||||||
|
type: string;
|
||||||
|
site_admin: boolean;
|
||||||
|
};
|
||||||
|
node_id: string;
|
||||||
|
tag_name: string;
|
||||||
|
target_commitish: string;
|
||||||
|
name: string;
|
||||||
|
draft: boolean;
|
||||||
|
prerelease: boolean;
|
||||||
|
created_at: string;
|
||||||
|
published_at: string;
|
||||||
|
assets: Array<{
|
||||||
|
url: string;
|
||||||
|
id: number;
|
||||||
|
node_id: string;
|
||||||
|
name: string;
|
||||||
|
label: string;
|
||||||
|
content_type: string;
|
||||||
|
state: string;
|
||||||
|
size: number;
|
||||||
|
download_count: number;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
browser_download_url: string;
|
||||||
|
uploader: {
|
||||||
|
login: string;
|
||||||
|
id: number;
|
||||||
|
node_id: string;
|
||||||
|
avatar_url: string;
|
||||||
|
gravatar_id: string;
|
||||||
|
url: string;
|
||||||
|
html_url: string;
|
||||||
|
followers_url: string;
|
||||||
|
following_url: string;
|
||||||
|
gists_url: string;
|
||||||
|
starred_url: string;
|
||||||
|
subscriptions_url: string;
|
||||||
|
organizations_url: string;
|
||||||
|
repos_url: string;
|
||||||
|
events_url: string;
|
||||||
|
received_events_url: string;
|
||||||
|
type: string;
|
||||||
|
site_admin: boolean;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getBuffer(url: string, headers: {[d: string]: any} = {}): Promise<Buffer> {
|
||||||
|
const dataReponse = await axios.get(url, {
|
||||||
|
headers: (headers||{}),
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
});
|
||||||
|
return Buffer.from(dataReponse.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getGithubRelease(Username: string, Repo: string): Promise<Array<githubRelease>> {
|
||||||
|
const data = await getBuffer(`https://api.github.com/repos/${Username}/${Repo}/releases`);
|
||||||
|
return JSON.parse(data.toString("utf8"));
|
||||||
|
}
|
@ -1,6 +1,64 @@
|
|||||||
import BdsManegerVersions from "@the-bds-maneger/server_versions/src/cjs/index";
|
import path from "path";
|
||||||
import axios from "axios";
|
import fs from "fs";
|
||||||
|
import os from "os";
|
||||||
|
import adm_zip from "adm-zip";
|
||||||
|
import { getBuffer, getGithubRelease } from "./HttpRequests";
|
||||||
|
|
||||||
async function DownloadServer(Version: string|boolean, Platform: "bedrock"|"java"|"pocketmine"|"spigot"|"dragonfly") {
|
type getVersionsType = {
|
||||||
if (Platform === "bedrock") {}
|
latest: {
|
||||||
|
[d: string]: string|undefined
|
||||||
|
};
|
||||||
|
platform: Array<{
|
||||||
|
name: "pocketmine"|"java"|"bedrock"|"dragonfly"|"spigot";
|
||||||
|
version: string;
|
||||||
|
Date: string;
|
||||||
|
data: string | {[platform: string]: {[arch: string]: string;};};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getVersions(): Promise<getVersionsType> {
|
||||||
|
return JSON.parse((await getBuffer("https://raw.githubusercontent.com/The-Bds-Maneger/ServerVersions/main/src/Versions.json")).toString("utf8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function InstallPHP(PathToInstall: string) {
|
||||||
|
const Release = (await getGithubRelease("The-Bds-Maneger", "PocketMinePHPAutoBinBuilds"))[0].assets.find(asset => RegExp(process.platform).test(asset.name) && RegExp(os.arch()).test(asset.name));
|
||||||
|
if (!Release) throw new Error("No file found for this Platform and Arch");
|
||||||
|
const PHPZip = new adm_zip(await getBuffer(Release.browser_download_url));
|
||||||
|
if (fs.existsSync(path.resolve(PathToInstall, "bin"))) await fs.promises.rmdir(path.resolve(PathToInstall, "bin"), {recursive: true});
|
||||||
|
PHPZip.extractAllTo(PathToInstall, true);
|
||||||
|
return Release;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DownloadServer(Platform: "bedrock"|"java"|"pocketmine"|"spigot"|"dragonfly", Version: string|boolean) {
|
||||||
|
const ServerPath = path.resolve(process.env.SERVERPATH||path.join(os.homedir(), "bds_core"));
|
||||||
|
const versions = await getVersions()
|
||||||
|
const info = versions.platform.filter(v => v.name === Platform).find(v => v.version === (typeof Version === "boolean"?versions.latest[Platform]:Version));
|
||||||
|
if (Platform === "bedrock") {
|
||||||
|
const BedrockPath = path.resolve(ServerPath, "bedrock");
|
||||||
|
if (!(await fs.existsSync(BedrockPath))) fs.mkdirSync(BedrockPath, {recursive: true});
|
||||||
|
const BedrockZip = new adm_zip(await getBuffer(info.data[process.platform][process.arch]));
|
||||||
|
BedrockZip.extractAllTo(BedrockPath, true);
|
||||||
|
} else if (Platform === "java") {
|
||||||
|
const JavaPath = path.resolve(ServerPath, "java");
|
||||||
|
if (!(await fs.existsSync(JavaPath))) fs.mkdirSync(JavaPath, {recursive: true});
|
||||||
|
await fs.promises.writeFile(path.resolve(JavaPath, "Server.jar"), await getBuffer(String(info.data)));
|
||||||
|
} else if (Platform === "spigot") {
|
||||||
|
const SpigotPath = path.resolve(ServerPath, "spigot");
|
||||||
|
if (!(await fs.existsSync(SpigotPath))) fs.mkdirSync(SpigotPath, {recursive: true});
|
||||||
|
await fs.promises.writeFile(path.resolve(SpigotPath, "Spigot.jar"), await getBuffer(String(info.data)));
|
||||||
|
} else if (Platform === "pocketmine") {
|
||||||
|
const PocketminePath = path.resolve(ServerPath, "pocketmine");
|
||||||
|
if (!(await fs.existsSync(PocketminePath))) fs.mkdirSync(PocketminePath, {recursive: true});
|
||||||
|
await InstallPHP(PocketminePath);
|
||||||
|
await fs.promises.writeFile(path.resolve(PocketminePath, "PocketMine.phar"), await getBuffer(String(info.data)));
|
||||||
|
} else if (Platform === "dragonfly") {
|
||||||
|
const DragonflyPath = path.resolve(ServerPath, "dragonfly");
|
||||||
|
if (!(await fs.existsSync(DragonflyPath))) fs.mkdirSync(DragonflyPath, {recursive: true});
|
||||||
|
await fs.promises.writeFile(path.resolve(DragonflyPath, "Dragonfly"+(process.platform === "win32"?".exe":"")), await getBuffer(String(info.data)));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
Version: info.version,
|
||||||
|
Date: new Date(info.Date),
|
||||||
|
url: (typeof info.data === "string"? info.data : info.data[process.platform][process.arch])
|
||||||
|
};
|
||||||
}
|
}
|
90
src/server.ts
Normal file
90
src/server.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import path from "path";
|
||||||
|
import os from "os";
|
||||||
|
import crypto from "crypto";
|
||||||
|
import child_process from "child_process";
|
||||||
|
|
||||||
|
type Session = {
|
||||||
|
startDate: Date;
|
||||||
|
on: (from: "stdout"|"stderr", callback: (data: string) => void) => void;
|
||||||
|
exit: (callback: (code: number, signal: string) => void) => void;
|
||||||
|
commands: {
|
||||||
|
tpPlayer: (username: string, x: number, y: number, z: number) => void;
|
||||||
|
execCommand: (command: string) => void;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Sessions: {[Session: string]: Session} = {};
|
||||||
|
export async function getSessions() {return Sessions;}
|
||||||
|
|
||||||
|
export function Start(Platform: "bedrock"|"java"|"pocketmine"|"spigot"|"dragonfly"): Session {
|
||||||
|
const ServerPath = path.resolve(process.env.SERVERPATH||path.join(os.homedir(), "bds_core"));
|
||||||
|
const Process: {command: string; args: Array<string>; env: {[env: string]: string}; cwd: string;} = {
|
||||||
|
command: "",
|
||||||
|
args: [],
|
||||||
|
env: {...process.env},
|
||||||
|
cwd: process.cwd()
|
||||||
|
};
|
||||||
|
if (Platform === "bedrock") {
|
||||||
|
if (process.platform === "darwin") throw new Error("Run Docker image");
|
||||||
|
Process.command = path.resolve(ServerPath, "bedrock/bedrock"+(process.platform === "win32"?".exe":""));
|
||||||
|
if (process.platform !== "win32") {
|
||||||
|
child_process.execFileSync("chmod", ["a+x", Process.command]);
|
||||||
|
Process.env.LD_LIBRARY_PATH = path.resolve(ServerPath, "bedrock");
|
||||||
|
if (process.arch !== "x64") {
|
||||||
|
console.warn("Minecraft bedrock start with emulated x64 architecture");
|
||||||
|
Process.args.push(Process.command);
|
||||||
|
Process.command = "qemu-x86_64-static";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (Platform === "java"||Platform === "spigot") {
|
||||||
|
Process.command = "java";
|
||||||
|
Process.args.push("-jar");
|
||||||
|
if (Platform === "java") Process.args.push(path.resolve(ServerPath, "java/Server.jar"));
|
||||||
|
else Process.args.push(path.resolve(ServerPath, "spigot/Spigot.jar"));
|
||||||
|
} else if (Platform === "pocketmine") {
|
||||||
|
if (process.platform === "win32") Process.command = path.resolve(ServerPath, "pocketmine/bins/php/php");
|
||||||
|
else Process.command = path.resolve(ServerPath, "pocketmine/bins/php7/bin/php");
|
||||||
|
Process.args.push(path.resolve(ServerPath, "pocketmine/PocketMine-MP.phar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Server
|
||||||
|
const ServerProcess = child_process.execFile(Process.command, Process.args, {env: Process.env, cwd: Process.cwd, maxBuffer: Infinity});
|
||||||
|
const StartDate = new Date();
|
||||||
|
|
||||||
|
// Log callback
|
||||||
|
const onLog = (from: "stdout"|"stderr", callback: (data: string) => void) => {
|
||||||
|
ServerProcess[from].on("data", callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit callback
|
||||||
|
const onExit = (callback: (code: number, signal: string) => void): void => {
|
||||||
|
ServerProcess.on("exit", callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run Command
|
||||||
|
const execCommand = (...command) => {
|
||||||
|
ServerProcess.stdin.write(command.join(" ")+"\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Teleport player
|
||||||
|
const tpPlayer = (username: string, x: number, y: number, z: number) => {
|
||||||
|
execCommand("tp", username, x, y, z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return Session
|
||||||
|
const Seesion = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
startDate: StartDate,
|
||||||
|
on: onLog,
|
||||||
|
exit: onExit,
|
||||||
|
commands: {
|
||||||
|
execCommand: execCommand,
|
||||||
|
tpPlayer: tpPlayer,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Sessions[Seesion.id] = Seesion;
|
||||||
|
return Seesion;
|
||||||
|
}
|
Reference in New Issue
Block a user