Rewrite in typescrypt #327
13
.cjs2esm.js
13
.cjs2esm.js
@ -1,13 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
input: ["src"],
|
|
||||||
output: "esm",
|
|
||||||
forceDirectory: null,
|
|
||||||
modules: [],
|
|
||||||
extension: {
|
|
||||||
use: "js",
|
|
||||||
ignore: [],
|
|
||||||
},
|
|
||||||
addModuleEntry: false,
|
|
||||||
addPackageJson: false,
|
|
||||||
filesWithShebang: [],
|
|
||||||
};
|
|
@ -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
|
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"commonjs": true,
|
|
||||||
"es2021": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"bds_log_string": "writable",
|
|
||||||
"bds_server_string": "writable",
|
|
||||||
"external_ip": "writable"
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 12,
|
|
||||||
"sourceType": "module",
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"quotes": [
|
|
||||||
"error",
|
|
||||||
"double"
|
|
||||||
],
|
|
||||||
"eqeqeq": 0,
|
|
||||||
"no-async-promise-executor": "off"
|
|
||||||
}
|
|
||||||
}
|
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
|||||||
* text=lf eol=lf
|
|
||||||
*.sh text=lf eol=lf
|
|
17
.github/stale.yml
vendored
17
.github/stale.yml
vendored
@ -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
|
|
63
.github/workflows/PullRequest.yml
vendored
63
.github/workflows/PullRequest.yml
vendored
@ -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
43
.github/workflows/code_analyzer.yml
vendored
Normal 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
|
50
.github/workflows/publish_docker_main.yml
vendored
Normal file
50
.github/workflows/publish_docker_main.yml
vendored
Normal 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') }}
|
43
.github/workflows/publish_docker_release.yml
vendored
Normal file
43
.github/workflows/publish_docker_release.yml
vendored
Normal 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
73
.github/workflows/publish_npm_main.yml
vendored
Normal 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
|
85
.github/workflows/publish_npm_release.yml
vendored
Normal file
85
.github/workflows/publish_npm_release.yml
vendored
Normal 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
34
.github/workflows/pull_request.yml
vendored
Normal 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
|
214
.github/workflows/root.yml
vendored
214
.github/workflows/root.yml
vendored
@ -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
15
.gitignore
vendored
@ -1,14 +1,5 @@
|
|||||||
# Log
|
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
# Node
|
|
||||||
node_modules/
|
node_modules/
|
||||||
.dccache
|
dist/
|
||||||
docs/
|
src/**/*.d.ts
|
||||||
the-bds-maneger-core-*.tgz
|
src/**/*.d.js
|
||||||
|
|
||||||
# **
|
|
||||||
.husky
|
|
||||||
Servers
|
|
||||||
.Build/Releases.json
|
|
||||||
esm/
|
|
13
.gitpod.yml
13
.gitpod.yml
@ -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"
|
|
32
.npmignore
32
.npmignore
@ -1,31 +1 @@
|
|||||||
# Log
|
!dist/
|
||||||
*.log
|
|
||||||
|
|
||||||
# Develop files
|
|
||||||
.devcontainer/
|
|
||||||
.vscode/
|
|
||||||
.Build/
|
|
||||||
|
|
||||||
# Linters
|
|
||||||
.eslint*
|
|
||||||
|
|
||||||
# test files
|
|
||||||
*.test
|
|
||||||
*test*.*js
|
|
||||||
*Test*.*js
|
|
||||||
test/
|
|
||||||
Test/
|
|
||||||
|
|
||||||
# Git
|
|
||||||
git*
|
|
||||||
.git*
|
|
||||||
|
|
||||||
# Docker
|
|
||||||
.docker*
|
|
||||||
Docker*
|
|
||||||
|
|
||||||
# Npm
|
|
||||||
the-bds-maneger-core*.tgz
|
|
||||||
|
|
||||||
# External Packages
|
|
||||||
packages/**/*
|
|
@ -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);
|
|
||||||
})()
|
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"files.eol": "\n"
|
"files.eol": "\n",
|
||||||
|
"editor.tabSize": 2
|
||||||
}
|
}
|
153
Dockerfile
153
Dockerfile
@ -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
146
README.md
@ -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&utm_medium=referral&utm_content=The-Bds-Maneger/Bds-Maneger-Core&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!
|
|
||||||
|
@ -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();
|
|
@ -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");
|
|
@ -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
16137
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
70
package.json
70
package.json
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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;
|
|
@ -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
87
src/HttpRequests.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
type githubRelease = {
|
||||||
|
url: string;
|
||||||
|
assets_url: string;
|
||||||
|
upload_url: string;
|
||||||
|
html_url: string;
|
||||||
|
id: number;
|
||||||
|
tarball_url: string;
|
||||||
|
zipball_url: string;
|
||||||
|
body: string;
|
||||||
|
author: {
|
||||||
|
login: string;
|
||||||
|
id: number;
|
||||||
|
node_id: string;
|
||||||
|
avatar_url: string;
|
||||||
|
gravatar_id: string;
|
||||||
|
url: string;
|
||||||
|
html_url: string;
|
||||||
|
followers_url: string;
|
||||||
|
following_url: string;
|
||||||
|
gists_url: string;
|
||||||
|
starred_url: string;
|
||||||
|
subscriptions_url: string;
|
||||||
|
organizations_url: string;
|
||||||
|
repos_url: string;
|
||||||
|
events_url: string;
|
||||||
|
received_events_url: string;
|
||||||
|
type: string;
|
||||||
|
site_admin: boolean;
|
||||||
|
};
|
||||||
|
node_id: string;
|
||||||
|
tag_name: string;
|
||||||
|
target_commitish: string;
|
||||||
|
name: string;
|
||||||
|
draft: boolean;
|
||||||
|
prerelease: boolean;
|
||||||
|
created_at: string;
|
||||||
|
published_at: string;
|
||||||
|
assets: Array<{
|
||||||
|
url: string;
|
||||||
|
id: number;
|
||||||
|
node_id: string;
|
||||||
|
name: string;
|
||||||
|
label: string;
|
||||||
|
content_type: string;
|
||||||
|
state: string;
|
||||||
|
size: number;
|
||||||
|
download_count: number;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
browser_download_url: string;
|
||||||
|
uploader: {
|
||||||
|
login: string;
|
||||||
|
id: number;
|
||||||
|
node_id: string;
|
||||||
|
avatar_url: string;
|
||||||
|
gravatar_id: string;
|
||||||
|
url: string;
|
||||||
|
html_url: string;
|
||||||
|
followers_url: string;
|
||||||
|
following_url: string;
|
||||||
|
gists_url: string;
|
||||||
|
starred_url: string;
|
||||||
|
subscriptions_url: string;
|
||||||
|
organizations_url: string;
|
||||||
|
repos_url: string;
|
||||||
|
events_url: string;
|
||||||
|
received_events_url: string;
|
||||||
|
type: string;
|
||||||
|
site_admin: boolean;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getBuffer(url: string, headers: {[d: string]: any} = {}): Promise<Buffer> {
|
||||||
|
const dataReponse = await axios.get(url, {
|
||||||
|
headers: (headers||{}),
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
});
|
||||||
|
return Buffer.from(dataReponse.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getGithubRelease(Username: string, Repo: string): Promise<Array<githubRelease>> {
|
||||||
|
const data = await getBuffer(`https://api.github.com/repos/${Username}/${Repo}/releases`);
|
||||||
|
return JSON.parse(data.toString("utf8"));
|
||||||
|
}
|
@ -1,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;
|
|
@ -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`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -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
|
|
||||||
};
|
|
@ -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;
|
|
@ -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;
|
|
593
src/addons/bedrock/install.ts
Normal file
593
src/addons/bedrock/install.ts
Normal 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
4
src/addons/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import * as bedrock from "./bedrock/install";
|
||||||
|
|
||||||
|
export default {bedrock};
|
||||||
|
export {bedrock};
|
100
src/api.js
100
src/api.js
@ -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
77
src/api.ts
Normal 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"});
|
||||||
|
});
|
@ -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"
|
|
||||||
});
|
|
||||||
});
|
|
@ -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)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
@ -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
23
src/backup.ts
Normal 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
65
src/bin/docker.ts
Normal 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
51
src/bin/index.ts
Normal 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
66
src/download_server.ts
Normal 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
2
src/globalType.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export type Platform = "bedrock"|"java"|"pocketmine"|"spigot"|"dragonfly";
|
||||||
|
export const PlatformArray = ["bedrock", "java", "pocketmine", "spigot", "dragonfly"];
|
74
src/index.js
74
src/index.js
@ -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
8
src/index.ts
Normal 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};
|
@ -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
|
|
||||||
};
|
|
@ -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;
|
|
@ -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;
|
|
132
src/lib/Token.js
132
src/lib/Token.js
@ -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
|
|
||||||
};
|
|
@ -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
203
src/server.ts
Normal 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
177
src/serverConfig.ts
Normal 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
17
tsconfig.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user