Rewrite in typescrypt #327

Merged
Sirherobrine23 merged 13 commits from re_Typescript into main 2022-03-28 21:43:14 +00:00
58 changed files with 3563 additions and 18600 deletions

View File

@ -1,13 +0,0 @@
module.exports = {
input: ["src"],
output: "esm",
forceDirectory: null,
modules: [],
extension: {
use: "js",
ignore: [],
},
addModuleEntry: false,
addPackageJson: false,
filesWithShebang: [],
};

View File

@ -1,5 +1,11 @@
node_modules/ /node_modules/
.git/ /.git/
*.log /.github/
Test /.vscode/
test /.devcontainer/
/*.md
.*ignore
.gitpod.y*ml
dist/
Dockerfile
docker-compose.y*ml

View File

@ -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
View File

@ -1,2 +0,0 @@
* text=lf eol=lf
*.sh text=lf eol=lf

17
.github/stale.yml vendored
View File

@ -1,17 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -1,63 +0,0 @@
name: Docker And Node Test
on:
pull_request:
branches:
- main
jobs:
Node:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 15.x
- 16.x
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3.0.0
with:
node-version: ${{ matrix.node-version }}
- name: Edit Version to next release
if: github.event_name != 'release'
shell: node {0}
run: |
const fs = require("fs");
const JsonPackage = JSON.parse(fs.readFileSync(process.cwd()+"/package.json", "utf8"));
const run_ID = "${{ github.run_id }}";
JsonPackage.version = `${run_ID.slice(0, 2)}.${run_ID.slice(3, 6)}.${run_ID.slice(7, 11)}`;
fs.writeFileSync(process.cwd()+"/package.json", JSON.stringify(JsonPackage, null, 2));
console.log("New Version to Package:", JsonPackage.version);
- name: Install node depedencies
run: npm install --no-save
- name: Install node depedencies
run: npm run esm_module
- name: Run test
run: npm test
Docker-Build:
needs: [Node]
runs-on: ubuntu-latest
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: checkout
uses: actions/checkout@v3
- name: Build Docker Image (Multiarch)
id: DockerArch
run: docker build --tag bdscore_pull:latest --file Dockerfile .
# Run docker image with dev test
- name: Run Docker Image (Multiarch)
run: docker run --rm -i -e PULL_REQUEST="true" bdscore_pull:latest

43
.github/workflows/code_analyzer.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Code Analyze
on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
- cron: "26 8 * * 1"
jobs:
snyk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --sarif-file-output=snyk.sarif
- name: Upload result to GitHub Code Scanning
continue-on-error: true
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: snyk.sarif
codeql:
name: CodeQL Analyze
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -0,0 +1,50 @@
name: Publish latest image
on:
push:
branches:
- main
paths:
- "docker-compose.yml"
- "package*.json"
- "Dockerfile"
- "README.md"
- "src/**/*"
- ".github/**/*"
env:
# DOCKERPLATFORM: "linux/amd64,linux/arm64"
DOCKERPLATFORM: "linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x"
DOCKERIMAGE: "ghcr.io/the-bds-maneger/core"
jobs:
latestDeploy:
runs-on: ubuntu-latest
name: Publish latest
steps:
- uses: actions/checkout@v2.4.0
with:
submodules: true
- name: Setup QEMU to Docker
uses: docker/setup-qemu-action@v1
- name: Setup Buildx
uses: docker/setup-buildx-action@v1
- name: Login into registry Github Packages
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push image
uses: docker/build-push-action@v2
with:
context: .
push: true
target: bdscore
tags: ${{ env.DOCKERIMAGE }}:latest
platforms: ${{ env.DOCKERPLATFORM }}
cache-from: type=gha,scope=${{ github.ref }}_${{ hashFiles('**/package-lock.json') }}
cache-to: type=gha,mode=max,scope=${{ github.ref }}_${{ hashFiles('**/package-lock.json') }}

View File

@ -0,0 +1,43 @@
name: Publish release image
on:
release:
types:
- created
env:
# DOCKERPLATFORM: "linux/amd64,linux/arm64"
DOCKERPLATFORM: "linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x"
DOCKERIMAGE: "ghcr.io/the-bds-maneger/core"
jobs:
latestDeploy:
runs-on: ubuntu-latest
name: Publish latest
steps:
- uses: actions/checkout@v2.4.0
with:
submodules: true
- name: Setup QEMU to Docker
uses: docker/setup-qemu-action@v1
- name: Setup Buildx
uses: docker/setup-buildx-action@v1
- name: Login into registry Github Packages
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push image
uses: docker/build-push-action@v2
with:
context: .
push: true
target: bdscore
tags: ${{ env.DOCKERIMAGE }}:latest
platforms: ${{ env.DOCKERPLATFORM }}
cache-from: type=gha,scope=${{ github.ref }}_${{ hashFiles('**/package-lock.json') }}
cache-to: type=gha,mode=max,scope=${{ github.ref }}_${{ hashFiles('**/package-lock.json') }}

73
.github/workflows/publish_npm_main.yml vendored Normal file
View File

@ -0,0 +1,73 @@
name: Publish dev/next module release
on:
push:
branches:
- main
paths:
- "docker-compose.yml"
- "package*.json"
- "Dockerfile"
- "README.md"
- "src/**/*"
- ".github/**/*"
env:
# DOCKERPLATFORM: "linux/amd64,linux/arm64"
DOCKERPLATFORM: "linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x"
DOCKERIMAGE: "ghcr.io/the-bds-maneger/core"
jobs:
latestDeploy:
runs-on: ubuntu-latest
name: Publish npm module
strategy:
matrix:
npm_registry:
- "Github"
- "NPM"
steps:
- uses: actions/checkout@v2.4.0
with:
submodules: true
- name: Setup Node.js (NPM Packages)
if: matrix.npm_registry == 'NPM'
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
registry-url: https://registry.npmjs.org/
- name: Setup Node.js (Github Packages)
if: matrix.npm_registry == 'Github'
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
registry-url: https://npm.pkg.github.com/
- name: Edit Version to next release
shell: node {0}
run: |
const fs = require("fs");
const JsonPackage = JSON.parse(fs.readFileSync(process.cwd()+"/package.json", "utf8"));
const run_ID = "${{ github.run_id }}";
JsonPackage.version = `${run_ID.slice(0, 2)}.${run_ID.slice(3, 6)}.${run_ID.slice(7, 11)}`;
fs.writeFileSync(process.cwd()+"/package.json", JSON.stringify(JsonPackage, null, 2));
console.log("New Version to Package:", JsonPackage.version);
- name: Install node depencies
run: npm install -d
- name: Build typescript to CJS and ESM
run: npm run build
- name: Publish Package
run: |
set -x
if [[ "${{ matrix.npm_registry }}" == "Github" ]];then
echo "Publish to Github Packages"
export NODE_AUTH_TOKEN="${{ secrets.GITHUB_TOKEN }}"
else
echo "Publish to NPM Registry"
export NODE_AUTH_TOKEN="${{ secrets.NPM_ORG_TOKEN }}"
fi
npm publish --tag next

View File

@ -0,0 +1,85 @@
name: Publish release module release
on:
release:
types:
- created
env:
# DOCKERPLATFORM: "linux/amd64,linux/arm64"
DOCKERPLATFORM: "linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x"
DOCKERIMAGE: "ghcr.io/the-bds-maneger/core"
jobs:
latestDeploy:
runs-on: ubuntu-latest
name: Publish npm module
strategy:
matrix:
npm_registry:
- "Github"
- "NPM"
steps:
- uses: actions/checkout@v2.4.0
with:
submodules: true
- name: Setup Node.js (NPM Packages)
if: matrix.npm_registry == 'NPM'
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
registry-url: https://registry.npmjs.org/
- name: Setup Node.js (Github Packages)
if: matrix.npm_registry == 'Github'
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
registry-url: https://npm.pkg.github.com/
- name: Remove Dev Version
shell: node {0}
run: |
const child_process = require("child_process");
const fs = require("fs");
const path = require("path");
const cli_color = require("cli-color");
(async function() {
global.fetch = (await import("node-fetch")).default;
fetch("https://registry.npmjs.org/@the-bds-maneger/core").then(res => res.json()).then(data => {
data.versions = Object.getOwnPropertyNames(data.versions).filter(version => /[0-9]+\.[0-9][0-9][0-9]/.test(version) && version !== data["dist-tags"].dev && version !== data["dist-tags"].latest)
fs.writeFileSync(path.resolve(__dirname, "Releases.json"), JSON.stringify(data, null, 2));
const Package = require(process.cwd()+"/package.json");
data.versions.map(version => {
const cmd = `npm unpublish ${Package.name}@${version}`;
console.log(cli_color.yellow(cmd));
try {
child_process.execSync(cmd).toString()
console.log(cli_color.green(`Sucess to remove ${Package.name}@${version}`, "\n"));
return cmd;
} catch (e) {
console.log(cli_color.red(`Failed to remove package: ${Package.name}@${version}`), "\n");
return version;
}
});
fs.writeFileSync(path.resolve(__dirname, "Releases.json"), JSON.stringify(data, null, 2));
});
})();
- name: Install node depencies
run: npm install -d
- name: Build typescript to CJS and ESM
run: npm run build
- name: Publish Package
run: |
set -x
if [[ "${{ matrix.npm_registry }}" == "Github" ]];then
echo "Publish to Github Packages"
export NODE_AUTH_TOKEN="${{ secrets.GITHUB_TOKEN }}"
else
echo "Publish to NPM Registry"
export NODE_AUTH_TOKEN="${{ secrets.NPM_ORG_TOKEN }}"
fi
npm publish

34
.github/workflows/pull_request.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Test module
on:
pull_request:
env:
# DOCKERPLATFORM: "linux/amd64,linux/arm64"
DOCKERPLATFORM: "linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x"
DOCKERIMAGE: "ghcr.io/the-bds-maneger/core"
jobs:
latestDeploy:
runs-on: ubuntu-latest
name: Publish npm module
strategy:
matrix:
node_version:
- "15"
- "16"
- "17"
steps:
- uses: actions/checkout@v2.4.0
with:
submodules: true
- name: Setup Node.js (Github Packages)
uses: actions/setup-node@v3.0.0
with:
node-version: "${{ matrix.node_version }}.x"
- name: Install node depencies
run: npm install -d
- name: Build typescript to CJS and ESM
run: npm run build

View File

@ -1,214 +0,0 @@
name: "Publish Packages"
on:
push:
branches:
- main
release:
types:
- released
jobs:
CodeQL:
name: Analyze
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: "javascript"
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
test:
strategy:
matrix:
node_version:
- 16.x
- 17.x
os:
- Ubuntu-latest
- windows-latest
# - macos-latest
name: "Test System: ${{ matrix.os }}, Node Version: ${{ matrix.node_version }}"
runs-on: "${{ matrix.os }}"
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Node.JS and NPM
uses: actions/setup-node@v3.0.0
with:
registry-url: https://registry.npmjs.org/
node-version: ${{ matrix.node_version }}
- name: Install Node Dependencies
run: npm ci
- name: Test
run: npm test
npm:
runs-on: ubuntu-latest
needs: [test]
strategy:
matrix:
npm_registry:
- "Github"
- "NPM"
name: Npm Publish (${{ matrix.npm_registry }})
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Node.js (NPM Packages)
if: matrix.npm_registry == 'NPM'
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
registry-url: https://registry.npmjs.org/
- name: Setup Node.js (Github Packages)
if: matrix.npm_registry == 'Github'
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
registry-url: https://npm.pkg.github.com/
- name: Edit Version to next release
if: github.event_name != 'release'
shell: node {0}
run: |
const fs = require("fs");
const JsonPackage = JSON.parse(fs.readFileSync(process.cwd()+"/package.json", "utf8"));
const run_ID = "${{ github.run_id }}";
JsonPackage.version = `${run_ID.slice(0, 2)}.${run_ID.slice(3, 6)}.${run_ID.slice(7, 11)}`;
fs.writeFileSync(process.cwd()+"/package.json", JSON.stringify(JsonPackage, null, 2));
console.log("New Version to Package:", JsonPackage.version);
- name: Install Node Dependencies
run: npm install -d
- name: ESM Modules
run: npm run esm_module
- name: Remove Dev Version
if: github.event_name == 'release'
shell: node {0}
run: |
const child_process = require("child_process");
const fs = require("fs");
const path = require("path");
const cli_color = require("cli-color");
(async function() {
global.fetch = (await import("node-fetch")).default;
fetch("https://registry.npmjs.org/@the-bds-maneger/core").then(res => res.json()).then(data => {
data.versions = Object.getOwnPropertyNames(data.versions).filter(version => /[0-9]+\.[0-9][0-9][0-9]/.test(version) && version !== data["dist-tags"].dev && version !== data["dist-tags"].latest)
fs.writeFileSync(path.resolve(__dirname, "Releases.json"), JSON.stringify(data, null, 2));
const Package = require(process.cwd()+"/package.json");
data.versions.map(version => {
const cmd = `npm unpublish ${Package.name}@${version}`;
console.log(cli_color.yellow(cmd));
try {
child_process.execSync(cmd).toString()
console.log(cli_color.green(`Sucess to remove ${Package.name}@${version}`, "\n"));
return cmd;
} catch (e) {
console.log(cli_color.red(`Failed to remove package: ${Package.name}@${version}`), "\n");
return version;
}
});
fs.writeFileSync(path.resolve(__dirname, "Releases.json"), JSON.stringify(data, null, 2));
});
})();
- name: Publish Package
run: |
set -x
if [[ "${{ matrix.npm_registry }}" == "Github" ]];then
echo "Publish to Github Packages"
export NODE_AUTH_TOKEN="${{ secrets.GITHUB_TOKEN }}"
else
echo "Publish to NPM Registry"
export NODE_AUTH_TOKEN="${{ secrets.NPM_ORG_TOKEN }}"
fi
if [[ "${{ github.event_name }}" == "release" ]];then
npm publish
else
npm publish --tag next
fi
docker:
runs-on: ubuntu-latest
name: Publish Docker Image
needs: [test]
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.JS and NPM
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
registry-url: https://registry.npmjs.org/
- name: Checkout Code
uses: actions/checkout@v3
- name: Edit Version to next release
if: github.event_name != 'release'
shell: node {0}
run: |
const fs = require("fs");
const JsonPackage = JSON.parse(fs.readFileSync(process.cwd()+"/package.json", "utf8"));
const run_ID = "${{ github.run_id }}";
JsonPackage.version = `${run_ID.slice(0, 2)}.${run_ID.slice(3, 6)}.${run_ID.slice(7, 11)}`;
fs.writeFileSync(process.cwd()+"/package.json", JSON.stringify(JsonPackage, null, 2));
console.log("New Version to Package:", JsonPackage.version)
- run: npm ci
- name: Get Version and Set in Env
shell: node {0}
run: |
const fs = require("fs");
const { version } = require(process.cwd()+"/package.json");
console.log(version);
fs.appendFileSync(process.env.GITHUB_ENV, `CoreVersion=${version}`)
- name: Build Bds Maneger Core (Release)
uses: docker/build-push-action@v2
if: github.event_name == 'release'
with:
push: true
context: .
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: |
ghcr.io/the-bds-maneger/core:latest
ghcr.io/the-bds-maneger/core:${{ env.CoreVersion }}
- name: Build Bds Maneger Core (Main)
uses: docker/build-push-action@v2
if: github.event_name != 'release'
with:
context: .
push: true
cache-from: type=registry,ref=ghcr.io/the-bds-maneger/core:nightly
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: ghcr.io/the-bds-maneger/core:nightly

15
.gitignore vendored
View File

@ -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/

View File

@ -1,17 +1,8 @@
# This configuration file was automatically generated by Gitpod.
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
# and commit this file to your remote git repository to share the goodness with others.
# experimentalNetwork: true
tasks: tasks:
- init: npm install - init: npm install
command: npm run start
ports: ports:
- port: 3000 - port: 3000
visibility: public visibility: public
onOpen: open-browser onOpen: ignore
- port: 19132 - port: 19132
visibility: public visibility: public
vscode:
extensions:
- "github.copilot"

View File

@ -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/**/*

View File

@ -1,63 +0,0 @@
process.env.ShowLoadTime = true;
const BdsCore = require("../src/index");
const TestInstrucation = [
async function() {
console.log("Change Platform to java");
await BdsCore.BdsSettings.ChangePlatform("java");
},
async function() {
console.log("Change Platform to Bedrock");
await BdsCore.BdsSettings.ChangePlatform("bedrock");
},
async function() {
console.log("Get Basic system information");
console.log("Arch:", BdsCore.BdsSystemInfo.arch);
return await BdsCore.BdsSystemInfo.CheckSystemAsync();
},
async function() {
console.log("Download Server to Current Platform");
return await BdsCore.BdsDownload.DownloadServer("latest");
},
async function() {
console.log("Get Bds Configs");
const { BdsDir, CurrentPlatorm, GetBdsConfig, GetPaths, UpdateServerVersion } = BdsCore.BdsSettings;
console.log("Bds Dir:", BdsDir);
console.log("Current Platform:", CurrentPlatorm());
console.log("Get Bds Config:", GetBdsConfig());
console.log("Get Paths:", GetPaths("all"));
console.log("Update Server Version:", UpdateServerVersion("1.0.0"));
},
() => {
const Server = BdsCore.BdsManegerServer.StartServer();
Server.on("log", data => process.stdout.write(data));
return Server;
},
async function(Server) {
console.log("Stoping Server");
const Code = await Server.stop();
if (Code === 0) return Code;
else throw new Error("Server Stop Error");
},
async function() {
console.log("Get Server Config");
const ServerConfig = await BdsCore.BdsServerSettings.get_config();
return ServerConfig;
}
];
(async () => {
let OldReturn;
for (const Action of TestInstrucation) {
try {
OldReturn = await Action(OldReturn);
console.log("Data:", OldReturn);
console.log("Result: Success\n");
} catch (err) {
console.error(err.stack||err);
console.log("Result: Failed\n");
process.exit(1);
}
}
process.exit(0);
})()

View File

@ -1,3 +1,4 @@
{ {
"files.eol": "\n" "files.eol": "\n",
"editor.tabSize": 2
} }

View File

@ -1,87 +1,98 @@
FROM debian:latest AS core FROM debian:latest AS nodedowload
ENV DEBIAN_FRONTEND="noninteractive" DOCKER_IMAGE="true" ENV DEBIAN_FRONTEND="noninteractive"
RUN apt update && apt -y install wget tar lsb-release
LABEL name="Bds Maneger Docker" # Install latest docker image
RUN mkdir /tmp/Node && NODEURL=""; NODEVERSION=$(wget -qO- https://api.github.com/repos/nodejs/node/releases | grep tag_name | cut -d '"' -f 4 | sort -V | tail -n 1) && \
case $(uname -m) in \
x86_64 ) NODEURL="https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-x64.tar.gz";; \
aarch64 ) NODEURL="https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-arm64.tar.gz";; \
armv7l ) NODEURL="https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-armv7l.tar.gz";; \
ppc64le ) NODEURL="https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-ppc64le.tar.gz";; \
s390x ) NODEURL="https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-s390x.tar.gz";; \
*) echo "Unsupported architecture ($(uname -m))"; exit 1;; \
esac && \
echo "Node bin Url: ${NODEURL}"; wget -q "${NODEURL}" -O /tmp/node.tar.gz && \
tar xfz /tmp/node.tar.gz -C /tmp/Node && \
mkdir /tmp/nodebin && cp -rp /tmp/Node/*/* /tmp/nodebin && ls /tmp/nodebin && rm -rfv /tmp/nodebin/LICENSE /tmp/nodebin/*.md
FROM debian:latest AS libries
ENV DEBIAN_FRONTEND="noninteractive"
RUN apt update && apt -y install wget unzip zip
RUN mkdir -p /libries; mkdir /libries/lib64; \
if [ "$(uname -m)" != "x86_64" ];then \
apt install -y qemu-user-static; \
wget -q "https://github.com/The-Bds-Maneger/external_files/raw/main/Linux/libs_amd64.zip" -O /tmp/libries.zip; \
unzip -o /tmp/libries.zip -d /libries; \
rm -rfv /tmp/libries.zip; \
fi
FROM debian:latest AS bdscore
LABEL org.opencontainers.image.title="Bds Maneger Docker" LABEL org.opencontainers.image.title="Bds Maneger Docker"
LABEL org.opencontainers.image.description="Start Minecraft Server with Docker containers and Auto Control Server wirh Bds Maneger Core." LABEL org.opencontainers.image.description="Start Minecraft Server with Docker containers and Auto Control Server wirh Bds Maneger Core."
LABEL org.opencontainers.image.vendor="Sirherobrine23" LABEL org.opencontainers.image.vendor="Sirherobrine23"
LABEL org.opencontainers.image.licenses="MIT" LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.source="https://github.com/The-Bds-Maneger/Bds-Maneger-Core.git" LABEL org.opencontainers.image.source="https://github.com/The-Bds-Maneger/Bds-Maneger-Core.git"
# Install Core Packages
RUN apt update && \
apt install -y curl wget unzip zip xz-utils tar procps
# Install external Libries to another architecture # Install external Libries to another architecture
ARG LibrieZip="https://github.com/The-Bds-Maneger/external_files/raw/main/Linux/libs_amd64.zip" COPY --from=libries /libries/ /
RUN \ # Install NodeJS and latest NPM
if [ "$(uname -m)" != "x86_64" ];then \ COPY --from=nodedowload /tmp/nodebin/ /usr
mkdir -p /lib64; \ RUN npm -g install npm@latest
apt install -y qemu-user-static; \
wget -q "${LibrieZip}" -O /tmp/libries.zip; \
unzip -o /tmp/libries.zip -d /; \
rm -rfv /tmp/libries.zip; \
fi
# Install external Libries to ARM64 # Install Core Packages
RUN apt install -y ca-certificates make build-essential procps lsb-release xdg-utils g++ libatomic1 libnss3 libatk-bridge2.0-0 gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxrandr2 libxrender1 libxss1 libxtst6 fonts-liberation libnss3 libgbm-dev ENV DEBIAN_FRONTEND="noninteractive"
RUN apt update && \
# Install Node.js apt install -y procps ca-certificates procps lsb-release xdg-utils g++ libatomic1 libnss3 \
RUN \ libatk-bridge2.0-0 gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
NODEVERSION=$(curl -sL https://api.github.com/repos/nodejs/node/releases | grep tag_name | cut -d '"' -f 4 | sort -V | tail -n 1) && \ libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 \
case $(uname -m) in \ libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \
x86_64 ) wget -q "https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-x64.tar.xz" -O /tmp/node.tar.xz;; \ libxcursor1 libxdamage1 libxext6 libxfixes3 libxrandr2 libxrender1 libxss1 libxtst6 fonts-liberation libnss3 libgbm-dev
aarch64 ) wget -q "https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-arm64.tar.xz" -O /tmp/node.tar.xz;; \
armv7l ) wget -q "https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-armv7l.tar.xz" -O /tmp/node.tar.xz;; \
ppc64el ) wget -q "https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-ppc64le.tar.xz" -O /tmp/node.tar.xz;; \
s390x ) wget -q "https://nodejs.org/download/release/$NODEVERSION/node-$NODEVERSION-linux-s390x.tar.xz" -O /tmp/node.tar.xz;; \
*) echo "Unsupported architecture"; exit 1;; \
esac && \
mkdir /tmp/Node && \
tar -xJf /tmp/node.tar.xz -C /tmp/Node && \
rm -rf /tmp/node.tar.xz && \
cp -rf /tmp/Node/*/* /usr && \
rm -rf /tmp/Node && \
npm -g install npm@latest
# Install openjdk # Install openjdk
RUN apt update && \ RUN apt update && \
case $(apt search openjdk) in \ JAVAVERSIONS="$(apt search openjdk|grep '/'|grep 'openjdk-'|sed 's|/| |g'|awk '{print $1}'|grep 'jre'|sed -e 's|-jre.*||g'|uniq)";\
*openjdk-15* ) apt install -y openjdk-15*;; \ case $JAVAVERSIONS in \
*openjdk-16* ) apt install -y openjdk-16*;; \ *17* ) apt install -y openjdk-17*;; \
*openjdk-17* ) apt install -y openjdk-17*;; \ *16* ) apt install -y openjdk-16*;; \
*) echo "Unsupported Java Version"; exit 1;; \ *) echo "Unsupported Java Version, avaibles"; echo "$JAVAVERSIONS";exit 0;; \
esac esac
# Create Volume to Storage Server And Config # Create Volume to Storage Server
VOLUME [ "/root/bds_core" ] VOLUME [ "/data" ]
# App Workspace
WORKDIR /app
ENTRYPOINT [ "node", "--trace-warnings", "/app/dist/cjs/bin/docker.js" ]
# Ports
EXPOSE 3000/tcp
EXPOSE 19132/udp
EXPOSE 19133/udp
EXPOSE 25565/tcp
EXPOSE 25566/tcp
# Default ENVs
ENV NODE_ENV="production"
ENV SERVER_PATH="/data/server"
ENV BACKUP_PATH="/data/backups"
ENV LOG_PATH="/data/logs"
ENV EXTRA_PATH="/data/extra"
# Server Settings
ENV DESCRIPTION="My Sample Server"
ENV WORLD_NAME="My Map"
ENV GAMEMODE="survival"
ENV DIFFICULTY="normal"
ENV MAXPLAYERS="5"
ENV REQUIRED_LOGIN="false"
ENV ALLOW_COMMADS="false"
# Bds Core Settings
ENV VERSION="latest"
ENV PLATFORM="bedrock"
# Node packages
COPY package*.json ./ COPY package*.json ./
RUN npm install RUN npm install --production --no-save
COPY ./ ./
# Set default ENVs to Bds Core RUN npm run build:cjs
ENV SERVER_VERSION="true" \
PLAYERS="5" \
WORLD_NAME="The Ultimate Server" \
DESCRIPTION="running Minecraft Server on Bds Maneger by Bds Manager Project" \
GAMEMODE="survival" \
DIFFICULTY="normal" \
ENABLE_COMMANDS="false" \
ACCOUNT="false" \
LEVEL_SEED="" \
SERVER="bedrock" \
SERVER_VERSION="latest" \
TelegramToken="" \
NODE_ENV="production"
# Bds Maneger Core required ports
EXPOSE 19132/udp 19133/udp 1932/tcp
# Copy Bds Maneger Core
WORKDIR /opt/backend_core_scripts/
# Install Core dependencies
ENTRYPOINT [ "sh", "-c", "node bin/BdsManeger.js start -ak -d ${SERVER_VERSION} -p ${SERVER} --players ${PLAYERS} --world-name ${WORLD_NAME} --description ${DESCRIPTION} --gamemode ${GAMEMODE} --difficulty ${DIFFICULTY} --level-seed ${LEVEL_SEED}" ]
COPY ./ ./

146
README.md
View File

@ -1,110 +1,100 @@
# Bds Maneger Core # Bds Maneger Core
Bds Maneger Core is a javascript core in Nodejs that manages several types of server seftware for Minecraft Bedrock and Java. Bds Maneger Core has integrated with a REST API with full integration with Bds Maneger Core in addition to CLI and One bot versions for the telegram. This is a small hub to manage various servers for Minecraft Bedrock and for Minecraft Java, such as installing, starting and keeping up to date with the latest version available.
Any contribution is welcome, but before a look at [CONTRIBUTING.md](CONTRIBUTING.md), [Bds Manager Core code of conduct](CODE_OF_CONDUCT.md) This module is fully compatible with ESM, CJS and Typescript.
## Requirements for Bds Maneger Core ## Requirements
### All This module requires some requirements to work:
* [Nodejs 15.6.0+](https://nodejs.org/en/download/current/) * NodeJS: `^15.x`.
* [OpenJDK 16+](https://www.oracle.com/java/technologies/javase-jdk16-downloads.html) * Java: `^8.0` or OpenJDK: `^16`.
### Windows 10+ ### For Windows Users
* [Microsoft Visual Studio C++ (The Bds Maneger Documentation)](<https://docs.bdsmaneger.com/docs/Bds Maneger core/WindowsFixDll/#windows-server>) Minecraft Bedrock needs Visual studio C++ if you are using Windows Server ([More information you can find on the Wiki](<https://github.com/The-Bds-Maneger/Bds-Maneger-Core/wiki/Server-Platforms#minecraft-bedrock-server-alpha>)).
## Documentation ## CLI
We have a separate repository for all Bds Maneger Project documentation, [link here from the main page](<https://docs.bdsmaneger.com/Bds Maneger core>), [Repository link](https://github.com/The-Bds-Maneger/Bds-Manager-Project-Documentation) This module also includes a simple CLI for managing servers. how:
## Badges 1. Download compatible server versions.
2. Update the server.
3. Start the server.
4. Backup Server.
[![Total alerts](https://img.shields.io/lgtm/alerts/g/Bds-Maneger/bds_maneger_api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Bds-Maneger/bds_maneger_api/alerts/) ## Install
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/Bds-Maneger/bds_maneger_api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Bds-Maneger/bds_maneger_api/context:javascript)
[![DeepScan grade](https://deepscan.io/api/teams/13683/projects/16691/branches/363172/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=13683&pid=16691&bid=363172)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d357bef9c4ba4198ab16be64a5adf051)](https://www.codacy.com/gh/The-Bds-Maneger/Bds-Maneger-Core/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=The-Bds-Maneger/Bds-Maneger-Core&amp;utm_campaign=Badge_Grade)
## Start Bds Maneger Core with npx To install CLI: `npm install -g @the-bds-maneger/core` (`Linux user Use sudo or root`).
### CLI To Install module: `npm install @the-bds-maneger/core`.
All options can be found in the bds maneger core documentation. Run withou install: `npx @the-bds-maneger/core`.
`npx @the-bds-maneger/core@latest -sk` ## Docker and Docker Compose
## Install Bds Maneger Core globally
The commands available after installation:
* bds_maneger
`npm i -g @the-bds-maneger/core@latest`
## Launch Bds Maneger Core with a docker image
### Docker Compose ### Docker Compose
[Docker Compose Install guide](https://docs.docker.com/compose/install/) [Docker Compose releases](<https://github.com/docker/compose/releases/latest>).
```yaml * MacOS and Windows docker users is already installed by default in Docker Desktop.
version: "2.1"
```yml
version: "3.9"
volumes:
server_storage:
services: services:
BdsCore: bdscore:
image: ghcr.io/the-bds-maneger/core:latest image: ghcr.io/the-bds-maneger/core:latest
container_name: BdsCore
restart: always
network_mode: host
environment:
DESCRIPTION: running Minecraft Bedrock Server on the docker by Bds Manager
WORLD_NAME: Bds Maneger Docker
GAMEMODE: survival
DIFFICULTY: normal
ACCOUNT: "false"
PLAYERS: 13
SERVER: bedrock
ENABLE_COMMANDS: "false"
volumes: volumes:
- ./BdsCore:/home/bds/bds_core - server_storage:/data
environment:
# Server Settings
DESCRIPTION: "My Sample Server"
WORLD_NAME: "My Map"
GAMEMODE: "survival"
DIFFICULTY: "normal"
MAXPLAYERS: "5"
REQUIRED_LOGIN: "false"
# Bds Core Settings
VERSION: "latest"
PLATFORM: "bedrock"
ports:
# Port to API
- 3000:3000/tcp
# Server Port to bedrock
- 19132:19132/udp
- 19133:19133/udp
# Server Port to java
- 25565:25565/tcp
- 25565:25565/udp
``` ```
### Windows ### Docker
```cmd create Docker volume: `docker volume create --driver local --name bds_server_storage`.
docker run --rm -d --name BdsManegerCore -v BdsCore:/home/bds/bds_core ^
--restart=always -p 19132:19132/udp -p 19133:19133/udp -p 1932:1932/tcp ^
-e DESCRIPTION="running Minecraft Bedrock Server on the docker by Bds Manager" ^
-e WORLD_NAME="Bds Maneger Docker" ^
-e GAMEMODE="survival" ^
-e DIFFICULTY="normal" ^
-e ACCOUNT="false" ^
-e PLAYERS="13" ^
-e SERVER="bedrock" ^
-e ENABLE_COMMANDS="false" ^
ghcr.io/the-bds-maneger/core:latest
```
### Linux/MacOS run image:
```bash ```bash
docker run --rm -d --name BdsManegerCore -v BdsCore/:/home/bds/bds_core \ docker run --rm -d \
--restart=always -p 19132:19132/udp -p 19133:19133/udp -p 1932:1932/tcp \ --name=bdscore \
-e DESCRIPTION="running Minecraft Bedrock Server on the docker by Bds Manager" \ -v bds_server_storage:/data \
-e WORLD_NAME="Bds Maneger Docker" \ -p 25565:25565/udp \
-e GAMEMODE="survival" \ -p 25565:25565/tcp \
-e DIFFICULTY="normal" \ -p 19132:19132/udp \
-e ACCOUNT="false" \ -p 19133:19133/udp \
-e PLAYERS="13" \ -p 3000:3000/tcp \
-e SERVER="bedrock" \ -e DESCRIPTION="My Sample Server" \
-e ENABLE_COMMANDS="false" \ -e WORLD_NAME="My Map" \
-e GAMEMODE="survival" \
-e DIFFICULTY="normal" \
-e MAXPLAYERS="5" \
-e REQUIRED_LOGIN="false" \
-e VERSION="latest" \
-e PLATFORM="bedrock" \
ghcr.io/the-bds-maneger/core:latest ghcr.io/the-bds-maneger/core:latest
``` ```
## Azure Container and Azure VM Get log: `docker logs bdscore`.
We've separate the repository for azure deploy templates, [go here](https://github.com/The-Bds-Maneger/Azure#azure-deploys) if you want to deploy to azure.
## Oracle Cloud
soon!

View File

@ -1,311 +0,0 @@
#!/usr/bin/env node
if (process.platform === "win32") process.title = "Bds Maneger CLI"; else process.title = "Bds-Manger-CLI";
process.env.IS_BDS_CLI = process.env.IS_BIN_BDS = true;
const fs = require("fs");
const path = require("path");
const readline = require("readline");
const BdsCore = require("../src/index");
const cli_color = require("cli-color");
const inquirer = require("inquirer");
async function DownloadServer(waitUserSelectVersion = "") {
const ora = (await import("ora")).default;
const Platform = BdsCore.BdsSettings.CurrentPlatorm();
const BdsCoreUrlManeger = require("@the-bds-maneger/server_versions");
const Versions = (await BdsCoreUrlManeger.listAsync());
if (waitUserSelectVersion === true || !waitUserSelectVersion) waitUserSelectVersion = (await inquirer.prompt({
type: "list",
name: "version",
message: `Select the version to download ${Platform}`,
choices: [
{
name: `Latest Version (${Versions.latest[Platform]})`,
value: "latest"
},
...(Versions.platform.filter(Version => Version.name === Platform).map(version => ({name: `v${version.version}`, value: version.version})))
]
})).version;
const RunSpinner = ora("Downloading...").start();
try {
const DownloadRes = await BdsCore.BdsDownload.DownloadServer(waitUserSelectVersion || "latest");
RunSpinner.succeed(`Downloaded ${DownloadRes.version}, Published in ${DownloadRes.data.getDate()}/${DownloadRes.data.getMonth()}/${DownloadRes.data.getFullYear()}`);
} catch (err) {
RunSpinner.fail(String(err));
process.exit(1);
}
}
async function info() {
const commandExist = require("../src/lib/commandExist");
const { valid_platform } = await (require("../src/lib/BdsSystemInfo"))();
var checkothearch = "";
if (process.platform === "linux" && BdsCore.BdsSystemInfo.arch !== "x64"){
checkothearch = `qemu-x86_64-static is installed to emulate an x64 system: ${commandExist("qemu-x86_64-static")}\n`
}
if (process.platform === "android" && BdsCore.BdsSystemInfo.arch !== "x64"){
checkothearch = `qemu-x86_64 is installed to emulate an x64 system: ${commandExist("qemu-x86_64")}\n`
}
const info = [
"",
`Bds Maneger Core And Bds Maneger CLI version: ${cli_color.magentaBright(BdsCore.version)}`,
`System: ${cli_color.yellow(process.platform)}, architecture: ${cli_color.blue(BdsCore.BdsSystemInfo.arch)}`,
checkothearch,
"**************************************************************",
"* Servers currently available:",
`* - Bedrock: ${valid_platform.bedrock ? cli_color.greenBright("Avaible") : cli_color.redBright("Not Avaible")}`,
`* - Java and Spigot: ${valid_platform.java ? cli_color.greenBright("Avaible") : cli_color.redBright("Not Avaible")}`,
`* - Dragonfly: ${valid_platform.dragonfly ? cli_color.greenBright("Avaible") : cli_color.redBright("Not Avaible")}`,
`* - Pocketmine-MP: ${valid_platform.pocketmine ? cli_color.greenBright("Avaible") : cli_color.redBright("Not Avaible")}`,
"*",
"**************************************************************"
];
console.log(cli_color.whiteBright(info.join("\n").replace(/true/gi, cli_color.greenBright("true")).replace(/false/gi, cli_color.redBright("false")).replace(/undefined/gi, cli_color.red("undefined"))));
// End
return;
}
function StartServer(ExitSession = true) {
const BdsManegerServer = BdsCore.BdsManegerServer.StartServer();
console.log(cli_color.greenBright(`Server started Session UUID: ${BdsManegerServer.uuid}`));
BdsManegerServer.on("log", data => process.stdout.write(cli_color.blueBright(data)));
const __readline = readline.createInterface({input: process.stdin, output: process.stdout});
__readline.on("line", data => BdsManegerServer.SendCommand(data));
if (process.env.DOCKER_IMAGE !== "true") __readline.on("close", BdsManegerServer.stop);
BdsManegerServer.on("exit", code => {
__readline.close();
console.log(cli_color.redBright(`Bds Core Exit with code ${code}, Uptimed: ${BdsManegerServer.Uptime()}`));
if (ExitSession) process.exit(code);
});
}
module.exports.StartServer = StartServer;
// Async functiona
async function RenderMainProcess(ProcessArgs = {}, Plugins = []) {
// ESM Modules
const ora = (await import("ora")).default;
// Update Bds Core Platform
if (ProcessArgs.platform) {
if (process.env.DOCKER_IMAGE === "true") {
try {
BdsCore.BdsSettings.ChangePlatform(ProcessArgs.platform);
} catch (err) {
console.log(cli_color.redBright(err));
process.exit(1);
}
} else {
const UpdatePla = ora("Updating Bds Platform").start();
try {
BdsCore.BdsSettings.ChangePlatform(ProcessArgs.platform);
UpdatePla.succeed(`Now the platform is the ${ProcessArgs.platform}`);
} catch (error) {
UpdatePla.fail(`Unable to update platform to ${ProcessArgs.platform}`);
process.exit(1);
}
}
}
// Print Info about Bds Core and Platforms
if (ProcessArgs.info) {
await info();
return;
}
// Backup
if (ProcessArgs.backup) {
const BackupEnd = BdsCore.BdsBackup.Backup();
BackupEnd.write_file();
console.log(cli_color.greenBright(`Backup created and saved in ${BackupEnd.file_path}`));
process.exit(0);
}
// Download
if (ProcessArgs.download) await DownloadServer(ProcessArgs.download);
// Kill
if (ProcessArgs.kill) await BdsCore.BdsCkeckKill.Kill();
// Server Proprieties
// --players ${PLAYERS} --world-name ${WORLD_NAME} --description ${DESCRIPTION} --gamemode ${GAMEMODE} --difficulty ${DIFFICULTY} --level-seed ${LEVEL_SEED}
try {
const ServerProprieties = await BdsCore.BdsServerSettings.get_config();
if (ProcessArgs["world-name"]) ServerProprieties.world = ProcessArgs["world-name"];
if (ProcessArgs.description) ServerProprieties.description = ProcessArgs.description;
if (ProcessArgs.gamemode) ServerProprieties.gamemode = ProcessArgs.gamemode;
if (ProcessArgs.difficulty) ServerProprieties.difficulty = ProcessArgs.difficulty;
if (ProcessArgs.players) ServerProprieties.players = ProcessArgs.players;
await BdsCore.BdsServerSettings.config(ServerProprieties);
} catch (err) {
console.log("Cannot Save Config")
}
// Do NOT Start API
if (!(ProcessArgs["no-api"])) BdsCore.BdsManegerAPI.api();
// Get Domain
if (ProcessArgs.get_domain) {
try {
const HostInfo = await BdsCore.BdsNetwork.GetHost();
console.log("Domain:", HostInfo.host);
process.on("exit", async () => {
await HostInfo.delete_host();
console.log("Sucess remove host");
});
} catch (err) {
console.log("Cannot get domain");
}
}
if (BdsCore.BdsToken.GetAllTokens().map(a => a.Token).length === 0) BdsCore.BdsToken.CreateToken();
console.log("Token:", BdsCore.BdsToken.GetAllTokens().map(a => a.Token).join("\n"));
for (let Plgun of Plugins) {
const { externalStart, name } = require(Plgun);
if (externalStart) {
console.log(name || Plgun, "Control Start");
return;
}
}
if (!ProcessArgs.auto_update) return StartServer(true);
else {
const BdsCoreUrlManeger = require("@the-bds-maneger/server_versions");
const BdsSettings = require("../src/lib/BdsSettings");
const BdsBackup = require("../src/BdsBackup");
const BdsManegerServer = require("../src/ServerManeger");
const BdsDownload = require("../src/BdsServersDownload");
const Sleep = async (Seconds = 1) => await new Promise(resolve => setTimeout(resolve, Seconds * 1000));
console.log("Auto Update Server Software Enabled");
const Platform = BdsSettings.CurrentPlatorm();
let TmpVersion = BdsSettings.GetBdsConfig().server.versions[Platform];
let IsFistStart = false;
StartServer(false);
// eslint-disable-next-line no-constant-condition
while (true) {
try {
if (IsFistStart) {
const LatestVersions = (await BdsCoreUrlManeger.listAsync()).latest[Platform];
if (LatestVersions !== TmpVersion) {
console.log("New Version:", LatestVersions);
const Servers = BdsManegerServer.GetSessions();
for (let session of Servers) {
try {session.ServerAction.say("AutoUpdate Stop Server");} catch (err) {console.log(err);}
await session.stop();
}
(BdsBackup.Backup()).write_file();
await BdsDownload.DownloadServer("latest");
StartServer(false);
TmpVersion = LatestVersions;
}
} else IsFistStart = true;
await Sleep(1000);
} catch (err) {
console.log(err);
}
}
}
}
const Yargs = require("yargs").usage("$0 [args]");
Yargs.command("info", "Show info", async () => {
await info();
process.exit(0);
});
Yargs.command("start", "Start Bds Core Server", (YargsOpt) => {
YargsOpt.option("platform", {
alias: "p",
describe: "Select BdsManeger Platform available to system and architecture",
type: "string"
});
YargsOpt.option("download", {
describe: "Download Bds Server",
type: "string",
alias: "d",
});
YargsOpt.option("kill", {
alias: "k",
describe: "Kill Bds Servers",
type: "boolean",
default: true
});
YargsOpt.option("backup", {
describe: "Backup Bds Server",
type: "boolean",
alias: "b",
default: false
});
YargsOpt.option("get_domain", {
describe: "Get Domain to connect to the Server",
type: "boolean",
default: false
});
YargsOpt.option("auto_update", {
describe: "Enable Auto Update Server",
alias: "a",
type: "boolean",
default: false
});
YargsOpt.option("no-api", {
describe: "Desactivate BdsManeger API",
type: "boolean",
default: false
});
// World Options
YargsOpt.option("world-name", {
describe: "World Name, (Some platforms do not accept spaces)",
type: "string"
});
YargsOpt.option("description", {
describe: "World Description",
type: "string"
});
YargsOpt.option("gamemode", {
describe: "Default Server Gamemode",
type: "string"
});
YargsOpt.option("difficulty", {
describe: "Default Server Difficulty",
type: "string"
});
YargsOpt.option("players", {
describe: "Max Players to Connect to the Server",
type: "number",
default: 15
});
YargsOpt.option("Develop", {
describe: "Develop Mode",
type: "boolean",
default: false
});
module.exports.Yargs = YargsOpt;
const Plugins = [];
fs.readdirSync(path.join(__dirname, "plugins")).map(file => path.resolve(__dirname, "plugins", file)).filter(Mod => fs.lstatSync(Mod).isFile() && Mod.endsWith(".js")).forEach(Plugin => {
try {
require(Plugin);
Plugins.push(Plugin);
} catch (err) {
console.log(cli_color.redBright(`Error loading plugin: ${path.basename(Plugin).replace(/\.js$/gi, "")}`));
console.log(cli_color.redBright(err));
}
});
const YargsOptArg = YargsOpt.help().version(false).parse();
if (YargsOptArg.Develop) process.env.NODE_ENV = "development";
else {
process.env.NODE_ENV = process.env.NODE_ENV ? process.env.NODE_ENV : "production";
}
return RenderMainProcess({
download: YargsOptArg.download || YargsOptArg.d,
kill: YargsOptArg.kill || YargsOptArg.k,
auto_update: YargsOptArg.auto_update || YargsOptArg.a,
backup: YargsOptArg.backup || YargsOptArg.b,
get_domain: YargsOptArg.get_domain,
"no-api": YargsOptArg["no-api"],
platform: YargsOptArg.platform || YargsOptArg.p,
"world-name": YargsOptArg["world-name"],
description: YargsOptArg.description,
gamemode: YargsOptArg.gamemode,
difficulty: YargsOptArg.difficulty,
players: YargsOptArg.players
}, Plugins).catch(err => {
console.log(cli_color.redBright(String(err.stack || err)));
process.exit(1);
});
});
Yargs.version(false).help(true).parse();

View File

@ -1,115 +0,0 @@
const { version, BdsSettings, BdsToken, BdsSystemInfo, BdsManegerServer } = require("../../src/index");
const { Telegraf } = require("telegraf");
const os = require("os");
const fs = require("fs");
const path = require("path");
// Set Telegram Bot
if (process.env.DOCKER_IMAGE === "true") {
if (process.env.TelegramToken) BdsSettings.more.telegramToken(process.env.TelegramToken);
}
const { Yargs } = require("../BdsManeger");
Yargs.option("telegram", {
describe: "Start Telegram Bot",
alias: "t",
type: "boolean",
default: false
});
const TelegramToken = BdsSettings.more.telegramToken();
if (TelegramToken) {
const bot = new Telegraf(TelegramToken);
// Bot Start And Help messages
const HelpAndStart = [
"Hello, welcome to Bds Maneger Telegram Bot",
"",
"We are changing some things but everything is working!!",
"Options:",
" /start or /help: This message!",
" ",
];
bot.start((ctx) => ctx.reply(HelpAndStart.join("\n")));
bot.help((ctx) => ctx.reply(HelpAndStart.join("\n")));
// Info
bot.command("info", async (ctx) => {
const info = await BdsSystemInfo.SystemInfo();
const reply = [
`Bds Maneger Core Version: ${version}`,
"Available Servers (Platfroms):",
"",
`Bedrock: ${info.valid_platform.bedrock ? "Avaible" : "Not Avaible"}`,
`Java: ${info.valid_platform.java ? "Avaible" : "Not Avaible"}`,
`Pocketmine-MP: ${info.valid_platform.pocketmine ? "Avaible" : "Not Avaible"}`,
`Spigot: ${info.valid_platform.java ? "Avaible" : "Not Avaible"}`,
`Dragonfly: ${info.valid_platform.dragonfly ? "Avaible" : "Not Avaible"}`,
];
return ctx.reply(reply.join("\n"));
});
// Setup User Token
bot.command("token", async (ctx) => {
const AllTokens = BdsToken.GetAllTokens();
const TextToken = ctx.message.text.replace(/\/token\s+/, "");
if (AllTokens.length > 0) {
if (!TextToken) return ctx.reply("Please, add your token");
if (!BdsToken.CheckToken(TextToken)) return ctx.reply("Invalid Token");
BdsToken.UpdateTelegramID(TextToken, ctx.message.from.id);
return ctx.reply(`Token Associed to your account (You id: ${ctx.message.from.id})`);
} else {
ctx.reply("Please wait, we are setting up your fist token");
const FistToken = BdsToken.CreateToken("admin", ctx.message.from.id);
return ctx.reply(`Your fist token is: ${FistToken.Token}`);
}
});
// Send Command to Servers
bot.command("command", async (ctx) => {
const user_id = ctx.message.from.id;
if (ctx.message.from.is_bot) return ctx.reply("You can't send commands to servers");
const command = ctx.message.text.replace(/^\/command\s+/i, "");
if (!(BdsToken.CheckTelegramID(user_id))) return ctx.reply("You are not allowed to send commands to servers or is not setup you Token");
const __Current_Sessions__ = BdsManegerServer.GetSessions();
const SessionsArray = Object.keys(__Current_Sessions__)
if (SessionsArray.length > 0) SessionsArray.forEach((key) => {
__Current_Sessions__[key].SendCommand(command);
}); else return ctx.reply("No Servers Running");
});
// Enable or Disable Player on connect
let ReplyList = [];
const TmpReplyList = path.join(os.tmpdir(), "ReplyList.json");
const WriteTmpReplyList = () => fs.writeFileSync(TmpReplyList, JSON.stringify(ReplyList));
if (fs.existsSync(TmpReplyList)) ReplyList = JSON.parse(fs.readFileSync(TmpReplyList));
BdsManegerServer.RegisterPlayerGlobalyCallbacks((Actions) => {
const MountText = [];
Actions.forEach((action) => {
MountText.push(`${action.Player} ${action.Action}`);
});
ReplyList.forEach((reply) => {
return bot.telegram.sendMessage(reply.id, MountText.join("\n"));
});
});
bot.command("player", ctx => {
const ChatID = ctx.chat.id;
if (ReplyList.find(User => User.id === ChatID)) {
ReplyList = ReplyList.filter(User => User.id !== ChatID);
ctx.reply("Player on connect disabled");
} else {
ReplyList.push({ id: ChatID });
ctx.reply("Player on connect enabled");
}
WriteTmpReplyList();
});
// Get Catch
bot.catch(console.log);
if (Yargs.parse()["telegram"]) () => {
console.log("Start Telegram Bot¹");
return bot.launch()
};
} else console.log("Telegram bot disabled");

View File

@ -19,7 +19,6 @@ services:
BDS_VERSION: "latest" BDS_VERSION: "latest"
SERVER: "bedrock" SERVER: "bedrock"
ports: ports:
- 1932:3000/tcp
- 3000:3000/tcp - 3000:3000/tcp
- 19132:19132/udp - 19132:19132/udp
- 19133:19133/udp - 19133:19133/udp

16137
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,38 @@
{ {
"name": "@the-bds-maneger/core", "name": "@the-bds-maneger/core",
"private": false,
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"version": "1.15.0", "version": "2.0.0",
"description": "A very simple way to manage Minecraft servers", "description": "A very simple way to manage Minecraft servers",
"private": false, "main": "dist/cjs/index.js",
"main": "src/index.js", "types": "dist/cjs/index.d.ts",
"exports": { "exports": {
"require": "./src/index.js", "require": "./dist/src/index.js",
"import": "./esm/index.js" "import": "./dist/esm/index.js"
}, },
"scripts": { "scripts": {
"start": "node bin/BdsManeger.js start", "build": "run-s build:*",
"test": "node .test/core.js", "build:cjs": "tsc --module commonjs --outDir dist/cjs",
"dev": "nodemon", "build:esm": "tsc --module es2020 --outDir dist/esm"
"esm": "cjs2esm",
"esm_module": "cjs2esm",
"eslint": "eslint --debug --fix .",
"Docker": "docker-compose up --build"
}, },
"nodemonConfig": { "nodemonConfig": {
"delay": 2500,
"ext": "json,js,ts",
"ignore": [ "ignore": [
"test/*" "test/*"
], ],
"delay": 2500,
"watch": [ "watch": [
"src", "src",
"bin", "bin",
"package.json", "package.json",
"package-lock.json" "package-lock.json"
], ],
"exec": "node --trace-warnings ./bin/BdsManeger.js start --Develop" "exec": "npm run build:cjs && node --trace-warnings ./dist/cjs/bin/index.js start --Develop"
}, },
"bin": { "bin": {
"bds_maneger": "bin/BdsManeger.js" "bds_maneger": "dist/cjs/bin/index.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -48,7 +46,8 @@
"java", "java",
"pocketmine", "pocketmine",
"server_mode", "server_mode",
"rest" "rest",
"typescript"
], ],
"author": "Sirherobrine23", "author": "Sirherobrine23",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
@ -66,37 +65,22 @@
"android" "android"
], ],
"dependencies": { "dependencies": {
"@iarna/toml": "^2.2.5", "adm-zip": "^0.5.9",
"@the-bds-maneger/server_versions": "^1.1.0", "axios": "^0.26.1",
"adm-zip": "^0.5.1",
"body-parser": "^1.19.0",
"cli-color": "^2.0.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"cron": "^1.8.2", "cron": "^1.8.2",
"deepmerge": "^4.2.2", "express": "^4.17.3",
"express": "^4.17.1", "prismarine-nbt": "^2.2.1",
"express-fileupload": "^1.2.1",
"express-prettify": "^0.1.1",
"express-rate-limit": "^6.0.1",
"inquirer": "^8.1.5",
"js-yaml": "^4.1.0",
"minecraft-server-util": "^5.2.8",
"node-cron": "^3.0.0",
"node-fetch": "^3.0.0",
"ora": "^6.0.1",
"prismarine-nbt": "^2.0.0",
"properties-to-json": "^0.2.1", "properties-to-json": "^0.2.1",
"request-ip": "^2.1.3", "yargs": "^17.4.0"
"socket.io": "^4.3.2",
"systeminformation": "^5.10.0",
"telegraf": "^4.0.0",
"yargs": "^17.3.1"
}, },
"devDependencies": { "devDependencies": {
"@actions/core": "^1.5.0", "@types/adm-zip": "^0.4.34",
"cjs2esm": "^2.0.2", "@types/cron": "^1.7.3",
"eslint": "^8.0.0", "@types/express": "^4.17.13",
"json-schema": ">=0.4.0", "@types/node": "^17.0.22",
"nodemon": "^2.0.12" "@types/yargs": "^17.0.10",
"npm-run-all": "^4.1.5",
"typescript": "^4.6.3"
} }
} }

View File

@ -1,64 +0,0 @@
const path = require("path");
const fs = require("fs");
const AdmZip = require("adm-zip");
const BdsSettings = require("../src/lib/BdsSettings");
function CreateZipBuffer() {
const Zip = new AdmZip();
const Functions = {};
/**
* Add file or folder to zip file
*/
Functions.Add = (Path = "", Name = path.basename(Path)) => {
const _S = fs.statSync(path.resolve(Path));
if (_S.isFile()) Zip.addLocalFile(Path, Name);
else Zip.addLocalFolder(Path, Name);
}
/**
* Get Buffer to File Zip, not parse arguments to Get Buffer.
*
* Parse arguments to Write file in path argument.
*/
Functions.WriteOrBuffer = (Path = "") => {
if (!Path) return Zip.toBuffer();
else fs.writeFileSync(Path, Zip.toBuffer(), "binary");
}
Functions.AdmZip = Zip;
return Functions;
}
function CreateBackup() {
const ZipFile = CreateZipBuffer();
ZipFile.AdmZip.addZipComment("Settings and World Backups, by The Bds Maneger Project©");
// Bedrock
const BedrockPath = BdsSettings.GetPaths("bedrock", true);
if (fs.existsSync(path.join(BedrockPath, "worlds"))) ZipFile.Add(path.join(BedrockPath, "worlds"), "Server/bedrock/worlds");
if (fs.existsSync(path.join(BedrockPath, "server.properties"))) ZipFile.Add(path.join(BedrockPath, "server.properties"), "Server/bedrock");
if (fs.existsSync(path.join(BedrockPath, "permissions.json"))) ZipFile.Add(path.join(BedrockPath, "permissions.json"), "Server/bedrock");
if (fs.existsSync(path.join(BedrockPath, "whitelist.json"))) ZipFile.Add(path.join(BedrockPath, "whitelist.json"), "Server/bedrock");
// Java
const JavaPath = BdsSettings.GetPaths("java", true);
for (const JavaFiles of fs.readdirSync(JavaPath)) {
if (!/eula.txt|logs|.*.jar|usercache.json/.test(JavaFiles)) {
ZipFile.Add(path.join(JavaPath, JavaFiles), "Server/java/");
}
}
const CurrentDate = new Date();
const ZipName = `Bds_Maneger_Core_Backups_${CurrentDate.getDate()}-${CurrentDate.getMonth()}-${CurrentDate.getFullYear()}.zip`
const PathBackup = path.join(BdsSettings.GetPaths("Backup"), ZipName);
return {
FilePath: PathBackup,
FileName: ZipName,
file_path: PathBackup,
file_name: ZipName,
Buffer: ZipFile.WriteOrBuffer(),
write_file: () => ZipFile.WriteOrBuffer(PathBackup)
}
}
module.exports.CreateBackup = CreateBackup;

View File

@ -1,135 +0,0 @@
{
"temp_host": {
"url": "http://hosts.bdsmaneger.com:3020"
},
"Fetchs": {
"php": "https://raw.githubusercontent.com/The-Bds-Maneger/Php_Static_Binary/main/binarys.json"
},
"IgnoreLog": {
"bedrock": [
{
"value": "Running AutoCompaction",
"regex": true
}
],
"java": [],
"pocketmine": [],
"spigot": [],
"dragonfly": []
},
"StartedServer": {
"bedrock": {
"value": "Server started",
"regex": true
},
"java": {
"value": null,
"regex": false
},
"pocketmine": {
"value": null,
"regex": false
},
"spigot": {
"value": null,
"regex": false
},
"dragonfly": {
"value": null,
"regex": false
}
},
"Servers": {
"bedrock": {
"stop": {
"value": "stop",
"type": "command"
},
"op": {
"value": "op \"{{}}\"",
"type": "command"
},
"deop": "op \"{{Player}}\"",
"ban": "tp \"{{Player}}\" ~ ~99999 ~",
"kick": "kick \"{{Player}}\" \"{{Text}}\"",
"tp": "tp \"{{Player}}\" {{X}} {{Y}} {{X}}",
"say": "say {{Text}}"
},
"java": {
"stop": "stop",
"op": "op {{Player}}",
"deop": "op {{Player}}",
"ban": "ban {{Player}}",
"kick": "kick {{Player}} {{Text}}",
"tp": "tp {{Player}} {{X}} {{Y}} {{X}}",
"say": "say {{Text}}"
},
"pocketmine": {
"stop": {
"value": "stop",
"type": "command"
},
"op": {
"value": "op {{Player}}",
"type": "command"
},
"deop": {
"value": "deop {{Player}}",
"type": "command"
},
"ban": {
"value": "ban {{Player}}",
"type": "command"
},
"kick": {
"value": "kick {{Player}}",
"type": "command"
},
"tp": {
"value": "tp {{Player}} {{X}} {{Y}} {{X}}",
"type": "command"
},
"say": {
"value": "say {{Text}}",
"type": "command"
}
},
"dragonfly": {
"stop": {
"value": "SIGNKILL",
"type": "process"
},
"op": {
"value": null,
"type": null
},
"deop": {
"value": null,
"type": null
},
"ban": {
"value": null,
"type": null
},
"kick": {
"value": null,
"type": null
},
"tp": {
"value": null,
"type": null
},
"say": {
"value": null,
"type": null
}
}
},
"contributors": [
{
"name": "Matheus Sampaio Queiroga",
"email": "srherobrine20@gmail.com",
"url": "https://sirherobrine23.org/?from=the-bds-maneger-project"
}
]
}

View File

@ -1,134 +0,0 @@
// External User ip
const Request = require("../src/lib/Requests");
const os = require("os");
function LocalInterfaces() {
const interfaces = os.networkInterfaces();
const localInterfaces = [];
for (const name of Object.getOwnPropertyNames(interfaces)) {
const Inter = {
interfaceName: name,
mac: "",
v4: {
addresses: "",
netmask: "",
cidr: ""
},
v6: {
addresses: "",
netmask: "",
cidr: ""
},
};
for (let iface of interfaces[name]) {
if (!Inter.mac && iface.mac) Inter.mac = iface.mac;
if (iface.family === "IPv4") {
Inter.v4.addresses = iface.address;
Inter.v4.netmask = iface.netmask;
Inter.v4.cidr = iface.cidr;
} else if (iface.family === "IPv6") {
Inter.v6.addresses = iface.address;
Inter.v6.netmask = iface.netmask;
Inter.v6.cidr = iface.cidr;
}
}
if (!(interfaces[name][0].internal)) localInterfaces.push(Inter);
}
return localInterfaces;
}
async function GetExternalPublicAddress() {
const ExternlIPs = {
ipv4: null,
ipv6: null
}
ExternlIPs["ipv4"] = (await Request.TEXT("https://api.ipify.org/")).replace("\n", "")
ExternlIPs["ipv6"] = (await Request.TEXT("https://api64.ipify.org/")).replace("\n", "")
if (ExternlIPs["ipv6"] === ExternlIPs["ipv4"]) ExternlIPs["ipv6"] = null;
return ExternlIPs;
}
module.exports.externalIP = {ipv4: "", ipv6: ""};
GetExternalPublicAddress().then(ExternlIPs => module.exports.externalIP = ExternlIPs);
// Internal ip user
const interfaces = os.networkInterfaces();
const internal_ip = [];
for (let inter of Object.getOwnPropertyNames(interfaces).map(index => interfaces[index])){
for (let ind in inter){
if (inter[ind].address.includes("::")) internal_ip.push(`[${inter[ind].address}]`)
else internal_ip.push(inter[ind].address)
}
}
// Network Interfaces
const Interfaces = Object.getOwnPropertyNames(interfaces).map(inter => {
inter = interfaces[inter]
if (inter[0].mac !== "00:00:00:00:00:00") {
try {
return {
MAC: inter[0].mac,
Interna_IP: {
ipv4: inter[0].address,
ipv6: inter[1].address,
}
}
} catch (err) {
return {
MAC: inter[0].mac,
Interna_IP: {
ipv4: inter[0].address,
ipv6: null,
}
}
}
}
}).filter(a=>a);
async function GetHost() {
const MacAddr = LocalInterfaces().map(Int => Int.mac);
const MachineID = Buffer.from(JSON.stringify(MacAddr)).toString("base64");
const ExternalAddress = (await GetExternalPublicAddress()).ipv4;
const RequestUpstream = await fetch("https://upstream.bdsmaneger.com/v2/domain", {
mode: "cors",
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
"external_ip": ExternalAddress,
"machine_id": MachineID
})
});
if (!RequestUpstream.ok) {
throw {
Backend: await RequestUpstream.json()
}
}
const HostInfo = await RequestUpstream.json();
const _toReturn = {
host: "",
delete_host: async () => {
const RequestDeleteHost = await fetch("https://upstream.bdsmaneger.com/v1/public_domain", {
method: "DELETE",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
"machine_id": MachineID
})
});
return await RequestDeleteHost.json();
}
}
_toReturn["host"] = HostInfo.domain+".bdsmaneger.com"
return _toReturn;
}
module.exports = {
internal_ip,
Interfaces,
LocalInterfaces,
GetExternalPublicAddress,
GetHost
}

View File

@ -1,183 +0,0 @@
const fs = require("fs");
const path = require("path");
const Extra = require("./BdsManegerInfo.json");
const bds = require("../src/index");
const Request = require("../src/lib/Requests");
const BdsCoreURlManeger = require("@the-bds-maneger/server_versions");
var AdmZip = require("adm-zip");
// Php download and install
async function php_download() {
const bds_dir_pocketmine = bds.BdsSettings.GetPaths("pocketmine", true);
const PHPBin = await Request.json(Extra.Fetchs.php);
const phpFolder = path.resolve(bds_dir_pocketmine, "bin");
// Check Php Binary
let urlPHPBin = PHPBin[process.platform]
if (!(urlPHPBin)) throw new Error("unsupported system")
urlPHPBin = urlPHPBin[bds.BdsSystemInfo.arch];
if (!(urlPHPBin)) throw new Error("unsupported arch")
// Remove Old php Binary if it exists
if (fs.existsSync(phpFolder)) {
fs.rmSync(phpFolder, { recursive: true });
}
// Download php binary
const ZipBuffer = await Request.buffer(urlPHPBin);
const zipExtractBin = new AdmZip(ZipBuffer);
zipExtractBin.extractAllTo(bds_dir_pocketmine, false)
if (process.platform === "win32") return path.resolve();
let phpConfigInit = fs.readFileSync(path.join(phpFolder, "php7", "bin", "php.ini"), "utf8");
const phpExtensiosnsDir = path.resolve(bds_dir_pocketmine, "bin/php7/lib/php/extensions");
if (!(fs.existsSync(phpExtensiosnsDir))) return true;
const phpExtensiosns = fs.readdirSync(phpExtensiosnsDir).map(FileFolder => {
if (!(FileFolder.includes("debug-zts"))) return false;
return path.resolve(phpExtensiosnsDir, FileFolder);
}).filter(a=>a);
if (phpConfigInit.includes("extension_dir")) console.log("Skipping php.ini configuration");
else {
phpConfigInit = (`extension_dir="${phpExtensiosns.join()}"\n${phpConfigInit}`);
fs.writeFileSync(path.join(phpFolder, "php7", "bin", "php.ini"), phpConfigInit);
}
return true;
}
// New Download Method
async function BdsDownload(version = "latest") {
const CurrentPlatform = bds.BdsSettings.CurrentPlatorm();
const { valid_platform } = await (require("../src/lib/BdsSystemInfo")).CheckSystemAsync();
const LocalServersVersions = bds.BdsSettings.GetBdsConfig().server.versions;
const { Servers, ServersConfig: SeverPathsConfig } = bds.BdsSettings.GetBdsConfig().paths;
if (typeof version === "boolean" || /true|false|null|undefined/.test(`${version}`.toLocaleLowerCase())) version = "latest";
const UrlsInfo = await BdsCoreURlManeger.findAsync(version, CurrentPlatform);
const ReturnObject = {
version: UrlsInfo.raw_request.version,
platform: CurrentPlatform,
url: UrlsInfo.url,
data: UrlsInfo.Date,
skip: false
};
// Bedrock
if (CurrentPlatform === "bedrock") {
const BedrockServerPath = path.join(Servers, SeverPathsConfig.bedrock);
if (valid_platform.bedrock) {
if (LocalServersVersions.bedrock !== version) {
// Download and Add buffer to AdmZip
const BedrockZip = new AdmZip(await Request.buffer(ReturnObject.url));
// Create Backup Bedrock Config
const BedrockConfigFiles = {
proprieties: "",
whitelist: "",
permissions: "",
};
// Get Bedrock Config Files
if (fs.existsSync(path.join(BedrockServerPath, "bedrock_server.properties"))) BedrockConfigFiles.proprieties = fs.readFileSync(path.join(BedrockServerPath, "bedrock_server.properties"), "utf8");
if (fs.existsSync(path.join(BedrockServerPath, "whitelist.json"))) BedrockConfigFiles.whitelist = fs.readFileSync(path.join(BedrockServerPath, "whitelist.json"), "utf8");
if (fs.existsSync(path.join(BedrockServerPath, "permissions.json"))) BedrockConfigFiles.permissions = fs.readFileSync(path.join(BedrockServerPath, "permissions.json"), "utf8");
// Extract to Bedrock Dir
BedrockZip.extractAllTo(BedrockServerPath, true);
// Write Bedrock Config Files
if (BedrockConfigFiles.proprieties) fs.writeFileSync(path.join(BedrockServerPath, "bedrock_server.properties"), BedrockConfigFiles.proprieties, "utf8");
if (BedrockConfigFiles.whitelist) fs.writeFileSync(path.join(BedrockServerPath, "whitelist.json"), BedrockConfigFiles.whitelist, "utf8");
if (BedrockConfigFiles.permissions) fs.writeFileSync(path.join(BedrockServerPath, "permissions.json"), BedrockConfigFiles.permissions, "utf8");
} else {
ReturnObject.skip = true;
}
} else {
throw Error("Bedrock not suported");
}
}
// Java
else if (CurrentPlatform === "java") {
const JavaServerPath = path.join(Servers, SeverPathsConfig.java);
if (valid_platform.java) {
if (LocalServersVersions.java !== version) {
// Download and write java file
const JavaBufferJar = await Request.buffer(ReturnObject.url);
fs.writeFileSync(path.join(JavaServerPath, "MinecraftServerJava.jar"), JavaBufferJar, "binary");
// Write EULA
fs.writeFileSync(path.join(JavaServerPath, "eula.txt"), "eula=true");
} else {
ReturnObject.skip = true;
}
} else {
throw Error("Java not suported");
}
}
// Spigot
else if (CurrentPlatform === "spigot") {
const SpigotServerPath = path.join(Servers, SeverPathsConfig.spigot);
if (valid_platform.spigot) {
if (LocalServersVersions.spigot !== version) {
// Download and write java file
fs.writeFileSync(path.join(SpigotServerPath, "spigot.jar"), await Request.buffer(ReturnObject.url), "binary");
} else {
ReturnObject.skip = true;
}
} else {
throw Error("Spigot not suported");
}
}
// Dragonfly
else if (CurrentPlatform === "dragonfly") {
const DragonflyServerPath = path.join(Servers, SeverPathsConfig.dragonfly);
if (valid_platform.dragonfly) {
if (LocalServersVersions.dragonfly !== version) {
// Download
let DgBin = path.join(DragonflyServerPath, "Dragonfly");
if (process.platform === "win32") DgBin += ".exe";
fs.writeFileSync(DgBin, await Request.buffer(ReturnObject.url), "binary");
} else {
ReturnObject.skip = true;
}
} else {
throw Error("Dragonfly not suported");
}
}
// Pocketmine-MP
else if (CurrentPlatform === "pocketmine") {
const PocketmineServerPath = path.join(Servers, SeverPathsConfig.pocketmine);
if (valid_platform.pocketmine) {
if (LocalServersVersions.pocketmine !== version) {
// Download PHP Bin
await php_download();
// Download php file and save
const PocketmineBufferPhp = await Request.buffer(ReturnObject.url);
fs.writeFileSync(path.join(PocketmineServerPath, "PocketMine-MP.phar"), PocketmineBufferPhp, "binary");
} else {
ReturnObject.skip = true;
}
} else {
throw Error("Pocketmine-MP not suported");
}
}
// if the platform does not exist
else throw Error("No Valid Platform");
// Update Config Version
bds.BdsSettings.UpdateServerVersion(ReturnObject.version, CurrentPlatform);
// Return info download
return ReturnObject;
}
// Export
module.exports.DownloadServer = BdsDownload;

View File

@ -1,65 +0,0 @@
const child_process = require("child_process");
const systeminformation = require("systeminformation");
async function getProcess(){
const Process = await (await systeminformation.processes()).list;
return Process.map(Process => {
const { pid, command, mem, params } = Process;
return {
command: `${command} ${params}`,
mem,
pid,
Kill: async () => {
if (process.platform === "win32") return child_process.execSync(`taskkill /PID ${pid} /F`).toString("utf8");
else return child_process.execSync(`kill -9 ${pid}`).toString("utf8")
}
}
});
}
async function Detect(){
const CurrentProcess = await getProcess();
let Status = false;
for (let check of CurrentProcess) {
if (/MinecraftServerJava\.jar/.test(check.command)) Status = true;
if (/spigot\.jar/.test(check.command)) Status = true;
if (/bedrock_server/.test(check.command)) Status = true;
if (/PocketMine-MP\.phar/.test(check.command)) Status = true;
if (/Dragonfly/.test(check.command)) Status = true;
}
return Status;
}
async function Kill(){
const CurrentProcess = await getProcess();
if (!(await Detect())) return false
for (let check of CurrentProcess) {
if (/MinecraftServerJava.jar/.test(check.command)) {
console.log("Killing Minecraft Server Java");
await check.Kill();
}
if (/spigot.jar/.test(check.command)) {
console.log("Killing Spigot");
await check.Kill();
}
if (/bedrock_server/.test(check.command)) {
console.log("Killing Minecraft Bedrock Server");
await check.Kill();
}
if (/PocketMine-MP.phar/.test(check.command)) {
console.log("Killing Pocketmine-MP");
await check.Kill();
}
if (/Dragonfly/.test(check.command)) {
console.log("Killing Dragonfly");
await check.Kill();
}
}
return true
}
module.exports = {
getProcess,
Detect,
Kill
}

87
src/HttpRequests.ts Normal file
View 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"));
}

View File

@ -1,170 +0,0 @@
const fs = require("fs");
const BdsSettings = require("../lib/BdsSettings");
module.exports.PlayersJsonExample = module.exports.Example = [
{
Player: "",
Action: "",
Platform: "",
Date: "",
},
{
Player: "",
Action: "",
Platform: "",
xuid: "",
Date: "",
},
];
async function BedrockJson(Data = "") {
const Bedrock_Json = [];
/*
*************************
Old Versions
[INFO] Player connected: Sirherobrine, xuid: 2535413418839840
[INFO] Player disconnected: Sirherobrine, xuid: 2535413418839840
*************************
New Version
[2022-01-05 16:19:07:752 INFO] Player connected: Sirherobrine, xuid: 2535413418839840
[2022-01-05 16:19:38:988 INFO] Player disconnected: Sirherobrine, xuid: 2535413418839840
*/
// Regex to test line
for (const line of Data.split(/\r\n|\n/gi)){
if (/\[.*\]\s+Player\s+.*connected:\s+.*,\s+xuid:[\s+]/gi.test(line)) {
const playerAction = {
Player: "",
Action: "",
Platform: "bedrock",
xuid: "",
Date: (new Date()).toString()
};
if (/disconnected|disconnected.*:/.test(line)) playerAction.Action = "disconnect"; else playerAction.Action = "connect";
// Player
line.replace(/\[.*\]\s+Player\s+.*connected:(.*),\s+xuid:[\s+]/gi, (a, b) => playerAction.Player = b.trim());
// xuid
line.replace(/\[.*\]\s+Player\s+.*connected:.*,\s+xuid:[\s+](.*)/gi, (a, b) => playerAction.xuid = b.trim());
// New Version get Date
if (/\[.*\s+.*\]\s+Player\s+.*connected:(.*),\s+xuid:[\s+]/gi.test(line)) line.replace(/\[(.*)\s+.*\]\s+Player\s+connected:.*,\s+xuid:[\s+].*/gi, (_, b) => playerAction.Date = (new Date(b.trim())).toString());
// Add to array
if (playerAction.Player) Bedrock_Json.push(playerAction);
else {
console.log("Error in parse bedrock json:", line);
}
}
}
return Bedrock_Json;
}
async function pocketmineJson(Data = "") {
const JavaStyle = [];
/*
[15:05:18.001] [Server thread/INFO]: Sirherobrine joined the game
[15:05:30.695] [Server thread/INFO]: Sirherobrine left the game
[15:05:21.501] [Server thread/INFO]: Sirherobrine fell out of the world
*/
for (const line of Data.split(/\r\n|\n/gi)) {
if (/\[.*\].*\[.*\]:\s+.*the game/gi.test(line)) {
const playerAction = {
Player: "",
Action: "",
Platform: "pocketmine",
Date: (new Date()).toString()
}
if (/fell.*out.*of.*the.*world/gi.test(line)) {
playerAction.Action = "Out_of_World";
} else {
if (/left.*the.*game/gi.test(line)) playerAction.Action = "disconnect";
else playerAction.Action = "connect";
}
// Player
line.replace(/\[.*\]\s+\[.*\]:\s+(.*)\s+joined the game/gi, (a, b) => playerAction.Player = b.trim());
// Add to array
JavaStyle.push(playerAction);
}
}
return JavaStyle;
}
// async function javaJson(Data = "") {
// const JavaStyle = [];
// /**/
// for (const line of Data.split(/\n|\r/gi)) {
// if (line.trim().includes("joined the game") || line.includes("left the game")) {
// const JavaObject = {
// Player: line.replace(/joined the game|left the game/gi, "").trim(),
// Action: "",
// Platform: "java",
// Date: (new Date()).toString()
// }
// if (/joined/.test(line)) JavaObject.Action = "connect"; else JavaObject.Action = "disconnect";
// JavaStyle.push(JavaObject);
// }
// }
// return JavaStyle;
// }
module.exports.createJsons = {
BedrockJson: BedrockJson,
pocketmineJson: pocketmineJson,
};
async function Promise_CreatePlayerJson(data = "", Current_platorm = BdsSettings.CurrentPlatorm()) {
// Bedrock
if (Current_platorm === "bedrock") return await BedrockJson(data);
// Pocketmine-MP
else if (Current_platorm === "pocketmine") return await pocketmineJson(data);
// Java
// else if (Current_platorm === "java") {
// javaJson(data).then(Data => {
// if (Data.length === 0) return;
// callback(Data);
// }).catch(err => console.log("Error in parse java json:", err.stack||String(err)));
// }
}
module.exports.Promise_CreatePlayerJson = Promise_CreatePlayerJson;
function CreatePlayerJsonCallback(data = "", callback = (d = [{Player: "", Action: "connect", Platform: "", xuid: "", Date: ""},{Player: "", Action: "disconnect", Platform: "", xuid: "", Date: ""}]) => console.log(d), Current_platorm = BdsSettings.CurrentPlatorm()){
Promise_CreatePlayerJson(data, Current_platorm).then(Data => {
if (Data.length === 0) return;
return callback(Data);
}).catch(err => console.log("Error in parse json:", err.stack||String(err)));
}
module.exports.CreatePlayerJson = CreatePlayerJsonCallback;
/**
* Concat new Users Array to old Users Array and Save to file
*
* @returns {Array<{
* Player: string;
* Action: string;
* Platform: string;
* Date: string;
* }>}
*/
function UpdateUserJSON(New_Object = [{Player: "", Action: "", Platform: "", Date: ""}]){
const Player_Json_path = BdsSettings.GetPaths("Player");
let Players_Json = [];
if (fs.existsSync(Player_Json_path)) Players_Json = JSON.parse(fs.readFileSync(Player_Json_path, "utf8"));
Players_Json = Players_Json.concat(New_Object)
fs.writeFileSync(Player_Json_path, JSON.stringify(Players_Json, null, 2));
return Players_Json;
}
module.exports.UpdateUserJSON = UpdateUserJSON;
// Search player in JSON
function Player_Search(player = "dontSteve") {
const Player_Json_path = BdsSettings.GetPaths("Player");
const Players_Json = JSON.parse(fs.readFileSync(Player_Json_path, "utf8"));
for (let Player of Players_Json) {
if (Player.Player === player.trim()) return Player;
}
return {};
}
module.exports.Player_Search = Player_Search;

View File

@ -1,76 +0,0 @@
// const RawGithubUrl = "https://raw.githubusercontent.com/The-Bds-Maneger/Plugins_Repository/main";
const path = require("path");
const fs = require("fs");
const request = require("./lib/Requests");
const BdsSettings = require("./lib/BdsSettings");
/**
* @returns {<{
* listVersions: () => Promise<Array<{
* name: string;
* versions: Array<{
* version: string;
* url: string;
* id: number;
* }>;
* }>;
* Install: (PluginName: string, PluginVersion?: string) => Promise<string>;
* >}
*/
function PluginManegerPocketmine() {
async function Poggit_pmmp() {
let PluginsJsonPoggit = await request.json("https://poggit.pmmp.io/plugins.json");
let PluginsObject = {};
for (const Plugin of PluginsJsonPoggit) {
if (!PluginsObject[Plugin.name]) PluginsObject[Plugin.name] = {
name: Plugin.name,
versions: []
};
PluginsObject[Plugin.name].versions.push({
version: Plugin.version,
url: `https://poggit.pmmp.io/get/${Plugin.name}/${Plugin.version}`,
id: Plugin.id
});
}
return Object.keys(PluginsObject).map(PluginName => {
const Plugin = PluginsObject[PluginName];
return {
name: String(Plugin.name),
versions: Array.from(Plugin.versions).map(Version => {
const NewValue = {};
NewValue.version = String(Version.version);
NewValue.url = String(Version.url);
NewValue.id = Number(Version.id);
return NewValue;
})
}
});
}
const Install = async (PluginName = "", PluginVersion = "latest") => {
if (!PluginName) throw new Error("Plugin name is empty");
const PluginsList = (await Poggit_pmmp()).filter(Plugin => Plugin.name === PluginName)[0];
if (!PluginsList) throw new Error(`Plugin ${PluginName} not found`);
const Plugin = PluginsList.versions.filter(Version => Version.version === PluginVersion)[0];
if (!Plugin) throw new Error(`Plugin ${PluginName} version ${PluginVersion} not found`);
const PluginBufferfile = await request.buffer(Plugin.url);
const PluginFile = path.join(BdsSettings.GetPaths("pocketmine", true), "plugins", `${PluginName}.phar`);
fs.writeFileSync(PluginFile, PluginBufferfile);
return PluginFile;
}
return {
listVersions: Poggit_pmmp,
Install: Install,
};
}
module.exports = {
PluginManeger: (platform = BdsSettings.CurrentPlatorm()) => {
switch (platform) {
case "pocketmine":
return PluginManegerPocketmine();
default:
throw new Error(`Platform ${platform} not found`);
}
}
};

View File

@ -1,83 +0,0 @@
const RawGithubUrl = "https://raw.githubusercontent.com/The-Bds-Maneger/Plugins_Repository/main";
/**
* Parse /Config.y[a]ml/ to return a object with url, type and versions
*/
function Parse(RepositoryPath = "", BdsPlatform = "pocketmine", Config = {}) {
for (let KeyArray of Object.keys(Config)) {
if (!(KeyArray === "revision" || KeyArray === "name" || KeyArray === "type" || KeyArray === "versions")) console.error(`${KeyArray} is not supported`);
}
if (Config.type === undefined) throw new Error("Config Error: type not found");
const NewConfig = {
revision: "v1",
type: String(Config.type).toLowerCase(),
name: String(Config.name||""),
versions: [
{
dependencies: [""],
version: "",
minimum: "",
url: "",
},
{
dependencies: [],
version: 0,
minimum: 0,
url: "",
},
]
}; NewConfig.versions = [];
if (BdsPlatform === "pocketmine") {
for (const Version of Config.versions) {
let AddObj = false;
const { version, from, minimum, dependencies } = Version;
if (version === undefined) throw new Error("Config Error: version not found");
if (from === undefined) throw new Error("Config Error: from not found");
const ObjVersion = {
dependencies: dependencies || [],
version: version,
minimum: 0,
url: "",
};
// Server Minimum version (0 is any version)
if (typeof minimum === "string") ObjVersion.minimum = minimum;
else if (typeof minimum === "number") ObjVersion.minimum = minimum;
else ObjVersion.minimum = 0;
if (version !== undefined) {
// Pocketmine from poggit
if (from === "poggit_pmmp") {
if (typeof Config.name === "undefined") throw new Error("Config Error: name not found");
const { poggit_id } = Version;
if (typeof poggit_id === "undefined") ObjVersion.url = `https://poggit.pmmp.io/get/${Config.name.trim()}/${version}`;
else ObjVersion.url = `https://poggit.pmmp.io/r/${typeof poggit_id === "number" ? parseInt(poggit_id) : poggit_id.trim()}/${Config.name}.phar`;
AddObj = true;
} else if (from === "file") {
const { file } = Version;
if (RepositoryPath === undefined) throw new Error("Config Error: RepositoryPath not found");
if (typeof file === "string") {
ObjVersion.url = `${RawGithubUrl}/${RepositoryPath}/${file.replace("./", "")}`;
AddObj = true;
} else throw new Error("Config Error: file not found");
} else if (from === "github_release") {
const { repository, file_name } = Version;
if (typeof repository === "undefined") throw new Error("Config Error: repository not found");
if (typeof file_name === "undefined") console.error("Config Error: file_name not defined, using default");
ObjVersion.url = `https://github.com/releases/download/${repository}/${file_name || Config.name}.phar`;
AddObj = true;
} else if (from === "url") {
const { url } = Version;
if (typeof url === "undefined") throw new Error("Config Error: url not found");
if (/^http[s]?:\/\//.test(url.trim())) {
ObjVersion.url = url.trim();
AddObj = true;
}
} else console.error(`Config Error: from ${from} not supported`);
}
if (AddObj) NewConfig.versions.push(ObjVersion);
}
}
return NewConfig;
}
module.exports = {
Parse
};

View File

@ -1,466 +0,0 @@
const child_process = require("child_process");
const fs = require("fs");
const path = require("path");
const Crypto = require("crypto");
const BdsSettings = require("./lib/BdsSettings");
const Players_json = require("./ManegerServer/Players_json");
const { PlayersJsonExample } = Players_json
const PlayersCallbacks = [];
module.exports.RegisterPlayerGlobalyCallbacks = (callback = () => {}) => PlayersCallbacks.push(callback);
const BackendServerManeger = {
ServerSessions: []
};
/**
* Get All sever Sessions
*
* @returns {Array<{
* uuid: string
* LogPath: string
* StartTime: Date
* on: (Action: "log"|"exit", Callback: (data: String|number)) => void
* PlayerAction: (Action: "connect"|"disconect"|"all", Callback: (data: PlayersJsonExample) => {}) => void
* stop: Promise<() => number>
* SendCommand: (Data: String) => void
* Uptime: () => number
* Players_in_Session: void
* ServerAction: {
* op: (player: String) => void
* deop: (player: String) => void
* ban: (player: String) => void
* kick: (player: String) => void
* tp: (player: string, cord: {x: number y: number z: number }) => void
* say: (text: String) => void
* }
* }>}
*/
module.exports.GetSessions = () => BackendServerManeger.ServerSessions;
/**
* Inicialize the server
*/
function StartServer() {
const commandExists = require("./lib/commandExist").commdExistSync;
const io = require("./api").SocketIO;
const CurrentBdsPlatform = BdsSettings.CurrentPlatorm();
const SetupCommands = {
RunInCroot: false,
command: "",
args: [],
cwd: "",
env: {...process.env}
}
// Minecraft Bedrock Oficial
if (CurrentBdsPlatform === "bedrock"){
// Check Darwin Platform
if (process.platform === "darwin") throw new Error("Use a imagem Docker");
// Windows Platform
else if (process.platform === "win32") {
SetupCommands.command = "bedrock_server.exe";
SetupCommands.cwd = BdsSettings.GetPaths("bedrock", true)
}
// Linux Platform
else if (process.platform === "linux"){
// Set Env and Cwd
SetupCommands.cwd = BdsSettings.GetPaths("bedrock", true);
SetupCommands.env.LD_LIBRARY_PATH = BdsSettings.GetPaths("bedrock", true);
// Set Executable file
child_process.execSync("chmod 777 bedrock_server", {cwd: SetupCommands.cwd});
// In case the cpu is different from x64, the command will use qemu static to run the server
if (process.arch !== "x64") {
if (!(commandExists("qemu-x86_64-static"))) throw new Error("Install qemu static")
SetupCommands.command = "qemu-x86_64-static"
SetupCommands.args.push("./bedrock_server");
} else SetupCommands.command = "./bedrock_server";
} else throw new Error("your system does not support Minecraft Bedrock (yet)")
}
// Minecraft Java Oficial and Spigot
else if (CurrentBdsPlatform === "java" || CurrentBdsPlatform === "spigot") {
const JavaConfig = BdsSettings.GetBdsConfig("java").server.Settings.java;
// Checking if java is installed on the device
if (commandExists("java")) {
SetupCommands.cwd = BdsSettings.GetPaths("java", true);
SetupCommands.command = "java";
SetupCommands.args.push("-jar");
if (CurrentBdsPlatform === "java") SetupCommands.args.push(`-Xms${JavaConfig.ram||1024}M`, `-Xmx${JavaConfig.ram||1024}M`, "MinecraftServerJava.jar", "nogui");
else SetupCommands.args.push("spigot.jar");
} else throw new Error("Install Java");
}
// Dragonfly
else if (CurrentBdsPlatform === "dragonfly") {
SetupCommands.cwd = BdsSettings.GetPaths("dragonfly", true);
if (process.platform === "win32") {
SetupCommands.command = "Dragonfly.exe";
} else {
SetupCommands.command = "./Dragonfly";
child_process.execFileSync("chmod", ["a+x", SetupCommands.command], {cwd: SetupCommands.cwd});
}
}
// Minecraft Bedrock (Pocketmine-MP)
else if (CurrentBdsPlatform === "pocketmine") {
// Start PocketMine-MP
SetupCommands.cwd = BdsSettings.GetPaths("pocketmine", true);
SetupCommands.command = path.join(path.resolve(BdsSettings.GetPaths("pocketmine", true), "bin", "php7", "bin"), "php");
if (process.platform === "win32") SetupCommands.command = path.join(path.resolve(BdsSettings.GetPaths("pocketmine", true), "bin/php"), "php.exe");
if (/linux|android/.test(process.platform)) child_process.execFileSync("chmod", ["a+x", SetupCommands.command]);
SetupCommands.args.push("./PocketMine-MP.phar");
}
// Show Error platform
else throw Error("Bds Config Error")
// Setup commands
const ServerExec = child_process.execFile(SetupCommands.command, SetupCommands.args, {
cwd: SetupCommands.cwd,
env: SetupCommands.env
});
// Log file
const LogFolderPath = BdsSettings.GetPaths("Log") || BdsSettings.GetPaths("log");
const LogFile = path.join(LogFolderPath, `${BdsSettings.CurrentPlatorm()}_${new Date().toString().replace(/:|\(|\)/g, "_")}_Bds_log.log`),
LatestLog_Path = path.join(LogFolderPath, "latest.log"),
LogSaveFunction = data => {
fs.appendFileSync(LogFile, data);
fs.appendFileSync(LatestLog_Path, data);
return data;
};
fs.writeFileSync(LatestLog_Path, "");
// Log File
ServerExec.stdout.on("data", LogSaveFunction);
ServerExec.stderr.on("data", LogSaveFunction);
// Mount commands to Return
const SessionUUID = Crypto.randomUUID();
// Uptime Server
let UptimeNumber = 0;
const UptimeCount = setInterval(() => UptimeNumber++, 1000);
/**
* Emit command in to the server
*
* @param {string} command
* @param {Array} command
*/
function SendCommand(Command = "list") {
if (!(typeof Command === "string" || typeof Command === "object" && typeof Command.map === "function")) throw new Error("Command must be a string or an array");
if (typeof Command === "string") {
ServerExec.stdin.write(`${Command}\n`);
} else if (typeof Command === "object" && typeof Command.map === "function") {
Command.filter(a => typeof a === "string").forEach(command => ServerExec.stdin.write(`${command}\n`));
}
return;
}
/**
* Register a function to run when the server issues a log or when it exits.
*
* @param {string} FunctionAction - Action to Register to run callback
* @callback
*/
function OnCallbacks(FunctionAction = "log", callback = (data = FunctionAction === "log" ? "" : 0) => console.log(data)) {
if (!(FunctionAction === "log" || FunctionAction === "exit")) throw new Error("Use some valid FunctionAction: log, exit");
if (FunctionAction === "log") {
ServerExec.stdout.on("data", data => callback(data));
ServerExec.stderr.on("data", data => callback(data));
} else if (FunctionAction === "exit") ServerExec.on("exit", code => callback(code));
else throw new Error("Use some valid FunctionAction: log, exit");
}
/**
* Any type of event that can be logged on the server, this is not a log.
*
* @param {string} Action - The event to listen for.
* @param {function} Callback - The callback to run when the event is triggered.
*/
function SessionPlayerAction(Action = "all", Callback = (PlayerActions = PlayersJsonExample) => console.log(PlayerActions)){
if (typeof Callback !== "function") throw new Error("Callback must be a function");
if (!(Action === "all" || Action === "connect" || Action === "disconnect")) throw new Error("Use some valid Action: all, connect, disconnect");
OnCallbacks("log", async data => {
const PlayersActions = await Players_json.Promise_CreatePlayerJson(data, CurrentBdsPlatform);
if (PlayersActions.length === 0) return;
return Callback(PlayersActions.filter(PlayersActions => {
if (Action === "all") return true;
else if (Action === "connect" && PlayersActions.Action === "connect") return true;
else if (Action === "disconnect" && PlayersActions.Action === "disconnect") return true;
else return false;
}));
});
}
let CodeExit = null;
/**
* Stop the server
*/
async function SessionStop(){
if (CurrentBdsPlatform === "bedrock") {
ServerExec.stdin.write("stop\n");
} else if (CurrentBdsPlatform === "dragonfly") {
ServerExec.kill("SIGKILL");
} else if (CurrentBdsPlatform === "java") {
ServerExec.stdin.write("stop\n");
} else if (CurrentBdsPlatform === "pocketmine") {
ServerExec.stdin.write("stop\n");
} else if (CurrentBdsPlatform === "spigot") {
ServerExec.stdin.write("stop\n");
} else throw new Error("Bds Core Bad Config Error");
setTimeout(() => {
try {
CodeExit = "Timeout"
ServerExec.kill("SIGKILL");
} catch (error) {
console.log(error);
}
}, 30 * 1000);
const Code = await new Promise(resolve => OnCallbacks("exit", resolve));
if (CodeExit === "Timeout") throw new Error("Timeout");
return Number(Code);
}
/**
* Op a player
*/
function SessionOp(player = "Steve") {
if (CurrentBdsPlatform === "bedrock") {
ServerExec.stdin.write(`op "${player}"\n`);
return "op";
} else if (CurrentBdsPlatform === "dragonfly") {
throw new Error("Dragonfly does not support commands");
} else if (CurrentBdsPlatform === "java") {
ServerExec.stdin.write(`op ${player}\n`);
return "op";
} else if (CurrentBdsPlatform === "pocketmine") {
ServerExec.stdin.write(`op ${player}\n`);
return "op";
} else if (CurrentBdsPlatform === "spigot") {
ServerExec.stdin.write(`op ${player}\n`);
return "op";
} else throw new Error("Bds Core Bad Config Error");
}
/**
* Deop a player
*/
function SessionDeop(player = "Steve") {
if (CurrentBdsPlatform === "bedrock") {
ServerExec.stdin.write(`deop "${player}"\n`);
return "deop";
} else if (CurrentBdsPlatform === "dragonfly") {
throw new Error("Dragonfly does not support commands");
} else if (CurrentBdsPlatform === "java") {
ServerExec.stdin.write(`deop ${player}\n`);
return "deop";
} else if (CurrentBdsPlatform === "pocketmine") {
ServerExec.stdin.write(`deop ${player}\n`);
return "deop";
} else if (CurrentBdsPlatform === "spigot") {
ServerExec.stdin.write(`deop ${player}\n`);
return "deop";
} else throw new Error("Bds Core Bad Config Error");
}
/**
* Ban a player
*/
function SessionBan(player = "Steve") {
if (CurrentBdsPlatform === "bedrock") {
ServerExec.stdin.write(`kick "${player}"\n`);
return "kick";
} else if (CurrentBdsPlatform === "dragonfly") {
throw new Error("Dragonfly does not support commands");
} else if (CurrentBdsPlatform === "java") {
ServerExec.stdin.write(`ban ${player}\n`);
return "ban";
} else if (CurrentBdsPlatform === "pocketmine") {
ServerExec.stdin.write(`ban ${player}\n`);
return "ban";
} else if (CurrentBdsPlatform === "spigot") {
ServerExec.stdin.write(`ban ${player}\n`);
return "ban";
} else throw new Error("Bds Core Bad Config Error");
}
/**
* Kick a player
*/
function SessionKick(player = "Steve", text = "you got kicked") {
if (CurrentBdsPlatform === "bedrock") {
ServerExec.stdin.write(`kick "${player}" ${text}\n`);
return "kick";
} else if (CurrentBdsPlatform === "dragonfly") {
throw new Error("Dragonfly does not support commands");
} else if (CurrentBdsPlatform === "java") {
ServerExec.stdin.write(`kick ${player} ${text}\n`);
return "kick";
} else if (CurrentBdsPlatform === "pocketmine") {
ServerExec.stdin.write(`kick ${player} ${text}\n`);
return "kick";
} else if (CurrentBdsPlatform === "spigot") {
ServerExec.stdin.write(`kick ${player} ${text}\n`);
return "kick";
} else throw new Error("Bds Core Bad Config Error");
}
/**
* Teleport a player
*/
function SessionTp(player = "Steve", cord = {x: 0, y: 128, z: 0}) {
if (CurrentBdsPlatform === "bedrock") {
ServerExec.stdin.write(`tp ${player} ${cord.x} ${cord.y} ${cord.z}\n`);
return "tp";
} else if (CurrentBdsPlatform === "dragonfly") {
throw new Error("Dragonfly does not support commands");
} else if (CurrentBdsPlatform === "java") {
ServerExec.stdin.write(`tp ${player} ${cord.x} ${cord.y} ${cord.z}\n`);
return "tp";
} else if (CurrentBdsPlatform === "pocketmine") {
ServerExec.stdin.write(`tp ${player} ${cord.x} ${cord.y} ${cord.z}\n`);
return "tp";
} else if (CurrentBdsPlatform === "spigot") {
ServerExec.stdin.write(`tp ${player} ${cord.x} ${cord.y} ${cord.z}\n`);
return "tp";
} else throw new Error("Bds Core Bad Config Error");
}
/**
* Send text to Server
*/
function SessionSay(text = ""){
if (CurrentBdsPlatform === "bedrock") {
ServerExec.stdin.write(`say ${text}\n`);
return "say";
} else if (CurrentBdsPlatform === "dragonfly") {
throw new Error("Dragonfly does not support commands");
} else if (CurrentBdsPlatform === "java") {
ServerExec.stdin.write(`say ${text}\n`);
return "say";
} else if (CurrentBdsPlatform === "pocketmine") {
ServerExec.stdin.write(`say ${text}\n`);
return "say";
} else if (CurrentBdsPlatform === "spigot") {
ServerExec.stdin.write(`say ${text}\n`);
return "say";
} else throw new Error("Bds Core Bad Config Error");
}
ServerExec.on("exit", code => {
BackendServerManeger.ServerSessions = BackendServerManeger.ServerSessions.filter(Session => Session.uuid !== SessionUUID);
io.emit("ServerExit", {
UUID: SessionUUID,
exitCode: code
});
clearInterval(UptimeCount);
});
// Socket.io
io.on("connection", socket => {
try {
socket.emit("ServerLog", {
UUID: SessionUUID,
data: fs.readFileSync(SessionReturn.LogPath, "utf8")
});
} catch (err) {
console.log(err);
}
socket.on("ServerCommand", (data) => {
if (typeof data === "string") return SessionReturn.SendCommand(data);
else if (typeof data === "object") {
if (typeof data.uuid === "string") {
if (data.uuid === SessionUUID) return SessionReturn.SendCommand(data.command);
}
}
return;
});
});
/**
* Player Session
*/
const PlayerSession = {};
OnCallbacks("log", data => {
io.emit("ServerLog", {
UUID: SessionUUID,
data: data
});
Players_json.Promise_CreatePlayerJson(data, CurrentBdsPlatform).then(async Actions => {
if (typeof Actions !== "object") return;
if (Actions.length === 0) return;
Players_json.UpdateUserJSON(Actions);
io.emit("PlayerAction", Actions);
PlayersCallbacks.forEach(async callback => {
if (typeof callback === "function") return callback(Actions);
});
console.log(Actions);
Actions.forEach(UseAction => {
const { Player, Action, Date } = UseAction;
if (PlayerSession[Player] === undefined) {
PlayerSession[Player] = {
connected: Action === "connect",
history: [
{
Action,
Date
}
]
}
} else {
PlayerSession[Player].connected = Action === "connect";
PlayerSession[Player].history.push({
Action,
Date
});
}
});
});
});
/**
* Get Player connectes or not in the server.
*
* @returns {Object<string,{
* connected: boolean,
* history: Array<{
* Action: string,
* Date: string
* }>
* }>}
*/
const Players_in_Session = () => PlayerSession;
// Return
const SessionReturn = {
uuid: SessionUUID,
LogPath: LogFile,
StartTime: new Date(),
on: OnCallbacks,
PlayerAction: SessionPlayerAction,
stop: SessionStop,
SendCommand: SendCommand,
Uptime: () => UptimeNumber,
Players_in_Session: Players_in_Session,
ServerAction: {
op: SessionOp,
deop: SessionDeop,
ban: SessionBan,
kick: SessionKick,
tp: SessionTp,
say: SessionSay,
},
}
BackendServerManeger.ServerSessions.push(SessionReturn);
return SessionReturn;
}
module.exports.StartServer = StartServer;

View File

@ -1,390 +0,0 @@
var fs = require("fs");
const path = require("path");
const propertiesToJSON = require("properties-to-json");
const BdsSettings = require("../src/lib/BdsSettings");
const { GetPaths, CurrentPlatorm } = BdsSettings;
const TOML = require("@iarna/toml");
const nbt = require("prismarine-nbt");
const crypto = require("crypto");
function CreateConfigToBedrock(
WorldName = "Bedrock",
ServerMotd = "Hello, is my Minecraft Bedrock Sever",
DefaultGameMode = "creative",
ServerDifficulty = "normal",
LevelSeed = "",
AllowCheats = false,
ServerLimitPlayers = 20,
RequiredAccout = true,
EnableWhitelist = false,
ServerPort = 19132,
ServerPortV6 = 19132,
PlayerDefaultPermission = "member",
) {
return ([
"# By The Bds Maneger project",
`# Date: ${(new Date()).toString()}`,
"",
// World Settings
`level-name=${WorldName}`,
`server-name=${ServerMotd}`,
`gamemode=${DefaultGameMode}`,
`difficulty=${ServerDifficulty}`,
`level-seed=${LevelSeed}`,
`allow-cheats=${AllowCheats}`,
`max-players=${ServerLimitPlayers}`,
`online-mode=${RequiredAccout}`,
`white-list=${EnableWhitelist}`,
`server-port=${ServerPort}`,
`server-portv6=${ServerPortV6}`,
`default-player-permission-level=${PlayerDefaultPermission}`,
// Backend Maneger
"tick-distance=32",
"max-threads=8",
"view-distance=32",
"player-idle-timeout=0",
"texturepack-required=true",
"content-log-file-enabled=false",
"compression-threshold=1",
"server-authoritative-movement=server-auth",
"player-movement-score-threshold=20",
"player-movement-distance-threshold=0.3",
"player-movement-duration-threshold-in-ms=500",
"correct-player-movement=false",
"server-authoritative-block-breaking=false",
]).join("\n");
}
function CreateConfigToJava(
WorldName = "world",
ServerMotd = "Hello, is my Minecraft Java Sever",
DefaultGameMode = "creative",
ServerDifficulty = "normal",
LevelSeed = "",
AllowCheats = false,
ServerLimitPlayers = 20,
RequiredAccout = true,
EnableWhitelist = false,
ServerPort = 19132
) {
let HeadCore = false;
if (DefaultGameMode === "headcore") {
DefaultGameMode = "survival";
HeadCore = true;
}
return ([
"# By The Bds Maneger project",
`# Date: ${Date.now()}`,
"",
// World Settings
`level-name=${WorldName}`,
`motd=${ServerMotd}`,
`gamemode=${DefaultGameMode}`,
`difficulty=${ServerDifficulty}`,
`level-seed=${LevelSeed}`,
`enable-command-block=${AllowCheats}`,
`max-players=${ServerLimitPlayers}`,
`online-mode=${RequiredAccout}`,
`white-list=${EnableWhitelist}`,
`server-port=${ServerPort}`,
`hardcore=${HeadCore}`,
"level-type=default",
"op-permission-level=4",
"pvp=true",
"allow-nether=true",
// Rcon
"enable-rcon=false",
`rcon.password=${crypto.randomBytes(6).toString("hex")}`,
"rcon.port=25575",
"broadcast-rcon-to-ops=true",
// Anothers
"query.port=65551",
"enable-jmx-monitoring=false",
"enable-query=true",
"generator-settings=",
"generate-structures=true",
"network-compression-threshold=256",
"max-tick-time=60000",
"use-native-transport=true",
"enable-status=true",
"allow-flight=false",
"view-distance=32",
"max-build-height=256",
"server-ip=",
"sync-chunk-writes=true",
"prevent-proxy-connections=false",
"resource-pack=",
"entity-broadcast-range-percentage=100",
"player-idle-timeout=0",
"force-gamemode=false",
"rate-limit=0",
"broadcast-console-to-ops=true",
"spawn-npcs=true",
"spawn-animals=true",
"snooper-enabled=true",
"function-permission-level=2",
"text-filtering-config=",
"spawn-monsters=true",
"enforce-whitelist=false",
"resource-pack-sha1=",
"spawn-protection=16",
"max-world-size=29999984",
"require-resource-pack=true",
"resource-pack-prompt=",
"hide-online-players=false",
"simulation-distance=10",
]).join("\n");
}
// Set Config
async function bds_config(NewConfig = {world: "Bds Maneger", description: "The Bds Maneger", gamemode: "creative", difficulty: "normal", players: 10, commands: true, account: true, whitelist: true, port: 19132, portv6: 19133, seed: ""}, BdsPlatform = CurrentPlatorm()){
const JsonConfig = {
world: "Bds Maneger",
description: "The Bds Maneger",
gamemode: "creative",
difficulty: "normal",
players: 10,
commands: true,
account: true,
whitelist: false,
port: 19132,
portv6: 19133,
seed: ""
};
// Strings
if (typeof NewConfig.world === "string" && NewConfig.world) JsonConfig.world = NewConfig.world
if (typeof NewConfig.description === "string" && NewConfig.description) JsonConfig.description = NewConfig.description
if (typeof NewConfig.gamemode === "string" && NewConfig.gamemode) JsonConfig.gamemode = NewConfig.gamemode
if (typeof NewConfig.difficulty === "string" && NewConfig.difficulty) JsonConfig.difficulty = NewConfig.difficulty
if ((typeof NewConfig.seed === "string" || typeof NewConfig.seed === "number") && NewConfig.seed) JsonConfig.seed = NewConfig.seed
// Booleans
if (typeof NewConfig.commands === "boolean" && (NewConfig.commands || NewConfig.commands === false)) JsonConfig.commands = NewConfig.commands
if (typeof NewConfig.account === "boolean" && (NewConfig.account || NewConfig.account === false)) JsonConfig.account = NewConfig.account
if (typeof NewConfig.whitelist === "boolean" && (NewConfig.whitelist || NewConfig.whitelist === false)) JsonConfig.whitelist = NewConfig.whitelist
// Numbers
if (typeof NewConfig.port === "number" && NewConfig.port) JsonConfig.port = NewConfig.port
if (typeof NewConfig.players === "number" && NewConfig.players) JsonConfig.players = NewConfig.players
if (typeof NewConfig.portv6 === "number" && NewConfig.portv6) JsonConfig.portv6 = NewConfig.portv6
const Config = [];
if (BdsPlatform === "bedrock") {
const BedrockProperties = path.join(BdsSettings.GetPaths("bedrock", true), "server.properties");
const BedrockConfig = CreateConfigToBedrock(JsonConfig.world, JsonConfig.description, JsonConfig.gamemode, JsonConfig.difficulty, JsonConfig.seed, false, JsonConfig.players, JsonConfig.account, JsonConfig.whitelist, JsonConfig.port, JsonConfig.portv6);
fs.writeFileSync(BedrockProperties, BedrockConfig);
return BedrockConfig;
} else if (BdsPlatform === "java") {
const JavaProperties = path.join(BdsSettings.GetPaths("java", true), "server.properties");
const JavaConfig = CreateConfigToJava(JsonConfig.world, JsonConfig.description, JsonConfig.gamemode, JsonConfig.difficulty, JsonConfig.seed, false, JsonConfig.players, JsonConfig.account, JsonConfig.whitelist, JsonConfig.port, JsonConfig.portv6);
fs.writeFileSync(JavaProperties, JavaConfig);
return JavaConfig;
} else if (BdsPlatform === "dragonfly") {
Config.push(
"",
"[Network]",
` Address = ":${JsonConfig.port}"`,
"",
"[Players]",
" Folder = \"players\"",
" MaxCount = 0",
" MaximumChunkRadius = 32",
" SaveData = true",
"",
"[Resources]",
" Folder = \"resources\"",
"",
"[Server]",
" AuthEnabled = true",
" JoinMessage = \"%v has joined the game\"",
` Name = "${JsonConfig.description}"`,
" QuitMessage = \"%v has left the game\"",
" ShutdownMessage = \"Server closed.\"",
"",
"[World]",
" Folder = \"world\"",
` Name = "${JsonConfig.world}"`,
" SimulationDistance = 8",
""
);
} else if (BdsPlatform === "pocketmine") {
// Whitelist
if (JsonConfig.whitelist === true) JsonConfig.whitelist = "on";
else JsonConfig.whitelist = "off";
// difficulty
if (JsonConfig.difficulty === "easy") JsonConfig.difficulty = 0;
else if (JsonConfig.difficulty === "peaceful") JsonConfig.difficulty = 1;
else if (JsonConfig.difficulty === "normal") JsonConfig.difficulty = 2;
else if (JsonConfig.difficulty === "hard") JsonConfig.difficulty = 3;
else throw new Error("Difficulty error");
// Required Accoutn
if (JsonConfig.account === true) JsonConfig.account = "on";
else JsonConfig.account = "off";
// Config
Config.push(
"# By The Bds Maneger project",
`# Date: ${Date.now()}`,
"",
"language=eng",
`level-name=${JsonConfig.world}`,
`motd=${JsonConfig.description}`,
`server-port=${JsonConfig.port}`,
`white-list=${JsonConfig.whitelist}`,
`max-players=${JsonConfig.players}`,
`gamemode=${JsonConfig.gamemode}`,
`difficulty=${JsonConfig.difficulty}`,
`xbox-auth=${JsonConfig.account}`,
`level-seed=${JsonConfig.seed}`,
"view-distance=32",
"hardcore=0",
"announce-player-achievements=on",
"spawn-protection=16",
"force-gamemode=off",
"pvp=on",
"generator-settings=",
"level-type=DEFAULT",
"enable-query=on",
"enable-rcon=off",
"rcon.password=F/deZ5kefY",
"auto-save=on",
);
}
throw new Error("Backend Reject Instruction");
// fs.writeFileSync(ConfigFilePath[BdsPlatform], Config.join("\n"))
return Config.join("\n");
}
// Get Config
async function bds_get_config(){
const BdsPlatform = CurrentPlatorm();
var config;
const JsonConfig = {
world: "",
description: "",
gamemode: "",
difficulty: "",
players: 0,
whitelist: false,
portv4: 0,
portv6: 0,
nbt: {}
};
if (BdsPlatform === "bedrock") {
const BedrockProperties = path.join(BdsSettings.GetPaths("bedrock", true), "server.properties");
if (fs.existsSync(BedrockProperties)) {
config = propertiesToJSON(fs.readFileSync(BedrockProperties, "utf8"));
// Players
JsonConfig.world = config["level-name"];
JsonConfig.description = config["server-name"];
JsonConfig.gamemode = config["gamemode"];
JsonConfig.difficulty = config["difficulty"];
JsonConfig.players = parseInt(config["max-players"]);
JsonConfig.account = (config["online-mode"] === "true");
JsonConfig.whitelist = (config["white-list"] === "true");
// Server/World
JsonConfig.portv4 = parseInt(config["server-port"]);
JsonConfig.portv6 = parseInt(config["server-portv6"]);
JsonConfig.seed = config["level-seed"];
JsonConfig.commands = (config["allow-cheats"] === "true");
// JsonConfig.worldtype = "default";
const BedrockLevelData = path.join(GetPaths("bedrock", true), "worlds", JsonConfig.world, "level.dat");
if (fs.existsSync(BedrockLevelData)) JsonConfig.nbt = (await nbt.parse(fs.readFileSync(BedrockLevelData))).parsed.value;
}
}
else if (BdsPlatform === "java") {
const JavaProperties = path.join(BdsSettings.GetPaths("java", true), "server.properties");
if (fs.existsSync(JavaProperties)) {
config = propertiesToJSON(fs.readFileSync(JavaProperties, "utf8"));
// Players
JsonConfig.world = config["level-name"];
JsonConfig.description = config["motd"];
JsonConfig.gamemode = config["gamemode"];
JsonConfig.difficulty = config["difficulty"];
JsonConfig.players = parseInt(config["max-players"]);
JsonConfig.account = (config["online-mode"] === "true");
JsonConfig.whitelist = (config["white-list"] === "true");
// Server/World
JsonConfig.portv4 = parseInt(config["server-port"]);
JsonConfig.portv6 = parseInt(config["server-port"]);
JsonConfig.seed = config["level-seed"];
JsonConfig.commands = (config["enable-command-block"] === "true");
const ParsedNBTJava = (await nbt.parse(fs.readFileSync(path.join(GetPaths("java", true), JsonConfig.world, "level.dat")))).parsed.value;
JsonConfig.nbt = ParsedNBTJava.Data.value||ParsedNBTJava.Data||ParsedNBTJava;
}
}
else if (BdsPlatform === "pocketmine") {
const PocketMineProperties = path.join(BdsSettings.GetPaths("pocketmine", true), "server.properties");
if (fs.existsSync(PocketMineProperties)) {
config = propertiesToJSON(fs.readFileSync(PocketMineProperties, "utf8"));
// Players
JsonConfig.world = config["level-name"];
JsonConfig.description = config["motd"];
// Gamemode
if (parseInt(config["gamemode"]) === 0) JsonConfig.gamemode = "survival";
else if (parseInt(config["gamemode"]) === 1) JsonConfig.gamemode = "creative";
else JsonConfig.gamemode = "";
// Difficulty
if (parseInt(config["difficulty"]) === 0) JsonConfig.difficulty = "easy";
else if (parseInt(config["difficulty"]) === 1) JsonConfig.difficulty = "peaceful";
else if (parseInt(config["difficulty"]) === 2) JsonConfig.difficulty = "normal";
else if (parseInt(config["difficulty"]) === 3) JsonConfig.difficulty = "hard";
else JsonConfig.difficulty = "";
JsonConfig.players = parseInt(config["max-players"]);
JsonConfig.account = (config["xbox-auth"] === "on");
JsonConfig.whitelist = (config["white-list"] === "true");
// Server/World
JsonConfig.portv4 = parseInt(config["server-port"]);
JsonConfig.portv6 = parseInt(config["server-port"]);
JsonConfig.seed = config["level-seed"];
JsonConfig.commands = false;
// JsonConfig.worldtype = config["level-type"];
const PocketmineLevelData = path.join(GetPaths("pocketmine", true), "worlds", JsonConfig.world, "level.dat");
if (fs.existsSync(PocketmineLevelData)) JsonConfig.nbt = (await nbt.parse(fs.readFileSync(PocketmineLevelData))).parsed.value;
}
} else if (BdsPlatform === "dragonfly") {
const DragonflyProperties = path.join(BdsSettings.GetPaths("dragonfly", true), "server.properties");
if (fs.existsSync(DragonflyProperties)) {
const ConfigFile = TOML.parse(fs.readFileSync(DragonflyProperties, "utf8"));
JsonConfig.world = ConfigFile.World.Name;
JsonConfig.description = ConfigFile.Server.Name;
JsonConfig.gamemode = "creative";
JsonConfig.difficulty = null;
JsonConfig.players = parseInt(ConfigFile.Players.MaxCount || 0);
JsonConfig.account = false;
JsonConfig.whitelist = null;
JsonConfig.portv4 = parseInt(ConfigFile.Network.Address.replace(":", ""));
JsonConfig.portv6 = parseInt(ConfigFile.Network.Address.replace(":", ""));
JsonConfig.seed = null;
JsonConfig.commands = false;
}
}
return JsonConfig;
}
// Get Withelist
async function bds_get_whitelist(BdsPlatform = CurrentPlatorm()){
const ReturnArrayWithPlayers = [];
if (BdsPlatform === "bedrock") {}
return ReturnArrayWithPlayers;
}
// Export modules
module.exports.set_config = bds_config;
module.exports.config = bds_config;
module.exports.get_config = bds_get_config;
module.exports.get_whitelist = bds_get_whitelist;

View File

@ -0,0 +1,593 @@
/**
* Original file url: https://github.com/chegele/BDSAddonInstaller/blob/6e9cf7334022941f8007c28470eb1e047dfe0e90/index.js
* License: No license provided.
* Github Repo: https://github.com/chegele/BDSAddonInstaller
*
* Patch by Sirherorine23 (Matheus Sampaio Queirora) <srherobrine20@gmail.com>
*/
import os from "os";
import path from "path";
import admZip from "adm-zip";
import fs from "fs";
// import stripJsonComments from "strip-json-comments";
const stripJsonComments = (data) => data.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m);
function ensureFileSync(pathFile: string){
if (!fs.existsSync(pathFile)){
if (!fs.existsSync(path.parse(pathFile).dir)) fs.mkdirSync(path.parse(pathFile).dir, {recursive: true});
fs.writeFileSync(pathFile, "");
}
}
// Below variables are updated by the constructor.
// All paths will be converted to full paths by including serverPath at the beginning.
let serverPath = null;
let worldName = null;
const providedServerPath = path.resolve(process.env.SERVER_PATH||path.join(os.homedir(), "bds_core/servers"), "bedrock");
const addonPath = path.resolve(providedServerPath, "../BDS-Addons/");
if (!(fs.existsSync(addonPath))) fs.mkdirSync(addonPath, {recursive: true});
let serverPacksJsonPath = "valid_known_packs.json";
let serverPacksJSON = null;
let serverResourcesDir = "resource_packs/";
let serverBehaviorsDir = "behavior_packs/";
let worldResourcesJsonPath = "worlds/<worldname>/world_resource_packs.json";
let worldResourcesJSON = null;
let worldBehaviorsJsonPath = "worlds/<worldname>/world_behavior_packs.json";
let worldBehaviorsJSON = null;
let worldResourcesDir = "worlds/<worldname>/resource_packs/";
let worldBehaviorsDir = "worlds/<worldname>/behavior_packs/";
// Below variables updated by mapInstalledPacks function.
// Updated to contain installed pack info {name, uuid, version, location}
let installedServerResources = new Map();
let installedServerBehaviors = new Map();
let installedWorldResources = new Map();
let installedWorldBehaviors = new Map();
// These files will be validated to confirm the provided serverPath is accurate.
const requiredFiles = ["behavior_packs", "resource_packs", "valid_known_packs.json"];
/**
* Prepares to install addons for the provided Bedrock Dedicated Server.
*/
export function addonInstaller() {
// const providedServerPath = path.resolve(process.env.SERVER_PATH||path.join(os.homedir(), "bds_core/servers"), "bedrock");
// Validate server path (path is provided, path is valid, path contains required files)
if (!providedServerPath) throw new Error("You must provide a server path for BDSAddonInstaller");
if (!fs.existsSync(providedServerPath)) throw new Error("The provided server path does not exist.\n" + providedServerPath);
requiredFiles.forEach(file => {
let filePath = path.join(providedServerPath, file);
if (!fs.existsSync(filePath)) throw new Error("Unable to find server files in provided path.\n" + filePath);
});
// Update all module paths from relative to full paths.
serverPath = providedServerPath;
// addonPath = path.join(providedServerPath, addonPath);
worldName = readWorldName();
worldResourcesJsonPath = path.join(serverPath, worldResourcesJsonPath.replace("<worldname>", worldName));
worldBehaviorsJsonPath = path.join(serverPath, worldBehaviorsJsonPath.replace("<worldname>", worldName));
worldResourcesDir = path.join(serverPath, worldResourcesDir.replace("<worldname>", worldName));
worldBehaviorsDir = path.join(serverPath, worldBehaviorsDir.replace("<worldname>", worldName));
serverPacksJsonPath = path.join(serverPath, serverPacksJsonPath);
serverResourcesDir = path.join(serverPath, serverResourcesDir);
serverBehaviorsDir = path.join(serverPath, serverBehaviorsDir);
// Create JSON files if they do not exists
ensureFileSync(serverPacksJsonPath);
ensureFileSync(worldResourcesJsonPath);
ensureFileSync(worldBehaviorsJsonPath);
// Read installed packs from JSON files & attempt to parse content.
let serverPackContents = fs.readFileSync(serverPacksJsonPath, "utf8");
let worldResourceContents = fs.readFileSync(worldResourcesJsonPath, "utf8");
let worldBehaviorContents = fs.readFileSync(worldBehaviorsJsonPath, "utf8");
// If there is an error parsing JSON assume no packs installed and use empty array.
try { serverPacksJSON = JSON.parse(serverPackContents) } catch(err) { serverPacksJSON = [] };
try { worldResourcesJSON = JSON.parse(worldResourceContents) } catch(err) { worldResourcesJSON = [] };
try { worldBehaviorsJSON = JSON.parse(worldBehaviorContents) } catch(err) { worldBehaviorsJSON = [] };
// If unexpected results from parsing JSON assume no packs installed and use empty array.
if (!Array.isArray(serverPacksJSON)) serverPacksJSON = [];
if (!Array.isArray(worldResourcesJSON)) worldResourcesJSON = [];
if (!Array.isArray(worldBehaviorsJSON)) worldBehaviorsJSON = [];
// Map installed packs from install directories
installedServerResources = mapInstalledPacks(serverResourcesDir);
installedServerBehaviors = mapInstalledPacks(serverBehaviorsDir);
installedWorldResources = mapInstalledPacks(worldResourcesDir);
installedWorldBehaviors = mapInstalledPacks(worldBehaviorsDir);
/**
* Installs the provide addon/pack to the BDS server and the active world.
* @param {String} packPath - The full path to the mcpack or mcaddon file.
*/
async function installAddon(packPath: string) {
// Validate provided pack (pack exists & is the correct file type)
if (!fs.existsSync(packPath)) throw new Error("Unable to install pack. The provided path does not exist. " + packPath);
if (!packPath.endsWith(".mcpack") && !packPath.endsWith(".mcaddon")) throw new Error("Unable to install pack. The provided file is not an addon or pack. " + packPath);
if (packPath.endsWith(".mcaddon")) {
// If the provided pack is an addon extract packs and execute this function again for each one.
let packs = await extractAddonPacks(packPath);
for (const pack of packs) await this.installAddon(pack);
return;
}
// Gather pack details from the manifest.json file
let manifest = await extractPackManifest(packPath);
// let name = manifest.header.name.replace(/\W/g, "");
let uuid = manifest.header.uuid;
let version = manifest.header.version;
if (!version) version = manifest.header.modules[0].version;
let type;
if (manifest.modules) {
type = manifest.modules[0].type.toLowerCase();
} else if (manifest.header.modules) {
type = manifest.header.modules[0].type.toLowerCase();
}else {
throw new Error("Unable to install pack. Unknown pack manifest format.\n" + packPath);
}
// console.log("BDSAddonInstaller - Installing " + name + "...");
// Check if already installed
let installedWorldPack, installedServerPack = null;
if (type == "resources") {
installedWorldPack = installedWorldResources.get(uuid);
installedServerPack = installedServerResources.get(uuid);
}else if (type == "data") {
installedWorldPack = installedWorldBehaviors.get(uuid);
installedServerPack = installedServerBehaviors.get(uuid)
}
// Check if current installed packs are up to date
if (installedWorldPack || installedServerPack) {
let upToDate = true;
if (installedWorldPack && installedWorldPack.version.toString() != version.toString()) upToDate = false;
if (installedServerPack && installedServerPack.version.toString() != version.toString()) upToDate = false;
if (upToDate) {
// console.log(`BDSAddonInstaller - The ${name} pack is already installed and up to date.`);
return;
}else{
// uninstall pack if not up to date
// console.log("BDSAddonInstaller - Uninstalling old version of pack");
if (installedServerPack) await uninstallServerPack(uuid, installedServerPack.location);
if (installedWorldPack && type == "resources") await uninstallWorldResource(uuid, installedWorldPack.location);
if (installedWorldPack && type == "data") await uninstallWorldBehavior(uuid, installedWorldPack.location);
}
}
await installPack(packPath, manifest);
// console.log("BDSAddonInstaller - Successfully installed the " + name + " pack.");
}
/**
* Installs all of the addons & packs found within the BDS-Addons directory.
* NOTE: Running this function with remove packs is only recommended if facing issues.
*/
async function installAllAddons(removeOldPacks: boolean) {
// If chosen, uninstall all world packs.
if (removeOldPacks) await uninstallAllWorldPacks();
// Read all packs & addons from BDS-Addon directory.
let packs = fs.readdirSync(addonPath);
// Get the full path of each addon/pack and install it.
for (let pack of packs) {
try {
let location = path.join(addonPath, pack);
await this.installAddon(location);
}catch(err) {
// console.error("BDSAddonInstaller - " + err);
}
}
}
return {
installAddon,
installAllAddons
};
}
////////////////////////////////////////////////////////////////
// BDSAddonInstaller - Install & Uninstall functions
/**
* Installs the provided pack to the world and Bedrock Dedicated Server.
* @param {String} packPath - The path to the pack to be installed.
* @param {Object} manifest - The pre-parsed manifest information for the pack.
*/
async function installPack(packPath, manifest) {
// Extract manifest information
let name = manifest.header.name.replace(/\W/g, "");
let uuid = manifest.header.uuid;
let version = manifest.header.version;
if (!version) version = manifest.header.modules[0].version;
let type;
if (manifest.modules) {
type = manifest.modules[0].type.toLowerCase();
} else if (manifest.header.modules) {
type = manifest.header.modules[0].type.toLowerCase();
}else {
throw new Error("Unable to install pack. Unknown pack manifest format.\n" + packPath);
}
// Create placeholder variables for pack installation paths.
let installServerPath, installWorldPath, WorldPacksJSON, WorldPacksPath, rawPath = null;
// Update variables based on the pack type.
if (type == "data") {
installServerPath = path.join(serverBehaviorsDir, name);
installWorldPath = path.join(worldBehaviorsDir, name);
WorldPacksJSON = worldBehaviorsJSON;
WorldPacksPath = worldBehaviorsJsonPath;
rawPath = "behavior_packs/" + name;
}else if (type == "resources") {
installServerPath = path.join(serverResourcesDir, name);
installWorldPath = path.join(worldResourcesDir, name);
WorldPacksJSON = worldResourcesJSON;
WorldPacksPath = worldResourcesJsonPath;
rawPath = "resource_packs/" + name;
}else {
throw new Error("Unknown pack type, " + type);
}
// Install pack to the world.
let worldPackInfo = {"pack_id": uuid, "version": version}
WorldPacksJSON.unshift(worldPackInfo);
await promiseExtract(packPath, installWorldPath);
fs.writeFileSync(WorldPacksPath, JSON.stringify(WorldPacksJSON, undefined, 2));
// Install pack to the server.
version = `${version[0]}.${version[1]}.${version[2]}`;
let serverPackInfo = {"file_system": "RawPath", "path": rawPath, "uuid": uuid, "version": version};
serverPacksJSON.splice(1, 0, serverPackInfo);
await promiseExtract(packPath, installServerPath);
fs.writeFileSync(serverPacksJsonPath, JSON.stringify(serverPacksJSON, undefined, 2));
}
/**
* Uninstall all resource and behavior packs from the Minecraft world.
* If the server also has the pick it will also be uninstalled.
* NOTE: Vanilla packs can"t be safely removed from the server packs & there is no way to differentiate vanilla and added packs.
* NOTE: This is why only packs found installed to the world will be removed from the server.
*/
async function uninstallAllWorldPacks() {
// console.log("BDSAddonInstaller - Uninstalling all packs found saved to world.");
// Uninstall all cached world resource packs.
for (let pack of installedWorldResources.values()) {
await uninstallWorldResource(pack.uuid, pack.location);
let serverPack = installedServerResources.get(pack.uuid);
if (serverPack) await uninstallServerPack(pack.uuid, serverPack.location);
}
// Uninstall all cached world behavior packs.
for (let pack of installedWorldBehaviors.values()) {
await uninstallWorldBehavior(pack.uuid, pack.location);
let serverPack = installedServerBehaviors.get(pack.uuid);
if (serverPack) await uninstallServerPack(pack.uuid, serverPack.location);
}
// All packs are cached by the constructor.
// Reload world packs after uninstall.
installedServerResources = mapInstalledPacks(serverResourcesDir);
installedServerBehaviors = mapInstalledPacks(serverBehaviorsDir);
installedWorldResources = mapInstalledPacks(worldResourcesDir);
installedWorldBehaviors = mapInstalledPacks(worldBehaviorsDir);
}
// TODO: uninstallWorldResource, uninstallWorldBehavior, and uninstallServerPack share the same logic.
// These functions can be merged into one function using an additional argument for pack type.
/**
* Uninstalls the pack from the world_resource_packs.json by uuid & deletes the provided pack path.
* @param {String} uuid - The id of the pack to remove from the world_resource_packs.json file.
* @param {String} location - The path to the root directory of the installed pack to be deleted.
* WARNING: No validation is done to confirm that the provided path is a pack.
*/
async function uninstallWorldResource(uuid, location) {
// Locate the pack in the manifest data.
let packIndex = findIndexOf(worldResourcesJSON, "pack_id", uuid);
// Remove the pack data and update the json file.
if (packIndex != -1) {
worldResourcesJSON.splice(packIndex, 1);
fs.writeFileSync(worldResourcesJsonPath, JSON.stringify(worldResourcesJSON, undefined, 2));
// console.log(`BDSAddonInstaller - Removed ${uuid} from world resource packs JSON.`);
}
// Delete the provided pack path.
if (fs.existsSync(location)) {
await fs.promises.rm(location, {recursive: true});
// console.log(`BDSAddonInstaller - Removed ${location}`);
}
}
/**
* Uninstalls the pack from the world_behavior_packs.json by uuid & deletes the provided pack path.
* @param {String} uuid - The id of the pack to remove from the world_behavior_packs.json file.
* @param {String} location - The path to the root directory of the installed pack to be deleted.
* WARNING: No validation is done to confirm that the provided path is a pack.
*/
async function uninstallWorldBehavior(uuid, location) {
// Locate the pack in the manifest data.
let packIndex = findIndexOf(worldBehaviorsJSON, "pack_id", uuid);
// Remove the pack data and update the json file.
if (packIndex != -1) {
worldBehaviorsJSON.splice(packIndex, 1);
fs.writeFileSync(worldBehaviorsJsonPath, JSON.stringify(worldBehaviorsJSON, undefined, 2));
// console.log(`BDSAddonInstaller - Removed ${uuid} from world behavior packs JSON.`);
}
// Delete the provided pack path.
if (fs.existsSync(location)) {
fs.promises.rm(location);
// console.log(`BDSAddonInstaller - Removed ${location}`);
}
}
/**
* Uninstalls the pack from the valid_known_packs.json by uuid & deletes the provided pack path.
* @param {String} uuid - The id of the pack to remove from the valid_known_packs.json file.
* @param {String} location - The path to the root directory of the installed pack to be deleted.
* WARNING: No validation is done to confirm that the provided path is a pack.
*/
async function uninstallServerPack (uuid, location) {
// Locate the pack in the manifest data.
let packIndex = findIndexOf(serverPacksJSON, "uuid", uuid);
// Remove the pack data and update the json file.
if (packIndex != -1) {
serverPacksJSON.splice(packIndex, 1);
fs.writeFileSync(serverPacksJsonPath, JSON.stringify(serverPacksJSON, undefined, 2));
// console.log(`BDSAddonInstaller - Removed ${uuid} from server packs JSON.`);
}
// Delete the provided pack path.
if (fs.existsSync(location)) {
fs.promises.rm(location);
// console.log(`BDSAddonInstaller - Removed ${location}`);
}
}
///////////////////////////////////////////////////////////
// BDSAddonInstaller misc functions
/**
* Extracts bundled packs from the provided addon file.
* This will only need to be ran once on an addon as it will convert the addon to multiple .mcpack files.
* @param {String} addonPath - The path of the addon file to extract packs from.
*/
async function extractAddonPacks(addonPath) {
// Validate the provided path is to an addon.
if (!fs.existsSync(addonPath)) throw new Error("Unable to extract packs from addon. Invalid file path provided: " + addonPath);
if (!addonPath.endsWith('.mcaddon')) throw new Error('Unable to extract packs from addon. The provided file is not an addon. ' + addonPath);
// console.log("BDSAddonInstaller - Extracting packs from " + addonPath);
// Extract file path and name info for saving the extracted packs.
let addonName = path.basename(addonPath).replace(".mcaddon", "");
let dirPath = path.dirname(addonPath);
// Create a temp location and extract the addon contents to it.
let tempLocation = path.join(dirPath, "tmp/", addonName + "/");
await promiseExtract(addonPath, tempLocation);
let packs = fs.readdirSync(tempLocation);
let results = [];
// Move addon packs from temporary location to BDS-Addon directory.
for (let pack of packs) {
// console.log(`BDSAddonInstaller - Extracting ${pack} from ${addonName}.`);
// If the mcpack is already packaged, move the file.
if (pack.endsWith(".mcpack")) {
let packName = addonName + "_" + pack;
let packFile = path.join(tempLocation, pack);
let packDestination = path.join(dirPath, packName);
await fs.promises.rename(packFile, packDestination);
results.push(packDestination);
// console.log("BDSAddonInstaller - Extracted " + packDestination);
}else {
// The pack still needs to be zipped and then moved.
let packName = addonName + "_" + pack + ".mcpack";
let packFolder = path.join(tempLocation, pack);
let packDestination = path.join(dirPath, packName);
await promiseZip(packFolder, packDestination);
results.push(packDestination);
// console.log("BDSAddonInstaller - Extracted " + packDestination);
}
}
// Remove temporary files and old addon.
await fs.promises.rm(path.join(dirPath, "tmp/"), {recursive: true});
await fs.promises.unlink(addonPath);
// Return an array of paths to the extracted packs.
return results;
}
/**
* Extracts the manifest data as an object from the provided .mcpack file.
* @param {String} packPath - The path to the pack to extract the manifest from.
* @returns {Object} The parsed manifest.json file.
*/
function extractPackManifest(packPath) {
// Validate the provided pack (path exists and file is correct type)
if (!fs.existsSync(packPath)) throw new Error("Unable to extract manifest file. Invalid file path provided: " + packPath);
if (!packPath.endsWith(".mcpack")) throw new Error("Unable to extract manifest file. The provided file is not a pack. " + packPath);
// console.log("BDSAddonInstaller - Reading manifest data from " + packPath);
// Locate the manifest file in the zipped pack.
let archive = new admZip(packPath);
let manifest = archive.getEntries().filter(entry => entry.entryName.endsWith("manifest.json") || entry.entryName.endsWith("pack_manifest.json"));
if (!manifest[0]) throw new Error("Unable to extract manifest file. It does not exist in this pack. " + packPath);
// Read the manifest and return the parsed JSON.
return JSON.parse(stripJsonComments(archive.readAsText(manifest[0].entryName)));
}
/**
* Reads the world name from a BDS server.properties file.
* @returns {String} The value found for level-name from server.properties.
* NOTE: This function is Synchronous for use in the constructor without need for a callback.
*/
function readWorldName() {
let propertyFile = path.join(serverPath, "server.properties");
// console.log("BDSAddonInstaller - Reading world name from " + propertyFile);
if (!fs.existsSync(propertyFile)) throw new Error("Unable to locate server properties @ " + propertyFile);
let properties = fs.readFileSync(propertyFile);
let levelName = properties.toString().match(/level-name=.*/);
if (!levelName) throw new Error("Unable to retrieve level-name from server properties.");
return levelName.toString().replace("level-name=", "");
}
/**
* Collects manifest information from all installed packs in provided location.
* @param {String} directory - The path to the directory containing extracted/installed packs.
* @returns {Map<PackData>} A collection of manifest information with the uuid as the key.
*
* Bug Note:
* Some of the vanilla packs are installed multiple times using the same uuid but different versions.
* This causes the map to only capture the last read pack with that uuid.
* This bug should not impact the installer, as there wont be a need to install / update vanilla packs.
*
* NOTE: This function is Synchronous for use in the constructor without need for a callback.
*/
function mapInstalledPacks(directory) {
// The provided directory may not exist if the world has no packs installed.
// Create the results Map & return empty if the directory does not exist.
let results = new Map();
if (!fs.existsSync(directory)) return results;
// Extract manifest & path information for each installed pack
let subdirectories = fs.readdirSync(directory);
subdirectories.forEach(subdirectory => {
let location = path.join(directory, subdirectory);
// console.log("BDSAddonInstaller - Reading manifest data from " + location);
// Locate the directory containing the pack manifest.
let manifestLocation = findFilesSync(["manifest.json", "pack_manifest.json"], location);
if (!manifestLocation) {
// console.error(manifestLocation);
// console.warn("BDSAddonInstaller - Unable to locate manifest file of installed pack.");
// console.warn("BDSAddonInstaller - Installed location: " + location);
return;
}
// Check if pack is using a manifest.json or pack.manifest.json
let filePath = path.join(manifestLocation, "manifest.json");
if (!fs.existsSync(filePath)) filePath = path.join(manifestLocation, "pack_manifest.json");
let file = fs.readFileSync(filePath, "utf8");
// Some vanilla packs have comments in them, this is not valid JSON and needs to be removed.
file = stripJsonComments(file.toString());
let manifest = JSON.parse(file);
// Collect and map the manifest information
let uuid = manifest.header.uuid;
let name = manifest.header.name;
let version = manifest.header.version;
if (!version) version = manifest.header.modules[0].version;
results.set(uuid, {name, uuid, version, location});
});
return results;
}
////////////////////////////////////////////////////////////////////
// Misc helper functions
/**
* Finds the first index of a key value pair from an array of objects.
* @param {Object[]} objectArray - An array of objects to search.
* @param {String} key - The key to match the value against.
* @param {*} value - The value to find the index of.
* @returns {Number} - The index of the key value pair or -1.
*/
function findIndexOf(objectArray, key, value) {
for (let index = 0; index < objectArray.length; index++) {
if (objectArray[index][key] == value) return index;
}
return -1;
}
/**
* Extracts all of the contents from a provided .zip archive.
* @param {String} file - The file to extract the contents from.
* @param {String} destination - The directory to unzip the contents into.
*/
function promiseExtract(file, destination) {
return new Promise(function(resolve, reject) {
let archive = new admZip(file);
archive.extractAllToAsync(destination, true, err => {
if (err) return reject(err);
resolve("");
});
});
}
/**
* Compresses contents of the provided folder using ADM Zip.
* @param {String} folder - The folder containing folder containing the files to compress.
* @param {String} destinationFile - The file to save the archive as.
*/
function promiseZip(folder, destinationFile) {
return new Promise(async function(resolve, reject) {
let archive = new admZip();
let contents = await fs.promises.readdir(folder);
for (let file of contents) {
let filePath = path.join(folder, file);
let stat = await fs.promises.stat(filePath);
stat.isFile() ? archive.addLocalFile(filePath) : archive.addLocalFolder(filePath, file);
}
archive.writeZip(destinationFile, err => {
if (err) return reject(err);
resolve("");
});
});
}
/**
* Attempt to locate the subdirectory containing one of the provided file names.
* @param {String[]} filenames - The name of files to search for.
* @param {String} directory - The directory to search in.
* @returns {String} The path to the first folder containing one of the files or null.
*/
function findFilesSync(filenames, directory) {
// Get the contents of the directory and see if it includes one of the files.
const contents = fs.readdirSync(directory);
for (let file of contents) {
if (filenames.includes(file)) return directory;
}
// If unable to find one of the files, check subdirectories.
for (let subDir of contents) {
let dirPath = path.join(directory, subDir);
let stat = fs.statSync(dirPath);
if (stat.isDirectory()) {
let subDirectoryResult = findFilesSync(filenames, dirPath);
if (subDirectoryResult) return subDirectoryResult;
}
}
// Unable to find the files.
return null;
}
//TODO: Add type definitions for the manifest files.
/**
* @typedef {Object} PackData - Information extracted from an installed pack.
* @property {String} name - The name found in the packs manifest.json file.
* @property {String} uuid - The uuid found in the packs manifest.json file.
* @property {String} version - the version found in the packs manifest.json fle.
* @property {String} location - The full path to the root directory of the installed pack.
* Used by the mapInstalledPacks function
*/

4
src/addons/index.ts Normal file
View File

@ -0,0 +1,4 @@
import * as bedrock from "./bedrock/install";
export default {bedrock};
export {bedrock};

View File

@ -1,100 +0,0 @@
const express = require("express");
const TokenManeger = require("./lib/Token");
const bodyParser = require("body-parser");
const fileUpload = require("express-fileupload");
const pretty = require("express-prettify");
const cors = require("cors");
const express_rate_limit = require("express-rate-limit");
const request_ip = require("request-ip");
const app = express();
app.use(cors());
app.use(bodyParser.json()); /* https://github.com/github/fetch/issues/323#issuecomment-331477498 */
app.use(bodyParser.urlencoded({ extended: true }));
app.use(pretty({always: true, spaces: 2}));
app.use(fileUpload({limits: { fileSize: 512 * 1024 }}));
app.use(request_ip.mw());
app.use(express_rate_limit({
windowMs: 1 * 60 * 1000, // 1 minutes
max: 500 // limit each IP to 500 requests per windowMs
}));
// Init Socket.io
const Server = require("http").createServer(app);
const SocketIo = require("socket.io");
const io = new SocketIo.Server(Server, {
cors: {
origin: "*"
}
});
io.use(function (socket, next) {
const { headers, query } = socket.handshake;
const Token = headers["authorizationtoken"] || query["token"] || query["Token"];
try {
if (TokenManeger.CheckToken(Token, "all")) {
socket.token = Token;
return next();
}
} catch (e) {
return next(e);
}
return next(new Error("Token is not valid"));
});
module.exports.SocketIO = io;
const BdsRoute = require("./api/ServerHost");
app.use("/", BdsRoute);
const PlayersRoute = require("./api/Players");
app.use("/players", TokenManeger.ExpressCheckToken, PlayersRoute);
const Plugins = require("./api/Plugins");
app.use("/plugins", TokenManeger.ExpressCheckToken, Plugins);
const ParseRoutes = (app, RootRoute="") => {
const RoutesArray = [];
for (const Route of [...(app.stack||[]), ...((app._router||{}).stack||[])]) {
if (Route.route) {
if (Route.route.path && typeof Route.route.path === "string") {
if (Object.keys(Route.route.methods).length) {
RoutesArray.push(`[${Object.keys(Route.route.methods)[0]}]: ${RootRoute}${Route.route.path}`);
} else RoutesArray.push(`${RootRoute}`+Route.route.path);
} else if (Route.route.paths && typeof Route.route.paths === "object") {
let Method = null;
if (Object.keys(Route.route.methods).length) Method = Object.keys(Route.route.methods)[0]
for (let Path of Route.route.paths) {
RoutesArray.push(`[${Method ? Method : "?"}]: ${RootRoute}${Path}`);
}
}
} else if (Route.path && typeof Route.path === "string") RoutesArray.push(`${RootRoute}`+Route.path);
}
return RoutesArray;
}
/**
* Launch an API To manage the server Remotely, some features are limited.
*/
function BdsApiListen(port_api = 3000, callback = (port = 0) => {return port;}){
app.all("*", (req, res) => {
const MapRoutes = ([
...(ParseRoutes(BdsRoute)),
...(ParseRoutes(Plugins, "/plugins")),
...(ParseRoutes(PlayersRoute, "/players")),
...(ParseRoutes(app)),
]).map(As => {const Data = {Method: "", Path: ""};As.replace(/\[(.*)\]: (.*)/gi, (_, Method, Path) => {Data.Method = Method; Data.Path = Path; return _;});return Data;});
return res.status(404).json({
error: "Not Found",
message: `The requested URL ${req.originalUrl} was not found on this server.`,
AvaibleRoutes: MapRoutes
});
});
const port = (port_api || 3000);
Server.listen(port, () => {
if (typeof callback === "function") callback(port);
});
return;
}
module.exports.api = BdsApiListen;
module.exports.Listen = Server.listen;
module.exports.BdsRoutes = app;

77
src/api.ts Normal file
View File

@ -0,0 +1,77 @@
import express from "express";
import cors from "cors";
import * as ServerManeger from "./server";
import { isDate } from "util/types";
const app = express();
app.use(cors());
app.use(express.urlencoded({extended: true}));
app.use(express.json());
app.use((req, res, next) => {
res.json = (body) => {
res.set("Content-Type", "application/json");
res.send(JSON.stringify(body, (key, value) => {
if (typeof value === "bigint") value = value.toString();
else if (isDate(value)) value = value.toString();
return value;
}, 2));
return res;
}
return next();
});
export function listen(port: number|string) {app.listen(port, () => console.log("API Listening on port %s", port));}
// Get Sessions
app.all("/", ({res}) => res.json((() => {
const sessions = ServerManeger.getSessions();
const data = {};
Object.keys(sessions).map(key => data[key] = {
players: sessions[key].getPlayer(),
ports: sessions[key].ports()
});
return data;
})()));
// Session info
app.get("/:SessionID", (req, res) => {
const SessionID: string = req.params.SessionID;
const Sessions = ServerManeger.getSessions();
if (!Sessions[SessionID]) return res.status(404).send({message: "Session not found"});
const filter = Object.keys(Sessions[SessionID]).filter(a => !(a === "addonManeger" || a ==="commands"));
const data = {};
filter.forEach(key => data[key] = Sessions[SessionID][key]);
return res.json(data);
});
// Get Players
app.get("/:SessionID/player", (req, res) => {
const SessionID: string = req.params.SessionID;
const Sessions = ServerManeger.getSessions();
if (!Sessions[SessionID]) return res.status(404).send({message: "Session not found"});
return res.json(Sessions[SessionID].getPlayer());
});
// Get Player Info
app.get("/:SessionID/player/:Player", (req, res) => {
const { SessionID, Player } = req.params;
const Sessions = ServerManeger.getSessions();
if (!Sessions[SessionID]) return res.status(404).send({message: "Session not found"});
return res.json(Sessions[SessionID].getPlayer()[Player]);
});
// Player Action
app.post("/:SessionID/player/:Player/:Action", (req, res) => {
const { SessionID, Player, Action } = req.params;
const Sessions = ServerManeger.getSessions();
if (!Sessions[SessionID]) return res.status(404).send({message: "Session not found"});
const player = Sessions[SessionID].getPlayer()[Player];
if (!player) return res.status(404).send({message: "Player not found"});
if (Action !== "connect") return res.status(400).send({message: "Player no connected to server"});
if (Action.toLowerCase() === "tp") {
const { x, y, z } = req.body;
if (!x || !y || !z) return res.status(400).send({message: "Missing x, y or z"});
Sessions[SessionID].commands.tpPlayer(Player, parseInt(x), parseInt(y), parseInt(z));
return res.status(200).send({message: "Player teleported"});
}
return res.status(400).send({message: "Action not found"});
});

View File

@ -1,104 +0,0 @@
const express = require("express");
const app = express.Router();
const ServerManeger = require("../ServerManeger");
module.exports = app;
// Sessions Players
app.get("/", (req, res) => {
const ServerSessions = ServerManeger.GetSessions().map(session => ({
uuid: session.uuid,
Players: session.Players_in_Session()
}));
return res.json(ServerSessions);
});
// kick player
app.get("/kick", (req, res) => {
const { Player = "Sirherobrine", Text = "You have been removed from the Server" } = req.query;
// Kick player
const Sessions = ServerManeger.GetSessions();
if (Sessions.length > 0) {
Sessions.forEach(RunnerServer => RunnerServer.kick(Player, Text));
return res.json({ success: true });
} else {
res.status(400).json({
error: "Server nots Run"
});
}
});
// Ban player
app.get("/ban", (req, res) => {
const { Player = "Sirherobrine" } = req.query;
// Ban player
const Sessions = ServerManeger.GetSessions();
if (Sessions.length > 0) {
Sessions.forEach(RunnerServer => RunnerServer.ban(Player));
return res.sendStatus(200);
}
res.status(400).json({
error: "Server nots Run"
});
});
// Op player
app.get("/op", (req, res) => {
const { Player = "Sirherobrine" } = req.query;
// Op player
const Sessions = ServerManeger.GetSessions();
if (Sessions.length > 0) {
Sessions.forEach(RunnerServer => RunnerServer.op(Player));
return res.sendStatus(200);
}
res.status(400).json({
error: "Server nots Run"
});
});
// Deop player
app.get("/deop", (req, res) => {
const { Player = "Sirherobrine" } = req.query;
// Deop player
const Sessions = ServerManeger.GetSessions();
if (Sessions.length > 0) {
Sessions.forEach(RunnerServer => RunnerServer.deop(Player));
return res.sendStatus(200);
}
res.status(400).json({
error: "Server nots Run"
});
});
// Say to Server
app.get("/say", (req, res) => {
const { Text = "Hello Server" } = req.query;
// Say to Server
const Sessions = ServerManeger.GetSessions();
if (Sessions.length > 0) {
Sessions.forEach(RunnerServer => RunnerServer.say(Text));
return res.sendStatus(200);
}
res.status(400).json({
error: "Server nots Run"
});
});
// Tp player
app.get("/tp", (req, res) => {
const { Player = "Sirherobrine", X = 0, Y = 0, Z = 0 } = req.query;
// Tp player
const Sessions = ServerManeger.GetSessions();
if (Sessions.length > 0) {
Sessions.forEach(RunnerServer => RunnerServer.tp(Player, X, Y, Z));
return res.sendStatus(200);
}
res.status(400).json({
error: "Server nots Run"
});
});

View File

@ -1,50 +0,0 @@
const express = require("express");
const app = express.Router();
module.exports = app;
const BdsSettings = require("../lib/BdsSettings");
const BdsServerPlugins = require("../PluginManeger");
// List
app.get("/", async (req, res) => {
try {
const { Platform = BdsSettings.CurrentPlatorm() } = req.query;
const PluginList = await (BdsServerPlugins.PluginManeger(Platform)).listVersions();
return res.json(PluginList);
} catch (err) {
return res.status(500).json({
error: String(err.stack || err).split(/\r\n|\n/gi)
});
}
});
app.post("/", async (req, res) => {
const { Platform = BdsSettings.CurrentPlatorm(), Plugin = "", Version = "latest" } = req.body;
if (/\.\/|\.\.\/|\.\\|\.\.\\/gi.test(Plugin)) return res.status(400).json({
error: "Invalid Plugin Name"
});
try {
const PluginList = await (BdsServerPlugins.PluginManeger(Platform)).listVersions();
const FiltedVersionsAndPlugins = (PluginList.filter(PluginName => PluginName.name === Plugin))[0].versions.filter((Plugin, PluginIndex) => {
if (Version === "latest") {
if (PluginIndex === 0) {
return true;
}
} else {
if (Plugin.version === Version) {
return true;
}
}
});
if (FiltedVersionsAndPlugins.length === 0) return res.status(400).json({
error: "Plugin not found or Version not found"
});
const PluginVersion = FiltedVersionsAndPlugins[0];
return res.json({
Path: await (BdsServerPlugins.PluginManeger(Platform)).Install(Plugin, PluginVersion.version)
});
} catch (err) {
return res.status(500).json({
error: String(err.stack || err).split(/\r\n|\n/gi)
});
}
});

View File

@ -1,179 +0,0 @@
// Express Routers
const express = require("express");
const app = express.Router();
module.exports = app;
const os = require("os");
const fs = require("fs");
const BdsSystemInfo = require("../lib/BdsSystemInfo");
const BdsSettings = require("../lib/BdsSettings");
const BdsToken = require("../lib/Token");
const ServerManeger = require("../ServerManeger");
const ServerSettings = require("../ServerSettings");
const BdsBackup = require("../BdsBackup");
const BdsDownload = require("../BdsServersDownload");
const BdsVersionManeger = require("@the-bds-maneger/server_versions");
const minecraft_server_util = require("minecraft-server-util");
function ErroRes(res, erro) {
return res.status(500).json({
Message: "Sorry, an unexpected error occurred on our part.",
RawError: String(erro.stack || erro).split(/\r\n|\n/gi),
});
}
app.get("/", ({res}) => {
try {
const BdsConfig = BdsSettings.GetBdsConfig();
const Info = {
server: {
version: BdsConfig.server.versions[BdsSettings.CurrentPlatorm()],
versions: BdsConfig.server.versions
},
host: {
System: process.platform,
Arch: BdsSystemInfo.arch,
Kernel: BdsSystemInfo.GetKernel(),
Cpu_Model: (os.cpus()[0] || {}).model || null,
Cores: os.cpus().length
},
Backend: {
npx: false,
Docker: false,
CLI: false,
}
}
if (process.env.DOCKER_IMAGE === "true") Info.Backend.Docker = true;
if (process.env.npm_lifecycle_event === "npx") Info.Backend.npx = true;
if (process.env.IS_BDS_CLI) Info.Backend.CLI = true;
res.json(Info);
} catch (err) {ErroRes(res, err);}
});
// Server Info
app.get("/info_server", async ({res}) => {
try {
const ServerSessions = ServerManeger.GetSessions();
const ServerRunner = [];
for (const Session of ServerSessions) {
ServerRunner.push({
UUID: Session.uuid,
Uptime: Session.Uptime(),
Started: Session.StartTime.toString(),
});
}
const BdsConfig = BdsSettings.GetBdsConfig();
delete BdsConfig.telegram;
const AsyncHostInfo = await BdsSystemInfo.CheckSystemAsync();
const Info = {
version: BdsConfig.server.versions[BdsSettings.CurrentPlatorm()],
Platform: BdsSettings.CurrentPlatorm(),
Platform_available: Object.keys(AsyncHostInfo.valid_platform).filter(a => AsyncHostInfo.valid_platform[a]),
players: Object.keys(ServerSessions).map(session => ServerSessions[session]).map(Session => {
const Users = Session.Players_in_Session();
const NewUsers = {
online: [],
offline: [],
Users
};
for (let Player of Object.keys(Users)) {
const Playersession = Users[Player];
if (Playersession.connected) NewUsers.online.push(Player);
else NewUsers.offline.push(Player);
}
return NewUsers
}),
Config: BdsConfig,
Process: ServerRunner
}
return res.json(Info);
} catch (err) {return ErroRes(res, err);}
});
// Get Server Log
app.get("/log", BdsToken.ExpressCheckToken, (req, res) => {
const Sessions = ServerManeger.GetSessions();
return res.json(Object.keys(Sessions).map(session => {
try {
return {
UUID: session,
data: fs.readFileSync(Sessions[session].LogPath, "utf8").replace(/\r\n/gi, "\n").split("\n")
};
} catch (err) {
return {
UUID: session,
Error: String(err)
};
}
}));
});
// Create Backup
app.post("/Backup", BdsToken.ExpressCheckToken, ({res}) => {
const BackupBuffer = BdsBackup.CreateBackup();
return res.send(BackupBuffer.Buffer);
});
// Download Server
app.get("/server", async ({res}) => res.json(await BdsVersionManeger.listAsync()));
app.post("/server", BdsToken.ExpressCheckToken, async (req, res) => {
const { Version = "latest" } = req.query;
try {
const DownloadResponse = await BdsDownload.DownloadServer(Version);
return res.json(DownloadResponse);
} catch (err) {return ErroRes(res, err);}
});
app.get("/settings", async (req, res) => {
const ConfigServer = await ServerSettings.get_config();
ConfigServer.MoreInfo = {};
const CurrentPlatorm = BdsSettings.CurrentPlatorm();
if (CurrentPlatorm === "bedrock") {
try {
const BacBed = await minecraft_server_util.statusBedrock("localhost", ConfigServer.portv4);
ConfigServer.MoreInfo.Motd = BacBed.motd;
ConfigServer.MoreInfo.Players = BacBed.players||{};
ConfigServer.MoreInfo.Version = BacBed.version;
} catch (err) {console.log(err)}
} else if (CurrentPlatorm === "java") {
try {
const BacJava = await minecraft_server_util.status("localhost", ConfigServer.portv4);
ConfigServer.MoreInfo.Motd = BacJava.motd;
ConfigServer.MoreInfo.Players = BacJava.players||{};
ConfigServer.MoreInfo.Version = BacJava.version;
} catch (err) {console.log(err)}
}
return res.json(ConfigServer);
});
app.post("/settings", BdsToken.ExpressCheckToken, async (req, res) => {
const ServerConfig = await ServerSettings.get_config();
if (req.body.world) ServerConfig.world = req.body.world;
if (req.body.description) ServerConfig.description = req.body.description;
if (req.body.gamemode) ServerConfig.gamemode = req.body.gamemode;
if (req.body.difficulty) ServerConfig.difficulty = req.body.difficulty;
if (req.body.players) ServerConfig.players = req.body.players;
if (req.body.whitelist) ServerConfig.whitelist = req.body.whitelist;
if (req.body.portv4) ServerConfig.portv4 = req.body.portv4;
if (req.body.portv6) ServerConfig.portv6 = req.body.portv6;
try {
await ServerSettings.set_config(ServerConfig);
return res.json(ServerConfig);
} catch (err) {return ErroRes(res, err);}
});
app.post("/settings/:Config", BdsToken.ExpressCheckToken, async (req, res) => {
const { Config } = req.params;
const ServerConfig = await ServerSettings.get_config();
if (ServerConfig[Config] === undefined) return res.status(404).json({
error: "Config Not Found",
message: {
Config: Config,
ConfigAvailable: Object.keys(ServerConfig)
}
});
if (!req.body.Value) return res.json({error: "Empty Value, Please provide a value"});
ServerConfig[Config] = req.body.Value;
try {
await ServerSettings.set_config(ServerConfig);
return res.json(ServerConfig);
} catch (err) {return ErroRes(res, err);}
});

23
src/backup.ts Normal file
View File

@ -0,0 +1,23 @@
import os from "os";
import path from "path";
import fs from "fs";
import AdmZip from "adm-zip";
export default CreateBackup;
export async function CreateBackup(Platform: "bedrock"|"java"|"pocketmine"|"spigot"|"dragonfly") {
const ServerPath = path.resolve(process.env.SERVER_PATH||path.join(os.homedir(), "bds_core/servers"), Platform);
const BackupPath = path.resolve(process.env.BACKUP_PATH||path.join(os.homedir(), "bds_core/backups"));
if (!(fs.existsSync(ServerPath))) throw new Error("Server no Installed or path not found");
if (!(fs.existsSync(BackupPath))) fs.mkdirSync(BackupPath, {recursive: true});
const Backup = new AdmZip();
if (Platform === "bedrock") {
if (fs.existsSync(path.join(ServerPath, "worlds"))) Backup.addLocalFolder(path.join(ServerPath, "worlds"));
if (fs.existsSync(path.join(ServerPath, "server.properties"))) Backup.addLocalFile(path.join(ServerPath, "server.properties"));
if (fs.existsSync(path.join(ServerPath, "permissions.json"))) Backup.addLocalFile(path.join(ServerPath, "permissions.json"));
}
const BackupFile = path.resolve(BackupPath, `${Platform}_${new Date().toString().replace(/[-\(\)\:\s+]/gi, "_")}.zip`);
const zipBuffer = Backup.toBuffer();
fs.writeFileSync(BackupFile, zipBuffer);
return {zipBuffer, BackupFile};
}

65
src/bin/docker.ts Normal file
View File

@ -0,0 +1,65 @@
import * as BdsCore from "../index";
import * as BdsTypes from "../globalType";
import { CronJob } from "cron";
const {
VERSION = "latest",
PLATFORM = "bedrock",
DESCRIPTION = "My Sample Server",
WORLD_NAME = "My Map",
GAMEMODE = "survival",
DIFFICULTY = "normal",
MAXPLAYERS = "5",
REQUIRED_LOGIN = "false",
ALLOW_COMMADS = "false",
} = process.env;
if (!BdsTypes.PlatformArray.find(p => p === PLATFORM)) {
console.error(`Platform ${PLATFORM} is not supported.`);
process.exit(1);
}
(async () => {
let versionDownloaded = "";
if (VERSION === "latest") {
const DownloadRes = await BdsCore.DownloadServer.DownloadServer(PLATFORM as BdsTypes.Platform, true);
versionDownloaded = DownloadRes.Version;
} else if (VERSION !== "latest") {
await BdsCore.DownloadServer.DownloadServer(PLATFORM as BdsTypes.Platform, VERSION);
} else {
console.log("Invalid Version");
}
BdsCore.serverConfig.createConfig(PLATFORM as BdsTypes.Platform, {
description: DESCRIPTION,
world: WORLD_NAME,
gamemode: GAMEMODE as any,
difficulty: DIFFICULTY as any,
players: parseInt(MAXPLAYERS),
require_login: REQUIRED_LOGIN === "true",
cheats_command: ALLOW_COMMADS === "true"
});
let lockExit = false;
const start = async () => {
const Server = await BdsCore.Server.Start(PLATFORM as BdsTypes.Platform);
Server.on("all", data => process.stdout.write(data));
Server.exit(code => {
if (lockExit) return;
process.exit(code);
});
return Server;
};
if (VERSION === "latest") {
let sessionStart = await start();
const cronUpdate = new CronJob("0 */1 * * * *", async () => {
const DownloadInfo = await BdsCore.DownloadServer.getVersions();
if (DownloadInfo.latest[PLATFORM as BdsTypes.Platform] === versionDownloaded) return;
lockExit = true;
await sessionStart.commands.stop();
await BdsCore.DownloadServer.DownloadServer(PLATFORM as BdsTypes.Platform, true);
sessionStart = await start();
});
cronUpdate.start();
} else await start();
})();

51
src/bin/index.ts Normal file
View File

@ -0,0 +1,51 @@
import yargs from "yargs";
import readline from "readline"
import * as BdsCore from "../index";
import * as bdsTypes from "../globalType";
const Yargs = yargs(process.argv.slice(2)).command("download", "Download and Install server", yargs => {
const options = yargs.option("platform", {
alias: "p",
describe: "Bds Core Platform",
choices: ["bedrock", "java", "pocketmine", "spigot", "dragonfly"],
default: "bedrock"
}).option("version", {
alias: "v",
describe: "Server Version",
demandOption: true,
type: "string"
}).parseSync();
const Platform = options.platform as bdsTypes.Platform;
console.log("Starting Download...");
BdsCore.DownloadServer.DownloadServer(Platform, options.version === "latest"?true:options.version).then(res => {
console.log("Sucess to download server");
console.info("Release date: %s", `${res.Date.getDate()}/${res.Date.getMonth()+1}/${res.Date.getFullYear()}`);
});
}).command("start", "Start Server", async yargs => {
const options = await yargs.option("platform", {
alias: "p",
describe: "Bds Core Platform",
choices: ["bedrock", "java", "pocketmine", "spigot", "dragonfly"],
default: "bedrock"
}).option("api", {
alias: "a",
describe: "Bds Core API port listen",
default: "3000",
type: "number"
}).parseAsync();
const Platform = options.platform as bdsTypes.Platform;
BdsCore.API.listen(options.api);
const Server = await BdsCore.Server.Start(Platform);
console.log("Session ID: %s", Server.id);
Server.on("all", data => process.stdout.write(data));
const Input = readline.createInterface({input: process.stdin,output: process.stdout})
Input.on("line", line => Server.commands.execCommand(line));
Server.exit(Input.close);
Input.on("close", () => Server.commands.execCommand("stop"));
}).command({
command: "*",
handler: () => {
Yargs.showHelp();
}
}).help().version(false);
Yargs.parseAsync();

66
src/download_server.ts Normal file
View File

@ -0,0 +1,66 @@
import path from "path";
import fs from "fs";
import os from "os";
import adm_zip from "adm-zip";
import { getBuffer, getGithubRelease } from "./HttpRequests";
import * as bdsTypes from "./globalType";
type getVersionsType = {
latest: {
[d: string]: string|undefined
};
platform: Array<{
name: bdsTypes.Platform;
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: bdsTypes.Platform, Version: string|boolean) {
const ServerPath = path.resolve(process.env.SERVER_PATH||path.join(os.homedir(), "bds_core/servers"), Platform);
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);
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);
if (!(await fs.existsSync(JavaPath))) fs.mkdirSync(JavaPath, {recursive: true});
await fs.promises.writeFile(path.resolve(JavaPath, "Server.jar"), await getBuffer(String(info.data)));
await fs.promises.writeFile(path.resolve(JavaPath, "eula.txt"), "eula=true");
} else if (Platform === "spigot") {
const SpigotPath = path.resolve(ServerPath);
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);
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);
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])
};
}

2
src/globalType.ts Normal file
View File

@ -0,0 +1,2 @@
export type Platform = "bedrock"|"java"|"pocketmine"|"spigot"|"dragonfly";
export const PlatformArray = ["bedrock", "java", "pocketmine", "spigot", "dragonfly"];

View File

@ -1,74 +0,0 @@
/* eslint-disable no-irregular-whitespace */
// process.env.ShowLoadTime = true;
// Load Root JSON
const BdsManegerCoreJSONs = {
Package: require("../package.json"),
Extra: require("./BdsManegerInfo.json")
};
// Bds Maneger Core Version
module.exports.version = BdsManegerCoreJSONs.Package.version;
const ExtraJSON = BdsManegerCoreJSONs;
module.exports.ExtraJSON = ExtraJSON;
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Settings");
const BdsSettings = require("./lib/BdsSettings");
module.exports.BdsSettings = BdsSettings;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Settings");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Token");
const BdsToken = require("./lib/Token");
module.exports.BdsToken = BdsToken;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Token");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: System Info");
const BdsSystemInfo = require("./lib/BdsSystemInfo");
module.exports.BdsSystemInfo = BdsSystemInfo;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: System Info");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Network");
const BdsNetwork = require("./BdsNetwork");
module.exports.BdsNetwork = BdsNetwork;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Network");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Backups");
const BdsBackup = require("./BdsBackup");
module.exports.BdsBackup = BdsBackup;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Backups");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Server Settings");
const BdsServerSettings = require("./ServerSettings");
module.exports.BdsServerSettings = BdsServerSettings;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Server Settings");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Download Server");
const BdsDownload = require("./BdsServersDownload");
module.exports.BdsDownload = BdsDownload;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Download Server");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Check And Kill");
const BdsCkeckKill = require("./CheckKill");
module.exports.BdsCkeckKill = BdsCkeckKill;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Check And Kill");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: API");
const BdsManegerAPI = require("./api");
module.exports.BdsManegerAPI = BdsManegerAPI;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: API");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Server Maneger");
const BdsManegerServer = require("./ServerManeger");
module.exports.BdsManegerServer = BdsManegerServer;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Server Maneger");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Plugin Maneger");
const BdsServerPlugins = require("./PluginManeger");
module.exports.BdsServerPlugins = BdsServerPlugins;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Plugin Maneger");
if (process.env.ShowLoadTime) console.time("Bds Maneger Core: Token Maneger");
const TokenManeger = require("./lib/Token");
module.exports.TokenManeger = TokenManeger;
if (process.env.ShowLoadTime) console.timeEnd("Bds Maneger Core: Token Maneger");

8
src/index.ts Normal file
View File

@ -0,0 +1,8 @@
import * as Server from "./server";
import * as Backup from "./backup";
import * as DownloadServer from "./download_server";
import * as API from "./api";
import * as serverConfig from "./serverConfig";
export default {Server, Backup, DownloadServer, API, serverConfig};
export {Server, Backup, DownloadServer, API, serverConfig};

View File

@ -1,177 +0,0 @@
const fs = require("fs");
const path = require("path");
const os = require("os");
const yaml = require("js-yaml");
const deepmerge = require("deepmerge");
// Config/Base Paths
const home = os.homedir(), bds_dir = path.join(home, "bds_core");
if (!(fs.existsSync(bds_dir))) fs.mkdirSync(bds_dir, {recursive: true});
module.exports.BdsDir = bds_dir;
/**
* Server Config Base
*/
let BdsConfig = {
version: 2.9,
paths: {
Backup: path.join(bds_dir, "Backups"),
Log: path.join(bds_dir, "Logs"),
Player: path.join(bds_dir, "Players.json"),
Servers: path.join(bds_dir, "Servers"),
ServersConfig: {
bedrock: "Bedrock",
java: "Java",
pocketmine: "Pocketmine-MP",
spigot: "Spigot",
dragonfly: "Dragonfly_go",
}
},
server: {
platform: "bedrock",
versions: {
bedrock: "",
java: "",
pocketmine: "",
spigot: "",
dragonfly: ""
},
BackupCron: [
{
enabled: false,
cron: "0 1 * * */3",
Azure: false,
Oracle: false,
Google: false,
Driver: false
}
],
Settings: {
java: {
ram: 1024
}
},
ban: [
{
username: "Steve",
bedrock: true,
java: true,
pocketmine: true,
spigot: true,
dragonfly: true
}
],
},
telegram: {
token: "",
admins: [],
ban: [],
}
}
// Config
const ConfigPath = path.join(bds_dir, "BdsConfig.yaml");
const SaveConfig = () => fs.writeFileSync(ConfigPath, yaml.dump(BdsConfig));
if (fs.existsSync(ConfigPath)) {
const UserConfig = yaml.load(fs.readFileSync(ConfigPath, "utf8"));
if (UserConfig.version === undefined) {
console.log("Updating settings to new version config file.");
fs.copyFileSync(ConfigPath, path.join(os.homedir(), "BdsConfigBackup.yml"));
console.log("Deleteing cloud Config.");
delete UserConfig.cloud;
console.log("Deleteing bds Object");
delete UserConfig.bds;
console.log("Moving User Bans to Server Object");
UserConfig.server.ban = UserConfig.ban;
delete UserConfig.ban;
}
BdsConfig.server.ban = [];
BdsConfig.server.BackupCron = [];
BdsConfig = deepmerge(BdsConfig, UserConfig);
} else fs.writeFileSync(ConfigPath, yaml.dump(BdsConfig));
// Basics
module.exports.GetBdsConfig = () => BdsConfig;
module.exports.CurrentPlatorm = () => BdsConfig.server.platform;
// Paths
if (!(fs.existsSync(BdsConfig.paths["Backup"]))) fs.promises.mkdir(BdsConfig.paths["Backup"], {recursive: true}).catch(e => console.log(e));
if (!(fs.existsSync(BdsConfig.paths["Log"]))) fs.promises.mkdir(BdsConfig.paths["Log"], {recursive: true}).catch(e => console.log(e));
if (!(fs.existsSync(BdsConfig.paths["Servers"]))) fs.promises.mkdir(BdsConfig.paths["Servers"], {recursive: true}).catch(e => console.log(e));
for (const Servers of Object.keys(BdsConfig.paths.ServersConfig).map(Servers => path.join(BdsConfig.paths.Servers, BdsConfig.paths.ServersConfig[Servers]))) {
if (!(fs.existsSync(Servers))) {
fs.promises.mkdir(Servers, {recursive: true}).catch(e => console.log(e));
}
}
/**
* Find path to Bds Core and the Bds Servers platform
*/
function GetPaths(PlatformOrPath = "", IsServers = false){
if (IsServers) {
if (PlatformOrPath === "all") return {
RootServers: BdsConfig.paths.Servers,
Platforms: BdsConfig.paths.ServersConfig
}
else if (BdsConfig.paths.ServersConfig[PlatformOrPath]) return path.join(BdsConfig.paths.Servers, BdsConfig.paths.ServersConfig[PlatformOrPath]);
} else {
if (PlatformOrPath === "all") return BdsConfig.paths;
else if (BdsConfig.paths[PlatformOrPath]) return BdsConfig.paths[PlatformOrPath];
}
return undefined;
}
module.exports.GetPaths = GetPaths;
// Create Player JSON
if (!(fs.existsSync(BdsConfig.paths.Player))) fs.writeFileSync(BdsConfig.paths.Player, JSON.stringify([], null, 2));
/**
* Update Server Version
*/
function UpdateServerVersion(version = "", platform = BdsConfig.server.platform){
version = version.trim();
if (!version) throw new Error("Version invalid")
if (BdsConfig.server.versions[platform] === undefined) throw new Error("Platform invalid");
if (BdsConfig.server.versions[platform] === version) return;
BdsConfig.server.versions[platform] = version;
SaveConfig();
return;
}
module.exports.UpdateServerVersion = UpdateServerVersion;
// Update the entire Bds Manager Core platform
function ChangePlatform(platform = ""){
if (!platform) throw new Error("Platform invalid");
platform = platform.toLocaleLowerCase().trim();
if (/bedrock/.test(platform)) {
BdsConfig.server.platform = "bedrock";
} else if (/java/.test(platform)) {
BdsConfig.server.platform = "java";
} else if (/pocketmine|pocketmine-mp/.test(platform)) {
BdsConfig.server.platform = "pocketmine";
} else if (/spigot/.test(platform)) {
BdsConfig.server.platform = "spigot";
} else if (/dragonfly/.test(platform)) {
BdsConfig.server.platform = "dragonfly";
} else throw new Error("platform no exists");
SaveConfig();
return BdsConfig.server.platform;
}
module.exports.ChangePlatform = ChangePlatform;
/**
* Update and Get Telegram Bot Token
*/
function telegramToken(Token = "") {
if (Token) {
BdsConfig.telegram.token = Token;
SaveConfig();
}
return BdsConfig.telegram.token;
}
module.exports.more = {
telegramToken
};

View File

@ -1,271 +0,0 @@
const child_process = require("child_process");
const os = require("os");
const fs = require("fs");
const Request = require("./Requests");
const BdsCoreUrlManeger = require("@the-bds-maneger/server_versions");
const commadExist = require("./commandExist");
// System Architect (x64, aarch64 and others)
let arch = process.arch;
if (process.arch === "arm64") arch = "aarch64";
module.exports.arch = arch;
// Get System Basic Info
async function CheckSystemAsync() {
const ServerVersions = await BdsCoreUrlManeger.listAsync();
const Servers = {
bedrock: ServerVersions.platform.filter(data => data.name === "bedrock")[0].data,
spigot: ServerVersions.platform.filter(data => data.name === "spigot")[0].data,
dragonfly: ServerVersions.platform.filter(data => data.name === "dragonfly")[0].data,
}
const BasicConfigJSON = {
require_qemu: false,
valid_platform: {
bedrock: true,
pocketmine: false,
java: await commadExist.commdExistAsync("java"),
dragonfly: true
}
}
// check php bin
const PhpBinFiles = await Request.GetLatestReleaseFromGithub("The-Bds-Maneger/PocketMinePHPAutoBinBuilds");
if (PhpBinFiles.assets.find(data => {
let Status = true;
if (process.platform === "win32") Status = data.name.startsWith("win32");
else if (process.platform === "linux") Status = data.name.startsWith("linux");
else if (process.platform === "darwin") Status = data.name.startsWith("darwin");
else if (process.platform === "android") Status = data.name.startsWith("android");
if (arch === "x64") Status = data.name.includes("x64");
else if (arch === "x32") Status = data.name.includes("x32");
else if (arch === "arm64") Status = data.name.includes("aarch64");
return Status;
})) BasicConfigJSON.valid_platform["pocketmine"] = true;
// Check for Dragonfly
if (!(Servers.dragonfly[process.platform][arch])) BasicConfigJSON.valid_platform["dragonfly"] = false;
// SoSystem X
if (process.platform == "linux") {
// Bedrock Check
if (Servers.bedrock[process.platform]) {
if (Servers.bedrock[process.platform][arch]) BasicConfigJSON.valid_platform["bedrock"] = true;
else BasicConfigJSON.valid_platform["bedrock"] = false;
} else BasicConfigJSON.valid_platform["bedrock"] = false;
if (BasicConfigJSON.valid_platform["bedrock"] === false) {
if (await commadExist.commdExistAsync("qemu-x86_64-static")) {
// console.warn("The Minecraft Bedrock Server is only being validated because you can use 'qemu-x86_64-static'");;
BasicConfigJSON.valid_platform["bedrock"] = true
BasicConfigJSON.require_qemu = true;
}
}
} else if (process.platform === "android") {
if (BasicConfigJSON.valid_platform["bedrock"]) BasicConfigJSON.valid_platform["bedrock"] = false;
}
return BasicConfigJSON;
}
module.exports = CheckSystemAsync;
module.exports.SystemInfo = CheckSystemAsync;
module.exports.CheckSystemAsync = CheckSystemAsync;
/**
* Platforms valid from deferents systems
*/
function GetKernel() {
if (process.platform === "win32") {
const kernelVersion = parseFloat(os.release());
if (kernelVersion <= 6.1) return "Windows 7";
else if (kernelVersion <= 6.2) return "Windows 8";
else if (kernelVersion <= 6.3) return "Windows 8.1";
else if (kernelVersion <= 10.0) return "Windows 10 or Windows 11";
else return "Other Windows";
} else if (process.platform === "android") return `Android: ${os.release()}, CPU Core ${fs.readdirSync("/sys/devices/system/cpu/").filter(data => /cpu[0-9]/.test(data)).length}`;
else if (commadExist.commdExistSync("uname")) {
const UnameRV = child_process.execSync("uname -rv").toString("ascii");
// Amazon web services
if (/aws/.test(UnameRV)) {
if (/arm64|aarch64/.test(process.arch)) return "Amazon AWS Cloud arm64: AWS Graviton Serie";
else return `Amazon AWS Cloud ${process.arch}: ${os.cpus()[0].model}`;
}
// Windows subsystem for Linux
else if (/WSL2|microsft/.test(UnameRV)) return "Microsoft WSL";
// Azure Virtual Machinime (VM)
else if (/[aA]zure/.test(UnameRV)) return "Microsoft Azure";
// Google Cloud Virtual Machinime (VM)
else if (/[gG]cp/.test(UnameRV)) return "Google Cloud Platform";
// Oracle cloud Virtual Machinime (VM)
else if (/[oO]racle/.test(UnameRV)) return "Oracle Cloud infrastructure";
// Darwin
else if (/[dD]arwin/.test(UnameRV)) return "Apple MacOS";
// Others Kernels
else return UnameRV.replace(/\n|\t|\r/gi, "");
} else return "Not identified";
}
module.exports.GetKernel = GetKernel;
/**
* Get CPU Cores number
*/
function GetCpuCoreCount() {
if (process.platform === "android") return fs.readdirSync("/sys/devices/system/cpu/").filter(data => /cpu[0-9]/.test(data)).length;
else return os.cpus().length;
}
module.exports.GetCpuCoreCount = GetCpuCoreCount;
/**
* Advanced System And Server Infomaion
*
* @return {{
* platform: NodeJS.Platform;
* arch: string;
* kernel: string;
* cpu_cores: number;
* RequiredQemu: boolean;
* RunningOn: "native"|"emulated"|"unknown";
* AvaibleServers: {
* bedrock: {
* avaible: boolean;
* RequiredQemu: boolean;
* RunningOn: "native"|"emulated";
* };
* spigot: {
* avaible: boolean;
* RequiredQemu: boolean;
* RunningOn: "native"|"emulated";
* };
* dragonfly: {
* avaible: boolean;
* RequiredQemu: boolean;
* RunningOn: "native"|"emulated";
* };
* pocketmine: {
* avaible: boolean;
* RequiredQemu: boolean;
* RunningOn: "native"|"emulated";
* };
* };
* }}
*/
async function AdvancedInfo() {
const Info = {
platform: process.platform,
arch: arch,
kernel: GetKernel(),
cpu_cores: GetCpuCoreCount(),
AvaibleQemu: false,
AvaibleServers: {
bedrock: {
avaible: false,
RequiredQemu: false,
RunningOn: "native",
arch: arch
},
spigot: {
avaible: false,
RequiredQemu: false,
RunningOn: "native",
arch: arch
},
java: {
avaible: false,
RequiredQemu: false,
RunningOn: "native",
arch: arch
},
dragonfly: {
avaible: false,
RequiredQemu: false,
RunningOn: "native",
arch: arch
},
pocketmine: {
avaible: false,
RequiredQemu: false,
RunningOn: "native",
arch: arch
},
}
}
if (process.platform === "linux") Info.AvaibleQemu = await commadExist.commdExistAsync("qemu-x86_64-static");
else if (process.platform === "android") Info.AvaibleQemu = await commadExist.commdExistAsync("qemu-x86_64");
// PHP Static bins
const PhpBinFiles = await Request.GetLatestReleaseFromGithub("The-Bds-Maneger/PocketMinePHPAutoBinBuilds");
if (PhpBinFiles.assets.find(data => {
let Status = true;
if (process.platform === "win32") Status = data.name.startsWith("win32");
else if (process.platform === "linux") Status = data.name.startsWith("linux");
else if (process.platform === "darwin") Status = data.name.startsWith("darwin");
else if (process.platform === "android") Status = data.name.startsWith("android");
if (arch === "x64") Status = data.name.includes("x64");
else if (arch === "x32") Status = data.name.includes("x32");
else if (arch === "arm64") Status = data.name.includes("aarch64");
return Status;
})) Info.AvaibleServers.pocketmine.avaible = true;
const Versions = await BdsCoreUrlManeger.listAsync();
const Bedrock = Versions.platform.filter(Data => Data.name === "bedrock");
const Dragonfly = Versions.platform.filter(Data => Data.name === "dragonfly");
// Bedrock
if (Bedrock.find(Data => Data.version === Versions.latest.bedrock).data[process.platform][arch]) Info.AvaibleServers.bedrock.avaible = true;
else {
if (Info.AvaibleQemu) {
Info.AvaibleServers.bedrock.RequiredQemu = true;
Info.AvaibleServers.bedrock.RunningOn = "emulated";
Info.AvaibleServers.bedrock.arch = "x64";
}
}
// Dragonfly
if (Dragonfly.find(Data => Data.version === Versions.latest.dragonfly).data[process.platform][arch]) Info.AvaibleServers.dragonfly.avaible = true;
else {
if (Info.AvaibleQemu) {
Info.AvaibleServers.dragonfly.RequiredQemu = true;
Info.AvaibleServers.dragonfly.RunningOn = "emulated";
Info.AvaibleServers.dragonfly.arch = "x64";
}
}
// Java
if (await commadExist.commdExistAsync("java")) {
let JavaVersion = "";
// OpenJDK
try {
const Javave = child_process.execFileSync("java", ["-version"]).toString();
if (Javave.includes("openjdk")) {
JavaVersion = Javave.match(/openjdk version "(.*)"/)[0];
} else {
JavaVersion = Javave.match(/java version "(.*)"/)[0];
}
} catch (err) {
JavaVersion = "Not found";
}
// Java
try {
const Javave = child_process.execFileSync("java", ["--version"]).toString();
JavaVersion = Javave.match(/java version "(.*)"/)[0];
} catch (err) {
JavaVersion = "Not found";
}
console.log(JavaVersion)
if (!(JavaVersion === "" || JavaVersion === "Not found")) {
if (parseFloat(JavaVersion) >= 16.0) {
Info.AvaibleServers.spigot.avaible = true;
Info.AvaibleServers.java.avaible = true;
}
}
}
return Info;
}
module.exports.AdvancedInfo = AdvancedInfo;

View File

@ -1,154 +0,0 @@
/**
* Fetch data and return buffer
* @param {String} url - The url of the file
* @param {RequestInit} args - The request options
* @returns {Buffer} The file buffer data
*/
async function BufferHTTP(url = "", args = {}) {
const Fetch = (await import("node-fetch")).default;
const res = await Fetch(url, {
mode: "cors",
...args
});
if (res.ok) return Buffer.from(await res.arrayBuffer());
else throw {
Error: await res.text(),
status: res.status,
urlRequest: url,
}
}
module.exports.BUFFER = BufferHTTP;
module.exports.buffer = BufferHTTP;
// Buffer
/**
* Fetch data and return JSON parsed
* @param {String} url - The url of the file
* @param {RequestInit} args - The request options
* @returns {any} The file JSON data
*/
async function JsonHTTP(url = "", args = {}) {
const res = await BufferHTTP(url, args);
return JSON.parse(res.toString());
}
module.exports.JSON = JsonHTTP;
module.exports.json = JsonHTTP;
// JSON
/**
* Fetch data and return JSON parsed
* @param {String} url - The url of the file
* @param {RequestInit} args - The request options
* @returns {String}
*/
async function TextHTTP(url = "", args = {}) {
return (await BufferHTTP(url, args)).toString("utf8");
}
module.exports.TEXT = TextHTTP;
module.exports.text = TextHTTP;
// Raw Text
/**
* Get github repository file paths
* @param {String} repo - The repository name, example: "poggit/poggit"
* @param {String} branch - The branch name, example: "main"
* @returns {Promise<Array<{
* truncated: boolean;
* sha: string;
* url: string;
* tree: Array<{
* path: string;
* mode: string;
* type: string;
* sha: string;
* size: number;
* url?: string|undefined;
* }>;
* }>} The repository files and Folder paths
*/
async function GithubTree(repo = "The-Bds-Maneger/Plugins_Repository", branch = "main") {
return await JsonHTTP(`https://api.github.com/repos/${repo}/git/trees/${branch}?recursive=true`);
}
module.exports.GithubTree = GithubTree;
/**
* Get Github latest relases
*
* @param {String} repo - The repository name, example: "poggit/poggit"
*
* @return {Promise<{
* 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;
* };
* }>;
*/
async function GetLatestReleaseFromGithub(repo = "The-Bds-Maneger/Plugins_Repository") {
return await JsonHTTP(`https://api.github.com/repos/${repo}/releases/latest`);
}
module.exports.GetLatestReleaseFromGithub = GetLatestReleaseFromGithub;

View File

@ -1,132 +0,0 @@
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
let Tokens = [
{
Token: "",
TelegramID: 0,
Scoped: "admin"
},
{
Token: "",
TelegramID: null,
Scoped: "user"
}
];
const BdsSettings = require("./BdsSettings");
const TokenFile = path.join(BdsSettings.BdsDir, "BdsToken.json");
const Save = () => fs.writeFileSync(TokenFile, JSON.stringify(Tokens, null, 2));
if (fs.existsSync(TokenFile)) Tokens = JSON.parse(fs.readFileSync(TokenFile, "utf8"));
else {
Tokens = [];
Save();
}
/**
* Register new Token to Bds Maneger Core
*
*/
function CreateToken(AdminScoped = "admin", TelegramID = null) {
if (!(AdminScoped === "admin" || AdminScoped === "user")) throw new Error("Invalid Admin Scoped, valid use admin and user");
const GetRandomUUID = crypto.randomUUID().split("-");
const TokenObject = {
Token: `BdsTks_${GetRandomUUID[0]}${GetRandomUUID[GetRandomUUID.length - 1]}`,
TelegramID: TelegramID,
Scoped: AdminScoped
}
Tokens.push(TokenObject);
Save();
return TokenObject;
}
/**
* Delete Token
*/
function DeleteToken(Token = "") {
if (!Token) throw new Error("Inform valid Token");
if (!(Tokens.find(token => token.Token === Token))) throw new Error("this token not exists.");
Tokens = Tokens.filter(token => token.Token !== Token);
Save();
return true;
}
/**
* Check for is valid Token
*/
function CheckToken(Token = "", Scope = "admin") {
if (process.env.NODE_ENV !== "production") return true;
if (!Token) throw new Error("Inform valid Token");
if (!(Scope === "admin" || Scope === "user" || Scope === "all")) throw new Error("Invalid Scope, valid use admin and user");
// Tmp Tokens
let TmpTokens = Tokens;
if (Scope !== "all") {
if (Scope === "user") TmpTokens = TmpTokens.filter(token => token.Scoped === "user");
else if (Scope === "admin") TmpTokens = TmpTokens.filter(token => token.Scoped === "admin");
}
// Check if Token exists
if (TmpTokens.find(token => token.Token === Token)) return true;
else return false;
}
/**
* Update TelegramID for Token
*/
function UpdateTelegramID(Token = "", TelegramID = null) {
if (!Token) throw new Error("Inform valid Token");
if (!TelegramID) throw new Error("Inform valid TelegramID");
if (!(CheckToken(Token, "all"))) throw new Error("this token not exists.");
Tokens = Tokens.map(token => {
if (token.Token === Token) token.TelegramID = TelegramID;
return token;
});
Save();
return;
}
/** */
function CheckTelegramID(TelegramID = null) {
if (!TelegramID) throw new Error("Inform valid TelegramID");
if (Tokens.find(token => token.TelegramID === TelegramID)) return true;
else return false;
}
/**
* Express Middleware to Check Token
*/
function ExpressCheckToken (req, res, next) {
if (process.env.NODE_ENV !== "production") return next();
let TokenFinded = "";
if (req.headers["authorizationtoken"]) TokenFinded = req.headers["authorizationtoken"];
else if (req.query.token) TokenFinded = req.query.token;
else if (req.headers.token) TokenFinded = req.headers.token;
else if (req.query.Token) TokenFinded = req.query.Token;
else if (req.headers.Token) TokenFinded = req.headers.Token;
else if (req.body.token) TokenFinded = req.body.token;
else if (req.body.Token) TokenFinded = req.body.Token;
if (!TokenFinded) {
return res.status(401).json({
error: "Unauthorized",
message: "Required Token"
});
} else {
if (CheckToken(TokenFinded, "all")) return next();
else return res.status(401).json({
error: "Unauthorized",
message: "Token is not valid"
});
}
}
// Export module
module.exports = {
CreateToken,
DeleteToken,
CheckToken,
ExpressCheckToken,
UpdateTelegramID,
CheckTelegramID,
TokenFile,
GetAllTokens: () => Tokens
};

View File

@ -1,42 +0,0 @@
const child_process = require("child_process");
function commdExistSync(command = ""){
if (process.platform === "linux" || process.platform === "darwin" || process.platform === "android") {
try {
child_process.execSync(`command -v ${command}`);
return true
} catch (error) {
return false
}
} else if (process.platform === "win32") {
try {
child_process.execSync(`where ${command} > nul 2> nul`);
return true
} catch (error) {
return false
}
}
throw new Error(`Platform ${process.platform} not supported`);
}
async function commdExistAsync(command = ""){
let result = false;
result = await new Promise((resolve, reject) => {
if (process.platform === "linux" || process.platform === "darwin" || process.platform === "android") {
child_process.exec(`command -v ${command}`, (error) => {
if (error) return resolve(false);
else return resolve(true);
});
} else if (process.platform === "win32") {
child_process.exec(`where ${command} > nul 2> nul`, (error) => {
if (error) return resolve(false);
else return resolve(true);
});
} else return reject(new Error(`Platform ${process.platform} not supported`));
});
return result;
}
module.exports.commdExistSync = commdExistSync;
module.exports.commdExistAsync = commdExistAsync;

203
src/server.ts Normal file
View File

@ -0,0 +1,203 @@
import path from "path";
import fs from "fs";
import os from "os";
import crypto from "crypto";
import child_process from "child_process";
import node_cron from "cron";
import addon from "./addons/index";
import * as bdsBackup from "./backup";
import * as serverConfig from "./serverConfig";
import * as bdsTypes from "./globalType";
type BdsSession = {
id: string;
startDate: Date;
seed?: string;
addonManeger: {
installAddon: (packPath: string) => Promise<void>;
installAllAddons: (removeOldPacks: boolean) => Promise<void>;
};
creteBackup: (crontime: string|Date) => void;
on: (from: "all"|"stdout"|"stderr", callback: (data: string) => void) => void;
exit: (callback: (code: number, signal: string) => void) => void;
getPlayer: () => {[player: string]: {action: "connect"|"disconnect"|"unknown"; date: Date; history: Array<{action: "connect"|"disconnect"|"unknown"; date: Date}>}};
ports: () => Array<{port: number; protocol: "TCP"|"UDP"; version?: "IPv4"|"IPv6"}>;
commands: {
tpPlayer: (username: string, x: number, y: number, z: number) => void;
execCommand: (command: string) => void;
stop: () => Promise<number|null>
}
};
// Server Sessions
const Sessions: {[Session: string]: BdsSession} = {};
export function getSessions() {return Sessions;}
// Start Server
export async function Start(Platform: bdsTypes.Platform): Promise<BdsSession> {
const ServerPath = path.resolve(process.env.SERVER_PATH||path.join(os.homedir(), "bds_core/servers"), Platform);
if (!(fs.existsSync(ServerPath))) fs.mkdirSync(ServerPath, {recursive: true});
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_server"+(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, "Server.jar"));
else Process.args.push(path.resolve(ServerPath, "Spigot.jar"));
} else if (Platform === "pocketmine") {
if (process.platform === "win32") Process.command = path.resolve(ServerPath, "php/php");
else Process.command = path.resolve(ServerPath, "php7/bin/php");
Process.args.push(path.resolve(ServerPath, "PocketMine-MP.phar"));
}
// Start Server
console.log(Process.command, ...Process.args);
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: "all"|"stdout"|"stderr", callback: (data: string) => void) => {
if (from === "all") {
ServerProcess.stdout.on("data", callback);
ServerProcess.stderr.on("data", callback);
} else if (from === "stderr") ServerProcess.stderr.on("data", callback);
else if (from === "stdout") ServerProcess.stdout.on("data", callback);
else throw new Error("Unknown log from");
return;
}
const playersConnections: {[player: string]: {action: "connect"|"disconnect"|"unknown"; date: Date; history: Array<{action: "connect"|"disconnect"|"unknown"; date: Date}>}} = {};
const ports: Array<{port: number; protocol: "TCP"|"UDP"; version?: "IPv4"|"IPv6"}> = [];
onLog("all", data => {
if (Platform === "bedrock") {
(() => {
const portParse = data.match(/(IPv[46])\s+.*,\s+port:\s+(.*)/);
if (portParse) ports.push({
port: parseInt(portParse[2]),
protocol: "UDP",
version: portParse[1] as "IPv4"|"IPv6"
});
const portParse2 = data.match(/port:\s+(.*)/);
if (portParse2) {
if (!ports.find(p => p.port === parseInt(portParse2[1]))) ports.push({
port: parseInt(portParse2[1]),
protocol: "UDP",
});
}
})()
const playerBedrock = (() => {
const [action, player, xuid] = (data.match(/r\s+(.*)\:\s+(.*)\,\s+xuid\:\s+(.*)/)||[]).slice(1, 4);
const __PlayerAction: {player: string, xuid: string|undefined, action: "connect"|"disconnect"|"unknown"} = {
player: player,
xuid: xuid,
action: "unknown"
};
if (action === "connected") __PlayerAction.action = "connect";
else if (action === "disconnected") __PlayerAction.action = "disconnect";
return __PlayerAction;
})();
if (playerBedrock.player && playerBedrock.action) {
const actionDate = new Date();
if (!!playersConnections[playerBedrock.player]) {
playersConnections[playerBedrock.player].action = playerBedrock.action;
playersConnections[playerBedrock.player].date = actionDate;
playersConnections[playerBedrock.player].history.push({action: playerBedrock.action, date: actionDate});
} else {
playersConnections[playerBedrock.player] = {
action: playerBedrock.action,
date: actionDate,
history: [{action: playerBedrock.action, date: actionDate}]
};
}
}
}
});
// 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;
}
// Stop Server
const stopServer: () => Promise<number|null> = () => {
execCommand("stop");
return new Promise((accept, reject) => {
ServerProcess.on("exit", code => code === 0 ? accept(code) : reject(code));
setTimeout(() => accept(null), 1000);
})
}
// Return Session
const Seesion: BdsSession = {
id: crypto.randomUUID(),
startDate: StartDate,
seed: undefined,
addonManeger: {
installAddon: async function (packPath: string) {console.log(packPath); return;},
installAllAddons: async function (removeOldPacks: boolean) {console.log(removeOldPacks); return;}
},
creteBackup: (crontime: string|Date) => {
const cronJob = new node_cron.CronJob(crontime, async () => {
if (Platform === "bedrock") {
execCommand("save hold");
execCommand("save query");
}
await bdsBackup.CreateBackup(Platform);
if (Platform === "bedrock") execCommand("save resume");
});
ServerProcess.on("exit", () => cronJob.stop());
cronJob.start();
return;
},
on: onLog,
exit: onExit,
ports: () => ports,
getPlayer: () => playersConnections,
commands: {
execCommand: execCommand,
tpPlayer: tpPlayer,
stop: stopServer
}
};
if (Platform === "bedrock") {
Seesion.addonManeger = addon.bedrock.addonInstaller();
const bedrockConfig = await serverConfig.parseConfig(Platform);
Seesion.seed = bedrockConfig.nbt.parsed.value.RandomSeed.value.toString();
}
const logFile = path.resolve(process.env.LOG_PATH||path.resolve(ServerPath, "../log"), `${Platform}_${Seesion.id}.log`);
if(!(fs.existsSync(path.parse(logFile).dir))) fs.mkdirSync(path.parse(logFile).dir, {recursive: true});
const logStream = fs.createWriteStream(logFile, {flags: "w+"});
logStream.write(`[${StartDate.toISOString()}] Server started\n\n`);
onLog("all", data => logStream.write(data));
Sessions[Seesion.id] = Seesion;
ServerProcess.on("exit", () => {delete Sessions[Seesion.id];});
return Seesion;
}

177
src/serverConfig.ts Normal file
View File

@ -0,0 +1,177 @@
import crypto from "crypto";
import path from "path";
import os from "os";
import fs from "fs";
import * as prismarineNbt from "prismarine-nbt";
import properties_to_json from "properties-to-json";
import * as bdsType from "./globalType";
export type BdsConfigGet = {
world: string;
description: string;
gamemode: "survival"|"creative"|"adventure"|"spectator";
difficulty: "peaceful"|"easy"|"normal"|"hard";
players: number;
whitelist: true|false;
portv4: number;
portv6: number;
nbt?: {
parsed: prismarineNbt.NBT;
type: prismarineNbt.NBTFormat;
metadata: prismarineNbt.Metadata;
}|undefined;
}
export async function parseConfig(Platform: bdsType.Platform): Promise<BdsConfigGet> {
const serverPath = path.resolve(process.env.SERVER_PATH||path.join(os.homedir(), "bds_core/servers"), Platform);
if (Platform === "bedrock") {
const bedrockConfigPath = path.join(serverPath, "server.properties");
if (!(fs.existsSync(bedrockConfigPath))) throw new Error("Bedrock server config not found");
const bedrockConfig = properties_to_json(fs.readFileSync(bedrockConfigPath, "utf8"));
const bedrockConfigNbtPath = path.join(serverPath, "worlds", bedrockConfig["level-name"], "level.dat");
return {
world: bedrockConfig["level-name"],
description: bedrockConfig["server-name"],
difficulty: bedrockConfig["difficulty"],
gamemode: bedrockConfig["gamemode"],
players: parseInt(bedrockConfig["max-players"]),
whitelist: bedrockConfig["white-list"] === "true",
portv4: parseInt(bedrockConfig["server-port"]),
portv6: parseInt(bedrockConfig["server-portv6"]),
nbt: (fs.existsSync(bedrockConfigNbtPath)) ? await prismarineNbt.parse(fs.readFileSync(bedrockConfigNbtPath)) : undefined
};
}
throw new Error("Platform not supported");
}
export type BdsConfigSet = {
world: string;
description: string;
gamemode: "survival"|"creative"|"adventure"|"hardcore";
difficulty: "peaceful"|"easy"|"normal"|"hard";
seed?: string;
players?: number;
whitelist?: true|false;
require_login?: true|false;
cheats_command?: true|false;
portv4?: number;
portv6?: number;
}
export async function createConfig(Platform: bdsType.Platform, config: BdsConfigSet): Promise<void> {
const serverPath = path.resolve(process.env.SERVER_PATH||path.join(os.homedir(), "bds_core/servers"), Platform);
if (Platform === "bedrock") {
if (!(config.seed && typeof config.seed === "string")) config.seed = "";
if (!(config.players && typeof config.players === "number")) config.players = 20;
if (!(config.whitelist && typeof config.whitelist === "boolean")) config.whitelist = false;
if (!(config.require_login && typeof config.require_login === "boolean")) config.require_login = false;
if (!(config.cheats_command && typeof config.cheats_command === "boolean")) config.cheats_command = false;
if (!(config.portv4 && typeof config.portv4 === "number")) config.portv4 = 19132;
if (!(config.portv6 && typeof config.portv6 === "number")) config.portv6 = 19133;
const bedrockConfigArray = [
"view-distance=32",
"tick-distance=4",
"player-idle-timeout=0",
"max-threads=8",
"default-player-permission-level=member",
"texturepack-required=true",
"content-log-file-enabled=false",
"compression-threshold=1",
"server-authoritative-movement=server-auth",
"player-movement-score-threshold=20",
"player-movement-action-direction-threshold=0.85",
"player-movement-distance-threshold=0.3",
"player-movement-duration-threshold-in-ms=500",
"correct-player-movement=false",
"server-authoritative-block-breaking=false",
"force-gamemode=false",
];
bedrockConfigArray.push(`level-name=${config.world}`);
if (config.seed) bedrockConfigArray.push(`level-seed=${config.seed}`);
else bedrockConfigArray.push("level-seed=");
bedrockConfigArray.push(`server-name=${config.description}`);
bedrockConfigArray.push(`gamemode=${config.gamemode}`);
bedrockConfigArray.push(`difficulty=${config.difficulty}`);
bedrockConfigArray.push(`allow-cheats=${config.cheats_command}`);
bedrockConfigArray.push(`max-players=${config.players}`);
bedrockConfigArray.push(`online-mode=${config.require_login}`);
bedrockConfigArray.push(`allow-list=${config.whitelist}`);
bedrockConfigArray.push(`server-port=${config.portv4}`);
bedrockConfigArray.push(`server-portv6=${config.portv6}`);
const bedrockConfig = bedrockConfigArray.join("\n");
fs.writeFileSync(path.join(serverPath, "server.properties"), bedrockConfig);
return;
} else if (Platform === "java") {
if (!(config.seed && typeof config.seed === "string")) config.seed = "";
if (!(config.players && typeof config.players === "number")) config.players = 20;
if (!(config.whitelist && typeof config.whitelist === "boolean")) config.whitelist = false;
if (!(config.require_login && typeof config.require_login === "boolean")) config.require_login = false;
if (!(config.cheats_command && typeof config.cheats_command === "boolean")) config.cheats_command = false;
if (!(config.portv4 && typeof config.portv4 === "number")) config.portv4 = 25565;
if (!(config.portv6 && typeof config.portv6 === "number")) config.portv6 = 255656;
const javaConfigArray = [
"query.port=65551",
"enable-jmx-monitoring=false",
"enable-query=true",
"generator-settings=",
"generate-structures=true",
"network-compression-threshold=256",
"max-tick-time=60000",
"use-native-transport=true",
"enable-status=true",
"allow-flight=false",
"view-distance=32",
"max-build-height=256",
"server-ip=",
"sync-chunk-writes=true",
"prevent-proxy-connections=false",
"resource-pack=",
"entity-broadcast-range-percentage=100",
"player-idle-timeout=0",
"force-gamemode=false",
"rate-limit=0",
"broadcast-console-to-ops=true",
"spawn-npcs=true",
"spawn-animals=true",
"snooper-enabled=true",
"function-permission-level=2",
"text-filtering-config=",
"spawn-monsters=true",
"enforce-whitelist=false",
"resource-pack-sha1=",
"spawn-protection=16",
"max-world-size=29999984",
"require-resource-pack=true",
"resource-pack-prompt=",
"hide-online-players=false",
"simulation-distance=10",
"enable-rcon=false",
`rcon.password=${crypto.randomBytes(6).toString("hex")}`,
"rcon.port=25575",
"broadcast-rcon-to-ops=true"
];
javaConfigArray.push(`level-name=${config.world}`);
javaConfigArray.push(`motd=${config.description}`);
if (config.gamemode === "hardcore") {
javaConfigArray.push("gamemode=survival");
javaConfigArray.push("hardcore=true");
} else {
javaConfigArray.push(`gamemode=${config.gamemode}`);
javaConfigArray.push(`hardcore=false`);
}
javaConfigArray.push(`difficulty=${config.difficulty}`);
if (config.seed) javaConfigArray.push(`level-seed=${config.seed}`);
else javaConfigArray.push("level-seed=");
javaConfigArray.push(`enable-command-block=${config.cheats_command}`);
javaConfigArray.push(`max-players=${config.players}`);
javaConfigArray.push(`online-mode=${config.require_login}`);
javaConfigArray.push(`white-list=${config.whitelist}`);
javaConfigArray.push(`server-port=${config.portv4}`);
javaConfigArray.push("level-type=default");
javaConfigArray.push("op-permission-level=4");
javaConfigArray.push("pvp=true");
javaConfigArray.push("allow-nether=true");
await fs.promises.writeFile(path.join(serverPath, "server.properties"), javaConfigArray.join("\n"));
} else if (Platform === "pocketmine") {}
throw new Error("Platform not supported");
}

17
tsconfig.json Normal file
View File

@ -0,0 +1,17 @@
{
"include": ["src/"],
"exclude": ["node_modules/"],
"compilerOptions": {
"outDir": "./dist/cjs",
"declaration": true,
"strict": false,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"esModuleInterop": true,
"moduleResolution": "node",
"module": "commonjs",
"allowJs": true,
"target": "ES6"
}
}